diff options
| author | Peter LaFosse <peter@vector35.com> | 2017-01-02 15:34:57 -0500 |
|---|---|---|
| committer | Peter LaFosse <peter@vector35.com> | 2017-01-02 15:34:57 -0500 |
| commit | 1ff75ac9611c4f8cbde195460dfc18e139fee696 (patch) | |
| tree | f4bd7945840002e8b937aa278f6b58d2e98da9ad /python | |
| parent | 842aba557f24ca9ab63f05cec6aa0c0efebd51b4 (diff) | |
merging svg export changes
Diffstat (limited to 'python')
| -rwxr-xr-x | python/examples/export_svg.py | 95 |
1 files changed, 40 insertions, 55 deletions
diff --git a/python/examples/export_svg.py b/python/examples/export_svg.py index 843b17a5..5a4d2982 100755 --- a/python/examples/export_svg.py +++ b/python/examples/export_svg.py @@ -1,30 +1,10 @@ -# Copyright (c) 2015-2016 Vector 35 LLC -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - from binaryninja import * import os import webbrowser try: - from urllib import pathname2url # Python 2.x + from urllib import pathname2url # Python 2.x except: - from urllib.request import pathname2url # Python 3.x + from urllib.request import pathname2url # Python 3.x colors = {'green': [162, 217, 175], 'red': [222, 143, 151], 'blue': [128, 198, 233], 'cyan': [142, 230, 237], 'lightCyan': [176, 221, 228], 'orange': [237, 189, 129], 'yellow': [237, 223, 179], 'magenta': [218, 196, 209], 'none': [74, 74, 74]} @@ -37,51 +17,52 @@ escape_table = { ' ': " " } - def escape(string): - string = string.decode('utf-8').encode('ascii', 'xmlcharrefreplace') # handle extended unicode - return ''.join(escape_table.get(i, i) for i in string) # still escape the basics + string=string.decode('utf-8').encode('ascii','xmlcharrefreplace') #handle extended unicode + return ''.join(escape_table.get(i,i) for i in string) #still escape the basics - -def save_svg(bv, function): - address = hex(function.start).replace('L', '') +def save_svg(bv,function): + address = hex(function.start).replace('L','') path = os.path.dirname(bv.file.filename) origname = os.path.basename(bv.file.filename) - filename = os.path.join(path, 'binaryninja-{filename}-{function}.html'.format(filename=origname, function=address)) + filename = os.path.join(path,'binaryninja-{filename}-{function}.html'.format(filename=origname,function=address)) outputfile = get_save_filename_input('File name for export_svg', 'HTML files (*.html)', filename) if outputfile is None: return content = render_svg(function) - output = open(outputfile, 'w') + output = open(outputfile,'w') output.write(content) output.close() - if show_message_box("Open SVG", "Would you like to view the exported SVG?", buttons=core.BNMessageBoxButtonSet.YesNoButtonSet, icon = core.BNMessageBoxIcon.QuestionIcon) == core.BNMessageBoxButtonResult.YesButton: + if show_message_box("Open SVG", "Would you like to view the exported SVG?", buttons = core.YesNoButtonSet, icon = core.QuestionIcon) == core.YesButton: url = 'file:{}'.format(pathname2url(outputfile)) webbrowser.open(url) - -def instruction_data_flow(function, address): +def instruction_data_flow(function,address): ''' TODO: Extract data flow information ''' - length = function.view.get_instruction_length(function.arch, address) + length = function.view.get_instruction_length(function.arch,address) bytes = function.view.read(address, length) hex = bytes.encode('hex') - padded = ' '.join([hex[i:i + 2] for i in range(0, len(hex), 2)]) + padded = ' '.join([hex[i:i+2] for i in range(0, len(hex), 2)]) return 'Opcode: {bytes}'.format(bytes=padded) - def render_svg(function): graph = function.create_graph() graph.layout_and_wait() heightconst = 15 ratio = 0.48 - widthconst = heightconst * ratio + widthconst = heightconst*ratio output = '''<html> <head> <style type="text/css"> @import url(https://fonts.googleapis.com/css?family=Source+Code+Pro); + body { + background-color: rgb(42, 42, 42); + } svg { background-color: rgb(42, 42, 42); + display: block; + margin: 0 auto; } .basicblock { stroke: rgb(224, 224, 224); @@ -154,56 +135,60 @@ def render_svg(function): <path d="M 0 0 L 10 5 L 0 10 z" /> </marker> </defs> - '''.format(width=graph.width * widthconst, height=graph.height * heightconst) + '''.format(width=graph.width*widthconst + 20, height=graph.height*heightconst + 20) output += ''' <g id="functiongraph0" class="functiongraph"> <title>Function Graph 0</title> ''' edges = '' - for i, block in enumerate(graph.blocks): + for i,block in enumerate(graph.blocks): - # Calculate basic block location and coordinates + #Calculate basic block location and coordinates x = ((block.x) * widthconst) y = ((block.y) * heightconst) width = ((block.width) * widthconst) height = ((block.height) * heightconst) - # Render block + #Render block output += ' <g id="basicblock{i}">\n'.format(i=i) output += ' <title>Basic Block {i}</title>\n'.format(i=i) - rgb = colors['none'] + rgb=colors['none'] try: bb = block.basic_block color_code = bb.highlight.color color_str = bb.highlight._standard_color_to_str(color_code) if color_str in colors: - rgb = colors[color_str] + rgb=colors[color_str] except: pass - output += ' <rect class="basicblock" x="{x}" y="{y}" fill-opacity="0.4" height="{height}" width="{width}" fill="rgb({r},{g},{b})"/>\n'.format(x=x, y=y, width=width, height=height, r=rgb[0], g=rgb[1], b=rgb[2]) + output += ' <rect class="basicblock" x="{x}" y="{y}" fill-opacity="0.4" height="{height}" width="{width}" fill="rgb({r},{g},{b})"/>\n'.format(x=x,y=y,width=width + 16,height=height + 12,r=rgb[0],g=rgb[1],b=rgb[2]) - # Render instructions, unfortunately tspans don't allow copying/pasting more - # than one line at a time, need SVG 1.2 textarea tags for that it looks like + #Render instructions, unfortunately tspans don't allow copying/pasting more + #than one line at a time, need SVG 1.2 textarea tags for that it looks like - output += ' <text x="{x}" y="{y}">\n'.format(x=x, y=y + (i + 1) * heightconst) - for i, line in enumerate(block.lines): - output += ' <tspan id="instr-{address}" x="{x}" y="{y}">'.format(x=x, y=y + (i + 0.7) * heightconst, address=hex(line.address)[:-1]) + output += ' <text x="{x}" y="{y}">\n'.format(x=x,y=y + (i + 1) * heightconst) + for i,line in enumerate(block.lines): + output += ' <tspan id="instr-{address}" x="{x}" y="{y}">'.format(x=x + 6,y=y + 6 + (i + 0.7) * heightconst,address=hex(line.address)[:-1]) hover = instruction_data_flow(function, line.address) output += '<title>{hover}</title>'.format(hover=hover) for token in line.tokens: # TODO: add hover for hex, function, and reg tokens - output += '<tspan class="{tokentype}">{text}</tspan>'.format(text=escape(token.text), tokentype=token.type.name) + output+='<tspan class="{tokentype}">{text}</tspan>'.format(text=escape(token.text),tokentype=token.type) output += '</tspan>\n' output += ' </text>\n' output += ' </g>\n' - # Edges are rendered in a seperate chunk so they have priority over the - # basic blocks or else they'd render below them + #Edges are rendered in a seperate chunk so they have priority over the + #basic blocks or else they'd render below them for edge in block.outgoing_edges: points = "" - for x, y in edge.points: - points += str(x * widthconst) + "," + str(y * heightconst) + " " - edges += ' <polyline class="edge {type}" points="{points}" marker-end="url(#arrow-{type})"/>\n'.format(type=edge.type.name, points=points) + x,y = edge.points[0] + points += str(x*widthconst)+","+str(y*heightconst + 12) + " " + for x,y in edge.points[1:-1]: + points += str(x*widthconst)+","+str(y*heightconst) + " " + x,y = edge.points[-1] + points += str(x*widthconst)+","+str(y*heightconst + 0) + " " + edges += ' <polyline class="edge {type}" points="{points}" marker-end="url(#arrow-{type})"/>\n'.format(type=edge.type,points=points) output += ' ' + edges + '\n' output += ' </g>\n' output += '</svg></html>' |
