ragweed 0.2.0-java

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.
Files changed (54) hide show
  1. data/History.txt +32 -0
  2. data/README.rdoc +60 -0
  3. data/README.txt +9 -0
  4. data/Rakefile +86 -0
  5. data/VERSION +1 -0
  6. data/examples/hittracertux.rb +45 -0
  7. data/examples/hittracerx.rb +63 -0
  8. data/examples/hook_notepad.rb +9 -0
  9. data/examples/snicker.rb +183 -0
  10. data/examples/tux-example.rb +24 -0
  11. data/lib/ragweed/arena.rb +55 -0
  12. data/lib/ragweed/blocks.rb +128 -0
  13. data/lib/ragweed/debugger32.rb +400 -0
  14. data/lib/ragweed/debuggerosx.rb +456 -0
  15. data/lib/ragweed/debuggertux.rb +502 -0
  16. data/lib/ragweed/detour.rb +223 -0
  17. data/lib/ragweed/ptr.rb +48 -0
  18. data/lib/ragweed/rasm/bblock.rb +73 -0
  19. data/lib/ragweed/rasm/isa.rb +1115 -0
  20. data/lib/ragweed/rasm.rb +59 -0
  21. data/lib/ragweed/sbuf.rb +197 -0
  22. data/lib/ragweed/trampoline.rb +103 -0
  23. data/lib/ragweed/utils.rb +182 -0
  24. data/lib/ragweed/wrap32/debugging.rb +401 -0
  25. data/lib/ragweed/wrap32/device.rb +49 -0
  26. data/lib/ragweed/wrap32/event.rb +50 -0
  27. data/lib/ragweed/wrap32/hooks.rb +39 -0
  28. data/lib/ragweed/wrap32/overlapped.rb +46 -0
  29. data/lib/ragweed/wrap32/process.rb +613 -0
  30. data/lib/ragweed/wrap32/process_token.rb +75 -0
  31. data/lib/ragweed/wrap32/thread_context.rb +142 -0
  32. data/lib/ragweed/wrap32/winx.rb +16 -0
  33. data/lib/ragweed/wrap32/wrap32.rb +583 -0
  34. data/lib/ragweed/wrap32.rb +59 -0
  35. data/lib/ragweed/wraposx/constants.rb +114 -0
  36. data/lib/ragweed/wraposx/kernelerrorx.rb +147 -0
  37. data/lib/ragweed/wraposx/region_info.rb +275 -0
  38. data/lib/ragweed/wraposx/structs.rb +102 -0
  39. data/lib/ragweed/wraposx/thread_context.rb +902 -0
  40. data/lib/ragweed/wraposx/thread_info.rb +160 -0
  41. data/lib/ragweed/wraposx/thread_info.rb.old +121 -0
  42. data/lib/ragweed/wraposx/wraposx.rb +356 -0
  43. data/lib/ragweed/wraposx.rb +60 -0
  44. data/lib/ragweed/wraptux/constants.rb +101 -0
  45. data/lib/ragweed/wraptux/process.rb +35 -0
  46. data/lib/ragweed/wraptux/threads.rb +7 -0
  47. data/lib/ragweed/wraptux/wraptux.rb +72 -0
  48. data/lib/ragweed/wraptux.rb +57 -0
  49. data/lib/ragweed.rb +112 -0
  50. data/ragweed.gemspec +102 -0
  51. data/spec/ragweed_spec.rb +7 -0
  52. data/spec/spec_helper.rb +16 -0
  53. data/test/test_ragweed.rb +0 -0
  54. metadata +121 -0
