mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-25 04:35:54 +08:00
Merge remote-tracking branch 'origin/GP-1245_Dan_wow64Emu--REBASED-1--SQUASHED'
This commit is contained in:
+8
-3
@@ -141,7 +141,7 @@ public class DBTraceCodeManager
|
||||
}
|
||||
catch (Exception e) {
|
||||
Msg.error(this, "Bad Instruction Prototype found in DB! Address: " + address +
|
||||
"b Bytes: " + NumericUtilities.convertBytesToString(bytes));
|
||||
"Bytes: " + NumericUtilities.convertBytesToString(bytes));
|
||||
return new InvalidPrototype(language);
|
||||
}
|
||||
}
|
||||
@@ -237,6 +237,11 @@ public class DBTraceCodeManager
|
||||
}
|
||||
}
|
||||
|
||||
protected byte[] valueBytes(RegisterValue rv) {
|
||||
byte[] bytes = rv.toBytes();
|
||||
return Arrays.copyOfRange(bytes, bytes.length / 2, bytes.length);
|
||||
}
|
||||
|
||||
protected int doRecordPrototype(InstructionPrototype prototype, MemBuffer memBuffer,
|
||||
ProcessorContextView context) {
|
||||
DBTraceCodePrototypeEntry protoEnt = protoStore.create();
|
||||
@@ -250,8 +255,8 @@ public class DBTraceCodeManager
|
||||
ctx = null;
|
||||
}
|
||||
else {
|
||||
BigInteger value = context.getValue(baseCtxReg, true);
|
||||
ctx = value == null ? null : value.toByteArray();
|
||||
RegisterValue value = context.getRegisterValue(baseCtxReg);
|
||||
ctx = value == null ? null : valueBytes(value);
|
||||
}
|
||||
protoEnt.set(languageManager.getKeyForLanguage(prototype.getLanguage()), bytes, ctx,
|
||||
memBuffer.getAddress(), prototype.isInDelaySlot());
|
||||
|
||||
+27
@@ -27,6 +27,8 @@ import ghidra.program.model.lang.InstructionError.InstructionErrorType;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.util.CodeUnitInsertionException;
|
||||
import ghidra.trace.database.DBTraceUtils;
|
||||
import ghidra.trace.database.context.DBTraceRegisterContextManager;
|
||||
import ghidra.trace.database.context.DBTraceRegisterContextSpace;
|
||||
import ghidra.trace.database.memory.DBTraceMemorySpace;
|
||||
import ghidra.trace.model.ImmutableTraceAddressSnapRange;
|
||||
import ghidra.trace.model.Trace.TraceCodeChangeType;
|
||||
@@ -64,9 +66,34 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
|
||||
this.conflictCodeUnit = conflictCodeUnit;
|
||||
}
|
||||
|
||||
protected void doSetContexts(Range<Long> lifespan, Address min, Address max,
|
||||
ProcessorContextView context) {
|
||||
Language language = space.baseLanguage;
|
||||
Register contextReg = language.getContextBaseRegister();
|
||||
if (contextReg == null) {
|
||||
return;
|
||||
}
|
||||
RegisterValue newValue = context.getRegisterValue(contextReg);
|
||||
DBTraceRegisterContextManager ctxMgr = space.trace.getRegisterContextManager();
|
||||
if (Objects.equals(ctxMgr.getDefaultValue(language, contextReg, min), newValue)) {
|
||||
DBTraceRegisterContextSpace ctxSpace = ctxMgr.get(space, false);
|
||||
if (ctxSpace == null) {
|
||||
return;
|
||||
}
|
||||
ctxSpace.setValue(language, null, lifespan, new AddressRangeImpl(min, max));
|
||||
return;
|
||||
}
|
||||
DBTraceRegisterContextSpace ctxSpace = ctxMgr.get(space, true);
|
||||
// TODO: Do not save non-flowing context beyond???
|
||||
ctxSpace.setValue(language, newValue, lifespan, new AddressRangeImpl(min, max));
|
||||
}
|
||||
|
||||
protected Instruction doCreateInstruction(Range<Long> lifespan, Address address,
|
||||
InstructionPrototype prototype, Instruction protoInstr) {
|
||||
try {
|
||||
doSetContexts(lifespan, address, address.addNoWrap(prototype.getLength() - 1),
|
||||
protoInstr);
|
||||
|
||||
Instruction created = doCreate(lifespan, address, prototype, protoInstr);
|
||||
// copy override settings to replacement instruction
|
||||
if (protoInstr.isFallThroughOverridden()) {
|
||||
|
||||
+53
-2
@@ -20,6 +20,7 @@ import static org.junit.Assert.*;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.*;
|
||||
|
||||
import org.junit.Test;
|
||||
@@ -32,8 +33,7 @@ import ghidra.app.plugin.assembler.sleigh.sem.AssemblyPatternBlock;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.pcode.emu.PcodeThread;
|
||||
import ghidra.pcode.exec.*;
|
||||
import ghidra.program.model.lang.Register;
|
||||
import ghidra.program.model.lang.RegisterValue;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.listing.Instruction;
|
||||
import ghidra.test.AbstractGhidraHeadlessIntegrationTest;
|
||||
import ghidra.trace.database.ToyDBTraceBuilder;
|
||||
@@ -775,6 +775,7 @@ public class TracePcodeEmulatorTest extends AbstractGhidraHeadlessIntegrationTes
|
||||
PcodeThread<byte[]> emuThread = emu.newThread(thread.getPath());
|
||||
emuThread.overrideContextWithDefault();
|
||||
emuThread.stepInstruction();
|
||||
// No assertions. It should simply not throw an exception.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -799,6 +800,7 @@ public class TracePcodeEmulatorTest extends AbstractGhidraHeadlessIntegrationTes
|
||||
PcodeThread<byte[]> emuThread = emu.newThread(thread.getPath());
|
||||
emuThread.overrideContextWithDefault();
|
||||
emuThread.stepInstruction();
|
||||
// No assertions. It should throw an exception.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -823,6 +825,7 @@ public class TracePcodeEmulatorTest extends AbstractGhidraHeadlessIntegrationTes
|
||||
PcodeThread<byte[]> emuThread = emu.newThread(thread.getPath());
|
||||
emuThread.overrideContextWithDefault();
|
||||
emuThread.stepInstruction();
|
||||
// No assertions. It should simply not throw an exception.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -847,6 +850,54 @@ public class TracePcodeEmulatorTest extends AbstractGhidraHeadlessIntegrationTes
|
||||
emuThread.overrideContextWithDefault();
|
||||
emuThread.stepInstruction();
|
||||
emuThread.stepInstruction();
|
||||
// No assertions. It should simply not throw an exception.
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDEC_MOV_compat32() throws Throwable {
|
||||
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
|
||||
Language lang = tb.trace.getBaseLanguage();
|
||||
Register ctxReg = lang.getContextBaseRegister();
|
||||
Register opsizeReg = lang.getRegister("opsize");
|
||||
Register addrsizeReg = lang.getRegister("addrsize");
|
||||
Register longModeReg = lang.getRegister("longMode");
|
||||
RegisterValue ctxVal = new RegisterValue(ctxReg)
|
||||
.assign(opsizeReg, BigInteger.ONE)
|
||||
.assign(addrsizeReg, BigInteger.ONE)
|
||||
.assign(longModeReg, BigInteger.ZERO);
|
||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
tb.trace.getRegisterContextManager()
|
||||
.setValue(lang, ctxVal, Range.atLeast(0L),
|
||||
tb.range(0x00400000, 0x00400002));
|
||||
}
|
||||
TraceThread thread = initTrace(tb,
|
||||
List.of(
|
||||
"RIP = 0x00400000;",
|
||||
"RSP = 0x00110000;",
|
||||
"RAX = 0xff12345678;"),
|
||||
List.of(
|
||||
"DEC EAX",
|
||||
"MOV ECX,EAX"));
|
||||
// Assembly sanity check
|
||||
ByteBuffer buf = ByteBuffer.allocate(3);
|
||||
tb.trace.getMemoryManager().getBytes(0, tb.addr(0x00400000), buf);
|
||||
assertArrayEquals(tb.arr(0x48, 0x89, 0xc1), buf.array());
|
||||
|
||||
TracePcodeEmulator emu = new TracePcodeEmulator(tb.trace, 0);
|
||||
PcodeThread<byte[]> emuThread = emu.newThread(thread.getPath());
|
||||
emuThread.overrideContext(ctxVal);
|
||||
emuThread.stepInstruction();
|
||||
emuThread.stepInstruction();
|
||||
|
||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
emu.writeDown(tb.trace, 1, 1, false);
|
||||
}
|
||||
|
||||
assertEquals(BigInteger.valueOf(0x00400003),
|
||||
TraceSleighUtils.evaluate("RIP", tb.trace, 1, thread, 0));
|
||||
assertEquals(BigInteger.valueOf(0x12345677),
|
||||
TraceSleighUtils.evaluate("RCX", tb.trace, 1, thread, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+21
@@ -215,6 +215,7 @@ public class DBTraceDisassemblerIntegrationTest extends AbstractGhidraHeadlessIn
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestLanguage(ProgramBuilder._X64)
|
||||
public void test64BitX86DBTrace() throws Exception {
|
||||
try (UndoableTransaction tid = b.startTransaction()) {
|
||||
@@ -233,6 +234,15 @@ public class DBTraceDisassemblerIntegrationTest extends AbstractGhidraHeadlessIn
|
||||
CodeUnit cu1 = cuManager.getAt(0, b.addr(0x00400000));
|
||||
assertEquals("MOV RCX,RAX", cu1.toString());
|
||||
}
|
||||
|
||||
File saved = b.save();
|
||||
|
||||
// Check that required context is actually saved and restored
|
||||
try (ToyDBTraceBuilder b = new ToyDBTraceBuilder(saved)) {
|
||||
DBTraceCodeUnitsMemoryView cuManager = b.trace.getCodeManager().codeUnits();
|
||||
CodeUnit cu1 = cuManager.getAt(0, b.addr(0x00400000));
|
||||
assertEquals("MOV RCX,RAX", cu1.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -258,6 +268,17 @@ public class DBTraceDisassemblerIntegrationTest extends AbstractGhidraHeadlessIn
|
||||
CodeUnit cu2 = cuManager.getAt(0, b.addr(0x00400001));
|
||||
assertEquals("MOV ECX,EAX", cu2.toString());
|
||||
}
|
||||
|
||||
File saved = b.save();
|
||||
|
||||
// Check that required context is actually saved and restored
|
||||
try (ToyDBTraceBuilder b = new ToyDBTraceBuilder(saved)) {
|
||||
DBTraceCodeUnitsMemoryView cuManager = b.trace.getCodeManager().codeUnits();
|
||||
CodeUnit cu1 = cuManager.getAt(0, b.addr(0x00400000));
|
||||
assertEquals("DEC EAX", cu1.toString());
|
||||
CodeUnit cu2 = cuManager.getAt(0, b.addr(0x00400001));
|
||||
assertEquals("MOV ECX,EAX", cu2.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user