a widget that displays values of registers of a Debugger also controls the Debugger and commands slave windows (showing listing & memory)
# File metasm/gui/debug.rb, line 272 def click(ex, ey) if p = @reg_pos.find { |x, y, w, h, vx| x <= ex and x+w >= ex and y <= ey and y+h >= ey } @caret_reg = @reg_pos.index(p) @caret_x = ((ex - p[4]) / @font_width).to_i rs = @register_size[@registers[@caret_reg]] @caret_x = rs-1 if @caret_x > rs-1 @caret_x = 0 if @caret_x < 0 update_caret end end
# File metasm/gui/debug.rb, line 450 def commit_writes @write_pending.each { |k, v| if @registers.index(k) @dbg.set_reg_value(k, v) else @dbg.set_flag_value(k, v) end @reg_cache[k] = v } @write_pending.clear end
# File metasm/gui/debug.rb, line 287 def doubleclick(x, y) gui_update # XXX end
# File metasm/gui/debug.rb, line 462 def gui_update @reg_cache.replace @registers.inject({}) { |h, r| h.update r => @dbg.get_reg_value(r) } @flags.each { |f| @reg_cache[f] = @dbg.get_flag_value(f) } redraw end
# File metasm/gui/debug.rb, line 268 def initialize_visible gui_update end
# File metasm/gui/debug.rb, line 241 def initialize_widget(dbg, parent_widget) @dbg = dbg @parent_widget = parent_widget @caret_x = @caret_reg = 0 @oldcaret_x = @oldcaret_reg = 42 @tid_stuff = {} swapin_tid @reg_pos = [] # list of x y w h vx of the reg drawing on widget, vx is x of value @default_color_association = ColorTheme.merge :label => :text, :data => :blue, :write_pending => :darkred, :changed => :green, :caret => :text, :inactive => :palegrey end
keyboard binding basic navigation (arrows, pgup etc)
# File metasm/gui/debug.rb, line 348 def keypress(key) case key when :left if @caret_x > 0 @caret_x -= 1 update_caret end when :right if @caret_x < @register_size[@registers[@caret_reg]]-1 @caret_x += 1 update_caret end when :up if @caret_reg > 0 @caret_reg -= 1 else @caret_reg = @registers.length+@flags.length-1 end @caret_x = 0 update_caret when :down if @caret_reg < @registers.length+@flags.length-1 @caret_reg += 1 else @caret_reg = 0 end @caret_x = 0 update_caret when :home @caret_x = 0 update_caret when :end @caret_x = @register_size[@registers[@caret_reg]]-1 update_caret when :tab if @caret_reg < @registers.length+@flags.length-1 @caret_reg += 1 else @caret_reg = 0 end @caret_x = 0 update_caret when :backspace # TODO when :enter commit_writes redraw when :esc @write_pending.clear redraw when \x20..\x7e if a.kind_of?(String) v = key.ord case key when \x20; v = nil # keep current value when 0..9; v -= 0.ord when a..f; v -= a.ord-10 when A..F; v -= A.ord-10 else return false end else case v = key when \x20; v = nil when 0..9; v -= 0 when a..f; v -= a - 10 when A..F; v -= A - 10 else return false end end reg = @registers[@caret_reg] || @flags[@caret_reg-@registers.length] rsz = @register_size[reg] if v and rsz != 1 oo = 4*(rsz-@caret_x-1) ov = @write_pending[reg] || @reg_cache[reg] ov &= ~(0xf << oo) ov |= v << oo @write_pending[reg] = ov elsif v and (v == 0 or v == 1) # TODO change z flag by typing 'z' or 'Z' @write_pending[reg] = v rsz = 1 end if rsz == 1 @caret_reg += 1 @caret_reg = @registers.length if @caret_reg >= @registers.length + @flags.length elsif @caret_x < rsz-1 @caret_x += 1 else @caret_x = 0 end redraw else return false end true end
# File metasm/gui/debug.rb, line 291 def paint x = 1 y = 0 w_w = width render = lambda { |str, color| draw_string_color(color, x, y, str) x += str.length * @font_width } @reg_pos = [] running = (@dbg.state != :stopped) regstrlen = @registers.map { |reg| reg.to_s.length + 1 }.max @registers.each { |reg| strlen = regstrlen + @register_size[reg] if x + strlen*@font_width >= w_w x = 1 y += @font_height end @reg_pos << [x, y, (strlen+1)*@font_width, @font_height, x+regstrlen*@font_width] render["#{reg}=".ljust(regstrlen), :label] v = @write_pending[reg] || @reg_cache[reg] col = running ? :inactive : @write_pending[reg] ? :write_pending : @reg_cache_old.fetch(reg, v) != v ? :changed : :data render["%0#{@register_size[reg]}x " % v, col] x += @font_width # space } @flags.each { |reg| if x + @font_width >= w_w # XXX nowrap flags ? x = 1 y += @font_height end @reg_pos << [x, y, @font_width, @font_height, x] v = @write_pending[reg] || @reg_cache[reg] col = running ? :inactive : @write_pending[reg] ? :write_pending : @reg_cache_old.fetch(reg, v) != v ? :changed : :data v = v == 0 ? reg.to_s.downcase : reg.to_s.upcase render[v, col] x += @font_width # space } if focus? # draw caret cx = @reg_pos[@caret_reg][4] + @caret_x*@font_width cy = @reg_pos[@caret_reg][1] draw_line_color(:caret, cx, cy, cx, cy+@font_height-1) end @oldcaret_x, @oldcaret_reg = @caret_x, @caret_reg @parent_widget.resize_child(self, width, y+@font_height) end
# File metasm/gui/debug.rb, line 446 def pre_dbg_run @reg_cache_old.replace @reg_cache if @reg_cache end
# File metasm/gui/debug.rb, line 283 def rightclick(x, y) doubleclick(x, y) # XXX end
# File metasm/gui/debug.rb, line 257 def swapin_tid stf = @tid_stuff[[@dbg.pid, @dbg.tid]] ||= {} return if not @dbg.cpu @write_pending = stf[:write_pending] ||= {} # addr -> newvalue (bytewise) @registers = stf[:registers] ||= @dbg.register_list @flags = stf[:flags] ||= @dbg.flag_list @register_size = stf[:reg_sz] ||= @registers.inject(Hash.new(1)) { |h, r| h.update r => @dbg.register_size[r]/4 } @reg_cache = stf[:reg_cache] ||= Hash.new(0) @reg_cache_old = stf[:reg_cache_old] ||= {} end
hint that the caret moved
# File metasm/gui/debug.rb, line 469 def update_caret return if @oldcaret_x == @caret_x and @oldcaret_reg == @caret_reg invalidate_caret(@oldcaret_x, 0, *@reg_pos[@oldcaret_reg].values_at(4, 1)) invalidate_caret(@caret_x, 0, *@reg_pos[@caret_reg].values_at(4, 1)) @oldcaret_x, @oldcaret_reg = @caret_x, @caret_reg end