GP-2814: Fix translation of address operands for guest instructions.

This commit is contained in:
Dan 2022-11-17 08:50:12 -05:00
parent 346eef3727
commit ef6fb310bb
8 changed files with 201 additions and 25 deletions

View file

@ -17,6 +17,7 @@ package ghidra.trace.database.listing;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.*;
import db.DBRecord;
@ -24,8 +25,7 @@ import ghidra.program.model.address.*;
import ghidra.program.model.lang.*;
import ghidra.program.model.listing.ContextChangeException;
import ghidra.program.model.listing.FlowOverride;
import ghidra.program.model.mem.MemBuffer;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.mem.*;
import ghidra.program.model.symbol.*;
import ghidra.trace.database.DBTrace;
import ghidra.trace.database.DBTraceUtils;
@ -106,11 +106,32 @@ public class DBTraceInstruction extends AbstractDBTraceCodeUnit<DBTraceInstructi
@Override
public ParserContext getParserContext(Address instructionAddress)
throws UnknownContextException, MemoryAccessException {
// TODO: Does the given address need mapping?
return DBTraceInstruction.this.getParserContext(instructionAddress);
}
}
protected class GuestMemBuffer implements MemBufferAdapter {
@Override
public Address getAddress() {
return platform.mapHostToGuest(getX1());
}
@Override
public Memory getMemory() {
return null;
}
@Override
public boolean isBigEndian() {
return platform.getLanguage().isBigEndian();
}
@Override
public int getBytes(ByteBuffer buffer, int addressOffset) {
return DBTraceInstruction.this.getBytes(buffer, addressOffset);
}
}
@DBAnnotatedField(column = PLATFORM_COLUMN_NAME)
private int platformKey;
@DBAnnotatedField(column = PROTOTYPE_COLUMN_NAME)
@ -126,6 +147,7 @@ public class DBTraceInstruction extends AbstractDBTraceCodeUnit<DBTraceInstructi
protected ParserContext parserContext;
protected InternalTracePlatform platform;
protected InstructionContext instructionContext;
protected MemBuffer memBuffer;
/**
* Construct an instruction unit
@ -150,9 +172,11 @@ public class DBTraceInstruction extends AbstractDBTraceCodeUnit<DBTraceInstructi
this.platform = platform;
if (platform.isHost()) {
instructionContext = this;
memBuffer = this;
}
else {
instructionContext = new GuestInstructionContext();
memBuffer = new GuestMemBuffer();
}
}
@ -708,12 +732,13 @@ public class DBTraceInstruction extends AbstractDBTraceCodeUnit<DBTraceInstructi
@Override
public MemBuffer getMemBuffer() {
return this;
return memBuffer;
}
@Override
public ParserContext getParserContext() throws MemoryAccessException {
return parserContext == null ? parserContext = prototype.getParserContext(this, this)
return parserContext == null
? parserContext = prototype.getParserContext(getMemBuffer(), getProcessorContext())
: parserContext;
}

View file

@ -16,16 +16,18 @@
package ghidra.trace.util;
import java.util.List;
import java.util.stream.Collectors;
import ghidra.program.model.address.Address;
import ghidra.program.model.lang.*;
import ghidra.program.model.listing.Instruction;
import ghidra.program.model.listing.InstructionPcodeOverride;
import ghidra.program.model.pcode.PcodeOp;
import ghidra.program.model.scalar.Scalar;
import ghidra.program.model.symbol.RefType;
import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.listing.TraceInstruction;
public interface InstructionAdapterFromPrototype extends Instruction {
public interface InstructionAdapterFromPrototype extends TraceInstruction {
default String getFullString() {
StringBuilder sb = new StringBuilder();
sb.append(getMnemonicString());
@ -68,7 +70,7 @@ public interface InstructionAdapterFromPrototype extends Instruction {
InstructionContext context = getInstructionContext();
int opType = prototype.getOpType(opIndex, context);
if (OperandType.isAddress(opType)) {
return prototype.getAddress(opIndex, context);
return getPlatform().mapGuestToHost(prototype.getAddress(opIndex, context));
}
return null;
}
@ -106,11 +108,13 @@ public interface InstructionAdapterFromPrototype extends Instruction {
}
StringBuilder sb = new StringBuilder();
for (Object opElem : opList) {
if (opElem instanceof Address) {
Address opAddr = (Address) opElem;
if (opElem instanceof Address opAddr) {
sb.append("0x");
sb.append(opAddr.toString(false));
}
else if (opElem == null) {
sb.append("<null>");
}
else {
sb.append(opElem.toString());
}
@ -120,7 +124,23 @@ public interface InstructionAdapterFromPrototype extends Instruction {
@Override
default List<Object> getDefaultOperandRepresentationList(int opIndex) {
return getPrototype().getOpRepresentationList(opIndex, getInstructionContext());
// TODO: Cache this in the instruction?
List<Object> list =
getPrototype().getOpRepresentationList(opIndex, getInstructionContext());
TracePlatform platform = getPlatform();
if (platform.isHost()) {
return list;
}
return list.stream().map(obj -> {
if (obj instanceof Address addr) {
Address hostAddr = platform.mapGuestToHost(addr);
if (hostAddr == null) {
return "guest:" + addr.toString(true);
}
return hostAddr;
}
return obj;
}).collect(Collectors.toList());
}
@Override