Merge branch 'GP-2521_ryanmkurtz_PR-4570_ryanmkurtz_NeFileBytes'

This commit is contained in:
Ryan Kurtz
2022-09-02 12:41:13 -04:00
2 changed files with 49 additions and 53 deletions
@@ -224,25 +224,4 @@ public class Segment {
public SegmentRelocation [] getRelocations() { public SegmentRelocation [] getRelocations() {
return relocations; return relocations;
} }
/**
* Returns the bytes the comprise this segment.
* The size of the byte array is MAX(length,minalloc).
* @return the bytes the comprise this segment
*/
public byte [] getBytes() throws IOException {
int offset_int = getOffsetShiftAligned();
int length_int = Conv.shortToInt(getLength());
int minalloc_int = Conv.shortToInt(getMinAllocSize());
if (minalloc_int == 0) minalloc_int = 0x10000;
byte [] bytes = reader.readByteArray(offset_int, length_int);
if (length_int >= minalloc_int) {
return bytes;
}
byte [] newbytes = new byte[minalloc_int];
System.arraycopy(bytes, 0, newbytes, 0, length_int);
return newbytes;
}
} }
@@ -26,7 +26,9 @@ import ghidra.app.util.bin.ByteProvider;
import ghidra.app.util.bin.format.ne.*; import ghidra.app.util.bin.format.ne.*;
import ghidra.app.util.importer.MessageLog; import ghidra.app.util.importer.MessageLog;
import ghidra.framework.options.Options; import ghidra.framework.options.Options;
import ghidra.framework.store.LockException;
import ghidra.program.database.function.OverlappingFunctionException; import ghidra.program.database.function.OverlappingFunctionException;
import ghidra.program.database.mem.FileBytes;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.data.ByteDataType; import ghidra.program.model.data.ByteDataType;
import ghidra.program.model.data.StringDataType; import ghidra.program.model.data.StringDataType;
@@ -91,11 +93,7 @@ public class NeLoader extends AbstractLibrarySupportLoader {
initVars(); initVars();
// We don't use the file bytes to create block because the bytes are manipulated before FileBytes fileBytes = MemoryBlockUtils.createFileBytes(prog, provider, monitor);
// forming the block. Creating the FileBytes anyway in case later we want access to all
// the original bytes.
MemoryBlockUtils.createFileBytes(prog, provider, monitor);
SegmentedAddressSpace space = SegmentedAddressSpace space =
(SegmentedAddressSpace) prog.getAddressFactory().getDefaultAddressSpace(); (SegmentedAddressSpace) prog.getAddressFactory().getDefaultAddressSpace();
NewExecutable ne = new NewExecutable(provider, space.getAddress(SEGMENT_START, 0)); NewExecutable ne = new NewExecutable(provider, space.getAddress(SEGMENT_START, 0));
@@ -119,7 +117,7 @@ public class NeLoader extends AbstractLibrarySupportLoader {
return; return;
} }
monitor.setMessage("Processing segment table..."); monitor.setMessage("Processing segment table...");
processSegmentTable(log, ib, st, space, prog, context, monitor); processSegmentTable(log, ib, st, space, prog, context, fileBytes, monitor);
if (prog.getMemory().isEmpty()) { if (prog.getMemory().isEmpty()) {
Msg.error(this, "Empty memory for " + prog); Msg.error(this, "Empty memory for " + prog);
return; return;
@@ -129,7 +127,7 @@ public class NeLoader extends AbstractLibrarySupportLoader {
return; return;
} }
monitor.setMessage("Processing resource table..."); monitor.setMessage("Processing resource table...");
processResourceTable(log, prog, rt, space, monitor); processResourceTable(log, prog, rt, space, fileBytes, monitor);
if (monitor.isCancelled()) { if (monitor.isCancelled()) {
return; return;
@@ -239,29 +237,48 @@ public class NeLoader extends AbstractLibrarySupportLoader {
private void processSegmentTable(MessageLog log, InformationBlock ib, SegmentTable st, private void processSegmentTable(MessageLog log, InformationBlock ib, SegmentTable st,
SegmentedAddressSpace space, Program program, ProgramContext context, SegmentedAddressSpace space, Program program, ProgramContext context,
TaskMonitor monitor) throws IOException { FileBytes fileBytes, TaskMonitor monitor) throws IOException {
try { try {
Segment[] segments = st.getSegments(); Segment[] segments = st.getSegments();
for (int i = 0; i < segments.length; ++i) { for (int i = 0; i < segments.length; ++i) {
String name = (segments[i].isCode() ? "Code" : "Data") + (i + 1); String name = (segments[i].isCode() ? "Code" : "Data") + (i + 1);
byte[] bytes = segments[i].getBytes();
Address addr = space.getAddress(segments[i].getSegmentID(), 0); Address addr = space.getAddress(segments[i].getSegmentID(), 0);
boolean r = true; boolean r = true;
boolean w = segments[i].isData() && !segments[i].isReadOnly(); boolean w = segments[i].isData() && !segments[i].isReadOnly();
boolean x = segments[i].isCode(); boolean x = segments[i].isCode();
if (bytes.length > 0) { int offset = segments[i].getOffsetShiftAligned();
MemoryBlockUtils.createInitializedBlock(program, false, name, addr, int length = Short.toUnsignedInt(segments[i].getLength());
new ByteArrayInputStream(bytes), bytes.length, "", "", r, w, x, log, int minalloc = Short.toUnsignedInt(segments[i].getMinAllocSize());
monitor); if (minalloc == 0) {
minalloc = 0x10000;
}
MemoryBlock block;
if (length > 0) {
block = MemoryBlockUtils.createInitializedBlock(program, false,
name, addr, fileBytes, offset, length, "", "", r, w, x, log);
if (length < minalloc) {
// Things actually rely on the block being padded out with real 0's, so we
// must expand it
byte[] zeros = new byte[minalloc - length];
MemoryBlock zeroBlock = MemoryBlockUtils.createInitializedBlock(program,
false, name, addr.add(length), new ByteArrayInputStream(zeros),
zeros.length, "", "", r, w, x, log, monitor);
try {
block = program.getMemory().join(block, zeroBlock); // expand
}
catch (MemoryBlockException | LockException | NotFoundException e) {
throw new IOException(e);
}
}
} }
else { else {
MemoryBlockUtils.createUninitializedBlock(program, false, name, addr, block = MemoryBlockUtils.createUninitializedBlock(program, false, name, addr,
bytes.length, "", "", r, w, x, log); minalloc, "", "", r, w, x, log);
} }
if (segments[i].is32bit()) { if (segments[i].is32bit()) {
Address end = addr.add(bytes.length - 1); Address end = block.getEnd();
Register opsizeRegister = context.getRegister("opsize"); Register opsizeRegister = context.getRegister("opsize");
Register addrsizeRegister = context.getRegister("addrsize"); Register addrsizeRegister = context.getRegister("addrsize");
@@ -314,7 +331,7 @@ public class NeLoader extends AbstractLibrarySupportLoader {
} }
private void processResourceTable(MessageLog log, Program program, ResourceTable rt, private void processResourceTable(MessageLog log, Program program, ResourceTable rt,
SegmentedAddressSpace space, TaskMonitor monitor) throws IOException { SegmentedAddressSpace space, FileBytes fileBytes, TaskMonitor monitor) {
Listing listing = program.getListing(); Listing listing = program.getListing();
if (rt == null) { if (rt == null) {
@@ -332,12 +349,12 @@ public class NeLoader extends AbstractLibrarySupportLoader {
Address addr = space.getAddress(segidx, 0); Address addr = space.getAddress(segidx, 0);
try { try {
byte[] bytes = resource.getBytes(); int offset = resource.getFileOffsetShifted();
int length = resource.getFileLengthShifted();
if (bytes != null && bytes.length > 0) { if (length > 0) {
MemoryBlockUtils.createInitializedBlock(program, false, "Rsrc" + (id++), MemoryBlockUtils.createInitializedBlock(program, false, "Rsrc" + (id++),
addr, new ByteArrayInputStream(bytes), bytes.length, "", "", true, addr, fileBytes, offset, length, "", "", true,
false, false, log, monitor); false, false, log);
} }
} }
catch (AddressOverflowException e) { catch (AddressOverflowException e) {
@@ -383,7 +400,7 @@ public class NeLoader extends AbstractLibrarySupportLoader {
listing.createData(straddr, new ByteDataType(), 1); listing.createData(straddr, new ByteDataType(), 1);
straddr = straddr.addNoWrap(1); straddr = straddr.addNoWrap(1);
listing.createData(straddr, new StringDataType(), listing.createData(straddr, new StringDataType(),
Conv.byteToInt(string.getLength())); Byte.toUnsignedInt(string.getLength()));
} }
catch (AddressOverflowException | CodeUnitInsertionException e) { catch (AddressOverflowException | CodeUnitInsertionException e) {
log.appendMsg("Error creating data"); log.appendMsg("Error creating data");
@@ -514,7 +531,7 @@ public class NeLoader extends AbstractLibrarySupportLoader {
if (segmentIdx > 0) { if (segmentIdx > 0) {
int segment = st.getSegments()[segmentIdx - 1].getSegmentID(); int segment = st.getSegments()[segmentIdx - 1].getSegmentID();
short offset = ib.getEntryPointOffset(); short offset = ib.getEntryPointOffset();
Address entryAddr = space.getAddress(segment, Conv.shortToInt(offset)); Address entryAddr = space.getAddress(segment, Short.toUnsignedInt(offset));
symbolTable.addExternalEntryPoint(entryAddr); symbolTable.addExternalEntryPoint(entryAddr);
try { try {
symbolTable.createLabel(entryAddr, "entry", SourceType.IMPORTED); symbolTable.createLabel(entryAddr, "entry", SourceType.IMPORTED);
@@ -529,7 +546,7 @@ public class NeLoader extends AbstractLibrarySupportLoader {
EntryTableBundle[] bundles = et.getBundles(); EntryTableBundle[] bundles = et.getBundles();
for (EntryTableBundle bundle : bundles) { for (EntryTableBundle bundle : bundles) {
if (bundle.getType() == EntryTableBundle.UNUSED) { if (bundle.getType() == EntryTableBundle.UNUSED) {
int count = Conv.byteToInt(bundle.getCount()); int count = Byte.toUnsignedInt(bundle.getCount());
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
entryPointList.add(null); entryPointList.add(null);
} }
@@ -553,7 +570,7 @@ public class NeLoader extends AbstractLibrarySupportLoader {
else { else {
seg = st.getSegments()[bundle.getType() - 1].getSegmentID(); seg = st.getSegments()[bundle.getType() - 1].getSegmentID();
} }
int off = Conv.shortToInt(pt.getOffset()); int off = Short.toUnsignedInt(pt.getOffset());
Address addr = space.getAddress(seg, off); Address addr = space.getAddress(seg, off);
symbolTable.addExternalEntryPoint(addr); symbolTable.addExternalEntryPoint(addr);
@@ -580,7 +597,7 @@ public class NeLoader extends AbstractLibrarySupportLoader {
Symbol symbol = symbols.get(0); Symbol symbol = symbols.get(0);
if (symbol.getSymbolType() == SymbolType.FUNCTION && symbol.isExternal()) { if (symbol.getSymbolType() == SymbolType.FUNCTION && symbol.isExternal()) {
Function func = (Function) symbol.getObject(); Function func = (Function) symbol.getObject();
Address[] thunkAddresses = func.getFunctionThunkAddresses(); Address[] thunkAddresses = func.getFunctionThunkAddresses(false);
if (thunkAddresses != null && thunkAddresses.length != 0) { if (thunkAddresses != null && thunkAddresses.length != 0) {
return (SegmentedAddress) thunkAddresses[0]; return (SegmentedAddress) thunkAddresses[0];
} }
@@ -604,7 +621,7 @@ public class NeLoader extends AbstractLibrarySupportLoader {
} }
int segment = st.getSegments()[s].getSegmentID(); int segment = st.getSegments()[s].getSegmentID();
int offset = Conv.shortToInt(reloc.getOffset()); int offset = Short.toUnsignedInt(reloc.getOffset());
SegmentedAddress relocAddr = null; SegmentedAddress relocAddr = null;
if (reloc.isInternalRef()) { if (reloc.isInternalRef()) {
@@ -613,7 +630,7 @@ public class NeLoader extends AbstractLibrarySupportLoader {
} }
else { else {
int seg = st.getSegments()[reloc.getTargetSegment() - 1].getSegmentID(); int seg = st.getSegments()[reloc.getTargetSegment() - 1].getSegmentID();
int off = Conv.shortToInt(reloc.getTargetOffset()); int off = Short.toUnsignedInt(reloc.getTargetOffset());
relocAddr = space.getAddress(seg, off); relocAddr = space.getAddress(seg, off);
} }
} }
@@ -624,7 +641,7 @@ public class NeLoader extends AbstractLibrarySupportLoader {
} }
else if (reloc.isImportOrdinal()) { else if (reloc.isImportOrdinal()) {
String modname = getRelocationModuleName(mrt, reloc); String modname = getRelocationModuleName(mrt, reloc);
int ordinal = Conv.shortToInt(reloc.getTargetOffset()); int ordinal = Short.toUnsignedInt(reloc.getTargetOffset());
String procname = SymbolUtilities.ORDINAL_PREFIX + ordinal; String procname = SymbolUtilities.ORDINAL_PREFIX + ordinal;
relocAddr = getImportSymbolByName(symbolTable, modname, procname); relocAddr = getImportSymbolByName(symbolTable, modname, procname);
} }
@@ -732,7 +749,7 @@ public class NeLoader extends AbstractLibrarySupportLoader {
return imp.getNameAt(reloc.getTargetOffset()).getString(); return imp.getNameAt(reloc.getTargetOffset()).getString();
} }
else if (reloc.isImportOrdinal()) { else if (reloc.isImportOrdinal()) {
int ordinal = Conv.shortToInt(reloc.getTargetOffset()); int ordinal = Short.toUnsignedInt(reloc.getTargetOffset());
return SymbolUtilities.ORDINAL_PREFIX + ordinal; return SymbolUtilities.ORDINAL_PREFIX + ordinal;
} }
return null; return null;
@@ -774,7 +791,7 @@ public class NeLoader extends AbstractLibrarySupportLoader {
private void createSymbols(LengthStringOrdinalSet[] lengthStringOrdinalSets, private void createSymbols(LengthStringOrdinalSet[] lengthStringOrdinalSets,
SymbolTable symbolTable) { SymbolTable symbolTable) {
for (LengthStringOrdinalSet lengthStringOrdinalSet : lengthStringOrdinalSets) { for (LengthStringOrdinalSet lengthStringOrdinalSet : lengthStringOrdinalSets) {
int ordinal = Conv.shortToInt(lengthStringOrdinalSet.getOrdinal()); int ordinal = Short.toUnsignedInt(lengthStringOrdinalSet.getOrdinal());
if (ordinal >= entryPointList.size()) { if (ordinal >= entryPointList.size()) {
continue; continue;
} }