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 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);
|
||||||
|
|
||||||
|
DBTraceMemoryManager memory = tb.trace.getMemoryManager();
|
||||||
|
if (pcInStack) {
|
||||||
DBTraceObject objFrame =
|
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);
|
objFrame.insert(zeroOn, ConflictResolution.DENY);
|
||||||
TraceObjectStackFrame frame = objFrame.queryInterface(TraceObjectStackFrame.class);
|
TraceObjectStackFrame frame = objFrame.queryInterface(TraceObjectStackFrame.class);
|
||||||
frame.setProgramCounter(zeroOn, tb.addr(offset));
|
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();
|
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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue