Rizin
unix-like reverse engineering framework and cli tools
dyldcache.c File Reference
#include "dyldcache.h"
#include <ht_pu.h>

Go to the source code of this file.

Macros

#define MAX_N_HDR   16
 
#define SHIFT_MAYBE(x)
 

Functions

static RzDyldLocSymrz_dyld_locsym_new (RzDyldCache *cache)
 
RZ_API bool rz_dyldcache_check_magic (const char *magic)
 
static ut64 va2pa (uint64_t addr, ut32 n_maps, cache_map_t *maps, RzBuffer *cache_buf, ut64 slide, ut32 *offset, ut32 *left)
 
static void free_bin (RzDyldBinImage *bin)
 
static cache_hdr_tread_cache_header (RzBuffer *cache_buf, ut64 offset)
 
static void populate_cache_headers (RzDyldCache *cache)
 
static void populate_cache_maps (RzDyldCache *cache)
 
static cache_accel_tread_cache_accel (RzBuffer *cache_buf, cache_hdr_t *hdr, cache_map_t *maps)
 
RZ_API objc_cache_opt_inforz_dyldcache_get_objc_opt_info (RzBinFile *bf, RzDyldCache *cache)
 
static cache_img_tread_cache_images (RzBuffer *cache_buf, cache_hdr_t *hdr, ut64 hdr_offset)
 
static void match_bin_entries (RzDyldCache *cache, void *entries)
 
static cache_imgxtr_tread_cache_imgextra (RzBuffer *cache_buf, cache_hdr_t *hdr, cache_accel_t *accel)
 
static char * get_lib_name (RzBuffer *cache_buf, cache_img_t *img)
 
static int string_contains (const void *a, const void *b)
 
static HtPU * create_path_to_index (RzBuffer *cache_buf, cache_img_t *img, cache_hdr_t *hdr)
 
static void carve_deps_at_address (RzDyldCache *cache, cache_img_t *img, HtPU *path_to_idx, ut64 address, int *deps, bool printing)
 
static RzListcreate_cache_bins (RzDyldCache *cache)
 
static ut32 dumb_ctzll (ut64 x)
 
static ut64 estimate_slide (RzDyldCache *cache, ut64 value_mask, ut64 value_add)
 
static RzDyldRebaseInfoget_rebase_info (RzDyldCache *cache, ut64 slideInfoOffset, ut64 slideInfoSize, ut64 start_of_data, ut64 slide)
 
static RzDyldRebaseInfosget_rebase_infos (RzDyldCache *cache)
 
RZ_API ut64 rz_dyldcache_get_slide (RzDyldCache *cache)
 
RZ_API void rz_dyldcache_symbols_from_locsym (RzDyldCache *cache, RzDyldBinImage *bin, RzList *symbols, SetU *hash)
 
RZ_API RzDyldCacherz_dyldcache_new_buf (RzBuffer *buf)
 
static void rebase_info3_free (RzDyldRebaseInfo3 *rebase_info)
 
static void rebase_info2_free (RzDyldRebaseInfo2 *rebase_info)
 
static void rebase_info1_free (RzDyldRebaseInfo1 *rebase_info)
 
static void rebase_info_free (RzDyldRebaseInfo *rebase_info)
 
RZ_API void rz_dyldcache_free (RzDyldCache *cache)
 
RZ_API ut64 rz_dyldcache_va2pa (RzDyldCache *cache, uint64_t vaddr, ut32 *offset, ut32 *left)
 

Macro Definition Documentation

◆ MAX_N_HDR

#define MAX_N_HDR   16

Definition at line 11 of file dyldcache.c.

◆ SHIFT_MAYBE

#define SHIFT_MAYBE (   x)
Value:
if (x) { \
x += offset; \
}
voidpf uLong offset
Definition: ioapi.h:144
int x
Definition: mipsasm.c:20

Function Documentation

◆ carve_deps_at_address()

static void carve_deps_at_address ( RzDyldCache cache,
cache_img_t img,
HtPU *  path_to_idx,
ut64  address,
int deps,
bool  printing 
)
static

Definition at line 436 of file dyldcache.c.

436  {
437  ut64 pa = va2pa(address, cache->n_maps, cache->maps, cache->buf, 0, NULL, NULL);
438  if (pa == UT64_MAX) {
439  return;
440  }
441  struct MACH0_(mach_header) mh;
442  if (rz_buf_fread_at(cache->buf, pa, (ut8 *)&mh, "8i", 1) != sizeof(struct MACH0_(mach_header))) {
443  return;
444  }
445  if (mh.magic != MH_MAGIC_64 || mh.sizeofcmds == 0) {
446  return;
447  }
448  ut64 cmds_at = pa + sizeof(struct MACH0_(mach_header));
449  ut8 *cmds = malloc(mh.sizeofcmds + 1);
450  if (!cmds || rz_buf_read_at(cache->buf, cmds_at, cmds, mh.sizeofcmds) != mh.sizeofcmds) {
451  goto beach;
452  }
453  cmds[mh.sizeofcmds] = 0;
454  ut8 *cursor = cmds;
455  ut8 *end = cmds + mh.sizeofcmds;
456  while (cursor < end) {
457  ut32 cmd = rz_read_le32(cursor);
458  ut32 cmdsize = rz_read_le32(cursor + sizeof(ut32));
459  if (cmd == LC_LOAD_DYLIB ||
460  cmd == LC_LOAD_WEAK_DYLIB ||
461  cmd == LC_REEXPORT_DYLIB ||
463  bool found;
464  if (cursor + 24 >= end) {
465  break;
466  }
467  const char *key = (const char *)cursor + 24;
468  size_t dep_index = (size_t)ht_pu_find(path_to_idx, key, &found);
469  if (!found || dep_index >= cache->hdr->imagesCount) {
470  RZ_LOG_WARN("alien dep '%s'\n", key);
471  continue;
472  }
473  deps[dep_index]++;
474  if (printing) {
475  RZ_LOG_INFO("-> %s\n", key);
476  }
477  }
478  cursor += cmdsize;
479  }
480 
481 beach:
482  free(cmds);
483 }
#define NULL
Definition: cris-opc.c:27
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags cmd
Definition: sflib.h:79
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len key
Definition: sflib.h:118
uint32_t ut32
static ut64 va2pa(uint64_t addr, ut32 n_maps, cache_map_t *maps, RzBuffer *cache_buf, ut64 slide, ut32 *offset, ut32 *left)
Definition: dyldcache.c:22
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
RZ_API const KEY_TYPE bool * found
Definition: ht_inc.h:130
uint8_t ut8
Definition: lh5801.h:11
void * malloc(size_t size)
Definition: malloc.c:123
@ LC_LOAD_UPWARD_DYLIB
@ LC_LOAD_WEAK_DYLIB
@ LC_LOAD_DYLIB
@ LC_REEXPORT_DYLIB
@ MH_MAGIC_64
Definition: mach0_defines.h:63
#define MACH0_(name)
Definition: mach0_specs.h:20
RZ_API st64 rz_buf_read_at(RZ_NONNULL RzBuffer *b, ut64 addr, RZ_NONNULL RZ_OUT ut8 *buf, ut64 len)
Read len bytes of the buffer at the specified address.
Definition: buf.c:1136
RZ_API st64 rz_buf_fread_at(RZ_NONNULL RzBuffer *b, ut64 addr, RZ_NONNULL ut8 *buf, RZ_NONNULL const char *fmt, int n)
...
Definition: buf.c:1001
static ut32 rz_read_le32(const void *src)
Definition: rz_endian.h:239
#define RZ_LOG_INFO(fmtstr,...)
Definition: rz_log.h:54
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
#define UT64_MAX
Definition: rz_types_base.h:86
int size_t
Definition: sftypes.h:40
uint32_t imagesCount
Definition: mach0_specs.h:215
cache_map_t * maps
Definition: dyldcache.h:101
cache_hdr_t * hdr
Definition: dyldcache.h:96
RzBuffer * buf
Definition: dyldcache.h:105
ut64(WINAPI *w32_GetEnabledXStateFeatures)()

References rz_dyldcache_t::buf, cmd, test_evm::end, found, free(), rz_dyldcache_t::hdr, cache_hdr_t::imagesCount, key, LC_LOAD_DYLIB, LC_LOAD_UPWARD_DYLIB, LC_LOAD_WEAK_DYLIB, LC_REEXPORT_DYLIB, MACH0_, malloc(), rz_dyldcache_t::maps, MH_MAGIC_64, rz_dyldcache_t::n_maps, NULL, rz_buf_fread_at(), rz_buf_read_at(), RZ_LOG_INFO, RZ_LOG_WARN, rz_read_le32(), ut64(), UT64_MAX, and va2pa().

Referenced by create_cache_bins().

◆ create_cache_bins()

static RzList* create_cache_bins ( RzDyldCache cache)
static

Definition at line 485 of file dyldcache.c.

