ragweed 0.2.0.pre2-java → 0.2.0.pre3-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/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0.pre2
1
+ 0.2.0.pre3
data/lib/ragweed.rb CHANGED
@@ -75,11 +75,11 @@ end # module Ragweed
75
75
  module Ragweed::FFIStructInclude
76
76
  if RUBY_VERSION < "1.9"
77
77
  def methods regular=true
78
- super + self.offsets.map{|x| x.first.to_s}
78
+ (super + self.members.map{|x| [x.to_s, x.to_s+"="]}).flatten
79
79
  end
80
80
  else
81
81
  def methods regular=true
82
- super + self.offsets.map{|x| x.first}
82
+ (super + self.members.map{|x| [x, (x.to_s+"=").intern]}).flatten
83
83
  end
84
84
  end
85
85
 
@@ -93,8 +93,8 @@ module Ragweed::FFIStructInclude
93
93
  end
94
94
 
95
95
  def respond_to? meth, include_priv=false
96
- mth = meth.to_s.gsub(/=$/,'')
97
- self.offsets.map{|x| x.first.to_s}.include? mth || super
96
+ # mth = meth.to_s.gsub(/=$/,'')
97
+ !((self.methods & [meth, meth.to_s]).empty?) || super
98
98
  end
99
99
  end
100
100
 
@@ -305,6 +305,7 @@ class Ragweed::Debugger32
305
305
  def on_heap_corruption(ev) end
306
306
  def on_buffer_overrun(ev) end
307
307
  def on_invalid_disposition(ev) end
308
+ def on_attach() end
308
309
 
309
310
  ## Read through me to see all the random events
310
311
  ## you can hook in a subclass.
@@ -382,6 +383,7 @@ class Ragweed::Debugger32
382
383
  Ragweed::Wrap32::debug_active_process(@p.pid)
383
384
  Ragweed::Wrap32::debug_set_process_kill_on_exit
384
385
  @attached = true
386
+ try(:on_attach)
385
387
  @breakpoints.each_pair do |k, bp|
386
388
  bp.install
387
389
  end
@@ -13,7 +13,7 @@ module Ragweed; end
13
13
  ## that Debuggertux already handles, call "super", too.
14
14
  class Ragweed::Debuggertux
15
15
  attr_reader :pid, :status, :exited, :signal
16
- attr_accessor :breakpoints, :mapped_regions
16
+ attr_accessor :breakpoints, :mapped_regions, :process
17
17
 
18
18
  ## Class to handle installing/uninstalling breakpoints
19
19
  class Breakpoint
@@ -78,6 +78,8 @@ class Ragweed::Debuggertux
78
78
  @mapped_regions = Hash.new
79
79
  @breakpoints = Hash.new
80
80
  @opts.each { |k, v| try(k) if v }
81
+
82
+ @process = Ragweed::Process.new(@pid)
81
83
  end
82
84
 
83
85
  def self.find_by_regex(rx)
@@ -462,6 +464,7 @@ class Ragweed::Debuggertux
462
464
  def print_registers
463
465
  regs = get_registers
464
466
  puts "eip %08x" % regs.eip
467
+ puts "ebp %08x" % regs.ebp
465
468
  puts "esi %08x" % regs.esi
466
469
  puts "edi %08x" % regs.edi
467
470
  puts "esp %08x" % regs.esp
@@ -13,6 +13,10 @@ module Ragweed::Wrap32
13
13
  UNLOAD_DLL = 7
14
14
  end
15
15
 
16
+ module PagePermissions
17
+ PAGE_EXECUTE_READWRITE = 0x40
18
+ end
19
+
16
20
  module ExceptionCodes
17
21
  ACCESS_VIOLATION = 0xC0000005
18
22
  GUARD_PAGE = 0x80000001
@@ -136,85 +140,154 @@ class Ragweed::Wrap32::DebugEventU < FFI::Union
136
140
  end
137
141
 
138
142
  class Ragweed::Wrap32::DebugEvent < FFI::Struct
