ragweed 0.2.3-java → 0.2.4-java

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -4,21 +4,20 @@
4
4
 
5
5
  == DESCRIPTION:
6
6
 
7
- * Ragweed is a set of scriptable debugging tools written mostly in native ruby.
7
+ * Ragweed is a set of scriptable debugging tools written in native ruby.
8
8
 
9
- * Where required the Ruby/DL and Win32API libraries are used to interface the machine
9
+ * Where required the FFI and Win32API libraries are used to interface the machine
10
10
  and OS native system calls.
11
11
 
12
+ * There are no third party dependencies
13
+
12
14
  == Supported Platforms
13
15
 
14
16
  Ragweed is supported and has been tested on the following platforms (32bit intel only):
15
17
 
16
- Windows 7
17
- Windows XP
18
- Linux Ubuntu 10.4
19
- Linux Ubuntu 9.10
20
- Mac OS X 10.6
21
- Mac OS X 10.5
18
+ Windows XP, 7
19
+ Linux Ubuntu 9.04 -> 11.04
20
+ Mac OS X 10.5, 10.6
22
21
 
23
22
  Ragweed works with Ruby 1.8.7, 1.9.1 and 1.9.2 and should work with any Ruby that includes FFI support on 32bit WinXP, Win7, Linux 2.6 and OSX 10.6.
24
23
  We are actively investigating 64 bit support for each platform. Unfortunately, this will require significant changes to Ragweed.
@@ -48,7 +47,8 @@ Please see the examples directory for more. There are hit tracers for each platf
48
47
  == INSTALL:
49
48
 
50
49
  sudo gem install ragweed
51
- # relax with a tasty beverage, you're done
50
+
51
+ # yep, thats it. you're done.
52
52
 
53
53
  == LICENSE:
54
54
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.3
1
+ 0.2.4
@@ -4,7 +4,8 @@
4
4
  # FILE is CSV file,address
5
5
  # PID is the proces id to attach to.
6
6
 
7
- require 'debuggerosx'
7
+ require 'rubygems'
8
+ require 'ragweed'
8
9
  require 'pp'
9
10
  require 'irb'
10
11
  include Ragweed
@@ -12,10 +13,18 @@ include Ragweed
12
13
  filename = ARGV[0]
13
14
  pid = ARGV[1].to_i
14
15
 
15
- raise "hittracerosx.rb FILE PID" if (ARGV.size < 2 or pid <= 0)
16
+ raise "hittracerx.rb FILE PID" if (ARGV.size < 2 or pid <= 0)
17
+
18
+ class HitTracer < Ragweed::Debuggerosx
19
+ attr_accessor :counts
20
+
21
+ def initialize(*args)
22
+ @counts = Hash.new(0)
23
+ super
24
+ end
16
25
 
17
- class Debuggerosx
18
26
  def on_exit
27
+ pp @counts
19
28
  exit(1)
20
29
  end
21
30
 
@@ -25,39 +34,51 @@ class Debuggerosx
25
34
  def on_segv(thread)
26
35
  pp self.get_registers(thread)
27
36
  pp self.threads
28
- self.threads.each {|thread| puts Wraposx::ThreadContext.get(thread).dump}
29
- self.threads.each {|thread| puts Wraposx::ThreadInfo.get(thread).dump}
37
+ self.threads.each {|thread| puts self.get_registers(thread).dump}
38
+ self.threads.each {|thread| puts Ragweed::Wraposx::thread_info(thread, Ragweed::Wraposx::ThreadInfo::BASIC_INFO).dump}
30
39
  throw(:break)
31
40
  end
32
41
 
33
42
  def on_bus(thread)
43
+ puts "BUS!"
34
44
  throw(:break)
35
45
  end
36
46
  end
37
47
 
38
- d = Debuggerosx.new(pid)
48
+ d = HitTracer.new(pid)
39
49
  d.attach
40
50
 
51
+ puts "attached"
52
+
41
53
  File.open(filename, "r") do |fd|
