GP-2816: Add test demonstrating this is already fixed.

This commit is contained in:
Dan 2024-02-21 13:05:23 -05:00
parent ee70fe99e9
commit 1a2fea0782
2 changed files with 59 additions and 12 deletions

View file

@ -17,9 +17,9 @@ package ghidra.app.plugin.core.debug.disassemble;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import java.io.IOException;
import java.math.BigInteger; import java.math.BigInteger;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -44,8 +44,7 @@ import ghidra.dbg.target.schema.XmlSchemaContext;
import ghidra.debug.api.control.ControlMode; import ghidra.debug.api.control.ControlMode;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSet; import ghidra.program.model.address.AddressSet;
import ghidra.program.model.lang.LanguageID; import ghidra.program.model.lang.*;
import ghidra.program.model.lang.RegisterValue;
import ghidra.program.model.listing.Instruction; import ghidra.program.model.listing.Instruction;
import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramLocation;
import ghidra.program.util.ProgramSelection; import ghidra.program.util.ProgramSelection;
@ -115,10 +114,20 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
<schema name='Stack' canonical='yes' elementResync='NEVER' <schema name='Stack' canonical='yes' elementResync='NEVER'
attributeResync='NEVER'> attributeResync='NEVER'>
<interface name='Stack' /> <interface name='Stack' />
<interface name='Aggregate' />
<element schema='Frame' /> <element schema='Frame' />
</schema> </schema>
<schema name='Frame' elementResync='NEVER' attributeResync='NEVER'> <schema name='Frame' elementResync='NEVER' attributeResync='NEVER'>
<interface name='StackFrame' /> <interface name='StackFrame' />
<interface name='Aggregate' />
<attribute name='Registers' schema='RegisterContainer' />
</schema>
<schema name='RegisterContainer' elementResync='NEVER' attributeResync='NEVER'>
<interface name='RegisterContainer' />
<element schema='Register' />
</schema>
<schema name='Register' elementResync='NEVER' attributeResync='NEVER'>
<interface name='Register' />
</schema> </schema>
</context>"""); </context>""");
@ -148,7 +157,12 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
} }
protected TraceObjectThread createPolyglotTrace(String arch, long offset, protected TraceObjectThread createPolyglotTrace(String arch, long offset,
Supplier<ByteBuffer> byteSupplier) throws IOException { Supplier<ByteBuffer> byteSupplier) throws Exception {
return createPolyglotTrace(arch, offset, byteSupplier, true);
}
protected TraceObjectThread createPolyglotTrace(String arch, long offset,
Supplier<ByteBuffer> byteSupplier, boolean pcInStack) throws Exception {
createAndOpenTrace("DATA:BE:64:default"); createAndOpenTrace("DATA:BE:64:default");
DBTraceObjectManager objects = tb.trace.getObjectManager(); DBTraceObjectManager objects = tb.trace.getObjectManager();
@ -171,13 +185,31 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
// TODO: Why doesn't setRange work after insert? // TODO: Why doesn't setRange work after insert?
objBinText.insert(zeroOn, ConflictResolution.DENY); objBinText.insert(zeroOn, ConflictResolution.DENY);
DBTraceObject objFrame =
objects.createObject(TraceObjectKeyPath.parse("Targets[0].Threads[0].Stack[0]"));
objFrame.insert(zeroOn, ConflictResolution.DENY);
TraceObjectStackFrame frame = objFrame.queryInterface(TraceObjectStackFrame.class);
frame.setProgramCounter(zeroOn, tb.addr(offset));
DBTraceMemoryManager memory = tb.trace.getMemoryManager(); DBTraceMemoryManager memory = tb.trace.getMemoryManager();
if (pcInStack) {
DBTraceObject objFrame =
objects.createObject(
TraceObjectKeyPath.parse("Targets[0].Threads[0].Stack[0]"));
objFrame.insert(zeroOn, ConflictResolution.DENY);
TraceObjectStackFrame frame = objFrame.queryInterface(TraceObjectStackFrame.class);
frame.setProgramCounter(zeroOn, tb.addr(offset));
}
else {
objects.createObject(
TraceObjectKeyPath.parse("Targets[0].Threads[0].Stack[0].Registers"))
.insert(zeroOn, ConflictResolution.DENY);
TraceObjectThread thread = objects.getObjectByCanonicalPath(
TraceObjectKeyPath.parse("Targets[0].Threads[0]"))
.queryInterface(TraceObjectThread.class);
traceManager.activateThread(thread);
DBTraceMemorySpace regs =
Objects.requireNonNull(memory.getMemoryRegisterSpace(thread, true));
TraceGuestPlatform platform =
Unique.assertOne(tb.trace.getPlatformManager().getGuestPlatforms());
Register regPc = platform.getLanguage().getProgramCounter();
regs.setValue(platform, 0, new RegisterValue(regPc, BigInteger.valueOf(offset)));
}
ByteBuffer bytes = byteSupplier.get(); ByteBuffer bytes = byteSupplier.get();
assertEquals(bytes.remaining(), memory.putBytes(0, tb.addr(offset), bytes)); assertEquals(bytes.remaining(), memory.putBytes(0, tb.addr(offset), bytes));
} }
@ -260,6 +292,21 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
}); });
} }
@Test
public void testAutoDisassembleGuestX8664WithPcInRegs() throws Throwable {
enableAutoDisassembly();
getSLEIGH_X86_64_LANGUAGE(); // So that the platform is mapped promptly
createPolyglotTrace("x86-64", 0x00400000, () -> tb.buf(0x90, 0x90, 0x90), false);
waitForPass(() -> {
DBTraceInstructionsMemoryView instructions = tb.trace.getCodeManager().instructions();
assertMnemonic("NOP", instructions.getAt(0, tb.addr(0x00400000)));
assertMnemonic("NOP", instructions.getAt(0, tb.addr(0x00400001)));
assertMnemonic("NOP", instructions.getAt(0, tb.addr(0x00400002)));
assertNull(instructions.getAt(0, tb.addr(0x00400003)));
});
}
@Test @Test
public void testCurrentDisassembleActionHostArm() throws Throwable { public void testCurrentDisassembleActionHostArm() throws Throwable {
createLegacyTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x1e, 0xff, 0x2f, 0xe1)); createLegacyTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x1e, 0xff, 0x2f, 0xe1));
@ -352,7 +399,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
TraceObjectThread thread = TraceObjectThread thread =
createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x70, 0x47)); createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x70, 0x47));
// Set up registers to injects will select THUMB // Set up registers so injects will select THUMB
// TODO // TODO
Address start = tb.addr(0x00400000); Address start = tb.addr(0x00400000);

View file

@ -1164,7 +1164,7 @@ public interface TargetObjectSchema {
* {@link TargetStackFrame}, and the frame level (index) must precede it. * {@link TargetStackFrame}, and the frame level (index) must precede it.
* *
* @param frameLevel the frame level. May be ignored if not applicable * @param frameLevel the frame level. May be ignored if not applicable
* @path the path of the seed object relative to the root * @param path the path of the seed object relative to the root
* @return the predicates where the register container should be found, possibly empty * @return the predicates where the register container should be found, possibly empty
*/ */
default PathPredicates searchForRegisterContainer(int frameLevel, List<String> path) { default PathPredicates searchForRegisterContainer(int frameLevel, List<String> path) {