mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-02-18 00:20:10 +00:00
Merge branch 'GP-2176_ryanmkurtz_dyld-iOS16' (Closes #4346,
Closes #4406)
This commit is contained in:
commit
61b135acd9
@ -36,7 +36,7 @@ import ghidra.util.task.TaskMonitor;
|
|||||||
/**
|
/**
|
||||||
* Represents a dyld_cache_accelerator_info structure.
|
* Represents a dyld_cache_accelerator_info structure.
|
||||||
*
|
*
|
||||||
* @see <a href="https://opensource.apple.com/source/dyld/dyld-852.2/dyld3/shared-cache/dyld_cache_format.h.auto.html">dyld3/shared-cache/dyld_cache_format.h</a>
|
* @see <a href="https://github.com/apple-oss-distributions/dyld/blob/main/cache-builder/dyld_cache_format.h">dyld_cache_format.h</a>
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class DyldCacheAccelerateInfo implements StructConverter {
|
public class DyldCacheAccelerateInfo implements StructConverter {
|
||||||
|
@ -26,7 +26,7 @@ import ghidra.util.exception.DuplicateNameException;
|
|||||||
/**
|
/**
|
||||||
* Represents a dyld_cache_accelerator_dof structure.
|
* Represents a dyld_cache_accelerator_dof structure.
|
||||||
*
|
*
|
||||||
* @see <a href="https://opensource.apple.com/source/dyld/dyld-852.2/dyld3/shared-cache/dyld_cache_format.h.auto.html">dyld3/shared-cache/dyld_cache_format.h</a>
|
* @see <a href="https://github.com/apple-oss-distributions/dyld/blob/main/cache-builder/dyld_cache_format.h">dyld_cache_format.h</a>
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class DyldCacheAcceleratorDof implements StructConverter {
|
public class DyldCacheAcceleratorDof implements StructConverter {
|
||||||
|
@ -26,7 +26,7 @@ import ghidra.util.exception.DuplicateNameException;
|
|||||||
/**
|
/**
|
||||||
* Represents a dyld_cache_accelerator_initializer structure.
|
* Represents a dyld_cache_accelerator_initializer structure.
|
||||||
*
|
*
|
||||||
* @see <a href="https://opensource.apple.com/source/dyld/dyld-852.2/dyld3/shared-cache/dyld_cache_format.h.auto.html">dyld3/shared-cache/dyld_cache_format.h</a>
|
* @see <a href="https://github.com/apple-oss-distributions/dyld/blob/main/cache-builder/dyld_cache_format.h">dyld_cache_format.h</a>
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class DyldCacheAcceleratorInitializer implements StructConverter {
|
public class DyldCacheAcceleratorInitializer implements StructConverter {
|
||||||
|
@ -27,6 +27,7 @@ import ghidra.program.model.data.*;
|
|||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.mem.MemoryBlock;
|
import ghidra.program.model.mem.MemoryBlock;
|
||||||
import ghidra.program.model.util.CodeUnitInsertionException;
|
import ghidra.program.model.util.CodeUnitInsertionException;
|
||||||
|
import ghidra.util.NumericUtilities;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
@ -34,7 +35,7 @@ import ghidra.util.task.TaskMonitor;
|
|||||||
/**
|
/**
|
||||||
* Represents a dyld_cache_header structure.
|
* Represents a dyld_cache_header structure.
|
||||||
*
|
*
|
||||||
* @see <a href="https://opensource.apple.com/source/dyld/dyld-852.2/dyld3/shared-cache/dyld_cache_format.h.auto.html">dyld3/shared-cache/dyld_cache_format.h</a>
|
* @see <a href="https://github.com/apple-oss-distributions/dyld/blob/main/cache-builder/dyld_cache_format.h">dyld_cache_format.h</a>
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class DyldCacheHeader implements StructConverter {
|
public class DyldCacheHeader implements StructConverter {
|
||||||
@ -42,8 +43,8 @@ public class DyldCacheHeader implements StructConverter {
|
|||||||
private byte[] magic;
|
private byte[] magic;
|
||||||
private int mappingOffset;
|
private int mappingOffset;
|
||||||
private int mappingCount;
|
private int mappingCount;
|
||||||
private int imagesOffset;
|
private int imagesOffsetOld;
|
||||||
private int imagesCount;
|
private int imagesCountOld;
|
||||||
private long dyldBaseAddress;
|
private long dyldBaseAddress;
|
||||||
private long codeSignatureOffset;
|
private long codeSignatureOffset;
|
||||||
private long codeSignatureSize;
|
private long codeSignatureSize;
|
||||||
@ -61,20 +62,20 @@ public class DyldCacheHeader implements StructConverter {
|
|||||||
private long imagesTextCount;
|
private long imagesTextCount;
|
||||||
private long patchInfoAddr;
|
private long patchInfoAddr;
|
||||||
private long patchInfoSize;
|
private long patchInfoSize;
|
||||||
private long otherImageGroupAddrUnused; // unused
|
private long otherImageGroupAddrUnused;
|
||||||
private long otherImageGroupSizeUnused; // unused
|
private long otherImageGroupSizeUnused;
|
||||||
private long progClosuresAddr;
|
private long progClosuresAddr;
|
||||||
private long progClosuresSize;
|
private long progClosuresSize;
|
||||||
private long progClosuresTrieAddr;
|
private long progClosuresTrieAddr;
|
||||||
private long progClosuresTrieSize;
|
private long progClosuresTrieSize;
|
||||||
private int platform;
|
private int platform;
|
||||||
private int dyld_info;
|
private int dyld_info;
|
||||||
private int formatVersion; // Extracted from dyld_info
|
private int formatVersion;
|
||||||
private boolean dylibsExpectedOnDisk; // Extracted from dyld_info
|
private boolean dylibsExpectedOnDisk;
|
||||||
private boolean simulator; // Extracted from dyld_info
|
private boolean simulator;
|
||||||
private boolean locallyBuiltCache; // Extracted from dyld_info
|
private boolean locallyBuiltCache;
|
||||||
private boolean builtFromChainedFixups; // Extracted from dyld_info
|
private boolean builtFromChainedFixups;
|
||||||
private int padding; // Extracted from dyld_info
|
private int padding;
|
||||||
private long sharedRegionStart;
|
private long sharedRegionStart;
|
||||||
private long sharedRegionSize;
|
private long sharedRegionSize;
|
||||||
private long maxSlide;
|
private long maxSlide;
|
||||||
@ -88,6 +89,26 @@ public class DyldCacheHeader implements StructConverter {
|
|||||||
private long otherTrieSize;
|
private long otherTrieSize;
|
||||||
private int mappingWithSlideOffset;
|
private int mappingWithSlideOffset;
|
||||||
private int mappingWithSlideCount;
|
private int mappingWithSlideCount;
|
||||||
|
private long dylibsPBLStateArrayAddrUnused;
|
||||||
|
private long dylibsPBLSetAddr;
|
||||||
|
private long programsPBLSetPoolAddr;
|
||||||
|
private long programsPBLSetPoolSize;
|
||||||
|
private long programTrieAddr;
|
||||||
|
private int programTrieSize;
|
||||||
|
private int osVersion;
|
||||||
|
private int altPlatform;
|
||||||
|
private int altOsVersion;
|
||||||
|
private long swiftOptsOffset;
|
||||||
|
private long swiftOptsSize;
|
||||||
|
private int subCacheArrayOffset;
|
||||||
|
private int subCacheArrayCount;
|
||||||
|
private byte[] symbolFileUUID;
|
||||||
|
private long rosettaReadOnlyAddr;
|
||||||
|
private long rosettaReadOnlySize;
|
||||||
|
private long rosettaReadWriteAddr;
|
||||||
|
private long rosettaReadWriteSize;
|
||||||
|
private int imagesOffset;
|
||||||
|
private int imagesCount;
|
||||||
|
|
||||||
private int headerType;
|
private int headerType;
|
||||||
private int headerSize;
|
private int headerSize;
|
||||||
@ -100,6 +121,7 @@ public class DyldCacheHeader implements StructConverter {
|
|||||||
private List<Long> branchPoolList;
|
private List<Long> branchPoolList;
|
||||||
private DyldCacheAccelerateInfo accelerateInfo;
|
private DyldCacheAccelerateInfo accelerateInfo;
|
||||||
private List<DyldCacheImageTextInfo> imageTextInfoList;
|
private List<DyldCacheImageTextInfo> imageTextInfoList;
|
||||||
|
private List<DyldSubcacheEntry> subcacheEntryList;
|
||||||
private DyldArchitecture architecture;
|
private DyldArchitecture architecture;
|
||||||
private List<DyldCacheMappingAndSlideInfo> cacheMappingAndSlideInfoList;
|
private List<DyldCacheMappingAndSlideInfo> cacheMappingAndSlideInfoList;
|
||||||
private MemoryBlock fileBlock;
|
private MemoryBlock fileBlock;
|
||||||
@ -119,8 +141,8 @@ public class DyldCacheHeader implements StructConverter {
|
|||||||
magic = reader.readNextByteArray(16);
|
magic = reader.readNextByteArray(16);
|
||||||
mappingOffset = reader.readNextInt();
|
mappingOffset = reader.readNextInt();
|
||||||
mappingCount = reader.readNextInt();
|
mappingCount = reader.readNextInt();
|
||||||
imagesOffset = reader.readNextInt();
|
imagesOffsetOld = reader.readNextInt();
|
||||||
imagesCount = reader.readNextInt();
|
imagesCountOld = reader.readNextInt();
|
||||||
dyldBaseAddress = reader.readNextLong();
|
dyldBaseAddress = reader.readNextLong();
|
||||||
|
|
||||||
// HEADER 2: https://opensource.apple.com/source/dyld/dyld-195.5/launch-cache/dyld_cache_format.h.auto.html
|
// HEADER 2: https://opensource.apple.com/source/dyld/dyld-195.5/launch-cache/dyld_cache_format.h.auto.html
|
||||||
@ -169,79 +191,144 @@ public class DyldCacheHeader implements StructConverter {
|
|||||||
headerType = 7;
|
headerType = 7;
|
||||||
}
|
}
|
||||||
if (reader.getPointerIndex() < mappingOffset) {
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
patchInfoAddr = reader.readNextLong(); // (unslid) address of dyld_cache_patch_info
|
patchInfoAddr = reader.readNextLong();
|
||||||
}
|
}
|
||||||
if (reader.getPointerIndex() < mappingOffset) {
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
patchInfoSize = reader.readNextLong(); // Size of all of the patch information pointed to via the dyld_cache_patch_info
|
patchInfoSize = reader.readNextLong();
|
||||||
}
|
}
|
||||||
if (reader.getPointerIndex() < mappingOffset) {
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
otherImageGroupAddrUnused = reader.readNextLong(); // unused
|
otherImageGroupAddrUnused = reader.readNextLong();
|
||||||
}
|
}
|
||||||
if (reader.getPointerIndex() < mappingOffset) {
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
otherImageGroupSizeUnused = reader.readNextLong(); // unused
|
otherImageGroupSizeUnused = reader.readNextLong();
|
||||||
}
|
}
|
||||||
if (reader.getPointerIndex() < mappingOffset) {
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
progClosuresAddr = reader.readNextLong(); // (unslid) address of list of program launch closures
|
progClosuresAddr = reader.readNextLong();
|
||||||
}
|
}
|
||||||
if (reader.getPointerIndex() < mappingOffset) {
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
progClosuresSize = reader.readNextLong(); // size of list of program launch closures
|
progClosuresSize = reader.readNextLong();
|
||||||
}
|
}
|
||||||
if (reader.getPointerIndex() < mappingOffset) {
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
progClosuresTrieAddr = reader.readNextLong(); // (unslid) address of trie of indexes into program launch closures
|
progClosuresTrieAddr = reader.readNextLong();
|
||||||
}
|
}
|
||||||
if (reader.getPointerIndex() < mappingOffset) {
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
progClosuresTrieSize = reader.readNextLong(); // size of trie of indexes into program launch closures
|
progClosuresTrieSize = reader.readNextLong();
|
||||||
}
|
}
|
||||||
if (reader.getPointerIndex() < mappingOffset) {
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
platform = reader.readNextInt(); // platform number (macOS=1, etc)
|
platform = reader.readNextInt();
|
||||||
}
|
}
|
||||||
if (reader.getPointerIndex() < mappingOffset) {
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
dyld_info = reader.readNextInt();
|
dyld_info = reader.readNextInt();
|
||||||
formatVersion = dyld_info & 0xff; // dyld3::closure::kFormatVersion
|
formatVersion = dyld_info & 0xff;
|
||||||
dylibsExpectedOnDisk = (dyld_info >>> 8 & 1) == 1; // dyld should expect the dylib exists on disk and to compare inode/mtime to see if cache is valid
|
dylibsExpectedOnDisk = (dyld_info >>> 8 & 1) == 1;
|
||||||
simulator = (dyld_info >>> 9 & 1) == 1; // for simulator of specified platform
|
simulator = (dyld_info >>> 9 & 1) == 1;
|
||||||
locallyBuiltCache = (dyld_info >> 10 & 1) == 1; // 0 for B&I built cache, 1 for locally built cache
|
locallyBuiltCache = (dyld_info >> 10 & 1) == 1;
|
||||||
builtFromChainedFixups = (dyld_info >> 11 & 1) == 1; // some dylib in cache was built using chained fixups, so patch tables must be used for overrides
|
builtFromChainedFixups = (dyld_info >> 11 & 1) == 1;
|
||||||
padding = (dyld_info >> 12) & 0xfffff; // TBD
|
padding = (dyld_info >> 12) & 0xfffff;
|
||||||
}
|
}
|
||||||
if (reader.getPointerIndex() < mappingOffset) {
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
sharedRegionStart = reader.readNextLong(); // base load address of cache if not slid
|
sharedRegionStart = reader.readNextLong();
|
||||||
}
|
}
|
||||||
if (reader.getPointerIndex() < mappingOffset) {
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
sharedRegionSize = reader.readNextLong(); // overall size of region cache can be mapped into
|
sharedRegionSize = reader.readNextLong();
|
||||||
}
|
}
|
||||||
if (reader.getPointerIndex() < mappingOffset) {
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
maxSlide = reader.readNextLong(); // runtime slide of cache can be between zero and this value
|
maxSlide = reader.readNextLong();
|
||||||
}
|
}
|
||||||
if (reader.getPointerIndex() < mappingOffset) {
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
dylibsImageArrayAddr = reader.readNextLong(); // (unslid) address of ImageArray for dylibs in this cache
|
dylibsImageArrayAddr = reader.readNextLong();
|
||||||
}
|
}
|
||||||
if (reader.getPointerIndex() < mappingOffset) {
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
dylibsImageArraySize = reader.readNextLong(); // size of ImageArray for dylibs in this cache
|
dylibsImageArraySize = reader.readNextLong();
|
||||||
}
|
}
|
||||||
if (reader.getPointerIndex() < mappingOffset) {
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
dylibsTrieAddr = reader.readNextLong(); // (unslid) address of trie of indexes of all cached dylibs
|
dylibsTrieAddr = reader.readNextLong();
|
||||||
}
|
}
|
||||||
if (reader.getPointerIndex() < mappingOffset) {
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
dylibsTrieSize = reader.readNextLong(); // size of trie of cached dylib paths
|
dylibsTrieSize = reader.readNextLong();
|
||||||
}
|
}
|
||||||
if (reader.getPointerIndex() < mappingOffset) {
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
otherImageArrayAddr = reader.readNextLong(); // (unslid) address of ImageArray for dylibs and bundles with dlopen closures
|
otherImageArrayAddr = reader.readNextLong();
|
||||||
}
|
}
|
||||||
if (reader.getPointerIndex() < mappingOffset) {
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
otherImageArraySize = reader.readNextLong(); // size of ImageArray for dylibs and bundles with dlopen closures
|
otherImageArraySize = reader.readNextLong();
|
||||||
}
|
}
|
||||||
if (reader.getPointerIndex() < mappingOffset) {
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
otherTrieAddr = reader.readNextLong(); // (unslid) address of trie of indexes of all dylibs and bundles with dlopen closures
|
otherTrieAddr = reader.readNextLong();
|
||||||
}
|
}
|
||||||
if (reader.getPointerIndex() < mappingOffset) {
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
otherTrieSize = reader.readNextLong(); // size of trie of dylibs and bundles with dlopen closures
|
otherTrieSize = reader.readNextLong();
|
||||||
}
|
}
|
||||||
if (reader.getPointerIndex() < mappingOffset) {
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
mappingWithSlideOffset = reader.readNextInt(); // file offset to first dyld_cache_mapping_and_slide_info
|
mappingWithSlideOffset = reader.readNextInt();
|
||||||
}
|
}
|
||||||
if (reader.getPointerIndex() < mappingOffset) {
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
mappingWithSlideCount = reader.readNextInt(); // number of dyld_cache_mapping_and_slide_info entries
|
mappingWithSlideCount = reader.readNextInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
// HEADER 8: https://github.com/apple-oss-distributions/dyld/blob/dyld-940/cache-builder/dyld_cache_format.h
|
||||||
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
|
headerType = 8;
|
||||||
|
}
|
||||||
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
|
dylibsPBLStateArrayAddrUnused = reader.readNextLong();
|
||||||
|
}
|
||||||
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
|
dylibsPBLSetAddr = reader.readNextLong();
|
||||||
|
}
|
||||||
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
|
programsPBLSetPoolAddr = reader.readNextLong();
|
||||||
|
}
|
||||||
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
|
programsPBLSetPoolSize = reader.readNextLong();
|
||||||
|
}
|
||||||
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
|
programTrieAddr = reader.readNextLong();
|
||||||
|
}
|
||||||
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
|
programTrieSize = reader.readNextInt();
|
||||||
|
}
|
||||||
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
|
osVersion = reader.readNextInt();
|
||||||
|
}
|
||||||
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
|
altPlatform = reader.readNextInt();
|
||||||
|
}
|
||||||
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
|
altOsVersion = reader.readNextInt();
|
||||||
|
}
|
||||||
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
|
swiftOptsOffset = reader.readNextLong();
|
||||||
|
}
|
||||||
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
|
swiftOptsSize = reader.readNextLong();
|
||||||
|
}
|
||||||
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
|
subCacheArrayOffset = reader.readNextInt();
|
||||||
|
}
|
||||||
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
|
subCacheArrayCount = reader.readNextInt();
|
||||||
|
}
|
||||||
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
|
symbolFileUUID = reader.readNextByteArray(16);
|
||||||
|
}
|
||||||
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
|
rosettaReadOnlyAddr = reader.readNextLong();
|
||||||
|
}
|
||||||
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
|
rosettaReadOnlySize = reader.readNextLong();
|
||||||
|
}
|
||||||
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
|
rosettaReadWriteAddr = reader.readNextLong();
|
||||||
|
}
|
||||||
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
|
rosettaReadWriteSize = reader.readNextLong();
|
||||||
|
}
|
||||||
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
|
imagesOffset = reader.readNextInt();
|
||||||
|
}
|
||||||
|
if (reader.getPointerIndex() < mappingOffset) {
|
||||||
|
imagesCount = reader.readNextInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
headerSize = (int) (reader.getPointerIndex() - startIndex);
|
headerSize = (int) (reader.getPointerIndex() - startIndex);
|
||||||
@ -252,9 +339,10 @@ public class DyldCacheHeader implements StructConverter {
|
|||||||
mappingInfoList = new ArrayList<>(mappingCount);
|
mappingInfoList = new ArrayList<>(mappingCount);
|
||||||
cacheMappingAndSlideInfoList = new ArrayList<>(mappingWithSlideCount);
|
cacheMappingAndSlideInfoList = new ArrayList<>(mappingWithSlideCount);
|
||||||
slideInfoList = new ArrayList<>();
|
slideInfoList = new ArrayList<>();
|
||||||
imageInfoList = new ArrayList<>(imagesCount);
|
imageInfoList = new ArrayList<>(imagesCountOld);
|
||||||
branchPoolList = new ArrayList<>(branchPoolsCount);
|
branchPoolList = new ArrayList<>(branchPoolsCount);
|
||||||
imageTextInfoList = new ArrayList<>();
|
imageTextInfoList = new ArrayList<>();
|
||||||
|
subcacheEntryList = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -280,6 +368,9 @@ public class DyldCacheHeader implements StructConverter {
|
|||||||
parseBranchPools(log, monitor);
|
parseBranchPools(log, monitor);
|
||||||
parseImageTextInfo(log, monitor);
|
parseImageTextInfo(log, monitor);
|
||||||
}
|
}
|
||||||
|
if (headerType >= 8) {
|
||||||
|
parseSubcaches(log, monitor);
|
||||||
|
}
|
||||||
parseCacheMappingSlideInfo(log, monitor);
|
parseCacheMappingSlideInfo(log, monitor);
|
||||||
if (hasSlideInfo()) {
|
if (hasSlideInfo()) {
|
||||||
parseSlideInfos(log, monitor);
|
parseSlideInfos(log, monitor);
|
||||||
@ -376,6 +467,9 @@ public class DyldCacheHeader implements StructConverter {
|
|||||||
markupAcceleratorInfo(program, space, monitor, log);
|
markupAcceleratorInfo(program, space, monitor, log);
|
||||||
markupImageTextInfo(program, space, monitor, log);
|
markupImageTextInfo(program, space, monitor, log);
|
||||||
}
|
}
|
||||||
|
if (headerType >= 8) {
|
||||||
|
markupSubcacheEntries(program, space, monitor, log);
|
||||||
|
}
|
||||||
if (mappingWithSlideOffset >= 0) {
|
if (mappingWithSlideOffset >= 0) {
|
||||||
markupCacheMappingSlideInfo(program, space, log, monitor);
|
markupCacheMappingSlideInfo(program, space, log, monitor);
|
||||||
}
|
}
|
||||||
@ -400,6 +494,24 @@ public class DyldCacheHeader implements StructConverter {
|
|||||||
return magic;
|
return magic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the UUID in {@link String} form
|
||||||
|
*
|
||||||
|
* @return The UUID in {@link String} form, or null if a UUID is not defined
|
||||||
|
*/
|
||||||
|
public String getUUID() {
|
||||||
|
return NumericUtilities.convertBytesToString(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the cache type
|
||||||
|
*
|
||||||
|
* @return The cache type
|
||||||
|
*/
|
||||||
|
public long getCacheType() {
|
||||||
|
return cacheType;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the {@link List} of {@link DyldCacheMappingInfo}s. Requires header to have been parsed.
|
* Gets the {@link List} of {@link DyldCacheMappingInfo}s. Requires header to have been parsed.
|
||||||
*
|
*
|
||||||
@ -415,7 +527,10 @@ public class DyldCacheHeader implements StructConverter {
|
|||||||
* @return The file offset to first {@link DyldCacheImageInfo}
|
* @return The file offset to first {@link DyldCacheImageInfo}
|
||||||
*/
|
*/
|
||||||
public int getImagesOffset() {
|
public int getImagesOffset() {
|
||||||
return imagesOffset;
|
if (imagesOffset != 0) {
|
||||||
|
return imagesOffset;
|
||||||
|
}
|
||||||
|
return imagesOffsetOld;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -424,41 +539,55 @@ public class DyldCacheHeader implements StructConverter {
|
|||||||
* @return The number of {@link DyldCacheImageInfo}s
|
* @return The number of {@link DyldCacheImageInfo}s
|
||||||
*/
|
*/
|
||||||
public int getImagesCount() {
|
public int getImagesCount() {
|
||||||
return imagesCount;
|
if (imagesOffset != 0) {
|
||||||
|
return imagesCount;
|
||||||
|
}
|
||||||
|
return imagesCountOld;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a {@link List} of {@link DyldCacheImage}s that are mapped in by this
|
* Generates a {@link List} of {@link DyldCacheImage}s that are mapped in by this
|
||||||
* {@link DyldCacheHeader}. Requires header to have been parsed.
|
* {@link DyldCacheHeader}. Requires header to have been parsed.
|
||||||
* <p>
|
* <p>
|
||||||
* NOTE: A "split" DYLD Cache header may declare an image, but that image may get loaded at an
|
* NOTE: A DYLD subcache header may declare an image, but that image may get loaded at an
|
||||||
* address defined by the memory map of a different split header. This method will only return
|
* address defined by the memory map of a different subcache header. This method will only
|
||||||
* the images that are mapped by "this" header's memory map.
|
* return the images that are mapped by "this" header's memory map.
|
||||||
*
|
|
||||||
*
|
*
|
||||||
* @return A {@link List} of {@link DyldCacheImage}s mapped by this {@link DyldCacheHeader}
|
* @return A {@link List} of {@link DyldCacheImage}s mapped by this {@link DyldCacheHeader}
|
||||||
*/
|
*/
|
||||||
public List<DyldCacheImage> getMappedImages() {
|
public List<DyldCacheImage> getMappedImages() {
|
||||||
|
// NOTE: A subcache will have an entry for every image, but not every image will be mapped
|
||||||
List<DyldCacheImage> images = new ArrayList<>();
|
List<DyldCacheImage> images = new ArrayList<>();
|
||||||
if (imageInfoList.size() > 0) {
|
for (DyldCacheImage imageInfo : imageInfoList) {
|
||||||
// The old, simple way
|
for (DyldCacheMappingInfo mappingInfo : mappingInfoList) {
|
||||||
images.addAll(imageInfoList);
|
if (mappingInfo.contains(imageInfo.getAddress())) {
|
||||||
}
|
images.add(imageInfo);
|
||||||
else {
|
break;
|
||||||
// The new, split file way. A split file will have an entry for every image, but
|
|
||||||
// not every image will be mapped.
|
|
||||||
for (DyldCacheImageTextInfo imageTextInfo : imageTextInfoList) {
|
|
||||||
for (DyldCacheMappingInfo mappingInfo : mappingInfoList) {
|
|
||||||
if (mappingInfo.contains(imageTextInfo.getAddress())) {
|
|
||||||
images.add(imageTextInfo);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return images;
|
return images;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the {@link List} of {@link DyldSubcacheEntry}s. Requires header to have been parsed.
|
||||||
|
*
|
||||||
|
* @return The {@link List} of {@link DyldSubcacheEntry}s
|
||||||
|
*/
|
||||||
|
public List<DyldSubcacheEntry> getSubcacheEntries() {
|
||||||
|
return subcacheEntryList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the symbol file UUID in {@link String} form
|
||||||
|
*
|
||||||
|
* @return The symbol file UUID in {@link String} form, or null if a symbol file UUID is not
|
||||||
|
* defined
|
||||||
|
*/
|
||||||
|
public String getSymbolFileUUID() {
|
||||||
|
return NumericUtilities.convertBytesToString(symbolFileUUID);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the {@link List} of {@link DyldCacheMappingAndSlideInfo}s. Requires header to have been parsed.
|
* Gets the {@link List} of {@link DyldCacheMappingAndSlideInfo}s. Requires header to have been parsed.
|
||||||
*
|
*
|
||||||
@ -515,8 +644,8 @@ public class DyldCacheHeader implements StructConverter {
|
|||||||
addHeaderField(struct, new ArrayDataType(ASCII, 16, 1), "magic","e.g. \"dyld_v0 i386\"");
|
addHeaderField(struct, new ArrayDataType(ASCII, 16, 1), "magic","e.g. \"dyld_v0 i386\"");
|
||||||
addHeaderField(struct, DWORD, "mappingOffset","file offset to first dyld_cache_mapping_info");
|
addHeaderField(struct, DWORD, "mappingOffset","file offset to first dyld_cache_mapping_info");
|
||||||
addHeaderField(struct, DWORD, "mappingCount", "number of dyld_cache_mapping_info entries");
|
addHeaderField(struct, DWORD, "mappingCount", "number of dyld_cache_mapping_info entries");
|
||||||
addHeaderField(struct, DWORD, "imagesOffset", "file offset to first dyld_cache_image_info");
|
addHeaderField(struct, DWORD, "imagesOffsetOld", "UNUSED: moved to imagesOffset to prevent older dsc_extarctors from crashing");
|
||||||
addHeaderField(struct, DWORD, "imagesCount", "number of dyld_cache_image_info entries");
|
addHeaderField(struct, DWORD, "imagesCountOld", "UNUSED: moved to imagesCount to prevent older dsc_extarctors from crashing");
|
||||||
addHeaderField(struct, QWORD, "dyldBaseAddress","base address of dyld when cache was built");
|
addHeaderField(struct, QWORD, "dyldBaseAddress","base address of dyld when cache was built");
|
||||||
|
|
||||||
// headerType 2
|
// headerType 2
|
||||||
@ -574,6 +703,28 @@ public class DyldCacheHeader implements StructConverter {
|
|||||||
addHeaderField(struct, DWORD, "mappingWithSlideOffset","file offset to first dyld_cache_mapping_and_slide_info");
|
addHeaderField(struct, DWORD, "mappingWithSlideOffset","file offset to first dyld_cache_mapping_and_slide_info");
|
||||||
addHeaderField(struct, DWORD, "mappingWithSlideCount","number of dyld_cache_mapping_and_slide_info entries");
|
addHeaderField(struct, DWORD, "mappingWithSlideCount","number of dyld_cache_mapping_and_slide_info entries");
|
||||||
|
|
||||||
|
// headerType 8
|
||||||
|
//
|
||||||
|
addHeaderField(struct, QWORD, "dylibsPBLStateArrayAddrUnused", "unused");
|
||||||
|
addHeaderField(struct, QWORD, "dylibsPBLSetAddr", "(unslid) address of PrebuiltLoaderSet of all cached dylibs");
|
||||||
|
addHeaderField(struct, QWORD, "programsPBLSetPoolAddr", "(unslid) address of pool of PrebuiltLoaderSet for each program ");
|
||||||
|
addHeaderField(struct, QWORD, "programsPBLSetPoolSize", "size of pool of PrebuiltLoaderSet for each program");
|
||||||
|
addHeaderField(struct, QWORD, "programTrieAddr", "(unslid) address of trie mapping program path to PrebuiltLoaderSet");
|
||||||
|
addHeaderField(struct, DWORD, "programTrieSize", "");
|
||||||
|
addHeaderField(struct, DWORD, "osVersion", "OS Version of dylibs in this cache for the main platform");
|
||||||
|
addHeaderField(struct, DWORD, "altPlatform", "e.g. iOSMac on macOS");
|
||||||
|
addHeaderField(struct, DWORD, "altOsVersion", "e.g. 14.0 for iOSMac");
|
||||||
|
addHeaderField(struct, QWORD, "swiftOptsOffset", "file offset to Swift optimizations header");
|
||||||
|
addHeaderField(struct, QWORD, "swiftOptsOffset", "size of Swift optimizations header");
|
||||||
|
addHeaderField(struct, DWORD, "subCacheArrayOffset", "file offset to first dyld_subcache_entry");
|
||||||
|
addHeaderField(struct, DWORD, "subCacheArrayCount", "number of subcache entries");
|
||||||
|
addHeaderField(struct, new ArrayDataType(BYTE, 16, 1), "symbolFileUUID","unique value for the shared cache file containing unmapped local symbols");
|
||||||
|
addHeaderField(struct, QWORD, "rosettaReadOnlyAddr", "(unslid) address of the start of where Rosetta can add read-only/executable data");
|
||||||
|
addHeaderField(struct, QWORD, "rosettaReadOnlySize", "maximum size of the Rosetta read-only/executable region");
|
||||||
|
addHeaderField(struct, QWORD, "rosettaReadWriteAddr", "(unslid) address of the start of where Rosetta can add read-write data");
|
||||||
|
addHeaderField(struct, QWORD, "rosettaReadWriteSize", "maximum size of the Rosetta read-write region");
|
||||||
|
addHeaderField(struct, DWORD, "imagesOffset", "file offset to first dyld_cache_image_info");
|
||||||
|
addHeaderField(struct, DWORD, "imagesCount", "number of dyld_cache_image_info entries");
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
|
||||||
struct.setCategoryPath(new CategoryPath(MachConstants.DATA_TYPE_CATEGORY));
|
struct.setCategoryPath(new CategoryPath(MachConstants.DATA_TYPE_CATEGORY));
|
||||||
@ -605,14 +756,16 @@ public class DyldCacheHeader implements StructConverter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void parseImageInfo(MessageLog log, TaskMonitor monitor) throws CancelledException {
|
private void parseImageInfo(MessageLog log, TaskMonitor monitor) throws CancelledException {
|
||||||
if (imagesOffset == 0) {
|
int offset = imagesOffset != 0 ? imagesOffset : imagesOffsetOld;
|
||||||
|
int count = imagesOffset != 0 ? imagesCount : imagesCountOld;
|
||||||
|
if (offset == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
monitor.setMessage("Parsing DYLD image info...");
|
monitor.setMessage("Parsing DYLD image info...");
|
||||||
monitor.initialize(imagesCount);
|
monitor.initialize(count);
|
||||||
try {
|
try {
|
||||||
reader.setPointerIndex(imagesOffset);
|
reader.setPointerIndex(offset);
|
||||||
for (int i = 0; i < imagesCount; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
imageInfoList.add(new DyldCacheImageInfo(reader));
|
imageInfoList.add(new DyldCacheImageInfo(reader));
|
||||||
monitor.checkCanceled();
|
monitor.checkCanceled();
|
||||||
monitor.incrementProgress(1);
|
monitor.incrementProgress(1);
|
||||||
@ -689,9 +842,29 @@ public class DyldCacheHeader implements StructConverter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void parseSubcaches(MessageLog log, TaskMonitor monitor) throws CancelledException {
|
||||||
|
if (subCacheArrayOffset == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
monitor.setMessage("Parsing DYLD subcaches...");
|
||||||
|
monitor.initialize(subCacheArrayCount);
|
||||||
|
try {
|
||||||
|
reader.setPointerIndex(subCacheArrayOffset);
|
||||||
|
for (int i = 0; i < subCacheArrayCount; ++i) {
|
||||||
|
subcacheEntryList.add(new DyldSubcacheEntry(reader, cacheType));
|
||||||
|
monitor.checkCanceled();
|
||||||
|
monitor.incrementProgress(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
log.appendMsg(DyldCacheHeader.class.getSimpleName(),
|
||||||
|
"Failed to parse dyld_subcache_entry.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void parseAcceleratorInfo(Program program, AddressSpace space, MessageLog log,
|
private void parseAcceleratorInfo(Program program, AddressSpace space, MessageLog log,
|
||||||
TaskMonitor monitor) throws CancelledException {
|
TaskMonitor monitor) throws CancelledException {
|
||||||
if (accelerateInfoAddr == 0) {
|
if (accelerateInfoAddr == 0 || cacheType >= 2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
monitor.setMessage("Parsing DYLD accelerateor info...");
|
monitor.setMessage("Parsing DYLD accelerateor info...");
|
||||||
@ -770,7 +943,8 @@ public class DyldCacheHeader implements StructConverter {
|
|||||||
monitor.setMessage("Marking up DYLD image info...");
|
monitor.setMessage("Marking up DYLD image info...");
|
||||||
monitor.initialize(imageInfoList.size());
|
monitor.initialize(imageInfoList.size());
|
||||||
try {
|
try {
|
||||||
Address addr = fileOffsetToAddr(imagesOffset, program, space);
|
Address addr = fileOffsetToAddr(imagesOffset != 0 ? imagesOffset : imagesOffsetOld,
|
||||||
|
program, space);
|
||||||
for (DyldCacheImageInfo imageInfo : imageInfoList) {
|
for (DyldCacheImageInfo imageInfo : imageInfoList) {
|
||||||
Data d = DataUtilities.createData(program, addr, imageInfo.toDataType(), -1, false,
|
Data d = DataUtilities.createData(program, addr, imageInfo.toDataType(), -1, false,
|
||||||
DataUtilities.ClearDataMode.CHECK_FOR_SPACE);
|
DataUtilities.ClearDataMode.CHECK_FOR_SPACE);
|
||||||
@ -868,7 +1042,7 @@ public class DyldCacheHeader implements StructConverter {
|
|||||||
monitor.setMessage("Marking up DYLD accelerator info...");
|
monitor.setMessage("Marking up DYLD accelerator info...");
|
||||||
monitor.initialize(1);
|
monitor.initialize(1);
|
||||||
try {
|
try {
|
||||||
if (accelerateInfo != null) {
|
if (accelerateInfo != null && cacheType < 2) {
|
||||||
Address addr = space.getAddress(accelerateInfoAddr);
|
Address addr = space.getAddress(accelerateInfoAddr);
|
||||||
DataUtilities.createData(program, addr, accelerateInfo.toDataType(), -1, false,
|
DataUtilities.createData(program, addr, accelerateInfo.toDataType(), -1, false,
|
||||||
DataUtilities.ClearDataMode.CHECK_FOR_SPACE);
|
DataUtilities.ClearDataMode.CHECK_FOR_SPACE);
|
||||||
@ -904,6 +1078,26 @@ public class DyldCacheHeader implements StructConverter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void markupSubcacheEntries(Program program, AddressSpace space, TaskMonitor monitor,
|
||||||
|
MessageLog log) throws CancelledException {
|
||||||
|
monitor.setMessage("Marking up DYLD subcache entries...");
|
||||||
|
monitor.initialize(subcacheEntryList.size());
|
||||||
|
try {
|
||||||
|
Address addr = fileOffsetToAddr(subCacheArrayOffset, program, space);
|
||||||
|
for (DyldSubcacheEntry subcacheEntry : subcacheEntryList) {
|
||||||
|
Data d = DataUtilities.createData(program, addr, subcacheEntry.toDataType(), -1,
|
||||||
|
false, DataUtilities.ClearDataMode.CHECK_FOR_SPACE);
|
||||||
|
addr = addr.add(d.getLength());
|
||||||
|
monitor.checkCanceled();
|
||||||
|
monitor.incrementProgress(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (CodeUnitInsertionException | DuplicateNameException | IOException e) {
|
||||||
|
log.appendMsg(DyldCacheHeader.class.getSimpleName(),
|
||||||
|
"Failed to markup dyld_subcache_entry.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the {@link MemoryBlock} associated with this header's FILE block.
|
* Sets the {@link MemoryBlock} associated with this header's FILE block.
|
||||||
*
|
*
|
||||||
@ -976,4 +1170,13 @@ public class DyldCacheHeader implements StructConverter {
|
|||||||
public long unslidLoadAddress() {
|
public long unslidLoadAddress() {
|
||||||
return mappingInfoList.get(0).getAddress();
|
return mappingInfoList.get(0).getAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks to see whether or not this is a subcache
|
||||||
|
*
|
||||||
|
* @return True if this is a subcache; otherwise, false if its a base cache
|
||||||
|
*/
|
||||||
|
public boolean isSubcache() {
|
||||||
|
return headerType >= 8 && subCacheArrayCount == 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ import ghidra.util.exception.DuplicateNameException;
|
|||||||
/**
|
/**
|
||||||
* Represents a dyld_cache_image_info structure.
|
* Represents a dyld_cache_image_info structure.
|
||||||
*
|
*
|
||||||
* @see <a href="https://opensource.apple.com/source/dyld/dyld-852.2/dyld3/shared-cache/dyld_cache_format.h.auto.html">dyld3/shared-cache/dyld_cache_format.h</a>
|
* @see <a href="https://github.com/apple-oss-distributions/dyld/blob/main/cache-builder/dyld_cache_format.h">dyld_cache_format.h</a>
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class DyldCacheImageInfo implements DyldCacheImage, StructConverter {
|
public class DyldCacheImageInfo implements DyldCacheImage, StructConverter {
|
||||||
|
@ -26,7 +26,7 @@ import ghidra.util.exception.DuplicateNameException;
|
|||||||
/**
|
/**
|
||||||
* Represents a dyld_cache_image_info_extra structure.
|
* Represents a dyld_cache_image_info_extra structure.
|
||||||
*
|
*
|
||||||
* @see <a href="https://opensource.apple.com/source/dyld/dyld-852.2/dyld3/shared-cache/dyld_cache_format.h.auto.html">dyld3/shared-cache/dyld_cache_format.h</a>
|
* @see <a href="https://github.com/apple-oss-distributions/dyld/blob/main/cache-builder/dyld_cache_format.h">dyld_cache_format.h</a>
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class DyldCacheImageInfoExtra implements StructConverter {
|
public class DyldCacheImageInfoExtra implements StructConverter {
|
||||||
|
@ -26,7 +26,7 @@ import ghidra.util.exception.DuplicateNameException;
|
|||||||
/**
|
/**
|
||||||
* Represents a dyld_cache_image_text_info structure.
|
* Represents a dyld_cache_image_text_info structure.
|
||||||
*
|
*
|
||||||
* @see <a href="https://opensource.apple.com/source/dyld/dyld-852.2/dyld3/shared-cache/dyld_cache_format.h.auto.html">dyld3/shared-cache/dyld_cache_format.h</a>
|
* @see <a href="https://github.com/apple-oss-distributions/dyld/blob/main/cache-builder/dyld_cache_format.h">dyld_cache_format.h</a>
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class DyldCacheImageTextInfo implements DyldCacheImage, StructConverter {
|
public class DyldCacheImageTextInfo implements DyldCacheImage, StructConverter {
|
||||||
|
@ -26,7 +26,7 @@ import ghidra.util.exception.DuplicateNameException;
|
|||||||
/**
|
/**
|
||||||
* Represents a dyld_cache_local_symbols_entry structure.
|
* Represents a dyld_cache_local_symbols_entry structure.
|
||||||
*
|
*
|
||||||
* @see <a href="https://opensource.apple.com/source/dyld/dyld-852.2/dyld3/shared-cache/dyld_cache_format.h.auto.html">dyld3/shared-cache/dyld_cache_format.h</a>
|
* @see <a href="https://github.com/apple-oss-distributions/dyld/blob/main/cache-builder/dyld_cache_format.h">dyld_cache_format.h</a>
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class DyldCacheLocalSymbolsEntry implements StructConverter {
|
public class DyldCacheLocalSymbolsEntry implements StructConverter {
|
||||||
|
@ -38,7 +38,7 @@ import ghidra.util.task.TaskMonitor;
|
|||||||
/**
|
/**
|
||||||
* Represents a dyld_cache_local_symbols_info structure.
|
* Represents a dyld_cache_local_symbols_info structure.
|
||||||
*
|
*
|
||||||
* @see <a href="https://opensource.apple.com/source/dyld/dyld-852.2/dyld3/shared-cache/dyld_cache_format.h.auto.html">dyld3/shared-cache/dyld_cache_format.h</a>
|
* @see <a href="https://github.com/apple-oss-distributions/dyld/blob/main/cache-builder/dyld_cache_format.h">dyld_cache_format.h</a>
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class DyldCacheLocalSymbolsInfo implements StructConverter {
|
public class DyldCacheLocalSymbolsInfo implements StructConverter {
|
||||||
|
@ -27,7 +27,7 @@ import ghidra.util.exception.DuplicateNameException;
|
|||||||
/**
|
/**
|
||||||
* Represents a dyld_cache_mapping_and_slide_info structure.
|
* Represents a dyld_cache_mapping_and_slide_info structure.
|
||||||
*
|
*
|
||||||
* @see <a href="https://opensource.apple.com/source/dyld/dyld-852.2/dyld3/shared-cache/dyld_cache_format.h.auto.html">dyld3/shared-cache/dyld_cache_format.h</a>
|
* @see <a href="https://github.com/apple-oss-distributions/dyld/blob/main/cache-builder/dyld_cache_format.h">dyld_cache_format.h</a>
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class DyldCacheMappingAndSlideInfo implements StructConverter {
|
public class DyldCacheMappingAndSlideInfo implements StructConverter {
|
||||||
|
@ -27,7 +27,7 @@ import ghidra.util.exception.DuplicateNameException;
|
|||||||
/**
|
/**
|
||||||
* Represents a dyld_cache_mapping_info structure.
|
* Represents a dyld_cache_mapping_info structure.
|
||||||
*
|
*
|
||||||
* @see <a href="https://opensource.apple.com/source/dyld/dyld-852.2/dyld3/shared-cache/dyld_cache_format.h.auto.html">dyld3/shared-cache/dyld_cache_format.h</a>
|
* @see <a href="https://github.com/apple-oss-distributions/dyld/blob/main/cache-builder/dyld_cache_format.h">dyld_cache_format.h</a>
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class DyldCacheMappingInfo implements StructConverter {
|
public class DyldCacheMappingInfo implements StructConverter {
|
||||||
|
@ -26,7 +26,7 @@ import ghidra.util.exception.DuplicateNameException;
|
|||||||
/**
|
/**
|
||||||
* Represents a dyld_cache_range_entry structure.
|
* Represents a dyld_cache_range_entry structure.
|
||||||
*
|
*
|
||||||
* @see <a href="https://opensource.apple.com/source/dyld/dyld-852.2/dyld3/shared-cache/dyld_cache_format.h.auto.html">dyld3/shared-cache/dyld_cache_format.h</a>
|
* @see <a href="https://github.com/apple-oss-distributions/dyld/blob/main/cache-builder/dyld_cache_format.h">dyld_cache_format.h</a>
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class DyldCacheRangeEntry implements StructConverter {
|
public class DyldCacheRangeEntry implements StructConverter {
|
||||||
|
@ -34,7 +34,7 @@ import ghidra.util.task.TaskMonitor;
|
|||||||
/**
|
/**
|
||||||
* Represents a dyld_cache_slide_info structure.
|
* Represents a dyld_cache_slide_info structure.
|
||||||
*
|
*
|
||||||
* @see <a href="https://opensource.apple.com/source/dyld/dyld-852.2/dyld3/shared-cache/dyld_cache_format.h.auto.html">dyld3/shared-cache/dyld_cache_format.h</a>
|
* @see <a href="https://github.com/apple-oss-distributions/dyld/blob/main/cache-builder/dyld_cache_format.h">dyld_cache_format.h</a>
|
||||||
*/
|
*/
|
||||||
public class DyldCacheSlideInfo1 extends DyldCacheSlideInfoCommon {
|
public class DyldCacheSlideInfo1 extends DyldCacheSlideInfoCommon {
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ import ghidra.util.task.TaskMonitor;
|
|||||||
/**
|
/**
|
||||||
* Represents a dyld_cache_slide_info2 structure.
|
* Represents a dyld_cache_slide_info2 structure.
|
||||||
*
|
*
|
||||||
* @see <a href="https://opensource.apple.com/source/dyld/dyld-852.2/dyld3/shared-cache/dyld_cache_format.h.auto.html">dyld3/shared-cache/dyld_cache_format.h</a>
|
* @see <a href="https://github.com/apple-oss-distributions/dyld/blob/main/cache-builder/dyld_cache_format.h">dyld_cache_format.h</a>
|
||||||
*/
|
*/
|
||||||
public class DyldCacheSlideInfo2 extends DyldCacheSlideInfoCommon {
|
public class DyldCacheSlideInfo2 extends DyldCacheSlideInfoCommon {
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ import ghidra.util.task.TaskMonitor;
|
|||||||
/**
|
/**
|
||||||
* Represents a dyld_cache_slide_info3 structure.
|
* Represents a dyld_cache_slide_info3 structure.
|
||||||
*
|
*
|
||||||
* @see <a href="https://opensource.apple.com/source/dyld/dyld-852.2/dyld3/shared-cache/dyld_cache_format.h.auto.html">dyld3/shared-cache/dyld_cache_format.h</a>
|
* @see <a href="https://github.com/apple-oss-distributions/dyld/blob/main/cache-builder/dyld_cache_format.h">dyld_cache_format.h</a>
|
||||||
*/
|
*/
|
||||||
public class DyldCacheSlideInfo3 extends DyldCacheSlideInfoCommon {
|
public class DyldCacheSlideInfo3 extends DyldCacheSlideInfoCommon {
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ import ghidra.util.task.TaskMonitor;
|
|||||||
/**
|
/**
|
||||||
* Represents a dyld_cache_slide_info3 structure.
|
* Represents a dyld_cache_slide_info3 structure.
|
||||||
*
|
*
|
||||||
* @see <a href="https://opensource.apple.com/source/dyld/dyld-852.2/dyld3/shared-cache/dyld_cache_format.h.auto.html">dyld3/shared-cache/dyld_cache_format.h</a>
|
* @see <a href="https://github.com/apple-oss-distributions/dyld/blob/main/cache-builder/dyld_cache_format.h">dyld_cache_format.h</a>
|
||||||
*/
|
*/
|
||||||
public class DyldCacheSlideInfo4 extends DyldCacheSlideInfoCommon {
|
public class DyldCacheSlideInfo4 extends DyldCacheSlideInfoCommon {
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ import ghidra.util.task.TaskMonitor;
|
|||||||
* The intent is for the the full dyld_cache_slide_info structures to extend this and add their
|
* The intent is for the the full dyld_cache_slide_info structures to extend this and add their
|
||||||
* specific parts.
|
* specific parts.
|
||||||
*
|
*
|
||||||
* @see <a href="https://opensource.apple.com/source/dyld/dyld-852.2/dyld3/shared-cache/dyld_cache_format.h.auto.html">dyld3/shared-cache/dyld_cache_format.h</a>
|
* @see <a href="https://github.com/apple-oss-distributions/dyld/blob/main/cache-builder/dyld_cache_format.h">dyld_cache_format.h</a>
|
||||||
*/
|
*/
|
||||||
public abstract class DyldCacheSlideInfoCommon implements StructConverter {
|
public abstract class DyldCacheSlideInfoCommon implements StructConverter {
|
||||||
|
|
||||||
|
@ -0,0 +1,110 @@
|
|||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package ghidra.app.util.bin.format.macho.dyld;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
|
import ghidra.app.util.bin.StructConverter;
|
||||||
|
import ghidra.app.util.bin.format.macho.MachConstants;
|
||||||
|
import ghidra.program.model.data.*;
|
||||||
|
import ghidra.util.NumericUtilities;
|
||||||
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a dyld_subcache_entry structure.
|
||||||
|
*
|
||||||
|
* @see <a href="https://github.com/apple-oss-distributions/dyld/blob/main/cache-builder/dyld_cache_format.h">dyld_cache_format.h</a>
|
||||||
|
*/
|
||||||
|
public class DyldSubcacheEntry implements StructConverter {
|
||||||
|
|
||||||
|
private byte[] uuid;
|
||||||
|
private long cacheVMOffset;
|
||||||
|
private byte[] cacheExtension;
|
||||||
|
|
||||||
|
private long cacheType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link DyldSubcacheEntry}.
|
||||||
|
*
|
||||||
|
* @param reader A {@link BinaryReader} positioned at the start of a DYLD subCache entry
|
||||||
|
* @param cacheType The cache type value
|
||||||
|
* @throws IOException if there was an IO-related problem creating the DYLD subCache entry
|
||||||
|
*/
|
||||||
|
public DyldSubcacheEntry(BinaryReader reader, long cacheType) throws IOException {
|
||||||
|
this.cacheType = cacheType;
|
||||||
|
|
||||||
|
uuid = reader.readNextByteArray(16);
|
||||||
|
cacheVMOffset = reader.readNextLong();
|
||||||
|
if (supportsCacheExtension()) {
|
||||||
|
cacheExtension = reader.readNextByteArray(32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the UUID of the subCache file
|
||||||
|
*
|
||||||
|
* @return The UUID of the subCache file
|
||||||
|
*/
|
||||||
|
public String getUuid() {
|
||||||
|
return NumericUtilities.convertBytesToString(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the offset of this subCache from the main cache base address
|
||||||
|
*
|
||||||
|
* @return The offset of this subCache from the main cache base address
|
||||||
|
*/
|
||||||
|
public long getCacheVMOffset() {
|
||||||
|
return cacheVMOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the extension of this subCache, if it is known
|
||||||
|
*
|
||||||
|
* @return The extension of this subCache, or null if it is not known
|
||||||
|
*/
|
||||||
|
public String getCacheExtension() {
|
||||||
|
if (cacheExtension == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new String(cacheExtension, StandardCharsets.US_ASCII);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
|
StructureDataType struct = new StructureDataType("dyld_subcache_entry", 0);
|
||||||
|
struct.add(new ArrayDataType(BYTE, 16, 1), "uuid", "The UUID of the subCache file");
|
||||||
|
struct.add(QWORD, "cacheVMOffset",
|
||||||
|
"The offset of this subcache from the main cache base address");
|
||||||
|
if (supportsCacheExtension()) {
|
||||||
|
struct.add(new ArrayDataType(ASCII, 32, 1), "cacheExtension",
|
||||||
|
"The extension of the subCache file");
|
||||||
|
}
|
||||||
|
struct.setCategoryPath(new CategoryPath(MachConstants.DATA_TYPE_CATEGORY));
|
||||||
|
return struct;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks to see if the subCache extension is known
|
||||||
|
*
|
||||||
|
* @return True if the subCache extension is known; otherwise, false
|
||||||
|
*/
|
||||||
|
private boolean supportsCacheExtension() {
|
||||||
|
return cacheType >= 2;
|
||||||
|
}
|
||||||
|
}
|
@ -42,22 +42,12 @@ public class DyldCacheLoader extends AbstractLibrarySupportLoader {
|
|||||||
/** Default value for loader option to process symbols */
|
/** Default value for loader option to process symbols */
|
||||||
static final boolean PROCESS_SYMBOLS_OPTION_DEFAULT = true;
|
static final boolean PROCESS_SYMBOLS_OPTION_DEFAULT = true;
|
||||||
|
|
||||||
/** Loader option to create memory blocks for DYLIB sections */
|
|
||||||
static final String CREATE_DYLIB_SECTIONS_OPTION_NAME = "Create DYLIB section memory blocks";
|
|
||||||
|
|
||||||
/** Loader option to add relocation entries for chained fixups */
|
/** Loader option to add relocation entries for chained fixups */
|
||||||
static final String ADD_CHAINED_FIXUPS_RELOCATIONS_OPTION_NAME =
|
static final String ADD_CHAINED_FIXUPS_RELOCATIONS_OPTION_NAME =
|
||||||
"Add relocation entries for chained fixups";
|
"Add relocation entries for chained fixups";
|
||||||
|
|
||||||
/** Default value for loader option add chained fixups relocation entries */
|
/** Default value for loader option to add chained fixups relocation entries */
|
||||||
static final boolean ADD_CHAINED_FIXUPS_RELOCATIONS_OPTION_DEFAULT = false;
|
static final boolean ADD_CHAINED_FIXUPS_RELOCATIONS_OPTION_DEFAULT = false;
|
||||||
|
|
||||||
/** Loader option to combine split DYLD Cache files (.1, .2, .symbol, etc) into one program */
|
|
||||||
static final String COMBINE_SPLIT_FILES_OPTION_NAME =
|
|
||||||
"Auto import and combine split DYLD Cache files";
|
|
||||||
|
|
||||||
/** Default value for loader option add relocation entries */
|
|
||||||
static final boolean COMBINE_SPLIT_FILES_OPTION_DEFAULT = true;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<LoadSpec> findSupportedLoadSpecs(ByteProvider provider) throws IOException {
|
public Collection<LoadSpec> findSupportedLoadSpecs(ByteProvider provider) throws IOException {
|
||||||
@ -69,6 +59,9 @@ public class DyldCacheLoader extends AbstractLibrarySupportLoader {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
DyldCacheHeader header = new DyldCacheHeader(new BinaryReader(provider, true));
|
DyldCacheHeader header = new DyldCacheHeader(new BinaryReader(provider, true));
|
||||||
|
if (header.isSubcache()) {
|
||||||
|
return loadSpecs;
|
||||||
|
}
|
||||||
DyldArchitecture architecture = header.getArchitecture();
|
DyldArchitecture architecture = header.getArchitecture();
|
||||||
if (architecture != null) {
|
if (architecture != null) {
|
||||||
List<QueryResult> results =
|
List<QueryResult> results =
|
||||||
@ -94,8 +87,8 @@ public class DyldCacheLoader extends AbstractLibrarySupportLoader {
|
|||||||
try {
|
try {
|
||||||
DyldCacheProgramBuilder.buildProgram(program, provider,
|
DyldCacheProgramBuilder.buildProgram(program, provider,
|
||||||
MemoryBlockUtils.createFileBytes(program, provider, monitor),
|
MemoryBlockUtils.createFileBytes(program, provider, monitor),
|
||||||
shouldProcessSymbols(options), shouldAddChainedFixupsRelocations(options),
|
shouldProcessSymbols(options), shouldAddChainedFixupsRelocations(options), log,
|
||||||
shouldCombineSplitFiles(options), log, monitor);
|
monitor);
|
||||||
}
|
}
|
||||||
catch (CancelledException e) {
|
catch (CancelledException e) {
|
||||||
return;
|
return;
|
||||||
@ -116,8 +109,6 @@ public class DyldCacheLoader extends AbstractLibrarySupportLoader {
|
|||||||
list.add(new Option(ADD_CHAINED_FIXUPS_RELOCATIONS_OPTION_NAME,
|
list.add(new Option(ADD_CHAINED_FIXUPS_RELOCATIONS_OPTION_NAME,
|
||||||
ADD_CHAINED_FIXUPS_RELOCATIONS_OPTION_DEFAULT, Boolean.class,
|
ADD_CHAINED_FIXUPS_RELOCATIONS_OPTION_DEFAULT, Boolean.class,
|
||||||
Loader.COMMAND_LINE_ARG_PREFIX + "-addChainedFixupsRelocations"));
|
Loader.COMMAND_LINE_ARG_PREFIX + "-addChainedFixupsRelocations"));
|
||||||
list.add(new Option(COMBINE_SPLIT_FILES_OPTION_NAME, COMBINE_SPLIT_FILES_OPTION_DEFAULT,
|
|
||||||
Boolean.class, Loader.COMMAND_LINE_ARG_PREFIX + "-combineSplitFiles"));
|
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
@ -132,11 +123,6 @@ public class DyldCacheLoader extends AbstractLibrarySupportLoader {
|
|||||||
ADD_CHAINED_FIXUPS_RELOCATIONS_OPTION_DEFAULT);
|
ADD_CHAINED_FIXUPS_RELOCATIONS_OPTION_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldCombineSplitFiles(List<Option> options) {
|
|
||||||
return OptionUtils.getOption(COMBINE_SPLIT_FILES_OPTION_NAME, options,
|
|
||||||
COMBINE_SPLIT_FILES_OPTION_DEFAULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return DYLD_CACHE_NAME;
|
return DYLD_CACHE_NAME;
|
||||||
|
@ -45,7 +45,6 @@ import ghidra.util.task.TaskMonitor;
|
|||||||
public class DyldCacheProgramBuilder extends MachoProgramBuilder {
|
public class DyldCacheProgramBuilder extends MachoProgramBuilder {
|
||||||
|
|
||||||
private boolean shouldProcessSymbols;
|
private boolean shouldProcessSymbols;
|
||||||
private boolean shouldCombineSplitFiles;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link DyldCacheProgramBuilder} based on the given information.
|
* Creates a new {@link DyldCacheProgramBuilder} based on the given information.
|
||||||
@ -56,17 +55,15 @@ public class DyldCacheProgramBuilder extends MachoProgramBuilder {
|
|||||||
* @param shouldProcessSymbols True if symbols should be processed; otherwise, false
|
* @param shouldProcessSymbols True if symbols should be processed; otherwise, false
|
||||||
* @param shouldAddChainedFixupsRelocations True if relocations should be added for chained
|
* @param shouldAddChainedFixupsRelocations True if relocations should be added for chained
|
||||||
* fixups; otherwise, false
|
* fixups; otherwise, false
|
||||||
* @param shouldCombineSplitFiles True if split DYLD Cache files should be automatically
|
|
||||||
* imported and combined into 1 program; otherwise, false
|
* imported and combined into 1 program; otherwise, false
|
||||||
* @param log The log
|
* @param log The log
|
||||||
* @param monitor A cancelable task monitor
|
* @param monitor A cancelable task monitor
|
||||||
*/
|
*/
|
||||||
protected DyldCacheProgramBuilder(Program program, ByteProvider provider, FileBytes fileBytes,
|
protected DyldCacheProgramBuilder(Program program, ByteProvider provider, FileBytes fileBytes,
|
||||||
boolean shouldProcessSymbols, boolean shouldAddChainedFixupsRelocations,
|
boolean shouldProcessSymbols, boolean shouldAddChainedFixupsRelocations, MessageLog log,
|
||||||
boolean shouldCombineSplitFiles, MessageLog log, TaskMonitor monitor) {
|
TaskMonitor monitor) {
|
||||||
super(program, provider, fileBytes, shouldAddChainedFixupsRelocations, log, monitor);
|
super(program, provider, fileBytes, shouldAddChainedFixupsRelocations, log, monitor);
|
||||||
this.shouldProcessSymbols = shouldProcessSymbols;
|
this.shouldProcessSymbols = shouldProcessSymbols;
|
||||||
this.shouldCombineSplitFiles = shouldCombineSplitFiles;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -78,26 +75,24 @@ public class DyldCacheProgramBuilder extends MachoProgramBuilder {
|
|||||||
* @param shouldProcessSymbols True if symbols should be processed; otherwise, false
|
* @param shouldProcessSymbols True if symbols should be processed; otherwise, false
|
||||||
* @param shouldAddChainedFixupsRelocations True if relocations should be added for chained
|
* @param shouldAddChainedFixupsRelocations True if relocations should be added for chained
|
||||||
* fixups; otherwise, false
|
* fixups; otherwise, false
|
||||||
* @param shouldCombineSplitFiles True if split DYLD Cache files should be automatically
|
|
||||||
* imported and combined into 1 program; otherwise, false
|
|
||||||
* @param log The log
|
* @param log The log
|
||||||
* @param monitor A cancelable task monitor
|
* @param monitor A cancelable task monitor
|
||||||
* @throws Exception if a problem occurs
|
* @throws Exception if a problem occurs
|
||||||
*/
|
*/
|
||||||
public static void buildProgram(Program program, ByteProvider provider, FileBytes fileBytes,
|
public static void buildProgram(Program program, ByteProvider provider, FileBytes fileBytes,
|
||||||
boolean shouldProcessSymbols, boolean shouldAddChainedFixupsRelocations,
|
boolean shouldProcessSymbols, boolean shouldAddChainedFixupsRelocations, MessageLog log,
|
||||||
boolean shouldCombineSplitFiles, MessageLog log, TaskMonitor monitor) throws Exception {
|
TaskMonitor monitor) throws Exception {
|
||||||
DyldCacheProgramBuilder dyldCacheProgramBuilder = new DyldCacheProgramBuilder(program,
|
DyldCacheProgramBuilder dyldCacheProgramBuilder = new DyldCacheProgramBuilder(program,
|
||||||
provider, fileBytes, shouldProcessSymbols, shouldAddChainedFixupsRelocations,
|
provider, fileBytes, shouldProcessSymbols, shouldAddChainedFixupsRelocations, log,
|
||||||
shouldCombineSplitFiles, log, monitor);
|
monitor);
|
||||||
dyldCacheProgramBuilder.build();
|
dyldCacheProgramBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void build() throws Exception {
|
protected void build() throws Exception {
|
||||||
|
|
||||||
try (SplitDyldCache splitDyldCache = new SplitDyldCache(provider, shouldProcessSymbols,
|
try (SplitDyldCache splitDyldCache =
|
||||||
shouldCombineSplitFiles, log, monitor)) {
|
new SplitDyldCache(provider, shouldProcessSymbols, log, monitor)) {
|
||||||
|
|
||||||
// Set image base
|
// Set image base
|
||||||
setDyldCacheImageBase(splitDyldCache.getDyldCacheHeader(0));
|
setDyldCacheImageBase(splitDyldCache.getDyldCacheHeader(0));
|
||||||
@ -108,8 +103,9 @@ public class DyldCacheProgramBuilder extends MachoProgramBuilder {
|
|||||||
for (int i = 0; i < splitDyldCache.size(); i++) {
|
for (int i = 0; i < splitDyldCache.size(); i++) {
|
||||||
DyldCacheHeader header = splitDyldCache.getDyldCacheHeader(i);
|
DyldCacheHeader header = splitDyldCache.getDyldCacheHeader(i);
|
||||||
ByteProvider bp = splitDyldCache.getProvider(i);
|
ByteProvider bp = splitDyldCache.getProvider(i);
|
||||||
|
String name = splitDyldCache.getName(i);
|
||||||
|
|
||||||
processDyldCacheMemoryBlocks(header, bp);
|
processDyldCacheMemoryBlocks(header, name, bp);
|
||||||
|
|
||||||
if (header.getLocalSymbolsInfo() != null) {
|
if (header.getLocalSymbolsInfo() != null) {
|
||||||
localSymbolsPresent = true;
|
localSymbolsPresent = true;
|
||||||
@ -147,26 +143,36 @@ public class DyldCacheProgramBuilder extends MachoProgramBuilder {
|
|||||||
* Processes the DYLD Cache's memory mappings and creates memory blocks for them.
|
* Processes the DYLD Cache's memory mappings and creates memory blocks for them.
|
||||||
*
|
*
|
||||||
* @param dyldCacheHeader The {@link DyldCacheHeader}
|
* @param dyldCacheHeader The {@link DyldCacheHeader}
|
||||||
|
* @param name The name of the DYLD Cache
|
||||||
* @param bp The corresponding {@link ByteProvider}
|
* @param bp The corresponding {@link ByteProvider}
|
||||||
* @throws Exception if there was a problem creating the memory blocks
|
* @throws Exception if there was a problem creating the memory blocks
|
||||||
*/
|
*/
|
||||||
private void processDyldCacheMemoryBlocks(DyldCacheHeader dyldCacheHeader, ByteProvider bp)
|
private void processDyldCacheMemoryBlocks(DyldCacheHeader dyldCacheHeader, String name,
|
||||||
throws Exception {
|
ByteProvider bp) throws Exception {
|
||||||
List<DyldCacheMappingInfo> mappingInfos = dyldCacheHeader.getMappingInfos();
|
List<DyldCacheMappingInfo> mappingInfos = dyldCacheHeader.getMappingInfos();
|
||||||
monitor.setMessage("Processing DYLD mapped memory blocks...");
|
monitor.setMessage("Processing DYLD mapped memory blocks...");
|
||||||
monitor.initialize(mappingInfos.size());
|
monitor.initialize(mappingInfos.size());
|
||||||
FileBytes fb = MemoryBlockUtils.createFileBytes(program, bp, monitor);
|
FileBytes fb = MemoryBlockUtils.createFileBytes(program, bp, monitor);
|
||||||
long endOfMappedOffset = 0;
|
long endOfMappedOffset = 0;
|
||||||
|
boolean bookmarkSet = false;
|
||||||
for (DyldCacheMappingInfo mappingInfo : mappingInfos) {
|
for (DyldCacheMappingInfo mappingInfo : mappingInfos) {
|
||||||
long offset = mappingInfo.getFileOffset();
|
long offset = mappingInfo.getFileOffset();
|
||||||
long size = mappingInfo.getSize();
|
long size = mappingInfo.getSize();
|
||||||
MemoryBlockUtils.createInitializedBlock(program, false, "DYLD",
|
MemoryBlock block = MemoryBlockUtils.createInitializedBlock(program, false, "DYLD",
|
||||||
space.getAddress(mappingInfo.getAddress()), fb, offset, size, "", "",
|
space.getAddress(mappingInfo.getAddress()), fb, offset, size, "", "",
|
||||||
mappingInfo.isRead(), mappingInfo.isWrite(), mappingInfo.isExecute(), log);
|
mappingInfo.isRead(), mappingInfo.isWrite(), mappingInfo.isExecute(), log);
|
||||||
|
|
||||||
if (offset + size > endOfMappedOffset) {
|
if (offset + size > endOfMappedOffset) {
|
||||||
endOfMappedOffset = offset + size;
|
endOfMappedOffset = offset + size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!bookmarkSet) {
|
||||||
|
program.getBookmarkManager()
|
||||||
|
.setBookmark(block.getStart(), BookmarkType.INFO, "Dyld Cache Header",
|
||||||
|
name + " - " + dyldCacheHeader.getUUID());
|
||||||
|
bookmarkSet = true;
|
||||||
|
}
|
||||||
|
|
||||||
monitor.checkCanceled();
|
monitor.checkCanceled();
|
||||||
monitor.incrementProgress(1);
|
monitor.incrementProgress(1);
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,7 @@ import java.util.*;
|
|||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.ByteProvider;
|
import ghidra.app.util.bin.ByteProvider;
|
||||||
import ghidra.app.util.bin.format.macho.dyld.DyldArchitecture;
|
import ghidra.app.util.bin.format.macho.dyld.*;
|
||||||
import ghidra.app.util.bin.format.macho.dyld.DyldCacheHeader;
|
|
||||||
import ghidra.app.util.importer.MessageLog;
|
import ghidra.app.util.importer.MessageLog;
|
||||||
import ghidra.formats.gfilesystem.*;
|
import ghidra.formats.gfilesystem.*;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
@ -98,13 +97,14 @@ public class DyldCacheUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to store a "split" DYLD Cache, which is split across several files (base file, .1, .2,
|
* Class to store a "split" DYLD Cache, which is split across several subcache files (base file,
|
||||||
* .symbols, etc).
|
* .1, .2, .symbols, etc).
|
||||||
*/
|
*/
|
||||||
public static class SplitDyldCache implements Closeable {
|
public static class SplitDyldCache implements Closeable {
|
||||||
|
|
||||||
private List<ByteProvider> providers = new ArrayList<>();
|
private List<ByteProvider> providers = new ArrayList<>();
|
||||||
private List<DyldCacheHeader> headers = new ArrayList<>();
|
private List<DyldCacheHeader> headers = new ArrayList<>();
|
||||||
|
private List<String> names = new ArrayList<>();
|
||||||
private FileSystemService fsService;
|
private FileSystemService fsService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -112,15 +112,13 @@ public class DyldCacheUtils {
|
|||||||
*
|
*
|
||||||
* @param baseProvider The {@link ByteProvider} of the "base" DYLD Cache file
|
* @param baseProvider The {@link ByteProvider} of the "base" DYLD Cache file
|
||||||
* @param shouldProcessSymbols True if symbols should be processed; otherwise, false
|
* @param shouldProcessSymbols True if symbols should be processed; otherwise, false
|
||||||
* @param shouldCombineSplitFiles True if split DYLD Cache files should be automatically
|
|
||||||
* @param log The log
|
* @param log The log
|
||||||
* @param monitor A cancelable task monitor
|
* @param monitor A cancelable task monitor
|
||||||
* @throws IOException If there was an IO-related issue with processing the split DYLD Cache
|
* @throws IOException If there was an IO-related issue with processing the split DYLD Cache
|
||||||
* @throws CancelledException If the user canceled the operation
|
* @throws CancelledException If the user canceled the operation
|
||||||
*/
|
*/
|
||||||
public SplitDyldCache(ByteProvider baseProvider, boolean shouldProcessSymbols,
|
public SplitDyldCache(ByteProvider baseProvider, boolean shouldProcessSymbols,
|
||||||
boolean shouldCombineSplitFiles, MessageLog log, TaskMonitor monitor)
|
MessageLog log, TaskMonitor monitor) throws IOException, CancelledException {
|
||||||
throws IOException, CancelledException {
|
|
||||||
|
|
||||||
// Setup "base" DYLD Cache
|
// Setup "base" DYLD Cache
|
||||||
monitor.setMessage("Parsing " + baseProvider.getName() + " headers...");
|
monitor.setMessage("Parsing " + baseProvider.getName() + " headers...");
|
||||||
@ -128,12 +126,14 @@ public class DyldCacheUtils {
|
|||||||
DyldCacheHeader baseHeader = new DyldCacheHeader(new BinaryReader(baseProvider, true));
|
DyldCacheHeader baseHeader = new DyldCacheHeader(new BinaryReader(baseProvider, true));
|
||||||
baseHeader.parseFromFile(shouldProcessSymbols, log, monitor);
|
baseHeader.parseFromFile(shouldProcessSymbols, log, monitor);
|
||||||
headers.add(baseHeader);
|
headers.add(baseHeader);
|
||||||
|
names.add(baseProvider.getName());
|
||||||
|
|
||||||
// Setup additional "split" DYLD Caches (if applicable)
|
// Setup additional "split" DYLD subcaches (if applicable)
|
||||||
if (!shouldCombineSplitFiles) {
|
if (baseHeader.getSubcacheEntries().size() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fsService = FileSystemService.getInstance();
|
fsService = FileSystemService.getInstance();
|
||||||
|
Map<String, FSRL> uuidToFileMap = new HashMap<>();
|
||||||
for (FSRL splitFSRL : findSplitDyldCacheFiles(baseProvider.getFSRL(), monitor)) {
|
for (FSRL splitFSRL : findSplitDyldCacheFiles(baseProvider.getFSRL(), monitor)) {
|
||||||
monitor.setMessage("Parsing " + splitFSRL.getName() + " headers...");
|
monitor.setMessage("Parsing " + splitFSRL.getName() + " headers...");
|
||||||
ByteProvider splitProvider = fsService.getByteProvider(splitFSRL, false, monitor);
|
ByteProvider splitProvider = fsService.getByteProvider(splitFSRL, false, monitor);
|
||||||
@ -146,7 +146,33 @@ public class DyldCacheUtils {
|
|||||||
new DyldCacheHeader(new BinaryReader(splitProvider, true));
|
new DyldCacheHeader(new BinaryReader(splitProvider, true));
|
||||||
splitHeader.parseFromFile(shouldProcessSymbols, log, monitor);
|
splitHeader.parseFromFile(shouldProcessSymbols, log, monitor);
|
||||||
headers.add(splitHeader);
|
headers.add(splitHeader);
|
||||||
log.appendMsg("Including split DYLD: " + splitProvider.getName());
|
names.add(splitFSRL.getName());
|
||||||
|
uuidToFileMap.put(splitHeader.getUUID(), splitFSRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the subcaches
|
||||||
|
for (DyldSubcacheEntry subcacheEntry : baseHeader.getSubcacheEntries()) {
|
||||||
|
String uuid = subcacheEntry.getUuid();
|
||||||
|
String extension = subcacheEntry.getCacheExtension();
|
||||||
|
FSRL fsrl = uuidToFileMap.get(uuid);
|
||||||
|
if (fsrl != null) {
|
||||||
|
log.appendMsg("Including subcache: " + fsrl.getName() + " - " + uuid);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log.appendMsg(String.format("Missing subcache: %s%s",
|
||||||
|
extension != null ? (baseProvider.getName() + "." + extension + " - ") : "",
|
||||||
|
uuid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String symbolUUID = baseHeader.getSymbolFileUUID();
|
||||||
|
FSRL symbolFSRL = uuidToFileMap.get(symbolUUID);
|
||||||
|
if (symbolFSRL != null) {
|
||||||
|
log.appendMsg(
|
||||||
|
"Including symbols subcache: " + symbolFSRL.getName() + " - " + symbolUUID);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log.appendMsg(String.format("Missing symbols subcache: %s%s",
|
||||||
|
baseProvider.getName() + ".symbols - " + symbolUUID));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,6 +196,16 @@ public class DyldCacheUtils {
|
|||||||
return headers.get(i);
|
return headers.get(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the i'th {@link String name} in the split DYLD Cache
|
||||||
|
*
|
||||||
|
* @param i The index of the {@link String name} to get
|
||||||
|
* @return The i'th {@link String name} in the split DYLD Cache
|
||||||
|
*/
|
||||||
|
public String getName(int i) {
|
||||||
|
return names.get(i);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the number of split DYLD Cache files
|
* Gets the number of split DYLD Cache files
|
||||||
*
|
*
|
||||||
|
@ -279,10 +279,6 @@ public class MachoProgramBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
log.appendMsg(
|
|
||||||
"Skipping segment: " + segment.getSegmentName() + " (" + source + ")");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create memory blocks for sections. They will be in the segments we just created, so the
|
// Create memory blocks for sections. They will be in the segments we just created, so the
|
||||||
@ -304,10 +300,6 @@ public class MachoProgramBuilder {
|
|||||||
section.getAddress(), section.getSize(), source));
|
section.getAddress(), section.getSize(), source));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
log.appendMsg("Skipping section: " + section.getSegmentName() + "." +
|
|
||||||
section.getSectionName() + " (" + source + ")");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,8 @@
|
|||||||
package ghidra.file.formats.ios.dyldcache;
|
package ghidra.file.formats.ios.dyldcache;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import ghidra.app.util.bin.*;
|
import ghidra.app.util.bin.*;
|
||||||
import ghidra.app.util.bin.format.macho.*;
|
import ghidra.app.util.bin.format.macho.*;
|
||||||
@ -84,7 +85,7 @@ public class DyldCacheDylibExtractor {
|
|||||||
TaskMonitor monitor) throws MachException, IOException {
|
TaskMonitor monitor) throws MachException, IOException {
|
||||||
ByteProvider provider = splitDyldCache.getProvider(index);
|
ByteProvider provider = splitDyldCache.getProvider(index);
|
||||||
this.reader = new BinaryReader(provider, true);
|
this.reader = new BinaryReader(provider, true);
|
||||||
this.header = new MachHeader(provider, dylibOffset, false).parse();
|
this.header = new MachHeader(provider, dylibOffset, false).parse(splitDyldCache);
|
||||||
this.monitor = monitor;
|
this.monitor = monitor;
|
||||||
|
|
||||||
// Keep track of each segment's file offset in the DYLD cache.
|
// Keep track of each segment's file offset in the DYLD cache.
|
||||||
|
@ -18,6 +18,7 @@ package ghidra.file.formats.ios.dyldcache;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.ByteProvider;
|
import ghidra.app.util.bin.ByteProvider;
|
||||||
import ghidra.app.util.bin.format.macho.MachException;
|
import ghidra.app.util.bin.format.macho.MachException;
|
||||||
import ghidra.app.util.bin.format.macho.dyld.DyldCacheHeader;
|
import ghidra.app.util.bin.format.macho.dyld.DyldCacheHeader;
|
||||||
@ -95,7 +96,16 @@ public class DyldCacheFileSystem extends GFileSystemBase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValid(TaskMonitor monitor) throws IOException {
|
public boolean isValid(TaskMonitor monitor) throws IOException {
|
||||||
return DyldCacheUtils.isDyldCache(provider);
|
if (!DyldCacheUtils.isDyldCache(provider)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
DyldCacheHeader header = new DyldCacheHeader(new BinaryReader(provider, true));
|
||||||
|
return !header.isSubcache();
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -103,7 +113,7 @@ public class DyldCacheFileSystem extends GFileSystemBase {
|
|||||||
MessageLog log = new MessageLog();
|
MessageLog log = new MessageLog();
|
||||||
monitor.setMessage("Opening DYLD cache...");
|
monitor.setMessage("Opening DYLD cache...");
|
||||||
|
|
||||||
splitDyldCache = new SplitDyldCache(provider, false, true, log, monitor);
|
splitDyldCache = new SplitDyldCache(provider, false, log, monitor);
|
||||||
for (int i = 0; i < splitDyldCache.size(); i++) {
|
for (int i = 0; i < splitDyldCache.size(); i++) {
|
||||||
DyldCacheHeader header = splitDyldCache.getDyldCacheHeader(i);
|
DyldCacheHeader header = splitDyldCache.getDyldCacheHeader(i);
|
||||||
monitor.setMessage("Find files...");
|
monitor.setMessage("Find files...");
|
||||||
|
Loading…
Reference in New Issue
Block a user