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

Go to the source code of this file.

Classes

struct  rz_dyld_rebase_info_t
 
struct  rz_dyld_rebase_infos_entry_t
 
struct  rz_dyld_rebase_infos_t
 
struct  rz_dyld_rebase_info_3_t
 
struct  rz_dyld_rebase_info_2_t
 
struct  rz_dyld_rebase_info_1_t
 
struct  rz_dyld_loc_sym_t
 
struct  rz_bin_dyld_image_t
 
struct  rz_dyldcache_t
 

Macros

#define RZ_BIN_MACH064   1
 

Typedefs

typedef struct rz_dyld_rebase_info_t RzDyldRebaseInfo
 
typedef struct rz_dyld_rebase_infos_entry_t RzDyldRebaseInfosEntry
 
typedef struct rz_dyld_rebase_infos_t RzDyldRebaseInfos
 
typedef struct rz_dyld_rebase_info_3_t RzDyldRebaseInfo3
 
typedef struct rz_dyld_rebase_info_2_t RzDyldRebaseInfo2
 
typedef struct rz_dyld_rebase_info_1_t RzDyldRebaseInfo1
 
typedef struct rz_dyld_loc_sym_t RzDyldLocSym
 
typedef struct rz_bin_dyld_image_t RzDyldBinImage
 
typedef struct rz_dyldcache_t RzDyldCache
 

Functions

RZ_API bool rz_dyldcache_check_magic (const char *magic)
 
RZ_API RzDyldCacherz_dyldcache_new_buf (RzBuffer *buf)
 
RZ_API void rz_dyldcache_free (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_inforz_dyldcache_get_objc_opt_info (RzBinFile *bf, RzDyldCache *cache)
 
RZ_API void rz_dyldcache_symbols_from_locsym (RzDyldCache *cache, RzDyldBinImage *bin, RzList *symbols, SetU *hash)
 
RZ_API RzBufferrz_dyldcache_new_rebasing_buf (RzDyldCache *cache)
 
RZ_API bool rz_dyldcache_needs_rebasing (RzDyldCache *cache)
 
RZ_API bool rz_dyldcache_range_needs_rebasing (RzDyldCache *cache, ut64 paddr, ut64 size)
 

Macro Definition Documentation

◆ RZ_BIN_MACH064

#define RZ_BIN_MACH064   1

Definition at line 11 of file dyldcache.h.

Typedef Documentation

◆ RzDyldBinImage

◆ RzDyldCache

typedef struct rz_dyldcache_t RzDyldCache

◆ RzDyldLocSym

◆ RzDyldRebaseInfo

◆ RzDyldRebaseInfo1

◆ RzDyldRebaseInfo2

◆ RzDyldRebaseInfo3

◆ RzDyldRebaseInfos

◆ RzDyldRebaseInfosEntry

Function Documentation

◆ 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 }
lzma_index ** i
Definition: index.h:629
#define NULL
Definition: cris-opc.c:27
static void rebase_info_free(RzDyldRebaseInfo *rebase_info)
Definition: dyldcache.c:1224
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
RZ_API void rz_buf_free(RzBuffer *b)
Free all internal data hold by the buffer and the buffer.
Definition: buf.c:1253
#define RZ_FREE(x)
Definition: rz_types.h:369
RzDyldRebaseInfo * info
Definition: dyldcache.h:26
RzDyldRebaseInfosEntry * entries
Definition: dyldcache.h:30
objc_cache_opt_info * oi
Definition: dyldcache.h:109
ut64 * hdr_offset
Definition: dyldcache.h:97
cache_map_t * maps
Definition: dyldcache.h:101
ut32 * maps_index
Definition: dyldcache.h:99
RzList * bins
Definition: dyldcache.h:104
cache_accel_t * accel
Definition: dyldcache.h:107
cache_hdr_t * hdr
Definition: dyldcache.h:96
RzBuffer * buf
Definition: dyldcache.h:105
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 }
RzList * sections(RzBinFile *bf)
Definition: bin_ne.c:110
lzma_check check
Definition: container.h:292
RZ_API ut64 rz_dyldcache_get_slide(RzDyldCache *cache)
Definition: dyldcache.c:1097
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
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
#define MACH0_(name)
Definition: mach0_specs.h:20
#define rz_buf_read_le64_at(b, addr, result)
Definition: rz_buf.h:272
#define RZ_NEW0(x)
Definition: rz_types.h:284
Definition: malloc.c:26
Definition: z80asm.h:102
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
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
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 }
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108

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_needs_rebasing()

RZ_API bool rz_dyldcache_needs_rebasing ( RzDyldCache cache)

Definition at line 284 of file dyldcache_rebase.c.

284  {
285  rz_return_val_if_fail(cache, false);
286  if (cache->rebase_infos) {
287  if (!rz_dyldcache_get_slide(cache)) {
288  return true;
289  }
290  }
291  return false;
292 }

References rz_dyldcache_t::rebase_infos, rz_dyldcache_get_slide(), and rz_return_val_if_fail.

Referenced by classes(), rz_dyldcache_range_needs_rebasing(), and virtual_files().

◆ 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
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
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_new_rebasing_buf()

RZ_API RzBuffer* rz_dyldcache_new_rebasing_buf ( RzDyldCache cache)

Definition at line 279 of file dyldcache_rebase.c.

279  {
280  rz_return_val_if_fail(cache, NULL);
281  return rz_buf_new_with_methods(&buf_methods, cache);
282 }
static const RzBufferMethods buf_methods
RZ_API RZ_OWN RzBuffer * rz_buf_new_with_methods(RZ_NONNULL const RzBufferMethods *methods, void *init_user)
Creates a new buffer with a specific back end.
Definition: buf.c:525

References buf_methods, NULL, rz_buf_new_with_methods(), and rz_return_val_if_fail.

Referenced by classes(), and virtual_files().

◆ rz_dyldcache_range_needs_rebasing()

RZ_API bool rz_dyldcache_range_needs_rebasing ( RzDyldCache cache,
ut64  paddr,
ut64  size 
)

Definition at line 294 of file dyldcache_rebase.c.

294  {
295  rz_return_val_if_fail(cache, false);
296  if (!rz_dyldcache_needs_rebasing(cache)) {
297  return false;
298  }
299  return !!rebase_info_by_range(cache->rebase_infos, paddr, size);
300 }
static RzDyldRebaseInfo * rebase_info_by_range(RzDyldRebaseInfos *infos, ut64 offset, ut64 count)
RZ_API bool rz_dyldcache_needs_rebasing(RzDyldCache *cache)

References rebase_info_by_range(), rz_dyldcache_t::rebase_infos, rz_dyldcache_needs_rebasing(), and rz_return_val_if_fail.

Referenced by maps().

◆ 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
uint32_t ut32
const char * k
Definition: dsignal.c:11
uint8_t ut8
Definition: lh5801.h:11
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 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 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
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
#define RZ_NEWS0(x, y)
Definition: rz_types.h:282
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
ut64 local_symbols_offset
Definition: dyldcache.h:76

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 }
voidpf uLong offset
Definition: ioapi.h:144
#define UT64_MAX
Definition: rz_types_base.h:86

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().