42
- lines = fd.readlines
43
- lines.map {|x| x.chomp}
44
- lines.each do |tl|
45
- fn, addr = tl.split(",", 2)
46
- d.breakpoint_set(addr.to_i(16), fn, (bpl = lambda do | t, r, s | puts "#{ s.breakpoints[r.eip].first.function } hit in thread #{ t }\n"; end))
54
+ fd.each_line do |tl|
55
+ fn, addr = tl.split(",", 2).map{|x| x.strip}
56
+ pp [fn, addr.to_i(16).to_s(16)]
57
+ d.breakpoint_set(addr.to_i(16), fn, (bpl = lambda do | tid, regs, slf |
58
+ puts "#{ slf.breakpoints[regs.eip].first.function } hit in thread #{ tid }\n"
59
+ d.counts[slf.breakpoints[regs.eip].first.function] += 1
60
+ end))
47
61
  end
48
62
  end
49
63
 
64
+ puts "breakpoints loaded"
65
+
50
66
  d.install_bps
67
+ puts "breakpoints installed"
51
68
  d.continue
52
- catch(:throw) { d.loop }
69
+ puts "continued"
70
+ catch(:throw) { d.loop(nil) }
71
+ puts 'thrown'
53
72
  pp d.wait 1
54
73
  pp d.threads
55
74
 
56
- d.threads.each do |t|
57
- r = Wraposx::ThreadContext.get(t)
58
- i = Wraposx::ThreadInfo.get(t)
75
+ d.threads.each do |tid|
76
+ r = d.get_registers(tid)
77
+ i = Wraposx::thread_info(tid, Wraposx::ThreadInfo::BASIC_INFO)
59
78
  pp r
60
79
  puts r.dump
61
80
  pp i
62
81
  puts i.dump
63
82
  end
83
+
84
+
@@ -12,14 +12,14 @@ require ::File.join(::File.dirname(__FILE__),'wrap32')
12
12
  class Ragweed::Debugger32
13
13
  include Ragweed
14
14
 
15
- ## This will preserve the last event seen, but as read only
16
- ## useful if you want to pass around the ragweed object after
17
- ## an event has occured (post-mortem crash analysis)
15
+ # This will preserve the last event seen, but as read only
16
+ # useful if you want to pass around the ragweed object after
17
+ # an event has occured (post-mortem crash analysis)
18
18
  attr_reader :event
19
19
 
20
- ## Breakpoint class. Handles the actual setting,
21
- ## removal and triggers for breakpoints.
22
- ## no user servicable parts.
20
+ # Breakpoint class. Handles the actual setting,
21
+ # removal and triggers for breakpoints.
22
+ # no user servicable parts.
23
23
  class Breakpoint
24
24
 
25
25
  INT3 = 0xCC
@@ -64,9 +64,9 @@ class Ragweed::Debugger32
64
64
  end
65
65
 
66
66
  def call(*args); @callable.call(*args); end
67
- end ## End Breakpoint class
67
+ end # End Breakpoint class
68
68
 
69
- ## Get a handle to the process so you can mess with it.
69
+ # Get a handle to the process so you can mess with it.
70
70
  def process; @p; end
71
71
 
72
72
  def self.find_by_regex(rx)
@@ -79,7 +79,7 @@ class Ragweed::Debugger32
79
79
  end
80
80
 
81
81
  def initialize(p)
82
- ## grab debug privilege at least once
82
+ # grab debug privilege at least once
83
83
  @@token ||= Ragweed::Wrap32::ProcessToken.new.grant('seDebugPrivilege')
84
84
 
85
85
  p = Process.new(p) if p.kind_of? Numeric
@@ -96,10 +96,10 @@ class Ragweed::Debugger32
96
96
  @ntdll_dbg_break_point = @p.get_proc_remote('ntdll!DbgBreakPoint')
97
97
  end
98
98
 
99
- ## single-step the thread (by TID). "callable" is something that honors
100
- ## .call, like a Proc. In a dubious design decision: the "handle" to the
101
- ## single stepper is the Proc object itself. See Debugger#on_breakpoint
102
- ## for an example of how to use this.
99
+ # single-step the thread (by TID). "callable" is something that honors
100
+ # .call, like a Proc. In a dubious design decision: the "handle" to the
101
+ # single stepper is the Proc object itself. See Debugger#on_breakpoint
102
+ # for an example of how to use this.
103
103
  def step(tid, callable)
104
104
  if @steppers.empty?
105
105
  Ragweed::Wrap32::open_thread(tid) do |h|
@@ -111,9 +111,9 @@ class Ragweed::Debugger32
111
111
  @steppers << callable
112
112
  end
113
113
 
114
- ## turn off single-stepping for one callable (you can have more than one
115
- ## at a time). In other words, when you pass a Proc to Debugger#step, save
116
- ## it somewhere, and later pass it to "unstep" to turn it off.
114
+ # turn off single-stepping for one callable (you can have more than one
115
+ # at a time). In other words, when you pass a Proc to Debugger#step, save
116
+ # it somewhere, and later pass it to "unstep" to turn it off.
117
117
  def unstep(tid, callable)
118
118
  @steppers = @steppers.reject {|x| x == callable}
119
119
  if @steppers.empty?
@@ -125,7 +125,7 @@ class Ragweed::Debugger32
125
125
  end
126
126
  end
127
127
 
128
- ## convenience: either from a TID or a BreakpointEvent, get the thread context.
128
+ # convenience: either from a TID or a BreakpointEvent, get the thread context.
129
129
  def context(tid_or_event)
130
130
  if not tid_or_event.kind_of? Numeric
131
131
  tid = tid_or_event.tid
@@ -135,16 +135,16 @@ class Ragweed::Debugger32
135
135
  Ragweed::Wrap32::open_thread(tid) { |h| Ragweed::Wrap32::get_thread_context(h) }
136
136
  end
137
137
 
138
- ## set a breakpoint given an address, which can also be a string in the form
139
- ## "module!function", as in, "user32!SendMessageW". Be aware that the symbol
140
- ## lookup takes place in an injected thread; it's safer to use literal addresses
141
- ## when possible.
138
+ # set a breakpoint given an address, which can also be a string in the form
139
+ # "module!function", as in, "user32!SendMessageW". Be aware that the symbol
140
+ # lookup takes place in an injected thread; it's safer to use literal addresses
141
+ # when possible.
142
142
  #
143
- ## to handle the breakpoint, pass a block to this method, which will be called
144
- ## when the breakpoint hits.
143
+ # to handle the breakpoint, pass a block to this method, which will be called
144
+ # when the breakpoint hits.
145
145
  #
146
- ## breakpoints are always re-set after firing. If you don't want them to be
147
- ## re-set, unset them manually.
146
+ # breakpoints are always re-set after firing. If you don't want them to be
147
+ # re-set, unset them manually.
148
148
  def breakpoint_set(ip, callable=nil, &block)
149
149
  if not callable and block_given?
150
150
  callable = block
@@ -152,7 +152,7 @@ class Ragweed::Debugger32
152
152
 
153
153
  def_status = false
154
154
 
155
- ## This is usually 'Module!Function' or 'Module!0x1234'
155
+ # This is usually 'Module!Function' or 'Module!0x1234'
156
156
  if @p.is_breakpoint_deferred(ip) == true
157
157
  def_status = true
158
158
  else
@@ -160,23 +160,23 @@ class Ragweed::Debugger32
160
160
  ip = @p.get_proc_remote(ip)
161
161
  end
162
162
 
163
- ## If we cant immediately set the breakpoint
164
- ## mark it as deferred and wait till later
165
- ## Sometimes *_proc_remote() will return the
166
- ## name indicating failure (just in case)
163
+ # If we cant immediately set the breakpoint
164
+ # mark it as deferred and wait till later
165
+ # Sometimes *_proc_remote() will return the
166
+ # name indicating failure (just in case)
167
167
  if ip == 0 or ip == 0xFFFFFFFF or ip.kind_of? String