139
- include Ragweed::FFIStructInclude
140
-
141
- layout :code, :ulong,
142
- :pid, :ulong,
143
- :tid, :ulong,
144
- :u, Ragweed::Wrap32::DebugEventU
145
-
146
- ## We have rubified this FFI structure by creating a bunch of instance
147
- ## variables that are normally only accessible via self.u.x.y which is
148
- ## a lot to type. You can still use that method however these instance
149
- ## variables should allow for considerably clearer code
150
- attr_accessor :base_of_dll, :base_of_image, :debug_info_file_offset, :debug_info_size, :exception_address, :exception_code,
151
- :exception_flags, :exception_record, :exit_code, :file_handle, :image_name, :number_of_parameters, :parameters,
152
- :process_handle, :rip_error, :rip_type, :start_address, :thread_local_base, :thread_handle, :thread_local_base,
153
- :unicode
154
-
155
- def initialize(buf)
156
- super buf
157
-
158
- case self.code
159
- when Ragweed::Wrap32::DebugCodes::CREATE_PROCESS
160
- @file_handle = self.u.create_process_debug_info.file_handle
161
- @process_handle = self.u.create_process_debug_info.process_handle
162
- @thread_handle = self.u.create_process_debug_info.thread_handle
163
- @base_of_image = self.u.create_process_debug_info.base_of_image
164
- @debug_info_file_offset = self.u.create_process_debug_info.debug_info_file_offset
165
- @debug_info_size = self.u.create_process_debug_info.debug_info_size
166
- @thread_local_base = self.u.create_process_debug_info.thread_local_base
167
- @start_address = self.u.create_process_debug_info.start_address
168
- @image_name = self.u.create_process_debug_info.image_name
169
- @unicode = self.u.create_process_debug_info.unicode
170
-
171
- when Ragweed::Wrap32::DebugCodes::CREATE_THREAD
172
- @thread_handle = self.u.create_thread_debug_info.thread_handle
173
- @thread_local_base = self.u.create_thread_debug_info.thread_local_base
174
- @start_address = self.u.create_thread_debug_info.start_address
175
-
176
- when Ragweed::Wrap32::DebugCodes::EXCEPTION
177
- @exception_code = self.u.exception_debug_info.exception_record.exception_code
178
- @exception_flags = self.u.exception_debug_info.exception_record.exception_flags
179
- @exception_record = self.u.exception_debug_info.exception_record.exception_record
180
- @exception_address = self.u.exception_debug_info.exception_record.exception_address
181
- @number_of_parameters = self.u.exception_debug_info.exception_record.number_of_parameters
182
-
183
- @parameters = []
184
-
185
- self.number_of_parameters.times do |i|
186
- @parameters << self.u.exception_debug_info.exception_record.exception_information[i]
143
+ include Ragweed::FFIStructInclude
144
+
145
+ layout :DebugEventCode, :ulong,
146
+ :ProcessId, :ulong,
147
+ :ThreadId, :ulong,
148
+ :u, Ragweed::Wrap32::DebugEventU
149
+
150
+ # backwards compatability
151
+ def code; self[:DebugEventCode]; end
152
+ def code=(cd); self[:DebugEventCode] = cd; end
153
+ def pid; self[:ProcessId]; end
154
+ def pid=(pd); self[:ProcessId]= pd; end
155
+ def tid; self[:ThreadId]; end
156
+ def tid=(td); self[:ThreadId] = td; end
157
+
158
+ # We have rubified this FFI structure by creating a bunch of proxy
159
+ # methods that are normally only accessible via self.u.x.y which is
160
+ # a lot to type. You can still use that method however these instance
161
+ # variables should allow for considerably clearer code
162
+ if RUBY_VERSION < "1.9"
163
+ def methods regular=true
164
+ ret = super + self.members.map{|x| [x.to_s, x.to_s + "="]}
165
+ ret += case self[:DebugEventCode]
166
+ when Ragweed::Wrap32::DebugCodes::CREATE_PROCESS
167
+ self[:u][:create_process_debug_info].members.map{|x| [x.to_s, x.to_s + "="]}
168
+ when Ragweed::Wrap32::DebugCodes::CREATE_THREAD
169
+ self[:u][:create_thread_debug_info].members.map{|x| [x.to_s, x.to_s + "="]}
170
+ when Ragweed::Wrap32::DebugCodes::EXIT_PROCESS
171
+ self[:u][:exit_process_debug_info].members.map{|x| [x.to_s, x.to_s + "="]}
172
+ when Ragweed::Wrap32::DebugCodes::EXIT_THREAD
173
+ self[:u][:exit_thread_debug_info].members.map{|x| [x.to_s, x.to_s + "="]}
174
+ when Ragweed::Wrap32::DebugCodes::LOAD_DLL
175
+ self[:u][:load_dll_debug_info].members.map{|x| [x.to_s, x.to_s + "="]}
176
+ when Ragweed::Wrap32::DebugCodes::OUTPUT_DEBUG_STRING
177
+ self[:u][:output_debug_string_info].members.map{|x| [x.to_s, x.to_s + "="]}
178
+ when Ragweed::Wrap32::DebugCodes::RIP
179
+ self[:u][:rip_info].members.map{|x| [x.to_s, x.to_s + "="]}
180
+ when Ragweed::Wrap32::DebugCodes::UNLOAD_DLL
181
+ self[:u][:unload_dll_debug_info].members.map{|x| [x.to_s, x.to_s + "="]}
182
+ when Ragweed::Wrap32::DebugCodes::EXCEPTION
183
+ self[:u][:exception_debug_info].members.map{|x| [x.to_s, x.to_s + "="]} + self[:u][:exception_debug_info][:exception_record].members.map{|x| [x.to_s, x.to_s + "="]}
184
+ else
185
+ []
187
186
  end
