def_analyze(self):region=self._region.recursive_copy()self._case_entry_to_switch_head:dict[int,int]=self._get_switch_case_entries()self.result_incomplete=False# visit the region in post-order DFSparent_map={}stack=[region]whilestack:current_region=stack[-1]has_region=Falsefornodeinnetworkx.dfs_postorder_nodes(current_region.graph,current_region.head):subnodes=[]iftype(node)isGraphRegion:ifnode.cyclic:subnodes.append(node)else:subnodes.insert(0,node)parent_map[node]=current_regionhas_region=True# remove existing regionsforsubnodeinsubnodes:ifsubnodeinstack:stack.remove(subnode)stack.extend(subnodes)ifnothas_region:# pop this region from the stackstack.pop()# Get the parent regionparent_region=parent_map.get(current_region,None)# structure this regionst:StructurerBase=self.project.analyses[self.structurer_cls].prep()(current_region.copy(),parent_map=parent_map,condition_processor=self.cond_proc,case_entry_to_switch_head=self._case_entry_to_switch_head,func=self.function,parent_region=parent_region,improve_structurer=self.improve_structurer,**self.structurer_options,)# replace this region with the resulting node in its parent region... if it's not an orphanifnotparent_region:# this is the top-level region. we are done!ifst.resultisNone:# take the partial result out of the graph_l.warning("Structuring failed to complete (most likely due to bugs in structuring). The ""output will miss code blocks.")self.result=self._pick_incomplete_result_from_region(st._region)self.result_incomplete=Trueelse:self.result=st.resultbreakifst.resultisNone:self._replace_region_with_region(parent_region,current_region,st._region)else:self._replace_region_with_node(parent_region,current_region,st._region,st.result,st.virtualized_edges)ifself.structurer_clsisDreamStructurer:# rewrite conditions in the result to remove all jump table entry conditionsrewriter=JumpTableEntryConditionRewriter(set(itertools.chain(*self.cond_proc.jump_table_conds.values())))rewriter.walk(self.result)# update SequenceNodes in-place# remove all goto statements# TODO: Properly implement support for multi-entry regionsStructurerBase._remove_all_jumps(self.result)else:StructurerBase._remove_redundant_jumps(self.result)# remove redundant labelsjtc=JumpTargetCollector(self.result)self.result=RedundantLabelRemover(self.result,jtc.jump_targets).result# remove empty nodes (if any)self.result=EmptyNodeRemover(self.result).resultifself.structurer_clsisDreamStructurer:# remove conditional jumpsStructurerBase._remove_conditional_jumps(self.result)self.result=self.cond_proc.remove_claripy_bool_asts(self.result)@staticmethoddef_replace_region_with_node(parent_region,sub_region,updated_sub_region,node,virtualized_edges):parent_region.replace_region(sub_region,updated_sub_region,node,virtualized_edges)@staticmethoddef_replace_region_with_region(parent_region,sub_region,new_region):parent_region.replace_region_with_region(sub_region,new_region)def_get_switch_case_entries(self)->dict[int,int]:ifself.functionisNone:return{}entries={}func_block_addrs=self.function.block_addrs_setjump_tables=self.kb.cfgs["CFGFast"].jump_tablesforjump_table_head_addr,jumptableinjump_tables.items():ifjump_table_head_addrnotinfunc_block_addrs:continueforentry_addrinjumptable.jumptable_entries:entries[entry_addr]=jump_table_head_addrreturnentriesdef_pick_incomplete_result_from_region(self,region):""" Parse the region graph and get (a) the node with address equal to the function address, or (b) the node with the lowest address. """min_node=Nonefornodeinregion.graph.nodes:ifnotisinstance(node,BaseNode):continueifnode.addr==self.function.addr:returnnodeifmin_nodeisNoneormin_node.addr<node.addr:min_node=nodereturnmin_node