GP-1574: Delaying fixing DyldCacheFileSystem slide pointers until the

first provider is requested
This commit is contained in:
Ryan Kurtz 2023-07-17 11:10:32 -04:00
parent befa5aa772
commit 3576ae9424
2 changed files with 45 additions and 22 deletions

View file

@ -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<DyldCacheSlideInfoCommon, List<DyldCacheSlideFixup>> getSlideFixups(
SplitDyldCache splitDyldCache, TaskMonitor monitor)
throws CancelledException, IOException {
Map<DyldCacheSlideInfoCommon, List<DyldCacheSlideFixup>> 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<DyldCacheSlideFixup> 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

View file

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