/** * Get the statement at a specific label. If there is no statement stored, attempts to disassemble * the instruction at the label's virtual address. If the address is outside of the file area, * logs an error and returns a Halt statement by default. * * @param label The label for which to get the statement * @return The statement object at label. */ public final RTLStatement getStatement(RTLLabel label) { if (!statementMap.containsKey(label)) { AbsoluteAddress address = label.getAddress(); Instruction instr = getInstruction(address); // If we did not get an instruction, add an artificial Halt for recovery if (instr == null) { RTLHalt halt = new RTLHalt(); halt.setLabel(label); putStatement(halt); logger.error("ERROR: Replacing unknown instruction with HALT."); if (Options.debug.getValue()) throw new DisassemblyException("Disassembly failed at " + address); } else { try { StatementSequence seq = arch.getRTLEquivalent(address, instr); for (RTLStatement s : seq) { putStatement(s); } } catch (Exception e) { logger.error("Error during translation of instruction to IL"); e.printStackTrace(); RTLStatement skip = new RTLSkip(); skip.setLabel(label); skip.setNextLabel(new RTLLabel(new AbsoluteAddress(address.getValue() + 1))); putStatement(skip); } assert statementMap.containsKey(label) : "Disassembly did not produce label: " + label; } } return statementMap.get(label); }
/** * Stores a statement in the program. If a statement already exists with the same label, it is * replaced. * * @param stmt The statement to be stored. Has to contain a proper label. */ public final void putStatement(RTLStatement stmt) { RTLStatement existing = statementMap.get(stmt.getLabel()); if (existing != null) { if (existing.equals(stmt)) return; logger.debug("Replacing statement at " + stmt.getLabel()); } statementMap.put(stmt.getLabel(), stmt); }
/* * @see org.jakstab.analysis.ConfigurableProgramAnalysis#post(org.jakstab.analysis.AbstractState, org.jakstab.analysis.StateTransformer, org.jakstab.analysis.Precision) */ @Override public Set<AbstractState> post(final AbstractState state, CFAEdge cfaEdge, Precision precision) { final RTLStatement statement = (RTLStatement) cfaEdge.getTransformer(); final ValuationState iState = (ValuationState) state; return Collections.singleton( statement.accept( new DefaultStatementVisitor<AbstractState>() { @Override protected AbstractState visitDefault(RTLStatement stmt) { return state; } @Override public AbstractState visit(RTLVariableAssignment stmt) { ValuationState post = new ValuationState(iState); Writable lhs = stmt.getLeftHandSide(); RTLExpression rhs = stmt.getRightHandSide(); AbstractDomainElement evaledRhs = iState.abstractEval(rhs); // Check for stackpointer alignment assignments (workaround for gcc compiled files) RTLVariable sp = Program.getProgram().getArchitecture().stackPointer(); if (lhs.equals(sp) && rhs instanceof RTLOperation) { RTLOperation op = (RTLOperation) rhs; if (op.getOperator().equals(Operator.AND) && op.getOperands()[0].equals(sp) && op.getOperands()[1] instanceof RTLNumber) { evaledRhs = iState.getVariableValue(sp); logger.warn("Ignoring stackpointer alignment at " + stmt.getAddress()); } } post.setVariableValue((RTLVariable) lhs, evaledRhs); return post; } @Override public AbstractState visit(RTLMemoryAssignment stmt) { ValuationState post = new ValuationState(iState); RTLMemoryLocation m = stmt.getLeftHandSide(); RTLExpression rhs = stmt.getRightHandSide(); AbstractDomainElement evaledRhs = iState.abstractEval(rhs); AbstractDomainElement evaledAddress = iState.abstractEval(m.getAddress()); post.setMemoryValue(evaledAddress, m.getBitWidth(), evaledRhs); return post; } @Override public AbstractState visit(RTLAssume stmt) { ValuationState post = new ValuationState(iState); RTLExpression assumption = stmt.getAssumption(); // TODO: implement assume if (assumption instanceof RTLOperation) { RTLOperation op = (RTLOperation) assumption; switch (op.getOperator()) { case UNSIGNED_LESS_OR_EQUAL: RTLExpression lhs = op.getOperands()[0]; RTLExpression rhs = op.getOperands()[1]; IntervalElement evaledLhs = (IntervalElement) iState.abstractEval(lhs); IntervalElement evaledRhs = (IntervalElement) iState.abstractEval(rhs); if (evaledRhs.getLeft() >= 0) { IntervalElement uLessInt = new IntervalElement( evaledRhs.getRegion(), 0, evaledRhs.getRight(), 1, evaledLhs.getBitWidth()); // TODO: Implement meet for interval elements for optimal result // uLessInt = uLessInt.meet(evaledLhs); // if uLessInt.isBot() return Collections.emptySet(); // cheap but sound solution for now: only use new interval if it has less // elements if (uLessInt.size() < evaledLhs.size()) { if (lhs instanceof RTLVariable) { post.setVariableValue((RTLVariable) lhs, uLessInt); } else if (lhs instanceof RTLMemoryLocation) { RTLMemoryLocation m = (RTLMemoryLocation) lhs; AbstractDomainElement evaledAddress = iState.abstractEval(m.getAddress()); post.setMemoryValue(evaledAddress, m.getBitWidth(), uLessInt); } } } break; default: // nothing } } return post; } @Override public AbstractState visit(RTLAlloc stmt) { ValuationState post = new ValuationState(iState); Writable lhs = stmt.getPointer(); MemoryRegion newRegion; if (stmt.getAllocationName() != null) { newRegion = MemoryRegion.create(stmt.getAllocationName()); } else { // TODO: Detect whether this allocation is unique to allow strong updates newRegion = MemoryRegion.createAsSummary("alloc" + stmt.getLabel()); } IntervalElement basePointer = new IntervalElement(newRegion, ExpressionFactory.createNumber(0, 32)); if (lhs instanceof RTLVariable) { post.setVariableValue((RTLVariable) lhs, basePointer); } else { RTLMemoryLocation m = (RTLMemoryLocation) lhs; AbstractDomainElement evaledAddress = iState.abstractEval(m.getAddress()); post.setMemoryValue(evaledAddress, m.getBitWidth(), basePointer); } return post; } @Override public AbstractState visit(RTLHavoc stmt) { ValuationState post = new ValuationState(iState); // Only create a single state with the havoc range, since this analysis // is not path sensitive post.setVariableValue( stmt.getVariable(), // new IntervalElement(ExpressionFactory.getInstance().createNumber(0, // stmt.getVariable().getBitWidth()), // (RTLNumber)stmt.getMaximum())); new IntervalElement( MemoryRegion.GLOBAL, 0, ((RTLNumber) stmt.getMaximum()).longValue(), 1, stmt.getVariable().getBitWidth())); return post; } @Override public AbstractState visit(RTLUnknownProcedureCall stmt) { ValuationState post = new ValuationState(iState); for (RTLVariable var : stmt.getDefinedVariables()) { post.setVariableValue(var, IntervalElement.getTop(var.getBitWidth())); } post.setMemoryValue( IntervalElement.getTop( Program.getProgram().getArchitecture().getAddressBitWidth()), 32, IntervalElement.getTop(32)); return post; } })); }