diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoLoader.java index c8c27e8834..964a9066d0 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoLoader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoLoader.java @@ -90,7 +90,8 @@ public class MachoLoader extends AbstractLibrarySupportLoader { // A Mach-O file may contain PRELINK information. If so, we use a special // program builder that knows how to deal with it. - if (MachoPrelinkUtils.isMachoPrelink(provider, true, monitor)) { + if (MachoPrelinkUtils.isMachoPrelink(provider, monitor) || + MachoPrelinkUtils.isMachoFileset(provider)) { MachoPrelinkProgramBuilder.buildProgram(program, provider, fileBytes, log, monitor); } else { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoPrelinkUtils.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoPrelinkUtils.java index a330d956a6..9053927eb7 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoPrelinkUtils.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoPrelinkUtils.java @@ -37,23 +37,22 @@ import ghidra.util.task.TaskMonitor; public class MachoPrelinkUtils { /** - * Check to see if the given {@link ByteProvider} is a Mach-O PRELINK binary + * Check to see if the given {@link ByteProvider} is a Mach-O PRELINK binary. + *

+ * NOTE: This method will return false if the binary is a Mach-O file set. * * @param provider The {@link ByteProvider} to check - * @param allowFileset True if Mach-O file sets should be considered a PRELINK binary; - * otherwise, false * @param monitor A monitor * @return True if the given {@link ByteProvider} is a Mach-O PRELINK binary; otherwise, false */ - public static boolean isMachoPrelink(ByteProvider provider, boolean allowFileset, - TaskMonitor monitor) { + public static boolean isMachoPrelink(ByteProvider provider, TaskMonitor monitor) { try { MachHeader header = new MachHeader(provider); boolean hasPrelinkSegment = new MachHeader(provider).parseSegments() .stream() .anyMatch(segment -> segment.getSegmentName().startsWith("__PRELINK")); boolean hasFileSet = header.parseAndCheck(LoadCommandTypes.LC_FILESET_ENTRY); - return hasPrelinkSegment && allowFileset && hasFileSet; + return hasPrelinkSegment && !hasFileSet; } catch (MachException | IOException e) { // Assume it's not a Mach-O PRELINK...fall through @@ -61,6 +60,22 @@ public class MachoPrelinkUtils { return false; } + /** + * Check to see if the given {@link ByteProvider} is a Mach-O file set + * + * @param provider The {@link ByteProvider} to check + * @return True if the given {@link ByteProvider} is a Mach-O file set; otherwise, false + */ + public static boolean isMachoFileset(ByteProvider provider) { + try { + return new MachHeader(provider).parseAndCheck(LoadCommandTypes.LC_FILESET_ENTRY); + } + catch (MachException | IOException e) { + // Assume it's not a Mach-O file set...fall through + } + return false; + } + /** * Parses the provider looking for PRELINK XML. * diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/fileset/MachoFileSetFileSystemFactory.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/fileset/MachoFileSetFileSystemFactory.java index 44bdfed874..7b9c76035a 100644 --- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/fileset/MachoFileSetFileSystemFactory.java +++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/fileset/MachoFileSetFileSystemFactory.java @@ -18,9 +18,7 @@ package ghidra.file.formats.ios.fileset; import java.io.IOException; import ghidra.app.util.bin.ByteProvider; -import ghidra.app.util.bin.format.macho.MachException; -import ghidra.app.util.bin.format.macho.MachHeader; -import ghidra.app.util.bin.format.macho.commands.LoadCommandTypes; +import ghidra.app.util.opinion.MachoPrelinkUtils; import ghidra.formats.gfilesystem.FSRLRoot; import ghidra.formats.gfilesystem.FileSystemService; import ghidra.formats.gfilesystem.factory.GFileSystemFactoryByteProvider; @@ -46,12 +44,6 @@ public class MachoFileSetFileSystemFactory implements @Override public boolean probe(ByteProvider byteProvider, FileSystemService fsService, TaskMonitor monitor) throws IOException, CancelledException { - try { - return new MachHeader(byteProvider).parseAndCheck(LoadCommandTypes.LC_FILESET_ENTRY); - } - catch (MachException e) { - // Assume it's not a Mach-O...fall through - } - return false; + return MachoPrelinkUtils.isMachoFileset(byteProvider); } } diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/prelink/MachoPrelinkFileSystem.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/prelink/MachoPrelinkFileSystem.java index 63e7dbcca5..5f4d4c7ab9 100644 --- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/prelink/MachoPrelinkFileSystem.java +++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/prelink/MachoPrelinkFileSystem.java @@ -75,7 +75,7 @@ public class MachoPrelinkFileSystem extends GFileSystemBase implements GFileSyst @Override public boolean isValid(TaskMonitor monitor) throws IOException { - return MachoPrelinkUtils.isMachoPrelink(provider, false, monitor); + return MachoPrelinkUtils.isMachoPrelink(provider, monitor); } @Override