diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/ubi/FatHeader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/ubi/FatHeader.java index e2edf0bc87..14b4de0bb7 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/ubi/FatHeader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/ubi/FatHeader.java @@ -23,8 +23,12 @@ import generic.continues.GenericFactory; import ghidra.app.util.bin.ByteProvider; import ghidra.app.util.bin.ByteProviderWrapper; import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader; +import ghidra.app.util.bin.format.coff.CoffException; +import ghidra.app.util.bin.format.coff.archive.CoffArchiveHeader; +import ghidra.app.util.bin.format.coff.archive.CoffArchiveMemberHeader; import ghidra.app.util.bin.format.macho.MachException; import ghidra.app.util.bin.format.macho.MachHeader; +import ghidra.util.task.TaskMonitor; /** * Represents a fat_header structure. @@ -71,9 +75,32 @@ public class FatHeader { } for (FatArch fatarch : architectures) { - ByteProviderWrapper wrapper = new ByteProviderWrapper(provider, fatarch.getOffset(), fatarch.getSize()); - MachHeader machHeader = MachHeader.createMachHeader(factory, wrapper); - machHeaders.add(machHeader); + ByteProviderWrapper wrapper = + new ByteProviderWrapper(provider, fatarch.getOffset(), fatarch.getSize()); + + // It could be a Mach-O or a COFF archive + CoffArchiveHeader caf = null; + try { + caf = CoffArchiveHeader.read(wrapper, TaskMonitor.DUMMY); + } + catch (CoffException e) { + throw new UbiException(e); + } + if (caf != null) { + for (CoffArchiveMemberHeader camh : caf.getArchiveMemberHeaders()) { + wrapper = new ByteProviderWrapper(provider, + fatarch.getOffset() + camh.getPayloadOffset(), camh.getSize()); + try { + machHeaders.add(MachHeader.createMachHeader(factory, wrapper)); + } + catch (MachException e) { + // Could be __.SYMDEF archive member instead of a Mach-O + } + } + } + else { + machHeaders.add(MachHeader.createMachHeader(factory, wrapper)); + } } } 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 e77ad1cf8d..8bd52e562d 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 @@ -16,8 +16,7 @@ package ghidra.app.util.opinion; import java.math.BigInteger; -import java.util.ArrayList; -import java.util.List; +import java.util.*; import ghidra.app.util.MemoryBlockUtils; import ghidra.app.util.bin.ByteProvider; @@ -215,26 +214,32 @@ public class MachoProgramBuilder { } // Create memory blocks for segments. - for (SegmentCommand segment : header.getAllSegments()) { + ListIterator it = header.getAllSegments().listIterator(); + while (it.hasNext()) { + int i = it.nextIndex(); + final SegmentCommand segment = it.next(); + if (monitor.isCancelled()) { break; } if (segment.getFileSize() > 0 && (allowZeroAddr || segment.getVMaddress() != 0)) { - if (createMemoryBlock(segment.getSegmentName(), - space.getAddress(segment.getVMaddress()), segment.getFileOffset(), - segment.getFileSize(), segment.getSegmentName(), source, segment.isRead(), - segment.isWrite(), segment.isExecute(), false) == null) { + String segmentName = segment.getSegmentName(); + if (segmentName.isBlank()) { + segmentName = "SEGMENT." + i; + } + if (createMemoryBlock(segmentName, space.getAddress(segment.getVMaddress()), + segment.getFileOffset(), segment.getFileSize(), segmentName, source, + segment.isRead(), segment.isWrite(), segment.isExecute(), false) == null) { log.appendMsg(String.format("Failed to create block: %s 0x%x 0x%x", segment.getSegmentName(), segment.getVMaddress(), segment.getVMsize())); } if (segment.getVMsize() > segment.getFileSize()) { // Pad the remaining address range with uninitialized data - if (createMemoryBlock(segment.getSegmentName(), + if (createMemoryBlock(segmentName, space.getAddress(segment.getVMaddress()).add(segment.getFileSize()), 0, - segment.getVMsize() - segment.getFileSize(), segment.getSegmentName(), - source, segment.isRead(), segment.isWrite(), segment.isExecute(), - true) == null) { + segment.getVMsize() - segment.getFileSize(), segmentName, source, + segment.isRead(), segment.isWrite(), segment.isExecute(), true) == null) { log.appendMsg(String.format("Failed to create block: %s 0x%x 0x%x", segment.getSegmentName(), segment.getVMaddress(), segment.getVMsize())); } @@ -1343,7 +1348,7 @@ public class MachoProgramBuilder { NList nList = machoHeader.getFirstLoadCommand(SymbolTableCommand.class).getSymbolAt( symbolIndex); Symbol symbol = SymbolUtilities.getLabelOrFunctionSymbol(program, nList.getString(), - err -> log.error("Macho", err)); + err -> log.appendMsg("Macho", err)); if (relocation.isPcRelocated()) { destinationAddress = symbol.getAddress().subtractWrap(