Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make dyld_chained_ptr_* parsing endian-independent #3113

Merged
merged 1 commit into from
Oct 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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