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 java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.format.macho.MachException;
|
import ghidra.app.util.bin.format.macho.*;
|
||||||
import ghidra.app.util.bin.format.macho.MachHeader;
|
|
||||||
import ghidra.app.util.bin.format.macho.dyld.DyldCacheHeader;
|
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.dyld.DyldCacheMappingInfo;
|
||||||
import ghidra.app.util.bin.format.macho.threadcommand.ThreadCommand;
|
import ghidra.app.util.bin.format.macho.threadcommand.ThreadCommand;
|
||||||
|
@ -163,6 +162,10 @@ public class LoadCommandFactory {
|
||||||
* <p>
|
* <p>
|
||||||
* NOTE: This method assumes that the __LINKEDIT segment {@link LoadCommand} has already been
|
* NOTE: This method assumes that the __LINKEDIT segment {@link LoadCommand} has already been
|
||||||
* parsed.
|
* 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 reader The {@link BinaryReader} used to read the given Mach-O header
|
||||||
* @param header The {@link MachHeader Mach-O header}
|
* @param header The {@link MachHeader Mach-O header}
|
||||||
|
@ -175,6 +178,12 @@ public class LoadCommandFactory {
|
||||||
SplitDyldCache splitDyldCache) throws MachException {
|
SplitDyldCache splitDyldCache) throws MachException {
|
||||||
SegmentCommand linkEdit = header.getSegment(SegmentNames.SEG_LINKEDIT);
|
SegmentCommand linkEdit = header.getSegment(SegmentNames.SEG_LINKEDIT);
|
||||||
if (linkEdit == null) {
|
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");
|
throw new MachException("__LINKEDIT segment not found");
|
||||||
}
|
}
|
||||||
if (splitDyldCache == null) {
|
if (splitDyldCache == null) {
|
||||||
|
|
|
@ -394,7 +394,11 @@ public class MachoProgramBuilder {
|
||||||
*/
|
*/
|
||||||
protected void fixupProgramTree() throws Exception {
|
protected void fixupProgramTree() throws Exception {
|
||||||
ProgramModule rootModule = listing.getDefaultRootModule();
|
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) {
|
if (segment.getVMsize() == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -409,17 +413,21 @@ public class MachoProgramBuilder {
|
||||||
// Move original segment fragment into module and rename it. After we add new
|
// 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 fragments, it will represent the parts of the segment that weren't in any
|
||||||
// section.
|
// 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;
|
ProgramFragment segmentFragment = null;
|
||||||
for (Group group : rootModule.getChildren()) {
|
for (Group group : rootModule.getChildren()) {
|
||||||
if (group instanceof ProgramFragment fragment &&
|
if (group instanceof ProgramFragment fragment &&
|
||||||
fragment.getName().equals(segment.getSegmentName())) {
|
fragment.getName().equals(segmentName)) {
|
||||||
fragment.setName(noSectionsName);
|
fragment.setName(noSectionsName);
|
||||||
segmentFragment = fragment;
|
segmentFragment = fragment;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ProgramModule segmentModule = rootModule.createModule(segment.getSegmentName());
|
ProgramModule segmentModule = rootModule.createModule(segmentName);
|
||||||
segmentModule.reparent(noSectionsName, rootModule);
|
segmentModule.reparent(noSectionsName, rootModule);
|
||||||
|
|
||||||
// Add the sections, which will remove overlapped ranges from the segment fragment
|
// 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 {
|
protected boolean processExports(MachHeader header) throws Exception {
|
||||||
List<ExportEntry> exports = new ArrayList<>();
|
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
|
// Old way - export tree in DyldInfoCommand
|
||||||
List<DyldInfoCommand> dyldInfoCommands = header.getLoadCommands(DyldInfoCommand.class);
|
List<DyldInfoCommand> dyldInfoCommands = header.getLoadCommands(DyldInfoCommand.class);
|
||||||
|
@ -480,6 +483,16 @@ public class MachoProgramBuilder {
|
||||||
exports.addAll(dyldExportsTreeCommand.getExportTrie().getExports(e -> !e.isReExport()));
|
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());
|
Address baseAddr = space.getAddress(textSegment.getVMaddress());
|
||||||
for (ExportEntry export : exports) {
|
for (ExportEntry export : exports) {
|
||||||
String name = SymbolUtilities.replaceInvalidChars(export.getName(), true);
|
String name = SymbolUtilities.replaceInvalidChars(export.getName(), true);
|
||||||
|
|
Loading…
Reference in a new issue