From fa3ccac6fc063308af0e51020b4317f63651e6b3 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Thu, 18 Apr 2024 13:31:00 -0400 Subject: [PATCH] GP-4533: MachoLoader can now create overlay blocks --- .../app/util/opinion/MachoProgramBuilder.java | 48 ++++++++++++++----- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoProgramBuilder.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoProgramBuilder.java index ccd2366a21..f07f69557a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoProgramBuilder.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoProgramBuilder.java @@ -74,6 +74,8 @@ public class MachoProgramBuilder { protected AddressSpace space; protected BinaryReader reader; + private Map segmentOverlayMap; + /** * Creates a new {@link MachoProgramBuilder} based on the given information. * @@ -94,6 +96,7 @@ public class MachoProgramBuilder { this.listing = program.getListing(); this.space = program.getAddressFactory().getDefaultAddressSpace(); this.reader = new BinaryReader(provider, !memory.isBigEndian()); + this.segmentOverlayMap = new HashMap<>(); } /** @@ -207,6 +210,8 @@ public class MachoProgramBuilder { return; } + Set
overlaySections = new HashSet<>(); + // Create memory blocks for segments. for (SegmentCommand segment : header.getAllSegments()) { if (monitor.isCancelled()) { @@ -218,7 +223,7 @@ public class MachoProgramBuilder { if (createMemoryBlock(segment.getSegmentName(), space.getAddress(segment.getVMaddress()), segment.getFileOffset(), segment.getFileSize(), segment.getSegmentName(), source, segment.isRead(), - segment.isWrite(), segment.isExecute(), false) == null) { + segment.isWrite(), segment.isExecute(), false, false) == null) { log.appendMsg(String.format("Failed to create block: %s 0x%x 0x%x", segment.getSegmentName(), segment.getVMaddress(), segment.getVMsize())); } @@ -228,12 +233,27 @@ public class MachoProgramBuilder { space.getAddress(segment.getVMaddress()).add(segment.getFileSize()), 0, segment.getVMsize() - segment.getFileSize(), segment.getSegmentName(), source, segment.isRead(), segment.isWrite(), segment.isExecute(), - true) == null) { + true, false) == null) { log.appendMsg(String.format("Failed to create block: %s 0x%x 0x%x", segment.getSegmentName(), segment.getVMaddress(), segment.getVMsize())); } } } + else if (segment.getVMaddress() != 0 && segment.getVMsize() == 0 && + segment.getFileSize() > 0) { + MemoryBlock overlayBlock = createMemoryBlock(segment.getSegmentName(), + space.getAddress(segment.getVMaddress()), segment.getFileOffset(), + segment.getFileSize(), segment.getSegmentName(), source, true, false, false, + false, true); + if (overlayBlock == null) { + log.appendMsg(String.format("Failed to create overlay block: %s 0x%x 0x%x", + segment.getSegmentName(), segment.getVMaddress(), segment.getVMsize())); + } + else { + segmentOverlayMap.put(segment.getSegmentName(), overlayBlock.getStart().getAddressSpace()); + overlaySections.addAll(segment.getSections()); + } + } } // Create memory blocks for sections. They will be in the segments we just created, so the @@ -243,14 +263,16 @@ public class MachoProgramBuilder { if (monitor.isCancelled()) { break; } - + AddressSpace sectionSpace = overlaySections.contains(section) + ? segmentOverlayMap.get(section.getSegmentName()) + : space; if (section.getSize() > 0 && section.getOffset() > 0 && (allowZeroAddr || section.getAddress() != 0)) { if (createMemoryBlock(section.getSectionName(), - space.getAddress(section.getAddress()), section.getOffset(), + sectionSpace.getAddress(section.getAddress()), section.getOffset(), section.getSize(), section.getSegmentName(), source, section.isRead(), section.isWrite(), section.isExecute(), - section.getType() == SectionTypes.S_ZEROFILL) == null) { + section.getType() == SectionTypes.S_ZEROFILL, false) == null) { log.appendMsg(String.format("Failed to create block: %s.%s 0x%x 0x%x %s", section.getSegmentName(), section.getSectionName(), section.getAddress(), section.getSize(), source)); @@ -277,12 +299,13 @@ public class MachoProgramBuilder { * @param x True if the new block has execute-permissions; otherwise, false. * @param zeroFill True if the new block is zero-filled; otherwise, false. Newly created * zero-filled blocks will be uninitialized to safe space. + * @param overlay True if the new block should be an overlay; otherwise, false. * @return The newly created (or split) memory block, or null if it failed to be created. * @throws Exception If there was a problem creating the new memory block. */ private MemoryBlock createMemoryBlock(String name, Address start, long dataOffset, long dataLength, String comment, String source, boolean r, boolean w, boolean x, - boolean zeroFill) throws Exception { + boolean zeroFill, boolean overlay) throws Exception { // Get a list of all blocks that intersect with the block we wish to create. There may be // more that one if the containing memory has both initialized and uninitialized pieces. @@ -301,11 +324,11 @@ public class MachoProgramBuilder { if (intersectingBlocks.isEmpty()) { if (zeroFill) { // Treat zero-fill blocks as uninitialized to save space - return MemoryBlockUtils.createUninitializedBlock(program, false, name, start, + return MemoryBlockUtils.createUninitializedBlock(program, overlay, name, start, dataLength, comment, source, r, w, x, log); } - return MemoryBlockUtils.createInitializedBlock(program, false, name, start, fileBytes, + return MemoryBlockUtils.createInitializedBlock(program, overlay, name, start, fileBytes, dataOffset, dataLength, comment, source, r, w, x, log); } @@ -354,10 +377,9 @@ public class MachoProgramBuilder { } ProgramModule rootModule = listing.getDefaultRootModule(); for (SegmentCommand segment : machoHeader.getAllSegments()) { - if (segment.getVMsize() == 0) { - continue; - } - Address segmentStart = space.getAddress(segment.getVMaddress()); + AddressSpace segmentSpace = + segmentOverlayMap.getOrDefault(segment.getSegmentName(), space); + Address segmentStart = segmentSpace.getAddress(segment.getVMaddress()); Address segmentEnd = segmentStart.add(segment.getVMsize() - 1); if (!memory.contains(segmentStart)) { continue; @@ -397,7 +419,7 @@ public class MachoProgramBuilder { if (section.getSize() == 0) { continue; } - Address sectionStart = space.getAddress(section.getAddress()); + Address sectionStart = segmentSpace.getAddress(section.getAddress()); Address sectionEnd = sectionStart.add(section.getSize() - 1); if (!memory.contains(sectionEnd)) { sectionEnd = memory.getBlock(sectionStart).getEnd();