class Metasm::Gui::DbgRegWidget

a widget that displays values of registers of a Debugger also controls the Debugger and commands slave windows (showing listing & memory)

Attributes

dbg[RW]

Public Instance Methods

click(ex, ey) click to toggle source
# 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
commit_writes() click to toggle source
# 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
doubleclick(x, y) click to toggle source
# File metasm/gui/debug.rb, line 287
def doubleclick(x, y)
        gui_update    # XXX
end
gui_update() click to toggle source
# 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
initialize_visible() click to toggle source
# File metasm/gui/debug.rb, line 268
def initialize_visible
        gui_update
end
initialize_widget(dbg, parent_widget) click to toggle source
# 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
keypress(key) click to toggle source

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
paint() click to toggle source
# 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
pre_dbg_run() click to toggle source
# File metasm/gui/debug.rb, line 446
def pre_dbg_run
        @reg_cache_old.replace @reg_cache if @reg_cache
end
rightclick(x, y) click to toggle source
# File metasm/gui/debug.rb, line 283
def rightclick(x, y)
        doubleclick(x, y)     # XXX
end
swapin_tid() click to toggle source
# 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
update_caret() click to toggle source

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