def compute_block_histogram_per_edge(self, dropped_edges=set()): if self.symb_tree.is_empty(): return dict(), dict(), dict() edges_post = dict() edges_pre = dict() root_histogram = self.__compute_block_histogram_per_edge( self.symb_tree.root.children[0], self.symb_tree.root, edges_post, edges_pre, set(), set(), dropped_edges) # calculate histogram pre for edge in edges_pre: visited = edges_pre[edge] new = dict() for node in visited: block_id = self.address_to_block[str(node.data.address)] insert_or_add(new, block_id, 1) edges_pre[edge] = new # add the first node block to the root histogram first_node_addr = self.symb_tree.root.children[0].data.address if first_node_addr in self.address_to_block: insert_or_add(root_histogram, self.address_to_block[first_node_addr], 1) return root_histogram, edges_post, edges_pre
def __compute_block_histogram_per_block(self, node, nodes_list_post, nodes_list_pre, visited_blocks, visited_nodes, dropped_nodes): node_id = str(node.data.address) child_visited_nodes = visited_nodes.copy() child_visited_blocks = visited_blocks.copy() # find out whether the addresses of child and father are in R2 CFG # they cannot be there due to fake angr blocks (simprocedures) if node_id not in self.address_to_block: node_block_id = None else: node_block_id = self.address_to_block[node_id] if node_block_id: child_visited_nodes.add(node) child_visited_blocks.add(node_block_id) # this edges is considered dropped. Return empty histogram if node_block_id in dropped_nodes: return dict() # combine nephew histograms (if any) children_histogram = dict() for child in node.children: child_hist = self.__compute_block_histogram_per_block( child, nodes_list_post, nodes_list_pre, child_visited_blocks, child_visited_nodes, dropped_nodes) combine_histograms(children_histogram, child_hist) my_histogram = children_histogram if node_block_id: # the current block is in R2. Add it to the histogram to be returned insert_or_add(my_histogram, node_block_id, 1) # merge my histogram to edges_list only if the current edge was not visited by parents # Otherwise -> double count (see TreeAnalyzerTests.test_6()) if node_block_id not in visited_blocks: if node_block_id not in nodes_list_post: nodes_list_post[node_block_id] = my_histogram else: combine_histograms(nodes_list_post[node_block_id], my_histogram) if node_block_id not in nodes_list_pre: nodes_list_pre[node_block_id] = visited_nodes else: nodes_list_pre[node_block_id] = nodes_list_pre[ node_block_id].union(visited_nodes) # return histogram. Copy it because it can be in edges_list_post return dict(my_histogram)
def __compute_node_count_per_edge(self, child, father, edges_list_post, edges_list_pre, visited_edges, visited_nodes, dropped_edges): child_id = str(child.data.address) father_id = str( father.data.block_addresses[-1]) if father.data else None nephew_visited_edges = visited_edges.copy() if child_id not in self.address_to_block: child_block_id = None else: child_block_id = self.address_to_block[child_id] if father_id not in self.address_to_block: father_block_id = None else: father_block_id = self.address_to_block[father_id] if child_block_id and father_block_id: nephew_visited_edges.add((father_block_id, child_block_id)) # this edges is considered dropped. Return empty histogram if (father_block_id, child_block_id) in dropped_edges: return dict() # add node even if its block is not in R2 # this is different with respect to "__compute_block_histogram_per_edge" nephew_visited_nodes = visited_nodes.copy() nephew_visited_nodes.add(child) nephews_blocks = 0 for nephew in child.children: nephew_blocks = self.__compute_node_count_per_edge( nephew, child, edges_list_post, edges_list_pre, nephew_visited_edges, nephew_visited_nodes, dropped_edges) nephews_blocks += nephew_blocks # count the node even if its block is not in R2 # this is different with respect to "__compute_block_histogram_per_edge" my_nodes = nephews_blocks + 1 if child_block_id and father_block_id: edge_id = (father_block_id, child_block_id) if edge_id not in visited_edges: insert_or_add(edges_list_post, edge_id, my_nodes) if edge_id not in edges_list_pre: edges_list_pre[edge_id] = visited_nodes else: edges_list_pre[edge_id] = edges_list_pre[edge_id].union( visited_nodes) return my_nodes
def __compute_node_count_per_block(self, node, nodes_list_post, nodes_list_pre, visited_blocks, visited_nodes, dropped_blocks): node_id = str(node.data.address) child_visited_blocks = visited_blocks.copy() child_visited_nodes = visited_nodes.copy() if node_id not in self.address_to_block: node_block_id = None else: node_block_id = self.address_to_block[node_id] if node_block_id: child_visited_blocks.add(node_block_id) # this edges is considered dropped. Return empty histogram if node_block_id in dropped_blocks: return dict() # add node even if its block is not in R2 # this is different with respect to "__compute_block_histogram_per_edge" child_visited_nodes.add(node) children_blocks = 0 for child in node.children: child_blocks = self.__compute_node_count_per_block( child, nodes_list_post, nodes_list_pre, child_visited_blocks, child_visited_nodes, dropped_blocks) children_blocks += child_blocks # count the node even if its block is not in R2 # this is different with respect to "__compute_block_histogram_per_edge" my_nodes = children_blocks + 1 if node_block_id: if node_block_id not in visited_blocks: insert_or_add(nodes_list_post, node_block_id, my_nodes) if node_block_id not in nodes_list_pre: nodes_list_pre[node_block_id] = visited_nodes else: nodes_list_pre[node_block_id] = nodes_list_pre[ node_block_id].union(visited_nodes) return my_nodes
def __compute_edges(self, child, father, res): child_id = str(child.data.address) father_id = str( father.data.block_addresses[-1]) if father.data else None if child_id not in self.address_to_block: child_block_id = None else: child_block_id = self.address_to_block[child_id] if father_id not in self.address_to_block: father_block_id = None else: father_block_id = self.address_to_block[father_id] if child_block_id and father_block_id: insert_or_add(res, (father_block_id, child_block_id), 1) for nephew in child.children: self.__compute_edges(nephew, child, res)
def compute_block_histogram_per_block(self, dropped_nodes=set()): if self.symb_tree.is_empty(): return dict(), dict(), dict() blocks_histogram_post = dict() blocks_histogram_pre = dict() root_histogram = self.__compute_block_histogram_per_block( self.symb_tree.root.children[0], blocks_histogram_post, blocks_histogram_pre, set(), set(), dropped_nodes) # calculate histogram pre for b in blocks_histogram_pre: visited = blocks_histogram_pre[b] new = dict() for node in visited: block_id = self.address_to_block[str(node.data.address)] insert_or_add(new, block_id, 1) blocks_histogram_pre[b] = new return root_histogram, blocks_histogram_post, blocks_histogram_pre
def __compute_block_histogram_per_edge(self, child, father, edges_list_post, edges_list_pre, visited_edges, visited_nodes, dropped_edges): child_id = str(child.data.address) father_id = str( father.data.block_addresses[-1]) if father.data else None nephew_visited_edges = visited_edges.copy() nephew_visited_nodes = visited_nodes.copy() # find out whether the addresses of child and father are in R2 CFG # they cannot be there due to fake angr blocks (simprocedures) if child_id not in self.address_to_block: child_block_id = None else: child_block_id = self.address_to_block[child_id] if father_id not in self.address_to_block: father_block_id = None else: father_block_id = self.address_to_block[father_id] if child_block_id and father_block_id: nephew_visited_edges.add((father_block_id, child_block_id)) # this edges is considered dropped. Return empty histogram if (father_block_id, child_block_id) in dropped_edges: return dict() if child_block_id: nephew_visited_nodes.add(child) # combine nephew histograms (if any) nephews_histogram = dict() for nephew in child.children: nephew_hist = self.__compute_block_histogram_per_edge( nephew, child, edges_list_post, edges_list_pre, nephew_visited_edges, nephew_visited_nodes, dropped_edges) combine_histograms(nephews_histogram, nephew_hist) my_histogram = nephews_histogram if child_block_id and father_block_id: # the current block is in R2. Add it to the histogram to be returned insert_or_add(my_histogram, child_block_id, 1) # merge my histogram to edges_list only if the current edge was not visited by parents # Otherwise -> double count (see TreeAnalyzerTests.test_6()) edge_id = (father_block_id, child_block_id) if edge_id not in visited_edges: if edge_id not in edges_list_post: edges_list_post[edge_id] = my_histogram else: combine_histograms(edges_list_post[edge_id], my_histogram) if edge_id not in edges_list_pre: edges_list_pre[edge_id] = visited_nodes else: edges_list_pre[edge_id] = edges_list_pre[edge_id].union( visited_nodes) # return histogram. Copy it because it can be in edges_list_post return dict(my_histogram)