Merge remote-tracking branch 'origin/GP-5804_emteere_FixDefaultSymbolicPropRecordState' into patch

This commit is contained in:
Ryan Kurtz 2025-07-18 06:15:13 -04:00
commit e69ce4104b
15 changed files with 66 additions and 51 deletions

View file

@ -353,7 +353,7 @@ public class MultiInstructionMemReference extends GhidraScript {
}
}
SymbolicPropogator symEval = new SymbolicPropogator(currentProgram);
SymbolicPropogator symEval = new SymbolicPropogator(currentProgram, false);
symEval.setParamRefCheck(false);
symEval.setReturnRefCheck(false);
symEval.setStoredRefCheck(false);

View file

@ -72,7 +72,7 @@ public class PropagateConstantReferences extends GhidraScript {
// use context to fill out addresses on certain instructions
ContextEvaluator eval = new ConstantPropagationContextEvaluator(monitor, true);
SymbolicPropogator symEval = new SymbolicPropogator(currentProgram);
SymbolicPropogator symEval = new SymbolicPropogator(currentProgram,false);
symEval.flowConstants(start, func.getBody(), eval, true, monitor);
}

View file

@ -140,7 +140,7 @@ public class PropagateX86ConstantReferences extends GhidraScript {
eval.setTrustWritableMemory(true)
.setCreateComplexDataFromPointers(true);
SymbolicPropogator symEval = new SymbolicPropogator(currentProgram);
SymbolicPropogator symEval = new SymbolicPropogator(currentProgram,false);
symEval.setParamRefCheck(true);
symEval.setReturnRefCheck(true);
symEval.setStoredRefCheck(true);

View file

@ -282,7 +282,7 @@ public class ResolveX86orX64LinuxSyscallsScript extends GhidraScript {
for (Function func : funcsToCalls.keySet()) {
Address start = func.getEntryPoint();
ContextEvaluator eval = new ConstantPropagationContextEvaluator(monitor, true);
SymbolicPropogator symEval = new SymbolicPropogator(program);
SymbolicPropogator symEval = new SymbolicPropogator(program, true);
symEval.flowConstants(start, func.getBody(), eval, true, tMonitor);
for (Address callSite : funcsToCalls.get(func)) {
Value val = symEval.getRegisterValue(callSite, syscallReg);

View file

@ -462,7 +462,7 @@ public class CreateThunkFunctionCmd extends BackgroundCommand<Program> {
}
final AtomicInteger foundCount = new AtomicInteger(0);
SymbolicPropogator prop = new SymbolicPropogator(program);
SymbolicPropogator prop = new SymbolicPropogator(program,false);
// try to compute the thunk by flowing constants from the start of the block
prop.flowConstants(jumpBlockAt.getFirstStartAddress(), jumpBlockAt,

View file

@ -270,7 +270,7 @@ public class NewFunctionStackAnalysisCmd extends BackgroundCommand<Program> {
// Add stack variables with undefined types to map to simplify merging
addFunctionStackVariablesToSortedList(func, sortedVariables);
SymbolicPropogator symEval = new SymbolicPropogator(program);
SymbolicPropogator symEval = new SymbolicPropogator(program, false);
symEval.setParamRefCheck(false);
symEval.setReturnRefCheck(false);
symEval.setStoredRefCheck(false);

View file

@ -471,7 +471,7 @@ public class ConstantPropagationAnalyzer extends AbstractAnalyzer {
flowStart = func.getEntryPoint();
}
SymbolicPropogator symEval = new SymbolicPropogator(program);
SymbolicPropogator symEval = new SymbolicPropogator(program, false);
symEval.setParamRefCheck(checkParamRefsOption);
symEval.setParamPointerRefCheck(checkPointerParamRefsOption);

View file

@ -1125,7 +1125,7 @@ public class GolangSymbolAnalyzer extends AbstractAnalyzer {
GoTypeManager goTypes = goBinary.getGoTypes();
ContextEvaluator eval = new ConstantPropagationContextEvaluator(monitor, true);
SymbolicPropogator symEval = new SymbolicPropogator(program);
SymbolicPropogator symEval = new SymbolicPropogator(program, true);
symEval.flowConstants(callingFunc.getEntryPoint(), callingFunc.getBody(), eval, true,
monitor);

View file

@ -65,7 +65,7 @@ public class SymbolicPropogator {
private boolean debug = false;
private boolean trackStartEndState = false; // track the start/end values for each instruction
private boolean recordStartEndState = false; // record the start/end values for registers at each instruction
private long pointerMask;
private int pointerSize;
@ -103,21 +103,35 @@ public class SymbolicPropogator {
// cache for pcode callother injection payloads
HashMap<Long, InjectPayload> injectPayloadCache = new HashMap<Long, InjectPayload>();
/**
* Create SymbolicPropagator for program.
*
* This will record all values at the beginning and ending of instructions.
* Recording all values can take more time and memory. So if the SymbolicEvaluator
* callback mechanism is being used, use the alternate constructor with false for
* recordStartEndState.
*
*/
public SymbolicPropogator(Program program) {
this (program, false);
this (program, true);
}
/**
* Create symbolic propagation on program
* Create SymbolicPropagator for program either recording or start/end state at each instruction.
*
* NOTE: if you are going to inspect values at instructions after {@link SymbolicPropogator}.flowConstants()
* has completed, then you should pass true for recordStartEndState. If you are using a custom
* SymbolicEvaluator with the flowConstants() method, then you should pass false.
*
* @param program program
* @param trackStartEndState - true to track the each register at the start/end of each instruction
* this will use more memory and be slightly slower
* @param recordStartEndState - true to record the value of each register at the start/end of each
* instruction This will use more memory and be slightly slower. If inspecting
* values after flowContants() has completed, you must pass true.
*/
public SymbolicPropogator(Program program, boolean trackStartEndState) {
public SymbolicPropogator(Program program, boolean recordStartEndState) {
this.program = program;
this.trackStartEndState = trackStartEndState;
this.recordStartEndState = recordStartEndState;
Language language = program.getLanguage();
@ -126,7 +140,7 @@ public class SymbolicPropogator {
setPointerMask(program);
context = new VarnodeContext(program, programContext, spaceContext, trackStartEndState);
context = new VarnodeContext(program, programContext, spaceContext, recordStartEndState);
context.setDebug(debug);
}
@ -259,7 +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, trackStartEndState);
VarnodeContext newContext = new VarnodeContext(program, newValueContext, newSpaceContext, recordStartEndState);
newContext.setDebug(debug);
programContext = newValueContext;
@ -318,8 +332,9 @@ public class SymbolicPropogator {
/**
* Get constant or register relative value assigned to the
* specified register at the specified address
* Note: This can only be called safely if trackStartEndState flag is true.
* specified register at the specified address.
*
* Note: This can only be called safely if recordStartEndState flag is true.
* Otherwise it will just return the current value, not the value at the given address.
*
* @param toAddr address
@ -349,13 +364,13 @@ public class SymbolicPropogator {
/**
* Get constant or register relative value assigned to the
* specified register at the specified address after the instruction has executed.
* Note: This can only be called if trackStartEndState flag is true.
* Note: This can only be called if recordStartEndState flag is true.
*
* @param toAddr address
* @param reg register
* @return register value
*
* @throws UnsupportedOperationException trackStartEndState == false at construction
* @throws UnsupportedOperationException recordStartEndState == false at construction
*/
public Value getEndRegisterValue(Address toAddr, Register reg) {

View file

@ -126,15 +126,15 @@ public class VarnodeContext implements ProcessorContext {
boolean isBE = false;
boolean trackStartEndState = false;
boolean recordStartEndState = false;
public boolean debug = false;
public VarnodeContext(Program program, ProgramContext programContext,
ProgramContext spaceProgramContext, boolean trackStartEndState) {
ProgramContext spaceProgramContext, boolean recordStartEndState) {
this.program = program;
this.isBE = program.getLanguage().isBigEndian();
this.trackStartEndState = trackStartEndState;
this.recordStartEndState = recordStartEndState;
// make a copy, because we could be making new spaces.
this.addrFactory = new OffsetAddressFactory(program);
@ -237,7 +237,7 @@ public class VarnodeContext implements ProcessorContext {
public void flowStart(Address toAddr) {
currentAddress = toAddr;
if (trackStartEndState) {
if (recordStartEndState) {
addrStartState.put(toAddr,new TraceDepthState(regVals.size(),regVals));
regVals.push(new HashMap<Address, Varnode>());
}
@ -247,7 +247,7 @@ public class VarnodeContext implements ProcessorContext {
* End flow and save any necessary end flow state for the current instruction at address
*/
public void flowEnd(Address address) {
if (trackStartEndState) {
if (recordStartEndState) {
addrEndState.put(address,new TraceDepthState(regVals.size(),regVals));
}
currentAddress = null;
@ -1273,7 +1273,7 @@ public class VarnodeContext implements ProcessorContext {
* Get the value (value, space, size) of a register at the end of the last execution
* flow taken for the instruction at toAddr.
*
* Note: This can only be called if trackStartEndState flag is true.
* Note: This can only be called if recordStartEndState flag is true.
*
* @param reg register to retrieve the end value
* @param fromAddr flow from address (not used currently, future use to retrieve multiple flows)
@ -1282,13 +1282,13 @@ public class VarnodeContext implements ProcessorContext {
*
* @return instruction end state value for register, or null if no known state
*
* @throws UnsupportedOperationException trackStartEndState == false at construction
* @throws UnsupportedOperationException recordStartEndState == false at construction
*/
public Varnode getEndRegisterVarnodeValue(Register reg, Address fromAddr, Address toAddr,
boolean signed) {
if (!trackStartEndState) {
throw new UnsupportedOperationException("Must construct class with trackStartEndState == true");
if (!recordStartEndState) {
throw new UnsupportedOperationException("Must construct class with recordStartEndState == true");
}
if (reg == null) {
@ -1330,7 +1330,7 @@ public class VarnodeContext implements ProcessorContext {
/**
* Get the current value of the register at the address.
* Note: If trackStartEndState flag is false, then this will return the current value.
* Note: If recordStartEndState flag is false, then this will return the current value.
*
* @param reg value of register to get
* @param toAddr value of register at a location
@ -1344,7 +1344,7 @@ public class VarnodeContext implements ProcessorContext {
/**
* Get the value of a register that was set coming from an address to an
* another address.
* Note: If trackStartEndState flag is false, then this will return the current value.
* Note: If recordStartEndState flag is false, then this will return the current value.
*
* @param reg value of register to get
* @param fromAddr location the value came from

View file

@ -479,7 +479,7 @@ public class DecompilerSwitchAnalyzer extends AbstractAnalyzer {
// NOTE: Assumption, we have found all flows leading to the switch that might split the basic block
final AtomicInteger foundCount = new AtomicInteger(0);
SymbolicPropogator prop = new SymbolicPropogator(program);
SymbolicPropogator prop = new SymbolicPropogator(program,false);
prop.flowConstants(jumpBlockAt.getFirstStartAddress(), jumpBlockAt,
new ContextEvaluatorAdapter() {
@Override

View file

@ -342,7 +342,7 @@ public class Motorola68KAnalyzer extends ConstantPropagationAnalyzer {
SwitchEvaluator switchEvaluator = new SwitchEvaluator();
// clear past constants. This example doesn't seem to depend on them
symEval = new SymbolicPropogator(program);
symEval = new SymbolicPropogator(program,false);
// now flow with the simple block of this branch....
// for each unknown branch destination,

View file

@ -175,7 +175,7 @@ public class AARCH64PltThunkAnalyzer extends AbstractAnalyzer {
private void analyzePltThunk(Program program, Address entryAddr, int thunkSize, TaskMonitor monitor)
throws CancelledException {
SymbolicPropogator symEval = new SymbolicPropogator(program);
SymbolicPropogator symEval = new SymbolicPropogator(program, false);
symEval.setParamRefCheck(false);
symEval.setReturnRefCheck(false);
symEval.setStoredRefCheck(false);

View file

@ -541,7 +541,7 @@ public class ArmAnalyzer extends ConstantPropagationAnalyzer {
SymbolicPropogator targetEval = symEval;
// if this is a tbX instruction, don't assume any old values
if (targetInstr != null && targetInstr.getMnemonicString().startsWith("tb")) {
targetEval = new SymbolicPropogator(program);
targetEval = new SymbolicPropogator(program, false);
}
Address zeroAddr = targetInstr.getMinAddress().getNewAddress(0);

View file

@ -248,7 +248,7 @@ public class PPC64CallStubAnalyzer extends AbstractAnalyzer {
private void analyzeCallStub(Program program, Function stubFunction, int stubLength,
TaskMonitor monitor) throws CancelledException {
SymbolicPropogator symEval = new SymbolicPropogator(program);
SymbolicPropogator symEval = new SymbolicPropogator(program, false);
symEval.setParamRefCheck(false);
symEval.setReturnRefCheck(false);
symEval.setStoredRefCheck(false);