168
168
  def_status = true
169
169
  else
170
170
  def_status = false
171
171
  end
172
172
 
173
- ## Dont want duplicate breakpoint objects
173
+ # Dont want duplicate breakpoint objects
174
174
  @breakpoints.each_key { |k| if k == ip then return end }
175
175
  bp = Breakpoint.new(@p, ip, def_status, callable)
176
176
  @breakpoints[ip] = bp
177
177
  end
178
178
 
179
- ## Clear a breakpoint by ip
179
+ # Clear a breakpoint by ip
180
180
  def breakpoint_clear(ip)
181
181
  bp = @breakpoints[ip]
182
182
 
@@ -188,8 +188,8 @@ class Ragweed::Debugger32
188
188
  @breakpoints.delete(ip)
189
189
  end
190
190
 
191
- ## handle a breakpoint event:
192
- ## call handlers for the breakpoint, step past and reset it.
191
+ # handle a breakpoint event:
192
+ # call handlers for the breakpoint, step past and reset it.
193
193
  def on_breakpoint(ev)
194
194
  ctx = context(ev)
195
195
  eip = ev.exception_address
@@ -200,34 +200,34 @@ class Ragweed::Debugger32
200
200
 
201
201
  @breakpoints[eip].uninstall
202
202
 
203
- ## Call the block passed to breakpoint_set
204
- ## which may have been passed through hook()
203
+ # Call the block passed to breakpoint_set
204
+ # which may have been passed through hook()
205
205
  @breakpoints[eip].call(ev, ctx)
206
206
 
207
- ## single step past the instruction...
207
+ # single step past the instruction...
208
208
  step(ev.tid, (onestep = lambda do |ev, ctx|
209
209
  if ev.exception_address != eip
210
- ## ... then re-install the breakpoint ...
210
+ # ... then re-install the breakpoint ...
211
211
  if not @breakpoints[eip].nil?
212
212
  @breakpoints[eip].install
213
213
  end
214
- ## ... and stop single-stepping.
214
+ # ... and stop single-stepping.
215
215
  unstep(ev.tid, onestep)
216
216
  end
217
217
  end))
218
218
 
219
- ## Put execution back where it's supposed to be...
219
+ # Put execution back where it's supposed to be...
220
220
  Ragweed::Wrap32::open_thread(ev.tid) do |h|
221
221
  ctx = context(ev)
222
222
  ctx.eip = eip ## eip was ev.exception_address
223
223
  Ragweed::Wrap32::set_thread_context(h, ctx)
224
224
  end
225
225
 
226
- ## Tell the target to stop handling this event
226
+ # Tell the target to stop handling this event
227
227
  @handled = Ragweed::Wrap32::ContinueCodes::CONTINUE
228
228
  end
229
229
 
230
- ## FIX: this method should be a bit more descriptive in its naming
230
+ # FIX: this method should be a bit more descriptive in its naming
231
231
  def get_dll_name(ev)
232
232
  name = Ragweed::Wrap32::get_mapped_filename(@p.handle, ev.base_of_dll, 256)
233
233
  name.gsub!(/[\n]+/,'')
@@ -264,7 +264,7 @@ class Ragweed::Debugger32
264
264
  end
265
265
  end
266
266
 
267
- ## handle a single-step event
267
+ # handle a single-step event
268
268
  def on_single_step(ev)
269
269
  ctx = context(ev)
270
270
  Ragweed::Wrap32::open_thread(ev.tid) do |h|
@@ -279,36 +279,54 @@ class Ragweed::Debugger32
279
279
  @handled = Ragweed::Wrap32::ContinueCodes::CONTINUE
280
280
  end
281
281
 
