mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-24_emteere fixing disassembly during emulation
This commit is contained in:
parent
b3b7bab4ca
commit
27f9b750db
4 changed files with 403 additions and 54 deletions
|
@ -920,9 +920,8 @@ public class Disassembler implements DisassemblerConflictHandler {
|
|||
|
||||
disassemblerContext.flowToAddress(addr);
|
||||
|
||||
// TODO: An overall better caching of bytes for this block could be done instead
|
||||
// the previous buffering done here was not doing any buffering
|
||||
MemBuffer instrMemBuffer = new DumbMemBufferImpl(blockMemBuffer.getMemory(), addr);
|
||||
MemBuffer instrMemBuffer = new WrappedMemBuffer(blockMemBuffer,
|
||||
(int) addr.subtract(blockMemBuffer.getAddress()));
|
||||
|
||||
adjustPreParseContext(instrMemBuffer);
|
||||
|
||||
|
|
|
@ -15,12 +15,11 @@
|
|||
*/
|
||||
package ghidra.program.model.mem;
|
||||
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.util.GhidraBigEndianDataConverter;
|
||||
import ghidra.util.GhidraLittleEndianDataConverter;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.util.GhidraDataConverter;
|
||||
|
||||
/**
|
||||
* MemBufferImpl implements the MemBuffer interface. It buffers up N bytes
|
||||
* at time, reducing the overall number of calls to Memory, greatly reducing
|
||||
|
@ -34,8 +33,9 @@ import java.math.BigInteger;
|
|||
|
||||
public class MemoryBufferImpl implements MutableMemBuffer {
|
||||
|
||||
private final GhidraDataConverter converter;
|
||||
|
||||
private static final int DEFAULT_BUFSIZE = 1024;
|
||||
private static final int THRESH = 8;
|
||||
|
||||
private Memory mem;
|
||||
private Address startAddr;
|
||||
|
@ -43,6 +43,7 @@ public class MemoryBufferImpl implements MutableMemBuffer {
|
|||
private int startAddrIndex = 0;
|
||||
private int minOffset = 0;
|
||||
private int maxOffset = -1;
|
||||
private int threshold = 0;
|
||||
|
||||
/**
|
||||
* Construct a new MemoryBufferImpl
|
||||
|
@ -62,6 +63,9 @@ public class MemoryBufferImpl implements MutableMemBuffer {
|
|||
public MemoryBufferImpl(Memory mem, Address addr, int bufSize) {
|
||||
this.mem = mem;
|
||||
buffer = new byte[bufSize];
|
||||
threshold = bufSize / 100; // 1/100 of buffer size
|
||||
|
||||
this.converter = GhidraDataConverter.getInstance(mem.isBigEndian());
|
||||
setPosition(addr);
|
||||
}
|
||||
|
||||
|
@ -81,7 +85,7 @@ public class MemoryBufferImpl implements MutableMemBuffer {
|
|||
if (minOffset <= maxOffset) {
|
||||
if (addr.getAddressSpace().equals(startAddr.getAddressSpace())) {
|
||||
long diff = addr.subtract(startAddr);
|
||||
if (diff >= minOffset && diff < maxOffset - THRESH) {
|
||||
if (diff >= minOffset && diff < maxOffset - threshold) {
|
||||
startAddr = addr;
|
||||
minOffset -= (int) diff;
|
||||
maxOffset -= (int) diff;
|
||||
|
@ -155,35 +159,22 @@ public class MemoryBufferImpl implements MutableMemBuffer {
|
|||
|
||||
@Override
|
||||
public short getShort(int offset) throws MemoryAccessException {
|
||||
if (mem.isBigEndian()) {
|
||||
return GhidraBigEndianDataConverter.INSTANCE.getShort(this, offset);
|
||||
}
|
||||
return GhidraLittleEndianDataConverter.INSTANCE.getShort(this, offset);
|
||||
return converter.getShort(this, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(int offset) throws MemoryAccessException {
|
||||
if (mem.isBigEndian()) {
|
||||
return GhidraBigEndianDataConverter.INSTANCE.getInt(this, offset);
|
||||
}
|
||||
return GhidraLittleEndianDataConverter.INSTANCE.getInt(this, offset);
|
||||
return converter.getInt(this, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(int offset) throws MemoryAccessException {
|
||||
if (mem.isBigEndian()) {
|
||||
return GhidraBigEndianDataConverter.INSTANCE.getLong(this, offset);
|
||||
}
|
||||
return GhidraLittleEndianDataConverter.INSTANCE.getLong(this, offset);
|
||||
return converter.getLong(this, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger getBigInteger(int offset, int size, boolean signed)
|
||||
throws MemoryAccessException {
|
||||
if (mem.isBigEndian()) {
|
||||
return GhidraBigEndianDataConverter.INSTANCE.getBigInteger(this, offset, size, signed);
|
||||
}
|
||||
return GhidraLittleEndianDataConverter.INSTANCE.getBigInteger(this, offset, size, signed);
|
||||
return converter.getBigInteger(this, offset, size, signed);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,13 +19,24 @@ import java.math.BigInteger;
|
|||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressOutOfBoundsException;
|
||||
import ghidra.util.GhidraDataConverter;
|
||||
|
||||
public class WrappedMemBuffer implements MemBuffer {
|
||||
|
||||
private final GhidraDataConverter converter;
|
||||
|
||||
private final MemBuffer memBuffer;
|
||||
private int baseOffset;
|
||||
private Address address;
|
||||
|
||||
private static final int DEFAULT_BUFSIZE = 10;
|
||||
|
||||
private byte[] buffer;
|
||||
private int subBufferIndex = 0;
|
||||
private int minOffset = 0;
|
||||
private int maxOffset = -1;
|
||||
private int threshold = 0;
|
||||
|
||||
/**
|
||||
* Construct a wrapped MemBuffer with an adjustable base offset
|
||||
* @param buf memory buffer
|
||||
|
@ -33,23 +44,60 @@ public class WrappedMemBuffer implements MemBuffer {
|
|||
* @throws AddressOutOfBoundsException
|
||||
*/
|
||||
public WrappedMemBuffer(MemBuffer buf, int offset) throws AddressOutOfBoundsException {
|
||||
this(buf, DEFAULT_BUFSIZE, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a wrapped MemBuffer with an adjustable base offset
|
||||
* @param buf memory buffer
|
||||
* @buffersize size of cache buffer - specify 0 for no buffering
|
||||
* @param offset base offset for this buffer relative to buf's address
|
||||
* @throws AddressOutOfBoundsException
|
||||
*/
|
||||
public WrappedMemBuffer(MemBuffer buf, int bufferSize, int offset)
|
||||
throws AddressOutOfBoundsException {
|
||||
this.memBuffer = buf;
|
||||
this.converter = GhidraDataConverter.getInstance(buf.isBigEndian());
|
||||
|
||||
buffer = new byte[bufferSize];
|
||||
threshold = bufferSize / 100; // 1/100 of buffer size
|
||||
|
||||
setBaseOffset(offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set new base offset relative to the associated MemBuffer's address
|
||||
* @param offset new base offset of this buffer
|
||||
* @throws AddressOutOfBoundsException
|
||||
*/
|
||||
public void setBaseOffset(int offset) throws AddressOutOfBoundsException {
|
||||
this.baseOffset = offset;
|
||||
this.address = memBuffer.getAddress().add(baseOffset);
|
||||
}
|
||||
this.address = memBuffer.getAddress().add(offset);
|
||||
|
||||
@Override
|
||||
public Address getAddress() {
|
||||
return address;
|
||||
// already set, changing position
|
||||
if (minOffset <= maxOffset) {
|
||||
long diff = offset - baseOffset;
|
||||
if (diff >= minOffset && diff < (maxOffset - threshold)) {
|
||||
baseOffset = offset;
|
||||
minOffset -= (int) diff;
|
||||
maxOffset -= (int) diff;
|
||||
subBufferIndex += diff;
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.baseOffset = offset;
|
||||
|
||||
if (buffer.length > 0) {
|
||||
subBufferIndex = 0;
|
||||
minOffset = 0;
|
||||
maxOffset = -1;
|
||||
|
||||
maxOffset = memBuffer.getBytes(buffer, baseOffset) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -70,11 +118,40 @@ public class WrappedMemBuffer implements MemBuffer {
|
|||
|
||||
@Override
|
||||
public byte getByte(int offset) throws MemoryAccessException {
|
||||
return memBuffer.getByte(computeOffset(offset));
|
||||
// no buffering, just get the byte
|
||||
if (buffer.length <= 0) {
|
||||
return memBuffer.getByte(computeOffset(offset));
|
||||
}
|
||||
|
||||
// byte found in buffer
|
||||
if ((offset >= minOffset) && (offset <= maxOffset)) {
|
||||
return buffer[subBufferIndex + offset];
|
||||
}
|
||||
|
||||
// fill the buffer
|
||||
int nRead = memBuffer.getBytes(buffer, computeOffset(offset));
|
||||
|
||||
subBufferIndex = -offset;
|
||||
minOffset = offset;
|
||||
maxOffset = offset + nRead - 1;
|
||||
|
||||
if (nRead == 0) {
|
||||
throw new MemoryAccessException();
|
||||
}
|
||||
return buffer[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBytes(byte[] b, int offset) {
|
||||
if (buffer.length > 0) {
|
||||
// bytes are contained in the buffer
|
||||
if (offset >= minOffset && (b.length + offset) <= maxOffset) {
|
||||
System.arraycopy(buffer, subBufferIndex + offset, b, 0, b.length);
|
||||
return b.length;
|
||||
}
|
||||
}
|
||||
|
||||
// grab from wrapped buffer, too many bytes, or no buffer
|
||||
try {
|
||||
return memBuffer.getBytes(b, computeOffset(offset));
|
||||
}
|
||||
|
@ -83,34 +160,34 @@ public class WrappedMemBuffer implements MemBuffer {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(int offset) throws MemoryAccessException {
|
||||
return memBuffer.getInt(computeOffset(offset));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(int offset) throws MemoryAccessException {
|
||||
return memBuffer.getLong(computeOffset(offset));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger getBigInteger(int offset, int size, boolean signed)
|
||||
throws MemoryAccessException {
|
||||
return memBuffer.getBigInteger(computeOffset(offset), size, signed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Memory getMemory() {
|
||||
return memBuffer.getMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShort(int offset) throws MemoryAccessException {
|
||||
return memBuffer.getShort(computeOffset(offset));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBigEndian() {
|
||||
return memBuffer.isBigEndian();
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShort(int offset) throws MemoryAccessException {
|
||||
return converter.getShort(this, computeOffset(offset));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(int offset) throws MemoryAccessException {
|
||||
return converter.getInt(this, computeOffset(offset));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(int offset) throws MemoryAccessException {
|
||||
return converter.getLong(this, computeOffset(offset));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger getBigInteger(int offset, int size, boolean signed)
|
||||
throws MemoryAccessException {
|
||||
return converter.getBigInteger(this, computeOffset(offset), size, signed);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue