fix Emulator.getValidPageSize

This commit is contained in:
caheckman 2019-08-29 10:07:39 -04:00
parent 6e8c48f180
commit 49e7351b94

View file

@ -30,7 +30,6 @@ import ghidra.program.model.listing.Instruction;
import ghidra.util.*; import ghidra.util.*;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
import ghidra.util.task.TaskMonitorAdapter;
public class Emulator { public class Emulator {
@ -51,7 +50,7 @@ public class Emulator {
private boolean isExecuting = false; private boolean isExecuting = false;
private boolean writeBack = false; private boolean writeBack = false;
private int pageSize; private int pageSize; // The preferred page size for a paged memory state
private String pcName; private String pcName;
private long initialPC; private long initialPC;
@ -97,19 +96,32 @@ public class Emulator {
} }
} }
/**
* Get the page size to use with a specific AddressSpace. The page containers (MemoryBank)
* assume page size is always power of 2. Any address space is assigned at least 8-bits of
* addressable locations, so at the very least, the size is divisible by 256. Starting with this
* minimum, this method finds the power of 2 that is closest to the preferred page size (pageSize)
* but that still divides the size of the space.
* @param space is the specific AddressSpace
* @return the page size to use
*/
private int getValidPageSize(AddressSpace space) { private int getValidPageSize(AddressSpace space) {
int ps = pageSize; int ps = 256; // Minimum page size supported
long maxOffset = space.getMaxAddress().getOffset(); long spaceSize = space.getMaxAddress().getOffset() + 1; // Number of bytes in the space (0 if 2^64 bytes)
if (ps > maxOffset && maxOffset > 0) { if ((spaceSize & 0xff) != 0) {
ps = (int) maxOffset; Msg.warn(this, "Emulator using page size of 256 bytes for " + space.getName() +
" which is NOT a multiple of 256");
return ps;
} }
else { spaceSize >>>= 8; // Divide required size by 256 (evenly)
ps -= (ps % space.getAddressableUnitSize()); while (ps < pageSize) { // If current page size is smaller than preferred page size
if ((spaceSize & 1) != 0) {
break; // a bigger page size does not divide the space size evenly, so use current size
} }
if (pageSize != ps) { ps <<= 1; // Bump up current page size to next power of 2
Msg.warn(this, "Emulator using adjusted page size of " + ps + " bytes for " + spaceSize >>>= 1; // Divide (evenly) by 2
space.getName() + " address space");
} }
return ps; return ps;
} }
@ -169,11 +181,13 @@ public class Emulator {
for (int i = 0; i < vals.size(); i++) { for (int i = 0; i < vals.size(); i++) {
String useKey = ""; String useKey = "";
if (key.equals("GDTR") || key.equals("IDTR") || key.equals("LDTR")) { if (key.equals("GDTR") || key.equals("IDTR") || key.equals("LDTR")) {
if (i == 0) if (i == 0) {
useKey = key + "_Limit"; useKey = key + "_Limit";
if (i == 1) }
if (i == 1) {
useKey = key + "_Address"; useKey = key + "_Address";
} }
}
else if (key.equals("S.base")) { else if (key.equals("S.base")) {
Integer lval = conv.getInt(vals.get(i)); Integer lval = conv.getInt(vals.get(i));
if (lval != 0 && i < vals.size() - 1) { if (lval != 0 && i < vals.size() - 1) {
@ -230,8 +244,8 @@ public class Emulator {
private String dumpBytesAsSingleValue(byte[] bytes) { private String dumpBytesAsSingleValue(byte[] bytes) {
StringBuffer buf = new StringBuffer("0x"); StringBuffer buf = new StringBuffer("0x");
if (language.isBigEndian()) { if (language.isBigEndian()) {
for (int i = 0; i < bytes.length; i++) { for (byte b : bytes) {
String byteStr = Integer.toHexString(bytes[i] & 0xff); String byteStr = Integer.toHexString(b & 0xff);
if (byteStr.length() == 1) { if (byteStr.length() == 1) {
buf.append('0'); buf.append('0');
} }
@ -372,7 +386,7 @@ public class Emulator {
EmulateMemoryStateBuffer memBuffer = new EmulateMemoryStateBuffer(memState, addr); EmulateMemoryStateBuffer memBuffer = new EmulateMemoryStateBuffer(memState, addr);
Disassembler disassembler = Disassembler.getDisassembler(language, addrFactory, Disassembler disassembler = Disassembler.getDisassembler(language, addrFactory,
TaskMonitorAdapter.DUMMY_MONITOR, null); TaskMonitor.DUMMY, null);
boolean stopOnError = false; boolean stopOnError = false;
@ -421,6 +435,7 @@ public class Emulator {
* parsed/executed. The context value returned will feed into the next * parsed/executed. The context value returned will feed into the next
* instruction to be parsed with its non-flowing bits cleared and * instruction to be parsed with its non-flowing bits cleared and
* any future context state merged in. * any future context state merged in.
* @return context as a RegisterValue object
*/ */
public RegisterValue getContextRegisterValue() { public RegisterValue getContextRegisterValue() {
return emulator.getContextRegisterValue(); return emulator.getContextRegisterValue();
@ -435,7 +450,7 @@ public class Emulator {
* take precedence over context set using this method. This method * take precedence over context set using this method. This method
* is primarily intended to be used to establish the initial * is primarily intended to be used to establish the initial
* context state. * context state.
* @param regValue * @param regValue is the value to set context to
*/ */
public void setContextRegisterValue(RegisterValue regValue) { public void setContextRegisterValue(RegisterValue regValue) {
emulator.setContextRegisterValue(regValue); emulator.setContextRegisterValue(regValue);