kit

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

elf.h (17206B)


      1 /* ELF wire-format constants, structs, and small helpers shared between
      2  * obj/elf_emit.c, obj/elf_read.c, and link/elf_exe.c.
      3  *
      4  * Private to src/. The public ObjBuilder/Linker surface is format-neutral
      5  * (obj/obj.h, link/link.h); the ELF spelling of those abstractions only
      6  * exists inside libkit.
      7  *
      8  * Scope: 64-bit little-endian only. The per-arch reloc mapping is split
      9  * across elf_reloc_<arch>.c (one TU per arch); emit_elf and the linker
     10  * dispatch to the right table by Compiler.target.arch. */
     11 
     12 #ifndef KIT_OBJ_ELF_H
     13 #define KIT_OBJ_ELF_H
     14 
     15 #include <kit/core.h>
     16 
     17 #include "core/core.h"
     18 #include "obj/obj.h"
     19 
     20 /* ---- e_ident indices and values ---- */
     21 #define EI_NIDENT 16
     22 #define EI_MAG0 0
     23 #define EI_MAG1 1
     24 #define EI_MAG2 2
     25 #define EI_MAG3 3
     26 #define EI_CLASS 4
     27 #define EI_DATA 5
     28 #define EI_VERSION 6
     29 #define EI_OSABI 7
     30 
     31 #define ELFMAG0 0x7f
     32 #define ELFMAG1 'E'
     33 #define ELFMAG2 'L'
     34 #define ELFMAG3 'F'
     35 #define ELFCLASS32 1
     36 #define ELFCLASS64 2
     37 #define ELFDATA2LSB 1
     38 #define EV_CURRENT 1
     39 #define ELFOSABI_NONE 0
     40 /* Bare-metal / freestanding (`*-none-elf`). kit stamps this so a freestanding
     41  * object round-trips as KIT_OS_FREESTANDING instead of decoding back to Linux
     42  * (EI_OSABI=SysV/0 is ambiguous and is otherwise read as a hosted Linux/PIE
     43  * default — the bug that forced rv32 links to be special-cased). */
     44 #define ELFOSABI_STANDALONE 0xFF
     45 #define ELFOSABI_GNU                           \
     46   3 /* a.k.a. ELFOSABI_LINUX — required when \
     47        the file uses STT_GNU_IFUNC / STB_GNU_UNIQUE. */
     48 #define ELFOSABI_LINUX ELFOSABI_GNU
     49 /* FreeBSD brand. The kernel matches EI_OSABI for hosted executables;
     50  * without it a static binary is rejected even when crt1.o carries the
     51  * FreeBSD ABI note. */
     52 #define ELFOSABI_FREEBSD 9
     53 
     54 /* ---- e_type ---- */
     55 #define ET_NONE 0
     56 #define ET_REL 1
     57 #define ET_EXEC 2
     58 #define ET_DYN 3
     59 
     60 /* ---- e_machine ---- */
     61 #define EM_X86_64 0x3E
     62 #define EM_AARCH64 0xB7
     63 #define EM_RISCV 0xF3
     64 
     65 /* ---- header sizes (also literal e_*size fields) ----
     66  * On-disk sizes of the ELF64 records the linker emits.  Wire-format
     67  * constants (per spec); never compute via sizeof on a host struct
     68  * since alignment / padding may diverge. */
     69 #define ELF64_EHDR_SIZE 64
     70 #define ELF64_SHDR_SIZE 64
     71 #define ELF64_PHDR_SIZE 56
     72 #define ELF64_SYM_SIZE 24u
     73 #define ELF64_RELA_SIZE 24u
     74 #define ELF64_DYN_SIZE 16u
     75 
     76 /* ELFCLASS32 (ELF32) on-disk record sizes. RV32 ET_REL/ET_EXEC use these
     77  * via the `is32` flag derived from EI_CLASS / Compiler.target.ptr_size==4.
     78  * Note: Elf32_Sym and Elf32_Phdr REORDER fields relative to their ELF64
     79  * counterparts (not just narrower) — see emit.c / read.c / link.c. */
     80 #define ELF32_EHDR_SIZE 52
     81 #define ELF32_SHDR_SIZE 40
     82 #define ELF32_PHDR_SIZE 32
     83 #define ELF32_SYM_SIZE 16u
     84 #define ELF32_RELA_SIZE 12u
     85 #define ELF32_DYN_SIZE 8u
     86 
     87 /* ---- special section indices ---- */
     88 #define SHN_UNDEF 0u
     89 #define SHN_ABS 0xfff1u
     90 #define SHN_COMMON 0xfff2u
     91 
     92 /* ---- sh_type ---- */
     93 #define SHT_NULL 0
     94 #define SHT_PROGBITS 1
     95 #define SHT_SYMTAB 2
     96 #define SHT_STRTAB 3
     97 #define SHT_RELA 4
     98 #define SHT_NOTE 7
     99 #define SHT_NOBITS 8
    100 #define SHT_REL 9
    101 #define SHT_INIT_ARRAY 14
    102 #define SHT_FINI_ARRAY 15
    103 #define SHT_PREINIT_ARRAY 16
    104 #define SHT_GROUP 17
    105 
    106 /* ---- sh_flags ---- */
    107 #define SHF_WRITE 0x1u
    108 #define SHF_ALLOC 0x2u
    109 #define SHF_EXECINSTR 0x4u
    110 #define SHF_MERGE 0x10u
    111 #define SHF_STRINGS 0x20u
    112 #define SHF_INFO_LINK 0x40u
    113 #define SHF_LINK_ORDER 0x80u
    114 #define SHF_GROUP 0x200u
    115 #define SHF_TLS 0x400u
    116 #define SHF_GNU_RETAIN 0x200000u
    117 
    118 /* ---- symbol bind / type / visibility ---- */
    119 #define STB_LOCAL 0
    120 #define STB_GLOBAL 1
    121 #define STB_WEAK 2
    122 /* GNU extension: a global symbol that the dynamic loader keeps unique across
    123  * the whole process (used for C++ inline statics, and by FreeBSD's crt for the
    124  * ABI-brand note symbol). For static-link resolution it behaves as a global
    125  * definition. */
    126 #define STB_GNU_UNIQUE 10
    127 
    128 #define STT_NOTYPE 0
    129 #define STT_OBJECT 1
    130 #define STT_FUNC 2
    131 #define STT_SECTION 3
    132 #define STT_FILE 4
    133 #define STT_COMMON 5
    134 #define STT_TLS 6
    135 #define STT_GNU_IFUNC 10
    136 
    137 #define STV_DEFAULT 0
    138 #define STV_INTERNAL 1
    139 #define STV_HIDDEN 2
    140 #define STV_PROTECTED 3
    141 
    142 #define ELF64_ST_INFO(b, t) ((u8)((((u32)(b)) << 4) | ((u32)(t) & 0xf)))
    143 #define ELF64_ST_BIND(i) ((u32)((i) >> 4))
    144 #define ELF64_ST_TYPE(i) ((u32)((i) & 0xf))
    145 #define ELF64_R_SYM(i) ((u32)((i) >> 32))
    146 #define ELF64_R_TYPE(i) ((u32)((i) & 0xffffffffu))
    147 #define ELF64_R_INFO(s, t) ((((u64)(s)) << 32) | ((u64)(t) & 0xffffffffull))
    148 
    149 /* ELF32 r_info packs the symbol index in the high 24 bits and an 8-bit
    150  * reloc type in the low byte. RV32 reloc type codes (<= 61) all fit. */
    151 #define ELF32_R_SYM(i) ((u32)((i) >> 8))
    152 #define ELF32_R_TYPE(i) ((u32)((i) & 0xffu))
    153 #define ELF32_R_INFO(s, t) ((u32)((((u32)(s)) << 8) | ((u32)(t) & 0xffu)))
    154 
    155 /* ---- kit SymKind/SymBind/SymVis -> ELF wire value, single source ----
    156  * One table per axis, indexed by the kit obj.h enum, wrapped in a
    157  * static-inline accessor so unused TUs that include elf.h don't trip
    158  * -Wunused-const-variable. SK_COMMON maps to STT_OBJECT here (the shape
    159  * clang/gcc/GNU-as emit: STT_OBJECT + shndx=SHN_COMMON); the linker's
    160  * symbol writer overrides COMMON to STT_NOTYPE at its call site. */
    161 static inline u8 elf_st_type(u8 kind /* SymKind */) {
    162   static const u8 kElfStType[] = {
    163       [SK_UNDEF] = STT_NOTYPE,  [SK_FUNC] = STT_FUNC,
    164       [SK_OBJ] = STT_OBJECT,    [SK_SECTION] = STT_SECTION,
    165       [SK_FILE] = STT_FILE,     [SK_COMMON] = STT_OBJECT,
    166       [SK_TLS] = STT_TLS,       [SK_ABS] = STT_NOTYPE,
    167       [SK_NOTYPE] = STT_NOTYPE, [SK_IFUNC] = STT_GNU_IFUNC,
    168   };
    169   if (kind >= (u8)(sizeof kElfStType / sizeof kElfStType[0])) return STT_NOTYPE;
    170   return kElfStType[kind];
    171 }
    172 
    173 static inline u8 elf_st_bind(u8 bind /* SymBind */) {
    174   static const u8 kElfStBind[] = {
    175       [SB_LOCAL] = STB_LOCAL,
    176       [SB_GLOBAL] = STB_GLOBAL,
    177       [SB_WEAK] = STB_WEAK,
    178   };
    179   if (bind >= (u8)(sizeof kElfStBind / sizeof kElfStBind[0])) return STB_LOCAL;
    180   return kElfStBind[bind];
    181 }
    182 
    183 static inline u8 elf_st_other(u8 vis /* SymVis */) {
    184   static const u8 kElfStOther[] = {
    185       [SV_DEFAULT] = STV_DEFAULT,
    186       [SV_HIDDEN] = STV_HIDDEN,
    187       [SV_PROTECTED] = STV_PROTECTED,
    188       [SV_INTERNAL] = STV_INTERNAL,
    189   };
    190   if (vis >= (u8)(sizeof kElfStOther / sizeof kElfStOther[0]))
    191     return STV_DEFAULT;
    192   return kElfStOther[vis];
    193 }
    194 
    195 /* ---- program header ---- */
    196 #define PT_NULL 0
    197 #define PT_LOAD 1
    198 #define PT_DYNAMIC 2
    199 #define PT_INTERP 3
    200 #define PT_NOTE 4
    201 #define PT_PHDR 6
    202 #define PT_TLS 7
    203 #define PT_GNU_EH_FRAME 0x6474e550
    204 #define PT_GNU_STACK 0x6474e551
    205 #define PT_GNU_RELRO 0x6474e552
    206 #define PF_X 0x1u
    207 #define PF_W 0x2u
    208 #define PF_R 0x4u
    209 
    210 /* ---- e_flags (RISC-V ABI bits, EM_RISCV) ---- */
    211 #define EF_RISCV_RVC 0x0001u
    212 #define EF_RISCV_FLOAT_ABI_SOFT 0x0000u
    213 #define EF_RISCV_FLOAT_ABI_SINGLE 0x0002u
    214 #define EF_RISCV_FLOAT_ABI_DOUBLE 0x0004u
    215 #define EF_RISCV_FLOAT_ABI_QUAD 0x0006u
    216 #define EF_RISCV_FLOAT_ABI_MASK 0x0006u
    217 #define EF_RISCV_RVE 0x0008u
    218 #define EF_RISCV_TSO 0x0010u
    219 
    220 /* ---- dynamic-table tags (PT_DYNAMIC body) ---- */
    221 #define DT_NULL 0
    222 #define DT_NEEDED 1
    223 #define DT_PLTRELSZ 2
    224 #define DT_PLTGOT 3
    225 #define DT_HASH 4
    226 #define DT_STRTAB 5
    227 #define DT_SYMTAB 6
    228 #define DT_RELA 7
    229 #define DT_RELASZ 8
    230 #define DT_RELAENT 9
    231 #define DT_STRSZ 10
    232 #define DT_SYMENT 11
    233 #define DT_INIT 12
    234 #define DT_FINI 13
    235 #define DT_SONAME 14
    236 #define DT_RPATH 15
    237 #define DT_SYMBOLIC 16
    238 #define DT_REL 17
    239 #define DT_RELSZ 18
    240 #define DT_RELENT 19
    241 #define DT_PLTREL 20
    242 #define DT_DEBUG 21
    243 #define DT_TEXTREL 22
    244 #define DT_JMPREL 23
    245 #define DT_BIND_NOW 24
    246 #define DT_INIT_ARRAY 25
    247 #define DT_FINI_ARRAY 26
    248 #define DT_INIT_ARRAYSZ 27
    249 #define DT_FINI_ARRAYSZ 28
    250 #define DT_RUNPATH 29
    251 #define DT_FLAGS 30
    252 #define DT_PREINIT_ARRAY 32
    253 #define DT_PREINIT_ARRAYSZ 33
    254 #define DT_GNU_HASH 0x6ffffef5
    255 #define DT_FLAGS_1 0x6ffffffb
    256 #define DF_1_NOW 0x00000001
    257 /* GNU symbol-versioning dynamic tags. */
    258 #define DT_VERSYM 0x6ffffff0   /* address of the .gnu.version table */
    259 #define DT_VERNEED 0x6ffffffe  /* address of the .gnu.version_r table */
    260 #define DT_VERNEEDNUM 0x6fffffff /* number of .gnu.version_r entries */
    261 
    262 /* ---- extra section types we need to recognize in DSO inputs ---- */
    263 #define SHT_DYNAMIC 6
    264 #define SHT_DYNSYM 11
    265 #define SHT_GNU_HASH 0x6ffffff6
    266 #define SHT_GNU_VERSYM 0x6fffffff
    267 #define SHT_GNU_VERNEED 0x6ffffffe
    268 #define SHT_GNU_VERDEF 0x6ffffffd
    269 
    270 /* ---- GNU symbol-versioning wire layout (ELFCLASS64) ----
    271  * .gnu.version (SHT_GNU_VERSYM): u16 per .dynsym entry. Special indices:
    272  *   0 = local (the null slot / unversioned undefined reference)
    273  *   1 = global, base version (a defined symbol with no explicit version)
    274  *   >=2 = index of a version requirement (Vernaux.vna_other) for an
    275  *         undefined reference, or a version definition for a defined symbol.
    276  * The 0x8000 bit (VERSYM_HIDDEN) marks a non-default version definition. */
    277 #define VER_NDX_LOCAL 0
    278 #define VER_NDX_GLOBAL 1
    279 #define VERSYM_HIDDEN 0x8000u
    280 #define VERSYM_VERSION 0x7fffu
    281 #define VER_FLG_BASE 0x1 /* Verdef: the file's base (soname) version entry */
    282 
    283 /* Elf64_Verdef (20 bytes) + Elf64_Verdaux (8 bytes) — version definitions in a
    284  * DSO's .gnu.version_d. Read-only on our side (we never emit a verdef). */
    285 #define ELF_VERDEF_SIZE 20
    286 #define ELF_VERDAUX_SIZE 8
    287 /* Elf64_Verneed (16 bytes) + Elf64_Vernaux (16 bytes) — version requirements
    288  * in .gnu.version_r, which we both read (DSO inputs) and emit (executables). */
    289 #define ELF_VERNEED_SIZE 16
    290 #define ELF_VERNAUX_SIZE 16
    291 
    292 /* ---- AArch64 ELF wire-format relocation type codes ----
    293  * Prefixed ELF_ to avoid collision with the kit-canonical RelocKind
    294  * enum values in obj.h (R_AARCH64_*). */
    295 #define ELF_R_AARCH64_NONE 0
    296 #define ELF_R_AARCH64_ABS64 257
    297 #define ELF_R_AARCH64_ABS32 258
    298 #define ELF_R_AARCH64_ABS16 259
    299 #define ELF_R_AARCH64_PREL64 260
    300 #define ELF_R_AARCH64_PREL32 261
    301 #define ELF_R_AARCH64_PREL16 262
    302 #define ELF_R_AARCH64_LD_PREL_LO19 273
    303 #define ELF_R_AARCH64_ADR_PREL_LO21 274
    304 #define ELF_R_AARCH64_ADR_PREL_PG_HI21 275
    305 #define ELF_R_AARCH64_ADR_PREL_PG_HI21_NC 276
    306 #define ELF_R_AARCH64_ADD_ABS_LO12_NC 277
    307 #define ELF_R_AARCH64_LDST8_ABS_LO12_NC 278
    308 #define ELF_R_AARCH64_TSTBR14 279
    309 #define ELF_R_AARCH64_CONDBR19 280
    310 #define ELF_R_AARCH64_JUMP26 282
    311 #define ELF_R_AARCH64_CALL26 283
    312 #define ELF_R_AARCH64_LDST16_ABS_LO12_NC 284
    313 #define ELF_R_AARCH64_LDST32_ABS_LO12_NC 285
    314 #define ELF_R_AARCH64_LDST64_ABS_LO12_NC 286
    315 #define ELF_R_AARCH64_LDST128_ABS_LO12_NC 299
    316 #define ELF_R_AARCH64_ADR_GOT_PAGE 311
    317 #define ELF_R_AARCH64_LD64_GOT_LO12_NC 312
    318 /* TLS Initial-Exec: ADRP/LDR of a GOT slot holding the symbol's tpoff. */
    319 #define ELF_R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 541
    320 #define ELF_R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC 542
    321 
    322 /* AArch64 dynamic-only reloc types: generated by the linker into
    323  * .rela.dyn / .rela.plt and processed by the runtime loader. */
    324 #define ELF_R_AARCH64_COPY 1024
    325 #define ELF_R_AARCH64_GLOB_DAT 1025
    326 #define ELF_R_AARCH64_JUMP_SLOT 1026
    327 #define ELF_R_AARCH64_RELATIVE 1027
    328 #define ELF_R_AARCH64_IRELATIVE 1032
    329 
    330 /* AArch64 TLS Local-Exec (static linking model: each TLV is at a fixed
    331  * offset from the thread pointer, computed at link time). */
    332 #define ELF_R_AARCH64_TLSLE_ADD_TPREL_HI12 549
    333 #define ELF_R_AARCH64_TLSLE_ADD_TPREL_LO12 550
    334 #define ELF_R_AARCH64_TLSLE_ADD_TPREL_LO12_NC 551
    335 #define ELF_R_AARCH64_TLSLE_LDST8_TPREL_LO12 552
    336 #define ELF_R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC 553
    337 #define ELF_R_AARCH64_TLSLE_LDST16_TPREL_LO12 554
    338 #define ELF_R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC 555
    339 #define ELF_R_AARCH64_TLSLE_LDST32_TPREL_LO12 556
    340 #define ELF_R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC 557
    341 #define ELF_R_AARCH64_TLSLE_LDST64_TPREL_LO12 558
    342 #define ELF_R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC 559
    343 
    344 /* Map kit-canonical RelocKind <-> AArch64 ELF reloc type. Returns
    345  * R_AARCH64_NONE (0) on unsupported kinds; emit_elf treats that as a
    346  * fatal error.
    347  *
    348  * Note: R_REL32/R_REL64 collapse to R_AARCH64_PREL32/64 on AArch64.
    349  * kit's distinction between "section-relative" and "PC-relative" is
    350  * not currently exercised on AArch64 (the linker resolves to absolute
    351  * vaddrs); document any divergence in the per-arch tables when other
    352  * archs land. */
    353 u32 elf_aarch64_reloc_to(u32 kind /* RelocKind */);
    354 u32 elf_aarch64_reloc_from(u32 elf_type);
    355 /* Diagnostic spelling of an AArch64 ELF reloc wire type; NULL on unknown
    356  * (caller falls back to the format-neutral reloc_kind_name). */
    357 const char* elf_aarch64_reloc_name(u32 elf_type);
    358 
    359 /* ---- x86_64 ELF reloc types ----
    360  *
    361  * Subset matching the kit-canonical RelocKind R_X64_* entries. The
    362  * full SysV-x86_64 ABI table has more entries (TLS, GOT variants, ...)
    363  * — only the ones the codegen and linker actually need today are
    364  * represented here. */
    365 #define ELF_R_X86_64_NONE 0
    366 #define ELF_R_X86_64_64 1
    367 #define ELF_R_X86_64_PC32 2
    368 #define ELF_R_X86_64_GOT32 3
    369 #define ELF_R_X86_64_PLT32 4
    370 #define ELF_R_X86_64_COPY 5
    371 #define ELF_R_X86_64_GLOB_DAT 6
    372 #define ELF_R_X86_64_JUMP_SLOT 7
    373 #define ELF_R_X86_64_RELATIVE 8
    374 #define ELF_R_X86_64_IRELATIVE 37
    375 #define ELF_R_X86_64_GOTPCREL 9
    376 #define ELF_R_X86_64_32 10
    377 #define ELF_R_X86_64_32S 11
    378 #define ELF_R_X86_64_16 12
    379 #define ELF_R_X86_64_PC16 13
    380 #define ELF_R_X86_64_8 14
    381 #define ELF_R_X86_64_PC8 15
    382 #define ELF_R_X86_64_DTPMOD64 16
    383 #define ELF_R_X86_64_DTPOFF64 17
    384 #define ELF_R_X86_64_TPOFF64 18
    385 #define ELF_R_X86_64_TLSGD 19
    386 #define ELF_R_X86_64_TLSLD 20
    387 #define ELF_R_X86_64_DTPOFF32 21
    388 #define ELF_R_X86_64_GOTTPOFF 22
    389 #define ELF_R_X86_64_TPOFF32 23
    390 #define ELF_R_X86_64_PC64 24
    391 #define ELF_R_X86_64_GOTOFF64 25
    392 #define ELF_R_X86_64_GOTPC32 26
    393 #define ELF_R_X86_64_GOTPCRELX 41
    394 #define ELF_R_X86_64_REX_GOTPCRELX 42
    395 
    396 u32 elf_x86_64_reloc_to(u32 kind /* RelocKind */);
    397 u32 elf_x86_64_reloc_from(u32 elf_type);
    398 /* Diagnostic spelling of an x86_64 ELF reloc wire type; NULL on unknown. */
    399 const char* elf_x86_64_reloc_name(u32 elf_type);
    400 
    401 /* ---- RISC-V relocation types ----
    402  *
    403  * Subset matching the kit-canonical RelocKind R_RV_* entries. The
    404  * full RISC-V ELF psABI has many more (TLS, GOT variants, compressed
    405  * forms, ...) — only the ones the codegen and linker actually need
    406  * today are represented here. */
    407 #define ELF_R_RISCV_NONE 0
    408 #define ELF_R_RISCV_32 1
    409 #define ELF_R_RISCV_64 2
    410 #define ELF_R_RISCV_RELATIVE 3
    411 #define ELF_R_RISCV_COPY 4
    412 #define ELF_R_RISCV_JUMP_SLOT 5
    413 #define ELF_R_RISCV_IRELATIVE 58
    414 #define ELF_R_RISCV_BRANCH 16
    415 #define ELF_R_RISCV_JAL 17
    416 #define ELF_R_RISCV_CALL 18
    417 #define ELF_R_RISCV_CALL_PLT 19
    418 #define ELF_R_RISCV_GOT_HI20 20
    419 #define ELF_R_RISCV_TLS_GOT_HI20 21
    420 #define ELF_R_RISCV_TLS_GD_HI20 22
    421 #define ELF_R_RISCV_PCREL_HI20 23
    422 #define ELF_R_RISCV_PCREL_LO12_I 24
    423 #define ELF_R_RISCV_PCREL_LO12_S 25
    424 #define ELF_R_RISCV_HI20 26
    425 #define ELF_R_RISCV_LO12_I 27
    426 #define ELF_R_RISCV_LO12_S 28
    427 #define ELF_R_RISCV_TPREL_HI20 29
    428 #define ELF_R_RISCV_TPREL_LO12_I 30
    429 #define ELF_R_RISCV_TPREL_LO12_S 31
    430 #define ELF_R_RISCV_TPREL_ADD 32
    431 #define ELF_R_RISCV_ADD8 33
    432 #define ELF_R_RISCV_ADD16 34
    433 #define ELF_R_RISCV_ADD32 35
    434 #define ELF_R_RISCV_ADD64 36
    435 #define ELF_R_RISCV_SUB8 37
    436 #define ELF_R_RISCV_SUB16 38
    437 #define ELF_R_RISCV_SUB32 39
    438 #define ELF_R_RISCV_SUB64 40
    439 #define ELF_R_RISCV_ALIGN 43
    440 #define ELF_R_RISCV_RVC_BRANCH 44
    441 #define ELF_R_RISCV_RVC_JUMP 45
    442 #define ELF_R_RISCV_RELAX 51
    443 #define ELF_R_RISCV_SUB6 52
    444 #define ELF_R_RISCV_SET6 53
    445 #define ELF_R_RISCV_SET8 54
    446 #define ELF_R_RISCV_SET16 55
    447 #define ELF_R_RISCV_SET32 56
    448 #define ELF_R_RISCV_32_PCREL 57
    449 #define ELF_R_RISCV_SET_ULEB128 60
    450 #define ELF_R_RISCV_SUB_ULEB128 61
    451 
    452 u32 elf_riscv64_reloc_to(u32 kind /* RelocKind */);
    453 u32 elf_riscv64_reloc_from(u32 elf_type);
    454 
    455 /* RV32 (ELFCLASS32) reloc table. Same XLEN-neutral kinds as riscv64; the
    456  * 64-bit-only kinds (R_ABS64 / R_RV_ADD64 / R_RV_SUB64) are unsupported. */
    457 u32 elf_riscv32_reloc_to(u32 kind /* RelocKind */);
    458 u32 elf_riscv32_reloc_from(u32 elf_type);
    459 /* Diagnostic spelling of a RISC-V ELF reloc wire type, and float-ABI
    460  * decode from RISC-V e_flags. Both XLEN-neutral — shared by the rv64 and
    461  * rv32 arch-ops descriptors. */
    462 const char* elf_riscv_reloc_name(u32 elf_type);
    463 KitFloatAbi elf_riscv_float_abi_from_e_flags(u32 e_flags);
    464 
    465 /* ---- little-endian byte writers (Writer-based) ----
    466  * Writes go through the shared writer_u*_le helpers (core/bytes.h); the
    467  * elf_wr_* aliases keep the ELF spelling at existing call sites. Reads
    468  * use rd_u*_le from core/bytes.h directly. */
    469 
    470 #include "core/bytes.h"
    471 
    472 #define elf_wr_u8 writer_u8_le
    473 #define elf_wr_u16 writer_u16_le
    474 #define elf_wr_u32 writer_u32_le
    475 #define elf_wr_u64 writer_u64_le
    476 
    477 /* Native-width address/offset/size field: 4 bytes on ELFCLASS32, 8 on
    478  * ELFCLASS64. Used wherever the Ehdr/Shdr/Sym widths shrink under is32. */
    479 static inline void elf_wr_addr(Writer* w, int is32, u64 v) {
    480   if (is32)
    481     elf_wr_u32(w, (u32)v);
    482   else
    483     elf_wr_u64(w, v);
    484 }
    485 
    486 static inline u64 elf_rd_addr(const u8* p, int is32) {
    487   return is32 ? (u64)rd_u32_le(p) : rd_u64_le(p);
    488 }
    489 
    490 /* EI_CLASS-aware arch-ops lookup. obj_elf_machine() keys on e_machine
    491  * alone, which cannot tell RV32 (EM_RISCV+ELFCLASS32) from RV64
    492  * (EM_RISCV+ELFCLASS64); this variant disambiguates via ei_class. */
    493 const struct ObjElfArchOps* obj_elf_machine_class(u32 e_machine, u8 ei_class);
    494 
    495 #endif /* KIT_OBJ_ELF_H */