From ebe4263323cf71abeeb0851f66ed063575344a4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=A4rkl?= Date: Sat, 24 Jun 2023 16:08:23 +0200 Subject: [PATCH] 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. --- librz/bin/format/mach0/mach0.h | 6 +- librz/bin/format/mach0/mach0_chained_fixups.c | 12 +++- librz/bin/format/mach0/mach0_relocs.c | 57 ++++++++++--------- test/db/analysis/classes | 2 +- test/db/formats/mach0/arm64e | 18 +++--- test/db/formats/mach0/imports | 12 ++-- test/db/formats/mach0/objc | 3 +- 7 files changed, 62 insertions(+), 48 deletions(-) diff --git a/librz/bin/format/mach0/mach0.h b/librz/bin/format/mach0/mach0.h index 6e5f7e7521..38d621963d 100644 --- a/librz/bin/format/mach0/mach0.h +++ b/librz/bin/format/mach0/mach0.h @@ -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); diff --git a/librz/bin/format/mach0/mach0_chained_fixups.c b/librz/bin/format/mach0/mach0_chained_fixups.c index f56c3f45e2..8d29974d81 100644 --- a/librz/bin/format/mach0/mach0_chained_fixups.c +++ b/librz/bin/format/mach0/mach0_chained_fixups.c @@ -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 } diff --git a/librz/bin/format/mach0/mach0_relocs.c b/librz/bin/format/mach0/mach0_relocs.c index 15f94902b9..5e78c38b00 100644 --- a/librz/bin/format/mach0/mach0_relocs.c +++ b/librz/bin/format/mach0/mach0_relocs.c @@ -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 diff --git a/test/db/analysis/classes b/test/db/analysis/classes index 5e0fd609b8..400831b294 100644 --- a/test/db/analysis/classes +++ b/test/db/analysis/classes @@ -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 diff --git a/test/db/formats/mach0/arm64e b/test/db/formats/mach0/arm64e index 58cda4aa77..aa14b0d20a 100644 --- a/test/db/formats/mach0/arm64e +++ b/test/db/formats/mach0/arm64e @@ -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 diff --git a/test/db/formats/mach0/imports b/test/db/formats/mach0/imports index 9c664d510e..532c36176b 100644 --- a/test/db/formats/mach0/imports +++ b/test/db/formats/mach0/imports @@ -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 diff --git a/test/db/formats/mach0/objc b/test/db/formats/mach0/objc index af85f5bd3f..ba45ccaf48 100644 --- a/test/db/formats/mach0/objc +++ b/test/db/formats/mach0/objc @@ -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