GP-2467: Change SleighProgramCompiler to use String (text block) instead of List<String>

This commit is contained in:
Dan 2022-09-12 09:03:54 -04:00
parent 6a2cd80550
commit 9d6f278f39
48 changed files with 730 additions and 613 deletions

View file

@ -24,7 +24,6 @@
//@toolbar
import java.nio.charset.Charset;
import java.util.List;
import ghidra.app.plugin.assembler.Assembler;
import ghidra.app.plugin.assembler.Assemblers;
@ -149,9 +148,10 @@ public class DebuggerEmuExampleScript extends GhidraScript {
* Inject a call to our custom print userop. Otherwise, the language itself will never
* invoke it.
*/
emulator.inject(injectHere, List.of(
"print_utf8(RCX);",
"emu_exec_decoded();"));
emulator.inject(injectHere, """
print_utf8(RCX);
emu_exec_decoded();
""");
/*
* Run the experiment: This should interrupt on the second SYSCALL, because any value other

View file

@ -22,7 +22,6 @@
//@toolbar
import java.nio.charset.Charset;
import java.util.List;
import ghidra.app.plugin.assembler.*;
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
@ -102,10 +101,10 @@ public class StandAloneEmuExampleScript extends GhidraScript {
*/
byte[] hw = "Hello, World!\n".getBytes(UTF8);
emulator.getSharedState().setVar(dyn, 0xdeadbeefL, hw.length, true, hw);
PcodeProgram init = SleighProgramCompiler.compileProgram(language, "init", List.of(
"RIP = 0x" + entry + ";",
"RSP = 0x00001000;"),
library);
PcodeProgram init = SleighProgramCompiler.compileProgram(language, "init", String.format("""
RIP = 0x%s;
RSP = 0x00001000;
""", entry), library);
thread.getExecutor().execute(init, library);
thread.overrideContextWithDefault();
thread.reInitialize();
@ -114,9 +113,10 @@ public class StandAloneEmuExampleScript extends GhidraScript {
* Inject a call to our custom print userop. Otherwise, the language itself will never
* invoke it.
*/
emulator.inject(injectHere, List.of(
"print_utf8(RCX);",
"emu_exec_decoded();"));
emulator.inject(injectHere, """
print_utf8(RCX);
emu_exec_decoded();
""");
/*
* Run the experiment: This should interrupt on the second SYSCALL, because any value other

View file

@ -103,9 +103,7 @@ public class StandAloneStructuredSleighScript extends GhidraScript {
print(userop.getName() + "(");
print(userop.getInputs().stream().collect(Collectors.joining(",")));
print(") {\n");
for (String line : userop.getLines()) {
print(line);
}
print(userop.getBody());
print("}\n\n");
}
}

View file

@ -22,7 +22,6 @@
//@toolbar
import java.nio.charset.Charset;
import java.util.List;
import ghidra.app.plugin.assembler.Assembler;
import ghidra.app.plugin.assembler.Assemblers;
@ -184,10 +183,11 @@ public class StandAloneSyscallEmuExampleScript extends GhidraScript {
/*
* Initialize the thread
*/
PcodeProgram init = SleighProgramCompiler.compileProgram(language, "init", List.of(
"RIP = 0x" + entry + ";",
"RSP = 0x00001000;"),
library);
PcodeProgram init =
SleighProgramCompiler.compileProgram(language, "init", String.format("""
RIP = 0x%s;
RSP = 0x00001000;
""", entry), library);
thread.getExecutor().execute(init, library);
thread.overrideContextWithDefault();
thread.reInitialize();

View file

@ -69,8 +69,10 @@ public class DebuggerPcodeStepperPluginScreenShots extends GhidraScreenShotGener
PcodeExecutor<byte[]> exe =
TraceSleighUtils.buildByteExecutor(tb.trace, snap0, thread, 0);
exe.executeSleighLine("RIP = 0x00400000");
exe.executeSleighLine("RSP = 0x0010fff8");
exe.executeSleigh("""
RIP = 0x00400000;
RSP = 0x0010fff8;
""");
Assembler asm = Assemblers.getAssembler(tb.trace.getFixedProgramView(snap0));
asm.assemble(tb.addr(0x00400000), "SUB RSP,0x40");

View file

@ -69,14 +69,18 @@ public class DebuggerWatchesPluginScreenShots extends GhidraScreenShotGenerator
PcodeExecutor<byte[]> executor0 =
TraceSleighUtils.buildByteExecutor(tb.trace, snap0, thread, 0);
executor0.executeSleighLine("RSP = 0x7ffefff8");
executor0.executeSleighLine("*:4 (RSP+8) = 0x4030201");
executor0.executeSleigh("""
RSP = 0x7ffefff8;
*:4 (RSP+8) = 0x4030201;
""");
PcodeExecutor<byte[]> executor1 =
TraceSleighUtils.buildByteExecutor(tb.trace, snap1, thread, 0);
executor1.executeSleighLine("RSP = 0x7ffefff8");
executor1.executeSleighLine("*:4 (RSP+8) = 0x1020304");
executor1.executeSleighLine("*:4 0x7fff0004:8 = 0x4A9A70C8");
executor1.executeSleigh("""
RSP = 0x7ffefff8;
*:4 (RSP+8) = 0x1020304;
*:4 0x7fff0004:8 = 0x4A9A70C8;
""");
}
watchesProvider.addWatch("RSP");

View file

@ -134,11 +134,12 @@ public class DebuggerBreakpointMarkerPluginTest extends AbstractGhidraHeadedDebu
});
}
protected TraceRecorder addMappedBreakpointOpenAndWait() throws Exception {
protected TraceRecorder addMappedBreakpointOpenAndWait() throws Throwable {
createTestModel();
mb.createTestProcessesAndThreads();
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
waitRecorder(recorder);
Trace trace = recorder.getTrace();
createProgramFromTrace(trace);
intoProject(trace);
@ -260,7 +261,7 @@ public class DebuggerBreakpointMarkerPluginTest extends AbstractGhidraHeadedDebu
Set.of("SW_EXECUTE", "HW_EXECUTE", "READ,WRITE", "READ", "WRITE");
@Test
public void testProgramNoBreakPopupMenus() throws Exception {
public void testProgramNoBreakPopupMenus() throws Throwable {
// NOTE: Need a target to have any breakpoint actions, even on programs
addMappedBreakpointOpenAndWait();
@ -276,7 +277,7 @@ public class DebuggerBreakpointMarkerPluginTest extends AbstractGhidraHeadedDebu
}
@Test
public void testTraceNoBreakPopupMenus() throws Exception {
public void testTraceNoBreakPopupMenus() throws Throwable {
TraceRecorder recorder = addMappedBreakpointOpenAndWait();
Trace trace = recorder.getTrace();
traceManager.activateTrace(trace);
@ -414,7 +415,7 @@ public class DebuggerBreakpointMarkerPluginTest extends AbstractGhidraHeadedDebu
@Test
public void testActionToggleBreakpointProgramWithNoCurrentBreakpointOnInstruction()
throws Exception {
throws Throwable {
addMappedBreakpointOpenAndWait(); // wasteful, but whatever
for (LogicalBreakpoint lb : List.copyOf(breakpointService.getAllBreakpoints())) {
lb.delete();
@ -442,7 +443,7 @@ public class DebuggerBreakpointMarkerPluginTest extends AbstractGhidraHeadedDebu
}
@Test
public void testActionToggleBreakpointProgramWithNoCurrentBreakpointOnData() throws Exception {
public void testActionToggleBreakpointProgramWithNoCurrentBreakpointOnData() throws Throwable {
addMappedBreakpointOpenAndWait(); // wasteful, but whatever
for (LogicalBreakpoint lb : List.copyOf(breakpointService.getAllBreakpoints())) {
lb.delete();
@ -470,7 +471,7 @@ public class DebuggerBreakpointMarkerPluginTest extends AbstractGhidraHeadedDebu
}
@Test
public void testActionToggleBreakpointProgram() throws Exception {
public void testActionToggleBreakpointProgram() throws Throwable {
addMappedBreakpointOpenAndWait();
LogicalBreakpoint lb = Unique.assertOne(breakpointService.getAllBreakpoints());
@ -486,7 +487,7 @@ public class DebuggerBreakpointMarkerPluginTest extends AbstractGhidraHeadedDebu
}
@Test
public void testActionToggleBreakpointTrace() throws Exception {
public void testActionToggleBreakpointTrace() throws Throwable {
TraceRecorder recorder = addMappedBreakpointOpenAndWait();
Trace trace = recorder.getTrace();
LogicalBreakpoint lb = Unique.assertOne(breakpointService.getAllBreakpoints());
@ -527,14 +528,16 @@ public class DebuggerBreakpointMarkerPluginTest extends AbstractGhidraHeadedDebu
}
protected void testActionSetBreakpointProgram(DockingAction action,
Set<TraceBreakpointKind> expectedKinds) throws Exception {
Set<TraceBreakpointKind> expectedKinds) throws Throwable {
addMappedBreakpointOpenAndWait(); // Adds an unneeded breakpoint. Aw well.
performAction(action, staticCtx(addr(program, 0x0400321)), false);
DebuggerPlaceBreakpointDialog dialog =
waitForDialogComponent(DebuggerPlaceBreakpointDialog.class);
dialog.setName("Test name");
runSwing(() -> dialog.okCallback());
runSwing(() -> {
dialog.setName("Test name");
dialog.okCallback();
});
waitForPass(() -> {
LogicalBreakpoint lb = Unique.assertOne(
@ -546,7 +549,7 @@ public class DebuggerBreakpointMarkerPluginTest extends AbstractGhidraHeadedDebu
}
protected void testActionSetBreakpointTrace(DockingAction action,
Set<TraceBreakpointKind> expectedKinds) throws Exception {
Set<TraceBreakpointKind> expectedKinds) throws Throwable {
TraceRecorder recorder = addMappedBreakpointOpenAndWait(); // Adds an unneeded breakpoint. Aw well.
Trace trace = recorder.getTrace();
@ -568,67 +571,67 @@ public class DebuggerBreakpointMarkerPluginTest extends AbstractGhidraHeadedDebu
}
@Test
public void testActionSetSoftwareBreakpointProgram() throws Exception {
public void testActionSetSoftwareBreakpointProgram() throws Throwable {
testActionSetBreakpointProgram(breakpointMarkerPlugin.actionSetSoftwareBreakpoint,
Set.of(TraceBreakpointKind.SW_EXECUTE));
}
@Test
public void testActionSetSoftwareBreakpointTrace() throws Exception {
public void testActionSetSoftwareBreakpointTrace() throws Throwable {
testActionSetBreakpointTrace(breakpointMarkerPlugin.actionSetSoftwareBreakpoint,
Set.of(TraceBreakpointKind.SW_EXECUTE));
}
@Test
public void testActionSetExecuteBreakpointProgram() throws Exception {
public void testActionSetExecuteBreakpointProgram() throws Throwable {
testActionSetBreakpointProgram(breakpointMarkerPlugin.actionSetExecuteBreakpoint,
Set.of(TraceBreakpointKind.HW_EXECUTE));
}
@Test
public void testActionSetExecuteBreakpointTrace() throws Exception {
public void testActionSetExecuteBreakpointTrace() throws Throwable {
testActionSetBreakpointTrace(breakpointMarkerPlugin.actionSetExecuteBreakpoint,
Set.of(TraceBreakpointKind.HW_EXECUTE));
}
@Test
public void testActionSetReadWriteBreakpointProgram() throws Exception {
public void testActionSetReadWriteBreakpointProgram() throws Throwable {
testActionSetBreakpointProgram(breakpointMarkerPlugin.actionSetReadWriteBreakpoint,
Set.of(TraceBreakpointKind.READ, TraceBreakpointKind.WRITE));
}
@Test
public void testActionSetReadWriteBreakpointTrace() throws Exception {
public void testActionSetReadWriteBreakpointTrace() throws Throwable {
testActionSetBreakpointTrace(breakpointMarkerPlugin.actionSetReadWriteBreakpoint,
Set.of(TraceBreakpointKind.READ, TraceBreakpointKind.WRITE));
}
@Test
public void testActionSetReadBreakpointProgram() throws Exception {
public void testActionSetReadBreakpointProgram() throws Throwable {
testActionSetBreakpointProgram(breakpointMarkerPlugin.actionSetReadBreakpoint,
Set.of(TraceBreakpointKind.READ));
}
@Test
public void testActionSetReadBreakpointTrace() throws Exception {
public void testActionSetReadBreakpointTrace() throws Throwable {
testActionSetBreakpointTrace(breakpointMarkerPlugin.actionSetReadBreakpoint,
Set.of(TraceBreakpointKind.READ));
}
@Test
public void testActionSetWriteBreakpointProgram() throws Exception {
public void testActionSetWriteBreakpointProgram() throws Throwable {
testActionSetBreakpointProgram(breakpointMarkerPlugin.actionSetWriteBreakpoint,
Set.of(TraceBreakpointKind.WRITE));
}
@Test
public void testActionSetWriteBreakpointTrace() throws Exception {
public void testActionSetWriteBreakpointTrace() throws Throwable {
testActionSetBreakpointTrace(breakpointMarkerPlugin.actionSetWriteBreakpoint,
Set.of(TraceBreakpointKind.WRITE));
}
@Test
public void testActionEnableBreakpointProgram() throws Exception {
public void testActionEnableBreakpointProgram() throws Throwable {
addMappedBreakpointOpenAndWait();
LogicalBreakpoint lb = Unique.assertOne(breakpointService.getAllBreakpoints());
lb.disable();
@ -641,7 +644,7 @@ public class DebuggerBreakpointMarkerPluginTest extends AbstractGhidraHeadedDebu
}
@Test
public void testActionEnableBreakpointTrace() throws Exception {
public void testActionEnableBreakpointTrace() throws Throwable {
TraceRecorder recorder = addMappedBreakpointOpenAndWait();
Trace trace = recorder.getTrace();
LogicalBreakpoint lb = Unique.assertOne(breakpointService.getAllBreakpoints());
@ -656,7 +659,7 @@ public class DebuggerBreakpointMarkerPluginTest extends AbstractGhidraHeadedDebu
}
@Test
public void testActionDisableBreakpointProgram() throws Exception {
public void testActionDisableBreakpointProgram() throws Throwable {
addMappedBreakpointOpenAndWait();
LogicalBreakpoint lb = Unique.assertOne(breakpointService.getAllBreakpoints());
@ -667,7 +670,7 @@ public class DebuggerBreakpointMarkerPluginTest extends AbstractGhidraHeadedDebu
}
@Test
public void testActionDisableBreakpointTrace() throws Exception {
public void testActionDisableBreakpointTrace() throws Throwable {
TraceRecorder recorder = addMappedBreakpointOpenAndWait();
Trace trace = recorder.getTrace();
LogicalBreakpoint lb = Unique.assertOne(breakpointService.getAllBreakpoints());
@ -680,7 +683,7 @@ public class DebuggerBreakpointMarkerPluginTest extends AbstractGhidraHeadedDebu
}
@Test
public void testActionClearBreakpointProgram() throws Exception {
public void testActionClearBreakpointProgram() throws Throwable {
addMappedBreakpointOpenAndWait();
performAction(breakpointMarkerPlugin.actionClearBreakpoint,
@ -690,7 +693,7 @@ public class DebuggerBreakpointMarkerPluginTest extends AbstractGhidraHeadedDebu
}
@Test
public void testActionClearBreakpointTrace() throws Exception {
public void testActionClearBreakpointTrace() throws Throwable {
TraceRecorder recorder = addMappedBreakpointOpenAndWait();
Trace trace = recorder.getTrace();
LogicalBreakpoint lb = Unique.assertOne(breakpointService.getAllBreakpoints());

View file

@ -1269,7 +1269,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
.createRegion(".text", 0, tb.range(0x00400000, 0x0040ffff),
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
thread1 = tb.getOrAddThread("Thread1", 0);
tb.exec(0, 0, thread1, java.util.List.of("RIP = 0x00400000;"));
tb.exec(0, 0, thread1, "RIP = 0x00400000;");
}
TraceThread thread2;
@ -1279,7 +1279,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
.createRegion(".text", 0, tb2.range(0x200, 0x3ff), TraceMemoryFlag.READ,
TraceMemoryFlag.EXECUTE);
thread2 = tb2.getOrAddThread("Thread2", 0);
tb2.exec(0, 0, thread2, java.util.List.of("PC = 0x100;"));
tb2.exec(0, 0, thread2, "PC = 0x100;");
}
traceManager.openTrace(tb.trace);

View file

@ -82,7 +82,7 @@ public class DebuggerPcodeStepperProviderTest extends AbstractGhidraHeadedDebugg
thread = tb.getOrAddThread("1", 0);
PcodeExecutor<byte[]> init = TraceSleighUtils.buildByteExecutor(tb.trace, 0, thread, 0);
init.executeSleighLine("pc = 0x00400000");
init.executeSleigh("pc = 0x00400000;");
Assembler asm = Assemblers.getAssembler(tb.trace.getFixedProgramView(0));
iit = asm.assemble(start,
@ -166,7 +166,7 @@ public class DebuggerPcodeStepperProviderTest extends AbstractGhidraHeadedDebugg
.anyMatch(r -> r.getCode().contains("emu_swi"))));
}
protected List<PcodeRow> format(List<String> sleigh) {
protected List<PcodeRow> format(String sleigh) {
SleighLanguage language = (SleighLanguage) getToyBE64Language();
PcodeProgram prog = SleighProgramCompiler.compileProgram(language, "test", sleigh,
PcodeUseropLibrary.nil());
@ -179,7 +179,7 @@ public class DebuggerPcodeStepperProviderTest extends AbstractGhidraHeadedDebugg
@Test
public void testPcodeFormatterSimple() {
List<PcodeRow> rows = format(List.of("r0 = 1;"));
List<PcodeRow> rows = format("r0 = 1;");
assertEquals(2, rows.size());
assertEquals("<html></html>", rows.get(0).getLabel());
assertEquals(FallthroughPcodeRow.class, rows.get(1).getClass());
@ -187,9 +187,10 @@ public class DebuggerPcodeStepperProviderTest extends AbstractGhidraHeadedDebugg
@Test
public void testPcodeFormatterStartsLabel() {
List<PcodeRow> rows = format(List.of(
"<L0> r0 = 1;",
"goto <L0>;"));
List<PcodeRow> rows = format("""
<L0> r0 = 1;
goto <L0>;
""");
assertEquals(3, rows.size());
assertEquals("<html><span class=\"lab\">&lt;0&gt;</span></html>", rows.get(0).getLabel());
assertEquals("<html></html>", rows.get(1).getLabel());
@ -198,10 +199,11 @@ public class DebuggerPcodeStepperProviderTest extends AbstractGhidraHeadedDebugg
@Test
public void testPcodeFormatterMiddleLabel() {
List<PcodeRow> rows = format(List.of(
"if 1:1 goto <SKIP>;",
"r0 = 1;",
"<SKIP> r1 = 2;"));
List<PcodeRow> rows = format("""
if 1:1 goto <SKIP>;
r0 = 1;
<SKIP> r1 = 2;
""");
assertEquals(4, rows.size());
assertEquals("<html></html>", rows.get(0).getLabel());
assertEquals("<html></html>", rows.get(1).getLabel());
@ -211,10 +213,11 @@ public class DebuggerPcodeStepperProviderTest extends AbstractGhidraHeadedDebugg
@Test
public void testPcodeFormatterFallthroughLabel() {
List<PcodeRow> rows = format(List.of(
"if 1:1 goto <SKIP>;",
"r0 = 1;",
"<SKIP>"));
List<PcodeRow> rows = format("""
if 1:1 goto <SKIP>;
r0 = 1;
<SKIP>
""");
assertEquals(3, rows.size());
assertEquals("<html></html>", rows.get(0).getLabel());
assertEquals("<html></html>", rows.get(1).getLabel());
@ -224,12 +227,13 @@ public class DebuggerPcodeStepperProviderTest extends AbstractGhidraHeadedDebugg
@Test
public void testPcodeFormatterManyLabel() {
List<PcodeRow> rows = format(List.of(
"<L0> goto <L1>;",
"<L1> goto <L2>;",
"<L2> goto <L3>;",
"goto <L0>;",
"<L3>"));
List<PcodeRow> rows = format("""
<L0> goto <L1>;
<L1> goto <L2>;
<L2> goto <L3>;
goto <L0>;
<L3>
""");
assertEquals(5, rows.size());
// NB. templates number labels in order of appearance in BRANCHes
assertEquals("<html><span class=\"lab\">&lt;3&gt;</span></html>", rows.get(0).getLabel());

View file

@ -469,7 +469,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
TraceThread thread = addThread();
try (UndoableTransaction tid = tb.startTransaction()) {
tb.exec(0, 0, thread, List.of("pc = 100;"));
tb.exec(0, 0, thread, "pc = 100;");
}
traceManager.activateThread(thread);
waitForSwing();
@ -800,10 +800,11 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
modelData.stream().filter(r -> r.getRegister() == pc).findFirst().orElse(null);
assertNotNull(pcAvail);
pcAvail.setSelected(false);
dialog.availableTableModel.fireTableDataChanged();
dialog.okCallback();
waitForSwing();
runSwing(() -> {
pcAvail.setSelected(false);
dialog.availableTableModel.fireTableDataChanged();
dialog.okCallback();
});
assertNull(getRegisterRow(pc));
assertTrue(registersProvider.actionSelectRegisters.isEnabled());

View file

@ -148,7 +148,7 @@ public class DebuggerStateEditingServiceTest extends AbstractGhidraHeadedDebugge
Assembler asm = Assemblers.getAssembler(tb.trace.getFixedProgramView(0));
asm.assemble(tb.addr(0x00400000), "imm r0,#123");
executor.executeSleighLine("pc = 0x00400000");
executor.executeSleigh("pc = 0x00400000;");
}
traceManager.activateTrace(tb.trace);
editingService.setCurrentMode(tb.trace, StateEditingMode.WRITE_EMULATOR);
@ -186,7 +186,7 @@ public class DebuggerStateEditingServiceTest extends AbstractGhidraHeadedDebugge
Assembler asm = Assemblers.getAssembler(tb.trace.getFixedProgramView(0));
asm.assemble(tb.addr(0x00400000), "imm r0,#123");
executor.executeSleighLine("pc = 0x00400000");
executor.executeSleigh("pc = 0x00400000;");
}
traceManager.activateTrace(tb.trace);
editingService.setCurrentMode(tb.trace, StateEditingMode.WRITE_EMULATOR);

View file

@ -337,7 +337,7 @@ public class DebuggerTraceManagerServiceTest extends AbstractGhidraHeadedDebugge
}
@Test
public void testAutoActivatePresent() throws Exception {
public void testAutoActivatePresent() throws Throwable {
assertTrue(traceManager.isAutoActivatePresent());
createTestModel();
@ -345,6 +345,7 @@ public class DebuggerTraceManagerServiceTest extends AbstractGhidraHeadedDebugge
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
waitRecorder(recorder);
Trace trace = recorder.getTrace();
traceManager.openTrace(trace);

View file

@ -18,7 +18,6 @@ package ghidra.pcode.exec;
import static org.junit.Assert.*;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;
import org.junit.Test;
@ -29,7 +28,6 @@ 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.*;
import ghidra.pcode.utils.Utils;
import ghidra.program.model.lang.Register;
import ghidra.trace.model.Trace;
@ -100,7 +98,7 @@ public class TraceRecorderAsyncPcodeExecTest extends AbstractGhidraHeadedDebugge
SleighLanguage language = (SleighLanguage) trace.getBaseLanguage();
PcodeProgram prog = SleighProgramCompiler.compileProgram(language, "test",
List.of("r2 = r0 + r1;"), PcodeUseropLibrary.NIL);
"r2 = r0 + r1;", PcodeUseropLibrary.NIL);
Register r0 = language.getRegister("r0");
Register r1 = language.getRegister("r1");

View file

@ -314,7 +314,7 @@ public class PatchStep implements Step {
@Override
public <T> void execute(PcodeThread<T> emuThread, Stepper<T> stepper, TaskMonitor monitor)
throws CancelledException {
PcodeProgram prog = emuThread.getMachine().compileSleigh("schedule", List.of(sleigh + ";"));
PcodeProgram prog = emuThread.getMachine().compileSleigh("schedule", sleigh + ";");
emuThread.getExecutor().execute(prog, emuThread.getUseropLibrary());
}
@ -368,7 +368,7 @@ public class PatchStep implements Step {
protected Map<AddressSpace, SemisparseByteArray> getPatches(Language language) {
PcodeProgram prog = SleighProgramCompiler.compileProgram((SleighLanguage) language,
"schedule", List.of(sleigh + ";"), PcodeUseropLibrary.nil());
"schedule", sleigh + ";", PcodeUseropLibrary.nil());
// SemisparseArray is a bit overkill, no?
Map<AddressSpace, SemisparseByteArray> result = new TreeMap<>();
for (PcodeOp op : prog.getCode()) {

View file

@ -35,7 +35,7 @@ import ghidra.util.database.UndoableTransaction;
public class AbstractTracePcodeEmulatorTest extends AbstractGhidraHeadlessIntegrationTest {
public TraceThread initTrace(ToyDBTraceBuilder tb, List<String> stateInit,
public TraceThread initTrace(ToyDBTraceBuilder tb, String stateInit,
List<String> assembly) throws Throwable {
return initTrace(tb, tb.range(0x00400000, 0x0040ffff), tb.range(0x00100000, 0x0010ffff),
stateInit, assembly);
@ -53,14 +53,13 @@ public class AbstractTracePcodeEmulatorTest extends AbstractGhidraHeadlessIntegr
* memory where it was assembled.
*
* @param tb the trace builder
* @param stateInit SLEIGH source lines to execute to initialize the trace state before
* emulation. Each line must end with ";"
* @param stateInit Sleigh source to execute to initialize the trace state before emulation
* @param assembly lines of assembly to place starting at {@code 0x00400000}
* @return a new trace thread, whose register state is initialized as specified
* @throws Throwable if anything goes wrong
*/
public TraceThread initTrace(ToyDBTraceBuilder tb, AddressRange text, AddressRange stack,
List<String> stateInit, List<String> assembly) throws Throwable {
String stateInit, List<String> assembly) throws Throwable {
TraceMemoryManager mm = tb.trace.getMemoryManager();
TraceThread thread;
try (UndoableTransaction tid = tb.startTransaction()) {

View file

@ -54,10 +54,10 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
@Test
public void testSinglePUSH() throws Throwable {
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
TraceThread thread = initTrace(tb,
List.of(
"RIP = 0x00400000;",
"RSP = 0x00110000;"),
TraceThread thread = initTrace(tb, """
RIP = 0x00400000;
RSP = 0x00110000;
""",
List.of(
"PUSH 0xdeadbeef"));
@ -94,10 +94,10 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
@Test
public void testDoublePUSH() throws Throwable {
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
TraceThread thread = initTrace(tb,
List.of(
"RIP = 0x00400000;",
"RSP = 0x00110000;"),
TraceThread thread = initTrace(tb, """
RIP = 0x00400000;
RSP = 0x00110000;
""",
List.of(
"PUSH 0xdeadbeef",
"PUSH 0xbaadf00d"));
@ -133,11 +133,11 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
Register pc = tb.language.getProgramCounter();
TraceThread thread = initTrace(tb,
List.of(
"RIP = 0x00400000;",
"RSP = 0x00110000;",
"RAX = 0x12345678;"),
TraceThread thread = initTrace(tb, """
RIP = 0x00400000;
RSP = 0x00110000;
RAX = 0x12345678;
""",
List.of(
"JMP 0x00400007", // 2 bytes
"MOV EAX,0xdeadbeef", // 5 bytes
@ -189,11 +189,12 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
AssemblyPatternBlock thumbPat = AssemblyPatternBlock.fromRegisterValue(thumbCtx);
// NOTE: Assemble the thumb section separately
TraceThread thread = initTrace(tb,
List.of(
"pc = 0x00400000;",
"sp = 0x00110000;",
"*:4 0x00400008:4 = 0x00401001;"), // immediately after bx
// write 0x00401001 immediately after bx (0x00400008)
TraceThread thread = initTrace(tb, """
pc = 0x00400000;
sp = 0x00110000;
*:4 0x00400008:4 = 0x00401001;
""",
List.of(
"ldr r6, [pc,#0]!", // 4 bytes, pc+4 should be 00400008
"bx r6")); // 4 bytes
@ -241,10 +242,10 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "Toy:BE:64:default")) {
assertEquals(Register.NO_CONTEXT, tb.language.getContextBaseRegister());
TraceThread thread = initTrace(tb,
List.of(
"pc = 0x00400000;",
"sp = 0x00110000;"),
TraceThread thread = initTrace(tb, """
pc = 0x00400000;
sp = 0x00110000;
""",
List.of(
"imm r0, #911")); // decimal
@ -272,10 +273,10 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
@Test
public void testBRDS() throws Throwable {
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "Toy:BE:64:default")) {
TraceThread thread = initTrace(tb,
List.of(
"pc = 0x00400000;",
"sp = 0x00110000;"),
TraceThread thread = initTrace(tb, """
pc = 0x00400000;
sp = 0x00110000;
""",
List.of(
"brds 0x00400006",
"imm r0, #911", // decimal
@ -314,13 +315,13 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
@Test
public void testSelfModifyingX86() throws Throwable {
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
TraceThread thread = initTrace(tb,
List.of(
"RIP = 0x00400000;",
"RSP = 0x00110000;",
"RAX = 0x12345678;",
// NB. Assembly actually happens first, so this is modifying
"*:1 0x00400007:8 = *0x00400007:8 ^ 0xcc;"),
// NB. Assembly actually happens first, so Sleigh will modify it
TraceThread thread = initTrace(tb, """
RIP = 0x00400000;
RSP = 0x00110000;
RAX = 0x12345678;
*:1 0x00400007:8 = *0x00400007:8 ^ 0xcc;
""",
List.of(
// First instruction undoes the modification above
"XOR byte ptr [0x00400007], 0xcc", // 7 bytes
@ -356,10 +357,10 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
@Test
public void testDoublePUSH_pCode() throws Throwable {
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
TraceThread thread = initTrace(tb,
List.of(
"RIP = 0x00400000;",
"RSP = 0x00110000;"),
TraceThread thread = initTrace(tb, """
RIP = 0x00400000;
RSP = 0x00110000;
""",
List.of(
"PUSH 0xdeadbeef",
"PUSH 0xbaadf00d"));
@ -424,10 +425,10 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
dumped.append(NumericUtilities.convertBytesToString(in));
}
};
TraceThread thread = initTrace(tb,
List.of(
"RIP = 0x00400000;",
"RSP = 0x00110000;"),
TraceThread thread = initTrace(tb, """
RIP = 0x00400000;
RSP = 0x00110000;
""",
List.of(
"PUSH 0xdeadbeef",
"PUSH 0xbaadf00d"));
@ -438,7 +439,7 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
return hexLib;
}
};
emu.inject(tb.addr(0x00400006), List.of("hexdump(RSP);"));
emu.inject(tb.addr(0x00400006), "hexdump(RSP);");
PcodeThread<byte[]> emuThread = emu.newThread(thread.getPath());
emuThread.overrideContextWithDefault();
@ -472,10 +473,10 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
dumped.append(NumericUtilities.convertBytesToString(in));
}
};
TraceThread thread = initTrace(tb,
List.of(
"RIP = 0x00400000;",
"RSP = 0x00110000;"),
TraceThread thread = initTrace(tb, """
RIP = 0x00400000;
RSP = 0x00110000;
""",
List.of(
"PUSH 0xdeadbeef",
"PUSH 0xbaadf00d"));
@ -486,12 +487,13 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
return hexLib;
}
};
emu.inject(tb.addr(0x00400006), List.of(
"hexdump(RSP);",
"emu_swi();",
"hexdump(RIP);",
"emu_exec_decoded();",
"hexdump(RIP);"));
emu.inject(tb.addr(0x00400006), """
hexdump(RSP);
emu_swi();
hexdump(RIP);
emu_exec_decoded();
hexdump(RIP);
""");
PcodeThread<byte[]> emuThread = emu.newThread(thread.getPath());
emuThread.overrideContextWithDefault();
@ -527,11 +529,11 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
@Test
public void testBreakpoints() throws Throwable {
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
TraceThread thread = initTrace(tb,
List.of(
"RIP = 0x00400000;",
"RSP = 0x00110000;",
"RAX = 0;"),
TraceThread thread = initTrace(tb, """
RIP = 0x00400000;
RSP = 0x00110000;
RAX = 0;
""",
List.of(
"PUSH 0xdeadbeef",
"PUSH 0xbaadf00d"));
@ -561,11 +563,11 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
@Test
public void testCLZ() throws Throwable {
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "ARM:LE:32:v8")) {
TraceThread thread = initTrace(tb,
List.of(
"pc = 0x00400000;",
"sp = 0x00110000;",
"r0 = 0x00008000;"),
TraceThread thread = initTrace(tb, """
pc = 0x00400000;
sp = 0x00110000;
r0 = 0x00008000;
""",
List.of(
"clz r1, r0"));
@ -594,12 +596,12 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
Register pc = tb.language.getProgramCounter();
TraceThread thread = initTrace(tb,
List.of(
"RIP = 0x00400000;",
"RSP = 0x00110000;",
"*:8 0x00600008:8 = 0x0123456789abcdef;", // LE
"*:8 0x00600000:8 = 0xfedcba9876543210;"),
TraceThread thread = initTrace(tb, """
RIP = 0x00400000;
RSP = 0x00110000;
*:8 0x00600008:8 = 0x0123456789abcdef;
*:8 0x00600000:8 = 0xfedcba9876543210;
""",
List.of(
"MOVAPS XMM0, xmmword ptr [0x00600000]"));
@ -632,12 +634,12 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
Register pc = tb.language.getProgramCounter();
TraceThread thread = initTrace(tb,
List.of(
"RIP = 0x00400000;",
"RSP = 0x00110000;",
"RAX = 0x7fffffff;",
"RCX = 4;"),
TraceThread thread = initTrace(tb, """
RIP = 0x00400000;
RSP = 0x00110000;
RAX = 0x7fffffff;
RCX = 4;
""",
List.of(
"SAR EAX, CL"));
@ -662,11 +664,11 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
@Test
public void testCachedReadAfterSmallWrite() throws Throwable {
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
TraceThread thread = initTrace(tb,
List.of(
"RIP = 0x00400000;",
"RSP = 0x00110000;",
"RAX = 0x12345678;"),
TraceThread thread = initTrace(tb, """
RIP = 0x00400000;
RSP = 0x00110000;
RAX = 0x12345678;
""",
List.of(
"XOR AH, AH",
"MOV RCX, RAX"));
@ -689,9 +691,9 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
@Test(expected = AccessPcodeExecutionException.class)
public void testCheckedMOV_err() throws Throwable {
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
TraceThread thread = initTrace(tb,
List.of(
"RIP = 0x00400000;"),
TraceThread thread = initTrace(tb, """
RIP = 0x00400000;
""",
List.of(
"MOV RCX,RAX"));
@ -711,10 +713,11 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
@Test
public void testCheckedMOV_known() throws Throwable {
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
TraceThread thread = initTrace(tb,
List.of(
"RIP = 0x00400000;",
"RAX = 0x1234;"), // Make it known in the trace
// Make RAX known in the trace
TraceThread thread = initTrace(tb, """
RIP = 0x00400000;
RAX = 0x1234;
""",
List.of(
"MOV RCX,RAX"));
@ -735,10 +738,11 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
@Test(expected = AccessPcodeExecutionException.class)
public void testCheckedMOV_knownPast_err() throws Throwable {
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
TraceThread thread = initTrace(tb,
List.of(
"RIP = 0x00400000;",
"RAX = 0x1234;"), // Make it known in the trace
// Make RAX known in the trace
TraceThread thread = initTrace(tb, """
RIP = 0x00400000;
RAX = 0x1234;
""",
List.of(
"MOV RCX,RAX"));
@ -760,10 +764,11 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
@Test
public void testCheckedMOV_knownPast_has() throws Throwable {
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
TraceThread thread = initTrace(tb,
List.of(
"RIP = 0x00400000;",
"RAX = 0x1234;"), // Make it known in the trace
// Make RAX known in the trace
TraceThread thread = initTrace(tb, """
RIP = 0x00400000;
RAX = 0x1234;
""",
List.of(
"MOV RCX,RAX"));
@ -785,9 +790,9 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
@Test
public void testCheckedMOV_initialized() throws Throwable {
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
TraceThread thread = initTrace(tb,
List.of(
"RIP = 0x00400000;"),
TraceThread thread = initTrace(tb, """
RIP = 0x00400000;
""",
List.of(
"MOV RAX,0", // Have the program initialize it
"MOV RCX,RAX"));
@ -820,11 +825,11 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
ctxManager.setValue(lang, ctxVal, Range.atLeast(0L),
tb.range(0x00400000, 0x00400002));
}
TraceThread thread = initTrace(tb,
List.of(
"RIP = 0x00400000;",
"RSP = 0x00110000;",
"RAX = 0xff12345678;"),
TraceThread thread = initTrace(tb, """
RIP = 0x00400000;
RSP = 0x00110000;
RAX = 0xff12345678;
""",
List.of(
"DEC EAX",
"MOV ECX,EAX"));
@ -863,11 +868,11 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
@Test
public void testMOV_EAX_dword_RBPm4() throws Throwable {
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
TraceThread thread = initTrace(tb,
List.of(
"RIP = 0x00400000;",
"RSP = 0x00110000;",
"*:4 (0:8-4) = 0x12345678;"),
TraceThread thread = initTrace(tb, """
RIP = 0x00400000;
RSP = 0x00110000;
*:4 (0:8-4) = 0x12345678;
""",
List.of(
"MOV EAX, dword ptr [RBP + -0x4]"));
@ -898,10 +903,10 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
@Test(expected = PcodeExecutionException.class)
public void testMOV_EAX_dword_RBPm2_x64() throws Throwable {
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
TraceThread thread = initTrace(tb,
List.of(
"RIP = 0x00400000;",
"RSP = 0x00110000;"),
TraceThread thread = initTrace(tb, """
RIP = 0x00400000;
RSP = 0x00110000;
""",
List.of(
"MOV EAX, dword ptr [RBP + -0x2]"));
@ -921,10 +926,10 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
@Test(expected = PcodeExecutionException.class)
public void testMOV_EAX_dword_EBPm2_x86() throws Throwable {
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:32:default")) {
TraceThread thread = initTrace(tb,
List.of(
"EIP = 0x00400000;",
"ESP = 0x00110000;"),
TraceThread thread = initTrace(tb, """
EIP = 0x00400000;
ESP = 0x00110000;
""",
List.of(
"MOV EAX, dword ptr [EBP + -0x2]"));
@ -944,10 +949,10 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "Toy:BE:64:default")) {
assertEquals(Register.NO_CONTEXT, tb.language.getContextBaseRegister());
TraceThread thread = initTrace(tb,
List.of(
"pc = 0x00400000;",
"sp = 0x00110000;"),
TraceThread thread = initTrace(tb, """
pc = 0x00400000;
sp = 0x00110000;
""",
List.of(
"unimpl"));
@ -966,11 +971,11 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
Address stackStart = tb.language.getDefaultDataSpace().getAddress(0, true);
TraceThread thread = initTrace(tb,
new AddressRangeImpl(textStart, 0x200),
new AddressRangeImpl(stackStart, 1),
List.of(
"PC = 0x000100;",
"W1 = 0x0800;",
"*[ram]:2 0x000800:3 = 0x1234;"),
new AddressRangeImpl(stackStart, 1), """
PC = 0x000100;
W1 = 0x0800;
*[ram]:2 0x000800:3 = 0x1234;
""",
List.of(
"mov.w [W1], W0"));

View file

@ -19,7 +19,6 @@ import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;
import org.junit.Before;
@ -207,14 +206,14 @@ public class TraceSleighUtilsTest extends AbstractGhidraHeadlessIntegrationTest
public void testCompileSleighProgram() throws Exception {
try (ToyDBTraceBuilder b = new ToyDBTraceBuilder("test", TOY_BE_64_HARVARD)) {
PcodeProgram sp = SleighProgramCompiler.compileProgram((SleighLanguage) b.language,
"test", List.of(
"if (r0) goto <else>;",
" r1 = 6;",
" goto <done>;",
"<else>",
" r1 = 7;",
"<done>"),
PcodeUseropLibrary.NIL);
"test", """
if (r0) goto <else>;
r1 = 6;
goto <done>;
<else>
r1 = 7;
<done>
""", PcodeUseropLibrary.NIL);
TraceThread thread;
try (UndoableTransaction tid = b.startTransaction()) {
thread = b.getOrAddThread("Thread1", 0);

View file

@ -27,7 +27,6 @@ import java.nio.charset.CharsetEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
import com.google.common.collect.Range;
@ -131,9 +130,9 @@ public class ToyDBTraceBuilder implements AutoCloseable {
* @param snap the snap to modify
* @param frame the frame to modify
* @param thread the thread to modify, can be {@code null} if only memory is used
* @param sleigh the lines of Sleigh, including semicolons.
* @param sleigh the Sleigh source
*/
public void exec(long snap, int frame, TraceThread thread, List<String> sleigh) {
public void exec(long snap, int frame, TraceThread thread, String sleigh) {
PcodeProgram program = SleighProgramCompiler.compileProgram((SleighLanguage) language,
"builder", sleigh, PcodeUseropLibrary.nil());
TraceSleighUtils.buildByteExecutor(trace, snap, thread, frame)

View file

@ -15,8 +15,6 @@
*/
package ghidra.trace.model.time.schedule;
import java.util.List;
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.pcode.emu.PcodeThread;
import ghidra.pcode.emu.ThreadPcodeExecutorState;
@ -167,7 +165,7 @@ class TestThread implements PcodeThread<Void> {
}
@Override
public void inject(Address address, List<String> sleigh) {
public void inject(Address address, String source) {
}
@Override

View file

@ -257,19 +257,19 @@ public abstract class AbstractPcodeMachine<T> implements PcodeMachine<T> {
}
@Override
public PcodeProgram compileSleigh(String sourceName, List<String> lines) {
return SleighProgramCompiler.compileProgram(language, sourceName, lines, stubLibrary);
public PcodeProgram compileSleigh(String sourceName, String source) {
return SleighProgramCompiler.compileProgram(language, sourceName, source, stubLibrary);
}
@Override
public void inject(Address address, List<String> sleigh) {
public void inject(Address address, String source) {
/**
* TODO: Can I compile the template and build as if the inject were a
* instruction:^instruction constructor? This would require me to delay that build until
* execution, or at least check for instruction modification, if I do want to cache the
* built p-code.
*/
PcodeProgram pcode = compileSleigh("machine_inject:" + address, sleigh);
PcodeProgram pcode = compileSleigh("machine_inject:" + address, source);
injects.put(address, pcode);
}
@ -292,11 +292,12 @@ public abstract class AbstractPcodeMachine<T> implements PcodeMachine<T> {
* addressed by formalizing and better exposing the notion of p-code stacks (of p-code
* frames)
*/
PcodeProgram pcode = compileSleigh("breakpoint:" + address, List.of(
"if (!(" + sleighCondition + ")) goto <nobreak>;",
" emu_swi();",
"<nobreak>",
" emu_exec_decoded();"));
PcodeProgram pcode = compileSleigh("breakpoint:" + address, String.format("""
if (!(%s)) goto <nobreak>;
emu_swi();
<nobreak>
emu_exec_decoded();
""", sleighCondition));
injects.put(address, pcode);
}
}

View file

@ -33,10 +33,10 @@ import ghidra.util.Msg;
* The default implementation of {@link PcodeThread} suitable for most applications
*
* <p>
* When emulating on concrete state, consider using {@link ModifiedPcodeThread}, so that
* state modifiers from the older {@link Emulator} are incorporated. In either case, it may be
* worthwhile to examine existing state modifiers to ensure they are appropriately represented in
* any abstract state. It may be necessary to port them.
* When emulating on concrete state, consider using {@link ModifiedPcodeThread}, so that state
* modifiers from the older {@link Emulator} are incorporated. In either case, it may be worthwhile
* to examine existing state modifiers to ensure they are appropriately represented in any abstract
* state. It may be necessary to port them.
*
* <p>
* This class implements the control-flow logic of the target machine, cooperating with the p-code
@ -148,9 +148,9 @@ public class DefaultPcodeThread<T> implements PcodeThread<T> {
}
@Override
public void executeSleighLine(String line) {
PcodeProgram program = SleighProgramCompiler.compileProgram(language, "line",
List.of(line + ";"), thread.library);
public void executeSleigh(String source) {
PcodeProgram program =
SleighProgramCompiler.compileProgram(language, "exec", source, thread.library);
execute(program, thread.library);
}
@ -588,9 +588,9 @@ public class DefaultPcodeThread<T> implements PcodeThread<T> {
}
@Override
public void inject(Address address, List<String> sleigh) {
public void inject(Address address, String source) {
PcodeProgram pcode = SleighProgramCompiler.compileProgram(
language, "thread_inject:" + address, sleigh, library);
language, "thread_inject:" + address, source, library);
injects.put(address, pcode);
}

View file

@ -16,7 +16,6 @@
package ghidra.pcode.emu;
import java.util.Collection;
import java.util.List;
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.pcode.emu.DefaultPcodeThread.PcodeEmulationLibrary;
@ -31,7 +30,7 @@ import ghidra.program.model.address.Address;
public interface PcodeMachine<T> {
/**
* Get the machine's SLEIGH language (processor model)
* Get the machine's Sleigh language (processor model)
*
* @return the language
*/
@ -61,7 +60,7 @@ public interface PcodeMachine<T> {
*
* <p>
* 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
* 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. <b>WARNING:</b> The stub library is not required to
* provide implementations of the userops. Often they will throw exceptions, so do not attempt
@ -114,26 +113,26 @@ public interface PcodeMachine<T> {
PcodeExecutorState<T> getSharedState();
/**
* Compile the given SLEIGH code for execution by a thread of this machine
* Compile the given Sleigh code for execution by a thread of this machine
*
* <p>
* This links in the userop library given at construction time and those defining the emulation
* userops, e.g., {@code emu_swi}.
*
* @param sourceName a user-defined source name for the resulting "program"
* @param lines the lines of SLEIGH source code
* @param lines the Sleigh source
* @return the compiled program
*/
PcodeProgram compileSleigh(String sourceName, List<String> lines);
PcodeProgram compileSleigh(String sourceName, String source);
/**
* Override the p-code at the given address with the given SLEIGH source
* Override the p-code at the given address with the given Sleigh source
*
* <p>
* This will attempt to compile the given source against this machine's userop library and then
* will inject it at the given address. The resulting p-code <em>replaces</em> that which would
* be executed by decoding the instruction at the given address. The means the machine will not
* decode, nor advance its counter, unless the SLEIGH causes it. In most cases, the SLEIGH will
* decode, nor advance its counter, unless the Sleigh causes it. In most cases, the Sleigh will
* call {@link PcodeEmulationLibrary#emu_exec_decoded()} to cause the machine to decode and
* execute the overridden instruction.
*
@ -143,9 +142,9 @@ public interface PcodeMachine<T> {
* double-wrapping, etc.
*
* @param address the address to inject at
* @param sleigh the SLEIGH source to compile and inject
* @param source the Sleigh source to compile and inject
*/
void inject(Address address, List<String> sleigh);
void inject(Address address, String source);
/**
* Remove the inject, if present, at the given address
@ -165,10 +164,10 @@ public interface PcodeMachine<T> {
* <p>
* Breakpoints are implemented at the p-code level using an inject, without modification to the
* emulated image. As such, it cannot coexist with another inject. A client needing to break
* during an inject must use {@link PcodeEmulationLibrary#emu_swi()} in the injected SLEIGH.
* during an inject must use {@link PcodeEmulationLibrary#emu_swi()} in the injected Sleigh.
*
* @param address the address at which to break
* @param sleighCondition a SLEIGH expression which controls the breakpoint
* @param sleighCondition a Sleigh expression which controls the breakpoint
*/
void addBreakpoint(Address address, String sleighCondition);
}

View file

@ -336,9 +336,9 @@ public interface PcodeThread<T> {
* inject.
*
* @param address the address to inject at
* @param sleigh the SLEIGH source to compile and inject
* @param source the Sleigh source to compile and inject
*/
void inject(Address address, List<String> sleigh);
void inject(Address address, String source);
/**
* Remove the per-thread inject, if present, at the given address

View file

@ -28,9 +28,10 @@ public class X86PcodeStateInitializer implements PcodeStateInitializer {
private static final List<LanguageID> LANG_IDS = List.of(
new LanguageID("x86:LE:32:default"),
new LanguageID("x86:LE:64:default"));
private static final List<String> SOURCE = List.of(
"FS_OFFSET = 0;",
"GS_OFFSET = 0;");
private static final String SOURCE = """
FS_OFFSET = 0;
GS_OFFSET = 0;
""";
@Override
public boolean isApplicable(Language language) {

View file

@ -91,13 +91,13 @@ public class PcodeExecutor<T> {
}
/**
* Compile and execute a line of Sleigh
* Compile and execute a block of Sleigh
*
* @param line the line, excluding the semicolon
* @param source the Sleigh source
*/
public void executeSleighLine(String line) {
PcodeProgram program = SleighProgramCompiler.compileProgram(language,
"line", List.of(line + ";"), PcodeUseropLibrary.NIL);
public void executeSleigh(String source) {
PcodeProgram program =
SleighProgramCompiler.compileProgram(language, "exec", source, PcodeUseropLibrary.NIL);
execute(program, PcodeUseropLibrary.nil());
}

View file

@ -15,7 +15,6 @@
*/
package ghidra.pcode.exec;
import java.text.MessageFormat;
import java.util.*;
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
@ -65,7 +64,7 @@ public class SleighPcodeUseropDefinition<T> implements PcodeUseropDefinition<T>
private final Factory factory;
private final String name;
private final List<String> params = new ArrayList<>();
private final List<String> lines = new ArrayList<>();
private final StringBuffer body = new StringBuffer();
protected Builder(Factory factory, String name) {
this.factory = factory;
@ -93,41 +92,12 @@ public class SleighPcodeUseropDefinition<T> implements PcodeUseropDefinition<T>
}
/**
* Add lines of SLEIGH source
* Add Sleigh source to the body
*
* <p>
* NOTE: The lines are joined only with line separators. No semicolons (;) are added at the
* end of each line.
*
* <p>
* TODO: See if this can be made any prettier with text blocks in newer Java versions.
*
* @param additionalLines the additional lines
* @return this builder
* @param additionalBody the additional source
*/
public Builder sleigh(Collection<String> additionalLines) {
this.lines.addAll(additionalLines);
return this;
}
/**
* @see #sleigh(Collection)
*/
public Builder sleigh(String... additionalLines) {
return this.sleigh(Arrays.asList(additionalLines));
}
/**
* Treat each line as a pattern as in {@link MessageFormat#format(String, Object...)},
* replacing each with the result.
*
* @param arguments the arguments to pass to the formatter
* @return this builder
*/
public Builder applyAsPattern(Object[] arguments) {
for (int i = 0; i < lines.size(); i++) {
lines.set(i, MessageFormat.format(lines.get(i), arguments));
}
public Builder body(CharSequence additionalBody) {
body.append(additionalBody);
return this;
}
@ -144,23 +114,23 @@ public class SleighPcodeUseropDefinition<T> implements PcodeUseropDefinition<T>
*/
public <T> SleighPcodeUseropDefinition<T> build() {
return new SleighPcodeUseropDefinition<>(factory.language, name, List.copyOf(params),
List.copyOf(lines));
body.toString());
}
}
private final SleighLanguage language;
private final String name;
private final List<String> params;
private final List<String> lines;
private final String body;
private final Map<List<Varnode>, PcodeProgram> cacheByArgs = new HashMap<>();
protected SleighPcodeUseropDefinition(SleighLanguage language, String name, List<String> params,
List<String> lines) {
String body) {
this.language = language;
this.name = name;
this.params = params;
this.lines = lines;
this.body = body;
}
/**
@ -181,7 +151,7 @@ public class SleighPcodeUseropDefinition<T> implements PcodeUseropDefinition<T>
args.add(outArg);
args.addAll(inArgs);
return cacheByArgs.computeIfAbsent(args,
a -> SleighProgramCompiler.compileUserop(language, name, params, lines, library, a));
a -> SleighProgramCompiler.compileUserop(language, name, params, body, library, a));
}
@Override
@ -211,11 +181,11 @@ public class SleighPcodeUseropDefinition<T> implements PcodeUseropDefinition<T>
}
/**
* Get the lines of source that define this userop
* Get the Sleigh source that defines this userop
*
* @return the lines
*/
public List<String> getLines() {
return lines;
public String getBody() {
return body;
}
}

View file

@ -19,8 +19,6 @@ import java.io.IOException;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import ghidra.app.plugin.processors.sleigh.*;
import ghidra.app.plugin.processors.sleigh.template.ConstructTpl;
import ghidra.pcodeCPort.pcoderaw.VarnodeData;
@ -66,12 +64,12 @@ public class SleighProgramCompiler {
* @param language the language
* @param parser the parser
* @param sourceName the name of the program, for error diagnostics
* @param text the SLEIGH source
* @param source the Sleigh source
* @return the constructor template
*/
public static ConstructTpl compileTemplate(Language language, PcodeParser parser,
String sourceName, String text) {
return parser.compilePcode(text, EXPRESSION_SOURCE_NAME, 1);
String sourceName, String source) {
return parser.compilePcode(source, EXPRESSION_SOURCE_NAME, 1);
}
/**
@ -82,7 +80,7 @@ public class SleighProgramCompiler {
* @return the list of p-code ops
* @throws UnknownInstructionException in case of crossbuilds, the target instruction is unknown
* @throws MemoryAccessException in case of crossbuilds, the target address cannot be accessed
* @throws IOException for errors in during emitting
* @throws IOException for errors in during emitting
*/
public static List<PcodeOp> buildOps(Language language, ConstructTpl template)
throws UnknownInstructionException, MemoryAccessException, IOException {
@ -164,33 +162,31 @@ public class SleighProgramCompiler {
}
/**
* Compile the given SLEIGH source into a simple p-code program
* Compile the given Sleigh source into a simple p-code program
*
* <p>
* This is suitable for modifying program state using SLEIGH statements. Most likely, in
* scripting, or perhaps in a SLEIGH repl. The library given during compilation must match the
* This is suitable for modifying program state using Sleigh statements. Most likely, in
* scripting, or perhaps in a Sleigh repl. The library given during compilation must match the
* library given for execution, at least in its binding of userop IDs to symbols.
*
* @param language the language of the target p-code machine
* @param sourceName a diagnostic name for the SLEIGH source
* @param lines the lines of SLEIGH source. These are joined with line separators but no
* semicolon!
* @param sourceName a diagnostic name for the Sleigh source
* @param source the Sleigh source
* @param library the userop library or stub library for binding userop symbols
* @return the compiled p-code program
*/
public static PcodeProgram compileProgram(SleighLanguage language, String sourceName,
List<String> lines, PcodeUseropLibrary<?> library) {
String source, PcodeUseropLibrary<?> library) {
PcodeParser parser = createParser(language);
Map<Integer, UserOpSymbol> symbols = library.getSymbols(language);
addParserSymbols(parser, symbols);
ConstructTpl template =
compileTemplate(language, parser, sourceName, StringUtils.join(lines, "\n"));
ConstructTpl template = compileTemplate(language, parser, sourceName, source);
return constructProgram(PcodeProgram::new, language, template, symbols);
}
/**
* Compile the given SLEIGH expression into a p-code program that can evaluate it
* Compile the given Sleigh expression into a p-code program that can evaluate it
*
* <p>
* TODO: Currently, expressions cannot be compiled for a user-supplied userop library. The
@ -198,7 +194,7 @@ public class SleighProgramCompiler {
* userop libraries are easily composed. It should be easy to add that feature if needed.
*
* @param language the languge of the target p-code machine
* @param expression the SLEIGH expression to be evaluated
* @param expression the Sleigh expression to be evaluated
* @return a p-code program whose {@link PcodeExpression#evaluate(PcodeExecutor)} method will
* evaluate the expression on the given executor and its state.
*/
@ -213,7 +209,7 @@ public class SleighProgramCompiler {
}
/**
* Generate a SLEIGH symbol for context when compiling a userop definition
* Generate a Sleigh symbol for context when compiling a userop definition
*
* @param language the language of the target p-code machine
* @param sleigh a means of translating address spaces between execution and compilation
@ -221,7 +217,7 @@ public class SleighProgramCompiler {
* @param opName a diagnostic name for the userop in which this parameter applies
* @param paramName the symbol name for the parameter
* @param arg the varnode to bind to the parameter symbol
* @return the named SLEIGH symbol bound to the given varnode
* @return the named Sleigh symbol bound to the given varnode
*/
public static VarnodeSymbol paramSym(Language language, SleighBase sleigh, String opName,
String paramName, Varnode arg) {
@ -232,11 +228,11 @@ public class SleighProgramCompiler {
}
/**
* Compile the definition of a p-code userop from SLEIGH source into a p-code program
* Compile the definition of a p-code userop from Sleigh source into a p-code program
*
* <p>
* TODO: Defining a userop from SLEIGH source is currently a bit of a hack. It would be nice if
* there were a formalization of SLEIGH/p-code subroutines. At the moment, the control flow for
* TODO: Defining a userop from Sleigh source is currently a bit of a hack. It would be nice if
* there were a formalization of Sleigh/p-code subroutines. At the moment, the control flow for
* subroutines is handled out of band, which actually works fairly well. However, parameter
* passing and returning results is not well defined. The current solution is to alias the
* parameters to their arguments, implementing a pass-by-reference scheme. Similarly, the output
@ -256,14 +252,13 @@ public class SleighProgramCompiler {
* @param opName the name of the userop (used only for diagnostics here)
* @param params the names of parameters in order. Index 0 names the output symbol, probably
* {@link SleighPcodeUseropDefinition#OUT_SYMBOL_NAME}
* @param lines the lines of SLEIGH source. These are joined with line separators but no
* semicolon!
* @param source the Sleigh source
* @param library the userop library or stub library for binding userop symbols
* @param args the varnode arguments in order. Index 0 is the output varnode.
* @return a p-code program that implements the userop for the given arguments
*/
public static PcodeProgram compileUserop(SleighLanguage language, String opName,
List<String> params, List<String> lines, PcodeUseropLibrary<?> library,
List<String> params, String source, PcodeUseropLibrary<?> library,
List<Varnode> args) {
PcodeParser parser = createParser(language);
Map<Integer, UserOpSymbol> symbols = library.getSymbols(language);
@ -288,7 +283,6 @@ public class SleighProgramCompiler {
}
}
String source = StringUtils.join(lines, "\n");
try {
ConstructTpl template = compileTemplate(language, parser, opName, source);
return constructProgram(PcodeProgram::new, language, template, symbols);

View file

@ -79,7 +79,7 @@ abstract class AbstractStmt implements Stmt {
* @param fall the label positioned immediately after this statement in the generated code
* @return the generated Sleigh code
*/
protected abstract String generate(Label next, Label fall);
protected abstract StringTree generate(Label next, Label fall);
/**
* Check if the statement is or contains a single branch statement

View file

@ -49,8 +49,14 @@ class AssignStmt extends AbstractStmt implements RValInternal, StmtWithVal {
}
@Override
protected String generate(Label next, Label fall) {
return lhs.generate() + " = " + rhs.generate() + ";\n" + next.genGoto(fall);
protected StringTree generate(Label next, Label fall) {
StringTree st = new StringTree();
st.append(lhs.generate());
st.append(" = ");
st.append(rhs.generate());
st.append(";\n");
st.append(next.genGoto(fall));
return st;
}
@Override

View file

@ -49,16 +49,16 @@ class BlockStmt extends AbstractStmt {
}
@Override
protected String generate(Label next, Label fall) {
protected StringTree generate(Label next, Label fall) {
if (children.isEmpty()) {
return next.genGoto(fall);
}
StringBuilder sb = new StringBuilder();
StringTree st = new StringTree();
for (AbstractStmt c : children.subList(0, children.size() - 1)) {
sb.append(c.generate(ctx.FALL, ctx.FALL));
st.append(c.generate(ctx.FALL, ctx.FALL));
}
sb.append(children.get(children.size() - 1).generate(next, fall));
return sb.toString();
st.append(children.get(children.size() - 1).generate(next, fall));
return st;
}
@Override

View file

@ -29,8 +29,14 @@ class DeclStmt extends AbstractStmt {
}
@Override
protected String generate(Label next, Label fall) {
return "local " + name + ":" + type.getLength() + ";\n" +
next.genGoto(fall);
protected StringTree generate(Label next, Label fall) {
StringTree st = new StringTree();
st.append("local ");
st.append(name);
st.append(":");
st.append(Integer.toString(type.getLength()));
st.append(";\n");
st.append(next.genGoto(fall));
return st;
}
}

View file

@ -29,23 +29,26 @@ class ForStmt extends LoopStmt {
}
@Override
protected String generate(Label next, Label fall) {
protected StringTree generate(Label next, Label fall) {
Label lTest = ctx.new FreshLabel();
Label lBegin = ctx.new FreshLabel();
Label lExit = lBreak = next.freshOrBorrow();
Label lStep = lContinue = ctx.new FreshLabel();
String initGen = init.generate(lTest, lTest);
String testGen = lExit.genGoto(cond.notb(), lBegin);
String stmtGen = stmt.generate(lStep, lStep);
String stepGen = step.generate(lTest, fall);
return initGen +
lTest.genAnchor() +
testGen +
lBegin.genAnchor() +
stmtGen +
lStep.genAnchor() +
stepGen +
lExit.genAnchor();
StringTree initGen = init.generate(lTest, lTest);
StringTree testGen = lExit.genGoto(cond.notb(), lBegin);
StringTree stmtGen = stmt.generate(lStep, lStep);
StringTree stepGen = step.generate(lTest, fall);
StringTree st = new StringTree();
st.append(initGen);
st.append(lTest.genAnchor());
st.append(testGen);
st.append(lBegin.genAnchor());
st.append(stmtGen);
st.append(lStep.genAnchor());
st.append(stepGen);
st.append(lExit.genAnchor());
return st;
}
}

View file

@ -25,7 +25,8 @@ class IfStmt extends ConditionalStmt {
}
@Override
protected String generate(Label next, Label fall) {
protected StringTree generate(Label next, Label fall) {
StringTree st = new StringTree();
if (elseStmt == null) {
if (stmt.isSingleGoto()) {
return stmt.getNext().genGoto(cond, fall);
@ -34,28 +35,31 @@ class IfStmt extends ConditionalStmt {
Label lTrue = ctx.new FreshLabel();
Label lFalse = next.freshOrBorrow();
String condGen = lFalse.genGoto(cond.notb(), lTrue);
String stmtGen = stmt.generate(next, fall);
return condGen +
lTrue.genAnchor() +
stmtGen +
lFalse.genAnchor();
StringTree condGen = lFalse.genGoto(cond.notb(), lTrue);
StringTree stmtGen = stmt.generate(next, fall);
st.append(condGen);
st.append(lTrue.genAnchor());
st.append(stmtGen);
st.append(lFalse.genAnchor());
}
else {
Label lFalse = ctx.new FreshLabel();
Label lTrue = ctx.new FreshLabel();
Label lExit = next.freshOrBorrow();
Label lFalse = ctx.new FreshLabel();
Label lTrue = ctx.new FreshLabel();
Label lExit = next.freshOrBorrow();
StringTree condGen = lTrue.genGoto(cond, lFalse);
StringTree elseGen = elseStmt.generate(lExit, lTrue);
StringTree stmtGen = stmt.generate(next, fall);
String condGen = lTrue.genGoto(cond, lFalse);
String elseGen = elseStmt.generate(lExit, lTrue);
String stmtGen = stmt.generate(next, fall);
return condGen +
lFalse.genAnchor() +
elseGen +
lTrue.genAnchor() +
stmtGen +
lExit.genAnchor();
st.append(condGen);
st.append(lFalse.genAnchor());
st.append(elseGen);
st.append(lTrue.genAnchor());
st.append(stmtGen);
st.append(lExit.genAnchor());
}
return st;
}
protected void addElse(Stmt elseStmt) {

View file

@ -32,7 +32,7 @@ abstract class LoopTruncateStmt extends AbstractStmt {
}
@Override
protected String generate(Label next, Label fall) {
protected StringTree generate(Label next, Label fall) {
return getNext().genGoto(fall);
}

View file

@ -26,7 +26,11 @@ class RawStmt extends AbstractStmt {
}
@Override
protected String generate(Label next, Label fall) {
return stmt + ";\n" + next.genGoto(fall);
protected StringTree generate(Label next, Label fall) {
StringTree st = new StringTree();
st.append(stmt);
st.append(";\n");
st.append(next.genGoto(fall));
return st;
}
}

View file

@ -30,14 +30,19 @@ class ResultStmt extends AbstractStmt {
}
@Override
protected String generate(Label next, Label fall) {
protected StringTree generate(Label next, Label fall) {
RoutineStmt routine = Objects.requireNonNull(nearest(RoutineStmt.class));
if (!ctx.isAssignable(routine.retType, result.getType())) {
ctx.emitResultTypeMismatch(routine, result);
}
return SleighPcodeUseropDefinition.OUT_SYMBOL_NAME + " = " + result.generate() + ";\n" +
routine.lReturn.genGoto(fall);
StringTree st = new StringTree();
st.append(SleighPcodeUseropDefinition.OUT_SYMBOL_NAME);
st.append(" = ");
st.append(result.generate());
st.append(";\n");
st.append(routine.lReturn.genGoto(fall));
return st;
}
}

View file

@ -27,7 +27,11 @@ class ReturnStmt extends AbstractStmt {
}
@Override
protected String generate(Label next, Label fall) {
return "return " + target.generate() + ";\n";
protected StringTree generate(Label next, Label fall) {
StringTree st = new StringTree();
st.append("return ");
st.append(target.generate());
st.append(";\n");
return st;
}
}

View file

@ -32,14 +32,17 @@ class RoutineStmt extends BlockStmt {
}
@Override
protected String generate(Label next, Label fall) {
protected StringTree generate(Label next, Label fall) {
if (children.isEmpty()) {
return "";
return StringTree.single("");
}
Label lExit = lReturn = next.freshOrBorrow();
// This is an odd case, because it's the root: use lExit instead of fall
String blockGen = super.generate(lReturn, lExit);
return blockGen +
lExit.genAnchor();
StringTree blockGen = super.generate(lReturn, lExit);
StringTree st = new StringTree();
st.append(blockGen);
st.append(lExit.genAnchor());
return st;
}
}

View file

@ -0,0 +1,76 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.struct;
import java.util.LinkedList;
import java.util.List;
public class StringTree {
public static StringTree single(CharSequence seq) {
StringTree st = new StringTree();
st.append(seq);
return st;
}
interface Node {
void walk(StringBuffer buf);
}
class Branch implements Node {
List<Node> children = new LinkedList<>();
void addChild(Node child) {
children.add(child);
}
@Override
public void walk(StringBuffer buf) {
for (Node child : children) {
child.walk(buf);
}
}
}
class Leaf implements Node {
final CharSequence seq;
public Leaf(CharSequence seq) {
this.seq = seq;
}
@Override
public void walk(StringBuffer buf) {
buf.append(seq);
}
}
Branch root = new Branch();
public void append(CharSequence seq) {
root.addChild(new Leaf(seq));
}
public void append(StringTree tree) {
root.addChild(tree.root);
}
@Override
public String toString() {
StringBuffer buf = new StringBuffer();
root.walk(buf);
return buf.toString();
}
}

View file

@ -987,13 +987,14 @@ public class StructuredSleigh {
/**
* Generate code for this label
*
* <p>
* This must be the last method called on the label, because it relies on knowing whether or
* not the label is actually used. (The Sleigh compiler rejects code if it contains unused
* labels.)
*
* @return the Sleigh code
*/
abstract String genAnchor();
abstract StringTree genAnchor();
/**
* Generate a reference to this label as it should appear in a Sleigh "{@code goto}"
@ -1001,7 +1002,7 @@ public class StructuredSleigh {
*
* @return the label's expression
*/
abstract String ref();
abstract StringTree ref();
/**
* Generate a goto statement that targets this label
@ -1009,7 +1010,7 @@ public class StructuredSleigh {
* @param fall the label following the goto
* @return the Sleigh code
*/
abstract String genGoto(Label fall);
abstract StringTree genGoto(Label fall);
/**
* Generate a conditional goto statement that targets this label
@ -1018,7 +1019,7 @@ public class StructuredSleigh {
* @param fall the label following the goto
* @return the Sleigh code
*/
abstract String genGoto(RVal cond, Label fall);
abstract StringTree genGoto(RVal cond, Label fall);
}
/**
@ -1041,32 +1042,49 @@ public class StructuredSleigh {
}
@Override
public String genAnchor() {
public StringTree genAnchor() {
if (name == null) {
return "";
return StringTree.single("");
}
return "<" + name + ">\n";
StringTree st = new StringTree();
st.append("<");
st.append(name);
st.append(">\n");
return st;
}
@Override
public String ref() {
return "<" + getName() + ">";
public StringTree ref() {
StringTree st = new StringTree();
st.append("<");
st.append(getName());
st.append(">");
return st;
}
@Override
public String genGoto(Label fall) {
public StringTree genGoto(Label fall) {
if (this == fall) {
return "";
return StringTree.single("");
}
return "goto " + ref() + ";\n";
StringTree st = new StringTree();
st.append("goto ");
st.append(ref());
st.append(";\n");
return st;
}
@Override
public String genGoto(RVal cond, Label fall) {
public StringTree genGoto(RVal cond, Label fall) {
if (this == fall) {
return "";
return StringTree.single("");
}
return "if " + ((RValInternal) cond).generate() + " " + genGoto(fall);
StringTree st = new StringTree();
st.append("if ");
st.append(((RValInternal) cond).generate());
st.append(" ");
st.append(genGoto(fall));
return st;
}
}
@ -1091,27 +1109,27 @@ public class StructuredSleigh {
}
@Override
public String genAnchor() {
return "";
public StringTree genAnchor() {
return StringTree.single("");
}
@Override
public String ref() {
public StringTree ref() {
return borrowed.ref();
}
@Override
public String genGoto(Label fall) {
public StringTree genGoto(Label fall) {
if (this == fall) { // placed will also check
return "";
return StringTree.single("");
}
return borrowed.genGoto(fall);
}
@Override
public String genGoto(RVal cond, Label fall) {
public StringTree genGoto(RVal cond, Label fall) {
if (this == fall) { // placed with also check
return "";
return StringTree.single("");
}
return borrowed.genGoto(cond, fall);
}
@ -1132,22 +1150,22 @@ public class StructuredSleigh {
}
@Override
public String genAnchor() {
return "";
public StringTree genAnchor() {
return StringTree.single("");
}
@Override
public String ref() {
public StringTree ref() {
throw new AssertionError();
}
@Override
public String genGoto(Label fall) {
return "";
public StringTree genGoto(Label fall) {
return StringTree.single("");
}
@Override
public String genGoto(RVal cond, Label fall) {
public StringTree genGoto(RVal cond, Label fall) {
throw new AssertionError();
}
}
@ -1703,8 +1721,8 @@ public class StructuredSleigh {
e);
}
});
String source = root.generate(FALL, FALL);
builder.sleigh(source);
StringTree source = root.generate(FALL, FALL);
builder.body(source.toString());
return builder.build();
}

View file

@ -43,8 +43,12 @@ class VoidExprStmt extends AbstractStmt implements RValInternal, StmtWithVal {
}
@Override
protected String generate(Label next, Label fall) {
return expr.generate() + ";\n" + next.genGoto(fall);
protected StringTree generate(Label next, Label fall) {
StringTree st = new StringTree();
st.append(expr.generate());
st.append(";\n");
st.append(next.genGoto(fall));
return st;
}
@Override

View file

@ -23,17 +23,21 @@ class WhileStmt extends LoopStmt {
}
@Override
protected String generate(Label next, Label fall) {
protected StringTree generate(Label next, Label fall) {
Label lTest = lContinue = ctx.new FreshLabel();
Label lBegin = ctx.new FreshLabel();
Label lExit = lBreak = next.freshOrBorrow();
String testGen = lExit.genGoto(cond.notb(), lBegin);
String stmtGen = stmt.generate(lTest, fall);
return lTest.genAnchor() +
testGen +
lBegin.genAnchor() +
stmtGen +
lExit.genAnchor();
StringTree testGen = lExit.genGoto(cond.notb(), lBegin);
StringTree stmtGen = stmt.generate(lTest, fall);
StringTree st = new StringTree();
st.append(lTest.genAnchor());
st.append(testGen);
st.append(lBegin.genAnchor());
st.append(stmtGen);
st.append(lExit.genAnchor());
return st;
}
}

View file

@ -20,7 +20,6 @@ import static org.junit.Assert.assertTrue;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.util.List;
import org.junit.Test;
@ -53,15 +52,15 @@ public class AnnotatedPcodeUseropLibraryTest extends AbstractGhidraHeadlessInteg
}
protected <T> void executeSleigh(PcodeExecutor<T> executor, PcodeUseropLibrary<T> library,
String... lines) {
String source) {
PcodeProgram program = SleighProgramCompiler.compileProgram(executor.getLanguage(), "test",
List.of(lines), library);
source, library);
executor.execute(program, library);
}
protected void executeSleigh(PcodeUseropLibrary<byte[]> library, String... lines)
protected void executeSleigh(PcodeUseropLibrary<byte[]> library, String source)
throws Exception {
executeSleigh(createBytesExecutor(), library, lines);
executeSleigh(createBytesExecutor(), library, source);
}
protected static void assertBytes(long expectedVal, int expectedSize, byte[] actual) {

View file

@ -17,8 +17,6 @@ package ghidra.pcode.exec;
import static org.junit.Assert.assertEquals;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
@ -27,26 +25,34 @@ import ghidra.program.model.lang.LanguageID;
import ghidra.test.AbstractGhidraHeadlessIntegrationTest;
public class PcodeFrameTest extends AbstractGhidraHeadlessIntegrationTest {
static final List<String> SAMPLE_ADD = List.of(
"r0 = r0 + r1;");
static final List<String> SAMPLE_ADD2 = List.of(
"r0 = r0 + r1 + r2;");
static final List<String> SAMPLE_IF = List.of(
"if (r0 == r1) goto <skip>;",
"r2 = r2 + 1;",
"<skip>");
static final List<String> SAMPLE_LOOP = List.of(
"<loop>",
"r0 = r0 + 1;",
"if (r0 == r1) goto <loop>;");
static final List<String> SAMPLE_BRANCH = List.of(
"goto 0x1234;");
static final List<String> SAMPLE_LOAD = List.of(
"r0 = *:8 r1;");
static final List<String> SAMPLE_LANG_USEROP = List.of(
"pcodeop_one(r0);");
static final List<String> SAMPLE_LIB_USEROP = List.of(
"__lib_userop(r0);");
static final String SAMPLE_ADD = """
r0 = r0 + r1;
""";
static final String SAMPLE_ADD2 = """
r0 = r0 + r1 + r2;
""";
static final String SAMPLE_IF = """
if (r0 == r1) goto <skip>;
r2 = r2 + 1;
<skip>
""";
static final String SAMPLE_LOOP = """
<loop>
r0 = r0 + 1;
if (r0 == r1) goto <loop>;
""";
static final String SAMPLE_BRANCH = """
goto 0x1234;
""";
static final String SAMPLE_LOAD = """
r0 = *:8 r1;
""";
static final String SAMPLE_LANG_USEROP = """
pcodeop_one(r0);
""";
static final String SAMPLE_LIB_USEROP = """
__lib_userop(r0);
""";
static class MyLib extends AnnotatedPcodeUseropLibrary<Void> {
@PcodeUserop
@ -63,11 +69,11 @@ public class PcodeFrameTest extends AbstractGhidraHeadlessIntegrationTest {
(SleighLanguage) getLanguageService().getLanguage(new LanguageID("Toy:BE:64:default"));
}
private PcodeProgram compile(List<String> sample) {
private PcodeProgram compile(String sample) {
return SleighProgramCompiler.compileProgram(language, getName(), sample, library);
}
private PcodeFrame frame(List<String> sample) {
private PcodeFrame frame(String sample) {
PcodeProgram program = compile(sample);
return new PcodeFrame(language, program.code, program.useropNames);
}
@ -75,172 +81,172 @@ public class PcodeFrameTest extends AbstractGhidraHeadlessIntegrationTest {
@Test
public void testProgramToStringAdd() throws Exception {
PcodeProgram program = compile(SAMPLE_ADD);
assertEquals("" +
"<PcodeProgram:\n" +
" r0 = INT_ADD r0, r1\n" +
">",
assertEquals("""
<PcodeProgram:
r0 = INT_ADD r0, r1
>""",
program.toString());
}
@Test
public void testProgramToStringAdd2() throws Exception {
PcodeProgram program = compile(SAMPLE_ADD2);
assertEquals("" +
"<PcodeProgram:\n" +
" $U2000:8 = INT_ADD r0, r1\n" +
" r0 = INT_ADD $U2000:8, r2\n" +
">",
assertEquals("""
<PcodeProgram:
$U2000:8 = INT_ADD r0, r1
r0 = INT_ADD $U2000:8, r2
>""",
program.toString());
}
@Test
public void testProgramToStringIf() throws Exception {
PcodeProgram program = compile(SAMPLE_IF);
assertEquals("" +
"<PcodeProgram:\n" +
" $U2000:1 = INT_EQUAL r0, r1\n" +
" CBRANCH <0>, $U2000:1\n" +
" r2 = INT_ADD r2, 1:8\n" +
"<0>\n" +
">",
assertEquals("""
<PcodeProgram:
$U2000:1 = INT_EQUAL r0, r1
CBRANCH <0>, $U2000:1
r2 = INT_ADD r2, 1:8
<0>
>""",
program.toString());
}
@Test
public void testProgramToStringLoop() throws Exception {
PcodeProgram program = compile(SAMPLE_LOOP);
assertEquals("" +
"<PcodeProgram:\n" +
"<0>\n" +
" r0 = INT_ADD r0, 1:8\n" +
" $U2080:1 = INT_EQUAL r0, r1\n" +
" CBRANCH <0>, $U2080:1\n" +
">",
assertEquals("""
<PcodeProgram:
<0>
r0 = INT_ADD r0, 1:8
$U2080:1 = INT_EQUAL r0, r1
CBRANCH <0>, $U2080:1
>""",
program.toString());
}
@Test
public void testProgramToStringLoad() throws Exception {
PcodeProgram program = compile(SAMPLE_LOAD);
assertEquals("" +
"<PcodeProgram:\n" +
" r0 = LOAD ram(r1)\n" +
">",
assertEquals("""
<PcodeProgram:
r0 = LOAD ram(r1)
>""",
program.toString());
}
@Test
public void testProgramToStringLangUserop() throws Exception {
PcodeProgram program = compile(SAMPLE_LANG_USEROP);
assertEquals("" +
"<PcodeProgram:\n" +
" CALLOTHER \"pcodeop_one\", r0\n" +
">",
assertEquals("""
<PcodeProgram:
CALLOTHER "pcodeop_one", r0
>""",
program.toString());
}
@Test
public void testProgramToStringLibUserop() throws Exception {
PcodeProgram program = compile(SAMPLE_LIB_USEROP);
assertEquals("" +
"<PcodeProgram:\n" +
" CALLOTHER \"__lib_userop\", r0\n" +
">",
assertEquals("""
<PcodeProgram:
CALLOTHER "__lib_userop", r0
>""",
program.toString());
}
@Test
public void testFrameToStringAdd() throws Exception {
PcodeFrame frame = frame(SAMPLE_ADD);
assertEquals("" +
"<p-code frame: index=0 {\n" +
" -> r0 = INT_ADD r0, r1\n" +
"}>",
assertEquals("""
<p-code frame: index=0 {
-> r0 = INT_ADD r0, r1
}>""",
frame.toString());
frame.advance();
assertEquals("" +
"<p-code frame: index=1 {\n" +
" r0 = INT_ADD r0, r1\n" +
" *> fall-through\n" +
"}>",
assertEquals("""
<p-code frame: index=1 {
r0 = INT_ADD r0, r1
*> fall-through
}>""",
frame.toString());
}
@Test
public void testFrameToStringIf() throws Exception {
PcodeFrame frame = frame(SAMPLE_IF);
assertEquals("" +
"<p-code frame: index=0 {\n" +
" -> $U2000:1 = INT_EQUAL r0, r1\n" +
" CBRANCH <0>, $U2000:1\n" +
" r2 = INT_ADD r2, 1:8\n" +
" <0>\n" +
"}>",
assertEquals("""
<p-code frame: index=0 {
-> $U2000:1 = INT_EQUAL r0, r1
CBRANCH <0>, $U2000:1
r2 = INT_ADD r2, 1:8
<0>
}>""",
frame.toString());
frame.advance();
frame.advance();
frame.advance();
assertEquals("" +
"<p-code frame: index=3 {\n" +
" $U2000:1 = INT_EQUAL r0, r1\n" +
" CBRANCH <0>, $U2000:1\n" +
" r2 = INT_ADD r2, 1:8\n" +
" <0>\n" +
" *> fall-through\n" +
"}>",
assertEquals("""
<p-code frame: index=3 {
$U2000:1 = INT_EQUAL r0, r1
CBRANCH <0>, $U2000:1
r2 = INT_ADD r2, 1:8
<0>
*> fall-through
}>""",
frame.toString());
}
@Test
public void testFrameToStringLoop() throws Exception {
PcodeFrame frame = frame(SAMPLE_LOOP);
assertEquals("" +
"<p-code frame: index=0 {\n" +
" <0>\n" +
" -> r0 = INT_ADD r0, 1:8\n" +
" $U2080:1 = INT_EQUAL r0, r1\n" +
" CBRANCH <0>, $U2080:1\n" +
"}>",
assertEquals("""
<p-code frame: index=0 {
<0>
-> r0 = INT_ADD r0, 1:8
$U2080:1 = INT_EQUAL r0, r1
CBRANCH <0>, $U2080:1
}>""",
frame.toString());
}
@Test
public void testFrameToStringBranch() throws Exception {
PcodeFrame frame = frame(SAMPLE_BRANCH);
assertEquals("" +
"<p-code frame: index=0 {\n" +
" -> BRANCH *[ram]0x1234:8\n" +
"}>",
assertEquals("""
<p-code frame: index=0 {
-> BRANCH *[ram]0x1234:8
}>""",
frame.toString());
frame.advance();
frame.finishAsBranch();
assertEquals("" +
"<p-code frame: index=-1 branched=0 {\n" +
" *> BRANCH *[ram]0x1234:8\n" +
"}>",
assertEquals("""
<p-code frame: index=-1 branched=0 {
*> BRANCH *[ram]0x1234:8
}>""",
frame.toString());
}
@Test
public void testFrameToStringLangUserop() throws Exception {
PcodeFrame frame = frame(SAMPLE_LANG_USEROP);
assertEquals("" +
"<p-code frame: index=0 {\n" +
" -> CALLOTHER \"pcodeop_one\", r0\n" +
"}>",
assertEquals("""
<p-code frame: index=0 {
-> CALLOTHER \"pcodeop_one\", r0
}>""",
frame.toString());
}
@Test
public void testFrameToStringLibUserop() throws Exception {
PcodeFrame frame = frame(SAMPLE_LIB_USEROP);
assertEquals("" +
"<p-code frame: index=0 {\n" +
" -> CALLOTHER \"__lib_userop\", r0\n" +
"}>",
assertEquals("""
<p-code frame: index=0 {
-> CALLOTHER \"__lib_userop\", r0
}>""",
frame.toString());
}
}

View file

@ -65,7 +65,7 @@ public class StructuredSleighTest extends AbstractGhidraHeadlessIntegrationTest
}
};
SleighPcodeUseropDefinition<Object> myUserop = ss.generate().get("my_userop");
assertEquals(List.of("__op_output = (param_1 * 0x2:4);\n"), myUserop.getLines());
assertEquals("__op_output = (param_1 * 0x2:4);\n", myUserop.getBody());
}
@Test(expected = SleighException.class)
@ -90,7 +90,7 @@ public class StructuredSleighTest extends AbstractGhidraHeadlessIntegrationTest
}
};
SleighPcodeUseropDefinition<Object> myUserop = ss.generate().get("my_userop");
assertEquals(List.of("__op_output = (r0 * 0x2:4);\n"), myUserop.getLines());
assertEquals("__op_output = (r0 * 0x2:4);\n", myUserop.getBody());
}
@Test
@ -103,10 +103,10 @@ public class StructuredSleighTest extends AbstractGhidraHeadlessIntegrationTest
}
};
SleighPcodeUseropDefinition<Object> myUserop = ss.generate().get("my_userop");
assertEquals(List.of("" +
"local my_var:4;\n" +
"__op_output = (my_var * 0x2:4);\n"),
myUserop.getLines());
assertEquals("""
local my_var:4;
__op_output = (my_var * 0x2:4);
""", myUserop.getBody());
// Verify the source compiles
myUserop.programFor(new Varnode(r0.getAddress(), r0.getNumBytes()), List.of(),
PcodeUseropLibrary.NIL);
@ -121,7 +121,7 @@ public class StructuredSleighTest extends AbstractGhidraHeadlessIntegrationTest
}
};
SleighPcodeUseropDefinition<Object> myUserop = ss.generate().get("my_userop");
assertEquals(List.of(""), myUserop.getLines());
assertEquals("", myUserop.getBody());
}
@Test
@ -137,14 +137,14 @@ public class StructuredSleighTest extends AbstractGhidraHeadlessIntegrationTest
}
};
SleighPcodeUseropDefinition<Object> myUserop = ss.generate().get("my_userop");
assertEquals(List.of("" +
"if 0x1:1 goto <L1>;\n" +
"tmp = 0x2:4;\n" +
"goto <L2>;\n" +
"<L1>\n" +
"tmp = 0x1:4;\n" +
"<L2>\n"),
myUserop.getLines());
assertEquals("""
if 0x1:1 goto <L1>;
tmp = 0x2:4;
goto <L2>;
<L1>
tmp = 0x1:4;
<L2>
""", myUserop.getBody());
}
@Test
@ -158,11 +158,11 @@ public class StructuredSleighTest extends AbstractGhidraHeadlessIntegrationTest
}
};
SleighPcodeUseropDefinition<Object> myUserop = ss.generate().get("my_userop");
assertEquals(List.of("" +
"if (!0x1:1) goto <L1>;\n" +
"tmp = 0x1:4;\n" +
"<L1>\n"),
myUserop.getLines());
assertEquals("""
if (!0x1:1) goto <L1>;
tmp = 0x1:4;
<L1>
""", myUserop.getBody());
}
@Test
@ -179,17 +179,18 @@ public class StructuredSleighTest extends AbstractGhidraHeadlessIntegrationTest
}
};
SleighPcodeUseropDefinition<Object> myUserop = ss.generate().get("my_userop");
assertEquals(List.of("" + "local i:4;\n" +
"local sum:4;\n" +
"i = 0x0:4;\n" +
"<L2>\n" +
"if (i >= n) goto <L1>;\n" +
"sum = (sum + i);\n" +
"i = (i + 0x1:4);\n" +
"goto <L2>;\n" +
"<L1>\n" +
"__op_output = sum;\n"),
myUserop.getLines());
assertEquals("""
local i:4;
local sum:4;
i = 0x0:4;
<L2>
if (i >= n) goto <L1>;
sum = (sum + i);
i = (i + 0x1:4);
goto <L2>;
<L1>
__op_output = sum;
""", myUserop.getBody());
}
@Test
@ -209,19 +210,19 @@ public class StructuredSleighTest extends AbstractGhidraHeadlessIntegrationTest
}
};
SleighPcodeUseropDefinition<Object> myUserop = ss.generate().get("my_userop");
assertEquals(List.of("" +
"local i:4;\n" +
"local sum:4;\n" +
"i = 0x0:4;\n" +
"<L2>\n" +
"if (i >= n) goto <L1>;\n" +
"sum = (sum + i);\n" +
"if (sum >= 0x3e8:4) goto <L1>;\n" +
"i = (i + 0x1:4);\n" +
"goto <L2>;\n" +
"<L1>\n" +
"__op_output = sum;\n"),
myUserop.getLines());
assertEquals("""
local i:4;
local sum:4;
i = 0x0:4;
<L2>
if (i >= n) goto <L1>;
sum = (sum + i);
if (sum >= 0x3e8:4) goto <L1>;
i = (i + 0x1:4);
goto <L2>;
<L1>
__op_output = sum;
""", myUserop.getBody());
}
@Test
@ -233,7 +234,7 @@ public class StructuredSleighTest extends AbstractGhidraHeadlessIntegrationTest
}
};
SleighPcodeUseropDefinition<Object> myUserop = ss.generate().get("my_userop");
assertEquals(List.of("return (* 0xdeadbeef:8);\n"), myUserop.getLines());
assertEquals("return (* 0xdeadbeef:8);\n", myUserop.getBody());
// TODO: Test that the generated code compiles in a slaspec file.
// It's rejected for injects because "return" is not valid there.
}

View file

@ -18,7 +18,6 @@ package ghidra.pcode.emu.taint.full;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.List;
import java.util.Set;
import org.junit.Before;
@ -105,8 +104,7 @@ public class TaintDebuggerPcodeEmulatorTest extends AbstractGhidraHeadedDebugger
new DefaultTraceLocation(tb.trace, null, Range.atLeast(0L), tb.addr(0x55550000)),
new ProgramLocation(program, tb.addr(0x00400000)), 0x1000, false);
thread = tb.getOrAddThread("Threads[0]", 0);
tb.exec(0, 0, thread, List.of(
"RIP = 0x55550000;"));
tb.exec(0, 0, thread, "RIP = 0x55550000;");
}
waitForDomainObject(tb.trace);
waitForPass(() -> assertEquals(new ProgramLocation(program, tb.addr(0x00400000)),

View file

@ -194,7 +194,7 @@ public class TaintPcodeEmulatorTest extends AbstractGhidraHeadlessIntegrationTes
public void testTaintViaSleigh() throws Exception {
prepareEmulator();
PcodeThread<?> thread = launchThread(start);
thread.getExecutor().executeSleighLine("*:8 0x00400000:8 = taint_arr(*:8 0x004000000:8)");
thread.getExecutor().executeSleigh("*:8 0x00400000:8 = taint_arr(*:8 0x004000000:8);");
Pair<byte[], TaintVec> taintVal =
emulator.getSharedState().getVar(space, 0x00400000, 8, true);

View file

@ -63,7 +63,7 @@ public class TaintTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
@Test
public void testReadStateMemory() throws Throwable {
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
TraceThread thread = initTrace(tb, List.of(), List.of());
TraceThread thread = initTrace(tb, "", List.of());
try (UndoableTransaction tid = tb.startTransaction()) {
TracePropertyMap<String> taintMap = tb.trace.getAddressPropertyManager()
@ -73,7 +73,7 @@ public class TaintTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
TaintTracePcodeEmulator emu = new TaintTracePcodeEmulator(tb.trace, 0);
PcodeThread<Pair<byte[], TaintVec>> emuThread = emu.newThread(thread.getPath());
emuThread.getExecutor().executeSleighLine("RAX = *0x00400000:8");
emuThread.getExecutor().executeSleigh("RAX = *0x00400000:8;");
Pair<byte[], TaintVec> valRAX =
emuThread.getState().getVar(tb.language.getRegister("RAX"));
@ -89,7 +89,7 @@ public class TaintTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
@Test
public void testReadStateRegister() throws Throwable {
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
TraceThread thread = initTrace(tb, List.of(), List.of());
TraceThread thread = initTrace(tb, "", List.of());
Register regRAX = tb.language.getRegister("RAX");
Register regEBX = tb.language.getRegister("EBX");
@ -103,7 +103,7 @@ public class TaintTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
TaintTracePcodeEmulator emu = new TaintTracePcodeEmulator(tb.trace, 0);
PcodeThread<Pair<byte[], TaintVec>> emuThread = emu.newThread(thread.getPath());
emuThread.getExecutor().executeSleighLine("RAX = RBX");
emuThread.getExecutor().executeSleigh("RAX = RBX;");
Pair<byte[], TaintVec> valRAX =
emuThread.getState().getVar(regRAX);
@ -119,7 +119,7 @@ public class TaintTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
@Test
public void testWriteStateMemory() throws Throwable {
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
initTrace(tb, List.of(), List.of());
initTrace(tb, "", List.of());
TaintTracePcodeEmulator emu = new TaintTracePcodeEmulator(tb.trace, 0);
TaintVec taintVal = TaintVec.empties(8);
@ -146,7 +146,7 @@ public class TaintTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
public void testWriteStateRegister() throws Throwable {
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
AddressSpace rs = tb.language.getAddressFactory().getRegisterSpace();
TraceThread thread = initTrace(tb, List.of(), List.of());
TraceThread thread = initTrace(tb, "", List.of());
TaintTracePcodeEmulator emu = new TaintTracePcodeEmulator(tb.trace, 0);
PcodeThread<Pair<byte[], TaintVec>> emuThread = emu.newThread(thread.getPath());
@ -176,9 +176,9 @@ public class TaintTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
public void testEmptyTaintClears() throws Throwable {
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
AddressSpace ram = tb.language.getAddressFactory().getDefaultAddressSpace();
TraceThread thread = initTrace(tb,
List.of(
"RIP = 0x00400000;"),
TraceThread thread = initTrace(tb, """
RIP = 0x00400000;
""",
List.of(
"MOV qword ptr [0x00600000], RAX",
"MOV qword ptr [0x00600000], RBX"));
@ -214,9 +214,9 @@ public class TaintTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
@Test
public void testZeroByXor() throws Throwable {
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
TraceThread thread = initTrace(tb,
List.of(
"RIP = 0x00400000;"),
TraceThread thread = initTrace(tb, """
RIP = 0x00400000;
""",
List.of(
"XOR RAX, RAX"));
@ -245,9 +245,9 @@ public class TaintTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
@Test
public void testZeroByXorVia32() throws Throwable {
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
TraceThread thread = initTrace(tb,
List.of(
"RIP = 0x00400000;"),
TraceThread thread = initTrace(tb, """
RIP = 0x00400000;
""",
List.of(
"XOR EAX, EAX"));