ragweed 0.1.7.3 → 0.2.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|