From 3aa9d21f10a44cdffbdb09099cb839be1e7253d5 Mon Sep 17 00:00:00 2001 From: Dan <46821332+nsadeveloper789@users.noreply.github.com> Date: Thu, 20 Oct 2022 13:26:17 -0400 Subject: [PATCH] GP-0: Fix tests --- .../agent/gdb/model/impl/GdbModelImpl.java | 11 ++++ .../gdb/model/impl/GdbModelTargetSession.java | 3 + .../DebuggerEmulationServicePlugin.java | 1 + .../AbstractGhidraHeadedDebuggerGUITest.java | 4 +- .../DebuggerPcodeStepperProviderTest.java | 65 +++++++++---------- 5 files changed, 48 insertions(+), 36 deletions(-) diff --git a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelImpl.java b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelImpl.java index 3751817822..be288a2bdf 100644 --- a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelImpl.java +++ b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelImpl.java @@ -61,6 +61,7 @@ public class GdbModelImpl extends AbstractDebuggerObjectModel { protected final GdbManager gdb; protected final GdbModelTargetSession session; + private volatile boolean closed; protected final CompletableFuture completedSession; protected final GdbStateListener gdbExitListener = this::checkExited; @@ -141,13 +142,22 @@ public class GdbModelImpl extends AbstractDebuggerObjectModel { public CompletableFuture startGDB(String gdbCmd, String[] args) { return CompletableFuture.runAsync(() -> { try { + if (closed) { + return; + } gdb.start(gdbCmd, args); } catch (IOException e) { + if (closed) { + return; + } throw new DebuggerModelTerminatingException( "Error while starting GDB: " + e.getMessage(), e); } }).thenCompose(__ -> { + if (closed) { + return AsyncUtils.NIL; + } return gdb.runRC(); }); } @@ -174,6 +184,7 @@ public class GdbModelImpl extends AbstractDebuggerObjectModel { @Override public CompletableFuture close() { + closed = true; try { terminate(); return super.close(); diff --git a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelTargetSession.java b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelTargetSession.java index 808c17d291..d3206c6cba 100644 --- a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelTargetSession.java +++ b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelTargetSession.java @@ -133,6 +133,9 @@ public class GdbModelTargetSession extends DefaultTargetModelRoot @Override public void output(GdbManager.Channel gdbChannel, String out) { + if (!valid) { + return; + } TargetConsole.Channel dbgChannel; switch (gdbChannel) { case STDOUT: diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/DebuggerEmulationServicePlugin.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/DebuggerEmulationServicePlugin.java index 83e587d59c..a6ee33ed06 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/DebuggerEmulationServicePlugin.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/DebuggerEmulationServicePlugin.java @@ -469,6 +469,7 @@ public class DebuggerEmulationServicePlugin extends Plugin implements DebuggerEm if (chosen == null) { // Must be special or otherwise not discovered. Could happen. Msg.warn(this, "An undiscovered emulator factory was set via the API: " + factory); + return; } chosen.setSelected(true); } diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/AbstractGhidraHeadedDebuggerGUITest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/AbstractGhidraHeadedDebuggerGUITest.java index b2f636c4fc..41b0d16c59 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/AbstractGhidraHeadedDebuggerGUITest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/AbstractGhidraHeadedDebuggerGUITest.java @@ -279,7 +279,7 @@ public abstract class AbstractGhidraHeadedDebuggerGUITest } protected static Set getMenuElementsText() { - MenuElement[] sel = MenuSelectionManager.defaultManager().getSelectedPath(); + MenuElement[] sel = runSwing(() -> MenuSelectionManager.defaultManager().getSelectedPath()); if (sel == null || sel.length == 0) { return Set.of(); } @@ -300,7 +300,7 @@ public abstract class AbstractGhidraHeadedDebuggerGUITest } protected static MenuElement getSubMenuElementByText(String text) { - MenuElement[] sel = MenuSelectionManager.defaultManager().getSelectedPath(); + MenuElement[] sel = runSwing(() -> MenuSelectionManager.defaultManager().getSelectedPath()); if (sel == null || sel.length == 0) { throw new NoSuchElementException("No menu is active"); } diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/pcode/DebuggerPcodeStepperProviderTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/pcode/DebuggerPcodeStepperProviderTest.java index 7616ea6bef..dbebcd99a9 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/pcode/DebuggerPcodeStepperProviderTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/pcode/DebuggerPcodeStepperProviderTest.java @@ -17,6 +17,7 @@ package ghidra.app.plugin.core.debug.gui.pcode; import static org.junit.Assert.*; +import java.lang.invoke.MethodHandles; import java.util.List; import org.junit.Before; @@ -28,12 +29,12 @@ import ghidra.app.plugin.assembler.Assemblers; import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest; import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingPlugin; import ghidra.app.plugin.core.debug.gui.pcode.DebuggerPcodeStepperProvider.PcodeRowHtmlFormatter; -import ghidra.app.plugin.core.debug.service.emulation.DebuggerPcodeMachine; +import ghidra.app.plugin.core.debug.service.emulation.*; +import ghidra.app.plugin.core.debug.service.emulation.data.PcodeDebuggerAccess; import ghidra.app.plugin.core.debug.service.tracemgr.DebuggerTraceManagerServicePlugin; import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.app.services.DebuggerEmulationService; import ghidra.app.services.DebuggerTraceManagerService; -import ghidra.pcode.emu.PcodeThread; import ghidra.pcode.exec.*; import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason; import ghidra.pcode.exec.trace.TraceSleighUtils; @@ -57,8 +58,7 @@ public class DebuggerPcodeStepperProviderTest extends AbstractGhidraHeadedDebugg private Address start; private TraceThread thread; - private Instruction imm1234; - private Instruction imm2045; + private Instruction imm123; @Before public void setUpPcodeStepperProviderTest() throws Exception { @@ -87,12 +87,10 @@ public class DebuggerPcodeStepperProviderTest extends AbstractGhidraHeadedDebugg Assembler asm = Assemblers.getAssembler(tb.trace.getFixedProgramView(0)); iit = asm.assemble(start, - "imm r0, #0x3d2", - "imm r1, #911"); // 10 bits unsigned + "imm r0, #0x123"); } - imm1234 = iit.next(); - imm2045 = iit.next(); + imm123 = iit.next(); } protected void assertEmpty() { @@ -137,40 +135,39 @@ public class DebuggerPcodeStepperProviderTest extends AbstractGhidraHeadedDebugg public void testCustomUseropDisplay() throws Exception { populateTrace(); + emuService.setEmulatorFactory(new BytesDebuggerPcodeEmulatorFactory() { + @Override + public DebuggerPcodeMachine create(PcodeDebuggerAccess access) { + BytesDebuggerPcodeEmulator emu = new BytesDebuggerPcodeEmulator(access) { + @Override + protected PcodeUseropLibrary createUseropLibrary() { + return new AnnotatedPcodeUseropLibrary() { + @Override + protected MethodHandles.Lookup getMethodLookup() { + return MethodHandles.lookup(); + } + + @PcodeUserop + public void stepper_test_userop() { + } + }; + } + }; + emu.inject(imm123.getAddress(), "stepper_test_userop();"); + return emu; + } + }); + + // Just one p-code step to load injection (decode step) TraceSchedule schedule1 = TraceSchedule.parse("0:.t0-1"); traceManager.openTrace(tb.trace); traceManager.activateThread(thread); traceManager.activateTime(schedule1); waitForPass(() -> assertEquals(schedule1, pcodeProvider.current.getTime())); - // P-code step to decode already done. One for each op. One to retire. - TraceSchedule schedule2 = - schedule1.steppedPcodeForward(thread, imm1234.getPcode().length + 1); - traceManager.activateTime(schedule2); - waitForPass(() -> assertEquals(schedule2, pcodeProvider.current.getTime())); - - DebuggerPcodeMachine emu = - waitForValue(() -> emuService.getCachedEmulator(tb.trace, schedule2)); - assertNotNull(emu); - PcodeThread et = emu.getThread(thread.getPath(), false); - waitForPass(() -> assertNull(et.getFrame())); - - /** - * NB. at the moment, there is no API to customize the service's emulator. In the meantime, - * the vanilla PcodeThread does inject a custom library for breakpoints, so we'll use that - * as our "custom userop" test case. It might also be nice if the emulator service placed - * breakpoints, no? - */ - emu.addBreakpoint(imm2045.getAddress(), "1:1"); - - // Just one p-code step to decode - TraceSchedule schedule3 = schedule2.steppedPcodeForward(thread, 1); - traceManager.activateTime(schedule3); - waitForPass(() -> assertEquals(schedule3, pcodeProvider.current.getTime())); - waitForPass(() -> assertTrue(pcodeProvider.pcodeTableModel.getModelData() .stream() - .anyMatch(r -> r.getCode().contains("emu_swi")))); + .anyMatch(r -> r.getCode().contains("stepper_test_userop")))); } protected List format(String sleigh) {