diff --git a/librz/bin/format/mach0/dyldcache.c b/librz/bin/format/mach0/dyldcache.c index 27e5cae527..1b967b5780 100644 --- a/librz/bin/format/mach0/dyldcache.c +++ b/librz/bin/format/mach0/dyldcache.c @@ -16,7 +16,10 @@ static RzDyldLocSym *rz_dyld_locsym_new(RzDyldCache *cache); * \param magic zero-terminated string from the beginning of some file */ RZ_API bool rz_dyldcache_check_magic(const char *magic) { - return !strcmp(magic, "dyld_v1 arm64") || !strcmp(magic, "dyld_v1 arm64e") || !strcmp(magic, "dyld_v1 x86_64") || !strcmp(magic, "dyld_v1 x86_64h"); + return !strncmp(magic, "dyld_v1 arm64", 16) || + !strncmp(magic, "dyld_v1 arm64e", 16) || + !strncmp(magic, "dyld_v1 x86_64", 16) || + !strncmp(magic, "dyld_v1 x86_64h", 16); } static ut64 va2pa(uint64_t addr, ut32 n_maps, cache_map_t *maps, RzBuffer *cache_buf, ut64 slide, ut32 *offset, ut32 *left) { @@ -49,33 +52,173 @@ static void free_bin(RzDyldBinImage *bin) { free(bin); } -static cache_hdr_t *read_cache_header(RzBuffer *cache_buf, ut64 offset) { +static RzDyldCacheHeader *read_cache_header(RzBuffer *cache_buf, ut64 offset) { if (!cache_buf) { return NULL; } - cache_hdr_t *hdr = RZ_NEW0(cache_hdr_t); + RzDyldCacheHeader *hdr = RZ_NEW0(RzDyldCacheHeader); if (!hdr) { return NULL; } - ut64 size = sizeof(cache_hdr_t); - if (rz_buf_fread_at(cache_buf, offset, (ut8 *)hdr, "16c4i7l16clii4l", 1) != size) { - free(hdr); - return NULL; - } - if (!rz_dyldcache_check_magic(hdr->magic)) { - free(hdr); - return NULL; + ut64 cur = offset; + if (!rz_buf_read_offset(cache_buf, &cur, (ut8 *)hdr->magic, sizeof(hdr->magic)) || + !rz_dyldcache_check_magic(hdr->magic) || + !rz_buf_read_le32_offset(cache_buf, &cur, &hdr->mappingOffset) || + !rz_buf_read_le32_offset(cache_buf, &cur, &hdr->mappingCount) || + !rz_buf_read_le32_offset(cache_buf, &cur, &hdr->imagesOffset) || + !rz_buf_read_le32_offset(cache_buf, &cur, &hdr->imagesCount) || + !rz_buf_read_le64_offset(cache_buf, &cur, &hdr->dyldBaseAddress) || + !rz_buf_read_le64_offset(cache_buf, &cur, &hdr->codeSignatureOffset) || + !rz_buf_read_le64_offset(cache_buf, &cur, &hdr->codeSignatureSize) || + !rz_buf_read_le64_offset(cache_buf, &cur, &hdr->slideInfoOffset) || + !rz_buf_read_le64_offset(cache_buf, &cur, &hdr->slideInfoSize) || + !rz_buf_read_le64_offset(cache_buf, &cur, &hdr->localSymbolsOffset) || + !rz_buf_read_le64_offset(cache_buf, &cur, &hdr->localSymbolsSize) || + !rz_buf_read_offset(cache_buf, &cur, hdr->uuid, sizeof(hdr->uuid)) || + !rz_buf_read_le64_offset(cache_buf, &cur, &hdr->cacheType) || + !rz_buf_read_le32_offset(cache_buf, &cur, &hdr->branchPoolsOffset) || + !rz_buf_read_le32_offset(cache_buf, &cur, &hdr->branchPoolsCount) || + !rz_buf_read_le64_offset(cache_buf, &cur, &hdr->accelerateInfoAddr) || + !rz_buf_read_le64_offset(cache_buf, &cur, &hdr->accelerateInfoSize) || + !rz_buf_read_le64_offset(cache_buf, &cur, &hdr->imagesTextOffset) || + !rz_buf_read_le64_offset(cache_buf, &cur, &hdr->imagesTextCount)) { + goto fail; } - if (!hdr->imagesCount && !hdr->imagesOffset) { - if (!rz_buf_read_le32_at(cache_buf, 0x1c0 + offset, &hdr->imagesOffset) || !rz_buf_read_le32_at(cache_buf, 0x1c4 + offset, &hdr->imagesCount)) { - free(hdr); - return NULL; - } + // Size of the header was continuously expanded during versions as newer fields got added. + // There is no dedicated header size stored in the file, but in practice the mappingOffset is + // directly after the header, so we use this as an indicator on how far we may read. + ut64 hdr_end_offset = offset + hdr->mappingOffset; +#define READ_OR_FINISH(bits, dst) \ + do { \ + if (cur + bits / 8 > hdr_end_offset || !rz_buf_read_le##bits##_offset(cache_buf, &cur, dst)) { \ + goto finish; \ + } \ + } while (0) + READ_OR_FINISH(64, &hdr->patchInfoAddr); + READ_OR_FINISH(64, &hdr->patchInfoSize); + READ_OR_FINISH(64, &hdr->otherImageGroupAddrUnused); + READ_OR_FINISH(64, &hdr->otherImageGroupSizeUnused); + READ_OR_FINISH(64, &hdr->progClosuresAddr); + READ_OR_FINISH(64, &hdr->progClosuresSize); + READ_OR_FINISH(64, &hdr->progClosuresTrieAddr); + READ_OR_FINISH(64, &hdr->progClosuresTrieSize); + READ_OR_FINISH(32, &hdr->platform); + + ut32 flags; + READ_OR_FINISH(32, &flags); + hdr->formatVersion = flags & rz_num_bitmask(8); + flags >>= 8; + hdr->dylibsExpectedOnDisk = flags & 1; + flags >>= 1; + hdr->simulator = flags & 1; + flags >>= 1; + hdr->locallyBuiltCache = flags & 1; + flags >>= 1; + hdr->builtFromChainedFixups = flags & 1; + flags >>= 1; + hdr->padding = flags; + + READ_OR_FINISH(64, &hdr->sharedRegionStart); + READ_OR_FINISH(64, &hdr->sharedRegionSize); + READ_OR_FINISH(64, &hdr->maxSlide); + READ_OR_FINISH(64, &hdr->dylibsImageArrayAddr); + READ_OR_FINISH(64, &hdr->dylibsImageArraySize); + READ_OR_FINISH(64, &hdr->dylibsTrieAddr); + READ_OR_FINISH(64, &hdr->dylibsTrieSize); + READ_OR_FINISH(64, &hdr->otherImageArrayAddr); + READ_OR_FINISH(64, &hdr->otherImageArraySize); + READ_OR_FINISH(64, &hdr->otherTrieAddr); + READ_OR_FINISH(64, &hdr->otherTrieSize); + READ_OR_FINISH(32, &hdr->mappingWithSlideOffset); + READ_OR_FINISH(32, &hdr->mappingWithSlideCount); + + READ_OR_FINISH(64, &hdr->dylibsPBLStateArrayAddrUnused); + READ_OR_FINISH(64, &hdr->dylibsPBLSetAddr); + READ_OR_FINISH(64, &hdr->programsPBLSetPoolAddr); + READ_OR_FINISH(64, &hdr->programsPBLSetPoolSize); + READ_OR_FINISH(64, &hdr->programTrieAddr); + READ_OR_FINISH(32, &hdr->programTrieSize); + READ_OR_FINISH(32, &hdr->osVersion); + READ_OR_FINISH(32, &hdr->altPlatform); + READ_OR_FINISH(32, &hdr->altOsVersion); + READ_OR_FINISH(64, &hdr->swiftOptsOffset); + READ_OR_FINISH(64, &hdr->swiftOptsSize); + READ_OR_FINISH(32, &hdr->subCacheArrayOffset); + READ_OR_FINISH(32, &hdr->subCacheArrayCount); + + if (cur + sizeof(hdr->symbolFileUUID) > hdr_end_offset || + !rz_buf_read_offset(cache_buf, &cur, hdr->symbolFileUUID, sizeof(hdr->symbolFileUUID))) { + goto finish; } + + READ_OR_FINISH(64, &hdr->rosettaReadOnlyAddr); + READ_OR_FINISH(64, &hdr->rosettaReadOnlySize); + READ_OR_FINISH(64, &hdr->rosettaReadWriteAddr); + READ_OR_FINISH(64, &hdr->rosettaReadWriteSize); + + // This intentionally overrides the imagesOffset/imagesCount above as these + // two fields were moved down here in dyld-940: + READ_OR_FINISH(32, &hdr->imagesOffset); + READ_OR_FINISH(32, &hdr->imagesCount); + + READ_OR_FINISH(32, &hdr->cacheSubType); + cur += 4; // 8-alignment/padding + READ_OR_FINISH(64, &hdr->objcOptsOffset); + READ_OR_FINISH(64, &hdr->objcOptsSize); + READ_OR_FINISH(64, &hdr->cacheAtlasOffset); + READ_OR_FINISH(64, &hdr->cacheAtlasSize); + READ_OR_FINISH(64, &hdr->dynamicDataOffset); + READ_OR_FINISH(64, &hdr->dynamicDataMaxSize); + +#undef READ_OR_FINISH +finish: return hdr; +fail: + free(hdr); + return NULL; +} + +RZ_API RZ_NONNULL const char *rz_dyldcache_get_platform_str(RzDyldCache *cache) { + switch (cache->hdr->platform) { + case 1: + return "macOS"; + case 2: + return "iOS"; + case 3: + return "tvOS"; + case 4: + return "watchOS"; + case 5: + return "bridgeOS"; + case 6: + return "iOSMac"; + case 7: + return "iOS_simulator"; + case 8: + return "tvOS_simulator"; + case 9: + return "watchOS_simulator"; + case 10: + return "driverKit"; + default: + return "darwin"; // unknown + } +} + +RZ_API RZ_NONNULL const char *rz_dyldcache_get_type_str(RzDyldCache *cache) { + switch (cache->hdr->cacheType) { + case 0: + return "development"; + case 1: + return "production"; + case 2: + return "multi-cache"; + default: + return "unknown"; + } } #define SHIFT_MAYBE(x) \ @@ -90,7 +233,7 @@ static void populate_cache_headers(RzDyldCache *cache) { return; } - cache_hdr_t *h; + RzDyldCacheHeader *h; ut64 offsets[MAX_N_HDR]; ut64 offset = 0; do { @@ -119,7 +262,7 @@ static void populate_cache_headers(RzDyldCache *cache) { goto beach; } - cache->hdr = RZ_NEWS0(cache_hdr_t, cache->n_hdr); + cache->hdr = RZ_NEWS0(RzDyldCacheHeader, cache->n_hdr); if (!cache->hdr) { cache->n_hdr = 0; goto beach; @@ -136,12 +279,12 @@ static void populate_cache_headers(RzDyldCache *cache) { ut32 i = 0; RzListIter *iter; - cache_hdr_t *item; + RzDyldCacheHeader *item; rz_list_foreach (hdrs, iter, item) { if (i >= cache->n_hdr) { break; } - memcpy(&cache->hdr[i++], item, sizeof(cache_hdr_t)); + memcpy(&cache->hdr[i++], item, sizeof(RzDyldCacheHeader)); } beach: @@ -157,7 +300,7 @@ static void populate_cache_maps(RzDyldCache *cache) { ut32 n_maps = 0; ut64 max_count = 0; for (i = 0; i < cache->n_hdr; i++) { - cache_hdr_t *hdr = &cache->hdr[i]; + RzDyldCacheHeader *hdr = &cache->hdr[i]; if (!hdr->mappingCount || !hdr->mappingOffset) { continue; } @@ -181,7 +324,7 @@ static void populate_cache_maps(RzDyldCache *cache) { ut32 last_idx = UT32_MAX; ut64 max_address = 0; for (i = 0; i < cache->n_hdr; i++) { - cache_hdr_t *hdr = &cache->hdr[i]; + RzDyldCacheHeader *hdr = &cache->hdr[i]; cache->maps_index[i] = next_map; if (!hdr->mappingCount || !hdr->mappingOffset) { @@ -213,8 +356,8 @@ static void populate_cache_maps(RzDyldCache *cache) { } } -static cache_accel_t *read_cache_accel(RzBuffer *cache_buf, cache_hdr_t *hdr, cache_map_t *maps) { - if (!cache_buf || !hdr || !hdr->accelerateInfoSize || !hdr->accelerateInfoAddr) { +static cache_accel_t *read_cache_accel(RzBuffer *cache_buf, RzDyldCacheHeader *hdr, cache_map_t *maps) { + if (!cache_buf || !hdr || !rz_dyldcache_header_may_have_accel(hdr) || !hdr->accelerateInfoSize || !hdr->accelerateInfoAddr) { return NULL; } @@ -315,7 +458,7 @@ beach: return result; } -static cache_img_t *read_cache_images(RzBuffer *cache_buf, cache_hdr_t *hdr, ut64 hdr_offset) { +static cache_img_t *read_cache_images(RzBuffer *cache_buf, RzDyldCacheHeader *hdr, ut64 hdr_offset) { if (!cache_buf || !hdr) { return NULL; } @@ -385,7 +528,7 @@ static void match_bin_entries(RzDyldCache *cache, void *entries) { RZ_FREE(imgs); } -static cache_imgxtr_t *read_cache_imgextra(RzBuffer *cache_buf, cache_hdr_t *hdr, cache_accel_t *accel) { +static cache_imgxtr_t *read_cache_imgextra(RzBuffer *cache_buf, RzDyldCacheHeader *hdr, cache_accel_t *accel) { if (!cache_buf || !hdr || !hdr->imagesCount || !accel || !accel->imageExtrasCount || !accel->imagesExtrasOffset) { return NULL; } @@ -418,7 +561,7 @@ static int string_contains(const void *a, const void *b) { return !strstr((const char *)a, (const char *)b); } -static HtPU *create_path_to_index(RzBuffer *cache_buf, cache_img_t *img, cache_hdr_t *hdr) { +static HtPU *create_path_to_index(RzBuffer *cache_buf, cache_img_t *img, RzDyldCacheHeader *hdr) { HtPU *path_to_idx = ht_pu_new0(); if (!path_to_idx) { return NULL; @@ -510,7 +653,7 @@ static RzList /**/ *create_cache_bins(RzDyldCache *cache) { ut32 i; for (i = 0; i < cache->n_hdr; i++) { - cache_hdr_t *hdr = &cache->hdr[i]; + RzDyldCacheHeader *hdr = &cache->hdr[i]; ut64 hdr_offset = cache->hdr_offset[i]; ut64 symbols_off = cache->symbols_off_base - hdr_offset; ut32 maps_index = cache->maps_index[i]; @@ -1270,7 +1413,7 @@ static RzDyldLocSym *rz_dyld_locsym_new(RzDyldCache *cache) { ut32 i; for (i = 0; i < cache->n_hdr; i++) { - cache_hdr_t *hdr = &cache->hdr[i]; + RzDyldCacheHeader *hdr = &cache->hdr[i]; if (!hdr || !hdr->localSymbolsSize || !hdr->localSymbolsOffset) { continue; } diff --git a/librz/bin/format/mach0/dyldcache.h b/librz/bin/format/mach0/dyldcache.h index e29ef63ca9..9643769ab7 100644 --- a/librz/bin/format/mach0/dyldcache.h +++ b/librz/bin/format/mach0/dyldcache.h @@ -12,6 +12,131 @@ #include "mach0.h" +typedef struct rz_dyld_cache_header_t { + char magic[16]; + ut32 mappingOffset; + ut32 mappingCount; + ut32 imagesOffset; + ut32 imagesCount; + ut64 dyldBaseAddress; + ut64 codeSignatureOffset; + ut64 codeSignatureSize; + ut64 slideInfoOffset; + ut64 slideInfoSize; + ut64 localSymbolsOffset; + ut64 localSymbolsSize; + ut8 uuid[16]; + ut64 cacheType; + ut32 branchPoolsOffset; + ut32 branchPoolsCount; + union { + struct { + ut64 accelerateInfoAddr; + ut64 accelerateInfoSize; + }; ///< used if rz_dyldcache_header_may_have_accel() == true + struct { + ut64 dyldInCacheMH; + ut64 dyldInCacheEntry; + }; ///< used if rz_dyldcache_header_may_have_accel() == false + }; + ut64 imagesTextOffset; + ut64 imagesTextCount; + ut64 patchInfoAddr; + ut64 patchInfoSize; + ut64 otherImageGroupAddrUnused; + ut64 otherImageGroupSizeUnused; + ut64 progClosuresAddr; + ut64 progClosuresSize; + ut64 progClosuresTrieAddr; + ut64 progClosuresTrieSize; + ut32 platform; + ut32 formatVersion : 8, + dylibsExpectedOnDisk : 1, + simulator : 1, + locallyBuiltCache : 1, + builtFromChainedFixups : 1, + padding : 20; + ut64 sharedRegionStart; + ut64 sharedRegionSize; + ut64 maxSlide; + ut64 dylibsImageArrayAddr; + ut64 dylibsImageArraySize; + ut64 dylibsTrieAddr; + ut64 dylibsTrieSize; + ut64 otherImageArrayAddr; + ut64 otherImageArraySize; + ut64 otherTrieAddr; + ut64 otherTrieSize; + ut32 mappingWithSlideOffset; + ut32 mappingWithSlideCount; + + // offset = 0x140 + + // below added in dyld-940 + ut64 dylibsPBLStateArrayAddrUnused; + ut64 dylibsPBLSetAddr; + ut64 programsPBLSetPoolAddr; + ut64 programsPBLSetPoolSize; + ut64 programTrieAddr; + ut32 programTrieSize; + ut32 osVersion; + ut32 altPlatform; + ut32 altOsVersion; + ut64 swiftOptsOffset; + ut64 swiftOptsSize; + ut32 subCacheArrayOffset; + ut32 subCacheArrayCount; + ut8 symbolFileUUID[16]; + ut64 rosettaReadOnlyAddr; + ut64 rosettaReadOnlySize; + ut64 rosettaReadWriteAddr; + ut64 rosettaReadWriteSize; + // ut32 imagesOffset; (consolidated with imageOffset above) + // ut32 imagesCount; (consolidated with imagesCount above) + + // offset = 0x1c8 + + // below added in dyld-1042.1 + ut32 cacheSubType; + ut64 objcOptsOffset; + ut64 objcOptsSize; + ut64 cacheAtlasOffset; + ut64 cacheAtlasSize; + ut64 dynamicDataOffset; + ut64 dynamicDataMaxSize; + // offset = 0x200 +} RzDyldCacheHeader; + +typedef enum rz_dyld_cache_header_version { + RZ_DYLD_CACHE_HEADER_BEFORE_940, + RZ_DYLD_CACHE_HEADER_940_OR_AFTER, + RZ_DYLD_CACHE_HEADER_1042_1_OR_AFTER +} RzDyldCacheHeaderVersion; + +/** + * Guess the dyld version that \p hdr was created from + */ +static inline RzDyldCacheHeaderVersion rz_dyldcache_header_version(RzDyldCacheHeader *hdr) { + // Fields were added during different dyld versions, so we can use the size of the header to guess + // the version. Even though there is no explicit header size field, mappingOffset is usually directly + // after the header, so we use this to measure size. + if (hdr->mappingOffset < 0x1c8) { + return RZ_DYLD_CACHE_HEADER_BEFORE_940; + } else if (hdr->mappingOffset < 0x200) { + return RZ_DYLD_CACHE_HEADER_940_OR_AFTER; + } else { + return RZ_DYLD_CACHE_HEADER_1042_1_OR_AFTER; + } +} + +/** + * Determine if the accelerateInfoAddr/accelerateInfoSize fields are available in the header, + * as opposed to dyldInCacheMH/dyldInCacheEntry + */ +static inline bool rz_dyldcache_header_may_have_accel(RzDyldCacheHeader *hdr) { + return rz_dyldcache_header_version(hdr) < RZ_DYLD_CACHE_HEADER_1042_1_OR_AFTER; +} + typedef struct rz_dyld_rebase_info_t { ut8 version; ut64 slide; @@ -93,7 +218,7 @@ typedef struct rz_bin_dyld_image_t { typedef struct rz_dyldcache_t { ut8 magic[8]; - cache_hdr_t *hdr; + RzDyldCacheHeader *hdr; ut64 *hdr_offset; ut64 symbols_off_base; ut32 *maps_index; @@ -113,6 +238,8 @@ typedef struct rz_dyldcache_t { RZ_API bool rz_dyldcache_check_magic(const char *magic); RZ_API RzDyldCache *rz_dyldcache_new_buf(RzBuffer *buf); RZ_API void rz_dyldcache_free(RzDyldCache *cache); +RZ_API RZ_NONNULL const char *rz_dyldcache_get_platform_str(RzDyldCache *cache); +RZ_API RZ_NONNULL const char *rz_dyldcache_get_type_str(RzDyldCache *cache); RZ_API ut64 rz_dyldcache_va2pa(RzDyldCache *cache, uint64_t vaddr, ut32 *offset, ut32 *left); RZ_API ut64 rz_dyldcache_get_slide(RzDyldCache *cache); RZ_API objc_cache_opt_info *rz_dyldcache_get_objc_opt_info(RzBinFile *bf, RzDyldCache *cache); diff --git a/librz/bin/format/mach0/mach0_specs.h b/librz/bin/format/mach0/mach0_specs.h index cf03ec3ce6..f4defe21f8 100644 --- a/librz/bin/format/mach0/mach0_specs.h +++ b/librz/bin/format/mach0/mach0_specs.h @@ -189,47 +189,6 @@ struct arm_thread_state64 { ut32 cpsr; }; -/* Cache header */ - -struct cache_header { - char version[16]; - ut32 baseaddroff; // mappingOffset - ut32 mappingCount; - ut32 startaddr; - ut32 numlibs; - ut64 dyldaddr; - ut64 codeSignatureOffset; - ut64 codeSignatureSize; - ut64 slideInfoOffset; - ut64 slideInfoSize; - ut64 localSymbolsOffset; - ut64 localSymbolsSize; -}; - -// dupe? -typedef struct { - char magic[16]; - uint32_t mappingOffset; - uint32_t mappingCount; - uint32_t imagesOffset; - uint32_t imagesCount; - uint64_t dyldBaseAddress; - uint64_t codeSignatureOffset; - uint64_t codeSignatureSize; - uint64_t slideInfoOffset; - uint64_t slideInfoSize; - uint64_t localSymbolsOffset; - uint64_t localSymbolsSize; - uint8_t uuid[16]; - uint64_t cacheType; - uint32_t branchPoolsOffset; - uint32_t branchPoolsCount; - uint64_t accelerateInfoAddr; - uint64_t accelerateInfoSize; - uint64_t imagesTextOffset; - uint64_t imagesTextCount; -} cache_hdr_t; - typedef struct { uint8_t uuid[16]; uint64_t loadAddress; diff --git a/librz/bin/p/bin_dyldcache.c b/librz/bin/p/bin_dyldcache.c index d94a136fd9..7d8fc7dbc9 100644 --- a/librz/bin/p/bin_dyldcache.c +++ b/librz/bin/p/bin_dyldcache.c @@ -111,7 +111,7 @@ static RzBinInfo *info(RzBinFile *bf) { } ret->file = strdup(bf->file); ret->bclass = strdup("dyldcache"); - ret->os = strdup("Darwin"); // TODO: actual OS info is available. See the platform member of struct dyld_cache_header in dyld source. + ret->os = strdup(rz_dyldcache_get_platform_str(cache)); if (strstr(cache->hdr->magic, "x86_64")) { ret->arch = strdup("x86"); ret->bits = 64; @@ -121,7 +121,8 @@ static RzBinInfo *info(RzBinFile *bf) { } ret->machine = strdup(ret->arch); ret->subsystem = strdup("xnu"); - ret->type = strdup("library-cache"); + ret->guid = rz_hex_bin2strdup((ut8 *)cache->hdr->uuid, sizeof(cache->hdr->uuid)); + ret->type = strdup(rz_dyldcache_get_type_str(cache)); ret->has_va = true; ret->big_endian = big_endian; ret->dbg_info = 0; @@ -515,6 +516,21 @@ static void header(RzBinFile *bf) { } pj_o(pj); + + pj_k(pj, "version"); + RzDyldCacheHeaderVersion ver = rz_dyldcache_header_version(cache->hdr); + switch (ver) { + case RZ_DYLD_CACHE_HEADER_BEFORE_940: + pj_s(pj, "<940"); + break; + case RZ_DYLD_CACHE_HEADER_940_OR_AFTER: + pj_s(pj, "940"); + break; + case RZ_DYLD_CACHE_HEADER_1042_1_OR_AFTER: + pj_s(pj, "1042.1"); + break; + } + pj_k(pj, "header"); pj_o(pj); pj_ks(pj, "magic", cache->hdr->magic); @@ -535,10 +551,73 @@ static void header(RzBinFile *bf) { pj_ks(pj, "cacheType", (cache->hdr->cacheType == 0) ? "development" : "production"); pj_kn(pj, "branchPoolsOffset", cache->hdr->branchPoolsOffset); pj_kn(pj, "branchPoolsCount", cache->hdr->branchPoolsCount); - pj_kn(pj, "accelerateInfoAddr", cache->hdr->accelerateInfoAddr + slide); - pj_kn(pj, "accelerateInfoSize", cache->hdr->accelerateInfoSize); + if (rz_dyldcache_header_may_have_accel(cache->hdr)) { + pj_kn(pj, "accelerateInfoAddr", cache->hdr->accelerateInfoAddr + slide); + pj_kn(pj, "accelerateInfoSize", cache->hdr->accelerateInfoSize); + } else { + pj_kn(pj, "dyldInCacheMH", cache->hdr->dyldInCacheMH); + pj_kn(pj, "dyldInCacheEntry", cache->hdr->dyldInCacheEntry); + } pj_kn(pj, "imagesTextOffset", cache->hdr->imagesTextOffset); pj_kn(pj, "imagesTextCount", cache->hdr->imagesTextCount); + pj_kn(pj, "patchInfoAddr", cache->hdr->patchInfoAddr); + pj_kn(pj, "patchInfoSize", cache->hdr->patchInfoSize); + pj_kn(pj, "otherImageGroupAddrUnused", cache->hdr->otherImageGroupAddrUnused); + pj_kn(pj, "otherImageGroupSizeUnused", cache->hdr->otherImageGroupSizeUnused); + pj_kn(pj, "progClosuresAddr", cache->hdr->progClosuresAddr); + pj_kn(pj, "progClosuresSize", cache->hdr->progClosuresSize); + pj_kn(pj, "progClosuresTrieAddr", cache->hdr->progClosuresTrieAddr); + pj_kn(pj, "progClosuresTrieSize", cache->hdr->progClosuresTrieSize); + pj_kn(pj, "platform", cache->hdr->platform); + pj_kn(pj, "formatVersion", cache->hdr->formatVersion); + pj_kn(pj, "dylibsExpectedOnDisk", cache->hdr->dylibsExpectedOnDisk); + pj_kn(pj, "simulator", cache->hdr->simulator); + pj_kn(pj, "locallyBuiltCache", cache->hdr->locallyBuiltCache); + pj_kn(pj, "builtFromChainedFixups", cache->hdr->builtFromChainedFixups); + pj_kn(pj, "padding", cache->hdr->padding); + pj_kn(pj, "sharedRegionStart", cache->hdr->sharedRegionStart); + pj_kn(pj, "sharedRegionSize", cache->hdr->sharedRegionSize); + pj_kn(pj, "maxSlide", cache->hdr->maxSlide); + pj_kn(pj, "dylibsImageArrayAddr", cache->hdr->dylibsImageArrayAddr); + pj_kn(pj, "dylibsImageArraySize", cache->hdr->dylibsImageArraySize); + pj_kn(pj, "dylibsTrieAddr", cache->hdr->dylibsTrieAddr); + pj_kn(pj, "dylibsTrieSize", cache->hdr->dylibsTrieSize); + pj_kn(pj, "otherImageArrayAddr", cache->hdr->otherImageArrayAddr); + pj_kn(pj, "otherImageArraySize", cache->hdr->otherImageArraySize); + pj_kn(pj, "otherTrieAddr", cache->hdr->otherTrieAddr); + pj_kn(pj, "otherTrieSize", cache->hdr->otherTrieSize); + pj_kn(pj, "mappingWithSlideOffset", cache->hdr->mappingWithSlideOffset); + pj_kn(pj, "mappingWithSlideCount", cache->hdr->mappingWithSlideCount); + if (ver >= RZ_DYLD_CACHE_HEADER_940_OR_AFTER) { + pj_kn(pj, "dylibsPBLStateArrayAddrUnused", cache->hdr->dylibsPBLStateArrayAddrUnused); + pj_kn(pj, "dylibsPBLSetAddr", cache->hdr->dylibsPBLSetAddr); + pj_kn(pj, "programsPBLSetPoolAddr", cache->hdr->programsPBLSetPoolAddr); + pj_kn(pj, "programsPBLSetPoolSize", cache->hdr->programsPBLSetPoolSize); + pj_kn(pj, "programTrieAddr", cache->hdr->programTrieAddr); + pj_kn(pj, "programTrieSize", cache->hdr->programTrieSize); + pj_kn(pj, "osVersion", cache->hdr->osVersion); + pj_kn(pj, "altPlatform", cache->hdr->altPlatform); + pj_kn(pj, "altOsVersion", cache->hdr->altOsVersion); + pj_kn(pj, "swiftOptsOffset", cache->hdr->swiftOptsOffset); + pj_kn(pj, "swiftOptsSize", cache->hdr->swiftOptsSize); + pj_kn(pj, "subCacheArrayOffset", cache->hdr->subCacheArrayOffset); + pj_kn(pj, "subCacheArrayCount", cache->hdr->subCacheArrayCount); + rz_hex_bin2str(cache->hdr->symbolFileUUID, sizeof(cache->hdr->symbolFileUUID), uuidstr); + pj_ks(pj, "symbolFileUUID", uuidstr); + pj_kn(pj, "rosettaReadOnlyAddr", cache->hdr->rosettaReadOnlyAddr); + pj_kn(pj, "rosettaReadOnlySize", cache->hdr->rosettaReadOnlySize); + pj_kn(pj, "rosettaReadWriteAddr", cache->hdr->rosettaReadWriteAddr); + pj_kn(pj, "rosettaReadWriteSize", cache->hdr->rosettaReadWriteSize); + } + if (ver >= RZ_DYLD_CACHE_HEADER_1042_1_OR_AFTER) { + pj_kn(pj, "cacheSubType", cache->hdr->cacheSubType); + pj_kn(pj, "objcOptsOffset", cache->hdr->objcOptsOffset); + pj_kn(pj, "objcOptsSize", cache->hdr->objcOptsSize); + pj_kn(pj, "cacheAtlasOffset", cache->hdr->cacheAtlasOffset); + pj_kn(pj, "cacheAtlasSize", cache->hdr->cacheAtlasSize); + pj_kn(pj, "dynamicDataOffset", cache->hdr->dynamicDataOffset); + pj_kn(pj, "dynamicDataMaxSize", cache->hdr->dynamicDataMaxSize); + } pj_end(pj); if (cache->accel) { diff --git a/test/db/formats/dyldcache b/test/db/formats/dyldcache index 15f5a51bf2..2549991697 100644 --- a/test/db/formats/dyldcache +++ b/test/db/formats/dyldcache @@ -4,7 +4,7 @@ CMDS=<