Rizin
unix-like reverse engineering framework and cli tools
mach0_relocs.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2021 Florian Märkl <info@florianmaerkl.de>
2 // SPDX-FileCopyrightText: 2020 Francesco Tamagni <mrmacete@protonmail.ch>
3 // SPDX-FileCopyrightText: 2010-2020 nibble <nibble.ds@gmail.com>
4 // SPDX-FileCopyrightText: 2010-2020 pancake <pancake@nopcode.org>
5 // SPDX-License-Identifier: LGPL-3.0-only
6 
7 #include <rz_util.h>
8 #include "mach0.h"
9 #include <ht_uu.h>
10 
11 #include "mach0_utils.inc"
12 
13 static int reloc_comparator(struct reloc_t *a, struct reloc_t *b) {
14  return a->addr - b->addr;
15 }
16 
17 static void parse_relocation_info(struct MACH0_(obj_t) * bin, RzSkipList *relocs, ut32 offset, ut32 num) {
18  if (!num || !offset || (st32)num < 0) {
19  return;
20  }
21 
22  ut64 total_size = num * sizeof(struct relocation_info);
23  struct relocation_info *info = calloc(num, sizeof(struct relocation_info));
24  if (!info) {
25  return;
26  }
27 
28  if (rz_buf_read_at(bin->b, offset, (ut8 *)info, total_size) < total_size) {
29  free(info);
30  return;
31  }
32 
33  size_t i;
34  for (i = 0; i < num; i++) {
35  struct relocation_info a_info = info[i];
36  ut32 sym_num = a_info.r_symbolnum;
37  if (sym_num >= bin->nsymtab) {
38  continue;
39  }
40 
41  ut32 stridx = bin->symtab[sym_num].n_strx;
42  char *sym_name = MACH0_(get_name)(bin, stridx, false);
43  if (!sym_name) {
44  continue;
45  }
46 
47  struct reloc_t *reloc = RZ_NEW0(struct reloc_t);
48  if (!reloc) {
49  free(info);
50  free(sym_name);
51  return;
52  }
53 
54  reloc->addr = MACH0_(paddr_to_vaddr)(bin, a_info.r_address);
55  reloc->offset = a_info.r_address;
56  reloc->ord = sym_num;
57  reloc->type = a_info.r_type; // enum RelocationInfoType
58  reloc->external = a_info.r_extern;
59  reloc->pc_relative = a_info.r_pcrel;
60  reloc->size = 1 << a_info.r_length; // macho/reloc.h says: 0=byte, 1=word, 2=long, 3=quad
61  rz_str_ncpy(reloc->name, sym_name, sizeof(reloc->name) - 1);
62  rz_skiplist_insert(relocs, reloc);
63  free(sym_name);
64  }
65  free(info);
66 }
67 
69  return size > 0 && size <= UT16_MAX;
70 }
71 
72 static int parse_import_ptr(struct MACH0_(obj_t) * bin, struct reloc_t *reloc, int idx) {
73  int i, j, sym;
74  size_t wordsize;
75  ut32 stype;
76  wordsize = get_word_size(bin);
77  if (idx < 0 || idx >= bin->nsymtab) {
78  return 0;
79  }
80  if ((bin->symtab[idx].n_desc & REFERENCE_TYPE) == REFERENCE_FLAG_UNDEFINED_LAZY) {
81  stype = S_LAZY_SYMBOL_POINTERS;
82  } else {
84  }
85 
86  reloc->offset = 0;
87  reloc->addr = 0;
88  reloc->addend = 0;
89 #define CASE(T) \
90  case ((T) / 8): reloc->type = RZ_BIN_RELOC_##T; break
91  switch (wordsize) {
92  CASE(8);
93  CASE(16);
94  CASE(32);
95  CASE(64);
96  default: return false;
97  }
98 #undef CASE
99 
100  for (i = 0; i < bin->nsects; i++) {
101  if ((bin->sects[i].flags & SECTION_TYPE) == stype) {
102  for (j = 0, sym = -1; bin->sects[i].reserved1 + j < bin->nindirectsyms; j++) {
103  int indidx = bin->sects[i].reserved1 + j;
104  if (indidx < 0 || indidx >= bin->nindirectsyms) {
105  break;
106  }
107  if (idx == bin->indirectsyms[indidx]) {
108  sym = j;
109  break;
110  }
111  }
112  reloc->offset = sym == -1 ? 0 : bin->sects[i].offset + sym * wordsize;
113  reloc->addr = sym == -1 ? 0 : bin->sects[i].addr + sym * wordsize;
114  return true;
115  }
116  }
117  return false;
118 }
119 
120 RZ_BORROW RzSkipList *MACH0_(get_relocs)(struct MACH0_(obj_t) * bin) {
122  if (bin->relocs_parsed) {
123  return bin->relocs;
124  }
125  bin->relocs_parsed = true;
127  RzPVector *threaded_binds = NULL;
128  size_t wordsize = get_word_size(bin);
129  if (bin->dyld_info) {
130  ut8 *opcodes, rel_type = 0;
131  size_t bind_size, lazy_size, weak_size;
132 
133 #define CASE(T) \
134  case ((T) / 8): rel_type = RZ_BIN_RELOC_##T; break
135  switch (wordsize) {
136  CASE(8);
137  CASE(16);
138  CASE(32);
139  CASE(64);
140  default: return NULL;
141  }
142 #undef CASE
143  bind_size = bin->dyld_info->bind_size;
144  lazy_size = bin->dyld_info->lazy_bind_size;
145  weak_size = bin->dyld_info->weak_bind_size;
146 
147  if (!bind_size && !lazy_size) {
148  return NULL;
149  }
150 
151  if ((bind_size + lazy_size) < 1) {
152  return NULL;
153  }
154  if (bin->dyld_info->bind_off > bin->size || bin->dyld_info->bind_off + bind_size > bin->size) {
155  return NULL;
156  }
157  if (bin->dyld_info->lazy_bind_off > bin->size ||
158  bin->dyld_info->lazy_bind_off + lazy_size > bin->size) {
159  return NULL;
160  }
161  if (bin->dyld_info->bind_off + bind_size + lazy_size > bin->size) {
162  return NULL;
163  }
164  if (bin->dyld_info->weak_bind_off + weak_size > bin->size) {
165  return NULL;
166  }
167  ut64 amount = bind_size + lazy_size + weak_size;
168  if (amount == 0 || amount > UT32_MAX) {
169  return NULL;
170  }
171  if (!bin->segs) {
172  return NULL;
173  }
175  if (!relocs) {
176  return NULL;
177  }
178  opcodes = calloc(1, amount + 1);
179  if (!opcodes) {
181  return NULL;
182  }
183 
184  int len = rz_buf_read_at(bin->b, bin->dyld_info->bind_off, opcodes, bind_size);
185  len += rz_buf_read_at(bin->b, bin->dyld_info->lazy_bind_off, opcodes + bind_size, lazy_size);
186  len += rz_buf_read_at(bin->b, bin->dyld_info->weak_bind_off, opcodes + bind_size + lazy_size, weak_size);
187  if (len < amount) {
188  RZ_LOG_ERROR("Error: read (dyld_info bind) at 0x%08" PFMT64x "\n", (ut64)(size_t)bin->dyld_info->bind_off);
189  RZ_FREE(opcodes);
191  return NULL;
192  }
193 
194  size_t partition_sizes[] = { bind_size, lazy_size, weak_size };
195  size_t pidx;
196  int opcodes_offset = 0;
197  for (pidx = 0; pidx < RZ_ARRAY_SIZE(partition_sizes); pidx++) {
198  size_t partition_size = partition_sizes[pidx];
199 
200  ut8 type = 0;
201  int lib_ord = 0, seg_idx = -1, sym_ord = -1;
202  char *sym_name = NULL;
203  size_t j, count, skip;
204  st64 addend = 0;
205  ut64 addr = bin->segs[0].vmaddr;
206  ut64 segment_end_addr = addr + bin->segs[0].vmsize;
207 
208  ut8 *p = opcodes + opcodes_offset;
209  ut8 *end = p + partition_size;
210  bool done = false;
211  while (!done && p < end) {
213  ut8 op = *p & BIND_OPCODE_MASK;
214  p++;
215  switch (op) {
216  case BIND_OPCODE_DONE: {
217  bool in_lazy_binds = pidx == 1;
218  if (!in_lazy_binds) {
219  done = true;
220  }
221  break;
222  }
223  case BIND_OPCODE_THREADED: {
224  switch (imm) {
226  ut64 table_size = read_uleb128(&p, end);
227  if (!is_valid_ordinal_table_size(table_size)) {
228  RZ_LOG_ERROR("Error: BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB size is wrong\n");
229  break;
230  }
231  if (threaded_binds) {
232  rz_pvector_free(threaded_binds);
233  }
234  threaded_binds = rz_pvector_new_with_len((RzPVectorFree)&free, table_size);
235  if (threaded_binds) {
236  sym_ord = 0;
237  }
238  break;
239  }
241  if (threaded_binds) {
242  int cur_seg_idx = (seg_idx != -1) ? seg_idx : 0;
243  size_t n_threaded_binds = rz_pvector_len(threaded_binds);
244  while (addr < segment_end_addr) {
245  ut8 tmp[8];
246  ut64 paddr = addr - bin->segs[cur_seg_idx].vmaddr + bin->segs[cur_seg_idx].fileoff;
247  if (rz_buf_read_at(bin->b, paddr, tmp, 8) != 8) {
248  break;
249  }
250  ut64 raw_ptr = rz_read_le64(tmp);
251  bool is_auth = (raw_ptr & (1ULL << 63)) != 0;
252  bool is_bind = (raw_ptr & (1ULL << 62)) != 0;
253  int ordinal = -1;
254  int addend = -1;
255  ut64 delta;
256  if (is_auth && is_bind) {
258  (struct dyld_chained_ptr_arm64e_auth_bind *)&raw_ptr;
259  delta = p->next;
260  ordinal = p->ordinal;
261  } else if (!is_auth && is_bind) {
263  (struct dyld_chained_ptr_arm64e_bind *)&raw_ptr;
264  delta = p->next;
265  ordinal = p->ordinal;
266  addend = p->addend;
267  } else if (is_auth && !is_bind) {
269  (struct dyld_chained_ptr_arm64e_auth_rebase *)&raw_ptr;
270  delta = p->next;
271  } else {
273  (struct dyld_chained_ptr_arm64e_rebase *)&raw_ptr;
274  delta = p->next;
275  }
276  if (ordinal != -1) {
277  if (ordinal >= n_threaded_binds) {
278  RZ_LOG_ERROR("Error: Malformed bind chain\n");
279  break;
280  }
281  struct reloc_t *ref = rz_pvector_at(threaded_binds, ordinal);
282  if (!ref) {
283  RZ_LOG_ERROR("Error: Inconsistent bind opcodes\n");
284  break;
285  }
286  struct reloc_t *reloc = RZ_NEW0(struct reloc_t);
287  if (!reloc) {
288  break;
289  }
290  *reloc = *ref;
291  reloc->addr = addr;
292  reloc->offset = paddr;
293  if (addend != -1) {
294  reloc->addend = addend;
295  }
296  rz_skiplist_insert(relocs, reloc);
297  }
298  addr += delta * wordsize;
299  if (!delta) {
300  break;
301  }
302  }
303  }
304  break;
305  default:
306  RZ_LOG_ERROR("Error: Unexpected BIND_OPCODE_THREADED sub-opcode: 0x%x\n", imm);
307  }
308  break;
309  }
311  lib_ord = imm;
312  break;
314  lib_ord = read_uleb128(&p, end);
315  break;
317  lib_ord = imm ? (st8)(BIND_OPCODE_MASK | imm) : 0;
318  break;
320  sym_name = (char *)p;
321  while (*p++ && p < end) {
322  /* empty loop */
323  }
324  if (threaded_binds) {
325  break;
326  }
327  sym_ord = -1;
328  if (bin->symtab && bin->dysymtab.nundefsym < UT16_MAX) {
329  for (j = 0; j < bin->dysymtab.nundefsym; j++) {
330  size_t stridx = 0;
331  bool found = false;
332  int iundefsym = bin->dysymtab.iundefsym;
333  if (iundefsym >= 0 && iundefsym < bin->nsymtab) {
334  int sidx = iundefsym + j;
335  if (sidx < 0 || sidx >= bin->nsymtab) {
336  continue;
337  }
338  stridx = bin->symtab[sidx].n_strx;
339  if (stridx >= bin->symstrlen) {
340  continue;
341  }
342  found = true;
343  }
344  if (found && !strcmp((const char *)bin->symstr + stridx, sym_name)) {
345  sym_ord = j;
346  break;
347  }
348  }
349  }
350  break;
351  }
353  type = imm;
354  break;
356  addend = rz_sleb128((const ut8 **)&p, end);
357  break;
359  seg_idx = imm;
360  if (seg_idx >= bin->nsegs) {
361  RZ_LOG_ERROR("Error: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB"
362  " has unexistent segment %d\n",
363  seg_idx);
364  free(opcodes);
366  rz_pvector_free(threaded_binds);
367  return NULL; // early exit to avoid future mayhem
368  }
369  addr = bin->segs[seg_idx].vmaddr + read_uleb128(&p, end);
370  segment_end_addr = bin->segs[seg_idx].vmaddr + bin->segs[seg_idx].vmsize;
371  break;
373  addr += read_uleb128(&p, end);
374  break;
375 #define DO_BIND() \
376  do { \
377  if (sym_ord < 0 && !sym_name) \
378  break; \
379  if (!threaded_binds) { \
380  if (seg_idx < 0) \
381  break; \
382  if (!addr) \
383  break; \
384  } \
385  struct reloc_t *reloc = RZ_NEW0(struct reloc_t); \
386  reloc->addr = addr; \
387  if (seg_idx >= 0) { \
388  reloc->offset = addr - bin->segs[seg_idx].vmaddr + bin->segs[seg_idx].fileoff; \
389  if (type == BIND_TYPE_TEXT_PCREL32) \
390  reloc->addend = addend - (bin->baddr + addr); \
391  else \
392  reloc->addend = addend; \
393  } else { \
394  reloc->addend = addend; \
395  } \
396  /* library ordinal ??? */ \
397  reloc->ord = lib_ord; \
398  reloc->ord = sym_ord; \
399  reloc->type = rel_type; \
400  if (sym_name) \
401  rz_str_ncpy(reloc->name, sym_name, 256); \
402  if (threaded_binds) \
403  rz_pvector_set(threaded_binds, sym_ord, reloc); \
404  else \
405  rz_skiplist_insert(relocs, reloc); \
406  } while (0)
407  case BIND_OPCODE_DO_BIND:
408  if (!threaded_binds && addr >= segment_end_addr) {
409  RZ_LOG_ERROR("Error: Malformed DO bind opcode 0x%" PFMT64x "\n", addr);
410  goto beach;
411  }
412  DO_BIND();
413  if (!threaded_binds) {
414  addr += wordsize;
415  } else {
416  sym_ord++;
417  }
418  break;
420  if (addr >= segment_end_addr) {
421  RZ_LOG_ERROR("Error: Malformed ADDR ULEB bind opcode\n");
422  goto beach;
423  }
424  DO_BIND();
425  addr += read_uleb128(&p, end) + wordsize;
426  break;
428  if (addr >= segment_end_addr) {
429  RZ_LOG_ERROR("Error: Malformed IMM SCALED bind opcode\n");
430  goto beach;
431  }
432  DO_BIND();
433  addr += (ut64)imm * (ut64)wordsize + wordsize;
434  break;
436  count = read_uleb128(&p, end);
437  skip = read_uleb128(&p, end);
438  for (j = 0; j < count; j++) {
439  if (addr >= segment_end_addr) {
440  RZ_LOG_ERROR("Error: Malformed ULEB TIMES bind opcode\n");
441  goto beach;
442  }
443  DO_BIND();
444  addr += skip + wordsize;
445  }
446  break;
447 #undef DO_BIND
448  default:
449  RZ_LOG_ERROR("Error: unknown bind opcode 0x%02x in dyld_info\n", *p);
450  RZ_FREE(opcodes);
451  goto beach;
452  }
453  }
454 
455  opcodes_offset += partition_size;
456  }
457 
458  RZ_FREE(opcodes);
459  rz_pvector_free(threaded_binds);
460  threaded_binds = NULL;
461  }
462 
463  if (bin->symtab && bin->symstr && bin->sects && bin->indirectsyms) {
464  int j;
465  int amount = bin->dysymtab.nundefsym;
466  if (amount < 0) {
467  amount = 0;
468  }
469  if (!relocs) {
471  if (!relocs) {
472  return NULL;
473  }
474  }
475  for (j = 0; j < amount; j++) {
476  struct reloc_t *reloc = RZ_NEW0(struct reloc_t);
477  if (!reloc) {
478  break;
479  }
480  if (parse_import_ptr(bin, reloc, bin->dysymtab.iundefsym + j)) {
481  reloc->ord = j;
482  rz_skiplist_insert(relocs, reloc);
483  } else {
484  RZ_FREE(reloc);
485  }
486  }
487  }
488 
489  if (bin->symtab && bin->dysymtab.extreloff && bin->dysymtab.nextrel) {
490  if (!relocs) {
492  if (!relocs) {
493  return NULL;
494  }
495  }
496  parse_relocation_info(bin, relocs, bin->dysymtab.extreloff, bin->dysymtab.nextrel);
497  }
498 beach:
499  rz_pvector_free(threaded_binds);
500  bin->relocs = relocs;
501  return relocs;
502 }
503 
504 static RzPVector *get_patchable_relocs(struct MACH0_(obj_t) * obj) {
505  if (!obj->options.patch_relocs) {
506  return NULL;
507  }
508  if (obj->patchable_relocs) {
509  return obj->patchable_relocs;
510  }
512  if (!relocs) {
513  return NULL;
514  }
515  obj->patchable_relocs = rz_pvector_new(NULL);
516  if (!obj->patchable_relocs) {
517  return NULL;
518  }
519  RzSkipListNode *it;
520  struct reloc_t *reloc;
521  rz_skiplist_foreach (relocs, it, reloc) {
522  if (!reloc->external) {
523  // right now, we only care about patching external relocs
524  // others might be interesting too in the future though, for example in object files.
525  continue;
526  }
527  rz_pvector_push(obj->patchable_relocs, reloc);
528  }
529  return obj->patchable_relocs;
530 }
531 
532 RZ_API bool MACH0_(needs_reloc_patching)(struct MACH0_(obj_t) * obj) {
533  rz_return_val_if_fail(obj, false);
534  RzPVector *patchable_relocs = get_patchable_relocs(obj);
535  return patchable_relocs && rz_pvector_len(patchable_relocs);
536 }
537 
538 static ut64 reloc_target_size(struct MACH0_(obj_t) * obj) {
539  int bits = MACH0_(get_bits_from_hdr)(&obj->hdr);
540  if (bits) {
541  return 8;
542  }
543  return bits / 8;
544 }
545 
547 RZ_API ut64 MACH0_(reloc_targets_vfile_size)(struct MACH0_(obj_t) * obj) {
548  RzPVector *patchable_relocs = get_patchable_relocs(obj);
549  if (!patchable_relocs) {
550  return 0;
551  }
552  return rz_pvector_len(patchable_relocs) * reloc_target_size(obj);
553 }
554 
556 RZ_API ut64 MACH0_(reloc_targets_map_base)(RzBinFile *bf, struct MACH0_(obj_t) * obj) {
557  if (obj->reloc_targets_map_base_calculated) {
558  return obj->reloc_targets_map_base;
559  }
561  obj->reloc_targets_map_base = rz_bin_relocs_patch_find_targets_map_base(maps, reloc_target_size(obj));
563  obj->reloc_targets_map_base_calculated = true;
564  return obj->reloc_targets_map_base;
565 }
566 
567 static bool _patch_reloc(struct MACH0_(obj_t) * bin, struct reloc_t *reloc, ut64 symbol_at) {
568  ut64 pc = reloc->addr;
569  ut64 ins_len = 0;
570 
571  switch (bin->hdr.cputype) {
572  case CPU_TYPE_X86_64: {
573  switch (reloc->type) {
575  break;
576  case X86_64_RELOC_BRANCH:
577  pc -= 1;
578  ins_len = 5;
579  break;
580  default:
581  RZ_LOG_ERROR("Warning: unsupported reloc type for X86_64 (%d), please file a bug.\n", reloc->type);
582  return false;
583  }
584  break;
585  }
586  case CPU_TYPE_ARM64:
587  case CPU_TYPE_ARM64_32:
588  pc = reloc->addr & ~3;
589  ins_len = 4;
590  break;
591  case CPU_TYPE_ARM:
592  break;
593  default:
594  RZ_LOG_ERROR("Warning: unsupported architecture for patching relocs, please file a bug. %s\n", MACH0_(get_cputype_from_hdr)(&bin->hdr));
595  return false;
596  }
597 
598  ut64 val = symbol_at;
599  if (reloc->pc_relative) {
600  val = symbol_at - pc - ins_len;
601  }
602 
603  ut8 buf[8];
604  rz_write_ble(buf, val, false, reloc->size * 8);
605  rz_buf_write_at(bin->buf_patched, reloc->offset, buf, RZ_MIN(sizeof(buf), reloc->size));
606  return true;
607 }
608 
614 RZ_API void MACH0_(patch_relocs)(RzBinFile *bf, struct MACH0_(obj_t) * obj) {
615  rz_return_if_fail(obj);
616  if (obj->relocs_patched || !MACH0_(needs_reloc_patching)(obj)) {
617  return;
618  }
619  obj->relocs_patched = true; // run this function just once (lazy relocs patching)
620  ut64 cdsz = reloc_target_size(obj);
622  if (!size) {
623  return;
624  }
625  RzBinRelocTargetBuilder *targets = rz_bin_reloc_target_builder_new(cdsz, MACH0_(reloc_targets_map_base)(bf, obj));
626  if (!targets) {
627  return;
628  }
630  if (!obj->buf_patched) {
632  return;
633  }
634  RzPVector *patchable_relocs = get_patchable_relocs(obj);
635  void **it;
636  rz_pvector_foreach (patchable_relocs, it) {
637  struct reloc_t *reloc = *it;
638  ut64 sym_addr = rz_bin_reloc_target_builder_get_target(targets, reloc->ord);
639  reloc->target = sym_addr;
640  _patch_reloc(obj, reloc, sym_addr);
641  }
643  // from now on, all writes should propagate through to the actual file
645 }
size_t len
Definition: 6502dis.c:15
#define imm
lzma_index ** i
Definition: index.h:629
ut16 val
Definition: armass64_const.h:6
OPCODE_DESC opcodes[]
Definition: avr_esil.c:1270
static RzList * maps(RzBinFile *bf)
Definition: bin_bf.c:116
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
RzList * relocs(RzBinFile *bf)
Definition: bin_ne.c:114
int bits(struct state *s, int need)
Definition: blast.c:72
#define RZ_API
#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 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 count
Definition: sflib.h:98
uint32_t ut32
struct tab * done
Definition: enough.c:233
void skip(file *in, unsigned n)
Definition: gzappend.c:202
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
voidpf void uLong size
Definition: ioapi.h:138
voidpf uLong offset
Definition: ioapi.h:144
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
void * p
Definition: libc.cpp:67
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode static oldfd struct tms static buf static getgid static geteuid const char static filename static arg static mask struct ustat static ubuf static getppid static setsid static egid sigset_t static set struct timeval struct timezone static tz fd_set fd_set fd_set struct timeval static timeout const char char static bufsiz const char static swapflags void static offset const char static length static mode static who const char struct statfs static buf unsigned unsigned num
Definition: sflib.h:126
RzList *MACH0_() get_maps_unpatched(RzBinFile *bf)
Definition: mach0.c:2217
RZ_API RZ_OWN char *MACH0_() get_name(struct MACH0_(obj_t) *mo, ut32 stridx, bool filter)
Get a string from the string table referenced by the LC_SYMTAB command.
Definition: mach0.c:2563
RZ_API ut64 MACH0_() paddr_to_vaddr(struct MACH0_(obj_t) *bin, ut64 offset)
Definition: mach0.c:67
int MACH0_() get_bits_from_hdr(struct MACH0_(mach_header) *hdr)
Definition: mach0.c:3299
const char *MACH0_() get_cputype_from_hdr(struct MACH0_(mach_header) *hdr)
Definition: mach0.c:3336
@ S_NON_LAZY_SYMBOL_POINTERS
S_NON_LAZY_SYMBOL_POINTERS - Section with non-lazy symbol pointers.
@ S_LAZY_SYMBOL_POINTERS
S_LAZY_SYMBOL_POINTERS - Section with lazy symbol pointers.
@ SECTION_TYPE
@ BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB
@ BIND_SUBOPCODE_THREADED_APPLY
@ BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB
@ BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED
@ BIND_OPCODE_SET_DYLIB_SPECIAL_IMM
@ BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
@ BIND_OPCODE_ADD_ADDR_ULEB
@ BIND_OPCODE_SET_TYPE_IMM
@ BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
@ BIND_OPCODE_DO_BIND
@ BIND_OPCODE_SET_ADDEND_SLEB
@ BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB
@ BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
@ BIND_OPCODE_THREADED
@ BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB
@ BIND_OPCODE_DONE
@ BIND_OPCODE_MASK
@ BIND_IMMEDIATE_MASK
@ REFERENCE_TYPE
@ REFERENCE_FLAG_UNDEFINED_LAZY
@ CPU_TYPE_ARM64_32
@ CPU_TYPE_ARM
@ CPU_TYPE_X86_64
@ CPU_TYPE_ARM64
@ X86_64_RELOC_BRANCH
@ X86_64_RELOC_UNSIGNED
RZ_API ut64 MACH0_() reloc_targets_map_base(RzBinFile *bf, struct MACH0_(obj_t) *obj)
base vaddr where to map the artificial reloc target vfile
Definition: mach0_relocs.c:556
RZ_BORROW RzSkipList *MACH0_() get_relocs(struct MACH0_(obj_t) *bin)
Definition: mach0_relocs.c:120
static ut64 reloc_target_size(struct MACH0_(obj_t) *obj)
Definition: mach0_relocs.c:538
static bool _patch_reloc(struct MACH0_(obj_t) *bin, struct reloc_t *reloc, ut64 symbol_at)
Definition: mach0_relocs.c:567
static void parse_relocation_info(struct MACH0_(obj_t) *bin, RzSkipList *relocs, ut32 offset, ut32 num)
Definition: mach0_relocs.c:17
static bool is_valid_ordinal_table_size(ut64 size)
Definition: mach0_relocs.c:68
static RzPVector * get_patchable_relocs(struct MACH0_(obj_t) *obj)
Definition: mach0_relocs.c:504
RZ_API bool MACH0_() needs_reloc_patching(struct MACH0_(obj_t) *obj)
Definition: mach0_relocs.c:532
RZ_API ut64 MACH0_() reloc_targets_vfile_size(struct MACH0_(obj_t) *obj)
size of the artificial reloc target vfile
Definition: mach0_relocs.c:547
#define DO_BIND()
#define CASE(T)
static int parse_import_ptr(struct MACH0_(obj_t) *bin, struct reloc_t *reloc, int idx)
Definition: mach0_relocs.c:72
RZ_API void MACH0_() patch_relocs(RzBinFile *bf, struct MACH0_(obj_t) *obj)
Patching of external relocs in a sparse overlay buffer.
Definition: mach0_relocs.c:614
static int reloc_comparator(struct reloc_t *a, struct reloc_t *b)
Definition: mach0_relocs.c:13
#define MACH0_(name)
Definition: mach0_specs.h:20
int type
Definition: mipsasm.c:17
int idx
Definition: setup.py:197
RZ_API ut64 rz_bin_reloc_target_builder_get_target(RzBinRelocTargetBuilder *builder, ut64 sym)
obtain the address of the target for a given symbol
Definition: relocs_patch.c:69
RZ_API void rz_bin_reloc_target_builder_free(RzBinRelocTargetBuilder *builder)
Definition: relocs_patch.c:51
RZ_API RzBinRelocTargetBuilder * rz_bin_reloc_target_builder_new(ut64 target_size, ut64 target_base)
Definition: relocs_patch.c:35
RZ_API ut64 rz_bin_relocs_patch_find_targets_map_base(RzList *maps, ut64 target_sz)
Finm a suitable location for putting the artificial reloc targets map.
Definition: relocs_patch.c:8
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RZ_API void rz_buf_sparse_set_write_mode(RzBuffer *b, RzBufferSparseWriteMode mode)
Only for sparse RzBuffers.
Definition: buf_sparse.c:325
RZ_API st64 rz_buf_write_at(RZ_NONNULL RzBuffer *b, ut64 addr, RZ_NONNULL const ut8 *buf, ut64 len)
Write len bytes of the buffer at the specified address.
Definition: buf.c:1197
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_BUF_SPARSE_WRITE_MODE_SPARSE
all writes are performed in the sparse overlay
Definition: rz_buf.h:60
@ RZ_BUF_SPARSE_WRITE_MODE_THROUGH
all writes are performed in the underlying base buffer
Definition: rz_buf.h:61
RZ_API RZ_OWN RzBuffer * rz_buf_new_sparse_overlay(RzBuffer *b, RzBufferSparseWriteMode write_mode)
Creates a sparse buffer from a already populated buffer.
Definition: buf.c:426
static void rz_write_ble(void *dst, ut64 val, bool big_endian, int size)
Definition: rz_endian.h:548
static ut64 rz_read_le64(const void *src)
Definition: rz_endian.h:266
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
int(* RzListComparator)(const void *value, const void *list_data)
Definition: rz_list.h:33
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API RzSkipList * rz_skiplist_new(RzListFree freefn, RzListComparator comparefn)
Definition: skiplist.c:107
#define rz_skiplist_foreach(list, it, pos)
Definition: rz_skiplist.h:48
RZ_API void rz_skiplist_free(RzSkipList *list)
Definition: skiplist.c:145
RZ_API RzSkipListNode * rz_skiplist_insert(RzSkipList *list, void *data)
Definition: skiplist.c:156
RZ_API size_t rz_str_ncpy(char *dst, const char *src, size_t n)
Secure string copy with null terminator.
Definition: str.c:923
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_ARRAY_SIZE(x)
Definition: rz_types.h:300
#define RZ_FREE(x)
Definition: rz_types.h:369
#define PFMT64x
Definition: rz_types.h:393
#define RZ_BORROW
Definition: rz_types.h:63
#define st8
Definition: rz_types_base.h:16
#define RZ_MIN(x, y)
#define st64
Definition: rz_types_base.h:10
#define UT32_MAX
Definition: rz_types_base.h:99
#define st32
Definition: rz_types_base.h:12
#define UT16_MAX
RZ_API st64 rz_sleb128(const ut8 **data, const ut8 *end)
Definition: uleb128.c:145
static size_t rz_pvector_len(const RzPVector *vec)
Definition: rz_vector.h:231
RZ_API RzPVector * rz_pvector_new(RzPVectorFree free)
Definition: vector.c:302
void(* RzPVectorFree)(void *e)
Definition: rz_vector.h:43
static void ** rz_pvector_push(RzPVector *vec, void *x)
Definition: rz_vector.h:300
RZ_API void rz_pvector_free(RzPVector *vec)
Definition: vector.c:336
RZ_API RzPVector * rz_pvector_new_with_len(RzPVectorFree free, size_t length)
Definition: vector.c:311
static void * rz_pvector_at(const RzPVector *vec, size_t index)
Definition: rz_vector.h:236
#define rz_pvector_foreach(vec, it)
Definition: rz_vector.h:334
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41
Definition: malloc.c:26
Definition: mach0.h:71
ut64 target
Definition: mach0.h:82
bool pc_relative
Definition: mach0.h:80
ut64 addr
Definition: mach0.h:73
char name[256]
Definition: mach0.h:78
int ord
Definition: mach0.h:76
bool external
Definition: mach0.h:79
ut64 offset
Definition: mach0.h:72
ut8 type
Definition: mach0.h:75
st64 addend
Definition: mach0.h:74
ut8 size
Definition: mach0.h:81
uint32_t r_symbolnum
XX curplugin == o->plugin.
Definition: rz_bin.h:298
Definition: dis.c:32
static st64 delta
Definition: vmenus.c:2425
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58