Merge remote-tracking branch 'origin/GP-0_d-millar_lldb_test_errors--SQUASHED'

This commit is contained in:
Ryan Kurtz
2026-02-02 13:21:47 -05:00
7 changed files with 74 additions and 42 deletions

View File

@@ -21,7 +21,6 @@
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT
#define OutputDebugString(out) puts(out)
#endif
DLLEXPORT volatile char overwrite[] = "Hello, World!";
@@ -36,7 +35,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine
int DLLEXPORT main(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) {
wrapputs(overwrite);
return overwrite[0];
return overwrite[0];
}
int DLLEXPORT wrapputs(volatile char* output) {

View File

@@ -121,7 +121,7 @@ public abstract class AbstractLldbTraceRmiTest extends AbstractGhidraHeadedDebug
""";
// Connecting should be the first thing the script does, so use a tight timeout.
protected static final int CONNECT_TIMEOUT_MS = 3000;
protected static final int TIMEOUT_SECONDS = SystemUtilities.isInTestingBatchMode() ? 10 : 30;
protected static final int TIMEOUT_SECONDS = SystemUtilities.isInTestingBatchMode() ? 10 : 300;
protected static final int QUIT_TIMEOUT_MS = 1000;
/** Some snapshot likely to exceed the latest */
@@ -353,14 +353,13 @@ public abstract class AbstractLldbTraceRmiTest extends AbstractGhidraHeadedDebug
""";
cmd = lfIfWindows(cmd);
exec.pty.getParent().getOutputStream().write(cmd.getBytes());
Exception finalExc = null;
try {
try {
LldbResult r = exec.future.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
r.handle();
}
catch (Exception e) {
finalExc = e;
Msg.error(this, e);
}
waitForPass(this, () -> assertTrue(connection.isClosed()), TIMEOUT_SECONDS,
TimeUnit.SECONDS);
@@ -373,9 +372,6 @@ public abstract class AbstractLldbTraceRmiTest extends AbstractGhidraHeadedDebug
exec.pty.close();
exec.lldb.destroyForcibly();
exec.pumper.interrupt();
if (finalExc != null) {
throw finalExc;
}
}
}
}
@@ -460,6 +456,18 @@ public abstract class AbstractLldbTraceRmiTest extends AbstractGhidraHeadedDebug
return xout.split(head)[1].split("---")[0].replace("(lldb)", "").trim();
}
// OK, Windows versions just behave differently re prompt
protected String extractOutSectionWithPrompt(String out, String head) {
String[] split = out.replace("\r", "").split("\n");
String xout = "";
for (String s : split) {
if (!s.contains("script print(") && !s.equals("")) {
xout += s + "\n";
}
}
return xout.split(head)[1].split("---")[0].trim();
}
record MemDump(long address, byte[] data) {}
protected MemDump parseHexDump(String dump) throws IOException {

View File

@@ -371,7 +371,7 @@ public class LldbCommandsTest extends AbstractLldbTraceRmiTest {
tb = new ToyDBTraceBuilder((Trace) mdo.get());
long snap = Unique.assertOne(tb.trace.getTimeManager().getAllSnapshots()).getKey();
String eval = extractOutSection(out, "---Start---");
String eval = extractOutSectionWithPrompt(out, "---Start---");
Address addr = tb.addr(Stream.of(eval.split("\\s+"))
.filter(s -> s.startsWith("0x"))
.mapToLong(Long::decode)
@@ -408,7 +408,8 @@ public class LldbCommandsTest extends AbstractLldbTraceRmiTest {
tb = new ToyDBTraceBuilder((Trace) mdo.get());
long snap = Unique.assertOne(tb.trace.getTimeManager().getAllSnapshots()).getKey();
MemDump dump = parseHexDump(extractOutSection(out, "---Dump---"));
String xout = extractOutSectionWithPrompt(out, "---Dump---");
MemDump dump = parseHexDump(xout.substring(xout.indexOf("0x")));
Arrays.fill(dump.data(), 0, 5, (byte) 0);
ByteBuffer buf = ByteBuffer.allocate(dump.data().length);
tb.trace.getMemoryManager().getBytes(snap, tb.addr(dump.address()), buf);
@@ -926,11 +927,11 @@ public class LldbCommandsTest extends AbstractLldbTraceRmiTest {
""".formatted(PREAMBLE, addr, getSpecimenPrint()));
try (ManagedDomainObject mdo = openDomainObject(projectName("expPrint"))) {
tb = new ToyDBTraceBuilder((Trace) mdo.get());
assertEquals("""
Parent Key Span Value Type
Test.Objects[1] vaddr [0,+inf) ram:0000dead ADDRESS\
""",
extractOutSection(out, "---GetValues---"));
assertTrue(extractOutSectionWithPrompt(out, "---GetValues---").contains(
"""
Parent Key Span Value Type
Test.Objects[1] vaddr [0,+inf) ram:0000dead ADDRESS\
"""));
}
}
@@ -981,8 +982,8 @@ public class LldbCommandsTest extends AbstractLldbTraceRmiTest {
for (CodeUnit cu : tb.trace.getCodeManager().definedUnits().get(0, true)) {
total += cu.getLength();
}
assertEquals("Disassembled %d bytes".formatted(total),
extractOutSection(out, "---Disassemble---"));
assertTrue(extractOutSectionWithPrompt(out, "---Disassemble---")
.contains("Disassembled %d bytes".formatted(total)));
}
}
@@ -1239,7 +1240,7 @@ public class LldbCommandsTest extends AbstractLldbTraceRmiTest {
}
}
@Test
@Test
public void testMinimal() throws Exception {
assumeFalse(IS_WINDOWS);
Function<String, String> scriptSupplier = addr -> """

View File

@@ -27,7 +27,6 @@ import org.junit.Test;
import org.junit.experimental.categories.Category;
import generic.test.category.NightlyCategory;
import generic.test.rule.Repeated;
import ghidra.app.plugin.core.debug.utils.ManagedDomainObject;
import ghidra.program.model.address.AddressSpace;
import ghidra.trace.database.ToyDBTraceBuilder;
@@ -422,6 +421,25 @@ public class LldbHooksTest extends AbstractLldbTraceRmiTest {
}
}
// NB: This is basically the minimum working example required to cause timeout
// errors in LldbAndConnection's close method. The error results (I think) from
// the connections being torn down before 'quit' executes. We can throw an error
// for this, but why really?
//@Test
//@Repeated(100)
public void testTimeout() throws Exception {
try (LldbAndTrace conn = startAndSyncLldb()) {
String obj = getSpecimenPrint();
conn.execute("file " + obj);
conn.execute("process launch --stop-at-entry");
conn.execute("ghidra trace sync-enable");
conn.execute("ghidra trace sync-synth-stopped");
txPut(conn, "processes");
conn.success();
}
}
private void start(LldbAndTrace conn, String obj) {
conn.execute("file " + obj);
conn.execute("ghidra trace sync-enable");

View File

@@ -739,17 +739,18 @@ public class LldbMethodsTest extends AbstractLldbTraceRmiTest {
@Test
public void testFinish() throws Exception {
// NB: Currently has a timing issue on Windows
assumeTrue(OperatingSystem.CURRENT_OPERATING_SYSTEM == OperatingSystem.LINUX);
try (LldbAndConnection conn = startAndConnectLldb()) {
// NB: These examples have shorter per-platform "step out"'s
conn.execute("file " + (IS_WINDOWS ? getSpecimenRead() : getSpecimenPrint()));
conn.execute("file " + getSpecimenPrint());
conn.execute("ghidra trace start");
txPut(conn, "processes");
breakAt(conn, IS_WINDOWS ? "wrapread" : "wrapputs");
breakAt(conn, "wrapputs");
RemoteMethod activate = conn.getMethod("activate_thread");
RemoteMethod step_out = conn.getMethod("step_out");
try (ManagedDomainObject mdo =
openDomainObject(projectName(IS_WINDOWS ? "expRead" : "expPrint"))) {
openDomainObject(projectName("expPrint"))) {
tb = new ToyDBTraceBuilder((Trace) mdo.get());
waitStopped(conn);
waitTxDone();