mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
GP-2816: Add test demonstrating this is already fixed.
This commit is contained in:
parent
ee70fe99e9
commit
1a2fea0782
2 changed files with 59 additions and 12 deletions
|
@ -17,9 +17,9 @@ package ghidra.app.plugin.core.debug.disassemble;
|
|||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
@ -44,8 +44,7 @@ import ghidra.dbg.target.schema.XmlSchemaContext;
|
|||
import ghidra.debug.api.control.ControlMode;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSet;
|
||||
import ghidra.program.model.lang.LanguageID;
|
||||
import ghidra.program.model.lang.RegisterValue;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.listing.Instruction;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.program.util.ProgramSelection;
|
||||
|
@ -115,10 +114,20 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
<schema name='Stack' canonical='yes' elementResync='NEVER'
|
||||
attributeResync='NEVER'>
|
||||
<interface name='Stack' />
|
||||
<interface name='Aggregate' />
|
||||
<element schema='Frame' />
|
||||
</schema>
|
||||
<schema name='Frame' elementResync='NEVER' attributeResync='NEVER'>
|
||||
<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>
|
||||
</context>""");
|
||||
|
||||
|
@ -148,7 +157,12 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
}
|
||||
|
||||
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");
|
||||
|
||||
DBTraceObjectManager objects = tb.trace.getObjectManager();
|
||||
|
@ -171,13 +185,31 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
// TODO: Why doesn't setRange work after insert?
|
||||
objBinText.insert(zeroOn, ConflictResolution.DENY);
|
||||
|
||||
DBTraceMemoryManager memory = tb.trace.getMemoryManager();
|
||||
if (pcInStack) {
|
||||
DBTraceObject objFrame =
|
||||
objects.createObject(TraceObjectKeyPath.parse("Targets[0].Threads[0].Stack[0]"));
|
||||
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)));
|
||||
}
|
||||
|
||||
DBTraceMemoryManager memory = tb.trace.getMemoryManager();
|
||||
ByteBuffer bytes = byteSupplier.get();
|
||||
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
|
||||
public void testCurrentDisassembleActionHostArm() throws Throwable {
|
||||
createLegacyTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x1e, 0xff, 0x2f, 0xe1));
|
||||
|
@ -352,7 +399,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
TraceObjectThread thread =
|
||||
createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x70, 0x47));
|
||||
|
||||
// Set up registers to injects will select THUMB
|
||||
// Set up registers so injects will select THUMB
|
||||
// TODO
|
||||
|
||||
Address start = tb.addr(0x00400000);
|
||||
|
|
|
@ -1164,7 +1164,7 @@ public interface TargetObjectSchema {
|
|||
* {@link TargetStackFrame}, and the frame level (index) must precede it.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
default PathPredicates searchForRegisterContainer(int frameLevel, List<String> path) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue