kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

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 }