def add_node(self, func): func_node = FlowGraphNode(self) line = DisassemblyTextLine([]) line.tokens.append( InstructionTextToken(InstructionTextTokenType.CodeSymbolToken, func.name, value=func.start, address=func.start)) func_node.lines = [line] self.append(func_node)
def add_func_node(self, func): if func in self.func_nodes: print(f"{func} already in, returning existing...") return self.func_nodes[func] func_node = FlowGraphNode(self) line = DisassemblyTextLine([]) line.tokens.append( InstructionTextToken(InstructionTextTokenType.CodeSymbolToken, func.name, value=func.start, address=func.start)) func_node.lines = [line] self.append(func_node) self.func_nodes[func] = func_node return func_node
def populate_nodes(self): func = self.function view = self.view nodes = {f: FlowGraphNode(self) for f in view.functions} for function, node in nodes.items(): if function.symbol.type == SymbolType.ImportedFunctionSymbol: token_type = InstructionTextTokenType.ImportToken else: token_type = InstructionTextTokenType.CodeSymbolToken node.lines = [ DisassemblyTextLine( [ InstructionTextToken(token_type, function.name, function.start) ], function.start, ) ] self.append(node) for function in view.functions: node = nodes[function] for callee in set(function.callees): callee_node = nodes[callee] node.add_outgoing_edge(BranchType.IndirectBranch, callee_node)
def populate_nodes(self): nodes = {} # create nodes for every block in the function for irb in viewvalues(self.ircfg.blocks): node = FlowGraphNode(self) nodes[irb.loc_key] = node self.append(node) for irb in viewvalues(self.ircfg.blocks): if not irb: continue # add edges for each block if irb.dst.is_cond(): if irb.dst.src1.is_loc() and irb.dst.src1.loc_key in nodes: nodes[irb.loc_key].add_outgoing_edge( BranchType.TrueBranch, nodes[irb.dst.src1.loc_key]) if irb.dst.src2.is_loc() and irb.dst.src2.loc_key in nodes: nodes[irb.loc_key].add_outgoing_edge( BranchType.FalseBranch, nodes[irb.dst.src2.loc_key]) elif irb.dst.is_loc() and irb.dst.loc_key in nodes: nodes[irb.loc_key].add_outgoing_edge( BranchType.UnconditionalBranch, nodes[irb.dst.loc_key]) lines = [] irb_token = self.expr_to_token(ExprLoc(irb.loc_key, irb.dst.size)) irb_token += [ InstructionTextToken(InstructionTextTokenType.TextToken, ":") ] lines.append(irb_token) for assignblk in irb: for dst, src in sorted(viewitems(assignblk)): tokens = [] tokens.append( InstructionTextToken( InstructionTextTokenType.TextToken, " ")) tokens += self.expr_to_token(dst) tokens.append( InstructionTextToken( InstructionTextTokenType.TextToken, " = ")) tokens += self.expr_to_token(src) lines.append(tokens) lines.append("") lines.pop() # remove last empty line nodes[irb.loc_key].lines = lines
def populate_nodes(self): # Create disassembly text renderers for assembly and IL func = self.function il = self.il_function asm_renderer = DisassemblyTextRenderer(func) il_renderer = DisassemblyTextRenderer(il) # First create nodes for every block in the function nodes = {} for block in il: node = FlowGraphNode(self) node.basic_block = block nodes[block.start] = node self.append(node) # Construct graph for block in il: il_renderer.basic_block = block # Add outgoing edges for the node for edge in block.outgoing_edges: nodes[block.start].add_outgoing_edge(edge.type, nodes[edge.target.start]) # Get instruction starts for assembly instructions in the block start_addr = il[block.start].address asm_block = func.get_basic_block_at(start_addr) if asm_block is None: # If first IL instruction was removed in IL translation, the previous call will fail. Find # the block that contains the instruction for i in func.basic_blocks: if start_addr >= i.start and start_addr < i.end: asm_block = i break asm_instrs = [] if asm_block is not None: asm_renderer.basic_block = asm_block start = asm_block.start end = asm_block.end addr = start while addr < end: asm_instrs.append(addr) data = func.view.read( addr, min(asm_block.arch.max_instr_length, end - addr)) info = asm_block.arch.get_instruction_info(data, addr) addr += info.length if info.length == 0: break # Iterate through instructions in this block and add disassembly lines lines = [] for i in block: # Display assembly instructions at or before the current IL instruction while len(asm_instrs) > 0 and i.address >= asm_instrs[0]: asm_lines, length = asm_renderer.get_disassembly_text( asm_instrs[0]) lines += asm_lines asm_instrs = asm_instrs[1:] # Display IL instruction il_lines, length = il_renderer.get_disassembly_text( i.instr_index) lines += il_lines # Go through lines and add addresses to them for line in lines: if line.il_instruction is None: # For assembly lines, show address line.tokens.insert( 0, InstructionTextToken( InstructionTextTokenType.AddressDisplayToken, "%.8x" % line.address, line.address)) line.tokens.insert( 1, InstructionTextToken( InstructionTextTokenType.TextToken, " ")) else: # For IL lines, show IL instruction index line.tokens.insert( 0, InstructionTextToken( InstructionTextTokenType.AnnotationToken, "%8s" % ("[%d]" % line.il_instruction.instr_index))) line.tokens.insert( 1, InstructionTextToken( InstructionTextTokenType.AnnotationToken, " => ")) nodes[block.start].lines = lines