reloc_aarch64.c (3681B)
1 /* RelocKind <-> arm64 Mach-O reloc-type mapping. Mirror of 2 * elf_reloc_aarch64.c for Mach-O. 3 * 4 * Mach-O relocations carry three independent fields that the kit 5 * RelocKind enum collapses into a single value: r_type (the 4-bit 6 * ARM64_RELOC_* code), r_pcrel, and r_length. The translator therefore 7 * exposes three accessors — the writer (macho_emit.c) consults all of 8 * them per Reloc, and the reader (macho_read.c) inverts via 9 * macho_aarch64_reloc_from which keys on (r_type, r_pcrel, r_length). */ 10 11 #include "core/util.h" 12 #include "obj/macho/macho.h" 13 14 u32 macho_aarch64_reloc_to(u32 kind /* RelocKind */) { 15 switch (kind) { 16 case R_NONE: 17 return (u32)-1; 18 case R_ABS64: 19 case R_ABS32: 20 return ARM64_RELOC_UNSIGNED; 21 case R_REL64: 22 case R_REL32: 23 case R_PC64: 24 case R_PC32: 25 /* PC-relative absolute pointer-difference; encoded as 26 * UNSIGNED with r_pcrel=1, length=3/2. */ 27 return ARM64_RELOC_UNSIGNED; 28 case R_AARCH64_JUMP26: 29 case R_AARCH64_CALL26: 30 return ARM64_RELOC_BRANCH26; 31 case R_AARCH64_ADR_PREL_PG_HI21: 32 case R_AARCH64_ADR_PREL_PG_HI21_NC: 33 return ARM64_RELOC_PAGE21; 34 case R_AARCH64_ADD_ABS_LO12_NC: 35 case R_AARCH64_LDST8_ABS_LO12_NC: 36 case R_AARCH64_LDST16_ABS_LO12_NC: 37 case R_AARCH64_LDST32_ABS_LO12_NC: 38 case R_AARCH64_LDST64_ABS_LO12_NC: 39 case R_AARCH64_LDST128_ABS_LO12_NC: 40 return ARM64_RELOC_PAGEOFF12; 41 case R_AARCH64_ADR_GOT_PAGE: 42 return ARM64_RELOC_GOT_LOAD_PAGE21; 43 case R_AARCH64_LD64_GOT_LO12_NC: 44 return ARM64_RELOC_GOT_LOAD_PAGEOFF12; 45 case R_AARCH64_TLVP_LOAD_PAGE21: 46 return ARM64_RELOC_TLVP_LOAD_PAGE21; 47 case R_AARCH64_TLVP_LOAD_PAGEOFF12: 48 return ARM64_RELOC_TLVP_LOAD_PAGEOFF12; 49 default: 50 return (u32)-1; 51 } 52 } 53 54 u32 macho_aarch64_reloc_pcrel(u32 kind /* RelocKind */) { 55 switch (kind) { 56 case R_REL64: 57 case R_REL32: 58 case R_PC64: 59 case R_PC32: 60 case R_AARCH64_JUMP26: 61 case R_AARCH64_CALL26: 62 case R_AARCH64_ADR_PREL_PG_HI21: 63 case R_AARCH64_ADR_PREL_PG_HI21_NC: 64 case R_AARCH64_ADR_GOT_PAGE: 65 case R_AARCH64_TLVP_LOAD_PAGE21: 66 return 1; 67 default: 68 return 0; 69 } 70 } 71 72 u32 macho_aarch64_reloc_length(u32 kind /* RelocKind */) { 73 /* log2 of the patch width in bytes: 0=byte, 1=hword, 2=word, 3=quad. 74 * AArch64 instructions are 4 bytes and Mach-O encodes any 32-bit fixup 75 * (BRANCH26, PAGE21, PAGEOFF12, ...) with length=2. */ 76 switch (kind) { 77 case R_ABS64: 78 case R_REL64: 79 case R_PC64: 80 return 3; 81 default: 82 return 2; 83 } 84 } 85 86 u32 macho_aarch64_reloc_from(u32 macho_type) { 87 /* The (r_type, r_pcrel, r_length) tuple disambiguates several kinds 88 * collapsed by macho_aarch64_reloc_to. The reader inspects pcrel and 89 * length itself when it matters; this function only maps the type 90 * field, returning the most common AArch64 instance for each. Reader 91 * callers refine via the pcrel/length companion if they need to 92 * distinguish R_ABS64 vs R_PC64 (both UNSIGNED). */ 93 switch (macho_type) { 94 case ARM64_RELOC_UNSIGNED: 95 return R_ABS64; 96 case ARM64_RELOC_BRANCH26: 97 return R_AARCH64_CALL26; 98 case ARM64_RELOC_PAGE21: 99 return R_AARCH64_ADR_PREL_PG_HI21; 100 case ARM64_RELOC_PAGEOFF12: 101 return R_AARCH64_ADD_ABS_LO12_NC; 102 case ARM64_RELOC_GOT_LOAD_PAGE21: 103 return R_AARCH64_ADR_GOT_PAGE; 104 case ARM64_RELOC_GOT_LOAD_PAGEOFF12: 105 return R_AARCH64_LD64_GOT_LO12_NC; 106 case ARM64_RELOC_TLVP_LOAD_PAGE21: 107 return R_AARCH64_TLVP_LOAD_PAGE21; 108 case ARM64_RELOC_TLVP_LOAD_PAGEOFF12: 109 return R_AARCH64_TLVP_LOAD_PAGEOFF12; 110 default: 111 return (u32)-1; 112 } 113 }