diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/stack/vars/VariableValueHoverService.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/stack/vars/VariableValueHoverService.java index 24b23e68bd..2a535d7b19 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/stack/vars/VariableValueHoverService.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/stack/vars/VariableValueHoverService.java @@ -310,7 +310,7 @@ public class VariableValueHoverService extends AbstractConfigurableHover } if (variable != null) { return fillFrameStorage(frame, variable.getName(), variable.getDataType(), - variable.getVariableStorage()); + variable.getProgram(), variable.getVariableStorage()); } Address dynAddr = frame.getBasePointer().add(stackAddress.getOffset()); TraceCodeUnit unit = current.getTrace() @@ -377,7 +377,7 @@ public class VariableValueHoverService extends AbstractConfigurableHover if (variable != null) { return fillFrameStorage(frame, variable.getName(), variable.getDataType(), - variable.getVariableStorage()); + variable.getProgram(), variable.getVariableStorage()); } if (frame.getLevel() == 0) { @@ -418,16 +418,17 @@ public class VariableValueHoverService extends AbstractConfigurableHover } public CompletableFuture fillStorage(Function function, String name, - DataType type, VariableStorage storage, AddressSetView symbolStorage) { + DataType type, Program program, VariableStorage storage, + AddressSetView symbolStorage) { return executeBackground(monitor -> { UnwoundFrame frame = - VariableValueUtils.requiresFrame(storage, symbolStorage) + VariableValueUtils.requiresFrame(program, storage, symbolStorage) ? eval.getStackFrame(function, warnings, monitor) : eval.getGlobalsFakeFrame(); if (frame == null) { throw new UnwindException("Cannot find frame for " + function); } - return fillFrameStorage(frame, name, type, storage); + return fillFrameStorage(frame, name, type, program, storage); }); } @@ -459,14 +460,14 @@ public class VariableValueHoverService extends AbstractConfigurableHover } public VariableValueTable fillFrameStorage(UnwoundFrame frame, String name, - DataType type, VariableStorage storage) { + DataType type, Program program, VariableStorage storage) { table.add(new NameRow(name)); if (!frame.isFake()) { table.add(new FrameRow(frame)); } table.add(new StorageRow(storage)); table.add(new TypeRow(type)); - WatchValue value = frame.getValue(storage); + WatchValue value = frame.getValue(program, storage); return fillWatchValue(frame, storage.getMinAddress(), type, value); } @@ -486,8 +487,7 @@ public class VariableValueHoverService extends AbstractConfigurableHover } public CompletableFuture fillHighVariable(HighVariable hVar, - String name, - AddressSetView symbolStorage) { + String name, AddressSetView symbolStorage) { Function function = hVar.getHighFunction().getFunction(); VariableStorage storage = VariableValueUtils.fabricateStorage(hVar); if (storage.isUniqueStorage()) { @@ -496,7 +496,8 @@ public class VariableValueHoverService extends AbstractConfigurableHover table.add(new ValueRow("(Unique)", TraceMemoryState.KNOWN)); return CompletableFuture.completedFuture(table); } - return fillStorage(function, name, hVar.getDataType(), storage, symbolStorage); + return fillStorage(function, name, hVar.getDataType(), function.getProgram(), storage, + symbolStorage); } public CompletableFuture fillHighVariable(HighVariable hVar, @@ -521,7 +522,7 @@ public class VariableValueHoverService extends AbstractConfigurableHover public CompletableFuture fillComposite(HighSymbol hSym, HighVariable hVar, AddressSetView symbolStorage) { return fillStorage(hVar.getHighFunction().getFunction(), hSym.getName(), - hSym.getDataType(), hSym.getStorage(), symbolStorage); + hSym.getDataType(), hSym.getProgram(), hSym.getStorage(), symbolStorage); } public CompletableFuture fillToken(ClangToken token) { @@ -582,7 +583,7 @@ public class VariableValueHoverService extends AbstractConfigurableHover throw new UnwindException("Cannot find frame for " + function); } return fillFrameStorage(frame, variable.getName(), variable.getDataType(), - variable.getVariableStorage()); + variable.getProgram(), variable.getVariableStorage()); }); } } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/stack/vars/VariableValueUtils.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/stack/vars/VariableValueUtils.java index b8990b686a..57f67c1387 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/stack/vars/VariableValueUtils.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/stack/vars/VariableValueUtils.java @@ -159,8 +159,8 @@ public enum VariableValueUtils { } @Override - public Boolean evaluateStorage(VariableStorage storage) { - return evaluateStorage(storage, false); + public Boolean evaluateStorage(Program program, VariableStorage storage) { + return evaluateStorage(program, storage, false); } } @@ -347,13 +347,15 @@ public enum VariableValueUtils { /** * Check if evaluation of the given storage will require a frame * + * @param program the program containing the variable storage * @param storage the storage to evaluate * @param symbolStorage the leaves of evaluation, usually storage used by symbols in scope. See * {@link #collectSymbolStorage(ClangLine)} * @return true if a frame is required, false otherwise */ - public static boolean requiresFrame(VariableStorage storage, AddressSetView symbolStorage) { - return new RequiresFrameEvaluator(symbolStorage).evaluateStorage(storage); + public static boolean requiresFrame(Program program, VariableStorage storage, + AddressSetView symbolStorage) { + return new RequiresFrameEvaluator(symbolStorage).evaluateStorage(program, storage); } /** diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/stack/AbstractUnwoundFrame.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/stack/AbstractUnwoundFrame.java index 440aa8965c..2a986f42df 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/stack/AbstractUnwoundFrame.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/stack/AbstractUnwoundFrame.java @@ -271,14 +271,14 @@ public abstract class AbstractUnwoundFrame implements UnwoundFrame { protected abstract Address applyBase(long offset); @Override - public T getValue(VariableStorage storage) { + public T getValue(Program program, VariableStorage storage) { SavedRegisterMap registerMap = computeRegisterMap(); return new FrameVarnodeValueGetter(state.getArithmetic()) { @Override protected T evaluateMemory(Address address, int size) { return registerMap.getVar(state, address, size, Reason.INSPECT); } - }.evaluateStorage(storage); + }.evaluateStorage(program, storage); } @Override @@ -289,14 +289,14 @@ public abstract class AbstractUnwoundFrame implements UnwoundFrame { } @Override - public T evaluate(VariableStorage storage, AddressSetView symbolStorage) { + public T evaluate(Program program, VariableStorage storage, AddressSetView symbolStorage) { SavedRegisterMap registerMap = computeRegisterMap(); return new FrameVarnodeEvaluator(state.getArithmetic(), symbolStorage) { @Override protected T evaluateMemory(Address address, int size) { return registerMap.getVar(state, address, size, Reason.INSPECT); } - }.evaluateStorage(storage); + }.evaluateStorage(program, storage); } @Override @@ -311,8 +311,8 @@ public abstract class AbstractUnwoundFrame implements UnwoundFrame { } @Override - public CompletableFuture setValue(StateEditor editor, VariableStorage storage, - BigInteger value) { + public CompletableFuture setValue(StateEditor editor, Program program, + VariableStorage storage, BigInteger value) { SavedRegisterMap registerMap = computeRegisterMap(); ByteBuffer buf = ByteBuffer.wrap(Utils.bigIntegerToBytes(value, storage.size(), true)); AsyncFence fence = new AsyncFence(); @@ -334,10 +334,10 @@ public abstract class AbstractUnwoundFrame implements UnwoundFrame { } @Override - public ByteBuffer evaluateStorage(VariableStorage storage) { - return evaluateStorage(storage, buf); + public ByteBuffer evaluateStorage(Program program, VariableStorage storage) { + return evaluateStorage(program, storage, buf); } - }.evaluateStorage(storage); + }.evaluateStorage(program, storage); return fence.ready(); } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/stack/UnwoundFrame.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/stack/UnwoundFrame.java index fe508f5183..0d905c4265 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/stack/UnwoundFrame.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/stack/UnwoundFrame.java @@ -149,10 +149,11 @@ public interface UnwoundFrame { * WARNING: Never invoke this method from the Swing thread. The state could be associated * with a live session, and this may block to retrieve live state. * + * @param program the program containing the variable storage * @param storage the storage * @return the value */ - T getValue(VariableStorage storage); + T getValue(Program program, VariableStorage storage); /** * Get the value of the variable from the frame @@ -166,7 +167,7 @@ public interface UnwoundFrame { * @return the value */ default T getValue(Variable variable) { - return getValue(variable.getVariableStorage()); + return getValue(variable.getProgram(), variable.getVariableStorage()); } /** @@ -198,11 +199,12 @@ public interface UnwoundFrame { * with a live session, and this may block to retrieve live state. * * @see VariableValueUtils#collectSymbolStorage(ClangLine) + * @param program the program containing the variable storage * @param storage the storage to evaluate * @param symbolStorage the terminal storage, usually that of symbols * @return the value */ - T evaluate(VariableStorage storage, AddressSetView symbolStorage); + T evaluate(Program program, VariableStorage storage, AddressSetView symbolStorage); /** * Evaluate the output for the given p-code op, ascending until symbol storage is reached @@ -227,11 +229,13 @@ public interface UnwoundFrame { * stack. * * @param editor the editor for setting values + * @param program the program containing the variable storage * @param storage the storage to modify * @param value the desired value * @return a future which completes when the necessary commands have all completed */ - CompletableFuture setValue(StateEditor editor, VariableStorage storage, BigInteger value); + CompletableFuture setValue(StateEditor editor, Program program, VariableStorage storage, + BigInteger value); /** * Set the value of the given variable @@ -244,7 +248,7 @@ public interface UnwoundFrame { */ default CompletableFuture setValue(StateEditor editor, Variable variable, BigInteger value) { - return setValue(editor, variable.getVariableStorage(), value); + return setValue(editor, variable.getProgram(), variable.getVariableStorage(), value); } /** diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/eval/AbstractVarnodeEvaluator.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/eval/AbstractVarnodeEvaluator.java index e4073741dd..1202d8dbbf 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/eval/AbstractVarnodeEvaluator.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/eval/AbstractVarnodeEvaluator.java @@ -187,12 +187,12 @@ public abstract class AbstractVarnodeEvaluator implements VarnodeEvaluator /** * Evaluate variable storage, providing an "identity" value * + * @param program the program containing the variable storage * @param storage the storage to evaluate * @param identity the value if storage had no varnodes * @return the value of the storage */ - protected T evaluateStorage(VariableStorage storage, T identity) { - Program program = storage.getProgram(); + protected T evaluateStorage(Program program, VariableStorage storage, T identity) { int total = storage.size(); T value = identity; for (Varnode vn : storage.getVarnodes()) { diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/eval/ArithmeticVarnodeEvaluator.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/eval/ArithmeticVarnodeEvaluator.java index 628e893631..0cd482e33f 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/eval/ArithmeticVarnodeEvaluator.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/eval/ArithmeticVarnodeEvaluator.java @@ -17,7 +17,7 @@ package ghidra.pcode.eval; import java.util.Map; -import ghidra.pcode.exec.*; +import ghidra.pcode.exec.PcodeArithmetic; import ghidra.pcode.exec.PcodeArithmetic.Purpose; import ghidra.pcode.opbehavior.BinaryOpBehavior; import ghidra.pcode.opbehavior.UnaryOpBehavior; @@ -75,8 +75,8 @@ public abstract class ArithmeticVarnodeEvaluator extends AbstractVarnodeEvalu } @Override - public T evaluateStorage(VariableStorage storage) { - return evaluateStorage(storage, arithmetic.fromConst(0, storage.size())); + public T evaluateStorage(Program program, VariableStorage storage) { + return evaluateStorage(program, storage, arithmetic.fromConst(0, storage.size())); } @Override diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/eval/VarnodeEvaluator.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/eval/VarnodeEvaluator.java index fc55df7e41..e752a7f32d 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/eval/VarnodeEvaluator.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/eval/VarnodeEvaluator.java @@ -50,10 +50,11 @@ public interface VarnodeEvaluator { * concatenated. The lower-indexed varnodes in storage are the more significant pieces, similar * to big endian. * + * @param program the program containing the variable storage * @param storage the storage * @return the value of the storage */ - T evaluateStorage(VariableStorage storage); + T evaluateStorage(Program program, VariableStorage storage); /** * Evaluate a high p-code op