187
+ ret.flatten
188
+ end
189
+ else
190
+ def methods regular=true
191
+ ret = super + self.members.map{|x| [x, (x.to_s + "=").intern]}
192
+ ret += case self[:DebugEventCode]
193
+ when Ragweed::Wrap32::DebugCodes::CREATE_PROCESS
194
+ self[:u][:create_process_debug_info].members.map{|x| [x, (x.to_s + "=").intern]}
195
+ when Ragweed::Wrap32::DebugCodes::CREATE_THREAD
196
+ self[:u][:create_thread_debug_info].members.map{|x| [x, (x.to_s + "=").intern]}
197
+ when Ragweed::Wrap32::DebugCodes::EXIT_PROCESS
198
+ self[:u][:exit_process_debug_info].members.map{|x| [x, (x.to_s + "=").intern]}
199
+ when Ragweed::Wrap32::DebugCodes::EXIT_THREAD
200
+ self[:u][:exit_thread_debug_info].members.map{|x| [x, (x.to_s + "=").intern]}
201
+ when Ragweed::Wrap32::DebugCodes::LOAD_DLL
202
+ self[:u][:load_dll_debug_info].members.map{|x| [x, (x.to_s + "=").intern]}
203
+ when Ragweed::Wrap32::DebugCodes::OUTPUT_DEBUG_STRING
204
+ self[:u][:output_debug_string_info].members.map{|x| [x, (x.to_s + "=").intern]}
205
+ when Ragweed::Wrap32::DebugCodes::RIP
206
+ self[:u][:rip_info].members.map{|x| [x, (x.to_s + "=").intern]}
207
+ when Ragweed::Wrap32::DebugCodes::UNLOAD_DLL
208
+ self[:u][:unload_dll_debug_info].members.map{|x| [x, (x.to_s + "=").intern]}
209
+ when Ragweed::Wrap32::DebugCodes::EXCEPTION
210
+ self[:u][:exception_debug_info].members.map{|x| [x, (x.to_s + "=").intern]} + self[:u][:exception_debug_info][:exception_record].members.map{|x| [x, (x.to_s + "=").intern]}
211
+ else
212
+ []
213
+ end
214
+ ret.flatten
215
+ end
216
+ end
188
217
 
189
- when Ragweed::Wrap32::DebugCodes::EXIT_PROCESS
190
- @exit_code = self.u.exit_process_debug_info.exit_code
191
-
192
- when Ragweed::Wrap32::DebugCodes::EXIT_THREAD
193
- @exit_code = self.u.exit_thread_debug_info.exit_code
194
-
195
- when Ragweed::Wrap32::DebugCodes::LOAD_DLL
196
- @file_handle = self.u.load_dll_debug_info.file_handle
197
- @base_of_dll = self.u.load_dll_debug_info.base_of_dll
198
- @debug_info_file_offset = self.u.load_dll_debug_info.debug_info_file_offset
199
- @debug_info_size = self.u.load_dll_debug_info.debug_info_size
200
- @image_name = self.u.load_dll_debug_info.image_name
201
- @unicode = self.u.load_dll_debug_info.unicode
202
-
203
- when Ragweed::Wrap32::DebugCodes::OUTPUT_DEBUG_STRING
204
- ##
205
-
206
- when Ragweed::Wrap32::DebugCodes::RIP
207
- @rip_error = self.u.rip_info.rip_error
208
- @rip_type = self.u.rip_info.rip_type
209
-
210
- when Ragweed::Wrap32::DebugCodes::UNLOAD_DLL
211
- @base_of_dll = self.u.unload_dll_debug_info.base_of_dll
212
-
218
+ def method_missing meth, *args
219
+ super unless self.respond_to? meth
220
+ if meth.to_s =~ /=$/
221
+ mth = meth.to_s.gsub(/=$/,'').intern
222
+ if self.members.include? mth
223
+ # don't proxy
224
+ self.__send__(:[]=, mth, *args)
225
+ else
226
+ case self[:DebugEventCode]
227
+ when Ragweed::Wrap32::DebugCodes::CREATE_PROCESS
228
+ self[:u][:create_process_debug_info].__send__(:[]=, mth, *args)
229
+ when Ragweed::Wrap32::DebugCodes::CREATE_THREAD
230
+ self[:u][:create_thread_debug_info].__send__(:[]=, mth, *args)
231
+ when Ragweed::Wrap32::DebugCodes::EXIT_PROCESS
232
+ self[:u][:exit_process_debug_info].__send__(:[]=, mth, *args)
233
+ when Ragweed::Wrap32::DebugCodes::EXIT_THREAD
234
+ self[:u][:exit_thread_debug_info].__send__(:[]=, mth, *args)
235
+ when Ragweed::Wrap32::DebugCodes::LOAD_DLL
236
+ self[:u][:load_dll_debug_info].__send__(:[]=, mth, *args)
237
+ when Ragweed::Wrap32::DebugCodes::OUTPUT_DEBUG_STRING
238
+ self[:u][:output_debug_string_info].__send__(:[]=, mth, *args)
239
+ when Ragweed::Wrap32::DebugCodes::RIP
240
+ self[:u][:rip_info].__send__(:[]=, mth, *args)
241
+ when Ragweed::Wrap32::DebugCodes::UNLOAD_DLL
242
+ self[:u][:unload_dll_debug_info].__send__(:[]=, mth, *args)
243
+ when Ragweed::Wrap32::DebugCodes::EXCEPTION
244
+ case mth
245
+ when :exception_record, :first_chance
246
+ self[:u][:exception_debug_info].__send__(:[]=, mth, *args)
247
+ else # it's in the exception_record -- gross, I know but...
248
+ self[:u][:exception_debug_info][:exception_record].__send__(meth, *args)
249
+ end
250
+ end
251
+ end
213
252
  else
214
- raise WinX.new(:wait_for_debug_event)
253
+ if self.members.include? meth
254
+ # don't proxy
255
+ self.__send__(:[], meth, *args)
256
+ else
257
+ case self[:DebugEventCode]
258
+ when Ragweed::Wrap32::DebugCodes::CREATE_PROCESS
259
+ self[:u][:create_process_debug_info].__send__(:[], meth, *args)
260
+ when Ragweed::Wrap32::DebugCodes::CREATE_THREAD
261
+ self[:u][:create_thread_debug_info].__send__(:[], meth, *args)
262
+ when Ragweed::Wrap32::DebugCodes::EXIT_PROCESS
263
+ self[:u][:exit_process_debug_info].__send__(:[], meth, *args)
264
+ when Ragweed::Wrap32::DebugCodes::EXIT_THREAD
265
+ self[:u][:exit_thread_debug_info].__send__(:[], meth, *args)
266
+ when Ragweed::Wrap32::DebugCodes::LOAD_DLL
267
+ self[:u][:load_dll_debug_info].__send__(:[], meth, *args)
268
+ when Ragweed::Wrap32::DebugCodes::OUTPUT_DEBUG_STRING
269
+ self[:u][:output_debug_string_info].__send__(:[], meth, *args)
270
+ when Ragweed::Wrap32::DebugCodes::RIP
271
+ self[:u][:rip_info].__send__(:[], meth, *args)
272
+ when Ragweed::Wrap32::DebugCodes::UNLOAD_DLL
273
+ self[:u][:unload_dll_debug_info].__send__(:[], meth, *args)
274
+ when Ragweed::Wrap32::DebugCodes::EXCEPTION
275
+ case meth
276
+ when :exception_record, :first_chance
277
+ self[:u][:exception_debug_info].__send__(:[], meth, *args)
278
+ else # it's in the exception_record -- gross, I know but...
279
+ self[:u][:exception_debug_info][:exception_record].__send__(meth, *args)
280
+ end
281
+ end
282
+ end
215
283
  end
216
284
  end
