diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/BinaryExporter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/BinaryExporter.java index b15b935b75b..80751fcab46 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/BinaryExporter.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/BinaryExporter.java @@ -21,9 +21,12 @@ import ghidra.app.util.DomainObjectService; import ghidra.app.util.Option; import ghidra.framework.model.DomainObject; +import ghidra.program.database.mem.AddressSourceInfo; +import ghidra.program.database.mem.FileBytes; import ghidra.program.model.address.*; import ghidra.program.model.listing.Program; import ghidra.program.model.mem.*; +import ghidra.program.model.reloc.Relocation; import ghidra.util.HelpLocation; import ghidra.util.task.TaskMonitor; @@ -39,48 +42,47 @@ public BinaryExporter() { @Override public boolean export(File file, DomainObject domainObj, AddressSetView addrSet, - TaskMonitor monitor) throws IOException, ExporterException { + TaskMonitor monitor) throws IOException { if (!(domainObj instanceof Program)) { log.appendMsg("Unsupported type: " + domainObj.getClass().getName()); return false; } - Program program = (Program) domainObj; + final Program program = (Program) domainObj; + final Memory memory = program.getMemory(); - Memory memory = program.getMemory(); + try (final RandomAccessFile fout = new RandomAccessFile(file, "rw")) { + final List fileBytes = memory.getAllFileBytes(); + if (!fileBytes.isEmpty()) { + final FileBytes fByte = fileBytes.get(0); + long offset = 0; + long size = fByte.getSize(); + while (size > Integer.MAX_VALUE) { + final byte[] bytes = new byte[Integer.MAX_VALUE]; + fByte.getModifiedBytes(offset, bytes); + fout.write(bytes); + size -= Integer.MAX_VALUE; + offset += Integer.MAX_VALUE; + } + final byte[] bytes = new byte[(int) size]; + fByte.getModifiedBytes(offset, bytes); + fout.write(bytes); - if (addrSet == null) { - addrSet = memory; - } - - FileOutputStream fos = new FileOutputStream(file); - - AddressSet set = new AddressSet(addrSet); - - //skip blocks that are not initialized... - MemoryBlock[] blocks = memory.getBlocks(); - for (int i = 0; i < blocks.length; ++i) { - if (!blocks[i].isInitialized()) { - set.delete(new AddressRangeImpl(blocks[i].getStart(), blocks[i].getEnd())); + // Now put back the original relocation bytes + final Iterable relocs = + () -> program.getRelocationTable().getRelocations(); + for (Relocation reloc : relocs) { + final AddressSourceInfo info = memory.getAddressSourceInfo(reloc.getAddress()); + // some relocations report negative offsets + if (info.getFileOffset() >= 0) { + // seek incase the offset is larger than an int + fout.seek(info.getFileOffset()); + fout.write(reloc.getBytes()); + } + } } } - try { - AddressRangeIterator iter = set.getAddressRanges(); - while (iter.hasNext()) { - AddressRange range = iter.next(); - byte[] mem = new byte[(int) range.getLength()]; - int numBytes = memory.getBytes(range.getMinAddress(), mem); - fos.write(mem, 0, numBytes); - } - } - catch (MemoryAccessException e) { - throw new ExporterException(e); - } - finally { - fos.close(); - } - return true; }