From dcd54c66954c80a0a2999bd936d0c8b65b85cb3c Mon Sep 17 00:00:00 2001 From: Dan <46821332+nsadeveloper789@users.noreply.github.com> Date: Thu, 22 Sep 2022 14:47:08 -0400 Subject: [PATCH] GP-1650: Introduce Reason for reading state. Fix spurrious uninit warnings. --- .../DebuggerEmuExampleScript.java | 5 +-- .../DemoPcodeUseropLibrary.java | 9 +++-- .../ghidra_scripts/DemoSyscallLibrary.java | 13 +++++--- .../StandAloneEmuExampleScript.java | 5 +-- .../StandAloneSyscallEmuExampleScript.java | 4 ++- .../core/debug/gui/pcode/UniqueRow.java | 5 +-- .../plugin/core/debug/gui/watch/WatchRow.java | 8 +++-- ...stractRWTargetPcodeExecutorStatePiece.java | 8 ++--- .../ghidra/pcode/exec/DebuggerPcodeUtils.java | 4 ++- .../DebuggerPcodeStepperProviderTest.java | 3 +- .../exec/TraceRecorderPcodeExecTest.java | 3 +- ...chedWriteBytesPcodeExecutorStatePiece.java | 4 +-- ...rectBytesTracePcodeExecutorStatePiece.java | 4 +-- ...aceMemoryStatePcodeExecutorStatePiece.java | 7 ++-- .../pcode/exec/trace/TraceSleighUtils.java | 5 +-- .../trace/BytesTracePcodeEmulatorTest.java | 13 ++++---- .../exec/trace/TraceSleighUtilsTest.java | 4 ++- .../trace/model/time/schedule/TestThread.java | 3 +- .../ghidra/pcode/emu/DefaultPcodeThread.java | 8 +++-- .../ghidra/pcode/emu/ModifiedPcodeThread.java | 2 +- .../pcode/emu/ThreadPcodeExecutorState.java | 6 ++-- .../EmuLinuxAmd64SyscallUseropLibrary.java | 7 ++-- .../EmuLinuxX86SyscallUseropLibrary.java | 7 ++-- .../pcode/emu/sys/EmuSyscallLibrary.java | 7 ++-- .../AbstractEmuUnixSyscallUseropLibrary.java | 3 +- .../AbstractBytesPcodeExecutorStatePiece.java | 10 +++--- ...ractLongOffsetPcodeExecutorStatePiece.java | 23 +++++++------ .../AddressOfPcodeExecutorStatePiece.java | 3 +- .../exec/AnnotatedPcodeUseropLibrary.java | 10 +++--- .../exec/BytesPcodeExecutorStateSpace.java | 10 +++--- .../pcode/exec/DefaultPcodeExecutorState.java | 4 +-- .../pcode/exec/PairedPcodeExecutorState.java | 5 +-- .../exec/PairedPcodeExecutorStatePiece.java | 7 ++-- .../ghidra/pcode/exec/PcodeArithmetic.java | 2 +- .../java/ghidra/pcode/exec/PcodeExecutor.java | 33 +++++++++++++------ .../pcode/exec/PcodeExecutorStatePiece.java | 33 ++++++++++++++----- ...EmuLinuxAmd64SyscallUseropLibraryTest.java | 21 ++++++------ .../EmuLinuxX86SyscallUseropLibraryTest.java | 21 ++++++------ .../sys/EmuAmd64SyscallUseropLibraryTest.java | 9 ++--- .../exec/AnnotatedPcodeUseropLibraryTest.java | 9 ++--- .../AbstractTaintPcodeExecutorStatePiece.java | 6 ++-- .../emu/taint/TaintPcodeThreadExecutor.java | 2 +- .../taint/plain/TaintPcodeEmulatorTest.java | 15 +++++---- .../trace/TaintTracePcodeEmulatorTest.java | 5 +-- 44 files changed, 224 insertions(+), 151 deletions(-) diff --git a/Ghidra/Debug/Debugger/ghidra_scripts/DebuggerEmuExampleScript.java b/Ghidra/Debug/Debugger/ghidra_scripts/DebuggerEmuExampleScript.java index 6ec34fa869..e9e4466a08 100644 --- a/Ghidra/Debug/Debugger/ghidra_scripts/DebuggerEmuExampleScript.java +++ b/Ghidra/Debug/Debugger/ghidra_scripts/DebuggerEmuExampleScript.java @@ -37,6 +37,7 @@ import ghidra.app.services.ProgramManager; import ghidra.framework.plugintool.PluginTool; import ghidra.pcode.emu.PcodeThread; import ghidra.pcode.exec.*; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.pcode.exec.trace.TraceSleighUtils; import ghidra.pcode.utils.Utils; import ghidra.program.database.ProgramDB; @@ -191,8 +192,8 @@ public class DebuggerEmuExampleScript extends GhidraScript { * This works the same as in the stand-alone case. */ println("RCX = " + - Utils.bytesToLong(thread.getState().getVar(language.getRegister("RCX")), 8, - language.isBigEndian())); + Utils.bytesToLong(thread.getState().getVar(language.getRegister("RCX"), Reason.INSPECT), + 8, language.isBigEndian())); println("RCX = " + Utils.bytesToLong( SleighProgramCompiler.compileExpression(language, "RCX").evaluate(thread.getExecutor()), diff --git a/Ghidra/Debug/Debugger/ghidra_scripts/DemoPcodeUseropLibrary.java b/Ghidra/Debug/Debugger/ghidra_scripts/DemoPcodeUseropLibrary.java index 68c1732d8d..8b9d673da5 100644 --- a/Ghidra/Debug/Debugger/ghidra_scripts/DemoPcodeUseropLibrary.java +++ b/Ghidra/Debug/Debugger/ghidra_scripts/DemoPcodeUseropLibrary.java @@ -19,6 +19,7 @@ import java.util.List; import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.app.script.GhidraScript; import ghidra.pcode.exec.*; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.pcode.struct.StructuredSleigh; import ghidra.pcode.utils.Utils; import ghidra.program.model.address.AddressSpace; @@ -75,17 +76,19 @@ public class DemoPcodeUseropLibrary extends AnnotatedPcodeUseropLibrary * @return the length of the string in bytes */ @PcodeUserop - public byte[] print_utf8(@OpState PcodeExecutorState state, byte[] start) { + public byte[] print_utf8(@OpExecutor PcodeExecutor executor, byte[] start) { + PcodeExecutorState state = executor.getState(); long offset = Utils.bytesToLong(start, start.length, language.isBigEndian()); long end = offset; - while (state.getVar(space, end, 1, true)[0] != 0) { + Reason reason = executor.getReason(); + while (state.getVar(space, end, 1, true, reason)[0] != 0) { end++; } if (end == offset) { script.println(""); return Utils.longToBytes(0, Long.BYTES, language.isBigEndian()); } - byte[] bytes = state.getVar(space, offset, (int) (end - offset), true); + byte[] bytes = state.getVar(space, offset, (int) (end - offset), true, reason); String str = new String(bytes, UTF8); script.println(str); return Utils.longToBytes(end - offset, Long.BYTES, language.isBigEndian()); diff --git a/Ghidra/Debug/Debugger/ghidra_scripts/DemoSyscallLibrary.java b/Ghidra/Debug/Debugger/ghidra_scripts/DemoSyscallLibrary.java index 732a863d21..bca15ca36d 100644 --- a/Ghidra/Debug/Debugger/ghidra_scripts/DemoSyscallLibrary.java +++ b/Ghidra/Debug/Debugger/ghidra_scripts/DemoSyscallLibrary.java @@ -24,6 +24,7 @@ import ghidra.pcode.emu.sys.AnnotatedEmuSyscallUseropLibrary; import ghidra.pcode.emu.sys.EmuSyscallLibrary; import ghidra.pcode.exec.*; import ghidra.pcode.exec.PcodeArithmetic.Purpose; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.pcode.struct.StructuredSleigh; import ghidra.pcode.utils.Utils; import ghidra.program.model.address.AddressSpace; @@ -102,13 +103,15 @@ public class DemoSyscallLibrary extends AnnotatedEmuSyscallUseropLibrary } /** + * {@inheritDoc} + * * The dispatcher doesn't know where the system call number is stored. It relies on this method * to read that number from the state. Here we'll assume the target is x64 and RAX contains the * syscall number. */ @Override - public long readSyscallNumber(PcodeExecutorStatePiece state) { - return Utils.bytesToLong(state.getVar(regRAX), regRAX.getNumBytes(), + public long readSyscallNumber(PcodeExecutorState state, Reason reason) { + return Utils.bytesToLong(state.getVar(regRAX, reason), regRAX.getNumBytes(), machine.getLanguage().isBigEndian()); } @@ -165,7 +168,7 @@ public class DemoSyscallLibrary extends AnnotatedEmuSyscallUseropLibrary */ @PcodeUserop @EmuSyscall("write") - public void demo_write(byte[] str, byte[] end) { + public void demo_write(@OpExecutor PcodeExecutor executor, byte[] str, byte[] end) { AddressSpace space = machine.getLanguage().getDefaultSpace(); /** * Because we have concrete {@code byte[]}, we could use Utils.bytesToLong, but for @@ -178,8 +181,8 @@ public class DemoSyscallLibrary extends AnnotatedEmuSyscallUseropLibrary long strLong = arithmetic.toLong(str, Purpose.LOAD); long endLong = arithmetic.toLong(end, Purpose.OTHER); - byte[] stringBytes = - machine.getSharedState().getVar(space, strLong, (int) (endLong - strLong), true); + byte[] stringBytes = machine.getSharedState() + .getVar(space, strLong, (int) (endLong - strLong), true, executor.getReason()); String string = new String(stringBytes, UTF8); script.println(string); } diff --git a/Ghidra/Debug/Debugger/ghidra_scripts/StandAloneEmuExampleScript.java b/Ghidra/Debug/Debugger/ghidra_scripts/StandAloneEmuExampleScript.java index 92d2a0e968..d83b6d560c 100644 --- a/Ghidra/Debug/Debugger/ghidra_scripts/StandAloneEmuExampleScript.java +++ b/Ghidra/Debug/Debugger/ghidra_scripts/StandAloneEmuExampleScript.java @@ -29,6 +29,7 @@ import ghidra.app.script.GhidraScript; import ghidra.pcode.emu.PcodeEmulator; import ghidra.pcode.emu.PcodeThread; import ghidra.pcode.exec.*; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.pcode.utils.Utils; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSpace; @@ -136,8 +137,8 @@ public class StandAloneEmuExampleScript extends GhidraScript { * convenient. */ println("RCX = " + - Utils.bytesToLong(thread.getState().getVar(language.getRegister("RCX")), 8, - language.isBigEndian())); + Utils.bytesToLong(thread.getState().getVar(language.getRegister("RCX"), Reason.INSPECT), + 8, language.isBigEndian())); println("RCX = " + Utils.bytesToLong( SleighProgramCompiler.compileExpression(language, "RCX").evaluate(thread.getExecutor()), diff --git a/Ghidra/Debug/Debugger/ghidra_scripts/StandAloneSyscallEmuExampleScript.java b/Ghidra/Debug/Debugger/ghidra_scripts/StandAloneSyscallEmuExampleScript.java index c8c10eae58..ce6f45568e 100644 --- a/Ghidra/Debug/Debugger/ghidra_scripts/StandAloneSyscallEmuExampleScript.java +++ b/Ghidra/Debug/Debugger/ghidra_scripts/StandAloneSyscallEmuExampleScript.java @@ -32,6 +32,7 @@ import ghidra.pcode.emu.PcodeThread; import ghidra.pcode.emu.sys.EmuInvalidSystemCallException; import ghidra.pcode.emu.sys.EmuSyscallLibrary; import ghidra.pcode.exec.*; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.pcode.utils.Utils; import ghidra.program.database.ProgramDB; import ghidra.program.model.address.*; @@ -210,7 +211,8 @@ public class StandAloneSyscallEmuExampleScript extends GhidraScript { * convenient. */ println("RDI = " + - Utils.bytesToLong(thread.getState().getVar(language.getRegister("RDI")), 8, + Utils.bytesToLong( + thread.getState().getVar(language.getRegister("RDI"), Reason.INSPECT), 8, language.isBigEndian())); println("RDI = " + Utils.bytesToLong( diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/pcode/UniqueRow.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/pcode/UniqueRow.java index 4537a3686b..d891dd909e 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/pcode/UniqueRow.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/pcode/UniqueRow.java @@ -21,6 +21,7 @@ import java.util.stream.Stream; import ghidra.docking.settings.SettingsImpl; import ghidra.pcode.exec.PcodeArithmetic; import ghidra.pcode.exec.PcodeArithmetic.Purpose; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.pcode.exec.PcodeExecutorState; import ghidra.program.model.address.*; import ghidra.program.model.data.DataType; @@ -65,11 +66,11 @@ public class UniqueRow { } public byte[] getBytes(Varnode vn) { - return arithmetic.toConcrete(state.getVar(vn), Purpose.INSPECT); + return arithmetic.toConcrete(state.getVar(vn, Reason.INSPECT), Purpose.INSPECT); } public BigInteger getValue(Varnode vn) { - return arithmetic.toBigInteger(state.getVar(vn), Purpose.INSPECT); + return arithmetic.toBigInteger(state.getVar(vn, Reason.INSPECT), Purpose.INSPECT); } } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/watch/WatchRow.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/watch/WatchRow.java index 09da1e4c0a..486b1f3fed 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/watch/WatchRow.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/watch/WatchRow.java @@ -32,6 +32,7 @@ import ghidra.docking.settings.Settings; import ghidra.docking.settings.SettingsImpl; import ghidra.framework.options.SaveState; import ghidra.pcode.exec.*; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.pcode.exec.trace.*; import ghidra.pcode.utils.Utils; import ghidra.program.model.address.*; @@ -185,8 +186,9 @@ public class WatchRow { } @Override - public byte[] getVar(AddressSpace space, long offset, int size, boolean quantize) { - byte[] data = super.getVar(space, offset, size, quantize); + public byte[] getVar(AddressSpace space, long offset, int size, boolean quantize, + Reason reason) { + byte[] data = super.getVar(space, offset, size, quantize, reason); if (space.isMemorySpace()) { offset = quantizeOffset(space, offset); } @@ -222,7 +224,7 @@ public class WatchRow { public ReadDepsPcodeExecutor(ReadDepsTraceBytesPcodeExecutorStatePiece depsState, SleighLanguage language, PairedPcodeArithmetic arithmetic, PcodeExecutorState> state) { - super(language, arithmetic, state); + super(language, arithmetic, state, Reason.INSPECT); this.depsPiece = depsState; } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/AbstractRWTargetPcodeExecutorStatePiece.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/AbstractRWTargetPcodeExecutorStatePiece.java index b72fe72898..ade16ff8a6 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/AbstractRWTargetPcodeExecutorStatePiece.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/AbstractRWTargetPcodeExecutorStatePiece.java @@ -47,25 +47,25 @@ public abstract class AbstractRWTargetPcodeExecutorStatePiece protected abstract void fillUninitialized(AddressSet uninitialized); @Override - public byte[] read(long offset, int size) { + public byte[] read(long offset, int size, Reason reason) { if (backing != null) { AddressSet uninitialized = addrSet(bytes.getUninitialized(offset, offset + size - 1)); if (uninitialized.isEmpty()) { - return super.read(offset, size); + return super.read(offset, size, reason); } fillUninitialized(uninitialized); AddressSetView unknown = backing.intersectUnknown( addrSet(bytes.getUninitialized(offset, offset + size - 1))); - if (!unknown.isEmpty()) { + if (!unknown.isEmpty() && reason == Reason.EXECUTE) { warnUnknown(unknown); } } // TODO: What to flush when bytes in the trace change? - return super.read(offset, size); + return super.read(offset, size, reason); } protected T waitTimeout(CompletableFuture future) { diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/pcode/exec/DebuggerPcodeUtils.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/pcode/exec/DebuggerPcodeUtils.java index 2e0d4a7cde..ba8a8e4237 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/pcode/exec/DebuggerPcodeUtils.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/pcode/exec/DebuggerPcodeUtils.java @@ -21,6 +21,7 @@ import ghidra.app.plugin.core.debug.service.emulation.data.DefaultPcodeDebuggerA import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.framework.plugintool.PluginTool; import ghidra.pcode.emu.ThreadPcodeExecutorState; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.program.model.lang.Language; import ghidra.trace.model.Trace; import ghidra.trace.model.guest.TracePlatform; @@ -83,6 +84,7 @@ public enum DebuggerPcodeUtils { PcodeExecutorState state = executorStateForCoordinates(tool, coordinates); SleighLanguage slang = (SleighLanguage) state.getLanguage(); - return new PcodeExecutor<>(slang, BytesPcodeArithmetic.forLanguage(slang), state); + return new PcodeExecutor<>(slang, BytesPcodeArithmetic.forLanguage(slang), state, + Reason.INSPECT); } } diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/pcode/DebuggerPcodeStepperProviderTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/pcode/DebuggerPcodeStepperProviderTest.java index 77f679f1ad..bb620e577e 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/pcode/DebuggerPcodeStepperProviderTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/pcode/DebuggerPcodeStepperProviderTest.java @@ -36,6 +36,7 @@ import ghidra.app.services.DebuggerEmulationService; import ghidra.app.services.DebuggerTraceManagerService; import ghidra.pcode.emu.PcodeThread; import ghidra.pcode.exec.*; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.pcode.exec.trace.TraceSleighUtils; import ghidra.program.model.address.Address; import ghidra.program.model.listing.Instruction; @@ -171,7 +172,7 @@ public class DebuggerPcodeStepperProviderTest extends AbstractGhidraHeadedDebugg PcodeProgram prog = SleighProgramCompiler.compileProgram(language, "test", sleigh, PcodeUseropLibrary.nil()); PcodeExecutor executor = - new PcodeExecutor<>(language, BytesPcodeArithmetic.BIG_ENDIAN, null); + new PcodeExecutor<>(language, BytesPcodeArithmetic.BIG_ENDIAN, null, Reason.INSPECT); PcodeFrame frame = executor.begin(prog); PcodeRowHtmlFormatter formatter = pcodeProvider.new PcodeRowHtmlFormatter(language, frame); return formatter.getRows(); diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/pcode/exec/TraceRecorderPcodeExecTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/pcode/exec/TraceRecorderPcodeExecTest.java index bea813317f..e7bd20feba 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/pcode/exec/TraceRecorderPcodeExecTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/pcode/exec/TraceRecorderPcodeExecTest.java @@ -30,6 +30,7 @@ import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.app.services.ActionSource; import ghidra.app.services.TraceRecorder; import ghidra.dbg.model.TestTargetRegisterBankInThread; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.pcode.exec.trace.DirectBytesTracePcodeExecutorState; import ghidra.pcode.utils.Utils; import ghidra.program.model.lang.Register; @@ -126,7 +127,7 @@ public class TraceRecorderPcodeExecTest extends AbstractGhidraHeadedDebuggerGUIT executor.execute(prog, PcodeUseropLibrary.nil()); // Ignore return value. We'll assert that it got written to the trace - executor.state.getVar(language.getRegister("r2")); + executor.state.getVar(language.getRegister("r2"), Reason.INSPECT); assertEquals(BigInteger.valueOf(11), new BigInteger(1, regs.regVals.get("r2"))); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/pcode/exec/trace/AbstractCheckedTraceCachedWriteBytesPcodeExecutorStatePiece.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/pcode/exec/trace/AbstractCheckedTraceCachedWriteBytesPcodeExecutorStatePiece.java index 97a43898b9..856c792fbb 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/pcode/exec/trace/AbstractCheckedTraceCachedWriteBytesPcodeExecutorStatePiece.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/pcode/exec/trace/AbstractCheckedTraceCachedWriteBytesPcodeExecutorStatePiece.java @@ -41,14 +41,14 @@ public abstract class AbstractCheckedTraceCachedWriteBytesPcodeExecutorStatePiec } @Override - public byte[] read(long offset, int size) { + public byte[] read(long offset, int size, Reason reason) { RangeSet uninitialized = bytes.getUninitialized(offset, offset + size - 1); if (!uninitialized.isEmpty()) { size = checkUninitialized(backing, space.getAddress(offset), size, addrSet(uninitialized)); } - return super.read(offset, size); + return super.read(offset, size, reason); } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/pcode/exec/trace/DirectBytesTracePcodeExecutorStatePiece.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/pcode/exec/trace/DirectBytesTracePcodeExecutorStatePiece.java index bac6441d59..39059c08c0 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/pcode/exec/trace/DirectBytesTracePcodeExecutorStatePiece.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/pcode/exec/trace/DirectBytesTracePcodeExecutorStatePiece.java @@ -99,7 +99,7 @@ public class DirectBytesTracePcodeExecutorStatePiece } @Override - protected byte[] getUnique(long offset, int size) { + protected byte[] getUnique(long offset, int size, Reason reason) { byte[] data = new byte[size]; unique.getData(offset, data); return data; @@ -120,7 +120,7 @@ public class DirectBytesTracePcodeExecutorStatePiece } @Override - protected byte[] getFromSpace(AddressSpace space, long offset, int size) { + protected byte[] getFromSpace(AddressSpace space, long offset, int size, Reason reason) { ByteBuffer buf = ByteBuffer.allocate(size); int read = data.getBytes(space.getAddress(offset), buf); if (read != size) { diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/pcode/exec/trace/TraceMemoryStatePcodeExecutorStatePiece.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/pcode/exec/trace/TraceMemoryStatePcodeExecutorStatePiece.java index acb3bac696..02ae1be60f 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/pcode/exec/trace/TraceMemoryStatePcodeExecutorStatePiece.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/pcode/exec/trace/TraceMemoryStatePcodeExecutorStatePiece.java @@ -78,7 +78,7 @@ public class TraceMemoryStatePcodeExecutorStatePiece extends } @Override - protected TraceMemoryState getUnique(long offset, int size) { + protected TraceMemoryState getUnique(long offset, int size, Reason reason) { RangeSet remains = TreeRangeSet.create(); Range range = range(offset, size); remains.add(range); @@ -106,12 +106,13 @@ public class TraceMemoryStatePcodeExecutorStatePiece extends } @Override - protected TraceMemoryState getFromSpace(AddressSpace space, long offset, int size) { + protected TraceMemoryState getFromSpace(AddressSpace space, long offset, int size, + Reason reason) { return data.getViewportState(range(space, offset, size)); } @Override - protected TraceMemoryState getFromNullSpace(int size) { + protected TraceMemoryState getFromNullSpace(int size, Reason reason) { return TraceMemoryState.UNKNOWN; } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/pcode/exec/trace/TraceSleighUtils.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/pcode/exec/trace/TraceSleighUtils.java index 0274880034..f029a85f81 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/pcode/exec/trace/TraceSleighUtils.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/pcode/exec/trace/TraceSleighUtils.java @@ -23,6 +23,7 @@ import org.apache.commons.lang3.tuple.Pair; import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.pcode.exec.*; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.pcode.utils.Utils; import ghidra.program.model.address.AddressRange; import ghidra.program.model.address.AddressSpace; @@ -61,7 +62,7 @@ public enum TraceSleighUtils { throw new IllegalArgumentException("TracePlatform must use a SLEIGH language"); } return new PcodeExecutor<>((SleighLanguage) language, - BytesPcodeArithmetic.forLanguage(language), state); + BytesPcodeArithmetic.forLanguage(language), state, Reason.INSPECT); } /** @@ -102,7 +103,7 @@ public enum TraceSleighUtils { } return new PcodeExecutor<>((SleighLanguage) language, new PairedPcodeArithmetic<>( BytesPcodeArithmetic.forLanguage(language), TraceMemoryStatePcodeArithmetic.INSTANCE), - paired); + paired, Reason.INSPECT); } /** diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/pcode/exec/trace/BytesTracePcodeEmulatorTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/pcode/exec/trace/BytesTracePcodeEmulatorTest.java index 5a5072264e..ca05d01491 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/pcode/exec/trace/BytesTracePcodeEmulatorTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/pcode/exec/trace/BytesTracePcodeEmulatorTest.java @@ -29,13 +29,12 @@ import com.google.common.collect.Range; import ghidra.app.plugin.assembler.*; import ghidra.app.plugin.assembler.sleigh.sem.AssemblyPatternBlock; -import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.dbg.target.schema.SchemaContext; import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName; import ghidra.dbg.target.schema.XmlSchemaContext; -import ghidra.lifecycle.Unfinished; import ghidra.pcode.emu.PcodeThread; import ghidra.pcode.exec.*; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.pcode.exec.trace.data.PcodeTraceDataAccess; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressRangeImpl; @@ -158,7 +157,7 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest assertEquals(tb.addr(0x00400007), emuThread.getCounter()); assertArrayEquals(tb.arr(0x07, 0, 0x40, 0, 0, 0, 0, 0), - emuThread.getState().getVar(pc)); + emuThread.getState().getVar(pc, Reason.INSPECT)); emuThread.stepInstruction(); @@ -220,11 +219,11 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest assertEquals(tb.addr(0x00401000), emuThread.getCounter()); assertArrayEquals(tb.arr(0, 0x10, 0x40, 0), - emuThread.getState().getVar(pc)); + emuThread.getState().getVar(pc, Reason.INSPECT)); assertEquals(new RegisterValue(ctxreg, BigInteger.valueOf(0x8000_0000_0000_0000L)), emuThread.getContext()); assertArrayEquals(tb.arr(0x80, 0, 0, 0, 0, 0, 0, 0), - emuThread.getState().getVar(ctxreg)); + emuThread.getState().getVar(ctxreg, Reason.INSPECT)); emuThread.stepInstruction(); @@ -610,7 +609,7 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest assertEquals(tb.addr(0x00400007), emuThread.getCounter()); assertArrayEquals(tb.arr(0x07, 0, 0x40, 0, 0, 0, 0, 0), - emuThread.getState().getVar(pc)); + emuThread.getState().getVar(pc, Reason.INSPECT)); try (UndoableTransaction tid = tb.startTransaction()) { emu.writeDown(tb.host, 1, 1); @@ -647,7 +646,7 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest assertEquals(tb.addr(0x00400002), emuThread.getCounter()); assertArrayEquals(tb.arr(0x02, 0, 0x40, 0, 0, 0, 0, 0), - emuThread.getState().getVar(pc)); + emuThread.getState().getVar(pc, Reason.INSPECT)); try (UndoableTransaction tid = tb.startTransaction()) { emu.writeDown(tb.host, 1, 1); diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/pcode/exec/trace/TraceSleighUtilsTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/pcode/exec/trace/TraceSleighUtilsTest.java index a0cfef81d4..abd05a7421 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/pcode/exec/trace/TraceSleighUtilsTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/pcode/exec/trace/TraceSleighUtilsTest.java @@ -26,6 +26,7 @@ import org.junit.Test; import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.pcode.exec.*; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.program.model.lang.*; import ghidra.program.util.DefaultLanguageService; import ghidra.test.AbstractGhidraHeadlessIntegrationTest; @@ -220,7 +221,8 @@ public class TraceSleighUtilsTest extends AbstractGhidraHeadlessIntegrationTest PcodeExecutor executor = new PcodeExecutor<>(sp.getLanguage(), BytesPcodeArithmetic.forLanguage(b.language), - new DirectBytesTracePcodeExecutorState(b.host, 0, thread, 0)); + new DirectBytesTracePcodeExecutorState(b.host, 0, thread, 0), + Reason.EXECUTE); sp.execute(executor, PcodeUseropLibrary.nil()); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/model/time/schedule/TestThread.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/model/time/schedule/TestThread.java index 468fc60cfb..f671683259 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/model/time/schedule/TestThread.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/model/time/schedule/TestThread.java @@ -19,6 +19,7 @@ import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.pcode.emu.PcodeThread; import ghidra.pcode.emu.ThreadPcodeExecutorState; import ghidra.pcode.exec.*; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.program.model.address.Address; import ghidra.program.model.lang.RegisterValue; import ghidra.program.model.listing.Instruction; @@ -61,7 +62,7 @@ class TestThread implements PcodeThread { @Override public PcodeExecutor getExecutor() { return new PcodeExecutor<>(TraceScheduleTest.TOY_BE_64_LANG, machine.getArithmetic(), - getState()) { + getState(), Reason.EXECUTE) { public PcodeFrame execute(PcodeProgram program, PcodeUseropLibrary library) { machine.record.add("x:" + name); // TODO: Verify the actual effect diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/DefaultPcodeThread.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/DefaultPcodeThread.java index 3e991e686a..d06a060527 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/DefaultPcodeThread.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/DefaultPcodeThread.java @@ -22,6 +22,7 @@ import ghidra.app.emulator.Emulator; import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.pcode.exec.*; import ghidra.pcode.exec.PcodeArithmetic.Purpose; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.program.model.address.Address; import ghidra.program.model.lang.*; import ghidra.program.model.listing.Instruction; @@ -143,7 +144,7 @@ public class DefaultPcodeThread implements PcodeThread { * @param state the composite state assigned to the thread */ public PcodeThreadExecutor(DefaultPcodeThread thread) { - super(thread.language, thread.arithmetic, thread.state); + super(thread.language, thread.arithmetic, thread.state, Reason.EXECUTE); this.thread = thread; } @@ -340,12 +341,13 @@ public class DefaultPcodeThread implements PcodeThread { @Override public void reInitialize() { - long offset = arithmetic.toLong(state.getVar(pc), Purpose.BRANCH); + long offset = arithmetic.toLong(state.getVar(pc, executor.getReason()), Purpose.BRANCH); setCounter(language.getDefaultSpace().getAddress(offset, true)); if (contextreg != Register.NO_CONTEXT) { try { - BigInteger ctx = arithmetic.toBigInteger(state.getVar(contextreg), Purpose.CONTEXT); + BigInteger ctx = arithmetic.toBigInteger(state.getVar( + contextreg, executor.getReason()), Purpose.CONTEXT); assignContext(new RegisterValue(contextreg, ctx)); } catch (AccessPcodeExecutionException e) { diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/ModifiedPcodeThread.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/ModifiedPcodeThread.java index be8d0d2e07..b967904182 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/ModifiedPcodeThread.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/ModifiedPcodeThread.java @@ -177,7 +177,7 @@ public class ModifiedPcodeThread extends DefaultPcodeThread { */ protected int getBytesChunk(byte[] res, AddressSpace spc, long off, int size, boolean stopOnUnintialized) { - T t = state.getVar(spc, off, size, true); + T t = state.getVar(spc, off, size, true, executor.getReason()); byte[] val = arithmetic.toConcrete(t, Purpose.OTHER); System.arraycopy(val, 0, res, 0, val.length); return val.length; diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/ThreadPcodeExecutorState.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/ThreadPcodeExecutorState.java index 7f7263d4b4..8d7429c291 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/ThreadPcodeExecutorState.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/ThreadPcodeExecutorState.java @@ -82,11 +82,11 @@ public class ThreadPcodeExecutorState implements PcodeExecutorState { } @Override - public T getVar(AddressSpace space, T offset, int size, boolean quantize) { + public T getVar(AddressSpace space, T offset, int size, boolean quantize, Reason reason) { if (isThreadLocalSpace(space)) { - return localState.getVar(space, offset, size, quantize); + return localState.getVar(space, offset, size, quantize, reason); } - return sharedState.getVar(space, offset, size, quantize); + return sharedState.getVar(space, offset, size, quantize, reason); } @Override diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/linux/EmuLinuxAmd64SyscallUseropLibrary.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/linux/EmuLinuxAmd64SyscallUseropLibrary.java index 4107f7f041..c3f4138623 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/linux/EmuLinuxAmd64SyscallUseropLibrary.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/linux/EmuLinuxAmd64SyscallUseropLibrary.java @@ -26,7 +26,8 @@ import ghidra.pcode.emu.unix.EmuUnixFileSystem; import ghidra.pcode.emu.unix.EmuUnixUser; import ghidra.pcode.exec.PcodeArithmetic.Purpose; import ghidra.pcode.exec.PcodeExecutor; -import ghidra.pcode.exec.PcodeExecutorStatePiece; +import ghidra.pcode.exec.PcodeExecutorState; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.program.model.data.DataTypeManager; import ghidra.program.model.data.FileDataTypeManager; import ghidra.program.model.lang.Register; @@ -91,8 +92,8 @@ public class EmuLinuxAmd64SyscallUseropLibrary extends AbstractEmuLinuxSyscal } @Override - public long readSyscallNumber(PcodeExecutorStatePiece state) { - return machine.getArithmetic().toLong(state.getVar(regRAX), Purpose.OTHER); + public long readSyscallNumber(PcodeExecutorState state, Reason reason) { + return machine.getArithmetic().toLong(state.getVar(regRAX, reason), Purpose.OTHER); } @Override diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/linux/EmuLinuxX86SyscallUseropLibrary.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/linux/EmuLinuxX86SyscallUseropLibrary.java index d498468910..711f19e5a2 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/linux/EmuLinuxX86SyscallUseropLibrary.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/linux/EmuLinuxX86SyscallUseropLibrary.java @@ -27,6 +27,7 @@ import ghidra.pcode.emu.unix.EmuUnixFileSystem; import ghidra.pcode.emu.unix.EmuUnixUser; import ghidra.pcode.exec.*; import ghidra.pcode.exec.PcodeArithmetic.Purpose; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.program.model.data.DataTypeManager; import ghidra.program.model.data.FileDataTypeManager; import ghidra.program.model.lang.Register; @@ -92,8 +93,8 @@ public class EmuLinuxX86SyscallUseropLibrary extends AbstractEmuLinuxSyscallU } @Override - public long readSyscallNumber(PcodeExecutorStatePiece state) { - return machine.getArithmetic().toLong(state.getVar(regEAX), Purpose.OTHER); + public long readSyscallNumber(PcodeExecutorState state, Reason reason) { + return machine.getArithmetic().toLong(state.getVar(regEAX, reason), Purpose.OTHER); } @Override @@ -121,7 +122,7 @@ public class EmuLinuxX86SyscallUseropLibrary extends AbstractEmuLinuxSyscallU if (intNo == 0x80) { // A CALLIND follows to the return of swi().... OK. // We'll just make that "fall through" instead - T next = executor.getState().getVar(regEIP); + T next = executor.getState().getVar(regEIP, executor.getReason()); PcodeThreadExecutor te = (PcodeThreadExecutor) executor; int pcSize = regEIP.getNumBytes(); int iLen = te.getThread().getInstruction().getLength(); diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/sys/EmuSyscallLibrary.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/sys/EmuSyscallLibrary.java index 4cbedc8edc..a4c0dacd94 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/sys/EmuSyscallLibrary.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/sys/EmuSyscallLibrary.java @@ -24,6 +24,7 @@ import generic.jar.ResourceFile; import ghidra.framework.Application; import ghidra.pcode.exec.*; import ghidra.pcode.exec.AnnotatedPcodeUseropLibrary.*; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.program.model.address.AddressSpace; import ghidra.program.model.lang.PrototypeModel; import ghidra.program.model.listing.Function; @@ -206,9 +207,11 @@ public interface EmuSyscallLibrary extends PcodeUseropLibrary { * database. Until then, we require system-specific implementations. * * @param state the executor's state + * @param the reason for reading state, probably {@link Reason#EXECUTE}, but should be taken + * from the executor * @return the system call number */ - long readSyscallNumber(PcodeExecutorStatePiece state); + long readSyscallNumber(PcodeExecutorState state, Reason reason); /** * Try to handle an error, usually by returning it to the user program @@ -239,7 +242,7 @@ public interface EmuSyscallLibrary extends PcodeUseropLibrary { @PcodeUserop default void syscall(@OpExecutor PcodeExecutor executor, @OpLibrary PcodeUseropLibrary library) { - long syscallNumber = readSyscallNumber(executor.getState()); + long syscallNumber = readSyscallNumber(executor.getState(), executor.getReason()); EmuSyscallDefinition syscall = getSyscalls().get(syscallNumber); if (syscall == null) { throw new EmuInvalidSystemCallException(syscallNumber); diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/unix/AbstractEmuUnixSyscallUseropLibrary.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/unix/AbstractEmuUnixSyscallUseropLibrary.java index 62fd7ccbab..11a205130e 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/unix/AbstractEmuUnixSyscallUseropLibrary.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/unix/AbstractEmuUnixSyscallUseropLibrary.java @@ -24,6 +24,7 @@ import ghidra.pcode.emu.sys.EmuProcessExitedException; import ghidra.pcode.emu.unix.EmuUnixFileSystem.OpenFlag; import ghidra.pcode.exec.*; import ghidra.pcode.exec.PcodeArithmetic.Purpose; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.program.model.address.AddressSpace; import ghidra.program.model.data.StringDataInstance; import ghidra.program.model.data.StringDataType; @@ -286,7 +287,7 @@ public abstract class AbstractEmuUnixSyscallUseropLibrary // TODO: Not ideal to require concrete size. What are the alternatives, though? // TODO: size should actually be long (size_t) int size = (int) arithmetic.toLong(count, Purpose.OTHER); - T buf = state.getVar(space, bufPtr, size, true); + T buf = state.getVar(space, bufPtr, size, true, Reason.EXECUTE); // TODO: Write back into state? "write" shouldn't touch the buffer.... return desc.write(buf); } diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/AbstractBytesPcodeExecutorStatePiece.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/AbstractBytesPcodeExecutorStatePiece.java index 8ec2854d45..54c3d384aa 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/AbstractBytesPcodeExecutorStatePiece.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/AbstractBytesPcodeExecutorStatePiece.java @@ -17,7 +17,6 @@ package ghidra.pcode.exec; import java.nio.ByteBuffer; -import ghidra.pcode.exec.PcodeArithmetic.Purpose; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSpace; import ghidra.program.model.lang.Language; @@ -68,7 +67,8 @@ public abstract class AbstractBytesPcodeExecutorStatePiece * * @param offset the offset in unique space to get the value * @param size the number of bytes to read (the size of the value) + * @param reason the reason for reading state * @return the read value */ - protected T getUnique(long offset, int size) { + protected T getUnique(long offset, int size, Reason reason) { S s = getForSpace(uniqueSpace, false); - return getFromSpace(s, offset, size); + return getFromSpace(s, offset, size, reason); } /** @@ -200,9 +201,10 @@ public abstract class AbstractLongOffsetPcodeExecutorStatePiece * @param space the address space * @param offset the offset within the space * @param size the number of bytes to read (the size of the value) + * @param reason the reason for reading state * @return the read value */ - protected abstract T getFromSpace(S space, long offset, int size); + protected abstract T getFromSpace(S space, long offset, int size, Reason reason); /** * In case spaces are generated lazily, and we're reading from a space that doesn't yet exist, @@ -212,9 +214,10 @@ public abstract class AbstractLongOffsetPcodeExecutorStatePiece * By default, the returned value is 0, which should be reasonable for all implementations. * * @param size the number of bytes to read (the size of the value) + * @param reason the reason for reading state * @return the default value */ - protected T getFromNullSpace(int size) { + protected T getFromNullSpace(int size, Reason reason) { return arithmetic.fromConst(0, size); } @@ -240,25 +243,25 @@ public abstract class AbstractLongOffsetPcodeExecutorStatePiece } @Override - public T getVar(AddressSpace space, A offset, int size, boolean quantize) { + public T getVar(AddressSpace space, A offset, int size, boolean quantize, Reason reason) { long lOffset = addressArithmetic.toLong(offset, Purpose.LOAD); - return getVar(space, lOffset, size, quantize); + return getVar(space, lOffset, size, quantize, reason); } @Override - public T getVar(AddressSpace space, long offset, int size, boolean quantize) { + public T getVar(AddressSpace space, long offset, int size, boolean quantize, Reason reason) { checkRange(space, offset, size); if (space.isConstantSpace()) { return arithmetic.fromConst(offset, size); } if (space.isUniqueSpace()) { - return getUnique(offset, size); + return getUnique(offset, size, reason); } S s = getForSpace(space, false); if (s == null) { - return getFromNullSpace(size); + return getFromNullSpace(size, reason); } offset = quantizeOffset(space, offset); - return getFromSpace(s, offset, size); + return getFromSpace(s, offset, size, reason); } } diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/AddressOfPcodeExecutorStatePiece.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/AddressOfPcodeExecutorStatePiece.java index 441297c372..77e7aaa350 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/AddressOfPcodeExecutorStatePiece.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/AddressOfPcodeExecutorStatePiece.java @@ -75,7 +75,8 @@ public class AddressOfPcodeExecutorStatePiece } @Override - public Address getVar(AddressSpace space, byte[] offset, int size, boolean quantize) { + public Address getVar(AddressSpace space, byte[] offset, int size, boolean quantize, + Reason reason) { long lOffset = addressArithmetic.toLong(offset, Purpose.LOAD); if (!space.isUniqueSpace()) { return space.getAddress(lOffset); diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/AnnotatedPcodeUseropLibrary.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/AnnotatedPcodeUseropLibrary.java index 97816cae00..944be75ddd 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/AnnotatedPcodeUseropLibrary.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/AnnotatedPcodeUseropLibrary.java @@ -27,6 +27,7 @@ import java.util.stream.Stream; import org.apache.commons.lang3.reflect.TypeUtils; import ghidra.pcode.emu.linux.EmuLinuxAmd64SyscallUseropLibrary; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.program.model.pcode.Varnode; import utilities.util.AnnotationUtilities; @@ -352,7 +353,7 @@ public abstract class AnnotatedPcodeUseropLibrary implements PcodeUseropLibra for (int i = 0; i < posIns.size(); i++) { int pos = posIns.get(i); if (posTs.contains(pos)) { - args.set(pos, state.getVar(inVars.get(i))); + args.set(pos, state.getVar(inVars.get(i), executor.getReason())); } else { args.set(pos, inVars.get(i)); @@ -424,10 +425,11 @@ public abstract class AnnotatedPcodeUseropLibrary implements PcodeUseropLibra } } - protected Object[] readVars(PcodeExecutorState state, List vars) { + protected Object[] readVars(PcodeExecutorState state, List vars, + Reason reason) { Object[] vals = (Object[]) Array.newInstance(opRawType, vars.size()); for (int i = 0; i < vals.length; i++) { - vals[i] = state.getVar(vars.get(i)); + vals[i] = state.getVar(vars.get(i), reason); } return vals; } @@ -436,7 +438,7 @@ public abstract class AnnotatedPcodeUseropLibrary implements PcodeUseropLibra protected void placeInputs(PcodeExecutor executor, List args, List inVars) { if (opRawType != null) { - args.set(posIns, readVars(executor.getState(), inVars)); + args.set(posIns, readVars(executor.getState(), inVars, executor.getReason())); } else { args.set(posIns, inVars.toArray(Varnode[]::new)); diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/BytesPcodeExecutorStateSpace.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/BytesPcodeExecutorStateSpace.java index 984f362baa..539869423a 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/BytesPcodeExecutorStateSpace.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/BytesPcodeExecutorStateSpace.java @@ -21,6 +21,7 @@ import com.google.common.collect.*; import com.google.common.primitives.UnsignedLong; import ghidra.generic.util.datastruct.SemisparseByteArray; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.program.model.address.*; import ghidra.program.model.lang.Language; import ghidra.program.model.lang.Register; @@ -99,7 +100,7 @@ public class BytesPcodeExecutorStateSpace { * @param size the number of bytes to read (the size of the value) * @return the bytes read */ - protected byte[] readBytes(long offset, int size) { + protected byte[] readBytes(long offset, int size, Reason reason) { byte[] data = new byte[size]; bytes.getData(offset, data); return data; @@ -158,16 +159,17 @@ public class BytesPcodeExecutorStateSpace { * * @param offset the offset * @param size the number of bytes to read (the size of the value) + * @param reason the reason for reading state * @return the bytes read */ - public byte[] read(long offset, int size) { + public byte[] read(long offset, int size, Reason reason) { if (backing != null) { readUninitializedFromBacking(bytes.getUninitialized(offset, offset + size - 1)); } RangeSet stillUninit = bytes.getUninitialized(offset, offset + size - 1); - if (!stillUninit.isEmpty()) { + if (!stillUninit.isEmpty() && reason == Reason.EXECUTE) { warnUninit(stillUninit); } - return readBytes(offset, size); + return readBytes(offset, size, reason); } } diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/DefaultPcodeExecutorState.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/DefaultPcodeExecutorState.java index 346ca0341f..161386a101 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/DefaultPcodeExecutorState.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/DefaultPcodeExecutorState.java @@ -52,8 +52,8 @@ public class DefaultPcodeExecutorState implements PcodeExecutorState { } @Override - public T getVar(AddressSpace space, T offset, int size, boolean quantize) { - return piece.getVar(space, offset, size, quantize); + public T getVar(AddressSpace space, T offset, int size, boolean quantize, Reason reason) { + return piece.getVar(space, offset, size, quantize, reason); } @Override diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/PairedPcodeExecutorState.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/PairedPcodeExecutorState.java index 9721cc00ec..a824ddaaaf 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/PairedPcodeExecutorState.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/PairedPcodeExecutorState.java @@ -112,7 +112,8 @@ public class PairedPcodeExecutorState implements PcodeExecutorState getVar(AddressSpace space, Pair offset, int size, boolean quantize) { - return piece.getVar(space, offset.getLeft(), size, quantize); + public Pair getVar(AddressSpace space, Pair offset, int size, boolean quantize, + Reason reason) { + return piece.getVar(space, offset.getLeft(), size, quantize, reason); } } diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/PairedPcodeExecutorStatePiece.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/PairedPcodeExecutorStatePiece.java index ec1ee002cf..3724525e6b 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/PairedPcodeExecutorStatePiece.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/PairedPcodeExecutorStatePiece.java @@ -93,10 +93,11 @@ public class PairedPcodeExecutorStatePiece } @Override - public Pair getVar(AddressSpace space, A offset, int size, boolean quantize) { + public Pair getVar(AddressSpace space, A offset, int size, boolean quantize, + Reason reason) { return Pair.of( - left.getVar(space, offset, size, quantize), - right.getVar(space, offset, size, quantize)); + left.getVar(space, offset, size, quantize, reason), + right.getVar(space, offset, size, quantize, reason)); } @Override diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/PcodeArithmetic.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/PcodeArithmetic.java index fc4e4b5c3f..36cc91eedd 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/PcodeArithmetic.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/PcodeArithmetic.java @@ -45,7 +45,7 @@ public interface PcodeArithmetic { int SIZEOF_SIZEOF = 8; /** - * Various reasons the emulator may require a concrete value + * Reasons for requiring a concrete value */ enum Purpose { /** The value is needed to parse an instruction */ diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/PcodeExecutor.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/PcodeExecutor.java index 8d7a41dc76..457032631d 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/PcodeExecutor.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/PcodeExecutor.java @@ -22,6 +22,7 @@ import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.pcode.emu.PcodeEmulator; import ghidra.pcode.error.LowlevelError; import ghidra.pcode.exec.PcodeArithmetic.Purpose; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.pcode.exec.PcodeUseropLibrary.PcodeUseropDefinition; import ghidra.pcode.opbehavior.*; import ghidra.program.model.address.Address; @@ -43,6 +44,7 @@ public class PcodeExecutor { protected final SleighLanguage language; protected final PcodeArithmetic arithmetic; protected final PcodeExecutorState state; + protected final Reason reason; protected final Register pc; protected final int pointerSize; @@ -52,12 +54,14 @@ public class PcodeExecutor { * @param language the processor language * @param arithmetic an implementation of arithmetic p-code ops * @param state an implementation of load/store p-code ops + * @param reason a reason for reading the state with this executor */ public PcodeExecutor(SleighLanguage language, PcodeArithmetic arithmetic, - PcodeExecutorState state) { + PcodeExecutorState state, Reason reason) { this.language = language; this.arithmetic = arithmetic; this.state = state; + this.reason = reason; this.pc = language.getProgramCounter(); this.pointerSize = language.getDefaultSpace().getPointerSize(); @@ -90,6 +94,15 @@ public class PcodeExecutor { return state; } + /** + * Get the reason for reading state with this executor + * + * @return the reason + */ + public Reason getReason() { + return reason; + } + /** * Compile and execute a block of Sleigh * @@ -295,7 +308,7 @@ public class PcodeExecutor { public void executeUnaryOp(PcodeOp op, UnaryOpBehavior b) { Varnode in1Var = op.getInput(0); Varnode outVar = op.getOutput(); - T in1 = state.getVar(in1Var); + T in1 = state.getVar(in1Var, reason); T out = arithmetic.unaryOp(op, in1); state.setVar(outVar, out); } @@ -310,8 +323,8 @@ public class PcodeExecutor { Varnode in1Var = op.getInput(0); Varnode in2Var = op.getInput(1); Varnode outVar = op.getOutput(); - T in1 = state.getVar(in1Var); - T in2 = state.getVar(in2Var); + T in1 = state.getVar(in1Var, reason); + T in2 = state.getVar(in2Var, reason); T out = arithmetic.binaryOp(op, in1, in2); state.setVar(outVar, out); } @@ -325,10 +338,10 @@ public class PcodeExecutor { int spaceID = getIntConst(op.getInput(0)); AddressSpace space = language.getAddressFactory().getAddressSpace(spaceID); Varnode inOffset = op.getInput(1); - T offset = state.getVar(inOffset); + T offset = state.getVar(inOffset, reason); Varnode outvar = op.getOutput(); - T out = state.getVar(space, offset, outvar.getSize(), true); + T out = state.getVar(space, offset, outvar.getSize(), true, reason); T mod = arithmetic.modAfterLoad(outvar.getSize(), inOffset.getSize(), offset, outvar.getSize(), out); state.setVar(outvar, mod); @@ -343,10 +356,10 @@ public class PcodeExecutor { int spaceID = getIntConst(op.getInput(0)); AddressSpace space = language.getAddressFactory().getAddressSpace(spaceID); Varnode inOffset = op.getInput(1); - T offset = state.getVar(inOffset); + T offset = state.getVar(inOffset, reason); Varnode valVar = op.getInput(2); - T val = state.getVar(valVar); + T val = state.getVar(valVar, reason); T mod = arithmetic.modBeforeStore(valVar.getSize(), inOffset.getSize(), offset, valVar.getSize(), val); state.setVar(space, offset, valVar.getSize(), true, mod); @@ -425,7 +438,7 @@ public class PcodeExecutor { */ public void executeConditionalBranch(PcodeOp op, PcodeFrame frame) { Varnode condVar = op.getInput(1); - T cond = state.getVar(condVar); + T cond = state.getVar(condVar, reason); if (arithmetic.isTrue(cond, Purpose.CONDITION)) { doExecuteBranch(op, frame); } @@ -444,7 +457,7 @@ public class PcodeExecutor { * @param frame the frame */ protected void doExecuteIndirectBranch(PcodeOp op, PcodeFrame frame) { - T offset = state.getVar(op.getInput(0)); + T offset = state.getVar(op.getInput(0), reason); branchToOffset(offset, frame); long concrete = arithmetic.toLong(offset, Purpose.BRANCH); diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/PcodeExecutorStatePiece.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/PcodeExecutorStatePiece.java index 3c66f8ff7e..a968f3afb3 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/PcodeExecutorStatePiece.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/PcodeExecutorStatePiece.java @@ -39,6 +39,16 @@ import ghidra.program.model.pcode.Varnode; */ public interface PcodeExecutorStatePiece { + /** + * Reasons for reading state + */ + enum Reason { + /** The value is needed by the emulator in the course of execution */ + EXECUTE, + /** The value is being inspected */ + INSPECT + } + /** * Construct a range, if only to verify the range is valid * @@ -141,23 +151,25 @@ public interface PcodeExecutorStatePiece { * Get the value of a register variable * * @param reg the register + * @param reason the reason for reading the register * @return the value */ - default T getVar(Register reg) { + default T getVar(Register reg, Reason reason) { Address address = reg.getAddress(); return getVar(address.getAddressSpace(), address.getOffset(), reg.getMinimumByteSize(), - true); + true, reason); } /** * Get the value of a variable * * @param var the variable + * @param reason the reason for reading the variable * @return the value */ - default T getVar(Varnode var) { + default T getVar(Varnode var, Reason reason) { Address address = var.getAddress(); - return getVar(address.getAddressSpace(), address.getOffset(), var.getSize(), true); + return getVar(address.getAddressSpace(), address.getOffset(), var.getSize(), true, reason); } /** @@ -167,9 +179,10 @@ public interface PcodeExecutorStatePiece { * @param offset the offset within the space * @param size the size of the variable * @param quantize true to quantize to the language's "addressable unit" + * @param reason the reason for reading the variable * @return the value */ - T getVar(AddressSpace space, A offset, int size, boolean quantize); + T getVar(AddressSpace space, A offset, int size, boolean quantize, Reason reason); /** * Get the value of a variable @@ -181,12 +194,13 @@ public interface PcodeExecutorStatePiece { * @param offset the offset within the space * @param size the size of the variable * @param quantize true to quantize to the language's "addressable unit" + * @param reason the reason for reading the variable * @return the value */ - default T getVar(AddressSpace space, long offset, int size, boolean quantize) { + default T getVar(AddressSpace space, long offset, int size, boolean quantize, Reason reason) { checkRange(space, offset, size); A aOffset = getAddressArithmetic().fromConst(offset, space.getPointerSize()); - return getVar(space, aOffset, size, quantize); + return getVar(space, aOffset, size, quantize, reason); } /** @@ -198,10 +212,11 @@ public interface PcodeExecutorStatePiece { * @param address the address of the variable * @param size the size of the variable * @param quantize true to quantize to the language's "addressable unit" + * @param reason the reason for reading the variable * @return the value */ - default T getVar(Address address, int size, boolean quantize) { - return getVar(address.getAddressSpace(), address.getOffset(), size, quantize); + default T getVar(Address address, int size, boolean quantize, Reason reason) { + return getVar(address.getAddressSpace(), address.getOffset(), size, quantize, reason); } /** diff --git a/Ghidra/Debug/ProposedUtils/src/test/java/ghidra/pcode/emu/linux/EmuLinuxAmd64SyscallUseropLibraryTest.java b/Ghidra/Debug/ProposedUtils/src/test/java/ghidra/pcode/emu/linux/EmuLinuxAmd64SyscallUseropLibraryTest.java index a8484bb9bd..3527fc889b 100644 --- a/Ghidra/Debug/ProposedUtils/src/test/java/ghidra/pcode/emu/linux/EmuLinuxAmd64SyscallUseropLibraryTest.java +++ b/Ghidra/Debug/ProposedUtils/src/test/java/ghidra/pcode/emu/linux/EmuLinuxAmd64SyscallUseropLibraryTest.java @@ -35,6 +35,7 @@ import ghidra.pcode.emu.sys.SyscallTestHelper.SyscallName; import ghidra.pcode.emu.unix.*; import ghidra.pcode.exec.*; import ghidra.pcode.exec.PcodeArithmetic.Purpose; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSpace; import ghidra.program.model.lang.Language; @@ -210,7 +211,7 @@ public class EmuLinuxAmd64SyscallUseropLibraryTest extends AbstractGhidraHeadles // Step through write and verify return value and actual output effect thread.stepInstruction(5); assertArrayEquals(arithmetic.fromConst(BYTES_HW.length, regRAX.getNumBytes()), - thread.getState().getVar(regRAX)); + thread.getState().getVar(regRAX, Reason.INSPECT)); assertArrayEquals(BYTES_HW, stdout.toByteArray()); stepGroupExit(thread); @@ -241,9 +242,9 @@ public class EmuLinuxAmd64SyscallUseropLibraryTest extends AbstractGhidraHeadles // Step through write and verify return value and actual output effect thread.stepInstruction(5); assertArrayEquals(arithmetic.fromConst(BYTES_HW.length, regRAX.getNumBytes()), - thread.getState().getVar(regRAX)); + thread.getState().getVar(regRAX, Reason.INSPECT)); assertArrayEquals(BYTES_HW, - emu.getSharedState().getVar(space, 0x00400800, BYTES_HW.length, true)); + emu.getSharedState().getVar(space, 0x00400800, BYTES_HW.length, true, Reason.INSPECT)); stepGroupExit(thread); } @@ -295,7 +296,7 @@ public class EmuLinuxAmd64SyscallUseropLibraryTest extends AbstractGhidraHeadles thread.stepInstruction(5); assertEquals(BYTES_HW.length, - arithmetic.toLong(thread.getState().getVar(regRAX), Purpose.OTHER)); + arithmetic.toLong(thread.getState().getVar(regRAX, Reason.INSPECT), Purpose.OTHER)); assertArrayEquals(BYTES_HW, stdout.toByteArray()); stepGroupExit(thread); @@ -350,11 +351,11 @@ public class EmuLinuxAmd64SyscallUseropLibraryTest extends AbstractGhidraHeadles thread.stepInstruction(5); assertEquals(BYTES_HW.length, - arithmetic.toLong(thread.getState().getVar(regRAX), Purpose.OTHER)); - assertArrayEquals(BYTES_HELLO, - emu.getSharedState().getVar(space, strHello.getOffset(), BYTES_HELLO.length, true)); - assertArrayEquals(BYTES_WORLD, - emu.getSharedState().getVar(space, strWorld.getOffset(), BYTES_WORLD.length, true)); + arithmetic.toLong(thread.getState().getVar(regRAX, Reason.INSPECT), Purpose.OTHER)); + assertArrayEquals(BYTES_HELLO, emu.getSharedState() + .getVar(space, strHello.getOffset(), BYTES_HELLO.length, true, Reason.INSPECT)); + assertArrayEquals(BYTES_WORLD, emu.getSharedState() + .getVar(space, strWorld.getOffset(), BYTES_WORLD.length, true, Reason.INSPECT)); stepGroupExit(thread); } @@ -431,6 +432,6 @@ public class EmuLinuxAmd64SyscallUseropLibraryTest extends AbstractGhidraHeadles execute(thread); assertArrayEquals(BYTES_HW, - emu.getSharedState().getVar(space, 0x00400800, BYTES_HW.length, true)); + emu.getSharedState().getVar(space, 0x00400800, BYTES_HW.length, true, Reason.INSPECT)); } } diff --git a/Ghidra/Debug/ProposedUtils/src/test/java/ghidra/pcode/emu/linux/EmuLinuxX86SyscallUseropLibraryTest.java b/Ghidra/Debug/ProposedUtils/src/test/java/ghidra/pcode/emu/linux/EmuLinuxX86SyscallUseropLibraryTest.java index fe1a1da8d0..2254db366e 100644 --- a/Ghidra/Debug/ProposedUtils/src/test/java/ghidra/pcode/emu/linux/EmuLinuxX86SyscallUseropLibraryTest.java +++ b/Ghidra/Debug/ProposedUtils/src/test/java/ghidra/pcode/emu/linux/EmuLinuxX86SyscallUseropLibraryTest.java @@ -36,6 +36,7 @@ import ghidra.pcode.emu.sys.SyscallTestHelper.SyscallName; import ghidra.pcode.emu.unix.*; import ghidra.pcode.exec.*; import ghidra.pcode.exec.PcodeArithmetic.Purpose; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSpace; import ghidra.program.model.lang.Register; @@ -210,7 +211,7 @@ public class EmuLinuxX86SyscallUseropLibraryTest extends AbstractGhidraHeadlessI // Step through write and verify return value and actual output effect thread.stepInstruction(5); assertArrayEquals(arithmetic.fromConst(BYTES_HW.length, regEAX.getNumBytes()), - thread.getState().getVar(regEAX)); + thread.getState().getVar(regEAX, Reason.INSPECT)); assertArrayEquals(BYTES_HW, stdout.toByteArray()); stepGroupExit(thread); @@ -241,9 +242,9 @@ public class EmuLinuxX86SyscallUseropLibraryTest extends AbstractGhidraHeadlessI // Step through write and verify return value and actual output effect thread.stepInstruction(5); assertArrayEquals(arithmetic.fromConst(BYTES_HW.length, regEAX.getNumBytes()), - thread.getState().getVar(regEAX)); + thread.getState().getVar(regEAX, Reason.INSPECT)); assertArrayEquals(BYTES_HW, - emu.getSharedState().getVar(space, 0x00400800, BYTES_HW.length, true)); + emu.getSharedState().getVar(space, 0x00400800, BYTES_HW.length, true, Reason.INSPECT)); stepGroupExit(thread); } @@ -295,7 +296,7 @@ public class EmuLinuxX86SyscallUseropLibraryTest extends AbstractGhidraHeadlessI thread.stepInstruction(5); assertEquals(BYTES_HW.length, - arithmetic.toLong(thread.getState().getVar(regEAX), Purpose.OTHER)); + arithmetic.toLong(thread.getState().getVar(regEAX, Reason.INSPECT), Purpose.OTHER)); assertArrayEquals(BYTES_HW, stdout.toByteArray()); stepGroupExit(thread); @@ -350,11 +351,11 @@ public class EmuLinuxX86SyscallUseropLibraryTest extends AbstractGhidraHeadlessI thread.stepInstruction(5); assertEquals(BYTES_HW.length, - arithmetic.toLong(thread.getState().getVar(regEAX), Purpose.OTHER)); - assertArrayEquals(BYTES_HELLO, - emu.getSharedState().getVar(space, strHello.getOffset(), BYTES_HELLO.length, true)); - assertArrayEquals(BYTES_WORLD, - emu.getSharedState().getVar(space, strWorld.getOffset(), BYTES_WORLD.length, true)); + arithmetic.toLong(thread.getState().getVar(regEAX, Reason.INSPECT), Purpose.OTHER)); + assertArrayEquals(BYTES_HELLO, emu.getSharedState() + .getVar(space, strHello.getOffset(), BYTES_HELLO.length, true, Reason.INSPECT)); + assertArrayEquals(BYTES_WORLD, emu.getSharedState() + .getVar(space, strWorld.getOffset(), BYTES_WORLD.length, true, Reason.INSPECT)); stepGroupExit(thread); } @@ -431,6 +432,6 @@ public class EmuLinuxX86SyscallUseropLibraryTest extends AbstractGhidraHeadlessI execute(thread); assertArrayEquals(BYTES_HW, - emu.getSharedState().getVar(space, 0x00400800, BYTES_HW.length, true)); + emu.getSharedState().getVar(space, 0x00400800, BYTES_HW.length, true, Reason.INSPECT)); } } diff --git a/Ghidra/Debug/ProposedUtils/src/test/java/ghidra/pcode/emu/sys/EmuAmd64SyscallUseropLibraryTest.java b/Ghidra/Debug/ProposedUtils/src/test/java/ghidra/pcode/emu/sys/EmuAmd64SyscallUseropLibraryTest.java index 548c7bc888..ae81d002d8 100644 --- a/Ghidra/Debug/ProposedUtils/src/test/java/ghidra/pcode/emu/sys/EmuAmd64SyscallUseropLibraryTest.java +++ b/Ghidra/Debug/ProposedUtils/src/test/java/ghidra/pcode/emu/sys/EmuAmd64SyscallUseropLibraryTest.java @@ -27,6 +27,7 @@ import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.pcode.emu.*; import ghidra.pcode.exec.*; import ghidra.pcode.exec.PcodeArithmetic.Purpose; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.program.model.address.*; import ghidra.program.model.data.DataTypeConflictHandler; import ghidra.program.model.data.PointerDataType; @@ -62,8 +63,8 @@ public class EmuAmd64SyscallUseropLibraryTest extends AbstractGhidraHeadlessInte } @Override - public long readSyscallNumber(PcodeExecutorStatePiece state) { - return machine.getArithmetic().toLong(state.getVar(regRAX), Purpose.OTHER); + public long readSyscallNumber(PcodeExecutorState state, Reason reason) { + return machine.getArithmetic().toLong(state.getVar(regRAX, reason), Purpose.OTHER); } @PcodeUserop @@ -192,7 +193,7 @@ public class EmuAmd64SyscallUseropLibraryTest extends AbstractGhidraHeadlessInte thread.stepInstruction(4); assertArrayEquals(arithmetic.fromConst(0xbeef, regRAX.getNumBytes()), - thread.getState().getVar(regRAX)); + thread.getState().getVar(regRAX, Reason.INSPECT)); } @Test @@ -211,6 +212,6 @@ public class EmuAmd64SyscallUseropLibraryTest extends AbstractGhidraHeadlessInte thread.stepInstruction(4); assertArrayEquals(arithmetic.fromConst(0xbeef, regRAX.getNumBytes()), - thread.getState().getVar(regRAX)); + thread.getState().getVar(regRAX, Reason.INSPECT)); } } diff --git a/Ghidra/Debug/ProposedUtils/src/test/java/ghidra/pcode/exec/AnnotatedPcodeUseropLibraryTest.java b/Ghidra/Debug/ProposedUtils/src/test/java/ghidra/pcode/exec/AnnotatedPcodeUseropLibraryTest.java index 601b94ee6a..690c60e698 100644 --- a/Ghidra/Debug/ProposedUtils/src/test/java/ghidra/pcode/exec/AnnotatedPcodeUseropLibraryTest.java +++ b/Ghidra/Debug/ProposedUtils/src/test/java/ghidra/pcode/exec/AnnotatedPcodeUseropLibraryTest.java @@ -25,6 +25,7 @@ import org.junit.Test; import ghidra.app.plugin.processors.sleigh.SleighException; import ghidra.app.plugin.processors.sleigh.SleighLanguage; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.pcode.utils.Utils; import ghidra.program.model.lang.LanguageID; import ghidra.program.model.lang.Register; @@ -48,7 +49,7 @@ public class AnnotatedPcodeUseropLibraryTest extends AbstractGhidraHeadlessInteg (SleighLanguage) getLanguageService().getLanguage(new LanguageID(languageId)); PcodeExecutorState state = new BytesPcodeExecutorState(language); PcodeArithmetic arithmetic = BytesPcodeArithmetic.forLanguage(language); - return new PcodeExecutor<>(language, arithmetic, state); + return new PcodeExecutor<>(language, arithmetic, state, Reason.EXECUTE); } protected void executeSleigh(PcodeExecutor executor, PcodeUseropLibrary library, @@ -154,7 +155,7 @@ public class AnnotatedPcodeUseropLibraryTest extends AbstractGhidraHeadlessInteg Register r0 = executor.getLanguage().getRegister("r0"); executeSleigh(executor, library, "r0 = __testop();"); - assertBytes(1234, 8, executor.getState().getVar(r0)); + assertBytes(1234, 8, executor.getState().getVar(r0, Reason.INSPECT)); } @Test @@ -174,7 +175,7 @@ public class AnnotatedPcodeUseropLibraryTest extends AbstractGhidraHeadlessInteg executor.getState().setVar(r0, Utils.longToBytes(10, 8, true)); executeSleigh(executor, library, "r1 = __testop(r0, 59:8);"); - assertBytes(159, 8, executor.getState().getVar(r1)); + assertBytes(159, 8, executor.getState().getVar(r1, Reason.INSPECT)); } @Test @@ -281,7 +282,7 @@ public class AnnotatedPcodeUseropLibraryTest extends AbstractGhidraHeadlessInteg assertRegVarnode(r0, library.outVar); assertRegVarnode(r1, library.inVar0); assertBytes(1234, 8, library.inVal1); - assertBytes(1234, 8, executor.getState().getVar(r0)); + assertBytes(1234, 8, executor.getState().getVar(r0, Reason.INSPECT)); } @Test(expected = SleighException.class) diff --git a/Ghidra/Debug/TaintAnalysis/src/main/java/ghidra/pcode/emu/taint/AbstractTaintPcodeExecutorStatePiece.java b/Ghidra/Debug/TaintAnalysis/src/main/java/ghidra/pcode/emu/taint/AbstractTaintPcodeExecutorStatePiece.java index 36bf8ad17d..f770b3aa40 100644 --- a/Ghidra/Debug/TaintAnalysis/src/main/java/ghidra/pcode/emu/taint/AbstractTaintPcodeExecutorStatePiece.java +++ b/Ghidra/Debug/TaintAnalysis/src/main/java/ghidra/pcode/emu/taint/AbstractTaintPcodeExecutorStatePiece.java @@ -68,7 +68,7 @@ public abstract class AbstractTaintPcodeExecutorStatePiece * Extension point: Create the actual space map * *

- * This will need to be implemented by each state piece, i.e., non-abstract derivating class. + * This will need to be implemented by each state piece, i.e., non-abstract derivative class. * The space map will provide instances of {@code }, which will provide the actual (extended) * storage logic. * @@ -100,7 +100,7 @@ public abstract class AbstractTaintPcodeExecutorStatePiece * the storage space. */ @Override - protected void setInSpace(TaintSpace space, long offset, int size, TaintVec val) { + protected void setInSpace(S space, long offset, int size, TaintVec val) { space.set(offset, val); } @@ -112,7 +112,7 @@ public abstract class AbstractTaintPcodeExecutorStatePiece * the storage space. */ @Override - protected TaintVec getFromSpace(TaintSpace space, long offset, int size) { + protected TaintVec getFromSpace(S space, long offset, int size, Reason reason) { return space.get(offset, size); } } diff --git a/Ghidra/Debug/TaintAnalysis/src/main/java/ghidra/pcode/emu/taint/TaintPcodeThreadExecutor.java b/Ghidra/Debug/TaintAnalysis/src/main/java/ghidra/pcode/emu/taint/TaintPcodeThreadExecutor.java index b4716e4c72..c3f9cc294c 100644 --- a/Ghidra/Debug/TaintAnalysis/src/main/java/ghidra/pcode/emu/taint/TaintPcodeThreadExecutor.java +++ b/Ghidra/Debug/TaintAnalysis/src/main/java/ghidra/pcode/emu/taint/TaintPcodeThreadExecutor.java @@ -58,7 +58,7 @@ public class TaintPcodeThreadExecutor extends PcodeThreadExecutor condition = state.getVar(op.getInput(1)); + Pair condition = state.getVar(op.getInput(1), reason); TaintVec taint = condition.getRight(); if (!taint.union().isEmpty()) { // getInstruction may return null if an inject executes a CBRANCH diff --git a/Ghidra/Debug/TaintAnalysis/src/test/java/ghidra/pcode/emu/taint/plain/TaintPcodeEmulatorTest.java b/Ghidra/Debug/TaintAnalysis/src/test/java/ghidra/pcode/emu/taint/plain/TaintPcodeEmulatorTest.java index 07c1afc0e7..8df3ac6663 100644 --- a/Ghidra/Debug/TaintAnalysis/src/test/java/ghidra/pcode/emu/taint/plain/TaintPcodeEmulatorTest.java +++ b/Ghidra/Debug/TaintAnalysis/src/test/java/ghidra/pcode/emu/taint/plain/TaintPcodeEmulatorTest.java @@ -31,6 +31,7 @@ import ghidra.pcode.emu.sys.EmuProcessExitedException; import ghidra.pcode.emu.taint.lib.TaintEmuUnixFileSystem; import ghidra.pcode.emu.taint.lib.TaintFileReadsLinuxAmd64SyscallLibrary; import ghidra.pcode.exec.PcodeUseropLibrary; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.pcode.utils.Utils; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSpace; @@ -146,7 +147,7 @@ public class TaintPcodeEmulatorTest extends AbstractGhidraHeadlessIntegrationTes thread.overrideContextWithDefault(); thread.stepInstruction(); - Pair endRAX = thread.getState().getVar(regRAX); + Pair endRAX = thread.getState().getVar(regRAX, Reason.INSPECT); assertEquals(0, Utils.bytesToLong(endRAX.getLeft(), regRAX.getNumBytes(), language.isBigEndian())); assertEquals(TaintVec.empties(regRAX.getNumBytes()), endRAX.getRight()); @@ -184,8 +185,8 @@ public class TaintPcodeEmulatorTest extends AbstractGhidraHeadlessIntegrationTes PcodeThread thread = launchThread(start); execute(thread); - Pair buf = - emulator.getSharedState().getVar(space, 0x00400800, BYTES_HW.length, true); + Pair buf = emulator.getSharedState() + .getVar(space, 0x00400800, BYTES_HW.length, true, Reason.INSPECT); assertArrayEquals(BYTES_HW, buf.getLeft()); assertEquals(TaintVec.array("myfile", 0, BYTES_HW.length), buf.getRight()); } @@ -197,7 +198,7 @@ public class TaintPcodeEmulatorTest extends AbstractGhidraHeadlessIntegrationTes thread.getExecutor().executeSleigh("*:8 0x00400000:8 = taint_arr(*:8 0x004000000:8);"); Pair taintVal = - emulator.getSharedState().getVar(space, 0x00400000, 8, true); + emulator.getSharedState().getVar(space, 0x00400000, 8, true, Reason.INSPECT); assertArrayEquals(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, taintVal.getLeft()); assertEquals(TaintVec.array("arr_0", 0, 8), taintVal.getRight()); } @@ -227,7 +228,7 @@ public class TaintPcodeEmulatorTest extends AbstractGhidraHeadlessIntegrationTes thread.overrideContextWithDefault(); thread.stepInstruction(); - Pair endRBX = thread.getState().getVar(regRBX); + Pair endRBX = thread.getState().getVar(regRBX, Reason.INSPECT); assertEquals(0x100f0e0d0c0b0a09L, Utils.bytesToLong(endRBX.getLeft(), regRBX.getNumBytes(), language.isBigEndian())); TaintSet fromIndirect = TaintVec.array("RAX", 0, 8).union().tagged("indR"); @@ -262,7 +263,7 @@ public class TaintPcodeEmulatorTest extends AbstractGhidraHeadlessIntegrationTes thread.stepInstruction(); Pair endMem = - emulator.getSharedState().getVar(dyn, 0x0807060504030201L, 8, true); + emulator.getSharedState().getVar(dyn, 0x0807060504030201L, 8, true, Reason.INSPECT); assertEquals(0x100f0e0d0c0b0a09L, Utils.bytesToLong(endMem.getLeft(), regRBX.getNumBytes(), language.isBigEndian())); TaintSet fromIndirect = TaintVec.array("RAX", 0, 8).union().tagged("indW"); @@ -293,7 +294,7 @@ public class TaintPcodeEmulatorTest extends AbstractGhidraHeadlessIntegrationTes thread.overrideContextWithDefault(); thread.stepInstruction(); - Pair endRAX = thread.getState().getVar(regRAX); + Pair endRAX = thread.getState().getVar(regRAX, Reason.INSPECT); assertEquals(0, Utils.bytesToLong(endRAX.getLeft(), regRAX.getNumBytes(), language.isBigEndian())); assertEquals(TaintVec.empties(regRAX.getNumBytes()), endRAX.getRight()); diff --git a/Ghidra/Debug/TaintAnalysis/src/test/java/ghidra/pcode/emu/taint/trace/TaintTracePcodeEmulatorTest.java b/Ghidra/Debug/TaintAnalysis/src/test/java/ghidra/pcode/emu/taint/trace/TaintTracePcodeEmulatorTest.java index dd97b2c7ca..35e66c0bda 100644 --- a/Ghidra/Debug/TaintAnalysis/src/test/java/ghidra/pcode/emu/taint/trace/TaintTracePcodeEmulatorTest.java +++ b/Ghidra/Debug/TaintAnalysis/src/test/java/ghidra/pcode/emu/taint/trace/TaintTracePcodeEmulatorTest.java @@ -33,6 +33,7 @@ import ghidra.dbg.target.schema.SchemaContext; import ghidra.dbg.target.schema.XmlSchemaContext; import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName; import ghidra.pcode.emu.PcodeThread; +import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.pcode.exec.trace.AbstractTracePcodeEmulatorTest; import ghidra.program.model.address.*; import ghidra.program.model.lang.Register; @@ -90,7 +91,7 @@ public class TaintTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest emuThread.getExecutor().executeSleigh("RAX = *0x00400000:8;"); Pair valRAX = - emuThread.getState().getVar(tb.language.getRegister("RAX")); + emuThread.getState().getVar(tb.language.getRegister("RAX"), Reason.INSPECT); TaintVec exp = TaintVec.empties(8); TaintSet testTaint = TaintSet.of(new TaintMark("test_0", Set.of())); for (int i = 0; i < 4; i++) { @@ -120,7 +121,7 @@ public class TaintTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest emuThread.getExecutor().executeSleigh("RAX = RBX;"); Pair valRAX = - emuThread.getState().getVar(regRAX); + emuThread.getState().getVar(regRAX, Reason.INSPECT); TaintVec exp = TaintVec.empties(8); TaintSet testTaint = TaintSet.of(new TaintMark("test_0", Set.of())); for (int i = 0; i < 4; i++) {