mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-28 08:38:18 +08:00
GP-0: Fix tests
This commit is contained in:
@@ -61,6 +61,7 @@ public class GdbModelImpl extends AbstractDebuggerObjectModel {
|
||||
|
||||
protected final GdbManager gdb;
|
||||
protected final GdbModelTargetSession session;
|
||||
private volatile boolean closed;
|
||||
|
||||
protected final CompletableFuture<GdbModelTargetSession> completedSession;
|
||||
protected final GdbStateListener gdbExitListener = this::checkExited;
|
||||
@@ -141,13 +142,22 @@ public class GdbModelImpl extends AbstractDebuggerObjectModel {
|
||||
public CompletableFuture<Void> 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<Void> close() {
|
||||
closed = true;
|
||||
try {
|
||||
terminate();
|
||||
return super.close();
|
||||
|
||||
+3
@@ -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:
|
||||
|
||||
+1
@@ -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);
|
||||
}
|
||||
|
||||
+2
-2
@@ -279,7 +279,7 @@ public abstract class AbstractGhidraHeadedDebuggerGUITest
|
||||
}
|
||||
|
||||
protected static Set<String> 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");
|
||||
}
|
||||
|
||||
+31
-34
@@ -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<byte[]> createUseropLibrary() {
|
||||
return new AnnotatedPcodeUseropLibrary<byte[]>() {
|
||||
@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<PcodeRow> format(String sleigh) {
|
||||
|
||||
Reference in New Issue
Block a user