Ptrace 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
data/module/Ptrace.c ADDED
@@ -0,0 +1,683 @@
1
+ /* Ptrace.c
2
+ * Copyright 2011 Thoughtgang <http://www.thoughtgang.org>
3
+ * Written by TG Community Developers <community@thoughtgang.org>
4
+ * Released under the GNU Public License, version 3.
5
+ * See http://www.gnu.org/licenses/gpl.txt for details.
6
+ */
7
+
8
+ #include <string.h>
9
+ #include <signal.h>
10
+ #include <errno.h>
11
+
12
+ #include <sys/types.h>
13
+ #include <sys/ptrace.h>
14
+ #include <sys/user.h>
15
+
16
+ // TODO: how to represent a 128-bit number in C and ruby
17
+ // gcc: unsigned __int128
18
+ // BigDecimal.new("0.0001")
19
+ // require 'bigdecimal'
20
+
21
+ #include <ruby.h>
22
+ #include "ruby_compat.h"
23
+
24
+ #include "Ptrace.h"
25
+
26
+ #define IVAR(attr) "@" attr
27
+
28
+ // TODO: decode user data structure ala sys/user.h
29
+
30
+ static VALUE modPtrace;
31
+ static VALUE clsDebug;
32
+ static VALUE clsError;
33
+
34
+
35
+ static VALUE str_to_sym( const char * str ) {
36
+ VALUE var = rb_str_new_cstr(str);
37
+ return rb_funcall(var, rb_intern("to_sym"), 0);
38
+ }
39
+
40
+ static VALUE pid_to_num( pid_t pid ) {
41
+ return (sizeof(pid_t) == sizeof(unsigned int)) ? UINT2NUM(pid)
42
+ : ULL2NUM(pid);
43
+ }
44
+
45
+ static pid_t num_to_pid( VALUE num ) {
46
+ if ( num == Qnil ) {
47
+ return 0;
48
+ }
49
+
50
+ return (sizeof(pid_t) == sizeof(unsigned int)) ? (pid_t) NUM2UINT(num)
51
+ : (pid_t) NUM2ULL(num);
52
+ }
53
+
54
+ /* return value for key or 0 */
55
+ static VALUE hash_get_int( VALUE h, VALUE key ) {
56
+
57
+ VALUE v = rb_hash_aref( h, key );
58
+ return (v == Qnil) ? UINT2NUM(0) : v;
59
+ }
60
+
61
+ #define CMD_HASH_ADD(h, str, val) \
62
+ rb_hash_aset(h, str_to_sym(str), UINT2NUM(val));
63
+
64
+ static VALUE build_cmd_hash( VALUE cls ) {
65
+ VALUE h = rb_hash_new();
66
+
67
+ CMD_HASH_ADD(h, SZ_PTRACE_TRACEME, PT_TRACE_ME)
68
+ CMD_HASH_ADD(h, SZ_PTRACE_PEEKTEXT, PT_READ_I)
69
+ CMD_HASH_ADD(h, SZ_PTRACE_PEEKDATA, PT_READ_D)
70
+ CMD_HASH_ADD(h, SZ_PTRACE_POKETEXT, PT_WRITE_I)
71
+ CMD_HASH_ADD(h, SZ_PTRACE_POKEDATA, PT_WRITE_D)
72
+ CMD_HASH_ADD(h, SZ_PTRACE_CONT, PT_CONTINUE)
73
+ CMD_HASH_ADD(h, SZ_PTRACE_SINGLESTEP, PT_STEP)
74
+ CMD_HASH_ADD(h, SZ_PTRACE_KILL, PT_KILL)
75
+ CMD_HASH_ADD(h, SZ_PTRACE_ATTACH, PT_ATTACH)
76
+ CMD_HASH_ADD(h, SZ_PTRACE_DETACH, PT_DETACH)
77
+
78
+ /* ====================================================== */
79
+ /* These may not be present in all ptrace implementations */
80
+ #ifdef PT_WRITE_U
81
+ CMD_HASH_ADD(h, SZ_PTRACE_POKEUSR, PT_WRITE_U)
82
+ #endif
83
+ #ifdef PT_READ_U
84
+ CMD_HASH_ADD(h, SZ_PTRACE_PEEKUSR, PT_READ_U)
85
+ #endif
86
+ #ifdef PT_SYSCALL
87
+ CMD_HASH_ADD(h, SZ_PTRACE_SYSCALL, PT_SYSCALL)
88
+ #endif
89
+ #ifdef PT_GETREGS
90
+ CMD_HASH_ADD(h, SZ_PTRACE_GETREGS, PT_GETREGS)
91
+ #endif
92
+ #ifdef PT_GETFPREGS
93
+ CMD_HASH_ADD(h, SZ_PTRACE_GETFPREGS, PT_GETFPREGS)
94
+ #endif
95
+ #ifdef PT_GETFPXREGS
96
+ CMD_HASH_ADD(h, SZ_PTRACE_GETFPXREGS, PT_GETFPXREGS)
97
+ #endif
98
+ #ifdef PT_SETREGS
99
+ CMD_HASH_ADD(h, SZ_PTRACE_SETREGS, PT_SETREGS)
100
+ #endif
101
+ #ifdef PT_SETFPREGS
102
+ CMD_HASH_ADD(h, SZ_PTRACE_SETFPREGS, PT_SETFPREGS)
103
+ #endif
104
+ #ifdef PT_SETFPXREGS
105
+ CMD_HASH_ADD(h, SZ_PTRACE_SETFPXREGS, PT_SETFPXREGS)
106
+ #endif
107
+ #ifdef PT_SETOPTIONS
108
+ CMD_HASH_ADD(h, SZ_PTRACE_SETOPTIONS, PT_SETOPTIONS)
109
+ #endif
110
+ #ifdef PT_GETSIGINFO
111
+ CMD_HASH_ADD(h, SZ_PTRACE_GETSIGINFO, PT_GETSIGINFO)
112
+ #endif
113
+ #ifdef PT_SETSIGINFO
114
+ CMD_HASH_ADD(h, SZ_PTRACE_SETSIGINFO, PT_SETSIGINFO)
115
+ #endif
116
+ #ifdef PT_GETEVENTMSG
117
+ CMD_HASH_ADD(h, SZ_PTRACE_GETEVENTMSG, PT_GETEVENTMSG)
118
+ #endif
119
+ #ifdef PT_SYSEMU
120
+ CMD_HASH_ADD(h, SZ_PTRACE_SYSEMU, PT_SYSEMU)
121
+ #endif
122
+ #ifdef PT_SYSEMU_SINGLESTEP
123
+ CMD_HASH_ADD(h, SZ_PTRACE_SYSEMU_SINGLESTEP, PT_SYSEMU_SINGLESTEP)
124
+ #endif
125
+ /* ====================================================== */
126
+
127
+ return h;
128
+ }
129
+
130
+ /* This is a hash of user structure members to offsets */
131
+ static VALUE build_user_hash( void ) {
132
+ VALUE h = rb_hash_new();
133
+ unsigned int offset;
134
+
135
+ //u_fp_valid
136
+ offset = sizeof(struct user_regs_struct);
137
+ //u_tsize =
138
+ offset += sizeof(int) + sizeof(struct user_fpregs_struct);
139
+ //u_dsize =
140
+ offset += sizeof(unsigned long int);
141
+ //u_ssize =
142
+ offset += sizeof(unsigned long int);
143
+ //start_code =
144
+ offset += sizeof(unsigned long int);
145
+ //start_stack =
146
+ offset += sizeof(unsigned long);
147
+ //signal =
148
+ offset += sizeof(unsigned long);
149
+ // magic
150
+ offset += sizeof(long int) + sizeof(void *) + sizeof(void *);
151
+ // comm
152
+ offset += sizeof(unsigned long int);
153
+ // debug_r0 - r7
154
+ offset += sizeof(char) * 32;
155
+ offset += sizeof(int);
156
+ //CMD_HASH_ADD(h, SZ_PTRACE_TRACEME, PT_TRACE_ME)
157
+
158
+ return h;
159
+ }
160
+
161
+ static VALUE build_option_hash( void ) {
162
+ VALUE h = rb_hash_new();
163
+
164
+ // TODO : Change this to if linux as these are not #defines!
165
+ #ifdef PTRACE_O_TRACESYSGOOD
166
+ CMD_HASH_ADD(h, SZ_PTRACE_O_TRACESYSGOOD, PTRACE_O_TRACESYSGOOD)
167
+ #endif
168
+ #ifdef PTRACE_O_TRACEFORK
169
+ CMD_HASH_ADD(h, SZ_PTRACE_O_TRACEFORK, PTRACE_O_TRACEFORK)
170
+ #endif
171
+ #ifdef PTRACE_O_TRACEVFORK
172
+ CMD_HASH_ADD(h, SZ_PTRACE_O_TRACEVFORK, PTRACE_O_TRACEVFORK)
173
+ #endif
174
+ #ifdef PTRACE_O_TRACEVFORKDONE
175
+ CMD_HASH_ADD(h, SZ_PTRACE_O_TRACEVFORKDONE, PTRACE_O_TRACEVFORKDONE)
176
+ #endif
177
+ #ifdef PTRACE_O_TRACECLONE
178
+ CMD_HASH_ADD(h, SZ_PTRACE_O_TRACECLONE, PTRACE_O_TRACECLONE)
179
+ #endif
180
+ #ifdef PTRACE_O_TRACEEXEC
181
+ CMD_HASH_ADD(h, SZ_PTRACE_O_TRACEEXEC, PTRACE_O_TRACEEXEC)
182
+ #endif
183
+ #ifdef PTRACE_O_TRACEEXIT
184
+ CMD_HASH_ADD(h, SZ_PTRACE_O_TRACEEXIT, PTRACE_O_TRACEEXIT)
185
+ #endif
186
+ return h;
187
+ }
188
+
189
+ /* ---------------------------------------------------------------------- */
190
+
191
+ static long int_ptrace_raw( enum __ptrace_request req, VALUE pid, void * addr,
192
+ void * data ) {
193
+ pid_t tgt;
194
+ long rv;
195
+
196
+ tgt = num_to_pid(pid);
197
+ rv = ptrace(req, tgt, addr, data);
198
+ if ( rv == -1l ) {
199
+ rb_raise(rb_eRuntimeError, "PTRACE: %s", strerror(errno));
200
+ }
201
+
202
+ return rv;
203
+ }
204
+
205
+ /* internal wrapper for ptrace that converts PID to a pid_t, and converts
206
+ * return value to a Fixnum */
207
+ static VALUE int_ptrace( enum __ptrace_request req, VALUE pid, void * addr,
208
+ void * data ) {
209
+ long rv = int_ptrace_raw(req, pid, addr, data);
210
+ return LONG2NUM(rv);
211
+ }
212
+
213
+ static VALUE int_ptrace_data( VALUE req, VALUE pid, VALUE addr, void * data ) {
214
+ enum __ptrace_request cmd = (req == Qnil) ? 0 :
215
+ (enum __ptrace_request) NUM2UINT(req);
216
+ void * tgt_addr = (addr == Qnil) ? NULL : (void *) NUM2OFFT(addr);
217
+
218
+ return int_ptrace(cmd, pid, tgt_addr, data);
219
+ }
220
+
221
+
222
+ /* ---------------------------------------------------------------------- */
223
+ /* PTRACE API */
224
+
225
+ static VALUE ptrace_send( VALUE cls, VALUE req, VALUE pid, VALUE addr) {
226
+ return int_ptrace_data( req, pid, addr, NULL );
227
+ }
228
+
229
+ /* NOTE only use this for data that is NOT a memory address (pointer)! */
230
+ static VALUE ptrace_send_data( VALUE cls, VALUE req, VALUE pid, VALUE addr,
231
+ VALUE data ) {
232
+ void * the_data = (data == Qnil) ? NULL : (void *) NUM2ULONG(data);
233
+
234
+ return int_ptrace_data(req, pid, addr, the_data);
235
+ }
236
+
237
+ /* peek_text, peek_data, peek_user */
238
+ static VALUE ptrace_peek( VALUE cls, VALUE req, VALUE pid, VALUE addr ) {
239
+ return int_ptrace_data(req, pid, addr, NULL);
240
+ }
241
+
242
+ /* poke_text, poke_data, poke_user */
243
+ static VALUE ptrace_poke( VALUE cls, VALUE req, VALUE pid, VALUE addr,
244
+ VALUE data ) {
245
+ void * the_data = (void *) NUM2ULONG(data);
246
+
247
+ return int_ptrace_data(req, pid, addr, the_data);
248
+ }
249
+
250
+ static VALUE ptrace_get_regs( VALUE cls, VALUE pid ) {
251
+ VALUE h = rb_hash_new();
252
+
253
+ #ifdef __linux
254
+ long rv = 0;
255
+ struct user_regs_struct regs = {0};
256
+
257
+ rv = int_ptrace_raw( PT_GETREGS, pid, NULL, &regs);
258
+
259
+ # ifdef __x86_64__
260
+ rb_hash_aset( h, rb_str_new_cstr("r15"), ULONG2NUM(regs.r15) );
261
+ rb_hash_aset( h, rb_str_new_cstr("r14"), ULONG2NUM(regs.r14) );
262
+ rb_hash_aset( h, rb_str_new_cstr("r13"), ULONG2NUM(regs.r13) );
263
+ rb_hash_aset( h, rb_str_new_cstr("r12"), ULONG2NUM(regs.r12) );
264
+ rb_hash_aset( h, rb_str_new_cstr("rbp"), ULONG2NUM(regs.rbp) );
265
+ rb_hash_aset( h, rb_str_new_cstr("rbx"), ULONG2NUM(regs.rbx) );
266
+ rb_hash_aset( h, rb_str_new_cstr("r11"), ULONG2NUM(regs.r11) );
267
+ rb_hash_aset( h, rb_str_new_cstr("r10"), ULONG2NUM(regs.r10) );
268
+ rb_hash_aset( h, rb_str_new_cstr("r9"), ULONG2NUM(regs.r9) );
269
+ rb_hash_aset( h, rb_str_new_cstr("r8"), ULONG2NUM(regs.r8) );
270
+ rb_hash_aset( h, rb_str_new_cstr("rax"), ULONG2NUM(regs.rax) );
271
+ rb_hash_aset( h, rb_str_new_cstr("rcx"), ULONG2NUM(regs.rcx) );
272
+ rb_hash_aset( h, rb_str_new_cstr("rdx"), ULONG2NUM(regs.rdx) );
273
+ rb_hash_aset( h, rb_str_new_cstr("rsi"), ULONG2NUM(regs.rsi) );
274
+ rb_hash_aset( h, rb_str_new_cstr("rdi"), ULONG2NUM(regs.rdi) );
275
+ rb_hash_aset( h, rb_str_new_cstr("orig_rax"), ULONG2NUM(regs.orig_rax));
276
+ rb_hash_aset( h, rb_str_new_cstr("rip"), ULONG2NUM(regs.rip) );
277
+ rb_hash_aset( h, rb_str_new_cstr("cs"), ULONG2NUM(regs.cs) );
278
+ rb_hash_aset( h, rb_str_new_cstr("eflags"), ULONG2NUM(regs.eflags) );
279
+ rb_hash_aset( h, rb_str_new_cstr("rsp"), ULONG2NUM(regs.rsp) );
280
+ rb_hash_aset( h, rb_str_new_cstr("ss"), ULONG2NUM(regs.ss) );
281
+ rb_hash_aset( h, rb_str_new_cstr("fs_base"), ULONG2NUM(regs.fs_base) );
282
+ rb_hash_aset( h, rb_str_new_cstr("gs_base"), ULONG2NUM(regs.gs_base) );
283
+ rb_hash_aset( h, rb_str_new_cstr("ds"), ULONG2NUM(regs.ds) );
284
+ rb_hash_aset( h, rb_str_new_cstr("es"), ULONG2NUM(regs.es) );
285
+ rb_hash_aset( h, rb_str_new_cstr("fs"), ULONG2NUM(regs.fs) );
286
+ rb_hash_aset( h, rb_str_new_cstr("gs"), ULONG2NUM(regs.gs) );
287
+ # else
288
+ rb_hash_aset( h, rb_str_new_cstr("ebx"), ULONG2NUM(regs.ebx) );
289
+ rb_hash_aset( h, rb_str_new_cstr("ecx"), ULONG2NUM(regs.ecx) );
290
+ rb_hash_aset( h, rb_str_new_cstr("edx"), ULONG2NUM(regs.edx) );
291
+ rb_hash_aset( h, rb_str_new_cstr("esi"), ULONG2NUM(regs.esi) );
292
+ rb_hash_aset( h, rb_str_new_cstr("edi"), ULONG2NUM(regs.edi) );
293
+ rb_hash_aset( h, rb_str_new_cstr("ebp"), ULONG2NUM(regs.ebp) );
294
+ rb_hash_aset( h, rb_str_new_cstr("eax"), ULONG2NUM(regs.eax) );
295
+ rb_hash_aset( h, rb_str_new_cstr("ds"), ULONG2NUM(regs.xds) );
296
+ rb_hash_aset( h, rb_str_new_cstr("es"), ULONG2NUM(regs.xes) );
297
+ rb_hash_aset( h, rb_str_new_cstr("fs"), ULONG2NUM(regs.xfs) );
298
+ rb_hash_aset( h, rb_str_new_cstr("gs"), ULONG2NUM(regs.xgs) );
299
+ rb_hash_aset( h, rb_str_new_cstr("orig_eax"), ULONG2NUM(regs.orig_eax));
300
+ rb_hash_aset( h, rb_str_new_cstr("eip"), ULONG2NUM(regs.eip) );
301
+ rb_hash_aset( h, rb_str_new_cstr("cs"), ULONG2NUM(regs.xcs) );
302
+ rb_hash_aset( h, rb_str_new_cstr("eflags"), ULONG2NUM(regs.eflags) );
303
+ rb_hash_aset( h, rb_str_new_cstr("esp"), ULONG2NUM(regs.esp) );
304
+ rb_hash_aset( h, rb_str_new_cstr("ss"), ULONG2NUM(regs.xss) );
305
+ # endif
306
+ #endif
307
+ return h;
308
+ }
309
+
310
+ static VALUE ptrace_set_regs( VALUE cls, VALUE pid, VALUE h ) {
311
+
312
+ #ifdef __linux
313
+ long rv = 0;
314
+ struct user_regs_struct regs = {0};
315
+ int_ptrace_raw( PT_GETREGS, pid, NULL, &regs);
316
+
317
+ # ifdef __x86_64__
318
+ regs.r15 = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("r15") ));
319
+ regs.r14 = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("r14") ));
320
+ regs.r13 = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("r13") ));
321
+ regs.r12 = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("r12") ));
322
+ regs.rbp = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("rbp") ));
323
+ regs.rbx = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("rbx") ));
324
+ regs.r11 = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("r11") ));
325
+ regs.r10 = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("r10") ));
326
+ regs.r9 = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("r9") ));
327
+ regs.r8 = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("r8") ));
328
+ regs.rax = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("rax") ));
329
+ regs.rcx = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("rcx") ));
330
+ regs.rdx = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("rdx") ));
331
+ regs.rsi = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("rsi") ));
332
+ regs.rdi = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("rdi") ));
333
+ /* Ptrace does not allow modification of these registers:
334
+ regs.orig_rax = NUM2ULONG(hash_get_int(h, rb_str_new_cstr("orig_rax")));
335
+ regs.cs = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("cs") ));
336
+ regs.ss = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("ss") ));
337
+ regs.fs_base = NUM2ULONG(hash_get_int(h, rb_str_new_cstr("fs_base") ));
338
+ regs.gs_base = NUM2ULONG(hash_get_int(h, rb_str_new_cstr("gs_base") ));
339
+ */
340
+ regs.rip = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("rip") ));
341
+ regs.eflags = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("eflags") ));
342
+ regs.rsp = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("rsp") ));
343
+ regs.ds = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("ds") ));
344
+ regs.es = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("es") ));
345
+ regs.fs = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("fs") ));
346
+ regs.gs = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("gs") ));
347
+ # else
348
+ regs.ebx = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("ebx") ));
349
+ regs.ecx = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("ecx") ));
350
+ regs.edx = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("edx") ));
351
+ regs.esi = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("esi") ));
352
+ regs.edi = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("edi") ));
353
+ regs.ebp = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("ebp") ));
354
+ regs.eax = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("eax") ));
355
+ regs.xds = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("ds") ));
356
+ regs.xes = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("es") ));
357
+ regs.xfs = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("fs") ));
358
+ regs.xgs = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("gs") ));
359
+ /* Ptrace does not allow modification of these registers:
360
+ regs.orig_rax = NUM2ULONG(hash_get_int(h, rb_str_new_cstr("orig_rax")));
361
+ regs.xcs = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("cs") ));
362
+ regs.xss = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("ss") ));
363
+ */
364
+ regs.eip = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("eip") ));
365
+ regs.eflags = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("eflags") ));
366
+ regs.esp = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("esp") ));
367
+ # endif
368
+ rv = int_ptrace_raw( PT_SETREGS, pid, NULL, &regs);
369
+ #endif
370
+ return Qnil;
371
+ }
372
+
373
+ static VALUE ptrace_get_fpregs( VALUE cls, VALUE pid ) {
374
+ VALUE h = rb_hash_new();
375
+ #ifdef __linux
376
+ long rv = 0;
377
+ int i;
378
+ struct user_fpregs_struct regs = {0};
379
+
380
+ rv = int_ptrace_raw( PT_GETFPREGS, pid, NULL, &regs);
381
+
382
+ # ifdef __x86_64__
383
+ rb_hash_aset( h, rb_str_new_cstr("cwd"), UINT2NUM(regs.cwd) );
384
+ rb_hash_aset( h, rb_str_new_cstr("swd"), UINT2NUM(regs.swd) );
385
+ rb_hash_aset( h, rb_str_new_cstr("ftw"), UINT2NUM(regs.ftw) );
386
+ rb_hash_aset( h, rb_str_new_cstr("fop"), UINT2NUM(regs.fop) );
387
+ rb_hash_aset( h, rb_str_new_cstr("rip"), ULONG2NUM(regs.rip) );
388
+ rb_hash_aset( h, rb_str_new_cstr("rdp"), ULONG2NUM(regs.rdp) );
389
+ rb_hash_aset( h, rb_str_new_cstr("mxcsr"), UINT2NUM(regs.mxcsr) );
390
+ rb_hash_aset( h, rb_str_new_cstr("mxcr_mask"),
391
+ UINT2NUM(regs.mxcr_mask) );
392
+ for ( i = 0; i < 32; i++ ) {
393
+ char buf[8];
394
+ sprintf(buf, "ST(%d)", i);
395
+ // TODO: 8 x 16-byte regs
396
+ //rb_hash_aset( h, rb_str_new_cstr(buf),
397
+ // UINT2NUM(regs.st_space[i]) );
398
+ }
399
+ for ( i = 0; i < 64; i++ ) {
400
+ char buf[8];
401
+ sprintf(buf, "xmm%d", i);
402
+ // TODO: 16 x 16-byte regs
403
+ //rb_hash_aset( h, rb_str_new_cstr(buf),
404
+ // UINT2NUM(regs.xmm_space[i]) );
405
+ }
406
+ # else
407
+ rb_hash_aset( h, rb_str_new_cstr("cwd"), UINT2NUM(regs.cwd) );
408
+ rb_hash_aset( h, rb_str_new_cstr("swd"), UINT2NUM(regs.swd) );
409
+ rb_hash_aset( h, rb_str_new_cstr("twd"), UINT2NUM(regs.twd) );
410
+ rb_hash_aset( h, rb_str_new_cstr("fip"), UINT2NUM(regs.fip) );
411
+ rb_hash_aset( h, rb_str_new_cstr("fcs"), UINT2NUM(regs.fcs) );
412
+ rb_hash_aset( h, rb_str_new_cstr("foo"), UINT2NUM(regs.foo) );
413
+ rb_hash_aset( h, rb_str_new_cstr("fos"), UINT2NUM(regs.fos) );
414
+ for ( i = 0; i < 20; i++ ) {
415
+ // 20x long int st_space
416
+ char buf[8];
417
+ sprintf(buf, "ST(%d)", i);
418
+ // TODO: 8 x 16-byte regs
419
+ //rb_hash_aset( h, rb_str_new_cstr(buf),
420
+ // UINT2NUM(regs.st_space[i]) );
421
+ }
422
+ # endif
423
+ #elif defined(__APPLE__)
424
+ # ifdef __x86_64__
425
+ # else
426
+ # endif
427
+ #endif
428
+ return h;
429
+ }
430
+
431
+ static VALUE ptrace_set_fpregs( VALUE cls, VALUE pid, VALUE h ) {
432
+
433
+ #ifdef __linux
434
+ long rv = 0;
435
+ int i;
436
+ struct user_fpregs_struct regs = {0};
437
+ # ifdef __x86_64__
438
+ regs.cwd = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("cwd") ));
439
+ regs.swd = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("swd") ));
440
+ regs.ftw = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("ftw") ));
441
+ regs.fop = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("fop") ));
442
+ regs.rip = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("rip") ));
443
+ regs.rdp = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("rdp") ));
444
+ regs.mxcsr = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("mxcsr") ));
445
+ regs.mxcr_mask = NUM2ULONG(hash_get_int( h,
446
+ rb_str_new_cstr("mxcr_mask") ));
447
+ for ( i = 0; i < 32; i++ ) {
448
+ char buf[8];
449
+ sprintf(buf, "ST(%d)", i);
450
+ // TODO: 8 * 16-byte regs
451
+ //regs.st_space[i] = NUM2UINT(hash_get_int( h,
452
+ // rb_str_new_cstr(buf) ));
453
+ }
454
+ for ( i = 0; i < 64; i++ ) {
455
+ char buf[8];
456
+ sprintf(buf, "xmm%d", i);
457
+ // TODO : 16 x 16-byte regs
458
+ //regs.xmm_space[i] = NUM2UINT(hash_get_int( h,
459
+ // rb_str_new_cstr(buf) ));
460
+ }
461
+ # else
462
+ regs.cwd = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("cwd") ));
463
+ regs.swd = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("swd") ));
464
+ regs.twd = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("twd") ));
465
+ regs.fip = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("fip") ));
466
+ regs.fcs = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("fcs") ));
467
+ regs.foo = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("foo") ));
468
+ regs.fos = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("fos") ));
469
+ for ( i = 0; i < 20; i++ ) {
470
+ char buf[8];
471
+ sprintf(buf, "ST(%d)", i);
472
+ // TODO: 8 * 16-byte regs
473
+ //regs.st_space[i] = NUM2UINT(hash_get_int( h,
474
+ // rb_str_new_cstr(buf) ));
475
+ }
476
+ # endif
477
+ rv = int_ptrace_raw( PT_SETFPREGS, pid, NULL, &regs);
478
+ #elif defined(__APPLE__)
479
+ # ifdef __x86_64__
480
+ # else
481
+ # endif
482
+ #endif
483
+ return Qnil;
484
+ }
485
+
486
+ static VALUE ptrace_get_fpxregs( VALUE cls, VALUE pid ) {
487
+ VALUE h = rb_hash_new();
488
+ #ifdef __linux
489
+ long rv = 0;
490
+ int i;
491
+
492
+ # ifdef __x86_64__
493
+ // Nothing to do: x86-64 has no fpxregs structure
494
+ # else
495
+ struct user_fpxregs_struct regs = {0};
496
+
497
+ rv = int_ptrace_raw( PT_GETFPREGS, pid, NULL, &regs);
498
+
499
+ rb_hash_aset( h, rb_str_new_cstr("cwd"), UINT2NUM(regs.cwd) );
500
+ rb_hash_aset( h, rb_str_new_cstr("swd"), UINT2NUM(regs.swd) );
501
+ rb_hash_aset( h, rb_str_new_cstr("twd"), UINT2NUM(regs.twd) );
502
+ rb_hash_aset( h, rb_str_new_cstr("fop"), UINT2NUM(regs.fop) );
503
+ rb_hash_aset( h, rb_str_new_cstr("fip"), ULONG2NUM(regs.fip) );
504
+ rb_hash_aset( h, rb_str_new_cstr("fcs"), UINT2NUM(regs.fcs) );
505
+ rb_hash_aset( h, rb_str_new_cstr("foo"), UINT2NUM(regs.foo) );
506
+ rb_hash_aset( h, rb_str_new_cstr("fos"), UINT2NUM(regs.fos) );
507
+ rb_hash_aset( h, rb_str_new_cstr("mxcsr"), UINT2NUM(regs.mxcsr) );
508
+ for ( i = 0; i < 32; i++ ) {
509
+ char buf[8];
510
+ sprintf(buf, "ST(%d)", i);
511
+ // TODO: 8 x 16-byte regs
512
+ //rb_hash_aset( h, rb_str_new_cstr(buf),
513
+ // UINT2NUM(regs.st_space[i]) );
514
+ }
515
+ for ( i = 0; i < 32; i++ ) {
516
+ char buf[8];
517
+ sprintf(buf, "xmm%d", i);
518
+ // TODO: 16 x 16-byte regs
519
+ //rb_hash_aset( h, rb_str_new_cstr(buf),
520
+ // UINT2NUM(regs.xmm_space[i]) );
521
+ }
522
+ # endif
523
+ #elif defined(__APPLE__)
524
+ # ifdef __x86_64__
525
+ # else
526
+ # endif
527
+ #endif
528
+ return h;
529
+ }
530
+
531
+ static VALUE ptrace_set_fpxregs( VALUE cls, VALUE pid, VALUE h ) {
532
+
533
+ #ifdef __linux
534
+ long rv = 0;
535
+ int i;
536
+ # ifdef __x86_64__
537
+ // Nothing to do: x86-64 has no fpxregs structure
538
+ # else
539
+ struct user_fpxregs_struct regs = {0};
540
+
541
+ regs.cwd = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("cwd") ));
542
+ regs.swd = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("swd") ));
543
+ regs.twd = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("twd") ));
544
+ regs.fop = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("fop") ));
545
+ regs.fip = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("fip") ));
546
+ regs.fcs = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("fcs") ));
547
+ regs.foo = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("foo") ));
548
+ regs.fos = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("fos") ));
549
+ regs.mxcsr = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("mxcsr") ));
550
+ for ( i = 0; i < 32; i++ ) {
551
+ char buf[8];
552
+ sprintf(buf, "ST(%d)", i);
553
+ // TODO: 8 * 16-byte regs
554
+ //regs.st_space[i] = NUM2UINT(hash_get_int( h,
555
+ // rb_str_new_cstr(buf) ));
556
+ }
557
+ for ( i = 0; i < 32; i++ ) {
558
+ char buf[8];
559
+ sprintf(buf, "xmm%d", i);
560
+ // TODO : 16 x 16-byte regs
561
+ //regs.xmm_space[i] = NUM2UINT(hash_get_int( h,
562
+ // rb_str_new_cstr(buf) ));
563
+ }
564
+ rv = int_ptrace_raw( PT_SETFPXREGS, pid, NULL, &regs);
565
+ # endif
566
+ #elif defined(__APPLE__)
567
+ # ifdef __x86_64__
568
+ # else
569
+ # endif
570
+ #endif
571
+ return Qnil;
572
+ }
573
+
574
+ static VALUE ptrace_get_siginfo( VALUE cls, VALUE pid ) {
575
+ VALUE h = rb_hash_new();
576
+ #ifdef PT_GETSIGINFO
577
+ # ifdef __linux
578
+ siginfo_t sig = {0};
579
+
580
+ int rv = int_ptrace_raw( PT_GETSIGINFO, pid, NULL, &sig);
581
+
582
+ rb_hash_aset( h, rb_str_new_cstr("signo"), UINT2NUM(sig.si_signo) );
583
+ rb_hash_aset( h, rb_str_new_cstr("errno"), UINT2NUM(sig.si_errno) );
584
+ rb_hash_aset( h, rb_str_new_cstr("code"), UINT2NUM(sig.si_code) );
585
+ //rb_hash_aset( h, rb_str_new_cstr("trapno"), UINT2NUM(sig.si_trapno) );
586
+ rb_hash_aset( h, rb_str_new_cstr("pid"), pid_to_num(sig.si_pid) );
587
+ rb_hash_aset( h, rb_str_new_cstr("uid"), UIDTNUM(sig.si_uid) );
588
+ rb_hash_aset( h, rb_str_new_cstr("status"), UINT2NUM(sig.si_status) );
589
+ rb_hash_aset( h, rb_str_new_cstr("utime"), UINT2NUM(sig.si_utime) );
590
+ rb_hash_aset( h, rb_str_new_cstr("stime"), UINT2NUM(sig.si_stime) );
591
+ //rb_hash_aset( h, rb_str_new_cstr("value"), UINT2NUM(sig.si_value) );
592
+ rb_hash_aset( h, rb_str_new_cstr("int"), UINT2NUM(sig.si_int) );
593
+ //rb_hash_aset( h, rb_str_new_cstr("ptr"), ULONG2NUM(sig.si_ptr) );
594
+ rb_hash_aset( h, rb_str_new_cstr("overrun"), UINT2NUM(sig.si_overrun) );
595
+ rb_hash_aset( h, rb_str_new_cstr("timerid"), UINT2NUM(sig.si_timerid) );
596
+ //rb_hash_aset( h, rb_str_new_cstr("addr"), ULONG2NUM(sig.si_addr) );
597
+ rb_hash_aset( h, rb_str_new_cstr("band"), UINT2NUM(sig.si_band) );
598
+ rb_hash_aset( h, rb_str_new_cstr("fd"), UINT2NUM(sig.si_fd) );
599
+ # elif defined(__APPLE__)
600
+ # endif
601
+ #endif
602
+ return h;
603
+ }
604
+ static VALUE ptrace_set_siginfo( VALUE cls, VALUE pid, VALUE hash ) {
605
+ VALUE rv = Qnil;
606
+ #ifdef PT_SET_SIGINFO
607
+ # ifdef __linux
608
+ siginfo_t sig = {0};
609
+
610
+ sig.si_signo = NUM2UINT(hash_get_int( h, rb_str_new_cstr("signo") ));
611
+ sig.si_errno = NUM2UINT(hash_get_int( h, rb_str_new_cstr("errno") ));
612
+ sig.si_code = NUM2UINT(hash_get_int( h, rb_str_new_cstr("code") ));
613
+ sig.si_trapno = NUM2UINT(hash_get_int( h, rb_str_new_cstr("trapno") ));
614
+ sig.si_pid = num_to_pid(hash_get_int( h, rb_str_new_cstr("pid") ));
615
+ sig.si_uid = NUM2UIDT(hash_get_int( h, rb_str_new_cstr("uid") ));
616
+ sig.si_status = NUM2UINT(hash_get_int( h, rb_str_new_cstr("status") ));
617
+ sig.si_utime = NUM2UINT(hash_get_int( h, rb_str_new_cstr("utime") ));
618
+ sig.si_stime = NUM2UINT(hash_get_int( h, rb_str_new_cstr("stime") ));
619
+ sig.si_value = NUM2UINT(hash_get_int( h, rb_str_new_cstr("value") ));
620
+ sig.si_int = NUM2UINT(hash_get_int( h, rb_str_new_cstr("int") ));
621
+ sig.si_ptr = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("ptr") ));
622
+ sig.si_overrun = NUM2UINT(hash_get_int(h, rb_str_new_cstr("overrun")));
623
+ sig.si_timerid = NUM2UINT(hash_get_int(h, rb_str_new_cstr("timerid")));
624
+ sig.si_addr = NUM2ULONG(hash_get_int( h, rb_str_new_cstr("addr") ));
625
+ sig.si_band = NUM2UINT(hash_get_int( h, rb_str_new_cstr("band") ));
626
+ sig.si_fd = NUM2UINT(hash_get_int( h, rb_str_new_cstr("fd") ));
627
+
628
+ int_ptrace_raw( PT_SETSIGINFO, pid, NULL, &sig);
629
+ # elif defined(__APPLE__)
630
+ # endif
631
+ #endif
632
+ return rv;
633
+ }
634
+
635
+ static VALUE ptrace_eventmsg( VALUE cls, VALUE pid ) {
636
+ VALUE rv = Qnil;
637
+ #ifdef PT_GETEVENTMSG
638
+ unsigned long long msg;
639
+
640
+ int_ptrace_raw( PT_GETEVENTMSG, pid, NULL, &msg);
641
+ rv = ULL2NUM(msg);
642
+ #endif
643
+ return rv;
644
+ }
645
+
646
+ /* ---------------------------------------------------------------------- */
647
+ /* Debugger Class */
648
+
649
+ static void init_debugger_class( VALUE modPtrace ) {
650
+ clsDebug = rb_define_class_under(modPtrace, DEBUGGER_CLASS_NAME,
651
+ rb_cObject);
652
+
653
+ rb_define_singleton_method(clsDebug, "commands", build_cmd_hash, 0);
654
+
655
+ rb_define_singleton_method(clsDebug, "send_cmd", ptrace_send, 3);
656
+ rb_define_singleton_method(clsDebug, "send_data", ptrace_send_data, 4);
657
+ rb_define_singleton_method(clsDebug, "peek", ptrace_peek, 3);
658
+ rb_define_singleton_method(clsDebug, "poke", ptrace_poke, 4);
659
+ rb_define_singleton_method(clsDebug, "regs", ptrace_get_regs, 1);
660
+ rb_define_singleton_method(clsDebug, "regs=", ptrace_set_regs, 2);
661
+ rb_define_singleton_method(clsDebug, "fpregs", ptrace_get_fpregs, 1);
662
+ rb_define_singleton_method(clsDebug, "fpregs=", ptrace_set_fpregs, 2);
663
+ rb_define_singleton_method(clsDebug, "fpxregs", ptrace_get_fpxregs, 1);
664
+ rb_define_singleton_method(clsDebug, "fpxregs=", ptrace_set_fpxregs, 2);
665
+ rb_define_singleton_method(clsDebug, "signal", ptrace_get_siginfo, 1);
666
+ rb_define_singleton_method(clsDebug, "signal=", ptrace_set_siginfo, 2);
667
+ rb_define_singleton_method(clsDebug, "event_msg", ptrace_eventmsg, 1);
668
+ }
669
+
670
+ /* ---------------------------------------------------------------------- */
671
+ /* USER */
672
+
673
+ /* ---------------------------------------------------------------------- */
674
+ /* Ptrace Module */
675
+
676
+ void Init_Ptrace_ext() {
677
+ modPtrace = rb_define_module(PTRACE_MODULE_NAME);
678
+ clsError = rb_define_class_under(rb_eRuntimeError,
679
+ PTRACE_ERROR_CLASS_NAME,
680
+ rb_cObject);
681
+
682
+ init_debugger_class(modPtrace);
683
+ }