@@ -92,11 +92,40 @@ def trampoline_payload_roles(self) -> List[str]:
9292
9393 @property
9494 def instructions (self ) -> Dict [str , ASTInterfaceInstruction ]:
95+ """Main access to ast representation of instructions.
96+
97+ The ASTInterfaceInstruction provides both the high-level and
98+ low-level representation of an instruction. It is important
99+ to have only one of these per instruction, because the high-level
100+ and low-level representation are created together, and in the
101+ process the relationship between the high-level and low-level
102+ is recorded in the AbstractSyntaxTree/Provenance data structure.
103+
104+ If another instruction is created separately (e.g., to only
105+ obtain the high-level or low-level representation), this
106+ relationship may be corrupted.
107+
108+ Thus, this function should be the only one to create
109+ ASTInterfaceInstruction's.
110+ """
95111 if len (self ._instructions ) == 0 :
96112 for (iaddr , instr ) in self .basicblock .instructions .items ():
97113 self ._instructions [iaddr ] = ASTInterfaceInstruction (instr )
98114 return self ._instructions
99115
116+ def has_instruction (self , iaddr : str ) -> bool :
117+ return iaddr in self .instructions
118+
119+ def get_instruction (self , iaddr : str ) -> ASTInterfaceInstruction :
120+ if self .has_instruction (iaddr ):
121+ return self .instructions [iaddr ]
122+ else :
123+ raise UF .CHBError (
124+ "No instruction found at address "
125+ + iaddr +
126+ " in basic block "
127+ + self .basicblock .baddr )
128+
100129 @property
101130 def trampoline_instructions (
102131 self ) -> Dict [str , Dict [str , ASTInterfaceInstruction ]]:
@@ -171,8 +200,8 @@ def assembly_ast(self, astree: "ASTInterface") -> AST.ASTStmt:
171200 def ast_fragment (
172201 self , astree : "ASTInterface" , frag : "BasicBlockFragment" ) -> AST .ASTStmt :
173202 if frag .is_predicated :
174- theninstrs = [ASTInterfaceInstruction ( i ) for i in frag .thenbranch ]
175- elseinstrs = [ASTInterfaceInstruction ( i ) for i in frag .elsebranch ]
203+ theninstrs = [self . get_instruction ( i . iaddr ) for i in frag .thenbranch ]
204+ elseinstrs = [self . get_instruction ( i . iaddr ) for i in frag .elsebranch ]
176205 thenstmt = self .linear_block_ast (astree , theninstrs )
177206 elsestmt = self .linear_block_ast (astree , elseinstrs )
178207 cinstr = theninstrs [0 ]
@@ -187,7 +216,7 @@ def ast_fragment(
187216 brcond .exprid , cinstr .iaddr , cinstr .bytestring )
188217 return astree .mk_branch (brcond , thenstmt , elsestmt , "0x0" )
189218 else :
190- instrs = [ASTInterfaceInstruction ( i ) for i in frag .linear ]
219+ instrs = [self . get_instruction ( i . iaddr ) for i in frag .linear ]
191220 return self .linear_ast (astree , instrs )
192221
193222 def fragmented_ast (self , astree : "ASTInterface" ) -> AST .ASTStmt :
0 commit comments