mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-26 22:50:48 +00:00
Refactor mach0 loading of relocs ##bin
This commit is contained in:
parent
86d77e2a54
commit
7ee8fb77a2
@ -2194,6 +2194,9 @@ void *MACH0_(mach0_free)(struct MACH0_(obj_t) *mo) {
|
||||
}
|
||||
r_list_free (mo->cached_segments);
|
||||
mo->cached_segments = NULL;
|
||||
if (mo->relocs_loaded) {
|
||||
r_skiplist_free (mo->relocs_cache);
|
||||
}
|
||||
if (mo->chained_starts) {
|
||||
for (i = 0; i < mo->nsegs && i < mo->segs_count; i++) {
|
||||
if (mo->chained_starts[i]) {
|
||||
@ -3540,8 +3543,7 @@ static bool is_valid_ordinal_table_size(ut64 size) {
|
||||
return size > 0 && size <= UT16_MAX;
|
||||
}
|
||||
|
||||
RSkipList *MACH0_(get_relocs)(struct MACH0_(obj_t) *bin) {
|
||||
RSkipList *relocs = NULL;
|
||||
static inline bool _load_relocations(struct MACH0_(obj_t) *bin) {
|
||||
RPVector *threaded_binds = NULL;
|
||||
size_t wordsize = get_word_size (bin);
|
||||
if (bin->dyld_info) {
|
||||
@ -3554,7 +3556,7 @@ RSkipList *MACH0_(get_relocs)(struct MACH0_(obj_t) *bin) {
|
||||
CASE(16);
|
||||
CASE(32);
|
||||
CASE(64);
|
||||
default: return NULL;
|
||||
default: return false;
|
||||
}
|
||||
#undef CASE
|
||||
bind_size = bin->dyld_info->bind_size;
|
||||
@ -3562,40 +3564,35 @@ RSkipList *MACH0_(get_relocs)(struct MACH0_(obj_t) *bin) {
|
||||
weak_size = bin->dyld_info->weak_bind_size;
|
||||
|
||||
if (!bind_size && !lazy_size) {
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((bind_size + lazy_size) < 1) {
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
if (bin->dyld_info->bind_off > bin->size || bin->dyld_info->bind_off + bind_size > bin->size) {
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
if (bin->dyld_info->lazy_bind_off > bin->size || \
|
||||
bin->dyld_info->lazy_bind_off + lazy_size > bin->size) {
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
if (bin->dyld_info->bind_off + bind_size + lazy_size > bin->size) {
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
if (bin->dyld_info->weak_bind_off + weak_size > bin->size) {
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
ut64 amount = bind_size + lazy_size + weak_size;
|
||||
if (amount == 0 || amount > UT32_MAX) {
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
if (!bin->segs) {
|
||||
return NULL;
|
||||
}
|
||||
relocs = r_skiplist_new ((RListFree) &free, (RListComparator) &reloc_comparator);
|
||||
if (!relocs) {
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
opcodes = calloc (1, amount + 1);
|
||||
if (!opcodes) {
|
||||
r_skiplist_free (relocs);
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
int len = r_buf_read_at (bin->b, bin->dyld_info->bind_off, opcodes, bind_size);
|
||||
@ -3604,8 +3601,7 @@ RSkipList *MACH0_(get_relocs)(struct MACH0_(obj_t) *bin) {
|
||||
if (len < amount) {
|
||||
R_LOG_ERROR ("read (dyld_info bind) at 0x%08"PFMT64x, (ut64)(size_t)bin->dyld_info->bind_off);
|
||||
R_FREE (opcodes);
|
||||
r_skiplist_free (relocs);
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t partition_sizes[] = {bind_size, lazy_size, weak_size};
|
||||
@ -3720,7 +3716,7 @@ RSkipList *MACH0_(get_relocs)(struct MACH0_(obj_t) *bin) {
|
||||
if (addend != -1) {
|
||||
reloc->addend = addend;
|
||||
}
|
||||
r_skiplist_insert (relocs, reloc);
|
||||
r_skiplist_insert (bin->relocs_cache, reloc);
|
||||
}
|
||||
addr += delta * wordsize;
|
||||
if (!delta) {
|
||||
@ -3788,9 +3784,8 @@ RSkipList *MACH0_(get_relocs)(struct MACH0_(obj_t) *bin) {
|
||||
bprintf ("Error: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB"
|
||||
" has unexistent segment %d\n", seg_idx);
|
||||
free (opcodes);
|
||||
r_skiplist_free (relocs);
|
||||
r_pvector_free (threaded_binds);
|
||||
return NULL; // early exit to avoid future mayhem
|
||||
return false; // early exit to avoid future mayhem
|
||||
}
|
||||
addr = bin->segs[seg_idx].vmaddr + read_uleb128 (&p, end);
|
||||
segment_end_addr = bin->segs[seg_idx].vmaddr \
|
||||
@ -3825,7 +3820,7 @@ RSkipList *MACH0_(get_relocs)(struct MACH0_(obj_t) *bin) {
|
||||
if (threaded_binds)\
|
||||
r_pvector_set (threaded_binds, sym_ord, reloc);\
|
||||
else\
|
||||
r_skiplist_insert (relocs, reloc);\
|
||||
r_skiplist_insert (bin->relocs_cache, reloc);\
|
||||
} while (0)
|
||||
case BIND_OPCODE_DO_BIND:
|
||||
if (!threaded_binds && addr >= segment_end_addr) {
|
||||
@ -3872,7 +3867,7 @@ RSkipList *MACH0_(get_relocs)(struct MACH0_(obj_t) *bin) {
|
||||
bprintf ("Error: unknown bind opcode 0x%02x in dyld_info\n", *p);
|
||||
R_FREE (opcodes);
|
||||
r_pvector_free (threaded_binds);
|
||||
return relocs;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3890,12 +3885,6 @@ RSkipList *MACH0_(get_relocs)(struct MACH0_(obj_t) *bin) {
|
||||
if (amount < 0) {
|
||||
amount = 0;
|
||||
}
|
||||
if (!relocs) {
|
||||
relocs = r_skiplist_new ((RListFree) &free, (RListComparator) &reloc_comparator);
|
||||
if (!relocs) {
|
||||
goto beach;
|
||||
}
|
||||
}
|
||||
for (j = 0; j < amount; j++) {
|
||||
struct reloc_t *reloc = R_NEW0 (struct reloc_t);
|
||||
if (!reloc) {
|
||||
@ -3903,7 +3892,7 @@ RSkipList *MACH0_(get_relocs)(struct MACH0_(obj_t) *bin) {
|
||||
}
|
||||
if (parse_import_ptr (bin, reloc, bin->dysymtab.iundefsym + j)) {
|
||||
reloc->ord = j;
|
||||
r_skiplist_insert_autofree (relocs, reloc);
|
||||
r_skiplist_insert_autofree (bin->relocs_cache, reloc);
|
||||
} else {
|
||||
R_FREE (reloc);
|
||||
}
|
||||
@ -3911,27 +3900,37 @@ RSkipList *MACH0_(get_relocs)(struct MACH0_(obj_t) *bin) {
|
||||
}
|
||||
|
||||
if (bin->symtab && bin->dysymtab.extreloff && bin->dysymtab.nextrel) {
|
||||
if (!relocs) {
|
||||
relocs = r_skiplist_new ((RListFree) &free, (RListComparator) &reloc_comparator);
|
||||
if (!relocs) {
|
||||
goto beach;
|
||||
}
|
||||
}
|
||||
parse_relocation_info (bin, relocs, bin->dysymtab.extreloff, bin->dysymtab.nextrel);
|
||||
parse_relocation_info (bin, bin->relocs_cache, bin->dysymtab.extreloff, bin->dysymtab.nextrel);
|
||||
}
|
||||
|
||||
if (!bin->dyld_info && bin->chained_starts && bin->nsegs && bin->fixups_offset) {
|
||||
if (!relocs) {
|
||||
relocs = r_skiplist_new ((RListFree) &free, (RListComparator) &reloc_comparator);
|
||||
if (!relocs) {
|
||||
goto beach;
|
||||
}
|
||||
}
|
||||
walk_bind_chains (bin, relocs);
|
||||
walk_bind_chains (bin, bin->relocs_cache);
|
||||
}
|
||||
|
||||
beach:
|
||||
r_pvector_free (threaded_binds);
|
||||
return relocs;
|
||||
return true;
|
||||
}
|
||||
|
||||
const RSkipList *MACH0_(load_relocs)(struct MACH0_(obj_t) *bin) {
|
||||
r_return_val_if_fail (bin, NULL);
|
||||
|
||||
if (bin->relocs_loaded) {
|
||||
return bin->relocs_cache;
|
||||
}
|
||||
|
||||
bin->relocs_loaded = true;
|
||||
bin->relocs_cache = r_skiplist_new ((RListFree) free, (RListComparator) reloc_comparator);
|
||||
if (!bin->relocs_cache) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool is_success = _load_relocations (bin);
|
||||
if (is_success) {
|
||||
return bin->relocs_cache;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct addr_t *MACH0_(get_entrypoint)(struct MACH0_(obj_t) *bin) {
|
||||
|
@ -62,7 +62,6 @@ struct reloc_t {
|
||||
st64 addend;
|
||||
ut8 type;
|
||||
int ord;
|
||||
int last;
|
||||
char name[256];
|
||||
bool external;
|
||||
bool pc_relative;
|
||||
@ -180,6 +179,8 @@ struct MACH0_(obj_t) {
|
||||
RVector sections_cache;
|
||||
bool imports_loaded;
|
||||
RPVector imports_cache;
|
||||
bool relocs_loaded;
|
||||
RSkipList *relocs_cache;
|
||||
RList *reloc_fixups;
|
||||
ut8 *internal_buffer;
|
||||
int internal_buffer_size;
|
||||
@ -247,7 +248,7 @@ RList *MACH0_(get_segments)(RBinFile *bf, struct MACH0_(obj_t) *bin);
|
||||
const RVector *MACH0_(load_symbols)(RBinFile *bf, struct MACH0_(obj_t) *bin);
|
||||
void MACH0_(pull_symbols)(struct MACH0_(obj_t) *mo, RBinSymbolCallback cb, void *user);
|
||||
const RPVector *MACH0_(load_imports)(RBinFile* bf, struct MACH0_(obj_t) *bin);
|
||||
RSkipList *MACH0_(get_relocs)(struct MACH0_(obj_t) *bin);
|
||||
const RSkipList *MACH0_(load_relocs)(struct MACH0_(obj_t) *bin);
|
||||
struct addr_t *MACH0_(get_entrypoint)(struct MACH0_(obj_t) *bin);
|
||||
const RPVector *MACH0_(load_libs)(struct MACH0_(obj_t) *bin);
|
||||
ut64 MACH0_(get_baddr)(struct MACH0_(obj_t) *bin);
|
||||
|
@ -112,7 +112,7 @@ static void get_objc_property_list(mach0_ut p, RBinFile *bf, RBinClass *klass);
|
||||
static void get_method_list_t(mach0_ut p, RBinFile *bf, char *class_name, RBinClass *klass, bool is_static, objc_cache_opt_info *oi);
|
||||
static void get_protocol_list_t(mach0_ut p, RBinFile *bf, RBinClass *klass, objc_cache_opt_info *oi);
|
||||
static void get_class_ro_t(mach0_ut p, RBinFile *bf, ut32 *is_meta_class, RBinClass *klass, objc_cache_opt_info *oi);
|
||||
static RList *MACH0_(parse_categories)(RBinFile *bf, RSkipList *relocs, objc_cache_opt_info *oi);
|
||||
static RList *MACH0_(parse_categories)(RBinFile *bf, const RSkipList *relocs, objc_cache_opt_info *oi);
|
||||
static bool read_ptr_pa(RBinFile *bf, ut64 paddr, mach0_ut *out);
|
||||
static bool read_ptr_va(RBinFile *bf, ut64 vaddr, mach0_ut *out);
|
||||
static char *read_str(RBinFile *bf, mach0_ut p, ut32 *offset, ut32 *left);
|
||||
@ -1137,7 +1137,7 @@ static mach0_ut get_isa_value(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MACH0_(get_class_t)(mach0_ut p, RBinFile *bf, RBinClass *klass, bool dupe, RSkipList *relocs, objc_cache_opt_info *oi) {
|
||||
void MACH0_(get_class_t)(mach0_ut p, RBinFile *bf, RBinClass *klass, bool dupe, const RSkipList *relocs, objc_cache_opt_info *oi) {
|
||||
struct MACH0_(SClass) c = {0};
|
||||
const int size = sizeof (struct MACH0_(SClass));
|
||||
mach0_ut r = 0;
|
||||
@ -1399,8 +1399,7 @@ RList *MACH0_(parse_classes)(RBinFile *bf, objc_cache_opt_info *oi) {
|
||||
}
|
||||
bool bigendian = bf->o->info->big_endian;
|
||||
|
||||
RSkipList *relocs = MACH0_(get_relocs) (bf->o->bin_obj);
|
||||
|
||||
const RSkipList *relocs = MACH0_(load_relocs) (bf->o->bin_obj);
|
||||
ret = MACH0_(parse_categories) (bf, relocs, oi);
|
||||
|
||||
/* check if it's Swift */
|
||||
@ -1410,7 +1409,6 @@ RList *MACH0_(parse_classes)(RBinFile *bf, objc_cache_opt_info *oi) {
|
||||
|
||||
const RVector *sections = MACH0_(load_sections) (bf->o->bin_obj);
|
||||
if (!sections) {
|
||||
r_skiplist_free (relocs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1526,18 +1524,16 @@ RList *MACH0_(parse_classes)(RBinFile *bf, objc_cache_opt_info *oi) {
|
||||
}
|
||||
r_list_append (ret, klass);
|
||||
}
|
||||
r_skiplist_free (relocs);
|
||||
return ret;
|
||||
|
||||
get_classes_error:
|
||||
r_list_free (sctns);
|
||||
r_list_free (ret);
|
||||
r_skiplist_free (relocs);
|
||||
// XXX DOUBLE FREE r_bin_class_free (klass);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static RList *MACH0_(parse_categories)(RBinFile *bf, RSkipList *relocs, objc_cache_opt_info *oi) {
|
||||
static RList *MACH0_(parse_categories)(RBinFile *bf, const RSkipList *relocs, objc_cache_opt_info *oi) {
|
||||
r_return_val_if_fail (bf && bf->o && bf->o->bin_obj && bf->o->info, NULL);
|
||||
|
||||
RList /*<RBinClass>*/ *ret = NULL;
|
||||
@ -1629,7 +1625,7 @@ error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MACH0_(get_category_t)(mach0_ut p, RBinFile *bf, RBinClass *klass, RSkipList *relocs, objc_cache_opt_info *oi) {
|
||||
void MACH0_(get_category_t)(mach0_ut p, RBinFile *bf, RBinClass *klass, const RSkipList *relocs, objc_cache_opt_info *oi) {
|
||||
r_return_if_fail (bf && bf->o && bf->o->info);
|
||||
|
||||
struct MACH0_(SCategory) c = {0};
|
||||
|
@ -18,7 +18,7 @@
|
||||
#define MACH0_CLASSES_H
|
||||
|
||||
R_API RList *MACH0_(parse_classes)(RBinFile *bf, objc_cache_opt_info *oi);
|
||||
R_API void MACH0_(get_class_t)(mach0_ut p, RBinFile *bf, RBinClass *klass, bool dupe, RSkipList *relocs, objc_cache_opt_info *oi);
|
||||
R_API void MACH0_(get_category_t)(mach0_ut p, RBinFile *bf, RBinClass *klass, RSkipList *relocs, objc_cache_opt_info *oi);
|
||||
R_API void MACH0_(get_class_t)(mach0_ut p, RBinFile *bf, RBinClass *klass, bool dupe, const RSkipList *relocs, objc_cache_opt_info *oi);
|
||||
R_API void MACH0_(get_category_t)(mach0_ut p, RBinFile *bf, RBinClass *klass, const RSkipList *relocs, objc_cache_opt_info *oi);
|
||||
|
||||
#endif // MACH0_CLASSES_H
|
||||
|
@ -282,7 +282,7 @@ static RList *relocs(RBinFile *bf) {
|
||||
return NULL;
|
||||
}
|
||||
ret->free = free;
|
||||
RSkipList *relocs = MACH0_(get_relocs) (bf->o->bin_obj);
|
||||
const RSkipList *relocs = MACH0_(load_relocs) (bf->o->bin_obj);
|
||||
if (!relocs) {
|
||||
return ret;
|
||||
}
|
||||
@ -317,8 +317,6 @@ static RList *relocs(RBinFile *bf) {
|
||||
r_list_append (ret, ptr);
|
||||
}
|
||||
|
||||
r_skiplist_free (relocs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -474,21 +472,19 @@ static RList* patch_relocs(RBin *b) {
|
||||
const bool apply_relocs = io->cached; // true; // !mo->b->readonly;
|
||||
const bool cache_relocs = io->cached;
|
||||
|
||||
RSkipList *all_relocs = MACH0_(get_relocs)(mo);
|
||||
const RSkipList *all_relocs = MACH0_(load_relocs)(mo);
|
||||
if (!all_relocs) {
|
||||
return NULL;
|
||||
}
|
||||
RList *ext_relocs = r_list_new ();
|
||||
if (!ext_relocs) {
|
||||
goto beach;
|
||||
}
|
||||
RPVector ext_relocs;
|
||||
r_pvector_init (&ext_relocs, NULL);
|
||||
RSkipListNode *it;
|
||||
struct reloc_t *reloc;
|
||||
r_skiplist_foreach (all_relocs, it, reloc) {
|
||||
if (!reloc->external) {
|
||||
continue;
|
||||
}
|
||||
r_list_append (ext_relocs, reloc);
|
||||
r_pvector_push (&ext_relocs, reloc);
|
||||
}
|
||||
if (mo->reloc_fixups && r_list_length (mo->reloc_fixups) > 0) {
|
||||
if (!apply_relocs) {
|
||||
@ -519,7 +515,7 @@ static RList* patch_relocs(RBin *b) {
|
||||
}
|
||||
}
|
||||
}
|
||||
ut64 num_ext_relocs = r_list_length (ext_relocs);
|
||||
ut64 num_ext_relocs = r_pvector_length (&ext_relocs);
|
||||
if (!num_ext_relocs) {
|
||||
goto beach;
|
||||
}
|
||||
@ -569,8 +565,9 @@ static RList* patch_relocs(RBin *b) {
|
||||
goto beach;
|
||||
}
|
||||
ut64 vaddr = n_vaddr;
|
||||
RListIter *liter;
|
||||
r_list_foreach (ext_relocs, liter, reloc) {
|
||||
void **ext_reloc_iter;
|
||||
r_pvector_foreach (&ext_relocs, ext_reloc_iter) {
|
||||
reloc = *ext_reloc_iter;
|
||||
bool found = false;
|
||||
ut64 sym_addr = ht_uu_find (relocs_by_sym, reloc->ord, &found);
|
||||
if (!found || !sym_addr) {
|
||||
@ -599,13 +596,12 @@ static RList* patch_relocs(RBin *b) {
|
||||
goto beach;
|
||||
}
|
||||
ht_uu_free (relocs_by_sym);
|
||||
r_list_free (ext_relocs);
|
||||
r_skiplist_free (all_relocs);
|
||||
r_pvector_fini (&ext_relocs);
|
||||
// XXX r_io_desc_free (gotr2desc);
|
||||
return ret;
|
||||
|
||||
beach:
|
||||
r_list_free (ext_relocs);
|
||||
r_skiplist_free (all_relocs);
|
||||
r_pvector_fini (&ext_relocs);
|
||||
r_io_desc_free (gotr2desc);
|
||||
r_list_free (ret);
|
||||
ht_uu_free (relocs_by_sym);
|
||||
|
@ -36,7 +36,7 @@ R_API RSkipListNode* r_skiplist_insert(RSkipList* list, void* data);
|
||||
R_API bool r_skiplist_insert_autofree(RSkipList* list, void* data);
|
||||
R_API bool r_skiplist_delete(RSkipList* list, void* data);
|
||||
R_API bool r_skiplist_delete_node(RSkipList *list, RSkipListNode *node);
|
||||
R_API RSkipListNode* r_skiplist_find(RSkipList* list, void* data);
|
||||
R_API RSkipListNode* r_skiplist_find(const RSkipList* list, void* data);
|
||||
R_API RSkipListNode* r_skiplist_find_geq(RSkipList* list, void* data);
|
||||
R_API RSkipListNode* r_skiplist_find_leq(RSkipList* list, void* data);
|
||||
R_API void r_skiplist_join(RSkipList *l1, RSkipList *l2);
|
||||
|
@ -48,7 +48,7 @@ static inline void init_head(RSkipListNode *head) {
|
||||
//
|
||||
// NOTE: `updates` should be big enough to contain `list->list_level + 1`
|
||||
// elements, when provided.
|
||||
static RSkipListNode *find_insertpoint(RSkipList *list, void *data, RSkipListNode **updates, bool by_data) {
|
||||
static RSkipListNode *find_insertpoint(const RSkipList *list, void *data, RSkipListNode **updates, bool by_data) {
|
||||
RSkipListNode *x = list->head;
|
||||
int i;
|
||||
|
||||
@ -216,7 +216,7 @@ R_API bool r_skiplist_delete_node(RSkipList *list, RSkipListNode *node) {
|
||||
return delete_element (list, node, false);
|
||||
}
|
||||
|
||||
R_API RSkipListNode* r_skiplist_find(RSkipList* list, void* data) {
|
||||
R_API RSkipListNode* r_skiplist_find(const RSkipList* list, void* data) {
|
||||
r_return_val_if_fail (list, NULL);
|
||||
RSkipListNode* x = find_insertpoint (list, data, NULL, true);
|
||||
if (x != list->head && list->compare (x->data, data) == 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user