485  {
487  if (!bins) {
488  return NULL;
489  }
490 
491  char *target_libs = NULL;
492  RzList *target_lib_names = NULL;
493  int *deps = NULL;
494  target_libs = rz_sys_getenv("RZ_DYLDCACHE_FILTER");
495  if (target_libs) {
496  target_lib_names = rz_str_split_list(target_libs, ":", 0);
497  if (!target_lib_names) {
499  return NULL;
500  }
501  deps = RZ_NEWS0(int, cache->hdr->imagesCount);
502  if (!deps) {
504  rz_list_free(target_lib_names);
505  return NULL;
506  }
507  }
508 
509  ut32 i;
510  for (i = 0; i < cache->n_hdr; i++) {
511  cache_hdr_t *hdr = &cache->hdr[i];
512  ut64 hdr_offset = cache->hdr_offset[i];
513  ut64 symbols_off = cache->symbols_off_base - hdr_offset;
514  ut32 maps_index = cache->maps_index[i];
515  cache_img_t *img = read_cache_images(cache->buf, hdr, hdr_offset);
516  if (!img) {
517  goto next;
518  }
519 
520  ut32 j;
521  ut16 *depArray = NULL;
522  cache_imgxtr_t *extras = NULL;
523  if (target_libs) {
524  HtPU *path_to_idx = NULL;
525  if (cache->accel) {
526  depArray = RZ_NEWS0(ut16, cache->accel->depListCount);
527  if (!depArray) {
528  goto next;
529  }
530 
531  if (rz_buf_fread_at(cache->buf, cache->accel->depListOffset, (ut8 *)depArray, "s", cache->accel->depListCount) != cache->accel->depListCount * 2) {
532  goto next;
533  }
534 
535  extras = read_cache_imgextra(cache->buf, hdr, cache->accel);
536  if (!extras) {
537  goto next;
538  }
539  } else {
540  path_to_idx = create_path_to_index(cache->buf, img, hdr);
541  }
542 
543  for (j = 0; j < hdr->imagesCount; j++) {
544  bool printing = !deps[j];
545  char *lib_name = get_lib_name(cache->buf, &img[j]);
546  if (!lib_name) {
547  break;
548  }
549  if (strstr(lib_name, "libobjc.A.dylib")) {
550  deps[j]++;
551  }
552  if (!rz_list_find(target_lib_names, lib_name, string_contains)) {
553  RZ_FREE(lib_name);
554  continue;
555  }
556  if (printing) {
557  RZ_LOG_INFO("FILTER: %s\n", lib_name);
558  }
559  RZ_FREE(lib_name);
560  deps[j]++;
561 
562  if (extras && depArray) {
563  ut32 k;
564  for (k = extras[j].dependentsStartArrayIndex; depArray[k] != 0xffff; k++) {
565  ut16 dep_index = depArray[k] & 0x7fff;
566  deps[dep_index]++;
567 
568  char *dep_name = get_lib_name(cache->buf, &img[dep_index]);
569  if (!dep_name) {
570  break;
571  }
572  if (printing) {
573  RZ_LOG_INFO("-> %s\n", dep_name);
574  }
575  free(dep_name);
576  }
577  } else if (path_to_idx) {
578  carve_deps_at_address(cache, img, path_to_idx, img[j].address, deps, printing);
579  }
580  }
581 
582  ht_pu_free(path_to_idx);
583  RZ_FREE(depArray);
584  RZ_FREE(extras);
585  }
586 
587  for (j = 0; j < hdr->imagesCount; j++) {
588  if (deps && !deps[j]) {
589  continue;
590  }
591  ut64 pa = va2pa(img[j].address, hdr->mappingCount, &cache->maps[maps_index], cache->buf, 0, NULL, NULL);
592  if (pa == UT64_MAX) {
593  continue;
594  }
595  ut8 magicbytes[4];
596  rz_buf_read_at(cache->buf, pa, magicbytes, 4);
597  int magic = rz_read_le32(magicbytes);
598  switch (magic) {
599  case MH_MAGIC_64: {
600  char file[256];
602  if (!bin) {
603  goto next;
604  }
605  bin->header_at = pa;
606  bin->hdr_offset = hdr_offset;
607  bin->symbols_off = symbols_off;
608  bin->va = img[j].address;
609  if (rz_buf_read_at(cache->buf, img[j].pathFileOffset, (ut8 *)&file, sizeof(file)) == sizeof(file)) {
610  file[255] = 0;
611  char *last_slash = strrchr(file, '/');
612  if (last_slash && *last_slash) {
613  if (last_slash > file) {
614  char *scan = last_slash - 1;
615  while (scan > file && *scan != '/') {
616  scan--;
617  }
618  if (*scan == '/') {
619  bin->file = strdup(scan + 1);
620  } else {
621  bin->file = strdup(last_slash + 1);
622  }
623  } else {
624  bin->file = strdup(last_slash + 1);
625  }
626  } else {
627  bin->file = strdup(file);
628  }
629  }
631  break;
632  }
633  default:
634  RZ_LOG_WARN("Unknown sub-bin\n");
635  break;
636  }
637  }
638  next:
639  RZ_FREE(depArray);
640  RZ_FREE(extras);
641  RZ_FREE(img);
642  }
643  if (rz_list_empty(bins)) {
645  bins = NULL;
646  }
647  RZ_FREE(deps);
648  RZ_FREE(target_libs);
649  rz_list_free(target_lib_names);
650  return bins;
651 }
lzma_index ** i
Definition: index.h:629
uint16_t ut16
const char * k
Definition: dsignal.c:11
static cache_imgxtr_t * read_cache_imgextra(RzBuffer *cache_buf, cache_hdr_t *hdr, cache_accel_t *accel)
Definition: dyldcache.c:386
static char * get_lib_name(RzBuffer *cache_buf, cache_img_t *img)
Definition: dyldcache.c:405
static cache_img_t * read_cache_images(RzBuffer *cache_buf, cache_hdr_t *hdr, ut64 hdr_offset)
Definition: dyldcache.c:316
static void free_bin(RzDyldBinImage *bin)
Definition: dyldcache.c:44
static HtPU * create_path_to_index(RzBuffer *cache_buf, cache_img_t *img, cache_hdr_t *hdr)
Definition: dyldcache.c:419
static void carve_deps_at_address(RzDyldCache *cache, cache_img_t *img, HtPU *path_to_idx, ut64 address, int *deps, bool printing)
Definition: dyldcache.c:436
static int string_contains(const void *a, const void *b)
Definition: dyldcache.c:415
RZ_API RZ_BORROW RzListIter * rz_list_find(RZ_NONNULL const RzList *list, const void *p, RZ_NONNULL RzListComparator cmp)
Returns RzListIter element which matches via the RzListComparator.
Definition: list.c:620
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
RZ_API RzList * rz_str_split_list(char *str, const char *c, int n)
Split the string str according to the substring c and returns a RzList with the result.
Definition: str.c:3429
RZ_API char * rz_sys_getenv(const char *key)
Get the value of an environment variable named key or NULL if none exists.
Definition: sys.c:483
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_NEWS0(x, y)
Definition: rz_types.h:282
#define RZ_FREE(x)
Definition: rz_types.h:369
Definition: malloc.c:26
uint32_t depListCount
Definition: mach0_specs.h:298
uint32_t depListOffset
Definition: mach0_specs.h:297
uint32_t mappingCount
Definition: mach0_specs.h:213
uint64_t address
Definition: mach0_specs.h:249
Definition: gzappend.c:170
ut64 * hdr_offset
Definition: dyldcache.h:97
ut32 * maps_index
Definition: dyldcache.h:99
cache_accel_t * accel
Definition: dyldcache.h:107
ut64 symbols_off_base
Definition: dyldcache.h:98
struct bin bins[64]
Definition: malloc.c:34

References rz_dyldcache_t::accel, cache_img_t::address, bins, rz_dyldcache_t::buf, carve_deps_at_address(), create_path_to_index(), cache_accel_t::depListCount, cache_accel_t::depListOffset, free(), free_bin(), get_lib_name(), rz_dyldcache_t::hdr, rz_dyldcache_t::hdr_offset, i, cache_hdr_t::imagesCount, k, cache_hdr_t::mappingCount, rz_dyldcache_t::maps, rz_dyldcache_t::maps_index, MH_MAGIC_64, rz_dyldcache_t::n_hdr, NULL, cache_img_t::pathFileOffset, read_cache_images(), read_cache_imgextra(), rz_buf_fread_at(), rz_buf_read_at(), RZ_FREE, rz_list_append(), rz_list_find(), rz_list_free(), rz_list_newf(), RZ_LOG_INFO, RZ_LOG_WARN, RZ_NEW0, RZ_NEWS0, rz_read_le32(), rz_str_split_list(), rz_sys_getenv(), strdup(), string_contains(), rz_dyldcache_t::symbols_off_base, ut64(), UT64_MAX, and va2pa().

Referenced by rz_dyldcache_new_buf().

◆ create_path_to_index()

static HtPU* create_path_to_index ( RzBuffer cache_buf,
cache_img_t img,
cache_hdr_t hdr 
)
static

Definition at line 419 of file dyldcache.c.

419  {
420  HtPU *path_to_idx = ht_pu_new0();
421  if (!path_to_idx) {
422  return NULL;
423  }
424  for (size_t i = 0; i != hdr->imagesCount; i++) {
425  char file[256];
426  if (rz_buf_read_at(cache_buf, img[i].pathFileOffset, (ut8 *)&file, sizeof(file)) != sizeof(file)) {
427  continue;
428  }
429  file[255] = 0;
430  ht_pu_insert(path_to_idx, file, (ut64)i);
431  }
432 
433  return path_to_idx;
434 }

References i, cache_hdr_t::imagesCount, NULL, rz_buf_read_at(), and ut64().

Referenced by create_cache_bins().

◆ dumb_ctzll()

static ut32 dumb_ctzll ( ut64  x)
static

Definition at line 653 of file dyldcache.c.

653  {
654  ut64 result = 0;
655  int i, j;
656  for (i = 0; i < 64; i += 8) {
657  ut8 byte = (x >> i) & 0xff;
658  if (!byte) {
659  result += 8;
660  } else {
661  for (j = 0; j < 8; j++) {
662  if (!((byte >> j) & 1)) {
663  result++;
664  } else {
665  break;
666  }
667  }
668  break;
669  }
670  }
671  return result;
672 }

References i, ut64(), and x.

Referenced by get_rebase_info().

◆ estimate_slide()

static ut64 estimate_slide ( RzDyldCache cache,
ut64  value_mask,
ut64  value_add 
)
static

Definition at line 674 of file dyldcache.c.

