14 return a->addr -
b->addr;
34 for (
i = 0;
i <
num;
i++) {
37 if (sym_num >=
bin->nsymtab) {
41 ut32 stridx =
bin->symtab[sym_num].n_strx;
76 wordsize = get_word_size(
bin);
77 if (idx < 0 || idx >=
bin->nsymtab) {
90 case ((T) / 8): reloc->type = RZ_BIN_RELOC_##T; break
96 default:
return false;
100 for (
i = 0;
i <
bin->nsects;
i++) {
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) {
107 if (
idx ==
bin->indirectsyms[indidx]) {
112 reloc->
offset = sym == -1 ? 0 :
bin->sects[
i].offset + sym * wordsize;
113 reloc->
addr = sym == -1 ? 0 :
bin->sects[
i].addr + sym * wordsize;
122 if (
bin->relocs_parsed) {
125 bin->relocs_parsed =
true;
128 size_t wordsize = get_word_size(
bin);
129 if (
bin->dyld_info) {
131 size_t bind_size, lazy_size, weak_size;
134 case ((T) / 8): rel_type = RZ_BIN_RELOC_##T; break
140 default:
return NULL;
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;
147 if (!bind_size && !lazy_size) {
151 if ((bind_size + lazy_size) < 1) {
154 if (
bin->dyld_info->bind_off >
bin->size ||
bin->dyld_info->bind_off + bind_size >
bin->size) {
157 if (
bin->dyld_info->lazy_bind_off >
bin->size ||
158 bin->dyld_info->lazy_bind_off + lazy_size >
bin->size) {
161 if (
bin->dyld_info->bind_off + bind_size + lazy_size >
bin->size) {
164 if (
bin->dyld_info->weak_bind_off + weak_size >
bin->size) {
167 ut64 amount = bind_size + lazy_size + weak_size;
168 if (amount == 0 || amount >
UT32_MAX) {
194 size_t partition_sizes[] = { bind_size, lazy_size, weak_size };
196 int opcodes_offset = 0;
197 for (pidx = 0; pidx <
RZ_ARRAY_SIZE(partition_sizes); pidx++) {
198 size_t partition_size = partition_sizes[pidx];
201 int lib_ord = 0, seg_idx = -1, sym_ord = -1;
202 char *sym_name =
NULL;
206 ut64 segment_end_addr =
addr +
bin->segs[0].vmsize;
217 bool in_lazy_binds = pidx == 1;
218 if (!in_lazy_binds) {
226 ut64 table_size = read_uleb128(&
p,
end);
228 RZ_LOG_ERROR(
"Error: BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB size is wrong\n");
231 if (threaded_binds) {
235 if (threaded_binds) {
241 if (threaded_binds) {
242 int cur_seg_idx = (seg_idx != -1) ? seg_idx : 0;
244 while (
addr < segment_end_addr) {
246 ut64 paddr =
addr -
bin->segs[cur_seg_idx].vmaddr +
bin->segs[cur_seg_idx].fileoff;
251 bool is_auth = (raw_ptr & (1ULL << 63)) != 0;
252 bool is_bind = (raw_ptr & (1ULL << 62)) != 0;
256 if (is_auth && is_bind) {
261 }
else if (!is_auth && is_bind) {
267 }
else if (is_auth && !is_bind) {
277 if (ordinal >= n_threaded_binds) {
306 RZ_LOG_ERROR(
"Error: Unexpected BIND_OPCODE_THREADED sub-opcode: 0x%x\n",
imm);
314 lib_ord = read_uleb128(&
p,
end);
320 sym_name = (
char *)
p;
321 while (*
p++ &&
p <
end) {
324 if (threaded_binds) {
329 for (j = 0; j <
bin->dysymtab.nundefsym; j++) {
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) {
338 stridx =
bin->symtab[sidx].n_strx;
339 if (stridx >=
bin->symstrlen) {
344 if (
found && !strcmp((
const char *)
bin->symstr + stridx, sym_name)) {
360 if (seg_idx >=
bin->nsegs) {
361 RZ_LOG_ERROR(
"Error: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB"
362 " has unexistent segment %d\n",
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;
377 if (sym_ord < 0 && !sym_name) \
379 if (!threaded_binds) { \
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); \
392 reloc->addend = addend; \
394 reloc->addend = addend; \
397 reloc->ord = lib_ord; \
398 reloc->ord = sym_ord; \
399 reloc->type = rel_type; \
401 rz_str_ncpy(reloc->name, sym_name, 256); \
402 if (threaded_binds) \
403 rz_pvector_set(threaded_binds, sym_ord, reloc); \
405 rz_skiplist_insert(relocs, reloc); \
408 if (!threaded_binds &&
addr >= segment_end_addr) {
413 if (!threaded_binds) {
420 if (
addr >= segment_end_addr) {
421 RZ_LOG_ERROR(
"Error: Malformed ADDR ULEB bind opcode\n");
425 addr += read_uleb128(&
p,
end) + wordsize;
428 if (
addr >= segment_end_addr) {
429 RZ_LOG_ERROR(
"Error: Malformed IMM SCALED bind opcode\n");
438 for (j = 0; j <
count; j++) {
439 if (
addr >= segment_end_addr) {
440 RZ_LOG_ERROR(
"Error: Malformed ULEB TIMES bind opcode\n");
449 RZ_LOG_ERROR(
"Error: unknown bind opcode 0x%02x in dyld_info\n", *
p);
455 opcodes_offset += partition_size;
460 threaded_binds =
NULL;
463 if (
bin->symtab &&
bin->symstr &&
bin->sects &&
bin->indirectsyms) {
465 int amount =
bin->dysymtab.nundefsym;
475 for (j = 0; j < amount; j++) {
489 if (
bin->symtab &&
bin->dysymtab.extreloff &&
bin->dysymtab.nextrel) {
505 if (!obj->options.patch_relocs) {
508 if (obj->patchable_relocs) {
509 return obj->patchable_relocs;
516 if (!obj->patchable_relocs) {
529 return obj->patchable_relocs;
549 if (!patchable_relocs) {
557 if (obj->reloc_targets_map_base_calculated) {
558 return obj->reloc_targets_map_base;
563 obj->reloc_targets_map_base_calculated =
true;
564 return obj->reloc_targets_map_base;
571 switch (
bin->hdr.cputype) {
573 switch (reloc->
type) {
581 RZ_LOG_ERROR(
"Warning: unsupported reloc type for X86_64 (%d), please file a bug.\n", reloc->
type);
600 val = symbol_at -
pc - ins_len;
619 obj->relocs_patched =
true;
630 if (!obj->buf_patched) {
static RzList * maps(RzBinFile *bf)
RzBinInfo * info(RzBinFile *bf)
RzList * relocs(RzBinFile *bf)
int bits(struct state *s, int need)
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
void skip(file *in, unsigned n)
RZ_API void Ht_() free(HtName_(Ht) *ht)
RZ_API const KEY_TYPE bool * found
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
void * calloc(size_t number, size_t size)
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
RzList *MACH0_() get_maps_unpatched(RzBinFile *bf)
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.
RZ_API ut64 MACH0_() paddr_to_vaddr(struct MACH0_(obj_t) *bin, ut64 offset)
int MACH0_() get_bits_from_hdr(struct MACH0_(mach_header) *hdr)
const char *MACH0_() get_cputype_from_hdr(struct MACH0_(mach_header) *hdr)
@ 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.
@ 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_SET_ADDEND_SLEB
@ BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB
@ BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
@ BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB
@ REFERENCE_FLAG_UNDEFINED_LAZY
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
RZ_BORROW RzSkipList *MACH0_() get_relocs(struct MACH0_(obj_t) *bin)
static ut64 reloc_target_size(struct MACH0_(obj_t) *obj)
static bool _patch_reloc(struct MACH0_(obj_t) *bin, struct reloc_t *reloc, ut64 symbol_at)
static void parse_relocation_info(struct MACH0_(obj_t) *bin, RzSkipList *relocs, ut32 offset, ut32 num)
static bool is_valid_ordinal_table_size(ut64 size)
static RzPVector * get_patchable_relocs(struct MACH0_(obj_t) *obj)
RZ_API bool MACH0_() needs_reloc_patching(struct MACH0_(obj_t) *obj)
RZ_API ut64 MACH0_() reloc_targets_vfile_size(struct MACH0_(obj_t) *obj)
size of the artificial reloc target vfile
static int parse_import_ptr(struct MACH0_(obj_t) *bin, struct reloc_t *reloc, int idx)
RZ_API void MACH0_() patch_relocs(RzBinFile *bf, struct MACH0_(obj_t) *obj)
Patching of external relocs in a sparse overlay buffer.
static int reloc_comparator(struct reloc_t *a, struct reloc_t *b)
RZ_API ut64 rz_bin_reloc_target_builder_get_target(RzBinRelocTargetBuilder *builder, ut64 sym)
obtain the address of the target for a given symbol
RZ_API void rz_bin_reloc_target_builder_free(RzBinRelocTargetBuilder *builder)
RZ_API RzBinRelocTargetBuilder * rz_bin_reloc_target_builder_new(ut64 target_size, ut64 target_base)
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.
#define rz_return_if_fail(expr)
#define rz_return_val_if_fail(expr, val)
RZ_API void rz_buf_sparse_set_write_mode(RzBuffer *b, RzBufferSparseWriteMode mode)
Only for sparse RzBuffers.
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.
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.
@ RZ_BUF_SPARSE_WRITE_MODE_SPARSE
all writes are performed in the sparse overlay
@ RZ_BUF_SPARSE_WRITE_MODE_THROUGH
all writes are performed in the underlying base buffer
RZ_API RZ_OWN RzBuffer * rz_buf_new_sparse_overlay(RzBuffer *b, RzBufferSparseWriteMode write_mode)
Creates a sparse buffer from a already populated buffer.
static void rz_write_ble(void *dst, ut64 val, bool big_endian, int size)
static ut64 rz_read_le64(const void *src)
void(* RzListFree)(void *ptr)
int(* RzListComparator)(const void *value, const void *list_data)
#define RZ_LOG_ERROR(fmtstr,...)
RZ_API RzSkipList * rz_skiplist_new(RzListFree freefn, RzListComparator comparefn)
#define rz_skiplist_foreach(list, it, pos)
RZ_API void rz_skiplist_free(RzSkipList *list)
RZ_API RzSkipListNode * rz_skiplist_insert(RzSkipList *list, void *data)
RZ_API size_t rz_str_ncpy(char *dst, const char *src, size_t n)
Secure string copy with null terminator.
RZ_API st64 rz_sleb128(const ut8 **data, const ut8 *end)
static size_t rz_pvector_len(const RzPVector *vec)
RZ_API RzPVector * rz_pvector_new(RzPVectorFree free)
void(* RzPVectorFree)(void *e)
static void ** rz_pvector_push(RzPVector *vec, void *x)
RZ_API void rz_pvector_free(RzPVector *vec)
RZ_API RzPVector * rz_pvector_new_with_len(RzPVectorFree free, size_t length)
static void * rz_pvector_at(const RzPVector *vec, size_t index)
#define rz_pvector_foreach(vec, it)
XX curplugin == o->plugin.
ut64(WINAPI *w32_GetEnabledXStateFeatures)()