class Metasm::Gui::CoverageWidget

Attributes

dasm[RW]
pixel_h[RW]
pixel_w[RW]
sections[RW]

Public Instance Methods

click(x, y) click to toggle source
# File metasm/gui/dasm_coverage.rb, line 26
def click(x, y)
        x, y = x.to_i - 1, y.to_i
        @sections.zip(@section_x).each { |s, sx|
                if x >= sx[0] and x < sx[1]+@pixel_w
                        @curaddr = s[0] + (x-sx[0])/@pixel_w*@byte_per_col + (y/@pixel_h-@spacing)*@byte_per_col/@col_height
                        @slave.focus_addr(@curaddr) if @slave rescue @slave=nil
                        redraw
                        break
                end
        }
end
current_address() click to toggle source

returns the address of the data under the cursor

# File metasm/gui/dasm_coverage.rb, line 166
def current_address
        @curaddr
end
doubleclick(x, y) click to toggle source
# File metasm/gui/dasm_coverage.rb, line 38
def doubleclick(x, y)
        click(x, y)
        cw = @parent_widget.clone_window(@curaddr, :listing)
        @slave = cw.dasm_widget
        @slave.focus_changed_callback = lambda { redraw rescue @slave.focus_changed_callback = nil }
end
Also aliased as: rightclick
focus_addr(addr) click to toggle source

focus on addr returns true on success (address exists)

# File metasm/gui/dasm_coverage.rb, line 157
def focus_addr(addr)
        return if not addr = @parent_widget.normalize(addr) or not @dasm.get_section_at(addr)
        @curaddr = addr
        @slave.focus_addr(@curaddr) if @slave rescue @slave=nil
        gui_update
        true
end
get_cursor_pos() click to toggle source
# File metasm/gui/dasm_coverage.rb, line 145
def get_cursor_pos
        @curaddr
end
gui_update() click to toggle source
# File metasm/gui/dasm_coverage.rb, line 170
def gui_update
        # ary of section [addr, len, codespan]
        # codespan is an ary of [code_off_start, code_off_end] (sorted by off)
        @sections = @dasm.sections.map { |a, ed|
                a = Expression[a].reduce
                l = ed.length
                if a.kind_of? Integer
                        l += a % 32
                        a -= a % 32
                end
                acc = []
                # stuff with addr-section_addr is to handle non-numeric section addrs (eg elf ET_REL)
                @dasm.decoded.keys.map { |da| da-a rescue nil }.grep(Integer).grep(0..l).sort.each { |o|
                        next if not da = @dasm.di_at(a+o)
                        oe = o + da.bin_length
                        if acc[-1] and acc[-1][1] >= o
                                # handle di overlapping
                                acc[-1][1] = oe if acc[-1][1] < oe
                        else
                                acc << [o, oe]
                        end
                }
                [a, l, acc]
        }
        @sections = @sections.sort if @sections.all? { |a, l, s| a.kind_of? Integer }
        redraw
end
initialize_widget(dasm, parent_widget) click to toggle source

TODO wheel -> zoom, dragdrop -> scroll?(zoomed)

# File metasm/gui/dasm_coverage.rb, line 12
def initialize_widget(dasm, parent_widget)
        @dasm = dasm
        @parent_widget = parent_widget

        @curaddr = 0
        @pixel_w = @pixel_h = 2       # use a font ?
        @sections = []
        @section_x = []
        @slave = nil  # another dasmwidget whose curaddr is kept sync

        @default_color_association = ColorTheme.merge :caret => :yellow, :caret_col => :darkyellow,
                :background => :palegrey, :code => :red, :data => :blue
end
mouse_wheel(dir, x, y) click to toggle source
# File metasm/gui/dasm_coverage.rb, line 46
def mouse_wheel(dir, x, y)
        # TODO zoom ?
        case dir
        when :up
        when :down
        end
end
paint() click to toggle source
# File metasm/gui/dasm_coverage.rb, line 54
def paint
        @curaddr = @slave.curaddr if @slave and @slave.curaddr rescue @slave=nil

        @spacing = 4  # pixels left for borders / inter-section

        @col_height = height/@pixel_h - 2*@spacing    # pixels per column
        @col_height = 1 if @col_height < 1

        cols = width/@pixel_w - 2*@spacing
        cols -= (@sections.length-1) * (@spacing+1)   # space+1: last col of each section may be only 1byte long
        cols = 64 if cols < 64

        # find how much bytes we must stuff per pixel so that it fits in the window
        bytes = @sections.map { |a, l, seq| l }.inject(0) { |a, b| a+b }
        @byte_per_col = (bytes / cols + @col_height) / @col_height * @col_height
        @byte_per_col = @col_height if @byte_per_col < @col_height

        x = @spacing*@pixel_w
        ybase = @spacing*@pixel_h

        # draws a rectangle covering h1 to h2 in y, of width w
        # advances x as needed
        draw_rect = lambda { |h1, h2, rw|
                h2 += 1
                draw_rectangle(x, ybase+@pixel_h*h1, @pixel_w*rw, @pixel_h*(h2-h1))
                rw -= 1 if h2 != @col_height
                x += rw*@pixel_w
        }

        # draws rectangles to cover o1 to o2
        draw = lambda { |o1, o2|
                next if o1 > o2
                o1_ = o1

                o1 /= @byte_per_col / @col_height
                o2 /= @byte_per_col / @col_height

                o11 = o1 % @col_height
                o12 = o1 / @col_height
                o21 = o2 % @col_height
                o22 = o2 / @col_height

                p11 = (o1_ - 1) / (@byte_per_col / @col_height) % @col_height
                x -= @pixel_w if o11 == @col_height-1 and o11 == p11

                if o11 > 0
                        draw_rect[o11, (o12 == o22 ? o21 : @col_height-1), 1]
                        next if o12 == o22
                        o12 += 1
                end

                if o12 < o22
                        draw_rect[0, @col_height-1, o22-o12]
                end

                draw_rect[0, o21, 1]
        }

        @section_x = []
        @sections.each { |a, l, seq|
                curoff = 0
                @section_x << [x]
                seq += [[l, l-1]] if not seq[-1] or seq[-1][1] < l   # to draw last data
                seq.each { |o, oe|
                        draw_color :data
                        draw[curoff, o-1]
                        draw_color :code
                        draw[o, oe]
                        curoff = oe+1
                }
                @section_x.last << x
                x += @spacing*@pixel_w
        }

        @sections.zip(@section_x).each { |s, sx|
                next if @curaddr.kind_of? Integer and not s[0].kind_of? Integer
                next if @curaddr.kind_of? Expression and not s[0].kind_of? Expression
                co = @curaddr-s[0]
                if co >= 0 and co < s[1]
                        draw_color :caret_col
                        x = sx[0] + (co/@byte_per_col)*@pixel_w
                        draw_rect[-@spacing, -1, 1]
                        draw_rect[@col_height, @col_height+@spacing, 1]
                        draw_color :caret
                        y = (co*@col_height/@byte_per_col) % @col_height
                        y = (co % @byte_per_col) / (@byte_per_col/@col_height)
                        draw_rect[y, y, 1]
                end
        }
end
rightclick(x, y)
Alias for: doubleclick
set_cursor_pos(p) click to toggle source
# File metasm/gui/dasm_coverage.rb, line 149
def set_cursor_pos(p)
        @curaddr = p
        @slave.focus_addr(@curaddr) if @slave rescue @slave=nil
        redraw
end