def write(self, offset, expr): """ Write @expr at @offset @offset: integer (in bytes) @expr: Expr instance value """ assert expr.size % 8 == 0 assert offset <= self._mask for index in xrange(expr.size / 8): # Wrap write: # @32[EAX+0xFFFFFFFF] is ok and will write at 0xFFFFFFFF, 0, 1, 2 request_offset = (offset + index) & self._mask # XXX TODO: only little endian here self._offset_to_expr[request_offset] = (index, expr) tmp = self.expr_simp(expr[index * 8:(index + 1) * 8]) # Special case: Simplify slice of pointer (simplification is ok # here, as we won't store the simplified expression) if tmp.is_slice() and tmp.arg.is_mem() and tmp.start % 8 == 0: new_ptr = self.expr_simp(tmp.arg.ptr + ExprInt(tmp.start / 8, tmp.arg.ptr.size)) tmp = ExprMem(new_ptr, tmp.stop - tmp.start) # Test if write to original value if tmp.is_mem(): src_ptr, src_off = get_expr_base_offset(tmp.ptr) if src_ptr == self.base and src_off == request_offset: del self._offset_to_expr[request_offset]
def write(self, offset, expr): """ Write @expr at @offset @offset: integer (in bytes) @expr: Expr instance value """ assert expr.size % 8 == 0 assert offset <= self._mask for index in xrange(expr.size / 8): # Wrap write: # @32[EAX+0xFFFFFFFF] is ok and will write at 0xFFFFFFFF, 0, 1, 2 request_offset = (offset + index) & self._mask # XXX TODO: only little endian here self._offset_to_expr[request_offset] = (index, expr) tmp = self.expr_simp(expr[index * 8: (index + 1) * 8]) # Special case: Simplify slice of pointer (simplification is ok # here, as we won't store the simplified expression) if tmp.is_slice() and tmp.arg.is_mem() and tmp.start % 8 == 0: new_ptr = self.expr_simp(tmp.arg.arg + ExprInt(tmp.start / 8, tmp.arg.arg.size)) tmp = ExprMem(new_ptr, tmp.stop - tmp.start) # Test if write to original value if tmp.is_mem(): src_ptr, src_off = get_expr_base_offset(tmp.arg) if src_ptr == self.base and src_off == request_offset: del self._offset_to_expr[request_offset]
def manage_mem(self, expr, state, cache, level): ptr = self.apply_expr_on_state_visit_cache(expr.arg, state, cache, level+1) ret = ExprMem(ptr, expr.size) ret = self.get_mem_state(ret) if ret.is_mem() and not ret.arg.is_int() and ret.arg == ptr: ret = exprid_top(expr) assert expr.size == ret.size return ret
def manage_mem(self, expr, state, cache, level): ptr = self.apply_expr_on_state_visit_cache(expr.arg, state, cache, level+1) ret = ExprMem(ptr, expr.size) ret = self.get_mem_state(ret) if ret.is_mem() and not ret.arg.is_int() and ret.arg == ptr: ret = exprid_top(expr) assert expr.size == ret.size return ret
def propagate(self, ssa, head): defuse = SSADefUse.from_ssa(ssa) to_replace = {} node_to_reg = {} for node in defuse.nodes(): lbl, index, reg = node src = defuse.get_node_target(node) if expr_has_call(src): continue if src.is_op('Phi'): continue if reg.is_mem(): continue to_replace[reg] = src node_to_reg[node] = reg modified = False for node, reg in node_to_reg.iteritems(): for successor in defuse.successors(node): if not self.propagation_allowed(ssa, to_replace, node, successor): continue loc_a, index_a, reg_a = node loc_b, index_b, reg_b = successor block = ssa.graph.blocks[loc_b] replace = {reg_a: to_replace[reg_a]} # Replace assignblks = list(block) assignblk = block[index_b] out = {} for dst, src in assignblk.iteritems(): if src.is_op('Phi'): out[dst] = src continue if src.is_mem(): ptr = src.ptr ptr = ptr.replace_expr(replace) new_src = ExprMem(ptr, src.size) else: new_src = src.replace_expr(replace) if dst.is_id(): new_dst = dst elif dst.is_mem(): ptr = dst.ptr ptr = ptr.replace_expr(replace) new_dst = ExprMem(ptr, dst.size) else: new_dst = dst.replace_expr(replace) if not (new_dst.is_id() or new_dst.is_mem()): new_dst = dst if src != new_src or dst != new_dst: modified = True out[new_dst] = new_src out = AssignBlock(out, assignblk.instr) assignblks[index_b] = out new_block = IRBlock(block.loc_key, assignblks) ssa.graph.blocks[block.loc_key] = new_block return modified
def propagate(self, ssa, head): defuse = SSADefUse.from_ssa(ssa) to_replace = {} node_to_reg = {} for node in defuse.nodes(): lbl, index, reg = node src = defuse.get_node_target(node) if expr_has_call(src): continue if src.is_op('Phi'): continue if reg.is_mem(): continue to_replace[reg] = src node_to_reg[node] = reg modified = False for node, reg in node_to_reg.iteritems(): for successor in defuse.successors(node): if not self.propagation_allowed(ssa, to_replace, node, successor): continue loc_a, index_a, reg_a = node loc_b, index_b, reg_b = successor block = ssa.graph.blocks[loc_b] replace = {reg_a: to_replace[reg_a]} # Replace assignblks = list(block) assignblk = block[index_b] out = {} for dst, src in assignblk.iteritems(): if src.is_op('Phi'): out[dst] = src continue if src.is_mem(): ptr = src.ptr ptr = ptr.replace_expr(replace) new_src = ExprMem(ptr, src.size) else: new_src = src.replace_expr(replace) if dst.is_id(): new_dst = dst elif dst.is_mem(): ptr = dst.ptr ptr = ptr.replace_expr(replace) new_dst = ExprMem(ptr, dst.size) else: new_dst = dst.replace_expr(replace) if not (new_dst.is_id() or new_dst.is_mem()): new_dst = dst if src != new_src or dst != new_dst: modified = True out[new_dst] = new_src out = AssignBlock(out, assignblk.instr) assignblks[index_b] = out new_block = IRBlock(block.loc_key, assignblks) ssa.graph.blocks[block.loc_key] = new_block return modified