diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/util/SymbolicPropogator.java b/Ghidra/Features/Base/src/main/java/ghidra/program/util/SymbolicPropogator.java index b31ce0c701..6e3ae287be 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/program/util/SymbolicPropogator.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/program/util/SymbolicPropogator.java @@ -36,8 +36,7 @@ import ghidra.program.model.scalar.Scalar; import ghidra.program.model.symbol.*; import ghidra.util.BigEndianDataConverter; import ghidra.util.Msg; -import ghidra.util.exception.AssertException; -import ghidra.util.exception.CancelledException; +import ghidra.util.exception.*; import ghidra.util.task.TaskMonitor; public class SymbolicPropogator { @@ -65,7 +64,7 @@ public class SymbolicPropogator { protected boolean hitCodeFlow = false; // no branching so far private boolean debug = false; - + private boolean recordStartEndState = false; // record the start/end values for registers at each instruction private long pointerMask; @@ -74,15 +73,15 @@ public class SymbolicPropogator { /* maximum exact instructions to execute, (ie. a run of shift instructions */ protected static final int MAX_EXACT_INSTRUCTIONS = 100; - + /* indicates not currently executing code that has already been followed */ - private static final int NOT_CONTINUING_CURRRENTLY = -1; + private static final int NOT_CONTINUING_CURRRENTLY = -1; /* maximum instructions along to continue along a path that has been followed already */ - private static final int MAX_EXTRA_INSTRUCTION_FLOW = 16; + private static final int MAX_EXTRA_INSTRUCTION_FLOW = 16; private static int LRU_SIZE = 4096; - + /** NOTE: most of these caches are to reduce contention on the program lock to enable better threading. * Once the lock contention has been reduced, these can be cut back or removed. */ @@ -97,7 +96,7 @@ public class SymbolicPropogator { // Cache instructions looked up by containing Map instructionContainingCache = new LRUMap<>(LRU_SIZE); - + // Cache of functions looked up Map functionAtCache = new LRUMap<>(LRU_SIZE); @@ -114,7 +113,7 @@ public class SymbolicPropogator { * */ public SymbolicPropogator(Program program) { - this(program, true); + this (program, true); } /** @@ -131,7 +130,7 @@ public class SymbolicPropogator { */ public SymbolicPropogator(Program program, boolean recordStartEndState) { this.program = program; - + this.recordStartEndState = recordStartEndState; Language language = program.getLanguage(); @@ -192,7 +191,7 @@ public class SymbolicPropogator { } context.flowToAddress(Address.NO_ADDRESS, startAddr); - + // copy any current registers with values into the context Register[] regWithVals = program.getProgramContext().getRegistersWithValues(); for (Register regWithVal : regWithVals) { @@ -246,11 +245,11 @@ public class SymbolicPropogator { if (space.isOverlaySpace()) { OverlayAddressSpace ovSpace = (OverlayAddressSpace) space; AddressSpace baseSpace = ovSpace.getPhysicalSpace(); - if (!(baseSpace.equals(defaultDataSpace) || baseSpace.equals(defaultSpace))) { + if (!( baseSpace.equals(defaultDataSpace) || baseSpace.equals(defaultSpace) ) ) { continue; } } - else if (!(space.equals(defaultDataSpace) || space.equals(defaultSpace))) { + else if (!( space.equals(defaultDataSpace) || space.equals(defaultSpace) ) ) { continue; } @@ -274,8 +273,7 @@ public class SymbolicPropogator { Language language = program.getLanguage(); ProgramContext newValueContext = new ProgramContextImpl(language); ProgramContext newSpaceContext = new ProgramContextImpl(language); - VarnodeContext newContext = - new VarnodeContext(program, newValueContext, newSpaceContext, recordStartEndState); + VarnodeContext newContext = new VarnodeContext(program, newValueContext, newSpaceContext, recordStartEndState); newContext.setDebug(debug); programContext = newValueContext; @@ -436,18 +434,15 @@ public class SymbolicPropogator { context.flowEnd(addr); } - record SavedFlowState(VarnodeContext vContext, FlowType flowType, Address source, - Address destination, + record SavedFlowState(VarnodeContext vContext, FlowType flowType, Address source, Address destination, int pcodeIndex, int continueAfterHittingFlow) { - public SavedFlowState(VarnodeContext vContext, FlowType flowType, Address source, - Address destination, + public SavedFlowState(VarnodeContext vContext, FlowType flowType, Address source, Address destination, int continueAfterHittingFlow) { - this(vContext, flowType, source, destination, 0, continueAfterHittingFlow); + this(vContext,flowType,source,destination,0,continueAfterHittingFlow); } - - public SavedFlowState(VarnodeContext vContext, FlowType flowType, Address source, - Address destination, + + public SavedFlowState(VarnodeContext vContext, FlowType flowType, Address source, Address destination, int pcodeIndex, int continueAfterHittingFlow) { this.vContext = vContext; this.flowType = flowType; @@ -457,16 +452,17 @@ public class SymbolicPropogator { this.continueAfterHittingFlow = continueAfterHittingFlow; vContext.pushMemState(pcodeIndex != 0); } - + public boolean isContinueAfterHittingFlow() { return continueAfterHittingFlow != NOT_CONTINUING_CURRRENTLY; } - + public void restoreState() { vContext.popMemState(); } } + // Used to stop runs of the same exact instruction protected int lastFullHashCode = 0; // full byte hash code protected int lastInstrCode = -1; // last instruction prototype hashcode @@ -488,14 +484,13 @@ public class SymbolicPropogator { throws CancelledException { visitedBody = new AddressSet(); AddressSet conflicts = new AddressSet(); - + // Locations that were jump and are now call targets and might be on saved future flows HashSet
doNotFlowTo = new HashSet<>(); // prime the context stack with the entry point address Stack contextStack = new Stack<>(); - contextStack.push( - new SavedFlowState(vContext, null, fromAddr, startAddr, NOT_CONTINUING_CURRRENTLY)); + contextStack.push(new SavedFlowState(vContext, null, fromAddr, startAddr, NOT_CONTINUING_CURRRENTLY)); canceled = false; // only stop flowing on unknown bad calls when the stack depth could be unknown @@ -503,7 +498,7 @@ public class SymbolicPropogator { .getDefaultCallingConvention() .getExtrapop() == PrototypeModel.UNKNOWN_EXTRAPOP; - HashMap> visitedMap = new HashMap<>(); + HashMap> visitedMap = new HashMap<>(); while (!contextStack.isEmpty()) { monitor.checkCancelled(); if (canceled) { @@ -519,19 +514,18 @@ public class SymbolicPropogator { int pcodeStartIndex = nextFlow.pcodeIndex; int continueAfterHittingFlow = nextFlow.continueAfterHittingFlow; nextFlow.restoreState(); - + if (flowType != null) { // if call flow, is inlined call, only inlined flows are pushed onto the flow stack // if (flowType.isCall()) { AddressSet savedBody = visitedBody; Function func = getFunctionAt(nextAddr); - flowConstants(nextFlow.source, nextAddr, func.getBody(), eval, vContext, - monitor); + flowConstants(nextFlow.source, nextAddr, func.getBody(), eval, vContext, monitor); visitedBody = savedBody; continue; } - + // if jump flow, make sure it isn't jumping to another function // if (flowType.isJump() && !flowType.isConditional()) { @@ -540,13 +534,12 @@ public class SymbolicPropogator { if (func != null && !func.getBody().contains(startAddr)) { // handle jump as if it were a call vContext.flowStart(nextAddr); - handleFunctionSideEffects(getInstructionAt(flowFromAddr), nextAddr, - monitor); + handleFunctionSideEffects(getInstructionAt(flowFromAddr), nextAddr, monitor); continue; } } } - + // don't follow flow if on list of jump targets that were turned into calls if (doNotFlowTo.contains(nextAddr)) { continue; @@ -568,14 +561,13 @@ public class SymbolicPropogator { visitSet = new HashSet<>(); visitedMap.put(nextAddr, visitSet); // never flowed to here, but have visited before - if (continueAfterHittingFlow == NOT_CONTINUING_CURRRENTLY && - visitedBody.contains(nextAddr)) { + if (continueAfterHittingFlow == NOT_CONTINUING_CURRRENTLY && visitedBody.contains(nextAddr)) { continueAfterHittingFlow = 0; } } visitSet.add(flowFromAddr); - + // record new flow from one basic block to another vContext.flowToAddress(fromAddr, nextAddr); @@ -589,7 +581,7 @@ public class SymbolicPropogator { // special flow start, retrieves the flow from/to saved state if there is one, and applies it // As if a mergeFuture flow had been done. vContext.flowStart(nextAddr); - + if (!visitedBody.contains(nextAddr)) { // got to a flow never been to before, turn off any continue flow behavior continueAfterHittingFlow = NOT_CONTINUING_CURRRENTLY; @@ -627,12 +619,11 @@ public class SymbolicPropogator { return visitedBody; } } - + // // apply the pcode effects // - boolean continueCurrentTrace = applyPcode(contextStack, vContext, instr, - pcodeStartIndex, continueAfterHittingFlow, monitor); + boolean continueCurrentTrace = applyPcode(contextStack, vContext, instr, pcodeStartIndex, continueAfterHittingFlow, monitor); pcodeStartIndex = 0; /* Allow evaluateContext routine to change override the flowtype of an instruction. @@ -646,7 +637,7 @@ public class SymbolicPropogator { return visitedBody; } } - + // if the instruction changed it's type to a call, need to handle the call side effects FlowType instrFlow = instr.getFlowType(); if (!originalFlowType.equals(instrFlow) && instrFlow.isCall()) { @@ -658,28 +649,26 @@ public class SymbolicPropogator { doNotFlowTo.add(target); } } - + // if already hit a flow, only continue through code until MAX_EXTRA instructions or hit a call if (visitedBody.contains(minInstrAddress) && !justPopped) { // even if second time through, run a few more instructions to see if get to a call if (continueAfterHittingFlow > NOT_CONTINUING_CURRRENTLY) { continueAfterHittingFlow++; + } else { + continueAfterHittingFlow=0; // start counting, hit body } - else { - continueAfterHittingFlow = 0; // start counting, hit body - } - if (continueAfterHittingFlow >= MAX_EXTRA_INSTRUCTION_FLOW || - instrFlow.isCall()) { + if (continueAfterHittingFlow >= MAX_EXTRA_INSTRUCTION_FLOW || instrFlow.isCall()) { break; } } // add this instruction to processed body set visitedBody.addRange(minInstrAddress, maxAddr); - + justPopped = false; - + vContext.flowEnd(minInstrAddress); - + // if already hit a flow, only continue until a call is hit, // TODO: this could be changed to some number of instructions // if (continueAfterHittingFlow > 0 && (instrFlow.isCall())) { @@ -699,7 +688,7 @@ public class SymbolicPropogator { nextAddr = fallThru; } } - + } //System.out.println(startAddr + " = " + instructionCount + ", " + continueCount); @@ -776,12 +765,12 @@ public class SymbolicPropogator { if (instructionAtCache.containsKey(addr)) { return null; } - + instr = program.getListing().getInstructionAt(addr); cacheInstruction(addr, instr); return instr; } - + public Function getFunctionAt(Address addr) { Function func = functionAtCache.get(addr); if (func != null) { @@ -790,7 +779,7 @@ public class SymbolicPropogator { if (functionAtCache.containsKey(addr)) { return null; } - + func = program.getFunctionManager().getFunctionAt(addr); functionAtCache.put(addr, func); return func; @@ -848,9 +837,7 @@ public class SymbolicPropogator { * @param monitor to cancel * @return true to to continue this instruction path, false otherwise */ - private boolean applyPcode(Stack contextStack, VarnodeContext vContext, - Instruction instruction, int startIndex, int continueAfterHittingFlow, - TaskMonitor monitor) { + private boolean applyPcode(Stack contextStack, VarnodeContext vContext, Instruction instruction, int startIndex, int continueAfterHittingFlow, TaskMonitor monitor) { Address nextAddr = null; if (instruction == null) { @@ -866,7 +853,8 @@ public class SymbolicPropogator { } Address minInstrAddress = instruction.getMinAddress(); - if (debug) { + if (debug) + { Msg.info(this, minInstrAddress + " " + instruction + " " + startIndex); } @@ -905,21 +893,19 @@ public class SymbolicPropogator { if (in[0].isAddress()) { AddressSpace addressSpace = in[0].getAddress().getAddressSpace(); // if not address mapped, or no register defined there - if (!addressSpace.hasMappedRegisters() || - program.getRegister(in[0]) == null) { - makeReference(vContext, instruction, Reference.MNEMONIC, in[0], - null, RefType.READ, ptype, true, monitor); + if (!addressSpace.hasMappedRegisters() || program.getRegister(in[0]) == null) { + makeReference(vContext, instruction, Reference.MNEMONIC, in[0], + null, RefType.READ, ptype, true, monitor); } } vContext.copy(out, in[0], mustClearAll, evaluator); break; - + case PcodeOp.SEGMENTOP: // treat like a copy for now, and extend the size as if segment had been applied Varnode vval = context.getValue(in[2], evaluator); - if (context.isSymbolicSpace(vval.getSpace())) { - vval = vContext.createVarnode(vval.getOffset(), vval.getSpace(), - out.getSize()); + if (context.isSymbolicSpace(vval.getSpace())) { + vval = vContext.createVarnode(vval.getOffset(), vval.getSpace(), out.getSize()); } vContext.putValue(out, vval, mustClearAll); break; @@ -930,15 +916,14 @@ public class SymbolicPropogator { val2 = vContext.getValue(in[1], evaluator); if (val1 != null && val2 != null) { suspectOffset = vContext.isSuspectConstant(val2); - + vt = vContext.getVarnode(in[0], val2, out.getSize(), evaluator); - + // TODO: may need to use DATA refType in some cases - + if (vt != null) { - addLoadStoreReference(vContext, instruction, ptype, vt, in[0], - in[1], - RefType.READ, suspectOffset == false, monitor); + addLoadStoreReference(vContext, instruction, ptype, vt, in[0], in[1], + RefType.READ, suspectOffset==false, monitor); // If vt is a bad varnode (bad space, no memory, no value in varnode) you won't get a value memVal = vContext.getValue(vt, evaluator); } @@ -954,10 +939,10 @@ public class SymbolicPropogator { suspectOffset = vContext.isSuspectConstant(offs); out = getStoredLocation(vContext, in[0], offs, in[2]); } - + // TODO: may need to use DATA refType in some cases addLoadStoreReference(vContext, instruction, ptype, out, in[0], in[1], - RefType.WRITE, suspectOffset == false, monitor); + RefType.WRITE, suspectOffset==false, monitor); val3 = vContext.getValue(in[2], null); @@ -971,14 +956,14 @@ public class SymbolicPropogator { val1 = vContext.getValue(in[0], evaluator); if (val1 != null) { suspectOffset = vContext.isSuspectConstant(val1); - + vt = getConstantOrExternal(vContext, minInstrAddress, val1); if (vt != null) { makeReference(vContext, instruction, -1, vt, null, instruction.getFlowType(), ptype, !suspectOffset, monitor); } } - + // even if we don't know the destination, branch to any jump // references already on the branch indirect vContext.propogateResults(true); @@ -1005,52 +990,50 @@ public class SymbolicPropogator { Function func = null; val1 = in[0]; if (ptype == PcodeOp.CALLIND) { - val1 = vContext.getValue(val1, evaluator); + val1 = vContext.getValue(val1, evaluator); - if (val1 != null) { - // TODO: Revisit handling of external functions... - - if (vContext.isConstant(val1)) { - suspectOffset = vContext.isSuspectConstant(val1); - // indirect target - assume single code space (same as instruction) - target = instruction.getAddress() - .getNewTruncatedAddress(val1.getOffset(), true); - } - else if (val1.isAddress()) { - // TODO: could this also occur if a memory location was copied ?? - // unable to resolve indirect value - can we trust stored pointer? - // if not, we must rely on reference to function. - target = resolveFunctionReference(val1.getAddress()); - } - else if (vContext.isExternalSpace(val1.getSpace())) { - target = val1.getAddress(); - } - // if the value didn't get changed, then the real value isn't in here, don't make a reference - if (target != null) { - Reference[] refs = instruction.getReferencesFrom(); - // make sure we aren't replacing a read ref with a call to the same place - if (refs.length <= 0 || - !refs[0].getToAddress().equals(target)) { - - Address oldTarget = target; - target = - makeReference(vContext, instruction, Reference.MNEMONIC, + if (val1 != null) { + // TODO: Revisit handling of external functions... + + if (vContext.isConstant(val1)) { + suspectOffset = vContext.isSuspectConstant(val1); + // indirect target - assume single code space (same as instruction) + target = instruction.getAddress() + .getNewTruncatedAddress(val1.getOffset(), true); + } + else if (val1.isAddress()) { + // TODO: could this also occur if a memory location was copied ?? + // unable to resolve indirect value - can we trust stored pointer? + // if not, we must rely on reference to function. + target = resolveFunctionReference(val1.getAddress()); + } + else if (vContext.isExternalSpace(val1.getSpace())) { + target = val1.getAddress(); + } + // if the value didn't get changed, then the real value isn't in here, don't make a reference + if (target != null) { + Reference[] refs = instruction.getReferencesFrom(); + // make sure we aren't replacing a read ref with a call to the same place + if (refs.length <= 0 || + !refs[0].getToAddress().equals(target)) { + + Address oldTarget = target; + target = makeReference(vContext, instruction, Reference.MNEMONIC, // Use target in case location has shifted (external...) target.getAddressSpace().getSpaceID(), target.getAddressableWordOffset(), val1.getSize(), null, - instruction.getFlowType(), ptype, !suspectOffset, - false, monitor); - if (target == null) { - // Target was nulled out, restore old target. - // Need to handle function call side-effects even if didn't make a reference - // The target can be changed by makeReference(), but if it is nulled out, then - // it indicates the reference was already made. - target = oldTarget; + instruction.getFlowType(), ptype, !suspectOffset, false, monitor); + if (target == null) { + // Target was nulled out, restore old target. + // Need to handle function call side-effects even if didn't make a reference + // The target can be changed by makeReference(), but if it is nulled out, then + // it indicates the reference was already made. + target = oldTarget; + } } } } - } } else { // CALL will always provide address @@ -1095,12 +1078,9 @@ public class SymbolicPropogator { if (func != null && func.isInline()) { // push fallthru pcodeIndex after call - contextStack.push(new SavedFlowState(vContext, FALL_THROUGH, - minInstrAddress, func.getEntryPoint(), pcodeIndex + 1, - continueAfterHittingFlow)); + contextStack.push(new SavedFlowState(vContext, FALL_THROUGH, minInstrAddress, func.getEntryPoint(), pcodeIndex+1 , continueAfterHittingFlow)); // push the call so it will happen first - contextStack.push(new SavedFlowState(vContext, UNCONDITIONAL_CALL, - minInstrAddress, func.getEntryPoint(), continueAfterHittingFlow)); + contextStack.push(new SavedFlowState(vContext, UNCONDITIONAL_CALL, minInstrAddress, func.getEntryPoint(), continueAfterHittingFlow)); return false; } handleFunctionSideEffects(instruction, target, monitor); @@ -1114,7 +1094,7 @@ public class SymbolicPropogator { injected = true; continue; } - + break; // for callother, could be an interrupt, need to look at it like a call @@ -1153,8 +1133,7 @@ public class SymbolicPropogator { vContext.propogateResults(true); nextAddr = minInstrAddress.getAddressSpace() .getOverlayAddress(in[0].getAddress()); - contextStack.push(new SavedFlowState(vContext, UNCONDITIONAL_JUMP, - minInstrAddress, nextAddr, continueAfterHittingFlow)); + contextStack.push(new SavedFlowState(vContext, UNCONDITIONAL_JUMP, minInstrAddress, nextAddr, continueAfterHittingFlow)); return false; case PcodeOp.CBRANCH: @@ -1175,8 +1154,7 @@ public class SymbolicPropogator { if (condition != null) { longVal1 = vContext.getConstant(condition, null); - } - else { + } else { // couldn't find the condition, so arbitrary which way to go longVal1 = Long.valueOf(0); // do fallthru first } @@ -1192,10 +1170,8 @@ public class SymbolicPropogator { // only go forwards in sequence, backwards could be a loop if (sequenceOffset > 0) { if (followFalse) { - contextStack.push(new SavedFlowState(vContext, FALL_THROUGH, - minInstrAddress, - minInstrAddress, pcodeIndex + 1, - continueAfterHittingFlow)); + contextStack.push(new SavedFlowState(vContext, FALL_THROUGH, minInstrAddress, + minInstrAddress, pcodeIndex+1, continueAfterHittingFlow)); } pcodeIndex += sequenceOffset - 1; } @@ -1208,34 +1184,29 @@ public class SymbolicPropogator { else { // memory branch if (followFalse) { // push follow false first - contextStack.push(new SavedFlowState(vContext, FALL_THROUGH, - minInstrAddress, - minInstrAddress, pcodeIndex + 1, continueAfterHittingFlow)); + contextStack.push(new SavedFlowState(vContext, FALL_THROUGH, minInstrAddress, + minInstrAddress, pcodeIndex+1, continueAfterHittingFlow)); } - + // pcode addresses are raw addresses, make sure address is in same instruction space nextAddr = minInstrAddress.getAddressSpace() .getOverlayAddress(in[0].getAddress()); - contextStack.push( - new SavedFlowState(vContext, CONDITIONAL_JUMP, minInstrAddress, - nextAddr, continueAfterHittingFlow)); - + contextStack.push(new SavedFlowState(vContext, CONDITIONAL_JUMP, minInstrAddress, + nextAddr, continueAfterHittingFlow)); + pcodeIndex = ops.length; // break out of the processing return false; // don't keep going } - } - else { + } else { if (internalBranch) { // handle internal branch int sequenceOffset = (int) in[0].getOffset(); // only go forwards in sequence, backwards could be a loop - if (sequenceOffset > 0) { + if (sequenceOffset > 0) { int internalIndex = pcodeIndex + sequenceOffset; if (followFalse) { - contextStack.push(new SavedFlowState(vContext, FALL_THROUGH, - minInstrAddress, - minInstrAddress, internalIndex, - continueAfterHittingFlow)); + contextStack.push(new SavedFlowState(vContext, FALL_THROUGH, minInstrAddress, + minInstrAddress, internalIndex, continueAfterHittingFlow)); } } else if (!followFalse) { @@ -1249,8 +1220,7 @@ public class SymbolicPropogator { // push follow false first nextAddr = minInstrAddress.getAddressSpace() .getOverlayAddress(in[0].getAddress()); - contextStack.push(new SavedFlowState(vContext, CONDITIONAL_JUMP, - minInstrAddress, + contextStack.push(new SavedFlowState(vContext, CONDITIONAL_JUMP, minInstrAddress, nextAddr, continueAfterHittingFlow)); } } @@ -1282,7 +1252,7 @@ public class SymbolicPropogator { case PcodeOp.INT_SEXT: if (in[0].isAddress()) { - makeReference(vContext, instruction, Reference.MNEMONIC, in[0], + makeReference(vContext, instruction, Reference.MNEMONIC, in[0], null, RefType.READ, ptype, true, monitor); } val1 = vContext.extendValue(out, in, true, evaluator); @@ -1304,7 +1274,7 @@ public class SymbolicPropogator { val1 = val2 = vContext.createConstantVarnode(v, val1.getSize()); } } - + result = vContext.add(val1, val2, evaluator); vContext.putValue(out, result, mustClearAll); break; @@ -1365,7 +1335,7 @@ public class SymbolicPropogator { val2 = vContext.getValue(in[1], false, evaluator); longVal1 = vContext.getConstant(val1, evaluator); longVal2 = vContext.getConstant(val2, evaluator); - if (longVal1 != null && longVal2 != null) { + if (longVal1 != null && longVal2 != null) { lresult = longVal1 ^ longVal2; result = vContext.createConstantVarnode(lresult, val1.getSize()); } @@ -1400,7 +1370,7 @@ public class SymbolicPropogator { longVal1 = vContext.getConstant(val1, evaluator); longVal2 = vContext.getConstant(val2, evaluator); if (longVal1 != null && longVal2 != null) { - lresult = longVal1 >> longVal2; + lresult = longVal1 >> longVal2 ; result = vContext.createConstantVarnode(lresult, val1.getSize()); } vContext.putValue(out, result, mustClearAll); @@ -1492,7 +1462,7 @@ public class SymbolicPropogator { longVal2 = vContext.getConstant(val2, evaluator); if (val1 != null && longVal2 != null) { long subbyte = 8 * longVal2; - + if (vContext.isSymbol(val1) & subbyte == 0 && out.getSize() == instruction.getAddress().getPointerSize()) { // assume the subpiece is just downcasting to be used as a pointer, just ignore, since this is already an offset, and shouldn't matter. @@ -1666,15 +1636,14 @@ public class SymbolicPropogator { } return vt; } - - private Varnode getStoredLocation(VarnodeContext vContext, Varnode space, Varnode offset, - Varnode size) { + + private Varnode getStoredLocation(VarnodeContext vContext, Varnode space, Varnode offset, Varnode size) { Varnode out = null; if (offset == null) { return null; } - + out = vContext.getVarnode(space, offset, size.getSize(), evaluator); return out; @@ -1711,7 +1680,7 @@ public class SymbolicPropogator { context.putValue(varnode, context.createBadVarnode(), false); } } - + // clear out any killed by call variables Varnode killedVarnodes[] = context.getKilledVarnodes(targetFunc); if (killedVarnodes != null) { @@ -1725,7 +1694,7 @@ public class SymbolicPropogator { if (targetFunc != null && targetFunc.isInline()) { return; } - + if (targetFunc != null && targetFunc.hasNoReturn()) { context.propogateResults(false); } @@ -1763,13 +1732,13 @@ public class SymbolicPropogator { } } else if (purge != 0) { - Varnode purgeVar = context.createConstantVarnode(purge, outStack.getSize()); - Varnode val1 = context.getValue(outStack, true, evaluator); - Varnode val2 = null; - if (val1 != null) { - val2 = context.add(val1, purgeVar, evaluator); - } - context.putValue(outStack, val2, false); + Varnode purgeVar = context.createConstantVarnode(purge, outStack.getSize()); + Varnode val1 = context.getValue(outStack, true, evaluator); + Varnode val2 = null; + if (val1 != null) { + val2 = context.add(val1, purgeVar, evaluator); + } + context.putValue(outStack, val2, false); } } } @@ -1929,8 +1898,7 @@ public class SymbolicPropogator { return null; } - private PcodeOp[] checkSegmentCallOther(InjectPayload payload, Instruction instr, Varnode[] ins, - Varnode out) { + private PcodeOp[] checkSegmentCallOther(InjectPayload payload, Instruction instr, Varnode[] ins, Varnode out) { if (!payload.getName().equals("segment_pcode")) { return null; } @@ -1941,7 +1909,7 @@ public class SymbolicPropogator { if (vval == null) { return null; } - if (!context.isSymbolicSpace(vval.getSpace())) { + if (!context.isSymbolicSpace(vval.getSpace())) { return null; } if (!context.isRegister(ins[1])) { @@ -2078,7 +2046,7 @@ public class SymbolicPropogator { conv = program.getCompilerSpec().getDefaultCallingConvention(); int extraParamIndex = -1; - + Parameter[] params = new Parameter[0]; SourceType signatureSource = SourceType.DEFAULT; if (func != null) { @@ -2091,8 +2059,7 @@ public class SymbolicPropogator { // not being set Namespace parentNamespace = func.getParentNamespace(); if (parentNamespace != null && parentNamespace instanceof GhidraClass) { - PrototypeModel thisConv = program.getCompilerSpec() - .getCallingConvention(CompilerSpec.CALLING_CONVENTION_thiscall); + PrototypeModel thisConv = program.getCompilerSpec().getCallingConvention(CompilerSpec.CALLING_CONVENTION_thiscall); if (conv != thisConv) { extraParamIndex = params.length; } @@ -2120,7 +2087,7 @@ public class SymbolicPropogator { DataType dataType = p.getDataType(); if (!(dataType instanceof Pointer || - (dataType instanceof TypeDef && ((TypeDef) dataType).isPointer()))) { + (dataType instanceof TypeDef && ((TypeDef) dataType).isPointer()))) { // wasn't a pointer immediately if (checkForParamPointerRefs) { continue; @@ -2143,29 +2110,26 @@ public class SymbolicPropogator { } if (extraParamIndex != -1) { // TODO Should cache the arg locations for each convention - VariableStorage var = - conv.getArgLocation(extraParamIndex, null, pointerSizedDT, program, - false); + VariableStorage var = conv.getArgLocation(extraParamIndex, null, pointerSizedDT, program); // can't trust stack storage if params aren't known if (!var.isStackStorage()) { createVariableStorageReference(instruction, varnodeContext, monitor, conv, var, - null, callOffset); + null, callOffset); } } } else if (!checkForParamPointerRefs) { // loop through potential params, since none defined, to find a potential pointer // only check the first seven param locations, if don't have a signature - for (int pi = 0; pi < 8; pi++) { + for (int pi=0; pi < 8; pi++) { // TODO Should cache the arg locations for each convention - VariableStorage var = - conv.getArgLocation(pi, null, pointerSizedDT, program, func.hasVarArgs()); + VariableStorage var = conv.getArgLocation(pi, null, pointerSizedDT, program); // can't trust stack storage if params aren't known if (var.isStackStorage()) { continue; } createVariableStorageReference(instruction, varnodeContext, monitor, conv, var, - null, callOffset); + null, callOffset); } } } @@ -2187,8 +2151,7 @@ public class SymbolicPropogator { return; } - createVariableStorageReference(instruction, varnodeContext, monitor, null, returnLoc, null, - 0); + createVariableStorageReference(instruction, varnodeContext, monitor, null, returnLoc, null, 0); } private void addLoadStoreReference(VarnodeContext vContext, Instruction instruction, @@ -2203,8 +2166,7 @@ public class SymbolicPropogator { int opIndex = findOperandWithVarnodeAssignment(instruction, assigningVarnode); if (instruction.getFlowType().isCall()) { - makeReference(vContext, instruction, opIndex, refLocation, null, reftype, pcodeType, - knownReference, monitor); + makeReference(vContext, instruction, opIndex, refLocation, null, reftype, pcodeType, knownReference, monitor); } else { int spaceID = refLocation.getSpace(); @@ -2221,7 +2183,7 @@ public class SymbolicPropogator { // TODO: This is speculative, should not be doing here // need to check if there is a memory/label at the other end, or some other // corroborating evidence very late in analysis - if (newTarget != null) { + if (newTarget != null ) { makeReference(vContext, instruction, Reference.MNEMONIC, newTarget.getAddressSpace().getSpaceID(), newTarget.getOffset(), 0, null, RefType.DATA, pcodeType, false, false, monitor); @@ -2231,8 +2193,7 @@ public class SymbolicPropogator { } } // even if this is symbolic space, give the evaluator a chance to do something with the symbolic value - makeReference(vContext, instruction, opIndex, refLocation, null, reftype, pcodeType, - knownReference, monitor); + makeReference(vContext, instruction, opIndex, refLocation, null, reftype, pcodeType, knownReference, monitor); } } @@ -2299,41 +2260,38 @@ public class SymbolicPropogator { long valueOffset = valueToStore.getOffset(); - makeReference(vContext, instruction, -1, -1, valueOffset, 0, null, RefType.DATA, - PcodeOp.STORE, + makeReference(vContext, instruction, -1, -1, valueOffset, 0, null, RefType.DATA, PcodeOp.STORE, false, false, monitor); } private void createVariableStorageReference(Instruction instruction, - VarnodeContext varnodeContext, TaskMonitor monitor, PrototypeModel conv, - VariableStorage storage, + VarnodeContext varnodeContext, TaskMonitor monitor, PrototypeModel conv, VariableStorage storage, DataType dataType, long callOffset) { - + Address lastSetAddr; BigInteger bval; - + // TODO: need to handle memory // TODO: need to handle multi-piece variables and re-assemble // - + if (storage.isStackStorage()) { if (conv == null) { return; } Varnode sVnode = storage.getFirstVarnode(); - + // translate the variable relative to the current stackpointer symbolic value Varnode stackVarnode = varnodeContext.getStackVarnode(); Varnode stackVal = varnodeContext.getValue(stackVarnode, null); if (stackVal == null) { return; } - Varnode realSPVarnode = - varnodeContext.createVarnode(stackVal.getOffset() + sVnode.getOffset(), + Varnode realSPVarnode = varnodeContext.createVarnode(stackVal.getOffset() + sVnode.getOffset(), stackVal.getSpace(), sVnode.getAddress().getAddressSpace().getPointerSize()); - + Varnode value = null; - value = varnodeContext.getValue(realSPVarnode, evaluator); + value = varnodeContext.getValue(realSPVarnode,evaluator); if (value == null) { return; } @@ -2342,23 +2300,23 @@ public class SymbolicPropogator { return; } bval = BigInteger.valueOf(value.getOffset()); - + lastSetAddr = varnodeContext.getLastSetLocation(realSPVarnode, bval); - + // TODO: What if last set location is in a delayslot? } else if (storage.isRegisterStorage()) { // TODO: need to handle compound register storage (e.g., two registers // used) Register reg = storage.getRegister(); - + // RegisterValue rval = // context.getRegisterValue(reg,instruction.getMinAddress()); RegisterValue rval = varnodeContext.getRegisterValue(reg); if (rval == null || !rval.hasValue()) { return; } - + reg = rval.getRegister(); bval = rval.getUnsignedValue(); lastSetAddr = varnodeContext.getLastSetLocation(reg, bval); @@ -2371,21 +2329,18 @@ public class SymbolicPropogator { lastSetAddr = instruction.getMaxAddress(); } } - + } else { return; } - - makeVariableStorageReference(storage, instruction, varnodeContext, monitor, callOffset, - dataType, lastSetAddr, bval); + + makeVariableStorageReference(storage, instruction, varnodeContext, monitor, callOffset, dataType, lastSetAddr, bval); } - private void makeVariableStorageReference(VariableStorage storage, Instruction instruction, - VarnodeContext varnodeContext, - TaskMonitor monitor, long callOffset, DataType dataType, Address lastSetAddr, - BigInteger bval) { - + private void makeVariableStorageReference(VariableStorage storage, Instruction instruction, VarnodeContext varnodeContext, + TaskMonitor monitor, long callOffset, DataType dataType, Address lastSetAddr, BigInteger bval) { + if (lastSetAddr == null) { lastSetAddr = instruction.getMaxAddress(); } @@ -2401,7 +2356,7 @@ public class SymbolicPropogator { if (lastSetAddr == null) { return; } - + // if the dataType is known, try to interpret it to an address given the // bytes in the storage location int knownSpaceID = -1; @@ -2430,26 +2385,23 @@ public class SymbolicPropogator { for (Reference ref : refs) { Address refAddr = ref.getToAddress(); Address addr = refAddr.getAddressSpace().getTruncatedAddress(val, true); - if (ref.getReferenceType() == RefType.PARAM && - !visitedBody.contains(ref.getFromAddress())) { + if (ref.getReferenceType() == RefType.PARAM && !visitedBody.contains(ref.getFromAddress())) { // if reference address is not in body yet, this is the first time at this location // get rid of the reference, reference could be changed to new AddressSpace or value instr.removeOperandReference(ref.getOperandIndex(), refAddr); - } - else if (refAddr.getOffset() == addr.getOffset()) { + } else if (refAddr.getOffset() == addr.getOffset()) { found = true; } } - + RefType refType = (callOffset == 0 ? RefType.DATA : RefType.PARAM); - makeReference(varnodeContext, instr, Reference.MNEMONIC, knownSpaceID, val, 0, dataType, - refType, - PcodeOp.UNIMPLEMENTED, knownReference, found, monitor); + makeReference(varnodeContext, instr, Reference.MNEMONIC, knownSpaceID, val, 0, dataType, refType, + PcodeOp.UNIMPLEMENTED, knownReference, found, monitor); } private Object getPointerDataTypeValue(DataType dataType, Address lastSetAddr, BigInteger bval) { - + int len = dataType.getLength(); byte[] byteArray = new byte[len]; @@ -2462,11 +2414,12 @@ public class SymbolicPropogator { if (len > byteArray.length) { return null; } - + Object value = dataType.getValue(buf, dataType.getDefaultSettings(), len); - + return value; - } + } + /** * get the return variable storage location for this function @@ -2601,8 +2554,7 @@ public class SymbolicPropogator { * @param monitor to cancel * @return address that was marked up, null otherwise */ - public Address makeReference(VarnodeContext varnodeContext, Instruction instruction, - int opIndex, Varnode vt, DataType dataType, RefType refType, + public Address makeReference(VarnodeContext varnodeContext, Instruction instruction, int opIndex, Varnode vt, DataType dataType, RefType refType, int pcodeop, boolean knownReference, TaskMonitor monitor) { if (!vt.isAddress() && !varnodeContext.isExternalSpace(vt.getSpace())) { if (evaluator != null) { @@ -2612,9 +2564,8 @@ public class SymbolicPropogator { } // offset must be word based to compute the reference correctly - return makeReference(varnodeContext, instruction, opIndex, vt.getSpace(), - vt.getWordOffset(), - vt.getSize(), dataType, refType, pcodeop, knownReference, false, monitor); + return makeReference(varnodeContext, instruction, opIndex, vt.getSpace(), vt.getWordOffset(), + vt.getSize(), dataType, refType, pcodeop, knownReference, false, monitor); } /** @@ -2637,11 +2588,10 @@ public class SymbolicPropogator { * @param preExisting preExisting reference * @param monitor - the task monitor * @return address that was marked up, null otherwise - + */ public Address makeReference(VarnodeContext vContext, Instruction instruction, int opIndex, - long knownSpaceID, long wordOffset, int size, DataType dataType, RefType refType, - int pcodeop, + long knownSpaceID, long wordOffset, int size, DataType dataType, RefType refType, int pcodeop, boolean knownReference, boolean preExisting, TaskMonitor monitor) { long spaceID = knownSpaceID; @@ -2700,8 +2650,7 @@ public class SymbolicPropogator { // to be considered later as a pointer. // allow flow references to memory not in program // program could be located in the wrong place, or other flow issues - if (!refType.isFlow() && - !program.getReferenceManager().hasReferencesTo(target)) { + if (!refType.isFlow() && !program.getReferenceManager().hasReferencesTo(target)) { return null; } } @@ -2779,7 +2728,7 @@ public class SymbolicPropogator { else { instruction.addOperandReference(opIndex, target, refType, SourceType.ANALYSIS); } - + return target; } @@ -2810,7 +2759,7 @@ public class SymbolicPropogator { dataType, refType)) { return null; } - + return target; } @@ -2852,8 +2801,7 @@ public class SymbolicPropogator { Instruction targetInstr = getInstructionContaining(target); if (targetInstr != null) { // if not at the top of an instruction, don't do it - Address disassemblyAddress = - PseudoDisassembler.getNormalizedDisassemblyAddress(program, target); + Address disassemblyAddress = PseudoDisassembler.getNormalizedDisassemblyAddress(program, target); if (!targetInstr.getMinAddress().equals(disassemblyAddress)) { return false; } @@ -2897,13 +2845,13 @@ public class SymbolicPropogator { } } } - + // Don't check more complicated operands if already found an operand that matches // only continue checking for an exact scalar/address operand if (opIndex != Reference.MNEMONIC) { continue; } - + // markup the program counter for any flow if ((opType & OperandType.REGISTER) != 0) { Register reg = instruction.getRegister(i); @@ -3026,7 +2974,7 @@ public class SymbolicPropogator { public void setParamPointerRefCheck(boolean checkParamRefsOption) { checkForParamPointerRefs = checkParamRefsOption; } - + /** * enable/disable checking return for constant references * diff --git a/Ghidra/Features/Decompiler/ghidra_scripts/StringParameterPropagator.java b/Ghidra/Features/Decompiler/ghidra_scripts/StringParameterPropagator.java index 3208e30263..a07fa165fe 100644 --- a/Ghidra/Features/Decompiler/ghidra_scripts/StringParameterPropagator.java +++ b/Ghidra/Features/Decompiler/ghidra_scripts/StringParameterPropagator.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -429,8 +429,7 @@ public class StringParameterPropagator extends GhidraScript { return false; } VariableStorage storage = - convention.getArgLocation(paramIndex, func.getParameters(), dt, currentProgram, - false); + convention.getArgLocation(paramIndex, func.getParameters(), dt, currentProgram); if (storage.isUnassignedStorage()) { return false; } @@ -499,7 +498,7 @@ public class StringParameterPropagator extends GhidraScript { continue; } VariableStorage storage = convention.getArgLocation(i - 1, f.getParameters(), - DataType.DEFAULT, currentProgram, false); + DataType.DEFAULT, currentProgram); if (storage.isUnassignedStorage()) { break; }