674  {
675  ut64 slide = 0;
676  if (cache->n_hdr > 1) {
677  return slide;
678  }
679  ut64 *classlist = malloc(64);
680  if (!classlist) {
681  goto beach;
682  }
683 
684  RzListIter *iter;
686  rz_list_foreach (cache->bins, iter, bin) {
687  bool found_sample = false;
688 
689  struct MACH0_(opts_t) opts = { 0 };
690  opts.header_at = bin->header_at;
691 
692  struct MACH0_(obj_t) *mach0 = MACH0_(new_buf)(cache->buf, &opts);
693  if (!mach0) {
694  goto beach;
695  }
696 
697  struct section_t *sections = NULL;
698  if (!(sections = MACH0_(get_sections)(mach0))) {
700  (mach0);
701  goto beach;
702  }
703 
704  int i;
705  int incomplete = 2;
706  int classlist_idx = 0, data_idx = 0;
707  for (i = 0; !sections[i].last && incomplete; i++) {
708  if (sections[i].size == 0) {
709  continue;
710  }
711  if (strstr(sections[i].name, "__objc_classlist")) {
712  incomplete--;
713  classlist_idx = i;
714  continue;
715  }
716  if (strstr(sections[i].name, "__objc_data")) {
717  incomplete--;
718  data_idx = i;
719  continue;
720  }
721  }
722 
723  if (incomplete) {
724  goto next_bin;
725  }
726 
727  int classlist_sample_size = RZ_MIN(64, sections[classlist_idx].size);
728  int n_classes = classlist_sample_size / 8;
729  ut64 sect_offset = sections[classlist_idx].offset + bin->hdr_offset;
730 
731  if (rz_buf_fread_at(cache->buf, sect_offset, (ut8 *)classlist, "l", n_classes) < classlist_sample_size) {
732  goto next_bin;
733  }
734 
735  ut64 data_addr = sections[data_idx].addr;
736  ut64 data_tail = data_addr & 0xfff;
737  ut64 data_tail_end = (data_addr + sections[data_idx].size) & 0xfff;
738  for (i = 0; i < n_classes; i++) {
739  ut64 cl_addr = (classlist[i] & value_mask) + value_add;
740  ut64 cl_tail = cl_addr & 0xfff;
741  if (cl_tail >= data_tail && cl_tail < data_tail_end) {
742  ut64 off = cl_tail - data_tail;
743  slide = ((cl_addr - off) & value_mask) - (data_addr & value_mask);
744  found_sample = true;
745  break;
746  }
747  }
748 
749  next_bin:
751  (mach0);
752  free(sections);
753 
754  if (found_sample) {
755  break;
756  }
757  }
758 
759 beach:
760  free(classlist);
761  return slide;
762 }
RzList * sections(RzBinFile *bf)
Definition: bin_ne.c:110
voidpf void uLong size
Definition: ioapi.h:138
struct section_t *MACH0_() get_sections(struct MACH0_(obj_t) *bin)
Definition: mach0.c:2411
void *MACH0_() mach0_free(struct MACH0_(obj_t) *mo)
Definition: mach0.c:2057
int off
Definition: pal.c:13
#define RZ_MIN(x, y)
Definition: z80asm.h:102
RzList * bins
Definition: dyldcache.h:104

References rz_dyldcache_t::bins, rz_dyldcache_t::buf, free(), get_sections(), i, MACH0_, mach0_free(), malloc(), rz_dyldcache_t::n_hdr, NULL, off, rz_buf_fread_at(), RZ_MIN, sections(), and ut64().

Referenced by get_rebase_info().

◆ free_bin()

static void free_bin ( RzDyldBinImage bin)
static

Definition at line 44 of file dyldcache.c.

44  {
45  if (!bin) {
46  return;
47  }
48  free(bin->file);
49  free(bin);
50 }

References free().

Referenced by create_cache_bins().

◆ get_lib_name()

static char* get_lib_name ( RzBuffer cache_buf,
cache_img_t img 
)
static

Definition at line 405 of file dyldcache.c.

405  {
406  char file[256];
407  char *lib_name = file;
408  if (rz_buf_read_at(cache_buf, img->pathFileOffset, (ut8 *)&file, sizeof(file)) == sizeof(file)) {
409  file[255] = 0;
410  return strdup(lib_name);
411  }
412  return strdup("FAIL");
413 }
uint32_t pathFileOffset
Definition: mach0_specs.h:252
static int file
Definition: z80asm.c:58

References file, cache_img_t::pathFileOffset, rz_buf_read_at(), and strdup().

Referenced by create_cache_bins().

◆ get_rebase_info()

static RzDyldRebaseInfo* get_rebase_info ( RzDyldCache cache,
ut64  slideInfoOffset,
ut64  slideInfoSize,
ut64  start_of_data,
ut64  slide 
)
static

Definition at line 764 of file dyldcache.c.

764  {
765  ut8 *tmp_buf_1 = NULL;
766  ut8 *tmp_buf_2 = NULL;
767  ut8 *one_page_buf = NULL;
768  RzBuffer *cache_buf = cache->buf;
769 
770  ut64 offset = slideInfoOffset;
771  ut32 slide_info_version = 0;
772  if (rz_buf_read_at(cache_buf, offset, (ut8 *)&slide_info_version, 4) != 4) {
773  return NULL;
774  }
775 
776  if (slide_info_version == 3) {
777  cache_slide3_t slide_info;
778  ut64 size = sizeof(cache_slide3_t);
779  if (rz_buf_fread_at(cache_buf, offset, (ut8 *)&slide_info, "4i1l", 1) < 20) {
780  return NULL;
781  }
782 
783  ut64 page_starts_offset = offset + size;
784  ut64 page_starts_size = slide_info.page_starts_count * 2;
785 
786  if (page_starts_size + size > slideInfoSize) {
787  return NULL;
788  }
789 
790  if (page_starts_size > 0) {
791  tmp_buf_1 = malloc(page_starts_size);
792  if (!tmp_buf_1) {
793  goto beach;
794  }
795  if (rz_buf_fread_at(cache_buf, page_starts_offset, tmp_buf_1, "s", slide_info.page_starts_count) != page_starts_size) {
796  goto beach;
797  }
798  }
799 
800  if (slide_info.page_size > 0) {
801  one_page_buf = malloc(slide_info.page_size);
802  if (!one_page_buf) {
803  goto beach;
804  }
805  }
806 
808  if (!rebase_info) {
809  goto beach;
810  }
811 
812  rebase_info->version = 3;
813  rebase_info->delta_mask = 0x3ff8000000000000ULL;
814  rebase_info->delta_shift = 51;
815  rebase_info->start_of_data = start_of_data;
816  rebase_info->page_starts = (ut16 *)tmp_buf_1;
817  rebase_info->page_starts_count = slide_info.page_starts_count;
818  rebase_info->auth_value_add = slide_info.auth_value_add;
819  rebase_info->page_size = slide_info.page_size;
820  rebase_info->one_page_buf = one_page_buf;
821  if (slide == UT64_MAX) {
822  rebase_info->slide = estimate_slide(cache, 0x7ffffffffffffULL, 0);
823  if (rebase_info->slide) {
824  RZ_LOG_INFO("dyldcache is slid: 0x%" PFMT64x "\n", rebase_info->slide);
825  }
826  } else {
827  rebase_info->slide = slide;
828  }
829 
830  return (RzDyldRebaseInfo *)rebase_info;
831  } else if (slide_info_version == 2 || slide_info_version == 4) {
832  cache_slide2_t slide_info;
833  ut64 size = sizeof(cache_slide2_t);
834  if (rz_buf_fread_at(cache_buf, offset, (ut8 *)&slide_info, "6i2l", 1) != size) {
835  return NULL;
836  }
837 
838  if (slide_info.page_starts_offset == 0 ||
839  slide_info.page_starts_offset > slideInfoSize ||
840  slide_info.page_starts_offset + slide_info.page_starts_count * 2 > slideInfoSize) {
841  return NULL;
842  }
843 
844  if (slide_info.page_extras_offset == 0 ||
845  slide_info.page_extras_offset > slideInfoSize ||
846  slide_info.page_extras_offset + slide_info.page_extras_count * 2 > slideInfoSize) {
847  return NULL;
848  }
849 
850  if (slide_info.page_starts_count > 0) {
851  ut64 size = slide_info.page_starts_count * 2;
852  ut64 at = slideInfoOffset + slide_info.page_starts_offset;
853  tmp_buf_1 = malloc(size);
854  if (!tmp_buf_1) {
855  goto beach;
856  }
857  if (rz_buf_fread_at(cache_buf, at, tmp_buf_1, "s", slide_info.page_starts_count) != size) {
858  goto beach;
859  }
860  }
861 
862  if (slide_info.page_extras_count > 0) {
863  ut64 size = slide_info.page_extras_count * 2;
864  ut64 at = slideInfoOffset + slide_info.page_extras_offset;
865  tmp_buf_2 = malloc(size);
866  if (!tmp_buf_2) {
867  goto beach;
868  }
869  if (rz_buf_fread_at(cache_buf, at, tmp_buf_2, "s", slide_info.page_extras_count) != size) {
870  goto beach;
871  }
872  }
873 
874  if (slide_info.page_size > 0) {
875  one_page_buf = malloc(slide_info.page_size);
876  if (!one_page_buf) {
877  goto beach;
878  }
879  }
880 
882  if (!rebase_info) {
883  goto beach;
884  }
885 
886  rebase_info->version = slide_info_version;
887  rebase_info->start_of_data = start_of_data;
888  rebase_info->page_starts = (ut16 *)tmp_buf_1;
889  rebase_info->page_starts_count = slide_info.page_starts_count;
890  rebase_info->page_extras = (ut16 *)tmp_buf_2;
891  rebase_info->page_extras_count = slide_info.page_extras_count;
892  rebase_info->value_add = slide_info.value_add;
893  rebase_info->delta_mask = slide_info.delta_mask;
894  rebase_info->value_mask = ~rebase_info->delta_mask;
895  rebase_info->delta_shift = dumb_ctzll(rebase_info->delta_mask) - 2;
896  rebase_info->page_size = slide_info.page_size;
897  rebase_info->one_page_buf = one_page_buf;
898  if (slide == UT64_MAX) {
899  rebase_info->slide = estimate_slide(cache, rebase_info->value_mask, rebase_info->value_add);
900  if (rebase_info->slide) {
901  RZ_LOG_INFO("dyldcache is slid: 0x%" PFMT64x "\n", rebase_info->slide);
902  }
903  } else {
904  rebase_info->slide = slide;
905  }
906 
907  return (RzDyldRebaseInfo *)rebase_info;
908  } else if (slide_info_version == 1) {
909  cache_slide1_t slide_info;
910  ut64 size = sizeof(cache_slide1_t);
911  if (rz_buf_fread_at(cache_buf, offset, (ut8 *)&slide_info, "6i", 1) != size) {
912  return NULL;
913  }
914 
915  if (slide_info.toc_offset == 0 ||
916  slide_info.toc_offset > slideInfoSize ||
917  slide_info.toc_offset + slide_info.toc_count * 2 > slideInfoSize) {
918  return NULL;
919  }
920 
921  if (slide_info.entries_offset == 0 ||
922  slide_info.entries_offset > slideInfoSize ||
923  slide_info.entries_offset + slide_info.entries_count * slide_info.entries_size > slideInfoSize) {
924  return NULL;
925  }
926 
927  if (slide_info.toc_count > 0) {
928  ut64 size = slide_info.toc_count * 2;
929  ut64 at = slideInfoOffset + slide_info.toc_offset;
930  tmp_buf_1 = malloc(size);
931  if (!tmp_buf_1) {
932  goto beach;
933  }
934  if (rz_buf_fread_at(cache_buf, at, tmp_buf_1, "s", slide_info.toc_count) != size) {
935  goto beach;
936  }
937  }
938 
939  if (slide_info.entries_count > 0) {
940  ut64 size = (ut64)slide_info.entries_count * (ut64)slide_info.entries_size;
941  ut64 at = slideInfoOffset + slide_info.entries_offset;
942  tmp_buf_2 = malloc(size);
943  if (!tmp_buf_2) {
944  goto beach;
945  }
946  if (rz_buf_read_at(cache_buf, at, tmp_buf_2, size) != size) {
947  goto beach;
948  }
949  }
950 
951  one_page_buf = malloc(4096);
952  if (!one_page_buf) {
953  goto beach;
954  }
955 
957  if (!rebase_info) {
958  goto beach;
959  }
960 
961  rebase_info->version = 1;
962  rebase_info->start_of_data = start_of_data;
963  rebase_info->one_page_buf = one_page_buf;
964  rebase_info->page_size = 4096;
965  rebase_info->toc = (ut16 *)tmp_buf_1;
966  rebase_info->toc_count = slide_info.toc_count;
967  rebase_info->entries = tmp_buf_2;
968  rebase_info->entries_size = slide_info.entries_size;
969  if (slide == UT64_MAX) {
970  rebase_info->slide = estimate_slide(cache, UT64_MAX, 0);
971  if (rebase_info->slide) {
972  RZ_LOG_INFO("dyldcache is slid: 0x%" PFMT64x "\n", rebase_info->slide);
973  }
974  } else {
975  rebase_info->slide = slide;
976  }
977 
978  return (RzDyldRebaseInfo *)rebase_info;
979  } else {
980  RZ_LOG_ERROR("Unsupported slide info version %d\n", slide_info_version);
981  return NULL;
982  }
983 
984 beach:
985  free(tmp_buf_1);
986  free(tmp_buf_2);
987  free(one_page_buf);
988  return NULL;
989 }
static ut64 estimate_slide(RzDyldCache *cache, ut64 value_mask, ut64 value_add)
Definition: dyldcache.c:674
static ut32 dumb_ctzll(ut64 x)
Definition: dyldcache.c:653
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
#define PFMT64x
Definition: rz_types.h:393

