[docs]classVEXIRSBScanner(SimEngineLightVEXMixin):""" Scan the VEX IRSB to determine if any argument-passing registers should be narrowed by detecting cases of loading the whole register and immediately narrowing the register before writing to the tmp. """
[docs]def__init__(self,*args,**kwargs):super().__init__(*args,**kwargs)# the following variables are for narrowing argument-passing register on 64-bit architectures. they are# initialized before processing each block.self.tmps_with_64bit_regs:Set[int]=set()# tmps that store 64-bit register valuesself.tmps_converted_to_32bit:Set[int]=set()# tmps that store the 64-to-32-bit converted valuesself.tmps_assignment_stmtidx:Dict[int,int]={}# statement IDs for the assignment of each tmpself.stmts_to_lower:Set[int]=set()# the following variables are for recognizing redundant argument register reads in gcc(?) -O0 binaries.# e.g.,# mov rdi, r9# mov rdi, rax## we will not create a variable for the register read in the first instruction (read from r9) in this case.self.tmp_with_reg_as_value:Dict[int,int]={}self.reg_with_reg_as_value:Dict[int,int]={}self.reg_read_stmt_id:Dict[int,int]={}self.reg_read_stmts_to_ignore:Set[int]=set()
def_top(self,size:int):returnNonedef_is_top(self,expr)->bool:returnTruedef_process_Stmt(self,whitelist=None):self.tmps_with_64bit_regs=set()self.tmps_assignment_stmtidx={}self.tmps_converted_to_32bit=set()super()._process_Stmt(whitelist=whitelist)self.stmts_to_lower={self.tmps_assignment_stmtidx[i]foriinself.tmps_converted_to_32bit}def_handle_Put(self,stmt):ifisinstance(stmt.data,pyvex.IRExpr.RdTmp)andstmt.data.tmpinself.tmp_with_reg_as_value:if(stmt.offsetinself.reg_with_reg_as_valueandself.reg_with_reg_as_value[stmt.offset]!=self.tmp_with_reg_as_value[stmt.data.tmp]):# we are overwriting an existing register with a value from another register, before this register is# ever used...# in this case, we should ignore the previous register readold_reg_offset=self.reg_with_reg_as_value[stmt.offset]self.reg_read_stmts_to_ignore.add(self.reg_read_stmt_id[old_reg_offset])self.reg_with_reg_as_value[stmt.offset]=self.tmp_with_reg_as_value[stmt.data.tmp]def_handle_PutI(self,stmt):passdef_handle_Load(self,expr):passdef_handle_Store(self,stmt):passdef_handle_LoadG(self,stmt):passdef_handle_LLSC(self,stmt:pyvex.IRStmt.LLSC):passdef_handle_StoreG(self,stmt):passdef_handle_WrTmp(self,stmt):ifisinstance(stmt.data,pyvex.IRExpr.Get)andstmt.data.result_size(self.tyenv)==64:self.tmps_with_64bit_regs.add(stmt.tmp)self.tmps_assignment_stmtidx[stmt.tmp]=self.stmt_idxifisinstance(stmt.data,pyvex.IRExpr.Get)andstmt.data.result_size(self.tyenv)==64:self.tmp_with_reg_as_value[stmt.tmp]=stmt.data.offsetsuper()._handle_WrTmp(stmt)def_handle_Get(self,expr):self.reg_read_stmt_id[expr.offset]=self.stmt_idxifexpr.offsetinself.reg_with_reg_as_value:delself.reg_with_reg_as_value[expr.offset]def_handle_GetI(self,expr):passdef_handle_RdTmp(self,expr):ifexpr.tmpinself.tmps_converted_to_32bit:self.tmps_converted_to_32bit.remove(expr.tmp)def_handle_Conversion(self,expr:pyvex.IRExpr.Unop):ifexpr.op=="Iop_64to32"andisinstance(expr.args[0],pyvex.IRExpr.RdTmp):# special handling for t11 = GET:I64(rdi); t4 = 64to32(t11) style of code in x86-64 (and other 64-bit# architectures as well)tmp_src=expr.args[0].tmpiftmp_srcinself.tmps_with_64bit_regs:self.tmps_converted_to_32bit.add(tmp_src)def_handle_16HLto32(self,expr):passdef_handle_Cmp_v(self,expr,_vector_size,_vector_count):pass_handle_CmpEQ_v=_handle_Cmp_v_handle_CmpNE_v=_handle_Cmp_v_handle_CmpLE_v=_handle_Cmp_v_handle_CmpLT_v=_handle_Cmp_v_handle_CmpGE_v=_handle_Cmp_v_handle_CmpGT_v=_handle_Cmp_vdef_handle_ExpCmpNE64(self,expr):passdef_handle_CCall(self,expr):passdef_handle_function(self,func_addr):pass