282
- ## This is sort of insane but most of my programs are just
283
- ## debug loops, so if you don't do this, they just hang when
284
- ## the target closes.
282
+ # This is sort of insane but most of my programs are just
283
+ # debug loops, so if you don't do this, they just hang when
284
+ # the target closes.
285
285
  def on_exit_process(ev)
286
286
  exit(1)
287
287
  end
288
288
 
289
- ## TODO: Implement each of these
289
+ # @abstract
290
290
  def on_create_process(ev) end
291
+ # @abstract
291
292
  def on_create_thread(ev) end
293
+ # @abstract
292
294
  def on_exit_thread(ev) end
295
+ # @abstract
293
296
  def on_output_debug_string(ev) end
297
+ # @abstract
294
298
  def on_rip(ev) end
299
+ # @abstract
295
300
  def on_unload_dll(ev) end
301
+ # @abstract
296
302
  def on_guard_page(ev) end
303
+ # @abstract
297
304
  def on_alignment(ev) end
305
+ # @abstract
298
306
  def on_bounds(ev) end
307
+ # @abstract
299
308
  def on_divide_by_zero(ev) end
309
+ # @abstract
300
310
  def on_int_overflow(ev) end
311
+ # @abstract
301
312
  def on_invalid_handle(ev) end
313
+ # @abstract
302
314
  def on_illegal_instruction(ev) end
315
+ # @abstract
303
316
  def on_priv_instruction(ev) end
317
+ # @abstract
304
318
  def on_stack_overflow(ev) end
319
+ # @abstract
305
320
  def on_heap_corruption(ev) end
321
+ # @abstract
306
322
  def on_buffer_overrun(ev) end
323
+ # @abstract
307
324
  def on_invalid_disposition(ev) end
325
+ # @abstract
308
326
  def on_attach() end
309
327
 
310
- ## Read through me to see all the random events
311
- ## you can hook in a subclass.
328
+ # Read through me to see all the random events
329
+ # you can hook in a subclass.
312
330
  def wait
313
331
  self.attach() if not @attached
314
332
 
@@ -370,15 +388,15 @@ class Ragweed::Debugger32
370
388
  @handled = Ragweed::Wrap32::ContinueCodes::UNHANDLED
371
389
  end
372
390
 
373
- ## Debug loop
391
+ # Debug loop
374
392
  def loop
375
393
  while true
376
394
  wait
377
395
  end
378
396
  end
379
397
 
380
- ## This is called implicitly by Debugger#wait.
381
- ## Attaches to the child process for debugging
398
+ # This is called implicitly by Debugger#wait.
399
+ # Attaches to the child process for debugging
382
400
  def attach
383
401
  Ragweed::Wrap32::debug_active_process(@p.pid)
384
402
  Ragweed::Wrap32::debug_set_process_kill_on_exit
@@ -389,7 +407,7 @@ class Ragweed::Debugger32
389
407
  end
390
408
  end
391
409
 
392
- ## Let go of the target.
410
+ # Let go of the target.
393
411
  def release
394
412
  Ragweed::Wrap32::debug_active_process_stop(@p.pid)
395
413
  @attached = false
@@ -21,7 +21,6 @@ class Ragweed::Debuggerosx
21
21
  attr_accessor :breakpoints
22
22
 
23
23
  class Breakpoint
24
- # include Ragweed::Wraposx
25
24
  INT3 = 0xCC
26
25
  attr_accessor :orig
27
26
  attr_accessor :bpid
@@ -70,14 +69,14 @@ class Ragweed::Debuggerosx
70
69
  def method_missing(meth, *args); @bp.send(meth, *args); end
71
70
  end
72
71
 
73
- #init object
74
- #p: pid of process to be debugged
75
- #opts: default options for automatically doing things (attach, install, and hook)
72
+ # init object
73
+ # p: pid of process to be debugged
74
+ # opts: default options for automatically doing things (attach, install, and hook)
76
75
  def initialize(p,opts={})
77
76
  if p.kind_of? Numeric
78
77
  @pid = p
79
78
  else