@@ -0,0 +1,902 @@
1
+ # 127 ((x == x86_THREAD_STATE32) || \
2
+ # 128 (x == x86_FLOAT_STATE32) || \
3
+ # 129 (x == x86_EXCEPTION_STATE32) || \
4
+ # 130 (x == x86_DEBUG_STATE32) || \
5
+ # 131 (x == x86_THREAD_STATE64) || \
6
+ # 132 (x == x86_FLOAT_STATE64) || \
7
+ # 133 (x == x86_EXCEPTION_STATE64) || \
8
+ # 134 (x == x86_DEBUG_STATE64) || \
9
+ # 135 (x == x86_THREAD_STATE) || \
10
+ # 136 (x == x86_FLOAT_STATE) || \
11
+ # 137 (x == x86_EXCEPTION_STATE) || \
12
+ # 138 (x == x86_DEBUG_STATE) || \
13
+
14
+ module Ragweed; end
15
+ module Ragweed::Wraposx::ThreadContext
16
+
17
+ X86_THREAD_STATE32 = 1
18
+ X86_FLOAT_STATE32 = 2
19
+ X86_EXCEPTION_STATE32 = 3
20
+ X86_DEBUG_STATE32 = 10
21
+ X86_THREAD_STATE64 = 4
22
+ X86_FLOAT_STATE64 = 5
23
+ X86_EXCEPTION_STATE64 = 6
24
+ X86_DEBUG_STATE64 = 11
25
+ # factory requests (return 32 or 64 bit structure)
26
+ X86_THREAD_STATE = 7
27
+ X86_FLOAT_STATE = 8
28
+ X86_EXCEPTION_STATE = 9
29
+ X86_DEBUG_STATE = 12
30
+ THREAD_STATE_NONE = 13
31
+
32
+ # depricated request names
33
+ I386_THREAD_STATE = X86_THREAD_STATE32
34
+ I386_FLOAT_STATE = X86_FLOAT_STATE32
35
+ I386_EXCEPTION_STATE = X86_EXCEPTION_STATE32
36
+
37
+ # struct x86_state_hdr {
38
+ # int flavor;
39
+ # int count;
40
+ # };
41
+ class X86StateHdr < FFI::Struct
42
+ include Ragweed::FFIStructInclude
43
+ layout :flavor, :int,
44
+ :count, :int
45
+ end
46
+
47
+ # _STRUCT_X86_THREAD_STATE32
48
+ # {
49
+ # unsigned int eax;
50
+ # unsigned int ebx;
51
+ # unsigned int ecx;
52
+ # unsigned int edx;
53
+ # unsigned int edi;
54
+ # unsigned int esi;
55
+ # unsigned int ebp;
56
+ # unsigned int esp;
57
+ # unsigned int ss;
58
+ # unsigned int eflags;
59
+ # unsigned int eip;
60
+ # unsigned int cs;
61
+ # unsigned int ds;
62
+ # unsigned int es;
63
+ # unsigned int fs;
64
+ # unsigned int gs;
65
+ # };
66
+ class State32 < FFI::Struct
67
+ include Ragweed::FFIStructInclude
68
+ FLAVOR = 1
69
+ layout :eax, :uint,
70
+ :ebx, :uint,
71
+ :ecx, :uint,
72
+ :edx, :uint,
73
+ :edi, :uint,
74
+ :esi, :uint,
75
+ :ebp, :uint,
76
+ :esp, :uint,
77
+ :ss, :uint,
78
+ :eflags, :uint,
79
+ :eip, :uint,
80
+ :cs, :uint,
81
+ :ds, :uint,
82
+ :es, :uint,
83
+ :fs, :uint,
84
+ :gs, :uint
85
+
86
+ module Flags
87
+ CARRY = 0x1
88
+ X0 = 0x2
89
+ PARITY = 0x4
90
+ X1 = 0x8
91
+ ADJUST = 0x10
92
+ X2 = 0x20
93
+ ZERO = 0x40
94
+ SIGN = 0x80
95
+ TRAP = 0x100
96
+ INTERRUPT = 0x200
97
+ DIRECTION = 0x400
98
+ OVERFLOW = 0x800
99
+ IOPL1 = 0x1000
100
+ IOPL2 = 0x2000
101
+ NESTEDTASK = 0x4000
102
+ X3 = 0x8000
103
+ RESUME = 0x10000
104
+ V86MODE = 0x20000
105
+ ALIGNCHECK = 0x40000
106
+ VINT = 0x80000
107
+ VINTPENDING = 0x100000
108
+ CPUID = 0x200000
109
+ end
110
+
111
+ def dump(&block)
112
+ maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
113
+ maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
114
+
115
+ string =<<EOM
116
+ -----------------------------------------------------------------------
117
+ CONTEXT:
118
+ EIP: #{self.eip.to_s(16).rjust(8, "0")} #{maybe_dis.call(self.eip)}
119
+
120
+ EAX: #{self.eax.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.eax)}
121
+ EBX: #{self.ebx.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.ebx)}
122
+ ECX: #{self.ecx.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.ecx)}
123
+ EDX: #{self.edx.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.edx)}
124
+ EDI: #{self.edi.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.edi)}
125
+ ESI: #{self.esi.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.esi)}
126
+ EBP: #{self.ebp.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.ebp)}
127
+ ESP: #{self.esp.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.esp)}
128
+ EFL: #{self.eflags.to_s(2).rjust(32, "0")} #{Flags.flag_dump(self.eflags)}
129
+ EOM
130
+ end
131
+
132
+ # sets/clears the TRAP flag
133
+ def single_step(v=true)
134
+ if v
135
+ self.eflags |= Flags::TRAP
136
+ else
137
+ self.eflags &= ~(Flags::TRAP)
138
+ end
139
+ end
140
+ end
141
+
142
+ # _STRUCT_X86_THREAD_STATE64
143
+ # {
144
+ # __uint64_t rax;
145
+ # __uint64_t rbx;
146
+ # __uint64_t rcx;
147
+ # __uint64_t rdx;
148
+ # __uint64_t rdi;
149
+ # __uint64_t rsi;
150
+ # __uint64_t rbp;
151
+ # __uint64_t rsp;
152
+ # __uint64_t r8;
153
+ # __uint64_t r9;
154
+ # __uint64_t r10;
155
+ # __uint64_t r11;
156
+ # __uint64_t r12;
157
+ # __uint64_t r13;
158
+ # __uint64_t r14;
159
+ # __uint64_t r15;
160
+ # __uint64_t rip;
161
+ # __uint64_t rflags;
162
+ # __uint64_t cs;
163
+ # __uint64_t fs;
164
+ # __uint64_t gs;
165
+ # };
166
+ class State64 < FFI::Struct
167
+ include Ragweed::FFIStructInclude
168
+ FLAVOR = 4
169
+ layout :rax, :uint64,
170
+ :rbx, :uint64,
171
+ :rcx, :uint64,
172
+ :rdx, :uint64,
173
+ :rdi, :uint64,
174
+ :rsi, :uint64,
175
+ :rbp, :uint64,
176
+ :rsp, :uint64,
177
+ :r8, :uint64,
178
+ :r9, :uint64,
179
+ :r10, :uint64,
180
+ :r11, :uint64,
181
+ :r12, :uint64,
182
+ :r13, :uint64,
183
+ :r14, :uint64,
184
+ :r15, :uint64,
185
+ :rip, :uint64,
186
+ :rflags, :uint64,
187
+ :cs, :uint64,
188
+ :fs, :uint64,
189
+ :gs, :uint64,
190
+
191
+ module Flags
192
+ CARRY = 0x1
193
+ X0 = 0x2
194
+ PARITY = 0x4
195
+ X1 = 0x8
196
+ ADJUST = 0x10
197
+ X2 = 0x20
198
+ ZERO = 0x40
199
+ SIGN = 0x80
200
+ TRAP = 0x100
201
+ INTERRUPT = 0x200
202
+ DIRECTION = 0x400
203
+ OVERFLOW = 0x800
204
+ IOPL1 = 0x1000
205
+ IOPL2 = 0x2000
206
+ NESTEDTASK = 0x4000
207
+ X3 = 0x8000
208
+ RESUME = 0x10000
209
+ V86MODE = 0x20000
210
+ ALIGNCHECK = 0x40000
211
+ VINT = 0x80000
212
+ VINTPENDING = 0x100000
213
+ CPUID = 0x200000
214
+ end
215
+
216
+ def dump(&block)
217
+ maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
218
+ maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
219
+
220
+ string =<<EOM
221
+ -----------------------------------------------------------------------
222
+ CONTEXT:
223
+ RIP: #{self.rip.to_s(16).rjust(16, "0")} #{maybe_dis.call(self.eip)}
224
+
225
+ RAX: #{self.rax.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.eax)}
226
+ RBX: #{self.rbx.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.ebx)}
227
+ RCX: #{self.rcx.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.ecx)}
228
+ RDX: #{self.rdx.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.edx)}
229
+ RDI: #{self.rdi.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.edi)}
230
+ RSI: #{self.rsi.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.esi)}
231
+ RBP: #{self.rbp.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.ebp)}
232
+ RSP: #{self.rsp.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.esp)}
233
+ RFL: #{(self.rflags & 0xffffffff).to_s(2).rjust(32, "0")} #{Flags.flag_dump(self.rflags & 0xffffffff)}
234
+ EOM
235
+ end
236
+
237
+ # sets/clears the TRAP flag
238
+ def single_step(v=true)
239
+ if v
240
+ @rflags |= Flags::TRAP
241
+ else
242
+ @rflags &= ~(Flags::TRAP)
243
+ end
244
+ end
245
+ end
246
+
247
+ class UnionThreadState < FFI::Union
248
+ include Ragweed::FFIStructInclude
249
+ layout :ts32, Ragweed::Wraposx::ThreadContext::State32,
250
+ :ts64, Ragweed::Wraposx::ThreadContext::State64
251
+ end
252
+
253
+ class State < FFI::Struct
254
+ include Ragweed::FFIStructInclude
255
+ FLAVOR = 7
256
+ layout :tsh, Ragweed::Wraposx::ThreadContext::X86StateHdr,
257
+ :uts, Ragweed::Wraposx::ThreadContext::UnionThreadState
258
+
259
+ # We have rubified this FFI structure by creating a bunch of proxy
260
+ # methods that are normally only accessible via self.v.x.y which is
261
+ # a lot to type. You can still use that method however these proxy
262
+ # methods should allow for considerably clearer code
263
+ if RUBY_VERSION < "1.9"
264
+ def methods regular=true
265
+ ret = super + self.members.map{|x| [x.to_s, x.to_s + "="]}
266
+ ret += self[:tsh].members.map{|x| [x.to_s, x.to_s + "="]}
267
+ ret + case self[:tsh][:flavor]
268
+ when Ragweed::Wraposx::ThreadContext::X86_THREAD_STATE32
269
+ self[:uts].ts32.members.map{|x| [x.to_s, x.to_s + "="]}
270
+ when Ragweed::Wraposx::ThreadContext::X86_THREAD_STATE64
271
+ self[:uts].ts64.members.map{|x| [x.to_s, x.to_s + "="]}
272
+ else
273
+ []
274
+ end
275
+ ret.flatten
276
+ end
277
+ else
278
+ def methods regular=true
279
+ ret = super + self.members.map{|x| [x, (x.to_s + "=").intern]}
280
+ ret += self[:tsh].members.map{|x| [x, (x.to_s + "=").intern]}
281
+ ret + case self[:tsh][:flavor]
282
+ when Ragweed::Wraposx::ThreadContext::X86_THREAD_STATE32
283
+ self[:uts].ts32.members.map{|x| [x, (x.to_s + "=").intern]}
284
+ when Ragweed::Wraposx::ThreadContext::X86_THREAD_STATE64
285
+ self[:uts].ts64.members.map{|x| [x, (x.to_s + "=").intern]}
286
+ else
287
+ []
288
+ end
289
+ ret.flatten
290
+ end
291
+ end
292
+
293
+ def method_missing meth, *args
294
+ super unless self.respond_to? meth
295
+ if meth.to_s =~ /=$/
296
+ mth = meth.to_s.gsub(/=$/,'').intern
297
+ if self.members.include? mth
298
+ # don't proxy
299
+ self.__send__(:[]=, mth, *args)
300
+ elsif self[:tsh].members.include? meth
301
+ self[:tsh].__send__(:[]=, mth, *args)
302
+ else
303
+ case self[:tsh][:flavor]
304
+ when Ragweed::Wraposx::ThreadContext::X86_THREAD_STATE32
305
+ self[:uts].ts32.__send__(:[]=, mth, *args)
306
+ when Ragweed::Wraposx::ThreadContext::X86_THREAD_STATE64
307
+ self[:uts].ts64.__send__(:[]=, mth, *args)
308
+ end
309
+ end
310
+ else
311
+ if self.members.include? meth
312
+ # don't proxy
313
+ self.__send__(:[], meth, *args)
314
+ elsif self[:tsh].members.include? meth
315
+ self[:tsh].__send__(:[], meth, *args)
316
+ else
317
+ case self[:tsh][:flavor]
318
+ when Ragweed::Wraposx::ThreadContext::X86_THREAD_STATE32
319
+ self[:uts].ts32.__send__(:[], meth, *args)
320
+ when Ragweed::Wraposx::ThreadContext::X86_THREAD_STATE64
321
+ self[:uts].ts64.__send__(:[], meth, *args)
322
+ end
323
+ end
324
+ end
325
+ end
326
+
327
+ def respond_to? meth, include_priv=false
328
+ mth = meth.to_s.gsub(/=$/,'') # may not be needed anymore
329
+ self.methods.include? mth || super
330
+ end
331
+
332
+ end
333
+
334
+ # _STRUCT_X86_DEBUG_STATE32
335
+ # {
336
+ # unsigned int dr0;
337
+ # unsigned int dr1;
338
+ # unsigned int dr2;
339
+ # unsigned int dr3;
340
+ # unsigned int dr4;
341
+ # unsigned int dr5;
342
+ # unsigned int dr6;
343
+ # unsigned int dr7;
344
+ # };
345
+ class Debug32 < FFI::Struct
346
+ include Ragweed::FFIStructInclude
347
+ FLAVOR = 10
348
+ layout :dr0, :uint,
349
+ :dr1, :uint,
350
+ :dr2, :uint,
351
+ :dr3, :uint,
352
+ :dr4, :uint,
353
+ :dr5, :uint,
354
+ :dr6, :uint,
355
+ :dr7, :uint
356
+
357
+ def dump(&block)
358
+ maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
359
+ maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
360
+
361
+ string =<<EOM
362
+ -----------------------------------------------------------------------
363
+ CONTEXT:
364
+ DR0: #{self.dr0.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.dr0)}
365
+ DR1: #{self.dr1.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.dr1)}
366
+ DR2: #{self.dr2.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.dr2)}
367
+ DR3: #{self.dr3.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.dr3)}
368
+ DR4: #{self.dr4.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.dr4)}
369
+ DR5: #{self.dr5.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.dr5)}
370
+ DR6: #{self.dr6.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.dr6)}
371
+ DR7: #{self.dr7.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.dr7)}
372
+ EOM
373
+ end
374
+ end
375
+
376
+ # _STRUCT_X86_DEBUG_STATE64
377
+ # {
378
+ # __uint64_t dr0;
379
+ # __uint64_t dr1;
380
+ # __uint64_t dr2;
381
+ # __uint64_t dr3;
382
+ # __uint64_t dr4;
383
+ # __uint64_t dr5;
384
+ # __uint64_t dr6;
385
+ # __uint64_t dr7;
386
+ # };
387
+ class Debug64 < FFI::Struct
388
+ include Ragweed::FFIStructInclude
389
+ FLAVOR = 11
390
+ layout :dr0, :uint64,
391
+ :dr1, :uint64,
392
+ :dr2, :uint64,
393
+ :dr3, :uint64,
394
+ :dr4, :uint64,
395
+ :dr5, :uint64,
396
+ :dr6, :uint64,
397
+ :dr7, :uint64
398
+
399
+ def dump(&block)
400
+ maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
401
+ maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
402
+
403
+ string =<<EOM
404
+ -----------------------------------------------------------------------
405
+ CONTEXT:
406
+ DR0: #{self.dr0.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.dr0)}
407
+ DR1: #{self.dr1.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.dr1)}
408
+ DR2: #{self.dr2.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.dr2)}
409
+ DR3: #{self.dr3.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.dr3)}
410
+ DR4: #{self.dr4.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.dr4)}
411
+ DR5: #{self.dr5.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.dr5)}
412
+ DR6: #{self.dr6.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.dr6)}
413
+ DR7: #{self.dr7.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.dr7)}
414
+ EOM
415
+ end
416
+ end
417
+
418
+ class UnionDebugState < FFI::Union
419
+ include Ragweed::FFIStructInclude
420
+ layout :ds32, Ragweed::Wraposx::ThreadContext::Debug32,
421
+ :ds64, Ragweed::Wraposx::ThreadContext::Debug64
422
+ end
423
+
424
+ class Debug < FFI::Struct
425
+ include Ragweed::FFIStructInclude
426
+ FLAVOR = 12
427
+ layout :dsh, Ragweed::Wraposx::ThreadContext::X86StateHdr,
428
+ :uds, Ragweed::Wraposx::ThreadContext::UnionDebugState
429
+
430
+ # We have rubified this FFI structure by creating a bunch of proxy
431
+ # methods that are normally only accessible via self.v.x.y which is
432
+ # a lot to type. You can still use that method however these proxy
433
+ # methods should allow for considerably clearer code
434
+ if RUBY_VERSION < "1.9"
435
+ def methods regular=true
436
+ ret = super + self.members.map{|x| [x.to_s, x.to_s + "="]}
437
+ ret += self[:dsh].members.map{|x| [x.to_s, x.to_s + "="]}
438
+ ret + case self[:dsh][:flavor]
439
+ when Ragweed::Wraposx::ThreadContext::X86_DEBUG_STATE32
440
+ self[:uds].ds32.members.map{|x| [x.to_s, x.to_s + "="]}
441
+ when Ragweed::Wraposx::ThreadContext::X86_DEBUG_STATE64
442
+ self[:uds].ds64.members.map{|x| [x.to_s, x.to_s + "="]}
443
+ else
444
+ []
445
+ end
446
+ ret.flatten
447
+ end
448
+ else
449
+ def methods regular=true
450
+ ret = super + self.members.map{|x| [x, (x.to_s + "=").intern]}
451
+ ret += self[:dsh].members.map{|x| [x, (x.to_s + "=").intern]}
452
+ ret + case self[:dsh][:flavor]
453
+ when Ragweed::Wraposx::ThreadContext::X86_DEBUG_STATE32
454
+ self[:uds].ds32.members.map{|x| [x, (x.to_s + "=").intern]}
455
+ when Ragweed::Wraposx::ThreadContext::X86_DEBUG_STATE64
456
+ self[:uds].ds64.members.map{|x| [x, (x.to_s + "=").intern]}
457
+ else
458
+ []
459
+ end
460
+ ret.flatten
461
+ end
462
+ end
463
+
464
+ def method_missing meth, *args
465
+ super unless self.respond_to? meth
466
+ if meth.to_s =~ /=$/
467
+ mth = meth.to_s.gsub(/=$/,'').intern
468
+ if self.members.include? mth
469
+ # don't proxy
470
+ self.__send__(:[]=, mth, *args)
471
+ elsif self[:dsh].members.include? meth
472
+ self[:dsh].__send__(:[]=, mth, *args)
473
+ else
474
+ case self[:dsh][:flavor]
475
+ when Ragweed::Wraposx::ThreadContext::X86_DEBUG_STATE32
476
+ self[:uds].ds32.__send__(:[]=, mth, *args)
477
+ when Ragweed::Wraposx::ThreadContext::X86_DEBUG_STATE64
478
+ self[:uds].ds64.__send__(:[]=, mth, *args)
479
+ end
480
+ end
481
+ else
482
+ if self.members.include? meth
483
+ # don't proxy
484
+ self.__send__(:[], meth, *args)
485
+ elsif self[:dsh].members.include? meth
486
+ self[:dsh].__send__(:[], meth, *args)
487
+ else
488
+ case self[:dsh][:flavor]
489
+ when Ragweed::Wraposx::ThreadContext::X86_DEBUG_STATE32
490
+ self[:uds].ds32.__send__(:[], meth, *args)
491
+ when Ragweed::Wraposx::ThreadContext::X86_DEBUG_STATE64
492
+ self[:uds].ds64.__send__(:[], meth, *args)
493
+ end
494
+ end
495
+ end
496
+ end
497
+
498
+ def respond_to? meth, include_priv=false
499
+ mth = meth.to_s.gsub(/=$/,'') # may not be needed anymore
500
+ self.methods.include? mth || super
501
+ end
502
+ end
503
+
504
+ # _STRUCT_X86_EXCEPTION_STATE32
505
+ # {
506
+ # unsigned int trapno;
507
+ # unsigned int err;
508
+ # unsigned int faultvaddr;
509
+ # };
510
+ class Exception32 < FFI::Struct
511
+ include Ragweed::FFIStructInclude
512
+ FLAVOR = 3
513
+ layout :trapno, :uint,
514
+ :err, :uint,
515
+ :faltvaddr, :uint
516
+
517
+ def dump(&block)
518
+ maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
519
+ maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
520
+
521
+ string =<<EOM
522
+ -----------------------------------------------------------------------
523
+ CONTEXT:
524
+ trapno: #{self.trapno.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.trapno)}
525
+ err: #{self.err.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.err)}
526
+ faultvaddr: #{self.faultvaddr.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.faultvaddr)}
527
+ EOM
528
+ end
529
+ end
530
+
531
+ # _STRUCT_X86_EXCEPTION_STATE64
532
+ # {
533
+ # unsigned int trapno;
534
+ # unsigned int err;
535
+ # __uint64_t faultvaddr;
536
+ # };
537
+ class Exception64 < FFI::Struct
538
+ include Ragweed::FFIStructInclude
539
+ FLAVOR = 6
540
+ layout :trapno, :uint,
541
+ :err, :uint,
542
+ :faltvaddr, :uint64
543
+
544
+ def dump(&block)
545
+ maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
546
+ maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
547
+
548
+ string =<<EOM
549
+ -----------------------------------------------------------------------
550
+ CONTEXT:
551
+ trapno: #{self.trapno.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.trapno)}
552
+ err: #{self.err.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.err)}
553
+ faultvaddr: #{self.faultvaddr.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.faultvaddr)}
554
+ EOM
555
+ end
556
+ end
557
+
558
+ class UnionExceptionState < FFI::Union
559
+ include Ragweed::FFIStructInclude
560
+ layout :es32, Ragweed::Wraposx::ThreadContext::Exception32,
561
+ :es64, Ragweed::Wraposx::ThreadContext::Exception64
562
+ end
563
+
564
+ class Exception < FFI::Struct
565
+ include Ragweed::FFIStructInclude
566
+ FLAVOR = 9
567
+ layout :esh, Ragweed::Wraposx::ThreadContext::X86StateHdr,
568
+ :ues, Ragweed::Wraposx::ThreadContext::UnionExceptionState
569
+
570
+ #comment
571
+ # We have rubified this FFI structure by creating a bunch of proxy
572
+ # methods that are normally only accessible via self.v.x.y which is
573
+ # a lot to type. You can still use that method however these proxy
574
+ # methods should allow for considerably clearer code
575
+ if RUBY_VERSION < "1.9"
576
+ def methods regular=true
577
+ ret = super + self.members.map{|x| [x.to_s, x.to_s + "="]}
578
+ ret += self[:esh].members.map{|x| [x.to_s, x.to_s + "="]}
579
+ ret + case self[:esh][:flavor]
580
+ when Ragweed::Wraposx::ThreadContext::X86_EXCEPTION_STATE32
581
+ self[:ues].es32.members.map{|x| [x.to_s, x.to_s + "="]}
582
+ when Ragweed::Wraposx::ThreadContext::X86_EXCEPTION_STATE64
583
+ self[:ues].es64.members.map{|x| [x.to_s, x.to_s + "="]}
584
+ else
585
+ []
586
+ end
587
+ ret.flatten
588
+ end
589
+ else
590
+ def methods regular=true
591
+ ret = super + self.members.map{|x| [x, (x.to_s + "=").intern]}
592
+ ret += self[:esh].members.map{|x| [x, (x.to_s + "=").intern]}
593
+ ret + case self[:esh][:flavor]
594
+ when Ragweed::Wraposx::ThreadContext::X86_EXCEPTION_STATE32
595
+ self[:ues].es32.members.map{|x| [x, (x.to_s + "=").intern]}
596
+ when Ragweed::Wraposx::ThreadContext::X86_EXCEPTION_STATE64
597
+ self[:ues].es64.members.map{|x| [x, (x.to_s + "=").intern]}
598
+ else
599
+ []
600
+ end
601
+ ret.flatten
602
+ end
603
+ end
604
+
605
+ def method_missing meth, *args
606
+ super unless self.respond_to? meth
607
+ if meth.to_s =~ /=$/
608
+ mth = meth.to_s.gsub(/=$/,'').intern
609
+ if self.members.include? mth
610
+ # don't proxy
611
+ self.__send__(:[]=, mth, *args)
612
+ elsif self[:esh].members.include? meth
613
+ self[:esh].__send__(:[]=, mth, *args)
614
+ else
615
+ case self[:esh][:flavor]
616
+ when Ragweed::Wraposx::ThreadContext::X86_EXCEPTION_STATE32
617
+ self[:ues].es32.__send__(:[]=, mth, *args)
618
+ when Ragweed::Wraposx::ThreadContext::X86_EXCEPTION_STATE64
619
+ self[:ues].es64.__send__(:[]=, mth, *args)
620
+ end
621
+ end
622
+ else
623
+ if self.members.include? meth
624
+ # don't proxy
625
+ self.__send__(:[], meth, *args)
626
+ elsif self[:esh].members.include? meth
627
+ self[:esh].__send__(:[], meth, *args)
628
+ else
629
+ case self[:esh][:flavor]
630
+ when Ragweed::Wraposx::ThreadContext::X86_EXCEPTION_STATE32
631
+ self[:ues].es32.__send__(:[], meth, *args)
632
+ when Ragweed::Wraposx::ThreadContext::X86_EXCEPTION_STATE64
633
+ self[:ues].es64.__send__(:[], meth, *args)
634
+ end
635
+ end
636
+ end
637
+ end
638
+
639
+ def respond_to? meth, include_priv=false
640
+ mth = meth.to_s.gsub(/=$/,'') # may not be needed anymore
641
+ self.methods.include? mth || super
642
+ end
643
+
644
+ end
645
+
646
+ # _STRUCT_X86_FLOAT_STATE32
647
+ # {
648
+ # int fpu_reserved[2];
649
+ # _STRUCT_FP_CONTROL fpu_fcw; /* x87 FPU control word */
650
+ # _STRUCT_FP_STATUS fpu_fsw; /* x87 FPU status word */
651
+ # __uint8_t fpu_ftw; /* x87 FPU tag word */
652
+ # __uint8_t fpu_rsrv1; /* reserved */
653
+ # __uint16_t fpu_fop; /* x87 FPU Opcode */
654
+ # __uint32_t fpu_ip; /* x87 FPU Instruction Pointer offset */
655
+ # __uint16_t fpu_cs; /* x87 FPU Instruction Pointer Selector */
656
+ # __uint16_t fpu_rsrv2; /* reserved */
657
+ # __uint32_t fpu_dp; /* x87 FPU Instruction Operand(Data) Pointer offset */
658
+ # __uint16_t fpu_ds; /* x87 FPU Instruction Operand(Data) Pointer Selector */
659
+ # __uint16_t fpu_rsrv3; /* reserved */
660
+ # __uint32_t fpu_mxcsr; /* MXCSR Register state */
661
+ # __uint32_t fpu_mxcsrmask; /* MXCSR mask */
662
+ # _STRUCT_MMST_REG fpu_stmm0; /* ST0/MM0 */
663
+ # _STRUCT_MMST_REG fpu_stmm1; /* ST1/MM1 */
664
+ # _STRUCT_MMST_REG fpu_stmm2; /* ST2/MM2 */
665
+ # _STRUCT_MMST_REG fpu_stmm3; /* ST3/MM3 */
666
+ # _STRUCT_MMST_REG fpu_stmm4; /* ST4/MM4 */
667
+ # _STRUCT_MMST_REG fpu_stmm5; /* ST5/MM5 */
668
+ # _STRUCT_MMST_REG fpu_stmm6; /* ST6/MM6 */
669
+ # _STRUCT_MMST_REG fpu_stmm7; /* ST7/MM7 */
670
+ # _STRUCT_XMM_REG fpu_xmm0; /* XMM 0 */
671
+ # _STRUCT_XMM_REG fpu_xmm1; /* XMM 1 */
672
+ # _STRUCT_XMM_REG fpu_xmm2; /* XMM 2 */
673
+ # _STRUCT_XMM_REG fpu_xmm3; /* XMM 3 */
674
+ # _STRUCT_XMM_REG fpu_xmm4; /* XMM 4 */
675
+ # _STRUCT_XMM_REG fpu_xmm5; /* XMM 5 */
676
+ # _STRUCT_XMM_REG fpu_xmm6; /* XMM 6 */
677
+ # _STRUCT_XMM_REG fpu_xmm7; /* XMM 7 */
678
+ # char fpu_rsrv4[14*16]; /* reserved */
679
+ # int fpu_reserved1;
680
+ # };
681
+ class Float32 < FFI::Struct
682
+ include Ragweed::FFIStructInclude
683
+ FLAVOR = 2
684
+ layout :fpu_reserved, [:int, 2],
685
+ :fpu_fcw, Ragweed::Wraposx::FpControl,
686
+ :fpu_fsw, Ragweed::Wraposx::FpStatus,
687
+ :fpu_ftw, :uint8,
688
+ :fpu_rsrv1, :uint8,
689
+ :fpu_fop, :uint16,
690
+ :fpu_ip, :uint32,
691
+ :fpu_cs, :uint16,
692
+ :fpu_rsrv2, :uint16,
693
+ :fpu_dp, :uint32,
694
+ :fpu_ds, :uint16,
695
+ :fpu_rsrv3, :uint16,
696
+ :fpu_mxcsr, :uint32,
697
+ :fpu_mxcsrmask, :uint32,
698
+ :fpu_stmm0, Ragweed::Wraposx::MmstReg,
699
+ :fpu_stmm1, Ragweed::Wraposx::MmstReg,
700
+ :fpu_stmm2, Ragweed::Wraposx::MmstReg,
701
+ :fpu_stmm3, Ragweed::Wraposx::MmstReg,
702
+ :fpu_stmm4, Ragweed::Wraposx::MmstReg,
703
+ :fpu_stmm5, Ragweed::Wraposx::MmstReg,
704
+ :fpu_stmm6, Ragweed::Wraposx::MmstReg,
705
+ :fpu_stmm7, Ragweed::Wraposx::MmstReg,
706
+ :fpu_xmm0, Ragweed::Wraposx::XmmReg,
707
+ :fpu_xmm1, Ragweed::Wraposx::XmmReg,
708
+ :fpu_xmm2, Ragweed::Wraposx::XmmReg,
709
+ :fpu_xmm3, Ragweed::Wraposx::XmmReg,
710
+ :fpu_xmm4, Ragweed::Wraposx::XmmReg,
711
+ :fpu_xmm5, Ragweed::Wraposx::XmmReg,
712
+ :fpu_xmm6, Ragweed::Wraposx::XmmReg,
713
+ :fpu_xmm7, Ragweed::Wraposx::XmmReg,
714
+ :fpu_rsrv4, [:char, 14*16],
715
+ :fpu_reserved1, :int
716
+
717
+ def dump(&block)
718
+ maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
719
+ maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
720
+
721
+ string =<<EOM
722
+ -----------------------------------------------------------------------
723
+ CONTEXT:
724
+ trapno: #{self.trapno.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.trapno)}
725
+ err: #{self.err.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.err)}
726
+ faultvaddr: #{self.faultvaddr.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.faultvaddr)}
727
+ EOM
728
+ end
729
+ end
730
+
731
+ # _STRUCT_X86_FLOAT_STATE64
732
+ # {
733
+ # int fpu_reserved[2];
734
+ # _STRUCT_FP_CONTROL fpu_fcw; /* x87 FPU control word */
735
+ # _STRUCT_FP_STATUS fpu_fsw; /* x87 FPU status word */
736
+ # __uint8_t fpu_ftw; /* x87 FPU tag word */
737
+ # __uint8_t fpu_rsrv1; /* reserved */
738
+ # __uint16_t fpu_fop; /* x87 FPU Opcode */
739
+ # /* x87 FPU Instruction Pointer */
740
+ # __uint32_t fpu_ip; /* offset */
741
+ # __uint16_t fpu_cs; /* Selector */
742
+ # __uint16_t fpu_rsrv2; /* reserved */
743
+ # /* x87 FPU Instruction Operand(Data) Pointer */
744
+ # __uint32_t fpu_dp; /* offset */
745
+ # __uint16_t fpu_ds; /* Selector */
746
+ # __uint16_t fpu_rsrv3; /* reserved */
747
+ # __uint32_t fpu_mxcsr; /* MXCSR Register state */
748
+ # __uint32_t fpu_mxcsrmask; /* MXCSR mask */
749
+ # _STRUCT_MMST_REG fpu_stmm0; /* ST0/MM0 */
750
+ # _STRUCT_MMST_REG fpu_stmm1; /* ST1/MM1 */
751
+ # _STRUCT_MMST_REG fpu_stmm2; /* ST2/MM2 */
752
+ # _STRUCT_MMST_REG fpu_stmm3; /* ST3/MM3 */
753
+ # _STRUCT_MMST_REG fpu_stmm4; /* ST4/MM4 */
754
+ # _STRUCT_MMST_REG fpu_stmm5; /* ST5/MM5 */
755
+ # _STRUCT_MMST_REG fpu_stmm6; /* ST6/MM6 */
756
+ # _STRUCT_MMST_REG fpu_stmm7; /* ST7/MM7 */
757
+ # _STRUCT_XMM_REG fpu_xmm0; /* XMM 0 */
758
+ # _STRUCT_XMM_REG fpu_xmm1; /* XMM 1 */
759
+ # _STRUCT_XMM_REG fpu_xmm2; /* XMM 2 */
760
+ # _STRUCT_XMM_REG fpu_xmm3; /* XMM 3 */
761
+ # _STRUCT_XMM_REG fpu_xmm4; /* XMM 4 */
762
+ # _STRUCT_XMM_REG fpu_xmm5; /* XMM 5 */
763
+ # _STRUCT_XMM_REG fpu_xmm6; /* XMM 6 */
764
+ # _STRUCT_XMM_REG fpu_xmm7; /* XMM 7 */
765
+ # _STRUCT_XMM_REG fpu_xmm8; /* XMM 8 */
766
+ # _STRUCT_XMM_REG fpu_xmm9; /* XMM 9 */
767
+ # _STRUCT_XMM_REG fpu_xmm10; /* XMM 10 */
768
+ # _STRUCT_XMM_REG fpu_xmm11; /* XMM 11 */
769
+ # _STRUCT_XMM_REG fpu_xmm12; /* XMM 12 */
770
+ # _STRUCT_XMM_REG fpu_xmm13; /* XMM 13 */
771
+ # _STRUCT_XMM_REG fpu_xmm14; /* XMM 14 */
772
+ # _STRUCT_XMM_REG fpu_xmm15; /* XMM 15 */
773
+ # char fpu_rsrv4[6*16]; /* reserved */
774
+ # int fpu_reserved1;
775
+ # };
776
+ class Float64 < FFI::Struct
777
+ include Ragweed::FFIStructInclude
778
+ FLAVOR = 5
779
+ layout :fpu_reserved, [:int, 2],
780
+ :fpu_fcw, Ragweed::Wraposx::FpControl,
781
+ :fpu_fsw, Ragweed::Wraposx::FpStatus,
782
+ :fpu_ftw, :uint8,
783
+ :fpu_rsrv1, :uint8,
784
+ :fpu_fop, :uint16,
785
+ :fpu_ip, :uint32,
786
+ :fpu_cs, :uint16,
787
+ :fpu_rsrv2, :uint16,
788
+ :fpu_dp, :uint32,
789
+ :fpu_ds, :uint16,
790
+ :fpu_rsrv3, :uint16,
791
+ :fpu_mxcsr, :uint32,
792
+ :fpu_mxcsrmask, :uint32,
793
+ :fpu_stmm0, Ragweed::Wraposx::MmstReg,
794
+ :fpu_stmm1, Ragweed::Wraposx::MmstReg,
795
+ :fpu_stmm2, Ragweed::Wraposx::MmstReg,
796
+ :fpu_stmm3, Ragweed::Wraposx::MmstReg,
797
+ :fpu_stmm4, Ragweed::Wraposx::MmstReg,
798
+ :fpu_stmm5, Ragweed::Wraposx::MmstReg,
799
+ :fpu_stmm6, Ragweed::Wraposx::MmstReg,
800
+ :fpu_stmm7, Ragweed::Wraposx::MmstReg,
801
+ :fpu_xmm0, Ragweed::Wraposx::XmmReg,
802
+ :fpu_xmm1, Ragweed::Wraposx::XmmReg,
803
+ :fpu_xmm2, Ragweed::Wraposx::XmmReg,
804
+ :fpu_xmm3, Ragweed::Wraposx::XmmReg,
805
+ :fpu_xmm4, Ragweed::Wraposx::XmmReg,
806
+ :fpu_xmm5, Ragweed::Wraposx::XmmReg,
807
+ :fpu_xmm6, Ragweed::Wraposx::XmmReg,
808
+ :fpu_xmm7, Ragweed::Wraposx::XmmReg,
809
+ :fpu_xmm8, Ragweed::Wraposx::XmmReg,
810
+ :fpu_xmm9, Ragweed::Wraposx::XmmReg,
811
+ :fpu_xmm10, Ragweed::Wraposx::XmmReg,
812
+ :fpu_xmm11, Ragweed::Wraposx::XmmReg,
813
+ :fpu_xmm12, Ragweed::Wraposx::XmmReg,
814
+ :fpu_xmm13, Ragweed::Wraposx::XmmReg,
815
+ :fpu_xmm14, Ragweed::Wraposx::XmmReg,
816
+ :fpu_xmm15, Ragweed::Wraposx::XmmReg,
817
+ :fpu_rsrv4, [:char, 6*16],
818
+ :fpu_reserved1, :int
819
+
820
+
821
+ def dump(&block)
822
+ maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
823
+ maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
824
+
825
+ string =<<EOM
826
+ -----------------------------------------------------------------------
827
+ CONTEXT:
828
+ trapno: #{self.trapno.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.trapno)}
829
+ err: #{self.err.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.err)}
830
+ faultvaddr: #{self.faultvaddr.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.faultvaddr)}
831
+ EOM
832
+ end
833
+ end
834
+
835
+ class UnionFloatState < FFI::Union
836
+ include Ragweed::FFIStructInclude
837
+ layout :fs32, Ragweed::Wraposx::ThreadContext::Float32,
838
+ :fs64, Ragweed::Wraposx::ThreadContext::Float64
839
+ end
840
+
841
+ class Float < FFI::Struct
842
+ include Ragweed::FFIStructInclude
843
+ FLAVOR = 8
844
+ layout :fsh, Ragweed::Wraposx::ThreadContext::X86StateHdr,
845
+ :ufs, Ragweed::Wraposx::ThreadContext::UnionFloatState
846
+ end
847
+
848
+ FLAVORS = {
849
+ X86_THREAD_STATE32 => {:size => 64, :count =>16, :class => State32},
850
+ X86_FLOAT_STATE32 => {:size => 64, :count =>16, :class => Float32},
851
+ X86_EXCEPTION_STATE32 => {:size => 12, :count =>3, :class => Exception32},
852
+ X86_DEBUG_STATE32 => {:size => 64, :count =>8, :class => Debug32},
853
+ X86_THREAD_STATE64 => {:size => 168, :count =>42, :class => State64},
854
+ X86_FLOAT_STATE64 => {:size => 64, :count =>16, :class => Float64},
855
+ X86_EXCEPTION_STATE64 => {:size => 16, :count =>4, :class => Exception64},
856
+ X86_DEBUG_STATE64 => {:size => 128, :count =>16, :class => Debug64},
857
+ X86_THREAD_STATE => {:size => 176, :count =>44, :class => State},
858
+ X86_FLOAT_STATE => {:size => 64, :count =>16, :class => Float},
859
+ X86_EXCEPTION_STATE => {:size => 24, :count =>6, :class => Exception},
860
+ X86_DEBUG_STATE => {:size => 136, :count =>18, :class => Debug}
861
+ }
862
+ end
863
+
864
+ module Ragweed::Wraposx
865
+
866
+ module Libc
867
+ extend FFI::Library
868
+ ffi_lib FFI::Library::LIBC
869
+ attach_function :thread_get_state, [:thread_act_t, :thread_state_flavor_t, :pointer, :mach_msg_type_number_t], :kern_return_t
870
+ attach_function :thread_set_state, [:thread_act_t, :thread_state_flavor_t, :pointer, :mach_msg_type_number_t], :kern_return_t
871
+ end
872
+
873
+ class << self
874
+ # Returns a thread's registers for given a thread id
875
+ #
876
+ # kern_return_t thread_get_state
877
+ # (thread_act_t target_thread,
878
+ # thread_state_flavor_t flavor,
879
+ # thread_state_t old_state,
880
+ # mach_msg_type_number_t old_state_count);
881
+ def thread_get_state(thread,flavor)
882
+ state = FFI::MemoryPointer.new Ragweed::Wraposx::ThreadContext::FLAVOR[flavor][:class], 1
883
+ count = FFI::MemoryPointer.new(:int, 1).write_int Ragweed::Wraposx::ThreadContext::FLAVOR[flavor][:count]
884
+ r = Libc.thread_get_state(thread, flavor, state, count)
885
+ raise KernelCallError.new(:thread_get_state, r) if r != 0
886
+ Ragweed::Wraposx::ThreadContext::FLAVOR[flavor][:class].new state
887
+ end
888
+
889
+ # Sets the register state of thread.
890
+ #
891
+ # kern_return_t thread_set_state
892
+ # (thread_act_t target_thread,
893
+ # thread_state_flavor_t flavor,
894
+ # thread_state_t new_state,
895
+ # mach_msg_number_t new_state_count);
896
+ def thread_set_state(thread, flavor, state)
897
+ r = Libc.thread_set_state(thread, flavor, state.to_ptr, ThreadContext::FLAVORS[flavor][:count])
898
+ raise KernelCallError.new(:thread_set_state, r) if r!= 0
899
+ Ragweed::Wraposx::ThreadContext::FLAVOR[flavor][:class].new state
900
+ end
901
+ end
902
+ end