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.
- data/History.txt +32 -0
- data/README.rdoc +60 -0
- data/README.txt +9 -0
- data/Rakefile +86 -0
- data/VERSION +1 -0
- data/examples/hittracertux.rb +45 -0
- data/examples/hittracerx.rb +63 -0
- data/examples/hook_notepad.rb +9 -0
- data/examples/snicker.rb +183 -0
- data/examples/tux-example.rb +24 -0
- data/lib/ragweed/arena.rb +55 -0
- data/lib/ragweed/blocks.rb +128 -0
- data/lib/ragweed/debugger32.rb +400 -0
- data/lib/ragweed/debuggerosx.rb +456 -0
- data/lib/ragweed/debuggertux.rb +502 -0
- data/lib/ragweed/detour.rb +223 -0
- data/lib/ragweed/ptr.rb +48 -0
- data/lib/ragweed/rasm/bblock.rb +73 -0
- data/lib/ragweed/rasm/isa.rb +1115 -0
- data/lib/ragweed/rasm.rb +59 -0
- data/lib/ragweed/sbuf.rb +197 -0
- data/lib/ragweed/trampoline.rb +103 -0
- data/lib/ragweed/utils.rb +182 -0
- data/lib/ragweed/wrap32/debugging.rb +401 -0
- data/lib/ragweed/wrap32/device.rb +49 -0
- data/lib/ragweed/wrap32/event.rb +50 -0
- data/lib/ragweed/wrap32/hooks.rb +39 -0
- data/lib/ragweed/wrap32/overlapped.rb +46 -0
- data/lib/ragweed/wrap32/process.rb +613 -0
- data/lib/ragweed/wrap32/process_token.rb +75 -0
- data/lib/ragweed/wrap32/thread_context.rb +142 -0
- data/lib/ragweed/wrap32/winx.rb +16 -0
- data/lib/ragweed/wrap32/wrap32.rb +583 -0
- data/lib/ragweed/wrap32.rb +59 -0
- data/lib/ragweed/wraposx/constants.rb +114 -0
- data/lib/ragweed/wraposx/kernelerrorx.rb +147 -0
- data/lib/ragweed/wraposx/region_info.rb +275 -0
- data/lib/ragweed/wraposx/structs.rb +102 -0
- data/lib/ragweed/wraposx/thread_context.rb +902 -0
- data/lib/ragweed/wraposx/thread_info.rb +160 -0
- data/lib/ragweed/wraposx/thread_info.rb.old +121 -0
- data/lib/ragweed/wraposx/wraposx.rb +356 -0
- data/lib/ragweed/wraposx.rb +60 -0
- data/lib/ragweed/wraptux/constants.rb +101 -0
- data/lib/ragweed/wraptux/process.rb +35 -0
- data/lib/ragweed/wraptux/threads.rb +7 -0
- data/lib/ragweed/wraptux/wraptux.rb +72 -0
- data/lib/ragweed/wraptux.rb +57 -0
- data/lib/ragweed.rb +112 -0
- data/ragweed.gemspec +102 -0
- data/spec/ragweed_spec.rb +7 -0
- data/spec/spec_helper.rb +16 -0
- data/test/test_ragweed.rb +0 -0
- 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
|