80
- #coming soon: find process by name
79
+ # coming soon: find process by name
81
80
  raise "Provide a PID"
82
81
  end
83
82
  @opts = opts
@@ -97,8 +96,11 @@ class Ragweed::Debuggerosx
97
96
  @opts.each {|k, v| try(k) if v}
98
97
  end
99
98
 
100
- #loop calls to wait
101
- #times: number of times to loop
99
+ # loop calls to wait.
100
+ # This is the main mode this class will be used at runtime.
101
+ # First, install the desired breakpoints. Then, run loop().
102
+ #
103
+ # times: number of times to loop
102
104
  # if nil this will loop until @exited is set
103
105
  def loop(times=nil)
104
106
  if times.kind_of? Numeric
@@ -111,6 +113,7 @@ class Ragweed::Debuggerosx
111
113
  end
112
114
 
113
115
  # wait for process and run callback on return then continue child
116
+ # This is usually called by loop()
114
117
  # FIXME - need to do signal handling better (loop through threads only for breakpoints and stepping)
115
118
  # opts: option flags to waitpid(2)
116
119
  #
@@ -165,27 +168,38 @@ class Ragweed::Debuggerosx
165
168
  end
166
169
 
167
170
  # these event functions are stubs. Implementations should override these
171
+
172
+ # Fired when attaching to the child process succeeds.
168
173
  def on_attach
169
174
  end
170
175
 
176
+ # Fired when detaching from the child process succeeds.
171
177
  def on_detach
172
178
  end
173
179
 
180
+ # Fired when single stepping at every step
181
+ # Not currently used in OSX
174
182
  def on_single_step
175
- #puts Ragweed::Wraposx::ThreadInfo.get(thread).inspect
176
183
  end
177
184
 
185
+ # Called with the child process's status on exit
186
+ # Implementations overriding this function should either set @exited to true or call super.
178
187
  def on_exit(status)
179
188
  @exited = true
180
189
  end
181
190
 
191
+ # Called with the signal used to exit kill the child process
192
+ # Implementations overriding this function should either set @exited to true or call super.
182
193
  def on_signal(signal)
183
194
  @exited = true
184
195
  end
185
196
 
197
+ # Called when the child process is stopped with the signal used.
186
198
  def on_stop(signal)
187
199
  end
188
200
 
201
+ # Called when the child process is continued.
202
+ # If used by an implementation, this will be a very noisy function.
189
203
  def on_continue
190
204
  end
191
205
 
@@ -235,16 +249,19 @@ class Ragweed::Debuggerosx
235
249
  # get task port for @pid and store in @task so mach calls can be made
236
250
  # opts is a hash for automatically firing other functions as an overide for @opts
237
251
  # returns the task port for @pid
252
+ # @deprecated - This function will change to attach_mach and instead become similar to the Debugger32#hook function used for tracing the entry and exit of functions in the child.
238
253
  def hook(opts=@opts)
239
254
  @task = Ragweed::Wraposx::task_for_pid(@pid)
240
255
  @hooked = true
241
256
  self.attach(opts) if opts[:attach] and not @attached
242
257
  return @task
243
258
  end
259
+ alias attach_mach hook
244
260
 
245
261
  # theoretically to close the task port but,
246
262
  # no way to close the port has yet been found.
247
263
  # This function currently does little/nothing.
264
+ # @deprecated - This will be removed at some point.
248
265
  def unhook(opts=@opts)
249
266
  self.detach(opts) if opts[:attach] and @attached
250
267
  self.unintsall_bps if opts[:install] and @installed
@@ -253,14 +270,14 @@ class Ragweed::Debuggerosx
253
270
  # resumes thread that has been suspended via thread_suspend
254
271
  # thread: thread id of thread to be resumed
255
272
  def resume(thread = nil)
256
- thread ||= self.threads.first)
273
+ thread ||= self.threads.first
257
274
  Ragweed::Wraposx::thread_resume(thread)
258
275
  end
259
276
 
