Skip to content

Commit

Permalink
Make dyld_chained_ptr_* parsing endian-independent
Browse files Browse the repository at this point in the history
Fixes test/db/cmd/cmd_tc and test/db/formats/mach0/arm64e on big endian
  • Loading branch information
thestr4ng3r committed Oct 21, 2022
1 parent 7685bfe commit e1ca030
Show file tree
Hide file tree
Showing 5 changed files with 245 additions and 58 deletions.
102 changes: 102 additions & 0 deletions librz/bin/format/mach0/mach0_defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -1483,6 +1483,14 @@ enum {
DYLD_CHAINED_PTR_ARM64E_USERLAND24 = 12,
};

#include <rz_util/rz_num.h>

#define READ_BITS(dst, count) \
do { \
dst = raw_val & rz_num_bitmask(count); \
raw_val >>= count; \
} while (0);

struct dyld_chained_ptr_arm64e_rebase {
uint64_t target : 43,
high8 : 8,
Expand All @@ -1491,6 +1499,14 @@ struct dyld_chained_ptr_arm64e_rebase {
auth : 1; // == 0
};

static inline void dyld_chained_ptr_arm64e_rebase_read(struct dyld_chained_ptr_arm64e_rebase *dst, ut64 raw_val) {
READ_BITS(dst->target, 43);
READ_BITS(dst->high8, 8);
READ_BITS(dst->next, 11);
READ_BITS(dst->bind, 1);
READ_BITS(dst->auth, 1);
}

struct dyld_chained_ptr_arm64e_bind {
uint64_t ordinal : 16,
zero : 16,
Expand All @@ -1500,6 +1516,15 @@ struct dyld_chained_ptr_arm64e_bind {
auth : 1; // == 0
};

static inline void dyld_chained_ptr_arm64e_bind_read(struct dyld_chained_ptr_arm64e_bind *dst, ut64 raw_val) {
READ_BITS(dst->ordinal, 16);
READ_BITS(dst->zero, 16);
READ_BITS(dst->addend, 19);
READ_BITS(dst->next, 11);
READ_BITS(dst->bind, 1);
READ_BITS(dst->auth, 1);
}

struct dyld_chained_ptr_arm64e_auth_rebase {
uint64_t target : 32,
diversity : 16,
Expand All @@ -1510,6 +1535,16 @@ struct dyld_chained_ptr_arm64e_auth_rebase {
auth : 1; // == 1
};

static inline void dyld_chained_ptr_arm64e_auth_rebase_read(struct dyld_chained_ptr_arm64e_auth_rebase *dst, ut64 raw_val) {
READ_BITS(dst->target, 32);
READ_BITS(dst->diversity, 16);
READ_BITS(dst->addrDiv, 1);
READ_BITS(dst->key, 2);
READ_BITS(dst->next, 11);
READ_BITS(dst->bind, 1);
READ_BITS(dst->auth, 1);
}

struct dyld_chained_ptr_arm64e_auth_bind {
uint64_t ordinal : 16,
zero : 16,
Expand All @@ -1521,6 +1556,17 @@ struct dyld_chained_ptr_arm64e_auth_bind {
auth : 1; // == 1
};

static inline void dyld_chained_ptr_arm64e_auth_bind_read(struct dyld_chained_ptr_arm64e_auth_bind *dst, ut64 raw_val) {
READ_BITS(dst->ordinal, 16);
READ_BITS(dst->zero, 16);
READ_BITS(dst->diversity, 16);
READ_BITS(dst->addrDiv, 1);
READ_BITS(dst->key, 2);
READ_BITS(dst->next, 11);
READ_BITS(dst->bind, 1);
READ_BITS(dst->auth, 1);
}

struct dyld_chained_ptr_64_rebase {
uint64_t target : 36,
high8 : 8,
Expand All @@ -1529,6 +1575,14 @@ struct dyld_chained_ptr_64_rebase {
bind : 1; // == 0
};

static inline void dyld_chained_ptr_64_rebase_read(struct dyld_chained_ptr_64_rebase *dst, ut64 raw_val) {
READ_BITS(dst->target, 36);
READ_BITS(dst->high8, 8);
READ_BITS(dst->reserved, 7);
READ_BITS(dst->next, 12);
READ_BITS(dst->bind, 1);
}

struct dyld_chained_ptr_64_bind {
uint64_t ordinal : 24,
addend : 8,
Expand All @@ -1537,6 +1591,14 @@ struct dyld_chained_ptr_64_bind {
bind : 1; // == 1
};

static inline void dyld_chained_ptr_64_bind_read(struct dyld_chained_ptr_64_bind *dst, ut64 raw_val) {
READ_BITS(dst->ordinal, 24);
READ_BITS(dst->addend, 8);
READ_BITS(dst->reserved, 19);
READ_BITS(dst->next, 12);
READ_BITS(dst->bind, 1);
}

/* WARNING: this is guesswork based on trial and error */
struct dyld_chained_ptr_arm64e_cache_rebase {
uint64_t target : 43,
Expand All @@ -1545,6 +1607,13 @@ struct dyld_chained_ptr_arm64e_cache_rebase {
auth : 1; // == 0
};

static inline void dyld_chained_ptr_arm64e_cache_rebase_read(struct dyld_chained_ptr_arm64e_cache_rebase *dst, ut64 raw_val) {
READ_BITS(dst->target, 43);
READ_BITS(dst->high8, 8);
READ_BITS(dst->next, 12);
READ_BITS(dst->auth, 1);
}

struct dyld_chained_ptr_arm64e_cache_auth_rebase {
uint64_t target : 32,
diversity : 16,
Expand All @@ -1554,6 +1623,15 @@ struct dyld_chained_ptr_arm64e_cache_auth_rebase {
auth : 1; // == 1
};

static inline void dyld_chained_ptr_arm64e_cache_auth_rebase_read(struct dyld_chained_ptr_arm64e_cache_auth_rebase *dst, ut64 raw_val) {
READ_BITS(dst->target, 32);
READ_BITS(dst->diversity, 16);
READ_BITS(dst->addrDiv, 1);
READ_BITS(dst->key, 2);
READ_BITS(dst->next, 12);
READ_BITS(dst->auth, 1);
}

struct dyld_chained_ptr_arm64e_bind24 {
uint64_t ordinal : 24,
zero : 8,
Expand All @@ -1563,6 +1641,15 @@ struct dyld_chained_ptr_arm64e_bind24 {
auth : 1; // == 0
};

static inline void dyld_chained_ptr_arm64e_bind24_read(struct dyld_chained_ptr_arm64e_bind24 *dst, ut64 raw_val) {
READ_BITS(dst->ordinal, 24);
READ_BITS(dst->zero, 8);
READ_BITS(dst->addend, 19);
READ_BITS(dst->next, 11);
READ_BITS(dst->bind, 1);
READ_BITS(dst->auth, 1);
}

struct dyld_chained_ptr_arm64e_auth_bind24 {
uint64_t ordinal : 24,
zero : 8,
Expand All @@ -1574,4 +1661,19 @@ struct dyld_chained_ptr_arm64e_auth_bind24 {
auth : 1; // == 1
};

static inline void dyld_chained_ptr_arm64e_auth_bind24_read(struct dyld_chained_ptr_arm64e_auth_bind24 *dst, ut64 raw_val) {
READ_BITS(dst->ordinal, 24);
READ_BITS(dst->zero, 8);
READ_BITS(dst->diversity, 16);
READ_BITS(dst->addrDiv, 1);
READ_BITS(dst->key, 2);
READ_BITS(dst->next, 11);
READ_BITS(dst->bind, 1);
READ_BITS(dst->auth, 1);
}

// When adding more structs/readers here, also add tests to test/unit/test_bin_mach0.c!

#undef READ_BITS

#endif
86 changes: 43 additions & 43 deletions librz/bin/format/mach0/mach0_rebase.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,55 +61,55 @@ RZ_API void MACH0_(rebase_buffer)(struct MACH0_(obj_t) * obj, ut64 off, ut8 *buf
case DYLD_CHAINED_PTR_ARM64E: {
bool is_bind = IS_PTR_BIND(raw_ptr);
if (is_auth && is_bind) {
struct dyld_chained_ptr_arm64e_auth_bind *p =
(struct dyld_chained_ptr_arm64e_auth_bind *)&raw_ptr;
delta = p->next;
struct dyld_chained_ptr_arm64e_auth_bind p;
dyld_chained_ptr_arm64e_auth_bind_read(&p, raw_ptr);
delta = p.next;
} else if (!is_auth && is_bind) {
struct dyld_chained_ptr_arm64e_bind *p =
(struct dyld_chained_ptr_arm64e_bind *)&raw_ptr;
delta = p->next;
struct dyld_chained_ptr_arm64e_bind p;
dyld_chained_ptr_arm64e_bind_read(&p, raw_ptr);
delta = p.next;
} else if (is_auth && !is_bind) {
struct dyld_chained_ptr_arm64e_auth_rebase *p =
(struct dyld_chained_ptr_arm64e_auth_rebase *)&raw_ptr;
delta = p->next;
ptr_value = p->target + obj->baddr;
struct dyld_chained_ptr_arm64e_auth_rebase p;
dyld_chained_ptr_arm64e_auth_rebase_read(&p, raw_ptr);
delta = p.next;
ptr_value = p.target + obj->baddr;
} else {
struct dyld_chained_ptr_arm64e_rebase *p =
(struct dyld_chained_ptr_arm64e_rebase *)&raw_ptr;
delta = p->next;
ptr_value = ((ut64)p->high8 << 56) | p->target;
struct dyld_chained_ptr_arm64e_rebase p;
dyld_chained_ptr_arm64e_rebase_read(&p, raw_ptr);
delta = p.next;
ptr_value = ((ut64)p.high8 << 56) | p.target;
}
break;
}
case DYLD_CHAINED_PTR_64_KERNEL_CACHE:
case DYLD_CHAINED_PTR_ARM64E_KERNEL: {
stride = 4;
if (is_auth) {
struct dyld_chained_ptr_arm64e_cache_auth_rebase *p =
(struct dyld_chained_ptr_arm64e_cache_auth_rebase *)&raw_ptr;
delta = p->next;
ptr_value = p->target + obj->baddr;
struct dyld_chained_ptr_arm64e_cache_auth_rebase p;
dyld_chained_ptr_arm64e_cache_auth_rebase_read(&p, raw_ptr);
delta = p.next;
ptr_value = p.target + obj->baddr;
} else {
struct dyld_chained_ptr_arm64e_cache_rebase *p =
(struct dyld_chained_ptr_arm64e_cache_rebase *)&raw_ptr;
delta = p->next;
ptr_value = ((ut64)p->high8 << 56) | p->target;
struct dyld_chained_ptr_arm64e_cache_rebase p;
dyld_chained_ptr_arm64e_cache_rebase_read(&p, raw_ptr);
delta = p.next;
ptr_value = ((ut64)p.high8 << 56) | p.target;
ptr_value += obj->baddr;
}
break;
}
case DYLD_CHAINED_PTR_64:
case DYLD_CHAINED_PTR_64_OFFSET: {
stride = 4;
struct dyld_chained_ptr_64_bind *bind =
(struct dyld_chained_ptr_64_bind *)&raw_ptr;
if (bind->bind) {
delta = bind->next;
struct dyld_chained_ptr_64_bind bind;
dyld_chained_ptr_64_bind_read(&bind, raw_ptr);
if (bind.bind) {
delta = bind.next;
} else {
struct dyld_chained_ptr_64_rebase *p =
(struct dyld_chained_ptr_64_rebase *)&raw_ptr;
delta = p->next;
ptr_value = (((ut64)p->high8 << 56) | p->target);
struct dyld_chained_ptr_64_rebase p;
dyld_chained_ptr_64_rebase_read(&p, raw_ptr);
delta = p.next;
ptr_value = (((ut64)p.high8 << 56) | p.target);
if (segment->pointer_format == DYLD_CHAINED_PTR_64_OFFSET) {
ptr_value += obj->baddr;
}
Expand All @@ -118,21 +118,21 @@ RZ_API void MACH0_(rebase_buffer)(struct MACH0_(obj_t) * obj, ut64 off, ut8 *buf
}
case DYLD_CHAINED_PTR_ARM64E_USERLAND24: {
stride = 8;
struct dyld_chained_ptr_arm64e_bind24 *bind =
(struct dyld_chained_ptr_arm64e_bind24 *)&raw_ptr;
if (bind->bind) {
delta = bind->next;
struct dyld_chained_ptr_arm64e_bind24 bind;
dyld_chained_ptr_arm64e_bind24_read(&bind, raw_ptr);
if (bind.bind) {
delta = bind.next;
} else {
if (bind->auth) {
struct dyld_chained_ptr_arm64e_auth_rebase *p =
(struct dyld_chained_ptr_arm64e_auth_rebase *)&raw_ptr;
delta = p->next;
ptr_value = p->target + obj->baddr;
if (bind.auth) {
struct dyld_chained_ptr_arm64e_auth_rebase p;
dyld_chained_ptr_arm64e_auth_rebase_read(&p, raw_ptr);
delta = p.next;
ptr_value = p.target + obj->baddr;
} else {
struct dyld_chained_ptr_arm64e_rebase *p =
(struct dyld_chained_ptr_arm64e_rebase *)&raw_ptr;
delta = p->next;
ptr_value = obj->baddr + (((ut64)p->high8 << 56) | p->target);
struct dyld_chained_ptr_arm64e_rebase p;
dyld_chained_ptr_arm64e_rebase_read(&p, raw_ptr);
delta = p.next;
ptr_value = obj->baddr + (((ut64)p.high8 << 56) | p.target);
}
}
break;
Expand Down
30 changes: 15 additions & 15 deletions librz/bin/format/mach0/mach0_relocs.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,24 +254,24 @@ RZ_BORROW RzSkipList *MACH0_(get_relocs)(struct MACH0_(obj_t) * bin) {
int addend = -1;
ut64 delta;
if (is_auth && is_bind) {
struct dyld_chained_ptr_arm64e_auth_bind *p =
(struct dyld_chained_ptr_arm64e_auth_bind *)&raw_ptr;
delta = p->next;
ordinal = p->ordinal;
struct dyld_chained_ptr_arm64e_auth_bind p;
dyld_chained_ptr_arm64e_auth_bind_read(&p, raw_ptr);
delta = p.next;
ordinal = p.ordinal;
} else if (!is_auth && is_bind) {
struct dyld_chained_ptr_arm64e_bind *p =
(struct dyld_chained_ptr_arm64e_bind *)&raw_ptr;
delta = p->next;
ordinal = p->ordinal;
addend = p->addend;
struct dyld_chained_ptr_arm64e_bind p;
dyld_chained_ptr_arm64e_bind_read(&p, raw_ptr);
delta = p.next;
ordinal = p.ordinal;
addend = p.addend;
} else if (is_auth && !is_bind) {
struct dyld_chained_ptr_arm64e_auth_rebase *p =
(struct dyld_chained_ptr_arm64e_auth_rebase *)&raw_ptr;
delta = p->next;
struct dyld_chained_ptr_arm64e_auth_rebase p;
dyld_chained_ptr_arm64e_auth_rebase_read(&p, raw_ptr);
delta = p.next;
} else {
struct dyld_chained_ptr_arm64e_rebase *p =
(struct dyld_chained_ptr_arm64e_rebase *)&raw_ptr;
delta = p->next;
struct dyld_chained_ptr_arm64e_rebase p;
dyld_chained_ptr_arm64e_rebase_read(&p, raw_ptr);
delta = p.next;
}
if (ordinal != -1) {
if (ordinal >= n_threaded_binds) {
Expand Down
1 change: 1 addition & 0 deletions test/unit/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ if get_option('enable_tests')
'base64',
'big',
'bin_lines',
'bin_mach0',
'bitmap',
'bitvector',
'buf',
Expand Down
Loading

0 comments on commit e1ca030

Please sign in to comment.