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 beab74594d..d78bdfdc31 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 @@ -186,7 +186,7 @@ public class WatchRow { private ReadDepsTraceBytesPcodeExecutorState depsState; public ReadDepsPcodeExecutor(ReadDepsTraceBytesPcodeExecutorState depsState, - Language language, PairedPcodeArithmetic arithmetic, + SleighLanguage language, PairedPcodeArithmetic arithmetic, PcodeExecutorState> state) { super(language, arithmetic, state); this.depsState = depsState; @@ -211,11 +211,14 @@ public class WatchRow { new ReadDepsTraceBytesPcodeExecutorState(trace, coordinates.getViewSnap(), coordinates.getThread(), coordinates.getFrame()); Language language = trace.getBaseLanguage(); + if (!(language instanceof SleighLanguage)) { + throw new IllegalArgumentException("Watch expressions require a SLEIGH language"); + } PcodeExecutorState> paired = state.paired(new AddressOfPcodeExecutorState(language.isBigEndian())); PairedPcodeArithmetic arithmetic = new PairedPcodeArithmetic<>( BytesPcodeArithmetic.forLanguage(language), AddressOfPcodeArithmetic.INSTANCE); - return new ReadDepsPcodeExecutor(state, language, arithmetic, paired); + return new ReadDepsPcodeExecutor(state, (SleighLanguage) language, arithmetic, paired); } public void setCoordinates(DebuggerCoordinates coordinates) { diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/pcode/exec/AsyncPcodeExecutor.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/pcode/exec/AsyncPcodeExecutor.java index 52585a1312..7bf23aa13b 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/pcode/exec/AsyncPcodeExecutor.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/pcode/exec/AsyncPcodeExecutor.java @@ -19,8 +19,8 @@ import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; +import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.async.AsyncUtils; -import ghidra.program.model.lang.Language; import ghidra.program.model.pcode.PcodeOp; import ghidra.program.model.pcode.Varnode; @@ -39,9 +39,10 @@ import ghidra.program.model.pcode.Varnode; * @param the type of values in the state */ public class AsyncPcodeExecutor extends PcodeExecutor> { - public AsyncPcodeExecutor(Language language, PcodeArithmetic> behavior, + public AsyncPcodeExecutor(SleighLanguage language, + PcodeArithmetic> arithmetic, PcodeExecutorStatePiece, CompletableFuture> state) { - super(language, behavior, state); + super(language, arithmetic, state); } public CompletableFuture stepOpAsync(PcodeOp op, PcodeFrame frame, diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/pcode/exec/TraceRecorderAsyncPcodeExecTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/pcode/exec/TraceRecorderAsyncPcodeExecTest.java index ac3ab76533..0a81ca9e37 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/pcode/exec/TraceRecorderAsyncPcodeExecTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/pcode/exec/TraceRecorderAsyncPcodeExecTest.java @@ -30,7 +30,6 @@ import ghidra.app.services.TraceRecorder; import ghidra.dbg.model.TestTargetRegisterBankInThread; import ghidra.dbg.testutil.DebuggerModelTestUtils; import ghidra.pcode.utils.Utils; -import ghidra.program.model.lang.Language; import ghidra.program.model.lang.Register; import ghidra.trace.model.Trace; import ghidra.trace.model.thread.TraceThread; @@ -55,10 +54,10 @@ public class TraceRecorderAsyncPcodeExecTest extends AbstractGhidraHeadedDebugge TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1)); Trace trace = recorder.getTrace(); - Language language = trace.getBaseLanguage(); + SleighLanguage language = (SleighLanguage) trace.getBaseLanguage(); SleighExpression expr = SleighProgramCompiler - .compileExpression((SleighLanguage) language, "r0 + r1"); + .compileExpression(language, "r0 + r1"); Register r0 = language.getRegister("r0"); Register r1 = language.getRegister("r1"); @@ -98,9 +97,9 @@ public class TraceRecorderAsyncPcodeExecTest extends AbstractGhidraHeadedDebugge TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1)); Trace trace = recorder.getTrace(); - Language language = trace.getBaseLanguage(); + SleighLanguage language = (SleighLanguage) trace.getBaseLanguage(); - PcodeProgram prog = SleighProgramCompiler.compileProgram((SleighLanguage) language, "test", + PcodeProgram prog = SleighProgramCompiler.compileProgram(language, "test", List.of("r2 = r0 + r1;"), SleighUseropLibrary.NIL); Register r0 = language.getRegister("r0"); 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 00679bb6f8..5ce6902343 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 @@ -51,7 +51,11 @@ public enum TraceSleighUtils { TraceBytesPcodeExecutorState state = new TraceBytesPcodeExecutorState(trace, snap, thread, frame); Language language = trace.getBaseLanguage(); - return new PcodeExecutor<>(language, BytesPcodeArithmetic.forLanguage(language), state); + if (!(language instanceof SleighLanguage)) { + throw new IllegalArgumentException("Trace must use a SLEIGH language"); + } + return new PcodeExecutor<>((SleighLanguage) language, + BytesPcodeArithmetic.forLanguage(language), state); } public static PcodeExecutor> buildByteWithStateExecutor( @@ -60,9 +64,12 @@ public enum TraceSleighUtils { new TraceBytesPcodeExecutorState(trace, snap, thread, frame); PcodeExecutorState> paired = state.withMemoryState(); Language language = trace.getBaseLanguage(); - return new PcodeExecutor<>(language, new PairedPcodeArithmetic<>( - BytesPcodeArithmetic.forLanguage(language), - TraceMemoryStatePcodeArithmetic.INSTANCE), paired); + if (!(language instanceof SleighLanguage)) { + throw new IllegalArgumentException("Trace must use a SLEIGH language"); + } + return new PcodeExecutor<>((SleighLanguage) language, new PairedPcodeArithmetic<>( + BytesPcodeArithmetic.forLanguage(language), TraceMemoryStatePcodeArithmetic.INSTANCE), + paired); } public static byte[] evaluateBytes(SleighExpression expr, Trace trace, long snap, diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/AbstractModifiedPcodeThread.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/AbstractModifiedPcodeThread.java index 1482f663b1..66c7b06dae 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/AbstractModifiedPcodeThread.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/AbstractModifiedPcodeThread.java @@ -86,7 +86,7 @@ public abstract class AbstractModifiedPcodeThread extends DefaultPcodeThread< } protected class GluePcodeThreadExecutor extends PcodeThreadExecutor { - public GluePcodeThreadExecutor(Language language, PcodeArithmetic arithmetic, + public GluePcodeThreadExecutor(SleighLanguage language, PcodeArithmetic arithmetic, PcodeExecutorStatePiece state) { super(language, arithmetic, state); } diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/AbstractPcodeMachine.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/AbstractPcodeMachine.java index b4f3ba0368..e7ed80b25a 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/AbstractPcodeMachine.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/AbstractPcodeMachine.java @@ -57,6 +57,26 @@ public abstract class AbstractPcodeMachine implements PcodeMachine { this.initializer = getPluggableInitializer(language); } + @Override + public SleighLanguage getLanguage() { + return language; + } + + @Override + public PcodeArithmetic getArithmetic() { + return arithmetic; + } + + @Override + public SleighUseropLibrary getUseropLibrary() { + return library; + } + + @Override + public SleighUseropLibrary getStubUseropLibrary() { + return stubLibrary; + } + protected abstract PcodeExecutorState createSharedState(); protected abstract PcodeExecutorState createLocalState(PcodeThread thread); 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 32c1610321..c8f131fcd3 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 @@ -21,7 +21,8 @@ import java.util.*; import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.pcode.exec.*; import ghidra.program.model.address.Address; -import ghidra.program.model.lang.*; +import ghidra.program.model.lang.Register; +import ghidra.program.model.lang.RegisterValue; import ghidra.program.model.listing.Instruction; import ghidra.program.model.pcode.PcodeOp; import ghidra.program.util.ProgramContextImpl; @@ -69,7 +70,7 @@ public class DefaultPcodeThread implements PcodeThread { protected class PcodeThreadExecutor extends PcodeExecutor { volatile boolean suspended = false; - public PcodeThreadExecutor(Language language, PcodeArithmetic arithmetic, + public PcodeThreadExecutor(SleighLanguage language, PcodeArithmetic arithmetic, PcodeExecutorStatePiece state) { super(language, arithmetic, state); } diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/PcodeMachine.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/PcodeMachine.java index 1f6312eba3..acb5dc7a82 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/PcodeMachine.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/PcodeMachine.java @@ -18,9 +18,9 @@ package ghidra.pcode.emu; import java.util.Collection; import java.util.List; +import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.pcode.emu.DefaultPcodeThread.SleighEmulationLibrary; -import ghidra.pcode.exec.PcodeExecutorState; -import ghidra.pcode.exec.PcodeProgram; +import ghidra.pcode.exec.*; import ghidra.program.model.address.Address; /** @@ -30,6 +30,47 @@ import ghidra.program.model.address.Address; */ public interface PcodeMachine { + /** + * Get the machine's SLEIGH language (processor model) + * + * @return the language + */ + SleighLanguage getLanguage(); + + /** + * Get the arithmetic applied by the machine + * + * @return the arithmetic + */ + PcodeArithmetic getArithmetic(); + + /** + * Get the userop library common to all threads in the machine. + * + *

+ * Note that threads may have larger libraries, but each should contain all the userops in this + * library. + * + * @return the userop library + */ + SleighUseropLibrary getUseropLibrary(); + + /** + * Get a userop library which at least declares all userops available in thread userop + * libraries. + * + *

+ * Thread userop libraries may have more userops than are defined in the machine's userop + * library. However, to compile SLEIGH programs linked to thread libraries, the thread's userops + * must be known to the compiler. The stub library will name all userops common among the + * threads, even if their definitions vary. WARNING: The stub library is not required to + * provide implementations of the userops. Often they will throw exceptions, so do not attempt + * to use the returned library in an executor. + * + * @return the stub library + */ + SleighUseropLibrary getStubUseropLibrary(); + /** * Create a new thread with a default name in this machine * diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/PcodeThread.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/PcodeThread.java index 50e44db14f..760aca1f56 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/PcodeThread.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/emu/PcodeThread.java @@ -17,6 +17,7 @@ package ghidra.pcode.emu; import java.util.List; +import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.pcode.emu.DefaultPcodeThread.SleighEmulationLibrary; import ghidra.pcode.exec.*; import ghidra.program.model.address.Address; @@ -222,6 +223,24 @@ public interface PcodeThread { */ void setSuspended(boolean suspended); + /** + * Get the thread's SLEIGH language (processor model) + * + * @return the language + */ + default SleighLanguage getLanguage() { + return getExecutor().getLanguage(); + } + + /** + * Get the thread's p-code arithmetic + * + * @return the arithmetic + */ + default PcodeArithmetic getArithmetic() { + return getExecutor().getArithmetic(); + } + /** * Get the thread's p-code executor * 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 cb93a5b2d7..aef40d6b6e 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 @@ -24,19 +24,18 @@ import ghidra.pcode.exec.SleighUseropLibrary.SleighUseropDefinition; import ghidra.pcode.opbehavior.*; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSpace; -import ghidra.program.model.lang.Language; import ghidra.program.model.lang.Register; import ghidra.program.model.pcode.PcodeOp; import ghidra.program.model.pcode.Varnode; public class PcodeExecutor { - protected final Language language; + protected final SleighLanguage language; protected final PcodeArithmetic arithmetic; protected final PcodeExecutorStatePiece state; protected final Register pc; protected final int pointerSize; - public PcodeExecutor(Language language, PcodeArithmetic arithmetic, + public PcodeExecutor(SleighLanguage language, PcodeArithmetic arithmetic, PcodeExecutorStatePiece state) { this.language = language; this.arithmetic = arithmetic; @@ -46,8 +45,35 @@ public class PcodeExecutor { this.pointerSize = language.getDefaultSpace().getPointerSize(); } + /** + * Get the executor's SLEIGH language (processor model) + * + * @return the language + */ + public SleighLanguage getLanguage() { + return language; + } + + /** + * Get the arithmetic applied by the executor + * + * @return the arithmetic + */ + public PcodeArithmetic getArithmetic() { + return arithmetic; + } + + /** + * Get the state bound to this executor + * + * @return the state + */ + public PcodeExecutorStatePiece getState() { + return state; + } + public void executeLine(String line) { - PcodeProgram program = SleighProgramCompiler.compileProgram((SleighLanguage) language, + PcodeProgram program = SleighProgramCompiler.compileProgram(language, "line", List.of(line + ";"), SleighUseropLibrary.NIL); execute(program, SleighUseropLibrary.nil()); }