260
- # suspends thread
261
- # thread: thread id of thread to be suspended
277
+ # suspends thread (increments the suspend count)
278
+ # thread: thread id of thread to be suspended defaults to first thread
262
279
  def suspend(thread = nil)
263
- thread ||= self.threads.first)
280
+ thread ||= self.threads.first
264
281
  Ragweed::Wraposx::thread_suspend(thread)
265
282
  end
266
283
 
@@ -310,24 +327,24 @@ class Ragweed::Debuggerosx
310
327
  # thread: id of the thread stopped at a breakpoint
311
328
  def on_breakpoint(thread)
312
329
  r = self.get_registers(thread)
313
- #rewind eip to correct position
330
+ # rewind eip to correct position
314
331
  r.eip -= 1
315
- #don't use r.eip since it may be changed by breakpoint callback
332
+ # don't use r.eip since it may be changed by breakpoint callback
316
333
  eip = r.eip
317
- #clear stuff set by INT3
318
- #r.esp -=4
319
- #r.ebp = r.esp
320
- #fire callback
334
+ # clear stuff set by INT3
335
+ # r.esp -=4
336
+ # r.ebp = r.esp
337
+ # fire callback
321
338
  @breakpoints[eip].call(thread, r, self)
322
339
  if @breakpoints[eip].first.installed?
323
- #uninstall breakpoint to continue past it
340
+ # uninstall breakpoint to continue past it
324
341
  @breakpoints[eip].first.uninstall
325
- #set trap flag so we don't go too far before reinserting breakpoint
342
+ # set trap flag so we don't go too far before reinserting breakpoint
326
343
  r.eflags |= Ragweed::Wraposx::EFlags::TRAP
327
- #set registers to commit eip and eflags changes
344
+ # set registers to commit eip and eflags changes
328
345
  self.set_registers(thread, r)
329
346
 
330
- #step once
347
+ # step once
331
348
  self.stepp
332
349
 
333
350
  # now we wait() to prevent a race condition that'll SIGBUS us
@@ -335,7 +352,7 @@ class Ragweed::Debuggerosx
335
352
  # instruction before the parent completes many
336
353
  Ragweed::Wraposx::waitpid(@pid,0)
337
354
 
338
- #reset breakpoint
355
+ # reset the breakpoint
339
356
  @breakpoints[eip].first.install
340
357
  end
341
358
  end
@@ -359,7 +376,7 @@ class Ragweed::Debuggerosx
359
376
  # returns a Ragweed::Wraposx::ThreadContext object containing the register states
360
377
  # thread: thread to get the register state of
361
378
  def get_registers(thread=nil)
362
- thread ||= self.threads.first)
379
+ thread ||= self.threads.first
363
380
  Ragweed::Wraposx.thread_get_state(thread, Ragweed::Wraposx::ThreadContext::X86_THREAD_STATE)
364
381
  end
365
382
 
@@ -400,6 +417,10 @@ class Ragweed::Debuggerosx
400
417
  def attached?; @attached; end
401
418
  def installed?; @installed; end
402
419
 
420
+ # returns information about a memory region
421
+ # addr: address contained in the memory region - usually the start address
422
+ # flavor: type of information to retrieve. May be specified as either symbol [:basic, :extended, :top] or by integer flavor id.
423
+ # Currently, only the basic flavor is supported by Apple.
403
424
  def region_info(addr, flavor = :basic)
404
425
  flav = case flavor
405
426
  when :basic
@@ -425,7 +446,9 @@ class Ragweed::Debuggerosx
425
446
  end
426
447
 
427
448
  # XXX watch this space for an object to hold this information
428
- # Return a range via mapping name
449
+ # Get memory ranges by mapping name
450
+ # name: name of memory range to search for
451
+ # exact: if true require an exact match, otherwise use regex
429
452
  def get_mapping_by_name name, exact = true
430
453
  ret = []
431
454
  IO.popen("vmmap -interleaved #{@pid}") do |pipe|