Code Blocks

If you ever looked at a function in the Graph-View, you know what code blocks are. They are the nodes in the function graph, sometimes referred to as a flowchart.

>>> block = sark.CodeBlock()
>>> print(list(block.next))
[<CodeBlock(start_ea=0x00417567, end_ea=0x00417570)>,
 <CodeBlock(start_ea=0x0041759E, end_ea=0x004175D4)>]

Sark’s CodeBlock object inherits from the idaapi.BasicBlock objects, and adds a few handy members.

Member Usage
lines the lines in the block, as a generator
next successor nodes, as a generator
prev predecessor nodes, as a generator
color the background color of the node

These members allow for easy traversal and analysis of nodes in a graph.

FlowChart

Sark’s flowchart, inheriting from idaapi.FlowChart, is in every way the same except for returning Sark CodeBlock objects instead of idaapi.BasicBlock ones. It can be used to quickly fetch all the blocks in a function graph.

Getting Codeblocks

Codeblocks are created using the sark.CodeBlock(ea) class. Flowcharts can be retrieved using the sark.FlowChart(ea) class accordingly.

In some cases, you may want to go over more than one function. In those cases, you can use the sark.codeblocks(start=None, end=None, full=True) function. The full parameter controls the way the blocks are generated. With full=True, FlowChart objects are generated per function, yielding fully capable CodeBlock objects. With full=False, a single FlowChart is generated for the entire address range. This results in faster iteration, but since the blocks are not associated to their containing functions, it is not possible to get or set block colors (line color will change, though.)

Advanced Usage

Since the function flowchart is actually a graph, it makes sense to use it as one. To ease you into it, the sark.get_nx_graph(ea) function was added.

>>> sark.get_nx_graph(idc.here())
<networkx.classes.digraph.DiGraph at 0x85d6570>

The function returns a NetworkX DiGraph object representing the flowchart, with each node being the start_ea of a matching block. Using NetworkX’s functionality, it is easy to trace routes in the graph.

>>> import networkx as nx
>>> func = sark.Function()
>>> graph = sark.get_nx_graph(func.ea)
>>> start_address = sark.get_block_start(func.start_ea)  # The `get_block_start(ea)` is short for `get_codeblock(ea).start_ea`
>>> end_address = sark.get_block_start(func.end_ea - 1)  # Remember, `end_ea` is outside the function!
>>> path = nx.shortest_path(graph, start_address, end_address)
>>> print("From {} to {}".format(hex(start_address), hex(end_address)))
From 0x417400L to 0x4176a6L

>>>print " -> ".join(map(hex, nx.shortest_path(graph, start, end)))
0x417400L -> 0x41745dL -> 0x417483L -> 0x417499L -> 0x4176a6L