ragweed 0.1.7.3 → 0.2.0.pre1
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/README.rdoc +33 -8
- data/Rakefile +80 -23
- data/VERSION +1 -0
- data/examples/hittracertux.rb +2 -6
- data/examples/hook_notepad.rb +1 -1
- data/examples/tux-example.rb +3 -2
- data/lib/.DS_Store +0 -0
- data/lib/ragweed/debugger32.rb +188 -145
- data/lib/ragweed/debuggerosx.rb +13 -13
- data/lib/ragweed/debuggertux.rb +267 -140
- data/lib/ragweed/rasm.rb +1 -1
- data/lib/ragweed/wrap32/debugging.rb +184 -64
- data/lib/ragweed/wrap32/hooks.rb +27 -11
- data/lib/ragweed/wrap32/process.rb +114 -7
- data/lib/ragweed/wrap32/process_token.rb +23 -7
- data/lib/ragweed/wrap32/thread_context.rb +100 -166
- data/lib/ragweed/wrap32/wrap32.rb +127 -72
- data/lib/ragweed/wrap32.rb +1 -1
- data/lib/ragweed/wraposx/constants.rb +1 -9
- data/lib/ragweed/wraposx/region_info.rb +209 -188
- data/lib/ragweed/wraposx/structs.rb +102 -0
- data/lib/ragweed/wraposx/thread_context.rb +636 -159
- data/lib/ragweed/wraposx/thread_info.rb +40 -107
- data/lib/ragweed/wraposx/thread_info.rb.old +121 -0
- data/lib/ragweed/wraposx/wraposx.rb +154 -231
- data/lib/ragweed/wraposx.rb +2 -1
- data/lib/ragweed/wraptux/constants.rb +46 -22
- data/lib/ragweed/wraptux/struct_helpers.rb +25 -0
- data/lib/ragweed/wraptux/threads.rb +0 -0
- data/lib/ragweed/wraptux/wraptux.rb +58 -62
- data/lib/ragweed/wraptux.rb +3 -4
- data/lib/ragweed.rb +36 -8
- data/ragweed.gemspec +85 -15
- metadata +50 -18
data/lib/ragweed/debuggertux.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require ::File.join(::File.dirname(__FILE__),'wraptux')
|
2
|
-
## Modeled after wraposx written by tduehr
|
3
2
|
|
4
3
|
module Ragweed; end
|
5
4
|
|
@@ -13,102 +12,87 @@ module Ragweed; end
|
|
13
12
|
## debugger and define your own on_whatever events. If you handle an event
|
14
13
|
## that Debuggertux already handles, call "super", too.
|
15
14
|
class Ragweed::Debuggertux
|
16
|
-
|
17
|
-
|
18
|
-
attr_reader :pid
|
19
|
-
attr_reader :status
|
20
|
-
attr_reader :exited
|
21
|
-
attr_accessor :breakpoints
|
15
|
+
attr_reader :pid, :status, :exited
|
16
|
+
attr_accessor :breakpoints, :mapped_regions
|
22
17
|
|
23
18
|
## Class to handle installing/uninstalling breakpoints
|
24
19
|
class Breakpoint
|
25
20
|
|
26
|
-
INT3 = 0xCC
|
21
|
+
INT3 = 0xCC
|
27
22
|
|
28
|
-
attr_accessor :orig
|
23
|
+
attr_accessor :orig, :bppid, :function, :installed
|
29
24
|
attr_reader :addr
|
30
|
-
attr_accessor :function
|
31
25
|
|
32
|
-
## bp: parent for method_missing calls
|
33
26
|
## ip: insertion point
|
34
27
|
## callable: lambda to be called when breakpoint is hit
|
28
|
+
## p: process ID
|
35
29
|
## name: name of breakpoint
|
36
|
-
def initialize(
|
37
|
-
|
38
|
-
@bp = bp
|
30
|
+
def initialize(ip, callable, p, name = "")
|
31
|
+
@bppid = p
|
39
32
|
@function = name
|
40
33
|
@addr = ip
|
41
34
|
@callable = callable
|
42
35
|
@installed = false
|
36
|
+
@exited = false
|
43
37
|
@orig = 0
|
44
|
-
|
45
|
-
end ## breakpoint initialize
|
38
|
+
end
|
46
39
|
|
47
|
-
## Install a breakpoint (replace instruction with int3)
|
48
40
|
def install
|
49
|
-
|
50
|
-
@orig = Ragweed::Wraptux::ptrace(Ragweed::Wraptux::Ptrace::PEEK_TEXT, $ppid, @addr, 0) ## Backup the old inst
|
41
|
+
@orig = Ragweed::Wraptux::ptrace(Ragweed::Wraptux::Ptrace::PEEK_TEXT, @bppid, @addr, 0)
|
51
42
|
if @orig != -1
|
52
|
-
|
53
|
-
Ragweed::Wraptux::ptrace(Ragweed::Wraptux::Ptrace::POKE_TEXT,
|
43
|
+
n = (@orig & ~0xff) | INT3;
|
44
|
+
Ragweed::Wraptux::ptrace(Ragweed::Wraptux::Ptrace::POKE_TEXT, @bppid, @addr, n)
|
54
45
|
@installed = true
|
55
46
|
else
|
56
47
|
@installed = false
|
57
48
|
end
|
58
49
|
end
|
59
50
|
|
60
|
-
## Uninstall the breakpoint
|
61
51
|
def uninstall
|
62
|
-
## Put back the original instruction
|
63
52
|
if @orig != INT3
|
64
|
-
Ragweed::Wraptux::ptrace(Ragweed::Wraptux::Ptrace::POKE_TEXT,
|
53
|
+
a = Ragweed::Wraptux::ptrace(Ragweed::Wraptux::Ptrace::POKE_TEXT, @bppid, @addr, @orig)
|
65
54
|
@installed = false
|
66
55
|
end
|
67
56
|
end
|
68
57
|
|
69
58
|
def installed?; @installed; end
|
70
59
|
def call(*args); @callable.call(*args) if @callable != nil; end
|
71
|
-
|
72
|
-
end ## Breakpoint Class
|
60
|
+
end
|
73
61
|
|
74
62
|
## init object
|
75
63
|
## p: pid of process to be debugged
|
76
64
|
## opts: default options for automatically doing things (attach and install)
|
77
|
-
def initialize(pid,opts
|
78
|
-
|
65
|
+
def initialize(pid, opts) ## Debuggertux Class
|
66
|
+
if p.to_i.kind_of? Fixnum
|
67
|
+
@pid = pid.to_i
|
68
|
+
else
|
69
|
+
raise "Provide a PID"
|
70
|
+
end
|
79
71
|
|
80
|
-
## FIXME - globals are bad...
|
81
|
-
$ppid = @pid ## temporary work around
|
82
72
|
@opts = opts
|
83
73
|
|
84
74
|
default_opts(opts)
|
85
75
|
@installed = false
|
86
76
|
@attached = false
|
87
77
|
|
88
|
-
|
89
|
-
@breakpoints = Hash.new
|
90
|
-
|
91
|
-
def bps.call(*args); each {|bp| bp.call(*args)}; end
|
92
|
-
def bps.install; each {|bp| bp.install}; end
|
93
|
-
def bps.uninstall; each {|bp| bp.uninstall}; end
|
94
|
-
def bps.orig; each {|bp| dp.orig}; end
|
95
|
-
h[k] = bps
|
96
|
-
end
|
97
|
-
@opts.each {|k, v| try(k) if v}
|
78
|
+
@mapped_regions = Hash.new
|
79
|
+
@breakpoints = Hash.new
|
80
|
+
@opts.each { |k, v| try(k) if v }
|
98
81
|
end
|
99
82
|
|
100
|
-
## This is crude!
|
101
83
|
def self.find_by_regex(rx)
|
102
84
|
a = Dir.entries("/proc/")
|
103
|
-
a.delete_if
|
104
|
-
a.delete_if
|
105
|
-
a.delete_if
|
85
|
+
a.delete_if { |x| x == '.' }
|
86
|
+
a.delete_if { |x| x == '..' }
|
87
|
+
a.delete_if { |x| x =~ /[a-z]/i }
|
88
|
+
|
106
89
|
a.each do |x|
|
107
90
|
f = File.read("/proc/#{x}/cmdline")
|
108
|
-
if f =~ rx
|
91
|
+
if f =~ rx and x.to_i != Process.pid.to_i
|
109
92
|
return x
|
110
93
|
end
|
111
94
|
end
|
95
|
+
return nil
|
112
96
|
end
|
113
97
|
|
114
98
|
def install_bps
|
@@ -125,12 +109,125 @@ class Ragweed::Debuggertux
|
|
125
109
|
@installed = false
|
126
110
|
end
|
127
111
|
|
112
|
+
## This has not been fully tested yet
|
113
|
+
def set_options(option)
|
114
|
+
r = Ragweed::Wraptux::ptrace(Ragweed::Wraptux::Ptrace::SETOPTIONS, @pid, 0, option)
|
115
|
+
end
|
116
|
+
|
128
117
|
## Attach calls install_bps so dont forget to call breakpoint_set
|
129
118
|
## BEFORE attach or explicitly call install_bps
|
130
119
|
def attach(opts=@opts)
|
131
|
-
Ragweed::Wraptux::ptrace(Ragweed::Wraptux::Ptrace::ATTACH, @pid, 0, 0)
|
132
|
-
|
133
|
-
|
120
|
+
r = Ragweed::Wraptux::ptrace(Ragweed::Wraptux::Ptrace::ATTACH, @pid, 0, 0)
|
121
|
+
if r != -1
|
122
|
+
@attached = true
|
123
|
+
on_attach
|
124
|
+
self.install_bps if (opts[:install] and not @installed)
|
125
|
+
else
|
126
|
+
raise "Attach failed!"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
## This method returns a hash of mapped regions
|
131
|
+
## The hash is also stored as @mapped_regions
|
132
|
+
## key = Start address of region
|
133
|
+
## value = Size of the region
|
134
|
+
def mapped
|
135
|
+
@mapped_regions.clear if @mapped_regions
|
136
|
+
|
137
|
+
File.read("/proc/#{pid}/maps").each_line do |l|
|
138
|
+
s,e = l.split('-')
|
139
|
+
e = e.split(' ').first
|
140
|
+
sz = e.to_i(16) - s.to_i(16)
|
141
|
+
@mapped_regions.store(s.to_i(16), sz)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
## Return a name for a range if possible
|
146
|
+
def get_mapping_name(val)
|
147
|
+
File.read("/proc/#{pid}/maps").each_line do |l|
|
148
|
+
base = l.split('-').first
|
149
|
+
max = l[0,17].split('-',2)[1]
|
150
|
+
if base.to_i(16) <= val && val <= max.to_i(16)
|
151
|
+
return l.split(' ').last
|
152
|
+
end
|
153
|
+
end
|
154
|
+
nil
|
155
|
+
end
|
156
|
+
|
157
|
+
## Parse procfs and create a hash containing
|
158
|
+
## a listing of each mapped shared object
|
159
|
+
def self.shared_libraries(p)
|
160
|
+
|
161
|
+
raise "pid is 0" if p.to_i == 0
|
162
|
+
|
163
|
+
if @shared_objects
|
164
|
+
@shared_objects.clear
|
165
|
+
else
|
166
|
+
@shared_objects = Hash.new
|
167
|
+
end
|
168
|
+
|
169
|
+
File.read("/proc/#{p}/maps").each_line do |l|
|
170
|
+
if l =~ /[a-zA-Z0-9].so/ && l =~ /xp /
|
171
|
+
lib = l.split(' ', 6)
|
172
|
+
sa = l.split('-', 0)
|
173
|
+
|
174
|
+
if lib[5] =~ /vdso/
|
175
|
+
next
|
176
|
+
end
|
177
|
+
|
178
|
+
lib = lib[5].strip
|
179
|
+
lib.gsub!(/[\s\n]+/, "")
|
180
|
+
@shared_objects.store(sa[0], lib)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
return @shared_objects
|
184
|
+
end
|
185
|
+
|
186
|
+
## Search a specific page for a value
|
187
|
+
## Should be used by most of the search_* methods
|
188
|
+
def search_page(base, max, val)
|
189
|
+
loc = Array.new
|
190
|
+
|
191
|
+
while base.to_i < max.to_i
|
192
|
+
r = Ragweed::Wraptux::ptrace(Ragweed::Wraptux::Ptrace::PEEK_TEXT, @pid, base, 0)
|
193
|
+
if r == val
|
194
|
+
loc.push(base)
|
195
|
+
end
|
196
|
+
base += 1
|
197
|
+
end
|
198
|
+
|
199
|
+
loc
|
200
|
+
end
|
201
|
+
|
202
|
+
## Search the heap for a value
|
203
|
+
def search_heap(val)
|
204
|
+
loc = Array.new
|
205
|
+
File.read("/proc/#{pid}/maps").each_line do |l|
|
206
|
+
if l =~ /\[heap\]/
|
207
|
+
s,e = l.split('-')
|
208
|
+
e = e.split(' ').first
|
209
|
+
s = s.to_i(16)
|
210
|
+
e = e.to_i(16)
|
211
|
+
sz = e - s
|
212
|
+
max = s + sz
|
213
|
+
loc = search_page(s, max, val)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
loc
|
217
|
+
end
|
218
|
+
|
219
|
+
## Search all mapped regions for a value
|
220
|
+
def search_process(val)
|
221
|
+
loc = Array.new
|
222
|
+
self.mapped
|
223
|
+
@mapped_regions.each_pair do |k,v|
|
224
|
+
if k == 0 or v == 0
|
225
|
+
next
|
226
|
+
end
|
227
|
+
max = k+v
|
228
|
+
loc.concat(search_page(k, max, val))
|
229
|
+
end
|
230
|
+
loc
|
134
231
|
end
|
135
232
|
|
136
233
|
def continue
|
@@ -143,8 +240,8 @@ class Ragweed::Debuggertux
|
|
143
240
|
Ragweed::Wraptux::ptrace(Ragweed::Wraptux::Ptrace::DETACH, @pid, 0, 0)
|
144
241
|
end
|
145
242
|
|
146
|
-
def
|
147
|
-
|
243
|
+
def single_step
|
244
|
+
on_single_step
|
148
245
|
ret = Ragweed::Wraptux::ptrace(Ragweed::Wraptux::Ptrace::STEP, @pid, 1, 0)
|
149
246
|
end
|
150
247
|
|
@@ -156,39 +253,20 @@ class Ragweed::Debuggertux
|
|
156
253
|
if not callable and block_given?
|
157
254
|
callable = block
|
158
255
|
end
|
159
|
-
@breakpoints
|
256
|
+
@breakpoints.each_key { |k| if k == ip then return end }
|
257
|
+
bp = Breakpoint.new(ip, callable, @pid, name)
|
258
|
+
@breakpoints[ip] = bp
|
160
259
|
end
|
161
260
|
|
162
|
-
##
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
if not bpid
|
168
|
-
@breakpoints[ip].uninstall
|
169
|
-
@breakpoints[ip].delete ip
|
170
|
-
else
|
171
|
-
found = nil
|
172
|
-
@breakpoints[ip].each_with_index do |bp, i|
|
173
|
-
if bp.bpid == bpid
|
174
|
-
found = i
|
175
|
-
if bp.orig != Breakpoint::INT3
|
176
|
-
if @breakpoints[op][i+1]
|
177
|
-
@breakpoints[ip][i + 1].orig = bp.orig
|
178
|
-
else
|
179
|
-
bp.uninstall
|
180
|
-
end
|
181
|
-
end
|
182
|
-
end
|
183
|
-
end
|
184
|
-
raise "could not find bp ##{bpid} at ##{ip}" if not found
|
185
|
-
@breakpoints[ip].delete_at(found) if found
|
186
|
-
end
|
261
|
+
## Remove a breakpoint by ip
|
262
|
+
def breakpoint_clear(ip)
|
263
|
+
bp = @breakpoints[ip]
|
264
|
+
return nil if bp.nil?
|
265
|
+
bp.uninstall
|
187
266
|
end
|
188
267
|
|
189
|
-
##loop for wait()
|
190
|
-
##times: the number of wait calls to make
|
191
|
-
## if nil loop will continue indefinitely
|
268
|
+
## loop for wait()
|
269
|
+
## times: the number of wait calls to make
|
192
270
|
def loop(times=nil)
|
193
271
|
if times.kind_of? Numeric
|
194
272
|
times.times do
|
@@ -199,19 +277,28 @@ class Ragweed::Debuggertux
|
|
199
277
|
end
|
200
278
|
end
|
201
279
|
|
280
|
+
def wexitstatus(status)
|
281
|
+
(((status) & 0xff00) >> 8)
|
282
|
+
end
|
283
|
+
|
284
|
+
def wtermsig(status)
|
285
|
+
((status) & 0x7f)
|
286
|
+
end
|
287
|
+
|
202
288
|
## This wait must be smart, it has to wait for a signal
|
203
289
|
## when SIGTRAP is received we need to see if one of our
|
204
290
|
## breakpoints has fired. If it has then execute the block
|
205
291
|
## originally stored with it. If its a different signal,
|
206
292
|
## then process it accordingly and move on
|
207
293
|
def wait(opts = 0)
|
208
|
-
r = Ragweed::Wraptux::waitpid(@pid,opts)
|
209
|
-
|
210
|
-
|
211
|
-
|
294
|
+
r, status = Ragweed::Wraptux::waitpid(@pid, opts)
|
295
|
+
wstatus = wtermsig(status)
|
296
|
+
signal = wexitstatus(status)
|
297
|
+
event_code = (status >> 16)
|
212
298
|
found = false
|
213
|
-
|
214
|
-
|
299
|
+
|
300
|
+
if r[0] != -1 ## Check the ret
|
301
|
+
case ## FIXME - I need better logic (use Signal module)
|
215
302
|
when wstatus == 0 ##WIFEXITED
|
216
303
|
@exited = true
|
217
304
|
self.on_exit
|
@@ -225,119 +312,159 @@ class Ragweed::Debuggertux
|
|
225
312
|
when signal == Ragweed::Wraptux::Signal::SIGILL
|
226
313
|
self.on_illegalinst
|
227
314
|
when signal == Ragweed::Wraptux::Signal::SIGTRAP
|
228
|
-
|
315
|
+
self.on_sigtrap
|
229
316
|
r = self.get_registers
|
230
|
-
eip = r
|
317
|
+
eip = r.eip
|
231
318
|
eip -= 1
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
319
|
+
case
|
320
|
+
when @breakpoints.has_key?(eip)
|
321
|
+
found = true
|
322
|
+
self.on_breakpoint
|
323
|
+
self.continue
|
324
|
+
when event_code == Ragweed::Wraptux::Ptrace::EventCodes::FORK
|
325
|
+
p = FFI::MemoryPointer.new(:int, 1)
|
326
|
+
Ragweed::Wraptux::ptrace(Ragweed::Wraptux::Ptrace::GETEVENTMSG, @pid, 0, p.to_i)
|
327
|
+
## Fix up the PID in each breakpoint
|
328
|
+
if (1..65535) === p.get_int32(0) && @opts[:fork] == true
|
329
|
+
@breakpoints.each_pair do |k,v|
|
330
|
+
v.each do |b|
|
331
|
+
b.bppid = p[:pid]
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
@pid = p[:pid]
|
336
|
+
self.on_fork_child(@pid)
|
337
|
+
end
|
338
|
+
when event_code == Ragweed::Wraptux::Ptrace::EventCodes::EXEC
|
339
|
+
when event_code == Ragweed::Wraptux::Ptrace::EventCodes::CLONE
|
340
|
+
when event_code == Ragweed::Wraptux::Ptrace::EventCodes::VFORK
|
341
|
+
when event_code == Ragweed::Wraptux::Ptrace::EventCodes::EXIT
|
342
|
+
## Not done yet
|
343
|
+
else
|
344
|
+
self.continue
|
237
345
|
end
|
238
|
-
|
346
|
+
when signal == Ragweed::Wraptux::Signal::SIGCHLD
|
347
|
+
self.on_sigchild
|
348
|
+
when signal == Ragweed::Wraptux::Signal::SIGTERM
|
349
|
+
self.on_sigterm
|
239
350
|
when signal == Ragweed::Wraptux::Signal::SIGCONT
|
240
351
|
self.continue
|
241
352
|
when signal == Ragweed::Wraptux::Signal::SIGSTOP
|
353
|
+
self.on_sigstop
|
354
|
+
Ragweed::Wraptux::kill(@pid, Ragweed::Wraptux::Signal::SIGCONT)
|
242
355
|
self.continue
|
356
|
+
when signal == Ragweed::Wraptux::Signal::SIGWINCH
|
357
|
+
self.continue
|
243
358
|
else
|
244
359
|
raise "Add more signal handlers (##{signal})"
|
245
360
|
end
|
246
361
|
end
|
247
362
|
end
|
248
363
|
|
249
|
-
## Return an array of thread PIDs
|
250
364
|
def self.threads(pid)
|
251
|
-
|
365
|
+
begin
|
366
|
+
a = Dir.entries("/proc/#{pid}/task/")
|
367
|
+
rescue
|
368
|
+
puts "No such PID: #{pid}"
|
369
|
+
return
|
370
|
+
end
|
252
371
|
a.delete_if { |x| x == '.' }
|
253
372
|
a.delete_if { |x| x == '..' }
|
254
373
|
end
|
255
374
|
|
256
|
-
## Gets the registers for the given process
|
257
375
|
def get_registers
|
258
|
-
|
259
|
-
regs = Array.new(size)
|
260
|
-
regs = regs.to_ptr
|
261
|
-
regs.struct!('LLLLLLLLLLLLLLLLL', :ebx,:ecx,:edx,:esi,:edi,:ebp,:eax,:xds,:xes,:xfs,:xgs,:orig_eax,:eip,:xcs,:eflags,:esp,:xss)
|
376
|
+
regs = FFI::MemoryPointer.new(Ragweed::Wraptux::PTRegs, 1)
|
262
377
|
Ragweed::Wraptux::ptrace(Ragweed::Wraptux::Ptrace::GETREGS, @pid, 0, regs.to_i)
|
263
|
-
return regs
|
378
|
+
return Ragweed::Wraptux::PTRegs.new regs
|
264
379
|
end
|
265
380
|
|
266
|
-
|
267
|
-
|
268
|
-
Ragweed::Wraptux::ptrace(Ragweed::Wraptux::Ptrace::SETREGS, @pid, 0, r.to_i)
|
381
|
+
def set_registers(regs)
|
382
|
+
Ragweed::Wraptux::ptrace(Ragweed::Wraptux::Ptrace::SETREGS, @pid, 0, regs.to_ptr.address)
|
269
383
|
end
|
270
384
|
|
271
385
|
## Here we need to do something about the bp
|
272
|
-
## we just hit. We have a block to execute
|
386
|
+
## we just hit. We have a block to execute.
|
387
|
+
## Remember if you implement this on your own
|
388
|
+
## make sure to call super, and also realize
|
389
|
+
## EIP won't look correct until this runs
|
273
390
|
def on_breakpoint
|
274
|
-
r =
|
275
|
-
eip = r
|
391
|
+
r = get_registers
|
392
|
+
eip = r.eip
|
276
393
|
eip -= 1
|
277
394
|
|
278
395
|
## Call the block associated with the breakpoint
|
279
396
|
@breakpoints[eip].call(r, self)
|
280
397
|
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
398
|
+
## The block may have called breakpoint_clear
|
399
|
+
del = true if !@breakpoints[eip].installed?
|
400
|
+
|
401
|
+
## Uninstall and single step the bp
|
402
|
+
@breakpoints[eip].uninstall
|
403
|
+
r.eip = eip
|
404
|
+
set_registers(r)
|
405
|
+
single_step
|
406
|
+
|
407
|
+
## ptrace peektext returns -1 upon reinstallation of bp without calling
|
408
|
+
## waitpid() if that occurs the breakpoint cannot be reinstalled
|
409
|
+
Ragweed::Wraptux::waitpid(@pid, 0)
|
410
|
+
|
411
|
+
if del == true
|
412
|
+
## The breakpoint block may have called breakpoint_clear
|
413
|
+
@breakpoints.delete(eip)
|
414
|
+
else
|
415
|
+
@breakpoints[eip].install
|
290
416
|
end
|
291
|
-
|
417
|
+
end
|
292
418
|
|
293
|
-
def
|
294
|
-
regs =
|
295
|
-
puts "eip %08x" % regs
|
296
|
-
puts "
|
297
|
-
puts "edi %08x" % regs
|
298
|
-
puts "esp %08x" % regs
|
299
|
-
puts "eax %08x" % regs
|
300
|
-
puts "ebx %08x" % regs
|
301
|
-
puts "ecx %08x" % regs
|
302
|
-
puts "edx %08x" % regs
|
419
|
+
def print_registers
|
420
|
+
regs = get_registers
|
421
|
+
puts "eip %08x" % regs.eip
|
422
|
+
puts "esi %08x" % regs.esi
|
423
|
+
puts "edi %08x" % regs.edi
|
424
|
+
puts "esp %08x" % regs.esp
|
425
|
+
puts "eax %08x" % regs.eax
|
426
|
+
puts "ebx %08x" % regs.ebx
|
427
|
+
puts "ecx %08x" % regs.ecx
|
428
|
+
puts "edx %08x" % regs.edx
|
303
429
|
end
|
304
430
|
|
305
431
|
def on_exit
|
306
|
-
#puts "process exited"
|
307
432
|
end
|
308
433
|
|
309
434
|
def on_illegalinst
|
310
|
-
#puts "illegal instruction"
|
311
|
-
exit
|
312
435
|
end
|
313
436
|
|
314
437
|
def on_attach
|
315
|
-
#puts "attached to process"
|
316
438
|
end
|
317
439
|
|
318
440
|
def on_detach
|
319
|
-
|
441
|
+
end
|
442
|
+
|
443
|
+
def on_sigchild
|
444
|
+
end
|
445
|
+
|
446
|
+
def on_sigterm
|
447
|
+
end
|
448
|
+
|
449
|
+
def on_sigtrap
|
320
450
|
end
|
321
451
|
|
322
452
|
def on_continue
|
323
|
-
#puts "process continued"
|
324
453
|
end
|
325
454
|
|
326
|
-
def
|
327
|
-
#puts "process stopped"
|
455
|
+
def on_sigstop
|
328
456
|
end
|
329
457
|
|
330
458
|
def on_signal
|
331
|
-
#puts "process received signal"
|
332
459
|
end
|
333
460
|
|
334
|
-
def
|
335
|
-
|
461
|
+
def on_single_step
|
462
|
+
end
|
463
|
+
|
464
|
+
def on_fork_child(pid)
|
336
465
|
end
|
337
466
|
|
338
467
|
def on_segv
|
339
|
-
print_regs
|
340
|
-
exit
|
341
468
|
end
|
342
469
|
|
343
470
|
def default_opts(opts)
|
data/lib/ragweed/rasm.rb
CHANGED
@@ -5,7 +5,7 @@ module Ragweed; end
|
|
5
5
|
module Ragweed::Rasm
|
6
6
|
|
7
7
|
# :stopdoc:
|
8
|
-
VERSION =
|
8
|
+
VERSION = File.read(File.join(File.dirname(__FILE__),"..","..","VERSION")).strip
|
9
9
|
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
|
10
10
|
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
|
11
11
|
# :startdoc:
|