References rz_dyld_rebase_info_3_t::auth_value_add, cache_slide3_t::auth_value_add, rz_dyldcache_t::buf, rz_dyld_rebase_info_3_t::delta_mask, rz_dyld_rebase_info_2_t::delta_mask, cache_slide2_t::delta_mask, rz_dyld_rebase_info_3_t::delta_shift, rz_dyld_rebase_info_2_t::delta_shift, dumb_ctzll(), rz_dyld_rebase_info_1_t::entries, cache_slide1_t::entries_count, cache_slide1_t::entries_offset, rz_dyld_rebase_info_1_t::entries_size, cache_slide1_t::entries_size, estimate_slide(), free(), malloc(), NULL, rz_dyld_rebase_info_3_t::one_page_buf, rz_dyld_rebase_info_2_t::one_page_buf, rz_dyld_rebase_info_1_t::one_page_buf, rz_dyld_rebase_info_2_t::page_extras, rz_dyld_rebase_info_2_t::page_extras_count, cache_slide2_t::page_extras_count, cache_slide2_t::page_extras_offset, rz_dyld_rebase_info_3_t::page_size, rz_dyld_rebase_info_2_t::page_size, rz_dyld_rebase_info_1_t::page_size, cache_slide3_t::page_size, cache_slide2_t::page_size, rz_dyld_rebase_info_3_t::page_starts, rz_dyld_rebase_info_2_t::page_starts, rz_dyld_rebase_info_3_t::page_starts_count, rz_dyld_rebase_info_2_t::page_starts_count, cache_slide3_t::page_starts_count, cache_slide2_t::page_starts_count, cache_slide2_t::page_starts_offset, PFMT64x, rz_buf_fread_at(), rz_buf_read_at(), RZ_LOG_ERROR, RZ_LOG_INFO, RZ_NEW0, rz_dyld_rebase_info_3_t::slide, rz_dyld_rebase_info_2_t::slide, rz_dyld_rebase_info_1_t::slide, rz_dyld_rebase_info_3_t::start_of_data, rz_dyld_rebase_info_2_t::start_of_data, rz_dyld_rebase_info_1_t::start_of_data, rz_dyld_rebase_info_1_t::toc, rz_dyld_rebase_info_1_t::toc_count, cache_slide1_t::toc_count, cache_slide1_t::toc_offset, ut64(), UT64_MAX, rz_dyld_rebase_info_2_t::value_add, cache_slide2_t::value_add, rz_dyld_rebase_info_2_t::value_mask, rz_dyld_rebase_info_3_t::version, rz_dyld_rebase_info_2_t::version, and rz_dyld_rebase_info_1_t::version.

Referenced by get_rebase_infos().

◆ get_rebase_infos()

static RzDyldRebaseInfos* get_rebase_infos ( RzDyldCache cache)
static

Definition at line 991 of file dyldcache.c.

991  {
993  if (!result) {
994  return NULL;
995  }
996 
997  if (!cache->hdr->slideInfoOffset || !cache->hdr->slideInfoSize) {
998  ut32 total_slide_infos = 0;
999  ut32 n_slide_infos[MAX_N_HDR];
1000 
1001  ut32 i;
1002  for (i = 0; i < cache->n_hdr && i < MAX_N_HDR; i++) {
1003  ut64 hdr_offset = cache->hdr_offset[i];
1004  if (!rz_buf_read_le32_at(cache->buf, 0x13c + hdr_offset, &n_slide_infos[i])) {
1005  goto beach;
1006  }
1007  total_slide_infos += n_slide_infos[i];
1008  }
1009 
1010  if (!total_slide_infos) {
1011  goto beach;
1012  }
1013 
1014  RzDyldRebaseInfosEntry *infos = RZ_NEWS0(RzDyldRebaseInfosEntry, total_slide_infos);
1015  if (!infos) {
1016  goto beach;
1017  }
1018 
1019  ut32 k = 0;
1020  for (i = 0; i < cache->n_hdr && i < MAX_N_HDR; i++) {
1021  ut64 hdr_offset = cache->hdr_offset[i];
1022  if (!n_slide_infos[i]) {
1023  continue;
1024  }
1025  ut32 sio;
1026  if (!rz_buf_read_le32_at(cache->buf, 0x138 + hdr_offset, &sio)) {
1027  continue;
1028  }
1029  ut64 slide_infos_offset = sio;
1030  if (!slide_infos_offset) {
1031  continue;
1032  }
1033  slide_infos_offset += hdr_offset;
1034 
1035  ut32 j;
1036  RzDyldRebaseInfo *prev_info = NULL;
1037  for (j = 0; j < n_slide_infos[i]; j++) {
1038  ut64 offset = slide_infos_offset + j * sizeof(cache_mapping_slide);
1040  if (rz_buf_fread_at(cache->buf, offset, (ut8 *)&entry, "6lii", 1) != sizeof(cache_mapping_slide)) {
1041  break;
1042  }
1043 
1044  if (entry.slideInfoOffset && entry.slideInfoSize) {
1045  infos[k].start = entry.fileOffset + hdr_offset;
1046  infos[k].end = infos[k].start + entry.size;
1047  ut64 slide = prev_info ? prev_info->slide : UT64_MAX;
1048  infos[k].info = get_rebase_info(cache, entry.slideInfoOffset + hdr_offset, entry.slideInfoSize, entry.fileOffset + hdr_offset, slide);
1049  prev_info = infos[k].info;
1050  k++;
1051  }
1052  }
1053  }
1054 
1055  if (!k) {
1056  free(infos);
1057  goto beach;
1058  }
1059 
1060  if (k < total_slide_infos) {
1062  if (!pruned_infos) {
1063  free(infos);
1064  goto beach;
1065  }
1066 
1067  memcpy(pruned_infos, infos, sizeof(RzDyldRebaseInfosEntry) * k);
1068  free(infos);
1069  infos = pruned_infos;
1070  }
1071 
1072  result->entries = infos;
1073  result->length = k;
1074  return result;
1075  }
1076 
1077  if (cache->hdr->mappingCount > 1) {
1079  if (!infos) {
1080  goto beach;
1081  }
1082 
1083  infos[0].start = cache->maps[1].fileOffset;
1084  infos[0].end = infos[0].start + cache->maps[1].size;
1085  infos[0].info = get_rebase_info(cache, cache->hdr->slideInfoOffset, cache->hdr->slideInfoSize, infos[0].start, UT64_MAX);
1086 
1087  result->entries = infos;
1088  result->length = 1;
1089  return result;
1090  }
1091 
1092 beach:
1093  free(result);
1094  return NULL;
1095 }
static RzDyldRebaseInfo * get_rebase_info(RzDyldCache *cache, ut64 slideInfoOffset, ut64 slideInfoSize, ut64 start_of_data, ut64 slide)
Definition: dyldcache.c:764
#define MAX_N_HDR
Definition: dyldcache.c:11
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
#define rz_buf_read_le32_at(b, addr, result)
Definition: rz_buf.h:271
uint64_t slideInfoOffset
Definition: mach0_specs.h:219
uint64_t slideInfoSize
Definition: mach0_specs.h:220
uint64_t size
Definition: mach0_specs.h:242
uint64_t fileOffset
Definition: mach0_specs.h:243
Definition: zipcmp.c:77
zip_uint64_t size
Definition: zipcmp.c:79
Definition: dyldcache.h:23
ut64 start
Definition: dyldcache.h:24
RzDyldRebaseInfo * info
Definition: dyldcache.h:26
ut64 end
Definition: dyldcache.h:25
RzDyldRebaseInfosEntry * entries
Definition: dyldcache.h:30

