mirror of
https://github.com/NationalSecurityAgency/ghidra
synced 2024-10-13 05:33:02 +00:00
Merge remote-tracking branch 'origin/GP-2699_ryanmkurtz-mh_object-fix'
This commit is contained in:
commit
56b8bc9471
|
@ -20,8 +20,7 @@ import static ghidra.app.util.bin.format.macho.commands.LoadCommandTypes.*;
|
|||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.format.macho.MachException;
|
||||
import ghidra.app.util.bin.format.macho.MachHeader;
|
||||
import ghidra.app.util.bin.format.macho.*;
|
||||
import ghidra.app.util.bin.format.macho.dyld.DyldCacheHeader;
|
||||
import ghidra.app.util.bin.format.macho.dyld.DyldCacheMappingInfo;
|
||||
import ghidra.app.util.bin.format.macho.threadcommand.ThreadCommand;
|
||||
|
@ -163,6 +162,10 @@ public class LoadCommandFactory {
|
|||
* <p>
|
||||
* NOTE: This method assumes that the __LINKEDIT segment {@link LoadCommand} has already been
|
||||
* parsed.
|
||||
* <p>
|
||||
* NOTE: In MH_OBJECT files, there is just one segment that all load commands point to. This
|
||||
* method will treat this lone segment as the __LINKEDIT segment, as it contains all the things
|
||||
* that are typically found in the __LINKEDIT segment.
|
||||
*
|
||||
* @param reader The {@link BinaryReader} used to read the given Mach-O header
|
||||
* @param header The {@link MachHeader Mach-O header}
|
||||
|
@ -175,6 +178,12 @@ public class LoadCommandFactory {
|
|||
SplitDyldCache splitDyldCache) throws MachException {
|
||||
SegmentCommand linkEdit = header.getSegment(SegmentNames.SEG_LINKEDIT);
|
||||
if (linkEdit == null) {
|
||||
if (header.getFileType() == MachHeaderFileTypes.MH_OBJECT) {
|
||||
SegmentCommand objectSegment = header.getSegment("");
|
||||
if (objectSegment != null) {
|
||||
return reader.clone(objectSegment.getFileOffset());
|
||||
}
|
||||
}
|
||||
throw new MachException("__LINKEDIT segment not found");
|
||||
}
|
||||
if (splitDyldCache == null) {
|
||||
|
|
|
@ -394,7 +394,11 @@ public class MachoProgramBuilder {
|
|||
*/
|
||||
protected void fixupProgramTree() throws Exception {
|
||||
ProgramModule rootModule = listing.getDefaultRootModule();
|
||||
for (SegmentCommand segment : machoHeader.getAllSegments()) {
|
||||
ListIterator<SegmentCommand> it = machoHeader.getAllSegments().listIterator();
|
||||
while (it.hasNext()) {
|
||||
int i = it.nextIndex();
|
||||
SegmentCommand segment = it.next();
|
||||
|
||||
if (segment.getVMsize() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
@ -409,17 +413,21 @@ public class MachoProgramBuilder {
|
|||
// Move original segment fragment into module and rename it. After we add new
|
||||
// section fragments, it will represent the parts of the segment that weren't in any
|
||||
// section.
|
||||
String noSectionsName = segment.getSegmentName() + " <no section>";
|
||||
String segmentName = segment.getSegmentName();
|
||||
if (segmentName.isBlank()) {
|
||||
segmentName = "SEGMENT." + i;
|
||||
}
|
||||
String noSectionsName = segmentName + " <no section>";
|
||||
ProgramFragment segmentFragment = null;
|
||||
for (Group group : rootModule.getChildren()) {
|
||||
if (group instanceof ProgramFragment fragment &&
|
||||
fragment.getName().equals(segment.getSegmentName())) {
|
||||
fragment.getName().equals(segmentName)) {
|
||||
fragment.setName(noSectionsName);
|
||||
segmentFragment = fragment;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ProgramModule segmentModule = rootModule.createModule(segment.getSegmentName());
|
||||
ProgramModule segmentModule = rootModule.createModule(segmentName);
|
||||
segmentModule.reparent(noSectionsName, rootModule);
|
||||
|
||||
// Add the sections, which will remove overlapped ranges from the segment fragment
|
||||
|
@ -460,11 +468,6 @@ public class MachoProgramBuilder {
|
|||
|
||||
protected boolean processExports(MachHeader header) throws Exception {
|
||||
List<ExportEntry> exports = new ArrayList<>();
|
||||
SegmentCommand textSegment = header.getSegment(SegmentNames.SEG_TEXT);
|
||||
if (textSegment == null) {
|
||||
log.appendMsg("Cannot process exports, __TEXT segment not found!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Old way - export tree in DyldInfoCommand
|
||||
List<DyldInfoCommand> dyldInfoCommands = header.getLoadCommands(DyldInfoCommand.class);
|
||||
|
@ -480,6 +483,16 @@ public class MachoProgramBuilder {
|
|||
exports.addAll(dyldExportsTreeCommand.getExportTrie().getExports(e -> !e.isReExport()));
|
||||
}
|
||||
|
||||
if (exports.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SegmentCommand textSegment = header.getSegment(SegmentNames.SEG_TEXT);
|
||||
if (textSegment == null) {
|
||||
log.appendMsg("Cannot process exports, __TEXT segment not found!");
|
||||
return false;
|
||||
}
|
||||
|
||||
Address baseAddr = space.getAddress(textSegment.getVMaddress());
|
||||
for (ExportEntry export : exports) {
|
||||
String name = SymbolUtilities.replaceInvalidChars(export.getName(), true);
|
||||
|
|
Loading…
Reference in a new issue