217
285
 
286
+ def respond_to? meth, include_priv=false
287
+ # mth = meth.to_s.gsub(/=$/,'')
288
+ !((self.methods & [meth, meth.to_s]).empty?) || super
289
+ end
290
+
218
291
  def inspect_code(c)
219
292
  Ragweed::Wrap32::DebugCodes.to_key_hash[c].to_s || c.to_i
220
293
  end
@@ -25,7 +25,7 @@ class Ragweed::Debugger32
25
25
  ## get an idea of where the instruction
26
26
  ## is mapped.
27
27
  eip = ctx.eip
28
- if esp != 0 and esp > (eip & 0xf0000000)
28
+ if esp != 0 #and esp > (eip & 0xf0000000)
29
29
  breakpoint_set(esp) do |ev,ctx|
30
30
  callable.call(ev, ctx, :leave, args)
31
31
  breakpoint_clear(esp)
@@ -117,6 +117,8 @@ module Ragweed::Wrap32
117
117
  attach_function 'DeviceIoControl', [ :long, :long, :pointer, :long, :pointer, :long, :pointer, :pointer ], :long
118
118
  attach_function 'GetOverlappedResult', [ :long, :pointer, :pointer, :long ], :long
119
119
  attach_function 'WaitForMultipleObjects', [ :long, :pointer, :long, :long ], :long
120
+ attach_function 'CreateProcessA', [ :pointer, :pointer, :pointer, :pointer, :long, :long, :pointer, :pointer, :pointer, :pointer ], :long
121
+ attach_function 'CreateProcessW', [ :pointer, :pointer, :pointer, :pointer, :long, :long, :pointer, :pointer, :pointer, :pointer ], :long
120
122
 
121
123
  ffi_lib 'ntdll'
122
124
  ffi_convention :stdcall
@@ -255,6 +255,80 @@ EOM
255
255
  FLAVOR = 7
256
256
  layout :tsh, Ragweed::Wraposx::ThreadContext::X86StateHdr,
257
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
+
258
332
  end
259
333
 
260
334
  # _STRUCT_X86_DEBUG_STATE32
@@ -352,6 +426,79 @@ EOM
352
426
  FLAVOR = 12
353
427
  layout :dsh, Ragweed::Wraposx::ThreadContext::X86StateHdr,
354
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
355
502
  end
356
503
 
357
504
  # _STRUCT_X86_EXCEPTION_STATE32
@@ -419,6 +566,81 @@ EOM
419
566
  FLAVOR = 9
420
567
  layout :esh, Ragweed::Wraposx::ThreadContext::X86StateHdr,
421
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
+
422
644
  end
423
645
 
424
646
  # _STRUCT_X86_FLOAT_STATE32
@@ -49,7 +49,6 @@ module Ragweed::Wraptux
49
49
  ::File.join(::File.dirname(fname), dir, '**', '*.rb'))
50
50
  Dir.glob(search_me).sort.each {|rb| require rb }
51
51
  # require File.dirname(File.basename(__FILE__)) + "/#{x}"
52
-
53
52
  end
54
53
  end # module Ragweed::Wraptux
55
54
 
@@ -90,3 +90,9 @@ module Ragweed::Wraptux::Wait
90
90
  CONTINUED = 10
91
91
  NOWWAIT = 20
92
92
  end
93
+
94
+ module Ragweed::Wraptux::PagePermissions
95
+ PROT_READ = 0x1
96
+ PROT_WRITE = 0x2
97
+ PROT_EXEC = 0x4
98
+ end
@@ -0,0 +1,35 @@
1
+ class Ragweed::Process
2
+
3
+ include Ragweed
4
+ attr_reader :pid
5
+
6
+ def initialize(pid); @pid = pid; end
7
+
8
+ ## Read/write ranges of data or fixnums to/from the process by address.
9
+ def read(off, sz=4096)
10
+ a = []
11
+ while off < off+sz
12
+ a.push(Ragweed::Wraptux::ptrace(Ragweed::Wraptux::Ptrace::PEEK_TEXT, @pid, off, 0))
13
+ return a.pack('L*') if a.last == -1 and FFI.errno != 0
14
+ off+=4
15
+ end
16
+ a.pack('L*')
17
+ end
18
+
19
+ ## ptrace sucks, writing 8 or 16 bytes will probably
20
+ ## result in failure unless you PTRACE_POKE first and
21
+ ## get the rest of the original value at the address
22
+ def write(off, data)
23
+ while off < data.size
24
+ Ragweed::Wraptux::ptrace(Ragweed::Wraptux::Ptrace::POKE_TEXT, @pid, off, data[off,4].unpack('L').first)
25
+ off += 4
26
+ end
27
+ end
28
+
29
+ def read32(off); read(off, 4).unpack("L").first; end
30
+ def read16(off); read(off, 2).unpack("v").first; end
31
+ def read8(off); read(off, 1)[0]; end
32
+ def write32(off, v); write(off, [v].pack("L")); end
33
+ def write16(off, v); write(off, [v].pack("v")); end
34
+ def write8(off, v); write(off, v.chr); end
35
+ end
@@ -48,7 +48,7 @@ module Ragweed::Wraptux
48
48
  p = FFI::MemoryPointer.new(:int, 1)
