def get_value(history, instr): if fmt == 'S+xI': return buildExpr(op, history.read(instr.sourceReg, basicTypes.word), algebra.Literal(instr.immediate)) elif fmt == 'S+I': return buildExpr(op, history.read(instr.sourceReg, basicTypes.word), algebra.Literal(extend(instr.immediate))) elif fmt == 'f(I)': return algebra.Literal(op(instr.immediate)) elif fmt == 'F+F': return buildExpr(op, history.read(instr.fs, basicTypes.single), history.read(instr.ft, basicTypes.single), flop=True) elif fmt == '@F': if op == 'id': return history.read(instr.fs) else: return buildExpr('@', op, history.read(instr.fs)) elif fmt == 'T<<A': return buildExpr(op, history.read(instr.targetReg, basicTypes.word), algebra.Literal(instr.shift)) elif fmt == 'S+T': return buildExpr(op, history.read(instr.sourceReg, basicTypes.word), history.read(instr.targetReg, basicTypes.word)) elif fmt == 'T<<S': return buildExpr(op, history.read(instr.targetReg, basicTypes.word), history.read(instr.sourceReg, basicTypes.word)) raise Error("Bad format")
def subLookup(self, fmt, base, address, others=[]): """Recursively find data at the given address from the start of a type""" if isinstance(base.type, basicTypes.Array): spacing = self.getSize(base.type.pointedType) index = algebra.Literal(address // spacing) canIndex = True for o in others: if (isinstance(o, algebra.Expression) and o.op == '*' and o.constant and o.constant.value == spacing): index = buildExpr( '+', index, algebra.Expression.arithmeticMerge('*', o.args)) else: canIndex = False break if canIndex: element = buildExpr('[', base, index) if basicTypes.isIndexable(base.type.pointedType): return self.subLookup(fmt, element, address % spacing) else: return element else: return buildExpr( '@', fmt, algebra.Expression.arithmeticMerge( '+', [base, algebra.Literal(address)] + others)) parentStruct = None if isinstance(base.type, basicTypes.Pointer): parentStruct = base.type.pointedType elif isinstance(base.type, str): parentStruct = base.type if parentStruct and parentStruct in self.bindings['structs']: members = self.bindings['structs'][parentStruct].members try: bestOffset = max(x for x in members if x <= address) except ValueError: # nothing less pass else: newBase = buildExpr('.', base, algebra.Symbol(*members[bestOffset])) if address < bestOffset + self.getSize(newBase.type): if basicTypes.isIndexable(newBase.type): return self.subLookup(fmt, newBase, address - bestOffset, others) if not others: #TODO account for reading the lower short of a word, etc. return newBase if others: return buildExpr( '@', fmt, algebra.arithmeticMerge( '+', [base, algebra.Literal(address)] + others)) else: return buildExpr( '.', base, algebra.Symbol( '{}_{:#x}'.format(basicTypes.getCode(fmt), address), fmt))
def foo(instr, history): if instr.sourceReg == Register.SP: return InstrResult.register, history.write(basicTypes.Stack(extend(instr.immediate)), history.read(instr.targetReg, datatype)) else: dest = history.lookupAddress(datatype, buildExpr('+', history.read(instr.sourceReg, basicTypes.address), algebra.Literal(extend(instr.immediate)))) return InstrResult.write, history.read(instr.targetReg, dest.type), dest
def foo(instr, history): if instr.sourceReg == Register.SP: #TODO account for more general reads (ie, just the lower bytes of a word) value = history.read(basicTypes.Stack(extend(instr.immediate)), datatype) else: address = buildExpr('+', history.read(instr.sourceReg, basicTypes.address), algebra.Literal(extend(instr.immediate))) value = history.lookupAddress(datatype, address) return InstrResult.register, history.write(instr.targetReg, value)
def __init__(self, bindings, args=[]): self.states = defaultdict(list) self.bindings = bindings self.argList = [] #arguments beyond the given ones self.now = Context([Branch()]) self.write(Register.R0, algebra.Literal(0)) self.write(Register.SP, algebra.Symbol('SP')) self.write(Register.RA, algebra.Symbol('RA')) self.write(SpecialRegister.Compare, algebra.Symbol('bad_CC')) for reg, name, fmt in args: showName = name if name else VariableHistory.getName(reg) self.argList.append(reg) self.write(reg, algebra.Symbol(showName, fmt))
def read(self, var, fmt=basicTypes.unknown): """Retrive (an appropriate representation of) the value in a register and track its usage var should be a register or Stack() object Depending on the expected format, the stored value may be altered substantially """ if var == Register.R0: #zero is zero, shouldn't remember type info return algebra.Literal(0) if var in self.states: uncertain = False for st in reversed(self.states[var]): if self.now.implies( st.context)[0]: # this state definitely occurred if uncertain: st.explicit = True break else: if isinstance(st.value, algebra.Literal): if isinstance(fmt, basicTypes.EnumType): st.value = self.getEnumValue( fmt, st.value.value) elif basicTypes.isIndexable(fmt): st.value = self.lookupAddress(fmt, st.value) elif st.value.type in [ basicTypes.unknown, basicTypes.bad ]: st.value.type = fmt return st.value elif self.now.isCompatibleWith(st.context): st.explicit = True uncertain = True return algebra.Symbol(VariableHistory.getName(var), fmt) else: symName = VariableHistory.getName(var) if VariableHistory.couldBeArg(var): self.argList.append(var) symName = 'arg_' + symName self.states[var].append( VariableState(self.getName(var), algebra.Symbol(symName, fmt), self.now)) return self.states[var][-1].value