2014-02-19 19:13:08 +00:00
|
|
|
# This file is part of Metasm, the Ruby assembly manipulation suite
|
|
|
|
# Copyright (C) 2006-2009 Yoann GUILLOT
|
|
|
|
#
|
|
|
|
# Licence is LGPL, see LICENCE in the top-level directory
|
|
|
|
|
|
|
|
|
|
|
|
# metasm dasm plugin: create a function to export the currently displayed
|
|
|
|
# dasm graph to a .svg file
|
|
|
|
# in the gui, type E to export. Tested only for graph-style view, *may* work in other cases
|
|
|
|
|
|
|
|
raise 'gui only' if not gui
|
|
|
|
|
|
|
|
def graph_to_svg
|
2014-02-19 20:01:20 +00:00
|
|
|
gw = gui.curview.dup
|
|
|
|
class << gw
|
|
|
|
attr_accessor :svgbuf, :svgcol
|
|
|
|
def draw_color(col)
|
|
|
|
col = @default_color_association.fetch(col, col)
|
|
|
|
col = BasicColor.fetch(col, col)
|
|
|
|
@svgcol = "##{col}"
|
|
|
|
end
|
2014-02-19 19:13:08 +00:00
|
|
|
|
2014-02-19 20:01:20 +00:00
|
|
|
def draw_line(x1, y1, x2, y2)
|
|
|
|
bb(x1, y1, x2, y2)
|
|
|
|
svgbuf << %Q{<line x1="#{x1}" y1="#{y1}" x2="#{x2}" y2="#{y2}" stroke="#{@svgcol}" />\n}
|
|
|
|
end
|
|
|
|
def draw_rectangle(x, y, w, h)
|
|
|
|
bb(x, y, x+w, y+h)
|
|
|
|
svgbuf << %Q{<rect x="#{x}" y="#{y}" width="#{w}" height="#{h}" fill="#{@svgcol}" />\n}
|
|
|
|
end
|
|
|
|
def draw_string(x, y, str)
|
|
|
|
bb(x, y, x+str.length*@font_width, y+@font_height)
|
|
|
|
stre = str.gsub('<', '<').gsub('>', '>')
|
|
|
|
svgbuf << %Q{<text x="#{(0...str.length).map { |i| x+i*@font_width }.join(',')}" y="#{y+@font_height*0.7}" stroke="#{@svgcol}">#{stre}</text>\n}
|
|
|
|
end
|
2014-02-19 19:13:08 +00:00
|
|
|
|
2014-02-19 20:01:20 +00:00
|
|
|
def draw_rectangle_color(c, *a)
|
|
|
|
draw_color(c)
|
|
|
|
draw_rectangle(*a)
|
|
|
|
end
|
|
|
|
def draw_line_color(c, *a)
|
|
|
|
draw_color(c)
|
|
|
|
draw_line(*a)
|
|
|
|
end
|
|
|
|
def draw_string_color(c, *a)
|
|
|
|
draw_color(c)
|
|
|
|
draw_string(*a)
|
|
|
|
end
|
2014-02-19 19:13:08 +00:00
|
|
|
|
2014-02-19 20:01:20 +00:00
|
|
|
def focus?; false; end
|
|
|
|
def view_x; @svgvx ||= @curcontext.boundingbox[0]-20; end
|
|
|
|
def view_y; @svgvy ||= @curcontext.boundingbox[1]-20; end
|
|
|
|
def width; @svgvw ||= (@curcontext ? (@curcontext.boundingbox[2]-@curcontext.boundingbox[0])*@zoom+20 : 800); end
|
|
|
|
def height; @svgvh ||= (@curcontext ? (@curcontext.boundingbox[3]-@curcontext.boundingbox[1])*@zoom+20 : 600); end
|
|
|
|
def svgcuraddr; @curcontext ? @curcontext.root_addrs.first : current_address; end
|
2014-02-19 19:13:08 +00:00
|
|
|
|
2014-02-19 20:01:20 +00:00
|
|
|
# drawing bounding box (for the background rectangle)
|
|
|
|
attr_accessor :bbx, :bby, :bbxm, :bbym
|
|
|
|
def bb(x1, y1, x2, y2)
|
|
|
|
@bbx = [x1, x2, @bbx].compact.min
|
|
|
|
@bbxm = [x1, x2, @bbxm].compact.max
|
|
|
|
@bby = [y1, y2, @bby].compact.min
|
|
|
|
@bbym = [y1, y2, @bbym].compact.max
|
|
|
|
end
|
|
|
|
end
|
|
|
|
ret = gw.svgbuf = ''
|
|
|
|
gw.paint
|
2014-02-19 19:13:08 +00:00
|
|
|
|
2014-02-19 20:01:20 +00:00
|
|
|
ret[0, 0] = <<EOS
|
2014-02-19 19:13:08 +00:00
|
|
|
<?xml version="1.0" standalone="no"?>
|
|
|
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
|
|
|
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" font-family="courier, monospace">
|
|
|
|
<desc>Graph of #{get_label_at(gw.svgcuraddr) || Expression[gw.svgcuraddr]}</desc>
|
|
|
|
<rect x="#{gw.bbx-10}" y="#{gw.bby-10}" width="#{gw.bbxm-gw.bbx+20}" height="#{gw.bbym-gw.bby+20}" fill="#{gw.draw_color(:background)}" />"
|
|
|
|
EOS
|
2014-02-19 20:01:20 +00:00
|
|
|
ret << %Q{</svg>}
|
2014-02-19 19:13:08 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
gui.keyboard_callback[?E] = lambda { |*a|
|
2014-02-19 20:01:20 +00:00
|
|
|
gui.savefile('svg target') { |f|
|
|
|
|
svg = graph_to_svg
|
|
|
|
File.open(f, 'w') { |fd| fd.write svg }
|
|
|
|
}
|
|
|
|
true
|
2014-02-19 19:13:08 +00:00
|
|
|
}
|