49
49
  FFI.errno = 0
50
50
  r = Libc.waitpid(pid,p,opts)
51
- raise SystemCallErro.new "waitpid", FFI.errno if r == -1
51
+ raise SystemCallError.new "waitpid", FFI.errno if r == -1
52
52
  status = p.get_int32(0)
53
53
  [r, status]
54
54
  end
data/ragweed.gemspec CHANGED
@@ -5,12 +5,12 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ragweed}
8
- s.version = "0.2.0.pre2"
8
+ s.version = "0.2.0.pre3"
9
9
  s.platform = %q{java}
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
12
12
  s.authors = ["tduehr", "struct", "tqbf"]
13
- s.date = %q{2011-02-14}
13
+ s.date = %q{2011-03-09}
14
14
  s.description = %q{General debugging tool written in Ruby for OSX/Win32/Linux}
15
15
  s.email = %q{td@matasano.com}
16
16
  s.extra_rdoc_files = [
@@ -65,7 +65,7 @@ Gem::Specification.new do |s|
65
65
  "lib/ragweed/wraposx/wraposx.rb",
66
66
  "lib/ragweed/wraptux.rb",
67
67
  "lib/ragweed/wraptux/constants.rb",
68
- "lib/ragweed/wraptux/struct_helpers.rb",
68
+ "lib/ragweed/wraptux/process.rb",
69
69
  "lib/ragweed/wraptux/threads.rb",
70
70
  "lib/ragweed/wraptux/wraptux.rb",
71
71
  "ragweed.gemspec",
metadata CHANGED
@@ -6,8 +6,8 @@ version: !ruby/object:Gem::Version
6
6
  - 0
7
7
  - 2
8
8
  - 0
9
- - pre2
10
- version: 0.2.0.pre2
9
+ - pre3
10
+ version: 0.2.0.pre3
11
11
  platform: java
12
12
  authors:
13
13
  - tduehr
@@ -17,7 +17,7 @@ autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
19
 
20
- date: 2011-02-14 00:00:00 -06:00
20
+ date: 2011-03-09 00:00:00 -06:00
21
21
  default_executable:
22
22
  dependencies: []
23
23
 
@@ -78,7 +78,7 @@ files:
78
78
  - lib/ragweed/wraposx/wraposx.rb
79
79
  - lib/ragweed/wraptux.rb
80
80
  - lib/ragweed/wraptux/constants.rb
81
- - lib/ragweed/wraptux/struct_helpers.rb
81
+ - lib/ragweed/wraptux/process.rb
82
82
  - lib/ragweed/wraptux/threads.rb
83
83
  - lib/ragweed/wraptux/wraptux.rb
84
84
  - ragweed.gemspec
@@ -1,25 +0,0 @@
1
- module Ragweed::FFIStructInclude
2
- if RUBY_VERSION < "1.9"
3
- def methods regular=true
4
- super + self.offsets.map{|x| x.first.to_s}
5
- end
6
- else
7
- def methods regular=true
8
- super + self.offsets.map{|x| x.first}
9
- end
10
- end
11
-
12
- def method_missing meth, *args
13
- super unless self.respond_to? meth
14
- if meth.to_s =~ /=$/
15
- self.__send__(:[]=, meth.to_s.gsub(/=$/,'').intern, *args)
16
- else
17
- self.__send__(:[], meth, *args)
18
- end
19
- end
20
-
21
- def respond_to? meth, include_priv=false
22
- mth = meth.to_s.gsub(/=$/,'')
23
- self.offsets.map{|x| x.first.to_s}.include? mth || super
24
- end
25
- end