diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/lldb/rmi/AbstractLldbTraceRmiTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/lldb/rmi/AbstractLldbTraceRmiTest.java index 0406f53b9f..3f6f0ba3ad 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/lldb/rmi/AbstractLldbTraceRmiTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/lldb/rmi/AbstractLldbTraceRmiTest.java @@ -194,7 +194,7 @@ public abstract class AbstractLldbTraceRmiTest extends AbstractGhidraHeadedDebug } protected record ExecInLldb(Pty pty, PtySession lldb, CompletableFuture future, - Thread pumper) {} + Thread pumper, ByteArrayOutputStream capture) {} @SuppressWarnings("resource") // Do not close stdin protected ExecInLldb execInLldb(String script) throws IOException { @@ -239,7 +239,7 @@ public abstract class AbstractLldbTraceRmiTest extends AbstractGhidraHeadedDebug lldbSession.destroyForcibly(); pumper.interrupt(); } - }), pumper); + }), pumper, capture); } public static class LldbError extends RuntimeException { @@ -262,8 +262,20 @@ public abstract class AbstractLldbTraceRmiTest extends AbstractGhidraHeadedDebug return result.get(TIMEOUT_SECONDS, TimeUnit.SECONDS).handle(); } - protected record LldbAndConnection(ExecInLldb exec, TraceRmiConnection connection) - implements AutoCloseable { + protected class LldbAndConnection implements AutoCloseable { + private final ExecInLldb exec; + private final TraceRmiConnection connection; + private boolean success = false; + + public LldbAndConnection(ExecInLldb exec, TraceRmiConnection connection) { + this.exec = exec; + this.connection = connection; + } + + public TraceRmiConnection connection() { + return connection; + } + protected RemoteMethod getMethod(String name) { return Objects.requireNonNull(connection.getMethods().get(name)); } @@ -293,6 +305,10 @@ public abstract class AbstractLldbTraceRmiTest extends AbstractGhidraHeadedDebug return pyeval.invoke(Map.of("expr", expr)); } + public void success() { + success = true; + } + @Override public void close() throws Exception { Msg.info(this, "Cleaning up lldb"); @@ -306,6 +322,10 @@ public abstract class AbstractLldbTraceRmiTest extends AbstractGhidraHeadedDebug waitForPass(() -> assertTrue(connection.isClosed())); } finally { + if (!success) { + Msg.info(this, "LLDB output:\n" + exec.capture.toString()); + } + exec.pty.close(); exec.lldb.destroyForcibly(); exec.pumper.interrupt(); diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/lldb/rmi/LldbCommandsTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/lldb/rmi/LldbCommandsTest.java index 03fab6613a..bf98e13af3 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/lldb/rmi/LldbCommandsTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/lldb/rmi/LldbCommandsTest.java @@ -1238,6 +1238,7 @@ public class LldbCommandsTest extends AbstractLldbTraceRmiTest { """.formatted(PREAMBLE, addr); try (LldbAndConnection conn = startAndConnectLldb(scriptSupplier)) { conn.execute("script print('FINISHED')"); + conn.success(); } } } diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/lldb/rmi/LldbHooksTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/lldb/rmi/LldbHooksTest.java index d97175621e..dedc31cf13 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/lldb/rmi/LldbHooksTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/lldb/rmi/LldbHooksTest.java @@ -15,14 +15,15 @@ */ package agent.lldb.rmi; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.instanceOf; import static org.junit.Assert.*; import java.nio.ByteBuffer; import java.util.List; import java.util.Objects; -import org.junit.Ignore; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -52,6 +53,10 @@ public class LldbHooksTest extends AbstractLldbTraceRmiTest { return conn.executeCapture(cmd); } + public void success() { + conn.success(); + } + @Override public void close() throws Exception { conn.close(); @@ -103,6 +108,7 @@ public class LldbHooksTest extends AbstractLldbTraceRmiTest { waitForPass(() -> assertEquals(2, tb.objValues(lastSnap(conn), "Processes[].Threads[]").size()), RUN_TIMEOUT_MS, RETRY_MS); + conn.success(); } } @@ -165,6 +171,7 @@ public class LldbHooksTest extends AbstractLldbTraceRmiTest { String threadIndex = threadIndex(traceManager.getCurrentObject()); assertTrue(ti0.contains(threadIndex)); }, RUN_TIMEOUT_MS, RETRY_MS); + conn.success(); } } @@ -222,13 +229,12 @@ public class LldbHooksTest extends AbstractLldbTraceRmiTest { RUN_TIMEOUT_MS, RETRY_MS); conn.execute("kill"); + conn.success(); } } - @Test - @Ignore + //@Test // Need a specimen public void testOnSyscallMemory() throws Exception { - // TODO: Need a specimen // FWIW, I've already seen this getting exercised in other tests. } @@ -248,6 +254,7 @@ public class LldbHooksTest extends AbstractLldbTraceRmiTest { tb.trace.getMemoryManager().getBytes(lastSnap(conn), tb.addr(address), buf); assertEquals(0x7f, buf.get(0)); }, RUN_TIMEOUT_MS, RETRY_MS); + conn.success(); } } @@ -270,6 +277,7 @@ public class LldbHooksTest extends AbstractLldbTraceRmiTest { regs.getValue(lastSnap(conn), tb.reg(PLAT.intReg())) .getUnsignedValue() .toString(16))); + conn.success(); } } @@ -287,6 +295,7 @@ public class LldbHooksTest extends AbstractLldbTraceRmiTest { }, RUN_TIMEOUT_MS, RETRY_MS); conn.execute("process interrupt"); + conn.success(); } } @@ -299,6 +308,7 @@ public class LldbHooksTest extends AbstractLldbTraceRmiTest { waitForPass(() -> { assertEquals("STOPPED", tb.objValue(inf, lastSnap(conn), "_state")); }, RUN_TIMEOUT_MS, RETRY_MS); + conn.success(); } } @@ -321,6 +331,7 @@ public class LldbHooksTest extends AbstractLldbTraceRmiTest { assertThat(val, instanceOf(Number.class)); assertEquals(72, ((Number) val).longValue()); }, RUN_TIMEOUT_MS, RETRY_MS); + conn.success(); } } @@ -338,6 +349,7 @@ public class LldbHooksTest extends AbstractLldbTraceRmiTest { assertEquals(1, brks.size()); return (TraceObject) brks.get(0); }); + conn.success(); } } @@ -367,6 +379,7 @@ public class LldbHooksTest extends AbstractLldbTraceRmiTest { waitForPass( () -> assertEquals("x>3", tb.objValue(brk, lastSnap(conn), "Condition"))); + conn.success(); } } @@ -392,6 +405,7 @@ public class LldbHooksTest extends AbstractLldbTraceRmiTest { waitForPass( () -> assertEquals(0, tb.objValues(lastSnap(conn), "Processes[].Breakpoints[]").size())); + conn.success(); } } @@ -407,5 +421,4 @@ public class LldbHooksTest extends AbstractLldbTraceRmiTest { conn.execute("ghidra trace put-" + obj); conn.execute("ghidra trace tx-commit"); } - } diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/lldb/rmi/LldbMethodsTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/lldb/rmi/LldbMethodsTest.java index ca5ac450ec..817b31b60b 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/lldb/rmi/LldbMethodsTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/lldb/rmi/LldbMethodsTest.java @@ -15,6 +15,7 @@ */ package agent.lldb.rmi; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import static org.junit.Assume.assumeTrue; @@ -55,6 +56,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { assertEquals(false, execute.parameters().get("to_string").getDefaultValue()); assertEquals("test\n", execute.invoke(Map.of("cmd", "script print('test')", "to_string", true))); + conn.success(); } } @@ -63,6 +65,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { try (LldbAndConnection conn = startAndConnectLldb()) { start(conn, getSpecimenPrint()); conn.execute("kill"); + conn.success(); } try (ManagedDomainObject mdo = openDomainObject("/New Traces/lldb/expPrint")) { // Just confirm it's present @@ -89,6 +92,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { .toList(); assertThat(list.size(), greaterThan(2)); } + conn.success(); } } @@ -128,6 +132,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { Set.of(TraceBreakpointKind.HW_EXECUTE), "main"); } + conn.success(); } } @@ -177,6 +182,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { Set.of(TraceBreakpointKind.READ, TraceBreakpointKind.WRITE), "main+0x30"); } + conn.success(); } } @@ -201,6 +207,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { .toList(); assertEquals(1, list.size()); } + conn.success(); } } @@ -223,6 +230,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { assertLocalOs(env.getValue(0, "_os").castValue()); assertEquals(PLAT.endian(), env.getValue(0, "_endian").getValue()); } + conn.success(); } } @@ -243,6 +251,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { // Would be nice to control / validate the specifics Unique.assertOne(tb.trace.getThreadManager().getAllThreads()); } + conn.success(); } } @@ -273,6 +282,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { .toList(); assertTrue(list.size() > 1); } + conn.success(); } } @@ -302,6 +312,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { // LLDB treats registers in arch's endian assertEquals("deadbeef", intRegVal.getUnsignedValue().toString(16)); } + conn.success(); } } @@ -324,6 +335,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { tb.trace.getMemoryManager().getAllRegions(); assertThat(all.size(), greaterThan(2)); } + conn.success(); } } @@ -347,6 +359,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { all.stream().filter(m -> m.getName(SNAP).contains("expPrint"))); assertNotEquals(tb.addr(0), Objects.requireNonNull(modExpPrint.getBase(SNAP))); } + conn.success(); } } @@ -388,6 +401,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { .or(containsString("tid = 0x%x".formatted(index)))); } } + conn.success(); } } @@ -421,6 +435,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { assertThat(out, containsString("#%s".formatted(level))); } } + conn.success(); } } @@ -440,6 +455,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { String out = conn.executeCapture("target list"); assertThat(out, containsString("No targets")); } + conn.success(); } } @@ -466,6 +482,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { String out = conn.executeCapture("target list"); assertThat(out, containsString("pid=%d".formatted(dproc.pid))); } + conn.success(); } } } @@ -490,6 +507,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { String out = conn.executeCapture("target list"); assertThat(out, containsString("pid=%d".formatted(dproc.pid))); } + conn.success(); } } } @@ -512,6 +530,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { //assertThat(out, containsString("pid=%d".formatted(dproc.pid))); assertThat(out, containsString("detached")); } + conn.success(); } } @@ -534,6 +553,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { String out = conn.executeCapture("target list"); assertThat(out, containsString(getSpecimenPrint())); } + conn.success(); } } @@ -565,6 +585,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { String out = conn.executeCapture("bt"); assertThat(out, containsString("read")); } + conn.success(); } } @@ -585,6 +606,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { String out = conn.executeCapture("target list"); assertThat(out, containsString("exited")); } + conn.success(); } } @@ -648,6 +670,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { FoundHex pc = FoundHex.findHex(List.of(disAt.split("\\s+")), 0); assertEquals(instr.target, pc.value); } + conn.success(); } } @@ -677,6 +700,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { FoundHex pc = FoundHex.findHex(List.of(disAt.split("\\s+")), 0); assertEquals(instr.next, pc.value); } + conn.success(); } } @@ -706,6 +730,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { FoundHex pc = FoundHex.findHex(List.of(disAt.split("\\s+")), 0); assertEquals(addr.value, pc); } + conn.success(); } } @@ -736,6 +761,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { int finalDepth = getDepth(conn); assertEquals(initDepth - 1, finalDepth); } + conn.success(); } } @@ -766,6 +792,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { int finalDepth = getDepth(conn); assertEquals(initDepth - 1, finalDepth); } + conn.success(); } } @@ -787,6 +814,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { assertThat(out, containsString("main")); assertThat(out, containsString(Long.toHexString(address))); } + conn.success(); } } @@ -806,6 +834,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { String out = conn.executeCapture("breakpoint list"); assertThat(out, containsString("main")); } + conn.success(); } } @@ -828,6 +857,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { String out = conn.executeCapture("breakpoint list"); assertThat(out, containsString(Long.toHexString(address))); } + conn.success(); } } @@ -849,6 +879,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { //NB: a little odd that this isn't in hex assertThat(out, containsString(Long.toString(address))); } + conn.success(); } } @@ -875,6 +906,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { assertThat(out, containsString("size = 1")); assertThat(out, containsString("type = r")); } + conn.success(); } } @@ -897,6 +929,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { assertThat(out, containsString(Long.toHexString(address))); assertThat(out, containsString("type = r")); } + conn.success(); } } @@ -925,6 +958,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { containsString("type = w"), containsString("type = m"))); } + conn.success(); } } @@ -949,6 +983,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { containsString("type = w"), containsString("type = m"))); } + conn.success(); } } @@ -975,6 +1010,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { assertThat(out, containsString("size = 1")); assertThat(out, containsString("type = rw")); } + conn.success(); } } @@ -997,6 +1033,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { assertThat(out, containsString(Long.toHexString(address))); assertThat(out, containsString("type = rw")); } + conn.success(); } } @@ -1017,6 +1054,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { assertThat(out, containsString("Exception")); assertThat(out, containsString("__cxa_throw")); } + conn.success(); } } @@ -1040,6 +1078,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { String out = conn.executeCapture("breakpoint list"); assertThat(out, containsString("disabled")); } + conn.success(); } } @@ -1064,6 +1103,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { String out = conn.executeCapture("breakpoint list"); assertThat(out, containsString("disabled")); } + conn.success(); } } @@ -1087,6 +1127,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { String out = conn.executeCapture("breakpoint list"); assertThat(out, containsString("No breakpoints")); } + conn.success(); } } @@ -1117,6 +1158,7 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest { out = conn.executeCapture("watchpoint list"); assertThat(out, containsString("No watchpoints")); } + conn.success(); } }