diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dyldcache/DyldCacheDylibExtractor.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dyldcache/DyldCacheDylibExtractor.java index 9e840fb205..b64ecf2aff 100644 --- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dyldcache/DyldCacheDylibExtractor.java +++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dyldcache/DyldCacheDylibExtractor.java @@ -23,6 +23,7 @@ import ghidra.app.util.bin.*; import ghidra.app.util.bin.format.macho.*; import ghidra.app.util.bin.format.macho.commands.*; import ghidra.app.util.bin.format.macho.dyld.*; +import ghidra.app.util.importer.MessageLog; import ghidra.app.util.opinion.DyldCacheUtils.SplitDyldCache; import ghidra.formats.gfilesystem.FSRL; import ghidra.util.*; @@ -60,6 +61,42 @@ public class DyldCacheDylibExtractor { return packedSegments.getByteProvider(fsrl); } + /** + * Gets a {@link Map} of {DyldCacheSlideInfoCommon}s to their corresponding + * {@link DyldCacheSlideFixup}s + * + * @param splitDyldCache The {@link SplitDyldCache} + * @param monitor {@link TaskMonitor} + * @return A {@link Map} of {DyldCacheSlideInfoCommon}s to their corresponding + * {@link DyldCacheSlideFixup}s + * @throws CancelledException If the user cancelled the operation + * @throws IOException If there was an IO-related issue with getting the slide fixups + */ + public static Map> getSlideFixups( + SplitDyldCache splitDyldCache, TaskMonitor monitor) + throws CancelledException, IOException { + Map> slideFixupMap = new HashMap<>(); + MessageLog log = new MessageLog(); + + for (int i = 0; i < splitDyldCache.size(); i++) { + DyldCacheHeader header = splitDyldCache.getDyldCacheHeader(i); + ByteProvider bp = splitDyldCache.getProvider(i); + DyldArchitecture arch = header.getArchitecture(); + for (DyldCacheSlideInfoCommon slideInfo : header.getSlideInfos()) { + try (ByteProvider wrapper = new ByteProviderWrapper(bp, + slideInfo.getMappingFileOffset(), slideInfo.getMappingSize())) { + BinaryReader wrapperReader = + new BinaryReader(wrapper, !arch.getEndianness().isBigEndian()); + List fixups = slideInfo.getSlideFixups(wrapperReader, + arch.is64bit() ? 8 : 4, log, monitor); + slideFixupMap.put(slideInfo, fixups); + } + } + } + + return slideFixupMap; + } + /** * A packed DYLIB that was once living inside of a DYLD shared cache. The DYLIB is said to be * packed because its segment file bytes, which were not adjacent in its containing DYLD, are diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dyldcache/DyldCacheFileSystem.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dyldcache/DyldCacheFileSystem.java index d1c016edc9..a7f1d7395e 100644 --- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dyldcache/DyldCacheFileSystem.java +++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dyldcache/DyldCacheFileSystem.java @@ -18,7 +18,8 @@ package ghidra.file.formats.ios.dyldcache; import java.io.IOException; import java.util.*; -import ghidra.app.util.bin.*; +import ghidra.app.util.bin.BinaryReader; +import ghidra.app.util.bin.ByteProvider; import ghidra.app.util.bin.format.macho.MachException; import ghidra.app.util.bin.format.macho.dyld.*; import ghidra.app.util.importer.MessageLog; @@ -45,7 +46,7 @@ public class DyldCacheFileSystem extends GFileSystemBase { @Override public void close() throws IOException { - slideFixupMap.clear(); + slideFixupMap = null; addrMap.clear(); indexMap.clear(); splitDyldCache.close(); @@ -62,6 +63,11 @@ public class DyldCacheFileSystem extends GFileSystemBase { int index = indexMap.get(file); long machHeaderStartIndexInProvider = addr - splitDyldCache.getDyldCacheHeader(index).getBaseAddress(); + + if (slideFixupMap == null) { + slideFixupMap = DyldCacheDylibExtractor.getSlideFixups(splitDyldCache, monitor); + } + try { return DyldCacheDylibExtractor.extractDylib(machHeaderStartIndexInProvider, splitDyldCache, index, slideFixupMap, file.getFSRL(), monitor); @@ -128,26 +134,6 @@ public class DyldCacheFileSystem extends GFileSystemBase { monitor.incrementProgress(1); } } - - // Get slide fixups - slideFixupMap = new HashMap<>(); - for (int i = 0; i < splitDyldCache.size(); i++) { - DyldCacheHeader header = splitDyldCache.getDyldCacheHeader(i); - ByteProvider bp = splitDyldCache.getProvider(i); - DyldArchitecture arch = header.getArchitecture(); - for (DyldCacheSlideInfoCommon slideInfo : header.getSlideInfos()) { - try (ByteProvider wrapper = new ByteProviderWrapper(bp, - slideInfo.getMappingFileOffset(), slideInfo.getMappingSize())) { - BinaryReader wrapperReader =new BinaryReader(wrapper, !arch.getEndianness().isBigEndian()); - List fixups = slideInfo.getSlideFixups(wrapperReader, - arch.is64bit() ? 8 : 4, log, monitor); - slideFixupMap.put(slideInfo, fixups); - } - catch (IOException e) { - throw new IOException(e); - } - } - } } private void storeFile(GFile file, Long addr, Integer index) {