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.setParamRefCheck(false);
symEval.setReturnRefCheck(false); symEval.setReturnRefCheck(false);
symEval.setStoredRefCheck(false); symEval.setStoredRefCheck(false);

View file

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -72,7 +72,7 @@ public class PropagateConstantReferences extends GhidraScript {
// use context to fill out addresses on certain instructions // use context to fill out addresses on certain instructions
ContextEvaluator eval = new ConstantPropagationContextEvaluator(monitor, true); 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); symEval.flowConstants(start, func.getBody(), eval, true, monitor);
} }

View file

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -140,7 +140,7 @@ public class PropagateX86ConstantReferences extends GhidraScript {
eval.setTrustWritableMemory(true) eval.setTrustWritableMemory(true)
.setCreateComplexDataFromPointers(true); .setCreateComplexDataFromPointers(true);
SymbolicPropogator symEval = new SymbolicPropogator(currentProgram); SymbolicPropogator symEval = new SymbolicPropogator(currentProgram,false);
symEval.setParamRefCheck(true); symEval.setParamRefCheck(true);
symEval.setReturnRefCheck(true); symEval.setReturnRefCheck(true);
symEval.setStoredRefCheck(true); symEval.setStoredRefCheck(true);

View file

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -282,7 +282,7 @@ public class ResolveX86orX64LinuxSyscallsScript extends GhidraScript {
for (Function func : funcsToCalls.keySet()) { for (Function func : funcsToCalls.keySet()) {
Address start = func.getEntryPoint(); Address start = func.getEntryPoint();
ContextEvaluator eval = new ConstantPropagationContextEvaluator(monitor, true); 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); symEval.flowConstants(start, func.getBody(), eval, true, tMonitor);
for (Address callSite : funcsToCalls.get(func)) { for (Address callSite : funcsToCalls.get(func)) {
Value val = symEval.getRegisterValue(callSite, syscallReg); Value val = symEval.getRegisterValue(callSite, syscallReg);

View file

@ -462,7 +462,7 @@ public class CreateThunkFunctionCmd extends BackgroundCommand<Program> {
} }
final AtomicInteger foundCount = new AtomicInteger(0); 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 // try to compute the thunk by flowing constants from the start of the block
prop.flowConstants(jumpBlockAt.getFirstStartAddress(), jumpBlockAt, 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 // Add stack variables with undefined types to map to simplify merging
addFunctionStackVariablesToSortedList(func, sortedVariables); addFunctionStackVariablesToSortedList(func, sortedVariables);
SymbolicPropogator symEval = new SymbolicPropogator(program); SymbolicPropogator symEval = new SymbolicPropogator(program, false);
symEval.setParamRefCheck(false); symEval.setParamRefCheck(false);
symEval.setReturnRefCheck(false); symEval.setReturnRefCheck(false);
symEval.setStoredRefCheck(false); symEval.setStoredRefCheck(false);

View file

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

View file

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

View file

@ -65,7 +65,7 @@ public class SymbolicPropogator {
private boolean debug = false; 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 long pointerMask;
private int pointerSize; private int pointerSize;
@ -103,21 +103,35 @@ public class SymbolicPropogator {
// cache for pcode callother injection payloads // cache for pcode callother injection payloads
HashMap<Long, InjectPayload> injectPayloadCache = new HashMap<Long, InjectPayload>(); 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) { 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 program program
* @param trackStartEndState - true to track the each register at the start/end of each instruction * @param recordStartEndState - true to record the value of each register at the start/end of each
* this will use more memory and be slightly slower * 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.program = program;
this.trackStartEndState = trackStartEndState; this.recordStartEndState = recordStartEndState;
Language language = program.getLanguage(); Language language = program.getLanguage();
@ -126,7 +140,7 @@ public class SymbolicPropogator {
setPointerMask(program); setPointerMask(program);
context = new VarnodeContext(program, programContext, spaceContext, trackStartEndState); context = new VarnodeContext(program, programContext, spaceContext, recordStartEndState);
context.setDebug(debug); context.setDebug(debug);
} }
@ -259,7 +273,7 @@ public class SymbolicPropogator {
Language language = program.getLanguage(); Language language = program.getLanguage();
ProgramContext newValueContext = new ProgramContextImpl(language); ProgramContext newValueContext = new ProgramContextImpl(language);
ProgramContext newSpaceContext = 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); newContext.setDebug(debug);
programContext = newValueContext; programContext = newValueContext;
@ -318,8 +332,9 @@ public class SymbolicPropogator {
/** /**
* Get constant or register relative value assigned to the * Get constant or register relative value assigned to the
* specified register at the specified address * specified register at the specified address.
* Note: This can only be called safely if trackStartEndState flag is true. *
* 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. * Otherwise it will just return the current value, not the value at the given address.
* *
* @param toAddr address * @param toAddr address
@ -349,13 +364,13 @@ public class SymbolicPropogator {
/** /**
* Get constant or register relative value assigned to the * Get constant or register relative value assigned to the
* specified register at the specified address after the instruction has executed. * 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 toAddr address
* @param reg register * @param reg register
* @return register value * @return register value
* *
* @throws UnsupportedOperationException trackStartEndState == false at construction * @throws UnsupportedOperationException recordStartEndState == false at construction
*/ */
public Value getEndRegisterValue(Address toAddr, Register reg) { public Value getEndRegisterValue(Address toAddr, Register reg) {

View file

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

View file

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -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 // NOTE: Assumption, we have found all flows leading to the switch that might split the basic block
final AtomicInteger foundCount = new AtomicInteger(0); final AtomicInteger foundCount = new AtomicInteger(0);
SymbolicPropogator prop = new SymbolicPropogator(program); SymbolicPropogator prop = new SymbolicPropogator(program,false);
prop.flowConstants(jumpBlockAt.getFirstStartAddress(), jumpBlockAt, prop.flowConstants(jumpBlockAt.getFirstStartAddress(), jumpBlockAt,
new ContextEvaluatorAdapter() { new ContextEvaluatorAdapter() {
@Override @Override

View file

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -342,7 +342,7 @@ public class Motorola68KAnalyzer extends ConstantPropagationAnalyzer {
SwitchEvaluator switchEvaluator = new SwitchEvaluator(); SwitchEvaluator switchEvaluator = new SwitchEvaluator();
// clear past constants. This example doesn't seem to depend on them // 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.... // now flow with the simple block of this branch....
// for each unknown branch destination, // for each unknown branch destination,

View file

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -175,7 +175,7 @@ public class AARCH64PltThunkAnalyzer extends AbstractAnalyzer {
private void analyzePltThunk(Program program, Address entryAddr, int thunkSize, TaskMonitor monitor) private void analyzePltThunk(Program program, Address entryAddr, int thunkSize, TaskMonitor monitor)
throws CancelledException { throws CancelledException {
SymbolicPropogator symEval = new SymbolicPropogator(program); SymbolicPropogator symEval = new SymbolicPropogator(program, false);
symEval.setParamRefCheck(false); symEval.setParamRefCheck(false);
symEval.setReturnRefCheck(false); symEval.setReturnRefCheck(false);
symEval.setStoredRefCheck(false); symEval.setStoredRefCheck(false);

View file

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

View file

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -248,7 +248,7 @@ public class PPC64CallStubAnalyzer extends AbstractAnalyzer {
private void analyzeCallStub(Program program, Function stubFunction, int stubLength, private void analyzeCallStub(Program program, Function stubFunction, int stubLength,
TaskMonitor monitor) throws CancelledException { TaskMonitor monitor) throws CancelledException {
SymbolicPropogator symEval = new SymbolicPropogator(program); SymbolicPropogator symEval = new SymbolicPropogator(program, false);
symEval.setParamRefCheck(false); symEval.setParamRefCheck(false);
symEval.setReturnRefCheck(false); symEval.setReturnRefCheck(false);
symEval.setStoredRefCheck(false); symEval.setStoredRefCheck(false);