Implement chained fixups patching for binds

For bind chained fixups (pointing to imports parsed in the previous
commit) we reuse the patching code for classic relocs as the logic is
more generic here than for local chained fixups.
This commit is contained in:
Florian Märkl 2023-06-24 16:08:23 +02:00 committed by Anton Kochkov
parent b6f984e445
commit ebe4263323
7 changed files with 62 additions and 48 deletions

View file

@ -68,8 +68,9 @@ struct reloc_t {
int ord;
int last;
char name[256];
bool external;
bool pc_relative;
bool external : 1,
pc_relative : 1,
chained : 1;
ut8 size;
ut64 target;
};
@ -278,6 +279,7 @@ RZ_API RZ_OWN char *MACH0_(chained_import_read_symbol_name)(struct MACH0_(obj_t)
RZ_API RZ_OWN char *MACH0_(read_chained_symbol)(struct MACH0_(obj_t) * obj, ut32 name_offset);
RZ_API bool MACH0_(needs_reloc_patching)(struct MACH0_(obj_t) * obj);
RZ_API ut64 MACH0_(reloc_target_size)(struct MACH0_(obj_t) * obj);
RZ_API ut64 MACH0_(reloc_targets_vfile_size)(struct MACH0_(obj_t) * obj);
RZ_API ut64 MACH0_(reloc_targets_map_base)(RzBinFile *bf, struct MACH0_(obj_t) * obj);
RZ_API void MACH0_(patch_relocs)(RzBinFile *bf, struct MACH0_(obj_t) * obj);

View file

@ -546,6 +546,10 @@ RZ_API bool MACH0_(segment_has_chained_fixups)(struct MACH0_(obj_t) * obj, size_
static void fixups_patch_cb(struct mach0_chained_fixup_t *fixup, void *user) {
RzBuffer *dst = user;
if (fixup->is_bind) {
// patching bind relocs is handled in MACH0_(patch_relocs)() before already
return;
}
switch (fixup->size) {
case 4:
rz_buf_write_le32_at(dst, fixup->paddr, fixup->result);
@ -559,7 +563,11 @@ static void fixups_patch_cb(struct mach0_chained_fixup_t *fixup, void *user) {
}
}
/**
* Patch all non-bind chained fixups into \p dst
*/
RZ_API void MACH0_(patch_chained_fixups)(struct MACH0_(obj_t) * obj, RzBuffer *dst) {
MACH0_(chained_fixups_foreach)
(obj, fixups_patch_cb, dst);
// clang-format off
MACH0_(chained_fixups_foreach)(obj, fixups_patch_cb, dst);
// clang-format on
}

View file

@ -88,6 +88,7 @@ static void parse_relocation_info(struct MACH0_(obj_t) * bin, RzSkipList *relocs
reloc->type = a_info.r_type; // enum RelocationInfoType
reloc->external = a_info.r_extern;
reloc->pc_relative = a_info.r_pcrel;
reloc->chained = false;
reloc->size = 1 << a_info.r_length; // macho/reloc.h says: 0=byte, 1=word, 2=long, 3=quad
rz_str_ncpy(reloc->name, sym_name, sizeof(reloc->name) - 1);
rz_skiplist_insert(relocs, reloc);
@ -165,6 +166,7 @@ static void fixups_as_relocs_cb(struct mach0_chained_fixup_t *fixup, void *user)
reloc->type = fixup->size == 4 ? RZ_BIN_RELOC_32 : RZ_BIN_RELOC_64;
reloc->ord = fixup->is_bind ? fixup->bind_ordinal : -1;
reloc->external = fixup->is_bind;
reloc->chained = true;
reloc->size = fixup->size;
if (fixup->is_bind) {
@ -570,7 +572,7 @@ RZ_API bool MACH0_(needs_reloc_patching)(struct MACH0_(obj_t) * obj) {
return patchable_relocs && rz_pvector_len(patchable_relocs);
}
static ut64 reloc_target_size(struct MACH0_(obj_t) * obj) {
RZ_API ut64 MACH0_(reloc_target_size)(struct MACH0_(obj_t) * obj) {
int bits = MACH0_(get_bits_from_hdr)(&obj->hdr);
if (bits) {
return 8;
@ -584,7 +586,7 @@ RZ_API ut64 MACH0_(reloc_targets_vfile_size)(struct MACH0_(obj_t) * obj) {
if (!patchable_relocs) {
return 0;
}
return rz_pvector_len(patchable_relocs) * reloc_target_size(obj);
return rz_pvector_len(patchable_relocs) * MACH0_(reloc_target_size)(obj);
}
/// base vaddr where to map the artificial reloc target vfile
@ -593,7 +595,7 @@ RZ_API ut64 MACH0_(reloc_targets_map_base)(RzBinFile *bf, struct MACH0_(obj_t) *
return obj->reloc_targets_map_base;
}
RzList *maps = MACH0_(get_maps_unpatched)(bf);
obj->reloc_targets_map_base = rz_bin_relocs_patch_find_targets_map_base(maps, reloc_target_size(obj));
obj->reloc_targets_map_base = rz_bin_relocs_patch_find_targets_map_base(maps, MACH0_(reloc_target_size)(obj));
rz_list_free(maps);
obj->reloc_targets_map_base_calculated = true;
return obj->reloc_targets_map_base;
@ -603,31 +605,33 @@ static bool _patch_reloc(struct MACH0_(obj_t) * bin, struct reloc_t *reloc, ut64
ut64 pc = reloc->addr;
ut64 ins_len = 0;
switch (bin->hdr.cputype) {
case CPU_TYPE_X86_64: {
switch (reloc->type) {
case X86_64_RELOC_UNSIGNED:
if (!reloc->chained) {
switch (bin->hdr.cputype) {
case CPU_TYPE_X86_64: {
switch (reloc->type) {
case X86_64_RELOC_UNSIGNED:
break;
case X86_64_RELOC_BRANCH:
pc -= 1;
ins_len = 5;
break;
default:
RZ_LOG_ERROR("Warning: unsupported reloc type for X86_64 (%d), please file a bug.\n", reloc->type);
return false;
}
break;
case X86_64_RELOC_BRANCH:
pc -= 1;
ins_len = 5;
}
case CPU_TYPE_ARM64:
case CPU_TYPE_ARM64_32:
pc = reloc->addr & ~3;
ins_len = 4;
break;
case CPU_TYPE_ARM:
break;
default:
RZ_LOG_ERROR("Warning: unsupported reloc type for X86_64 (%d), please file a bug.\n", reloc->type);
RZ_LOG_ERROR("Warning: unsupported architecture for patching relocs, please file a bug. %s\n", MACH0_(get_cputype_from_hdr)(&bin->hdr));
return false;
}
break;
}
case CPU_TYPE_ARM64:
case CPU_TYPE_ARM64_32:
pc = reloc->addr & ~3;
ins_len = 4;
break;
case CPU_TYPE_ARM:
break;
default:
RZ_LOG_ERROR("Warning: unsupported architecture for patching relocs, please file a bug. %s\n", MACH0_(get_cputype_from_hdr)(&bin->hdr));
return false;
}
ut64 val = symbol_at;
@ -663,7 +667,7 @@ RZ_API void MACH0_(patch_relocs)(RzBinFile *bf, struct MACH0_(obj_t) * obj) {
}
if (needs_reloc_patch) {
ut64 cdsz = reloc_target_size(obj);
ut64 cdsz = MACH0_(reloc_target_size)(obj);
ut64 size = MACH0_(reloc_targets_vfile_size)(obj);
if (!size) {
return;
@ -684,8 +688,9 @@ RZ_API void MACH0_(patch_relocs)(RzBinFile *bf, struct MACH0_(obj_t) * obj) {
}
if (needs_chained_patch) {
MACH0_(patch_chained_fixups)
(obj, obj->buf_patched);
// clang-format off
MACH0_(patch_chained_fixups)(obj, obj->buf_patched);
// clang-format on
}
// from now on, all writes should propagate through to the actual file

View file

@ -103,7 +103,7 @@ Type Info at 0x100008370:
type: __class_type_info
found_at: 4295000200
class_vtable: 4295000176
ref_to_type_class: -4608308318706860020
ref_to_type_class: 4295065704
ref_to_type_name: 4294999928
name: A
name_unique: true

View file

@ -139,15 +139,15 @@ vaddr paddr target type name
5 fd: 3 +0x0000c000 0x10000c000 - 0x10000ffff r-- fmap.__LINKEDIT
--
__auth_got (auth, bind)
0x100004000 0xc009000000000000
0x100004008 0xc009000000000005
0x100004010 0xc009000000000006
0x100004018 0xc009000000000007
0x100004020 0xc009000000000008
0x100004000 0x0000000100010008 reloc.target.NSLog
0x100004008 0x0000000100010010 reloc.target.objc_alloc_init
0x100004010 0x0000000100010018 reloc.target.objc_autoreleasePoolPop
0x100004018 0x0000000100010020 reloc.target.objc_autoreleasePoolPush
0x100004020 0x0000000100010028 reloc.target.objc_msgSend
--
cstring (!auth, !bind)
- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
0x100004028 0100 0000 e16a 15c0 c807 0000 0000 0000 .....j..........
0x100004028 3000 0100 0100 0000 c807 0000 0000 0000 0...............
0x100004038 643e 0000 0100 0000 d>......
--
local fcn ptr (auth, !bind)
@ -157,7 +157,7 @@ local fcn ptr (auth, !bind)
--
global (!auth, bind)
- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
0x100008108 0400 0000 0000 1040 .......@
0x100008108 4000 0100 0100 0000 @.......
EOF
RUN
@ -218,7 +218,7 @@ vaddr paddr target type name
0x100008140 0x00008140 0x00000000 SET_64
0x100008158 0x00008158 0x00000000 SET_64
0x100008160 0x00008160 0x00000000 SET_64
0500000000002080
3000010001000000
643e000001000000
0x100004038 0x0000000100003e64 d>...... 4294983268 3.__TEXT.__cstring str.static_method_called,section.3.__TEXT.__cstring R X 'invalid' static method called
address min max name super
@ -296,7 +296,7 @@ vaddr paddr target type name
0x100008140 0x00008140 0x00000000 SET_64
0x100008158 0x00008158 0x00000000 SET_64
0x100008160 0x00008160 0x00000000 SET_64
04000000000009c0
2800010001000000
083e000001000000
033f000001000000
address min max name super

View file

@ -99,11 +99,11 @@ vaddr paddr target type name
0x100008110 0x00008110 0x100010040 SET_64 _objc_empty_cache
0x100008120 0x00008120 0x00000000 SET_64
0x1000080c0 0x0000000100008100 ........ @ section.13.__DATA.__objc_classrefs 4295000320 15.__DATA.__objc_data class Stub R 0x1000080d8
0x1000080c8 0x8020000000000005 ...... . @ reloc.NSString
0x1000080c8 0x0000000100010030 0....... @ reloc.NSString 4295032880 NSString R 0x0
;-- section.13.__DATA.__objc_classrefs:
0x1000080c0 .qword 0x0000000100008100 ; sym.class_Stub; RELOC 64 ; [13] -rw- section size 16 named 13.__DATA.__objc_classrefs
;-- NSString:
0x1000080c8 .qword 0x8020000000000005 ; RELOC 64 NSString
0x1000080c8 .qword 0x0000000100010030 ; reloc.target.NSString; RELOC 64 NSString
address min max name super
--------------------------------------------------
0x1000080d8 0x1000080d8 0x1000080d8 Stub NSObject
@ -158,11 +158,11 @@ vaddr paddr target type name
0x100008110 0x00008110 0x100010040 SET_64 _objc_empty_cache
0x100008120 0x00008120 0x00000000 SET_64
0x1000080c0 0x0000000100008100 ........ @ section.13.__DATA.__objc_classrefs 4295000320 15.__DATA.__objc_data class Stub R 0x1000080d8
0x1000080c8 0x4010000000000000 .......@ @ reloc.NSString
0x1000080c8 0x0000000100010030 0....... @ reloc.NSString 4295032880 NSString R 0x0
;-- section.13.__DATA.__objc_classrefs:
0x1000080c0 .qword 0x0000000100008100 ; sym.class_Stub; RELOC 64 ; [13] -rw- section size 16 named 13.__DATA.__objc_classrefs
;-- NSString:
0x1000080c8 .qword 0x4010000000000000 ; RELOC 64 NSString
0x1000080c8 .qword 0x0000000100010030 ; reloc.target.NSString; RELOC 64 NSString
address min max name super
--------------------------------------------------
0x1000080d8 0x1000080d8 0x1000080d8 Stub NSObject
@ -217,11 +217,11 @@ vaddr paddr target type name
0x100008110 0x00008110 0x100010040 SET_64 _objc_empty_cache
0x100008120 0x00008120 0x00000000 SET_64
0x1000080c0 0x0000000100008100 ........ @ section.13.__DATA.__objc_classrefs 4295000320 15.__DATA.__objc_data class Stub R 0x1000080d8
0x1000080c8 0x4010000000000005 .......@ @ reloc.NSString
0x1000080c8 0x0000000100010030 0....... @ reloc.NSString 4295032880 NSString R 0x0
;-- section.13.__DATA.__objc_classrefs:
0x1000080c0 .qword 0x0000000100008100 ; sym.class_Stub; RELOC 64 ; [13] -rw- section size 16 named 13.__DATA.__objc_classrefs
;-- NSString:
0x1000080c8 .qword 0x4010000000000005 ; RELOC 64 NSString
0x1000080c8 .qword 0x0000000100010030 ; reloc.target.NSString; RELOC 64 NSString
address min max name super
--------------------------------------------------
0x1000080d8 0x1000080d8 0x1000080d8 Stub NSObject

View file

@ -345,8 +345,7 @@ ret
| 0x100003da0 adrp x1, section.13.__DATA.__objc_const ; 0x100008000
| 0x100003da4 ldr x1, [x1, 0xc8] ; [0x100003f3c:4]=0x6874656d ; "methodWithReturn"
| 0x100003da8 adrp x16, reloc.NSLog ; 0x100004000
| 0x100003dac ldr x16, [x16, 0x20] ; [0x100004020:4]=4
| ; reloc.objc_msgSend
| 0x100003dac ldr x16, [x16, 0x20] ; [0x100004020:4]=0x10028 ; u"(\x01\x01"
\ 0x100003db0 br x16
EOF
RUN