def setx(self, loc, val, size=0): """ high level method to set the expressions value associated to left-value loc (register or address). The value is possibly an integer or a symbolic expression instance. The input loc is either a register string, an integer address, or associated expressions' instances. Optionally, the size of the loc expression can be adjusted by the size argument. """ if isinstance(loc, str): x = getattr(self.cpu, loc) size = x.size elif isinstance(loc, int): endian = self.cpu.get_data_endian() psz = self.cpu.PC().size x = self.cpu.mem(self.cpu.cst(addr, psz), size, endian=endian) else: x = loc size = x.size if isinstance(val, bytes): if x._is_mem: x.size = len(val) if size == 0 else size self.state._Mem_write(x.a, val) else: endian = self.cpu.get_data_endian() v = self.cpu.cst( Bits(val[0:x.size:endian], bitorder=1).int(), x.size * 8) self.state[x] = v elif isinstance(val, int): self.state[x] = self.cpu.cst(val, size) else: self.state[x] = val
def _Mem_read(self, a, l): try: res = self.__Mem.read(a, l) except MemoryError: # no zone for location a; res = [exp(l * 8)] if exp._endian == -1: res.reverse() P = [] cur = 0 for p in res: plen = len(p) if isinstance(p, exp) and (p._is_def is False): if self.csi: p = self.csi(mem(a, p.size, disp=cur)) else: p = mem(a, p.size, disp=cur) if isinstance(p, str): p = cst(Bits(p[::exp._endian], bitorder=1).int(), plen * 8) P.append(p) cur += plen return composer(P)
def _Mem_read(self, a, l, endian=1): "read l bytes from memory address a and return an expression" try: res = self.__Mem.read(a, l) except MemoryError: # no zone for location a; res = [exp(l * 8)] if endian == -1: res.reverse() P = [] cur = 0 for p in res: plen = len(p) if isinstance(p, exp) and (p._is_def is False): # p is "bottom": if self.csi: p = self.csi(mem(a, p.size, disp=cur, endian=endian)) else: p = mem(a, p.size, disp=cur) if isinstance(p, bytes): p = cst(Bits(p[::endian], bitorder=1).int(), plen * 8) P.append(p) cur += plen return composer(P)
def _Mem_read(self, a, l, endian=1): "read l bytes from memory address a and return an expression" try: res = self.__Mem.read(a, l) except MemoryError: # no zone for location a; res = [exp(l * 8)] if endian == -1: res.reverse() P = [] cur = 0 for p in res: plen = len(p) if isinstance(p, bytes): p = cst(Bits(p[::endian], bitorder=1).int(), plen * 8) elif isinstance(p, exp): if p._is_def == 0: # p is "bottom": p = mem(a, p.size, disp=cur) elif p._is_ext and p._subrefs.get("mmio_r", None): p = p.stub(self, mode="r") P.append(p) cur += plen return composer(P)
class mapper(object): assume_no_aliasing = False __slots__ = ['__map', '__Mem', 'conds', 'csi'] # a mapper is inited with a list of instructions # provided by a disassembler def __init__(self, instrlist=None, csi=None): self.__map = generation() self.__map.lastw = 0 self.__Mem = MemoryMap() self.conds = [] self.csi = csi icache = [] # if the __map needs to be inited before executing instructions # one solution is to prepend the instrlist with a function dedicated # to this init phase... for instr in instrlist or []: # call the instruction with this mapper: if not instr.misc['delayed']: instr(self) else: icache.append(instr) for instr in icache: instr(self) def __len__(self): return len(self.__map) def __str__(self): return '\n'.join(["%s <- %s" % x for x in self]) def pp(self, **kargs): lv = [(l.pp(**kargs), v.pp(**kargs)) for (l, v) in self] return '\n'.join(["%s <- %s" % x for x in lv]) def __getstate__(self): return (self.__map, self.csi) def __setstate__(self, state): self.__map, self.csi = state self.__Mem = MemoryMap() for loc, v in self: if loc._is_ptr: self._Mem_write(loc, v) # list antecedent locations (used in the mapping) def inputs(self): return sum(map(locations_of, self.__map.itervalues()), []) # list image locations (modified in the mapping) def outputs(self): L = [] for l in sum(map(locations_of, self.__map.iterkeys()), []): if l._is_ptr: l = mem(l, self.__map[l].size) L.append(l) return L def has(self, loc): for l in self.__map.keys(): if loc == l: return True return False def history(self, loc): return self.__map._generation__getall(loc) def rw(self): r = filter(lambda x: x._is_mem, self.inputs()) w = filter(lambda x: x._is_mem, self.outputs()) sr = [x.size for x in r] sw = [x.size for x in w] return (sr, sw) def clear(self): self.__map.clear() self.__Mem = MemoryMap() def memory(self): return self.__Mem def generation(self): return self.__map # compare self with mapper m: def __cmp__(self, m): d = cmp(self.__map.lastdict(), m.__map.lastdict()) return d # iterate over ordered correspondances: def __iter__(self): for (loc, v) in self.__map.iteritems(): yield (loc, v) # get a (plain) register value: def R(self, x): if self.csi: return self.__map.get(x, self.csi(x)) else: return self.__map.get(x, x) # get a memory location value (fetch) : # k must be mem expressions def M(self, k): if k.a.base._is_ext: return k.a.base n = self.aliasing(k) if n > 0: f = lambda e: e[0]._is_ptr items = filter(f, self.__map.items()[0:n]) res = mem(k.a, k.size, mods=items) else: res = self._Mem_read(k.a, k.length) res.sf = k.sf return res def aliasing(self, k): if self.assume_no_aliasing: return 0 K = self.__map.keys() n = self.__map.lastw try: i = K.index(k.a) except ValueError: # k has never been written to explicitly # but it is maybe in a zone that was written to i = -1 for l in K[i + 1:n]: if not l._is_ptr: continue if l.base == k.a.base: continue return n return 0 # read MemoryMap and return the result as an expression: def _Mem_read(self, a, l): try: res = self.__Mem.read(a, l) except MemoryError, e: # no zone for location a; res = [top(l * 8)] if exp._endian == -1: res.reverse() P = [] cur = 0 for p in res: plen = len(p) if isinstance(p, exp) and not p._is_def: if self.csi: p = self.csi(mem(a, p.size, disp=cur)) else: p = mem(a, p.size, disp=cur) if isinstance(p, str): p = cst(Bits(p[::exp._endian], bitorder=1).int(), plen * 8) P.append(p) cur += plen return composer(P)