Ptrace 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }