mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 19:42:36 +02:00
Better support for Mach-O MH_OBJECTs and archives (fixes #2702)
This commit is contained in:
parent
6ed341bc87
commit
3bccb8ce65
2 changed files with 47 additions and 15 deletions
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<SegmentCommand> 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(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue