diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/ne/Segment.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/ne/Segment.java index 48034d3ade..faec08a28b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/ne/Segment.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/ne/Segment.java @@ -224,25 +224,4 @@ public class Segment { public SegmentRelocation [] getRelocations() { 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; - } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/NeLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/NeLoader.java index 24e22438fa..e176a3d0f5 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/NeLoader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/NeLoader.java @@ -26,7 +26,9 @@ import ghidra.app.util.bin.ByteProvider; import ghidra.app.util.bin.format.ne.*; import ghidra.app.util.importer.MessageLog; import ghidra.framework.options.Options; +import ghidra.framework.store.LockException; import ghidra.program.database.function.OverlappingFunctionException; +import ghidra.program.database.mem.FileBytes; import ghidra.program.model.address.*; import ghidra.program.model.data.ByteDataType; import ghidra.program.model.data.StringDataType; @@ -91,11 +93,7 @@ public class NeLoader extends AbstractLibrarySupportLoader { initVars(); - // We don't use the file bytes to create block because the bytes are manipulated before - // forming the block. Creating the FileBytes anyway in case later we want access to all - // the original bytes. - MemoryBlockUtils.createFileBytes(prog, provider, monitor); - + FileBytes fileBytes = MemoryBlockUtils.createFileBytes(prog, provider, monitor); SegmentedAddressSpace space = (SegmentedAddressSpace) prog.getAddressFactory().getDefaultAddressSpace(); NewExecutable ne = new NewExecutable(provider, space.getAddress(SEGMENT_START, 0)); @@ -119,7 +117,7 @@ public class NeLoader extends AbstractLibrarySupportLoader { return; } 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()) { Msg.error(this, "Empty memory for " + prog); return; @@ -129,7 +127,7 @@ public class NeLoader extends AbstractLibrarySupportLoader { return; } monitor.setMessage("Processing resource table..."); - processResourceTable(log, prog, rt, space, monitor); + processResourceTable(log, prog, rt, space, fileBytes, monitor); if (monitor.isCancelled()) { return; @@ -239,29 +237,48 @@ public class NeLoader extends AbstractLibrarySupportLoader { private void processSegmentTable(MessageLog log, InformationBlock ib, SegmentTable st, SegmentedAddressSpace space, Program program, ProgramContext context, - TaskMonitor monitor) throws IOException { + FileBytes fileBytes, TaskMonitor monitor) throws IOException { try { Segment[] segments = st.getSegments(); for (int i = 0; i < segments.length; ++i) { String name = (segments[i].isCode() ? "Code" : "Data") + (i + 1); - byte[] bytes = segments[i].getBytes(); Address addr = space.getAddress(segments[i].getSegmentID(), 0); boolean r = true; boolean w = segments[i].isData() && !segments[i].isReadOnly(); boolean x = segments[i].isCode(); - if (bytes.length > 0) { - MemoryBlockUtils.createInitializedBlock(program, false, name, addr, - new ByteArrayInputStream(bytes), bytes.length, "", "", r, w, x, log, - monitor); + int offset = segments[i].getOffsetShiftAligned(); + int length = Short.toUnsignedInt(segments[i].getLength()); + int minalloc = Short.toUnsignedInt(segments[i].getMinAllocSize()); + 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 { - MemoryBlockUtils.createUninitializedBlock(program, false, name, addr, - bytes.length, "", "", r, w, x, log); + block = MemoryBlockUtils.createUninitializedBlock(program, false, name, addr, + minalloc, "", "", r, w, x, log); } if (segments[i].is32bit()) { - Address end = addr.add(bytes.length - 1); + Address end = block.getEnd(); Register opsizeRegister = context.getRegister("opsize"); Register addrsizeRegister = context.getRegister("addrsize"); @@ -314,7 +331,7 @@ public class NeLoader extends AbstractLibrarySupportLoader { } 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(); if (rt == null) { @@ -332,12 +349,12 @@ public class NeLoader extends AbstractLibrarySupportLoader { Address addr = space.getAddress(segidx, 0); try { - byte[] bytes = resource.getBytes(); - - if (bytes != null && bytes.length > 0) { + int offset = resource.getFileOffsetShifted(); + int length = resource.getFileLengthShifted(); + if (length > 0) { MemoryBlockUtils.createInitializedBlock(program, false, "Rsrc" + (id++), - addr, new ByteArrayInputStream(bytes), bytes.length, "", "", true, - false, false, log, monitor); + addr, fileBytes, offset, length, "", "", true, + false, false, log); } } catch (AddressOverflowException e) { @@ -383,7 +400,7 @@ public class NeLoader extends AbstractLibrarySupportLoader { listing.createData(straddr, new ByteDataType(), 1); straddr = straddr.addNoWrap(1); listing.createData(straddr, new StringDataType(), - Conv.byteToInt(string.getLength())); + Byte.toUnsignedInt(string.getLength())); } catch (AddressOverflowException | CodeUnitInsertionException e) { log.appendMsg("Error creating data"); @@ -514,7 +531,7 @@ public class NeLoader extends AbstractLibrarySupportLoader { if (segmentIdx > 0) { int segment = st.getSegments()[segmentIdx - 1].getSegmentID(); short offset = ib.getEntryPointOffset(); - Address entryAddr = space.getAddress(segment, Conv.shortToInt(offset)); + Address entryAddr = space.getAddress(segment, Short.toUnsignedInt(offset)); symbolTable.addExternalEntryPoint(entryAddr); try { symbolTable.createLabel(entryAddr, "entry", SourceType.IMPORTED); @@ -529,7 +546,7 @@ public class NeLoader extends AbstractLibrarySupportLoader { EntryTableBundle[] bundles = et.getBundles(); for (EntryTableBundle bundle : bundles) { if (bundle.getType() == EntryTableBundle.UNUSED) { - int count = Conv.byteToInt(bundle.getCount()); + int count = Byte.toUnsignedInt(bundle.getCount()); for (int i = 0; i < count; ++i) { entryPointList.add(null); } @@ -553,7 +570,7 @@ public class NeLoader extends AbstractLibrarySupportLoader { else { 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); symbolTable.addExternalEntryPoint(addr); @@ -580,7 +597,7 @@ public class NeLoader extends AbstractLibrarySupportLoader { Symbol symbol = symbols.get(0); if (symbol.getSymbolType() == SymbolType.FUNCTION && symbol.isExternal()) { Function func = (Function) symbol.getObject(); - Address[] thunkAddresses = func.getFunctionThunkAddresses(); + Address[] thunkAddresses = func.getFunctionThunkAddresses(false); if (thunkAddresses != null && thunkAddresses.length != 0) { return (SegmentedAddress) thunkAddresses[0]; } @@ -604,7 +621,7 @@ public class NeLoader extends AbstractLibrarySupportLoader { } int segment = st.getSegments()[s].getSegmentID(); - int offset = Conv.shortToInt(reloc.getOffset()); + int offset = Short.toUnsignedInt(reloc.getOffset()); SegmentedAddress relocAddr = null; if (reloc.isInternalRef()) { @@ -613,7 +630,7 @@ public class NeLoader extends AbstractLibrarySupportLoader { } else { 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); } } @@ -624,7 +641,7 @@ public class NeLoader extends AbstractLibrarySupportLoader { } else if (reloc.isImportOrdinal()) { String modname = getRelocationModuleName(mrt, reloc); - int ordinal = Conv.shortToInt(reloc.getTargetOffset()); + int ordinal = Short.toUnsignedInt(reloc.getTargetOffset()); String procname = SymbolUtilities.ORDINAL_PREFIX + ordinal; relocAddr = getImportSymbolByName(symbolTable, modname, procname); } @@ -732,7 +749,7 @@ public class NeLoader extends AbstractLibrarySupportLoader { return imp.getNameAt(reloc.getTargetOffset()).getString(); } else if (reloc.isImportOrdinal()) { - int ordinal = Conv.shortToInt(reloc.getTargetOffset()); + int ordinal = Short.toUnsignedInt(reloc.getTargetOffset()); return SymbolUtilities.ORDINAL_PREFIX + ordinal; } return null; @@ -774,7 +791,7 @@ public class NeLoader extends AbstractLibrarySupportLoader { private void createSymbols(LengthStringOrdinalSet[] lengthStringOrdinalSets, SymbolTable symbolTable) { for (LengthStringOrdinalSet lengthStringOrdinalSet : lengthStringOrdinalSets) { - int ordinal = Conv.shortToInt(lengthStringOrdinalSet.getOrdinal()); + int ordinal = Short.toUnsignedInt(lengthStringOrdinalSet.getOrdinal()); if (ordinal >= entryPointList.size()) { continue; }