class Metasm::Gui::DbgWidget
TODO invalidate dbg.disassembler on selfmodifying code
Attributes
code[RW]
console[RW]
dbg[RW]
keyboard_callback[RW]
keyboard_callback_ctrl[RW]
mem[RW]
parent_widget[RW]
regs[RW]
watchpoint[RW]
win[RW]
Public Instance Methods
dbg_continue(*a)
click to toggle source
# File metasm/gui/debug.rb, line 140 def dbg_continue(*a) wrap_run { @dbg.continue(*a) } end
dbg_singlestep(*a)
click to toggle source
# File metasm/gui/debug.rb, line 141 def dbg_singlestep(*a) wrap_run { @dbg.singlestep(*a) } end
dbg_stepout(*a)
click to toggle source
# File metasm/gui/debug.rb, line 143 def dbg_stepout(*a) wrap_run { @dbg.stepout(*a) } end
dbg_stepover(*a)
click to toggle source
# File metasm/gui/debug.rb, line 142 def dbg_stepover(*a) wrap_run { @dbg.stepover(*a) } end
dragdropfile(f)
click to toggle source
# File metasm/gui/debug.rb, line 207 def dragdropfile(f) case f when /\.(c|h|cpp)$/; @dbg.disassembler.parse_c_file(f) when /\.map$/; @dbg.load_map(f) when /\.rb$/; @dbg.load_plugin(f) ; @console.add_log "loaded plugin #{File.basename(f, '.rb')}" else messagebox("unsupported file extension #{f}") end end
gui_update()
click to toggle source
# File metasm/gui/debug.rb, line 152 def gui_update @console.redraw @children.each { |c| c.gui_update } end
initialize_widget(dbg)
click to toggle source
# File metasm/gui/debug.rb, line 16 def initialize_widget(dbg) @dbg = dbg @keyboard_callback = {} @keyboard_callback_ctrl = {} @parent_widget = nil @regs = DbgRegWidget.new(dbg, self) @mem = DisasmWidget.new(dbg.disassembler) @code = DisasmWidget.new(dbg.disassembler) # after mem so that dasm.gui == @code @console = DbgConsoleWidget.new(dbg, self) @code.parent_widget = self @mem.parent_widget = self @dbg.disassembler.disassemble_fast(@dbg.pc) oldcb = @code.bg_color_callback @code.bg_color_callback = lambda { |a| if a == @dbg.pc :red_bg # TODO breakpoints & stuff elsif oldcb; oldcb[a] end } # TODO popup menu, set bp, goto here, show arg in memdump.. @children = [@code, @mem, @regs] add @regs, 'expand' => false # XXX add @mem add @code add @console @watchpoint = { @code => @dbg.register_pc } pc = @dbg.resolve_expr(@watchpoint[@code]) graph = :graph if @dbg.disassembler.function_blocks(pc).to_a.length < 100 @code.focus_addr(pc, graph, true) @mem.focus_addr(0, :hex, true) end
keypress(key)
click to toggle source
# File metasm/gui/debug.rb, line 73 def keypress(key) return true if @keyboard_callback[key] and @keyboard_callback[key][key] case key when :f5; protect { dbg_continue } when :f10; protect { dbg_stepover } when :f11; protect { dbg_singlestep } when :f12; protect { dbg_stepout } when ?.; @console.grab_focus else return @parent_widget ? @parent_widget.keypress(key) : false end true end
keypress_ctrl(key)
click to toggle source
# File metasm/gui/debug.rb, line 86 def keypress_ctrl(key) return true if @keyboard_callback_ctrl[key] and @keyboard_callback_ctrl[key][key] case key when :f5; protect { @dbg.pass_current_exception ; dbg.continue } else return @parent_widget ? @parent_widget.keypress_ctrl(key) : false end true end
post_dbg_run()
click to toggle source
TODO check_target always, incl when :stopped
# File metasm/gui/debug.rb, line 100 def post_dbg_run # focus currently stopped threads if @dbg.state == :running and tt = @dbg.tid_stuff.find { |tid, tstuff| tstuff[:state] != :running } @dbg.tid = tt[0] end want_redraw = true return if @idle_checking ||= nil # load only one bg proc @idle_checking = true Gui.idle_add { protect { @dbg.check_target if @dbg.state == :running redraw if want_redraw # redraw once if the target is running (less flicker with singlestep) want_redraw = false sleep 0.01 next true end @idle_checking = false @dbg.dasm_invalidate @mem.gui_update @dbg.disassembler.sections.clear if @dbg.state == :dead @dbg.disassembler.disassemble_fast(@dbg.pc) @children.each { |c| if wp = @watchpoint[c] c.focus_addr @dbg.resolve_expr(wp), nil, true end } redraw false } } end
pre_dbg_run()
click to toggle source
# File metasm/gui/debug.rb, line 95 def pre_dbg_run @regs.pre_dbg_run end
prompt_attach(caption='chose target')
click to toggle source
# File metasm/gui/debug.rb, line 157 def prompt_attach(caption='chose target') l = nil i = inputbox(caption) { |name| i = nil ; l.destroy if l and not l.destroyed? @dbg.attach(name) } # build process list in bg (exe name resolution takes a few seconds) list = [['pid', 'name']] list_pr = OS.current.list_processes Gui.idle_add { if pr = list_pr.shift list << [pr.pid, pr.path] if pr.path true elsif i me = ::Process.pid.to_s l = listwindow('running processes', list, :noshow => true, :color_callback => lambda { |le| [:grey, :palegrey] if le[0] == me } ) { |e| i.text = e[0] i.keypress(:enter) if l.destroyed? } l.x += l.width l.show false end } if not list_pr.empty? end
prompt_createprocess(caption='chose path')
click to toggle source
# File metasm/gui/debug.rb, line 187 def prompt_createprocess(caption='chose path') openfile(caption) { |path| path = '"' + path + '"' if @dbg.shortname == 'windbg' and path =~ /\s/ inputbox('target args?', :text => path) { |pa| @dbg.create_process(pa) } } end
prompt_datawatch()
click to toggle source
# File metasm/gui/debug.rb, line 196 def prompt_datawatch inputbox('data watch', :text => @watchpoint[@mem].to_s) { |e| case e when '', 'nil', 'none', 'delete' @watchpoint.delete @mem else @watchpoint[@mem] = @console.parse_expr(e) end } end
redraw()
click to toggle source
Calls superclass method
# File metasm/gui/debug.rb, line 145 def redraw super @console.redraw @regs.gui_update @children.each { |c| c.redraw } end
swapin_pid()
click to toggle source
# File metasm/gui/debug.rb, line 66 def swapin_pid @mem.dasm = @dbg.disassembler @code.dasm = @dbg.disassembler swapin_tid gui_update end
swapin_tid()
click to toggle source
# File metasm/gui/debug.rb, line 55 def swapin_tid @regs.swapin_tid @dbg.disassembler.disassemble_fast(@dbg.pc) @children.each { |c| if wp = @watchpoint[c] c.focus_addr @dbg.resolve_expr(wp), nil, true end } redraw end
wrap_run() { || ... }
click to toggle source
# File metasm/gui/debug.rb, line 134 def wrap_run pre_dbg_run yield post_dbg_run end