References rz_dyldcache_t::buf, rz_dyld_rebase_infos_entry_t::end, rz_dyld_rebase_infos_t::entries, cache_map_t::fileOffset, free(), get_rebase_info(), rz_dyldcache_t::hdr, rz_dyldcache_t::hdr_offset, i, rz_dyld_rebase_infos_entry_t::info, k, rz_dyld_rebase_infos_t::length, cache_hdr_t::mappingCount, rz_dyldcache_t::maps, MAX_N_HDR, memcpy(), rz_dyldcache_t::n_hdr, NULL, rz_buf_fread_at(), rz_buf_read_le32_at, RZ_NEW0, RZ_NEWS0, cache_map_t::size, entry::size, rz_dyld_rebase_info_t::slide, cache_hdr_t::slideInfoOffset, cache_hdr_t::slideInfoSize, rz_dyld_rebase_infos_entry_t::start, ut64(), and UT64_MAX.

Referenced by rz_dyldcache_new_buf().

◆ match_bin_entries()

static void match_bin_entries ( RzDyldCache cache,
void *  entries 
)
static

Definition at line 346 of file dyldcache.c.

346  {
347  rz_return_if_fail(cache && cache->bins && entries);
348 
349  cache_img_t *imgs = read_cache_images(cache->buf, cache->hdr, 0);
350  if (!imgs) {
351  return;
352  }
353 
355  RzListIter *it = rz_list_iterator(cache->bins);
356 
357  bool has_large_entries = cache->n_hdr > 1;
358 
359  ut32 i;
360  for (i = 0; i < cache->hdr->imagesCount; i++) {
361  cache_img_t *img = &imgs[i];
362  if (!it) {
363  break;
364  }
365  bin = it->data;
366  if (!bin) {
367  break;
368  }
369  if (bin && bin->va == img->address) {
370  if (has_large_entries) {
372  bin->nlist_start_index = e->nlistStartIndex;
373  bin->nlist_count = e->nlistCount;
374  } else {
376  bin->nlist_start_index = e->nlistStartIndex;
377  bin->nlist_count = e->nlistCount;
378  }
379  it = it->n;
380  }
381  }
382 
383  RZ_FREE(imgs);
384 }
#define e(frag)
RzList * entries(RzBinFile *bf)
Definition: bin_ne.c:98
RZ_API RZ_BORROW RzListIter * rz_list_iterator(const RzList *list)
returns the first RzList iterator int the list
Definition: list.c:51
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
Definition: mach0_specs.h:328
Definition: mach0_specs.h:322
struct rz_list_iter_t * n
Definition: rz_list.h:15
void * data
Definition: rz_list.h:14

References cache_img_t::address, rz_dyldcache_t::bins, rz_dyldcache_t::buf, rz_list_iter_t::data, e, entries(), rz_dyldcache_t::hdr, i, cache_hdr_t::imagesCount, rz_list_iter_t::n, rz_dyldcache_t::n_hdr, NULL, read_cache_images(), RZ_FREE, rz_list_iterator(), and rz_return_if_fail.

Referenced by rz_dyld_locsym_new().

◆ populate_cache_headers()

static void populate_cache_headers ( RzDyldCache cache)
static

Definition at line 81 of file dyldcache.c.

81  {
82  cache->n_hdr = 0;
83  RzList *hdrs = rz_list_newf(NULL);
84  if (!hdrs) {
85  return;
86  }
87 
88  cache_hdr_t *h;
89  ut64 offsets[MAX_N_HDR];
90  ut64 offset = 0;
91  do {
92  offsets[cache->n_hdr] = offset;
93  h = read_cache_header(cache->buf, offset);
94  if (!h) {
95  break;
96  }
97  rz_list_append(hdrs, h);
98 
99  ut64 size = h->codeSignatureOffset + h->codeSignatureSize;
100 
101 #define SHIFT_MAYBE(x) \
102  if (x) { \
103  x += offset; \
104  }
105 
106  SHIFT_MAYBE(h->mappingOffset);
107  SHIFT_MAYBE(h->imagesOffset);
108  SHIFT_MAYBE(h->codeSignatureOffset);
109  SHIFT_MAYBE(h->slideInfoOffset);
110  SHIFT_MAYBE(h->localSymbolsOffset);
111  SHIFT_MAYBE(h->branchPoolsOffset);
112  SHIFT_MAYBE(h->imagesTextOffset);
113 
114  offset += size;
115  cache->n_hdr++;
116  } while (cache->n_hdr < MAX_N_HDR);
117 
118  if (!cache->n_hdr) {
119  goto beach;
120  }
121 
122  cache->hdr = RZ_NEWS0(cache_hdr_t, cache->n_hdr);
123  if (!cache->hdr) {
124  cache->n_hdr = 0;
125  goto beach;
126  }
127 
128  cache->hdr_offset = RZ_NEWS0(ut64, cache->n_hdr);
129  if (!cache->hdr_offset) {
130  cache->n_hdr = 0;
131  RZ_FREE(cache->hdr);
132  goto beach;
133  }
134 
135  memcpy(cache->hdr_offset, offsets, cache->n_hdr * sizeof(ut64));
136 
137  ut32 i = 0;
138  RzListIter *iter;
139  cache_hdr_t *item;
140  rz_list_foreach (hdrs, iter, item) {
141  if (i >= cache->n_hdr) {
142  break;
143  }
144  memcpy(&cache->hdr[i++], item, sizeof(cache_hdr_t));
145  }
146 
147 beach:
148  rz_list_free(hdrs);
149 }
static cache_hdr_t * read_cache_header(RzBuffer *cache_buf, ut64 offset)
Definition: dyldcache.c:52
#define SHIFT_MAYBE(x)
#define h(i)
Definition: sha256.c:48

References rz_dyldcache_t::buf, h, rz_dyldcache_t::hdr, rz_dyldcache_t::hdr_offset, i, MAX_N_HDR, memcpy(), rz_dyldcache_t::n_hdr, NULL, read_cache_header(), RZ_FREE, rz_list_append(), rz_list_free(), rz_list_newf(), RZ_NEWS0, SHIFT_MAYBE, and ut64().

Referenced by rz_dyldcache_new_buf().

◆ populate_cache_maps()

static void populate_cache_maps ( RzDyldCache cache)
static

Definition at line 151 of file dyldcache.c.

151  {
152  rz_return_if_fail(cache && cache->buf);
153 
154  ut32 i;
155  ut32 n_maps = 0;
156  ut64 max_count = 0;
157  for (i = 0; i < cache->n_hdr; i++) {
158  cache_hdr_t *hdr = &cache->hdr[i];
159  if (!hdr->mappingCount || !hdr->mappingOffset) {
160  continue;
161  }
163  n_maps += hdr->mappingCount;
164  }
165 
166  if (n_maps < 1 || n_maps < max_count /* overflow */) {
167  cache->maps = NULL;
168  cache->n_maps = 0;
169  return;
170  }
171 
172  cache->maps_index = RZ_NEWS0(ut32, cache->n_hdr);
173  if (!cache->maps_index) {
174  return;
175  }
176  cache_map_t *maps = RZ_NEWS0(cache_map_t, n_maps);
177 
178  ut32 next_map = 0;
179  ut32 last_idx = UT32_MAX;
180  ut64 max_address = 0;
181  for (i = 0; i < cache->n_hdr; i++) {
182  cache_hdr_t *hdr = &cache->hdr[i];
183  cache->maps_index[i] = next_map;
184 
185  if (!hdr->mappingCount || !hdr->mappingOffset) {
186  continue;
187  }
188  ut64 size = sizeof(cache_map_t) * hdr->mappingCount;
189  if (rz_buf_fread_at(cache->buf, hdr->mappingOffset, (ut8 *)&maps[next_map], "3l2i", hdr->mappingCount) != size) {
190  continue;
191  }
192  ut32 j;
193  ut64 hdr_offset = cache->hdr_offset[i];
194  for (j = 0; j < hdr->mappingCount; j++) {
195  cache_map_t *map = &maps[next_map + j];
196  map->fileOffset += hdr_offset;
197  if (map->address > max_address) {
198  last_idx = i;
199  max_address = map->address;
200  }
201  }
202  next_map += hdr->mappingCount;
203  }
204 
205  cache->maps = maps;
206  cache->n_maps = next_map;
207  if (last_idx == UT32_MAX) {
208  cache->symbols_off_base = 0;
209  } else {
210  cache->symbols_off_base = cache->hdr_offset[last_idx];
211  }
212 }
static RzList * maps(RzBinFile *bf)
Definition: bin_bf.c:116
size_t map(int syms, int left, int len)
Definition: enough.c:237
static size_t max_count
Definition: malloc.c:67
#define UT32_MAX
Definition: rz_types_base.h:99
#define RZ_MAX(x, y)
uint32_t mappingOffset
Definition: mach0_specs.h:212
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4

References rz_dyldcache_t::buf, rz_dyldcache_t::hdr, rz_dyldcache_t::hdr_offset, i, if(), map(), cache_hdr_t::mappingCount, cache_hdr_t::mappingOffset, rz_dyldcache_t::maps, maps(), rz_dyldcache_t::maps_index, max_count, rz_dyldcache_t::n_hdr, rz_dyldcache_t::n_maps, NULL, rz_buf_fread_at(), RZ_MAX, RZ_NEWS0, rz_return_if_fail, rz_dyldcache_t::symbols_off_base, UT32_MAX, and ut64().

