Merge remote-tracking branch 'origin/GP-2699_ryanmkurtz-mh_object-fix'

This commit is contained in:
Ryan Kurtz 2022-10-17 10:47:29 -04:00
commit 56b8bc9471
2 changed files with 33 additions and 11 deletions

View file

@ -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) {

View file

@ -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);