Referenced by rz_dyldcache_new_buf().

◆ read_cache_accel()

static cache_accel_t* read_cache_accel ( RzBuffer cache_buf,
cache_hdr_t hdr,
cache_map_t maps 
)
static

Definition at line 214 of file dyldcache.c.

214  {
215  if (!cache_buf || !hdr || !hdr->accelerateInfoSize || !hdr->accelerateInfoAddr) {
216  return NULL;
217  }
218 
219  ut64 offset = va2pa(hdr->accelerateInfoAddr, hdr->mappingCount, maps, cache_buf, 0, NULL, NULL);
220  if (!offset) {
221  return NULL;
222  }
223 
224  ut64 size = sizeof(cache_accel_t);
226  if (!accel) {
227  return NULL;
228  }
229 
230  if (rz_buf_fread_at(cache_buf, offset, (ut8 *)accel, "16il", 1) != size) {
231  RZ_FREE(accel);
232  return NULL;
233  }
234 
235  accel->imagesExtrasOffset += offset;
236  accel->bottomUpListOffset += offset;
237  accel->dylibTrieOffset += offset;
238  accel->initializersOffset += offset;
239  accel->dofSectionsOffset += offset;
240  accel->reExportListOffset += offset;
241  accel->depListOffset += offset;
242  accel->rangeTableOffset += offset;
243 
244  return accel;
245 }
uint64_t accelerateInfoAddr
Definition: mach0_specs.h:227
uint64_t accelerateInfoSize
Definition: mach0_specs.h:228

References cache_hdr_t::accelerateInfoAddr, cache_hdr_t::accelerateInfoSize, cache_accel_t::bottomUpListOffset, cache_accel_t::depListOffset, cache_accel_t::dofSectionsOffset, cache_accel_t::dylibTrieOffset, cache_accel_t::imagesExtrasOffset, cache_accel_t::initializersOffset, cache_hdr_t::mappingCount, maps(), NULL, cache_accel_t::rangeTableOffset, cache_accel_t::reExportListOffset, rz_buf_fread_at(), RZ_FREE, RZ_NEW0, ut64(), and va2pa().

Referenced by rz_dyldcache_new_buf().

◆ read_cache_header()

static cache_hdr_t* read_cache_header ( RzBuffer cache_buf,
ut64  offset 
)
static

Definition at line 52 of file dyldcache.c.

52  {
53  if (!cache_buf) {
54  return NULL;
55  }
56 
58  if (!hdr) {
59  return NULL;
60  }
61 
62  ut64 size = sizeof(cache_hdr_t);
63  if (rz_buf_fread_at(cache_buf, offset, (ut8 *)hdr, "16c4i7l16clii4l", 1) != size) {
64  free(hdr);
65  return NULL;
66  }
67  if (!rz_dyldcache_check_magic(hdr->magic)) {
68  free(hdr);
69  return NULL;
70  }
71 
72  if (!hdr->imagesCount && !hdr->imagesOffset) {
73  if (!rz_buf_read_le32_at(cache_buf, 0x1c0 + offset, &hdr->imagesOffset) || !rz_buf_read_le32_at(cache_buf, 0x1c4 + offset, &hdr->imagesCount)) {
74  free(hdr);
75  return NULL;
76  }
77  }
78  return hdr;
79 }
RZ_API bool rz_dyldcache_check_magic(const char *magic)
Definition: dyldcache.c:18

References free(), cache_hdr_t::imagesCount, cache_hdr_t::imagesOffset, cache_hdr_t::magic, NULL, rz_buf_fread_at(), rz_buf_read_le32_at, rz_dyldcache_check_magic(), RZ_NEW0, and ut64().

Referenced by populate_cache_headers().

◆ read_cache_images()

static cache_img_t* read_cache_images ( RzBuffer cache_buf,
cache_hdr_t hdr,
ut64  hdr_offset 
)
static

Definition at line 316 of file dyldcache.c.

316  {
317  if (!cache_buf || !hdr) {
318  return NULL;
319  }
320  if (!hdr->imagesCount || !hdr->imagesOffset || hdr->imagesOffset == UT32_MAX || hdr->imagesCount == UT32_MAX) {
321  return NULL;
322  }
323 
324  ut64 size = sizeof(cache_img_t) * hdr->imagesCount;
325  cache_img_t *images = RZ_NEWS0(cache_img_t, hdr->imagesCount);
326  if (!images) {
327  return NULL;
328  }
329 
330  if (rz_buf_fread_at(cache_buf, hdr->imagesOffset, (ut8 *)images, "3l2i", hdr->imagesCount) != size) {
331  RZ_FREE(images);
332  return NULL;
333  }
334 
335  if (hdr_offset) {
336  ut32 i;
337  for (i = 0; i < hdr->imagesCount; i++) {
338  cache_img_t *img = &images[i];
339  img->pathFileOffset += hdr_offset;
340  }
341  }
342 
343  return images;
344 }
uint32_t imagesOffset
Definition: mach0_specs.h:214

References i, cache_hdr_t::imagesCount, cache_hdr_t::imagesOffset, NULL, cache_img_t::pathFileOffset, rz_buf_fread_at(), RZ_FREE, RZ_NEWS0, UT32_MAX, and ut64().

Referenced by create_cache_bins(), and match_bin_entries().

◆ read_cache_imgextra()

static cache_imgxtr_t* read_cache_imgextra ( RzBuffer cache_buf,
cache_hdr_t hdr,
cache_accel_t accel 
)
static

Definition at line 386 of file dyldcache.c.

386  {
387  if (!cache_buf || !hdr || !hdr->imagesCount || !accel || !accel->imageExtrasCount || !accel->imagesExtrasOffset) {
388  return NULL;
389  }
390 
391  ut64 size = sizeof(cache_imgxtr_t) * accel->imageExtrasCount;
393  if (!images) {
394  return NULL;
395  }
396 
397  if (rz_buf_fread_at(cache_buf, accel->imagesExtrasOffset, (ut8 *)images, "ll4i", accel->imageExtrasCount) != size) {
398  RZ_FREE(images);
399  return NULL;
400  }
401 
402  return images;
403 }
uint32_t imageExtrasCount
Definition: mach0_specs.h:286
uint32_t imagesExtrasOffset
Definition: mach0_specs.h:287

References cache_accel_t::imageExtrasCount, cache_hdr_t::imagesCount, cache_accel_t::imagesExtrasOffset, NULL, rz_buf_fread_at(), RZ_FREE, RZ_NEWS0, and ut64().

Referenced by create_cache_bins().

◆ rebase_info1_free()

static void rebase_info1_free ( RzDyldRebaseInfo1 rebase_info)
static

Definition at line 1215 of file dyldcache.c.

1215  {
1216  if (!rebase_info) {
1217  return;
1218  }
1219  free(rebase_info->toc);
1220  free(rebase_info->entries);
1221  free(rebase_info);
1222 }

References rz_dyld_rebase_info_1_t::entries, free(), and rz_dyld_rebase_info_1_t::toc.

Referenced by rebase_info_free().

◆ rebase_info2_free()

static void rebase_info2_free ( RzDyldRebaseInfo2 rebase_info)
static

Definition at line 1206 of file dyldcache.c.

1206  {
1207  if (!rebase_info) {
1208  return;
1209  }
1210  free(rebase_info->page_starts);
1211  free(rebase_info->page_extras);
1212  free(rebase_info);
1213 }

References free(), rz_dyld_rebase_info_2_t::page_extras, and rz_dyld_rebase_info_2_t::page_starts.

Referenced by rebase_info_free().

◆ rebase_info3_free()

static void rebase_info3_free ( RzDyldRebaseInfo3 rebase_info)
static

Definition at line 1198 of file dyldcache.c.

1198  {
1199  if (!rebase_info) {
1200  return;
1201  }
1202  free(rebase_info->page_starts);
1203  free(rebase_info);
1204 }

References free(), and rz_dyld_rebase_info_3_t::page_starts.

Referenced by rebase_info_free().

◆ rebase_info_free()

static void rebase_info_free ( RzDyldRebaseInfo rebase_info)
static

Definition at line 1224 of file dyldcache.c.

1224  {
1225  if (!rebase_info) {
1226  return;
1227  }
1228 
1229  RZ_FREE(rebase_info->one_page_buf);
1230 
1231  ut8 version = rebase_info->version;
1232 
1233  if (version == 1) {
1234  rebase_info1_free((RzDyldRebaseInfo1 *)rebase_info);
1235  } else if (version == 2 || version == 4) {
1236  rebase_info2_free((RzDyldRebaseInfo2 *)rebase_info);
1237  } else if (version == 3) {
1238  rebase_info3_free((RzDyldRebaseInfo3 *)rebase_info);
1239  } else {
1240  free(rebase_info);
1241  }
1242 }
static void rebase_info2_free(RzDyldRebaseInfo2 *rebase_info)
Definition: dyldcache.c:1206
static void rebase_info3_free(RzDyldRebaseInfo3 *rebase_info)
Definition: dyldcache.c:1198
static void rebase_info1_free(RzDyldRebaseInfo1 *rebase_info)
Definition: dyldcache.c:1215

References free(), rz_dyld_rebase_info_t::one_page_buf, rebase_info1_free(), rebase_info2_free(), rebase_info3_free(), RZ_FREE, and rz_dyld_rebase_info_t::version.

Referenced by rz_dyldcache_free().

◆ rz_dyld_locsym_new()

static RzDyldLocSym * rz_dyld_locsym_new ( RzDyldCache cache)
static

Definition at line 1244 of file dyldcache.c.

1244  {
1245  rz_return_val_if_fail(cache && cache->buf, NULL);
1246 
1247  ut32 i;
1248  for (i = 0; i < cache->n_hdr; i++) {
1249  cache_hdr_t *hdr = &cache->hdr[i];
1250  if (!hdr || !hdr->localSymbolsSize || !hdr->localSymbolsOffset) {
1251  continue;
1252  }
1253 
1255  void *entries = NULL;
1256 
1257  ut64 info_size = sizeof(cache_locsym_info_t);
1259  if (!info) {
1260  goto beach;
1261  }
1262  if (rz_buf_fread_at(cache->buf, hdr->localSymbolsOffset, (ut8 *)info, "6i", 1) != info_size) {
1263  RZ_LOG_ERROR("Cannot read cache_locsym_info_t from header\n");
1264  goto beach;
1265  }
1266  if (info->entriesCount != cache->hdr->imagesCount) {
1267  RZ_LOG_ERROR("The number of entries count differs from cache header image count\n");
1268  goto beach;
1269  }
1270 
1271  bool has_large_entries = cache->n_hdr > 1;
1272  if (has_large_entries) {
1273  ut64 entries_size = sizeof(cache_locsym_entry_large_t) * info->entriesCount;
1274  cache_locsym_entry_large_t *large_entries = RZ_NEWS0(cache_locsym_entry_large_t, info->entriesCount);
1275  if (!large_entries) {
1276  goto beach;
1277  }
1278  if (rz_buf_fread_at(cache->buf, hdr->localSymbolsOffset + info->entriesOffset, (ut8 *)large_entries, "lii",
1279  info->entriesCount) != entries_size) {
1280  RZ_LOG_ERROR("Cannot read cache_locsym_entry_large_t\n");
1281  goto beach;
1282  }
1283  entries = large_entries;
1284  } else {
1285  ut64 entries_size = sizeof(cache_locsym_entry_t) * info->entriesCount;
1286  cache_locsym_entry_t *regular_entries = RZ_NEWS0(cache_locsym_entry_t, info->entriesCount);
1287  if (!regular_entries) {
1288  goto beach;
1289  }
1290  if (rz_buf_fread_at(cache->buf, hdr->localSymbolsOffset + info->entriesOffset, (ut8 *)regular_entries, "iii",
1291  info->entriesCount) != entries_size) {
1292  RZ_LOG_ERROR("Cannot read cache_locsym_entry_t\n");
1293  goto beach;
1294  }
1295  entries = regular_entries;
1296  }
1297  RzDyldLocSym *locsym = RZ_NEW0(RzDyldLocSym);
1298  if (!locsym) {
1299  goto beach;
1300  }
1301 
1302  match_bin_entries(cache, entries);
1303 
1305  locsym->nlists_offset = info->nlistOffset;
1306  locsym->nlists_count = info->nlistCount;
1307  locsym->strings_offset = info->stringsOffset;
1308  locsym->strings_size = info->stringsSize;
1309 
1310  free(info);
1311  free(entries);
1312 
1313  return locsym;
1314 
1315  beach:
1316  free(info);
1317  free(entries);
1318 
1319  RZ_LOG_ERROR("dyldcache: malformed local symbols metadata\n");
1320  break;
1321  }
1322  return NULL;
1323 }
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
static void match_bin_entries(RzDyldCache *cache, void *entries)
Definition: dyldcache.c:346
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
uint64_t localSymbolsOffset
Definition: mach0_specs.h:221
uint64_t localSymbolsSize
Definition: mach0_specs.h:222
ut64 local_symbols_offset
Definition: dyldcache.h:76

References rz_dyldcache_t::buf, entries(), free(), rz_dyldcache_t::hdr, i, cache_hdr_t::imagesCount, info(), rz_dyld_loc_sym_t::local_symbols_offset, cache_hdr_t::localSymbolsOffset, cache_hdr_t::localSymbolsSize, match_bin_entries(), rz_dyldcache_t::n_hdr, rz_dyld_loc_sym_t::nlists_count, rz_dyld_loc_sym_t::nlists_offset, NULL, rz_buf_fread_at(), RZ_LOG_ERROR, RZ_NEW0, RZ_NEWS0, rz_return_val_if_fail, rz_dyld_loc_sym_t::strings_offset, rz_dyld_loc_sym_t::strings_size, and ut64().

Referenced by rz_dyldcache_new_buf().

◆ rz_dyldcache_check_magic()

RZ_API bool rz_dyldcache_check_magic ( const char *  magic)
Parameters
magiczero-terminated string from the beginning of some file

Definition at line 18 of file dyldcache.c.

18  {
19  return !strcmp(magic, "dyld_v1 arm64") || !strcmp(magic, "dyld_v1 arm64e") || !strcmp(magic, "dyld_v1 x86_64") || !strcmp(magic, "dyld_v1 x86_64h");
20 }

Referenced by check_buffer(), and read_cache_header().

◆ rz_dyldcache_free()

RZ_API void rz_dyldcache_free ( RzDyldCache cache)

Definition at line 1325 of file dyldcache.c.

1325  {
1326  if (!cache) {
1327  return;
1328  }
1329 
1330  rz_list_free(cache->bins);
1331  cache->bins = NULL;
1332  rz_buf_free(cache->buf);
1333  cache->buf = NULL;
1334  if (cache->rebase_infos) {
1335  int i;
1336  for (i = 0; i < cache->rebase_infos->length; i++) {
1338  cache->rebase_infos->entries[i].info = NULL;
1339  }
1340  RZ_FREE(cache->rebase_infos->entries);
1341  RZ_FREE(cache->rebase_infos);
1342  }
1343  free(cache->hdr);
1344  free(cache->maps);
1345  free(cache->maps_index);
1346  free(cache->hdr_offset);
1347  free(cache->accel);
1348  free(cache->locsym);
1349  free(cache->oi);
1350  free(cache);
1351 }
static void rebase_info_free(RzDyldRebaseInfo *rebase_info)
Definition: dyldcache.c:1224
RZ_API void rz_buf_free(RzBuffer *b)
Free all internal data hold by the buffer and the buffer.
Definition: buf.c:1253
objc_cache_opt_info * oi
Definition: dyldcache.h:109
RzDyldRebaseInfos * rebase_infos
Definition: dyldcache.h:106
RzDyldLocSym * locsym
Definition: dyldcache.h:108

References rz_dyldcache_t::accel, rz_dyldcache_t::bins, rz_dyldcache_t::buf, rz_dyld_rebase_infos_t::entries, free(), rz_dyldcache_t::hdr, rz_dyldcache_t::hdr_offset, i, rz_dyld_rebase_infos_entry_t::info, rz_dyld_rebase_infos_t::length, rz_dyldcache_t::locsym, rz_dyldcache_t::maps, rz_dyldcache_t::maps_index, NULL, rz_dyldcache_t::oi, rebase_info_free(), rz_dyldcache_t::rebase_infos, rz_buf_free(), RZ_FREE, and rz_list_free().

Referenced by destroy(), and rz_dyldcache_new_buf().

◆ rz_dyldcache_get_objc_opt_info()

RZ_API objc_cache_opt_info* rz_dyldcache_get_objc_opt_info ( RzBinFile bf,
RzDyldCache cache 
)

Definition at line 247 of file dyldcache.c.

247  {
248  objc_cache_opt_info *result = NULL;
249  RzListIter *iter;
251  rz_list_foreach (cache->bins, iter, bin) {
252  if (strcmp(bin->file, "lib/libobjc.A.dylib")) {
253  continue;
254  }
255 
256  struct MACH0_(opts_t) opts = { 0 };
257  opts.verbose = bf->rbin->verbose;
258  opts.header_at = bin->header_at;
259 
260  struct MACH0_(obj_t) *mach0 = MACH0_(new_buf)(cache->buf, &opts);
261  if (!mach0) {
262  goto beach;
263  }
264 
265  struct section_t *sections = NULL;
266  if (!(sections = MACH0_(get_sections)(mach0))) {
268  (mach0);
269  goto beach;
270  }
271 
272  int i;
273  ut64 scoffs_offset = 0;
274  ut64 scoffs_size = 0;
275  ut64 slide = rz_dyldcache_get_slide(cache);
276  for (i = 0; !sections[i].last; i++) {
277  if (sections[i].size == 0) {
278  continue;
279  }
280  if (strstr(sections[i].name, "__objc_scoffs")) {
281  scoffs_offset = va2pa(sections[i].addr, cache->n_maps, cache->maps, cache->buf, slide, NULL, NULL);
282  scoffs_size = sections[i].size;
283  break;
284  }
285  }
286 
288  (mach0);
289  RZ_FREE(sections);
290 
291  if (!scoffs_offset || scoffs_size < 40) {
292  break;
293  }
294  ut64 check;
295  if (!rz_buf_read_le64_at(cache->buf, scoffs_offset, &check) || check != 2) {
296  break;
297  }
298  ut64 sel_string_base;
299  if (!rz_buf_read_le64_at(cache->buf, scoffs_offset + 8, &sel_string_base)) {
300  break;
301  }
302  ut64 sel_string_end;
303  if (!rz_buf_read_le64_at(cache->buf, scoffs_offset + 16, &sel_string_end) || sel_string_end == sel_string_base) {
304  break;
305  }
306  result = RZ_NEW0(objc_cache_opt_info);
307  if (!result) {
308  break;
309  }
310  result->sel_string_base = sel_string_base;
311  }
312 beach:
313  return result;
314 }
lzma_check check
Definition: container.h:292
RZ_API ut64 rz_dyldcache_get_slide(RzDyldCache *cache)
Definition: dyldcache.c:1097
#define rz_buf_read_le64_at(b, addr, result)
Definition: rz_buf.h:272
uint64_t sel_string_base
Definition: mach0_specs.h:346
struct rz_bin_t * rbin
Definition: rz_bin.h:316
bool verbose
Definition: rz_bin.h:359
static int addr
Definition: z80asm.c:58

References addr, rz_dyldcache_t::bins, rz_dyldcache_t::buf, check, get_sections(), i, MACH0_, mach0_free(), rz_dyldcache_t::maps, rz_dyldcache_t::n_maps, NULL, rz_bin_file_t::rbin, rz_buf_read_le64_at, rz_dyldcache_get_slide(), RZ_FREE, RZ_NEW0, sections(), objc_cache_opt_info::sel_string_base, ut64(), va2pa(), and rz_bin_t::verbose.

Referenced by classes().

◆ rz_dyldcache_get_slide()

RZ_API ut64 rz_dyldcache_get_slide ( RzDyldCache cache)

Definition at line 1097 of file dyldcache.c.

1097  {
1098  rz_return_val_if_fail(cache, 0);
1099  if (!cache->rebase_infos || !cache->rebase_infos->length) {
1100  return 0;
1101  }
1102 
1103  size_t i;
1104  for (i = 0; i < cache->rebase_infos->length; i++) {
1105  if (cache->rebase_infos->entries[i].info) {
1106  return cache->rebase_infos->entries[i].info->slide;
1107  }
1108  }
1109 
1110  return 0;
1111 }

References rz_dyld_rebase_infos_t::entries, i, rz_dyld_rebase_infos_entry_t::info, rz_dyld_rebase_infos_t::length, rz_dyldcache_t::rebase_infos, rz_return_val_if_fail, and rz_dyld_rebase_info_t::slide.

Referenced by header(), maps(), rz_dyldcache_get_objc_opt_info(), rz_dyldcache_needs_rebasing(), rz_dyldcache_symbols_from_locsym(), rz_dyldcache_va2pa(), sections(), and symbols().

◆ rz_dyldcache_new_buf()

RZ_API RzDyldCache* rz_dyldcache_new_buf ( RzBuffer buf)

Definition at line 1170 of file dyldcache.c.

1170  {
1171  RzDyldCache *cache = RZ_NEW0(RzDyldCache);
1172  if (!cache) {
1173  return NULL;
1174  }
1175  memcpy(cache->magic, "dyldcac", 7);
1176  cache->buf = rz_buf_ref(buf);
1177  populate_cache_headers(cache);
1178  if (!cache->hdr) {
1179  goto cupertino;
1180  }
1181  populate_cache_maps(cache);
1182  if (!cache->maps) {
1183  goto cupertino;
1184  }
1185  cache->accel = read_cache_accel(cache->buf, cache->hdr, cache->maps);
1186  cache->bins = create_cache_bins(cache);
1187  if (!cache->bins) {
1188  goto cupertino;
1189  }
1190  cache->locsym = rz_dyld_locsym_new(cache);
1191  cache->rebase_infos = get_rebase_infos(cache);
1192  return cache;
1193 cupertino:
1194  rz_dyldcache_free(cache);
1195  return NULL;
1196 }
static RzDyldLocSym * rz_dyld_locsym_new(RzDyldCache *cache)
Definition: dyldcache.c:1244
RZ_API void rz_dyldcache_free(RzDyldCache *cache)
Definition: dyldcache.c:1325
static void populate_cache_headers(RzDyldCache *cache)
Definition: dyldcache.c:81
static RzList * create_cache_bins(RzDyldCache *cache)
Definition: dyldcache.c:485
static cache_accel_t * read_cache_accel(RzBuffer *cache_buf, cache_hdr_t *hdr, cache_map_t *maps)
Definition: dyldcache.c:214
static RzDyldRebaseInfos * get_rebase_infos(RzDyldCache *cache)
Definition: dyldcache.c:991
static void populate_cache_maps(RzDyldCache *cache)
Definition: dyldcache.c:151
voidpf void * buf
Definition: ioapi.h:138
RZ_API RzBuffer * rz_buf_ref(RzBuffer *b)
Increment the reference count of the buffer.
Definition: buf.c:668
ut8 magic[8]
Definition: dyldcache.h:94

References rz_dyldcache_t::accel, rz_dyldcache_t::bins, rz_dyldcache_t::buf, create_cache_bins(), get_rebase_infos(), rz_dyldcache_t::hdr, rz_dyldcache_t::locsym, rz_dyldcache_t::magic, rz_dyldcache_t::maps, memcpy(), NULL, populate_cache_headers(), populate_cache_maps(), read_cache_accel(), rz_dyldcache_t::rebase_infos, rz_buf_ref(), rz_dyld_locsym_new(), rz_dyldcache_free(), and RZ_NEW0.

Referenced by load_buffer().

◆ rz_dyldcache_symbols_from_locsym()

RZ_API void rz_dyldcache_symbols_from_locsym ( RzDyldCache cache,
RzDyldBinImage bin,
RzList symbols,
SetU hash 
)

Definition at line 1113 of file dyldcache.c.

1113  {
1114  RzDyldLocSym *locsym = cache->locsym;
1115  if (!locsym) {
1116  return;
1117  }
1118 
1119  if (bin->nlist_start_index >= locsym->nlists_count ||
1120  bin->nlist_start_index + bin->nlist_count > locsym->nlists_count) {
1121  RZ_LOG_ERROR("dyldcache: malformed local symbol entry\n");
1122  return;
1123  }
1124 
1125  ut64 nlists_size = sizeof(struct MACH0_(nlist)) * bin->nlist_count;
1126  struct MACH0_(nlist) *nlists = RZ_NEWS0(struct MACH0_(nlist), bin->nlist_count);
1127  if (!nlists) {
1128  return;
1129  }
1130  ut64 nlists_offset = locsym->local_symbols_offset + locsym->nlists_offset +
1131  bin->nlist_start_index * sizeof(struct MACH0_(nlist));
1132  if (rz_buf_fread_at(cache->buf, nlists_offset, (ut8 *)nlists, "iccsl", bin->nlist_count) != nlists_size) {
1133  free(nlists);
1134  return;
1135  }
1136 
1137  ut32 j;
1138  for (j = 0; j != bin->nlist_count; j++) {
1139  struct MACH0_(nlist) *nlist = &nlists[j];
1140  if (set_u_contains(hash, (ut64)nlist->n_value)) {
1141  continue;
1142  }
1143  set_u_add(hash, (ut64)nlist->n_value);
1144  if (nlist->n_strx >= locsym->strings_size) {
1145  continue;
1146  }
1148  if (!sym) {
1149  break;
1150  }
1151  sym->type = "LOCAL";
1152  sym->vaddr = nlist->n_value;
1153  ut64 slide = rz_dyldcache_get_slide(cache);
1154  sym->paddr = va2pa(nlist->n_value, cache->n_maps, cache->maps, cache->buf, slide, NULL, NULL);
1155 
1156  char *symstr = rz_buf_get_string(cache->buf, locsym->local_symbols_offset + locsym->strings_offset + nlist->n_strx);
1157  if (symstr) {
1158  sym->name = symstr;
1159  } else {
1160  static ut32 k = 0;
1161  sym->name = rz_str_newf("unk_local%d", k++);
1162  }
1163 
1164  rz_list_append(symbols, sym);
1165  }
1166 
1167  free(nlists);
1168 }
RzList * symbols(RzBinFile *bf)
Definition: bin_ne.c:102
RZ_API RZ_OWN char * rz_buf_get_string(RZ_NONNULL RzBuffer *b, ut64 addr)
Get a string from the buffer.
Definition: buf.c:628
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API void set_u_add(SetU *s, ut64 u)
Definition: set.c:34
RZ_API bool set_u_contains(SetU *s, ut64 u)
Definition: set.c:38
uint32_t n_value
uint32_t n_strx
const char * type
Definition: rz_bin.h:682
char * name
Definition: rz_bin.h:675

References rz_dyldcache_t::buf, free(), k, rz_dyld_loc_sym_t::local_symbols_offset, rz_dyldcache_t::locsym, MACH0_, rz_dyldcache_t::maps, rz_dyldcache_t::n_maps, nlist::n_strx, nlist::n_value, rz_bin_symbol_t::name, rz_dyld_loc_sym_t::nlists_count, rz_dyld_loc_sym_t::nlists_offset, NULL, rz_bin_symbol_t::paddr, rz_buf_fread_at(), rz_buf_get_string(), rz_dyldcache_get_slide(), rz_list_append(), RZ_LOG_ERROR, RZ_NEW0, RZ_NEWS0, rz_str_newf(), set_u_add(), set_u_contains(), rz_dyld_loc_sym_t::strings_offset, rz_dyld_loc_sym_t::strings_size, symbols(), rz_bin_symbol_t::type, ut64(), va2pa(), and rz_bin_symbol_t::vaddr.

Referenced by symbols().

◆ rz_dyldcache_va2pa()

RZ_API ut64 rz_dyldcache_va2pa ( RzDyldCache cache,
uint64_t  vaddr,
ut32 offset,
ut32 left 
)

Definition at line 1353 of file dyldcache.c.

1353  {
1355  ut64 slide = rz_dyldcache_get_slide(cache);
1356  ut64 res = va2pa(vaddr, cache->n_maps, cache->maps, cache->buf, slide, offset, left);
1357  if (res == UT64_MAX) {
1358  res = 0;
1359  }
1360  return res;
1361 }

References rz_dyldcache_t::buf, rz_dyldcache_t::maps, rz_dyldcache_t::n_maps, rz_dyldcache_get_slide(), rz_return_val_if_fail, ut64(), UT64_MAX, and va2pa().

Referenced by bin_obj_va2pa(), classes(), and sections_from_bin().

◆ string_contains()

static int string_contains ( const void *  a,
const void *  b 
)
static

Definition at line 415 of file dyldcache.c.

415  {
416  return !strstr((const char *)a, (const char *)b);
417 }
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41

References a, and b.

Referenced by create_cache_bins().

◆ va2pa()

static ut64 va2pa ( uint64_t  addr,
ut32  n_maps,
cache_map_t maps,
RzBuffer cache_buf,
ut64  slide,
ut32 offset,
ut32 left 
)
static

Definition at line 22 of file dyldcache.c.

22  {
23  ut64 res = UT64_MAX;
24  ut32 i;
25 
26  addr -= slide;
27 
28  for (i = 0; i < n_maps; i++) {
29  if (addr >= maps[i].address && addr < maps[i].address + maps[i].size) {
30  res = maps[i].fileOffset + addr - maps[i].address;
31  if (offset) {
32  *offset = addr - maps[i].address;
33  }
34  if (left) {
35  *left = maps[i].size - (addr - maps[i].address);
36  }
37  break;
38  }
39  }
40 
41  return res;
42 }

References addr, i, maps(), ut64(), and UT64_MAX.

Referenced by carve_deps_at_address(), create_cache_bins(), read_cache_accel(), rz_dyldcache_get_objc_opt_info(), rz_dyldcache_symbols_from_locsym(), and rz_dyldcache_va2pa().