kit

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

commit 1541d1cfc7b9638a91946f78a7d4ccae1630b644
parent 47cede9aca1511ee8a697c37bbf98aab26bb4ee3
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Mon,  8 Jun 2026 11:42:52 -0700

reloc: shrink reloc enum; neutral R_ABS8/16, R_PREL16, R_TPOFF64; rename R_RV_ADD*/SUB*/SET* to arch-neutral

Diffstat:
Minclude/kit/object.h | 2+-
Msrc/arch/aa64/link.c | 3---
Msrc/arch/aa64/reloc.c | 9++++-----
Msrc/arch/riscv/link.c | 5-----
Msrc/arch/riscv/reloc.c | 27++++++++++++---------------
Msrc/arch/x64/link.c | 3+--
Msrc/arch/x64/reloc.c | 1-
Msrc/cg/data.c | 16++++++++--------
Msrc/link/link_arch.h | 11++++-------
Msrc/link/link_jit.c | 2+-
Msrc/link/link_reloc_layout.c | 9+++++----
Msrc/obj/elf/link.c | 15+++++++++------
Msrc/obj/elf/reloc_aarch64.c | 8++++----
Msrc/obj/elf/reloc_riscv32.c | 52+++++++++++++++++++++++++---------------------------
Msrc/obj/elf/reloc_riscv64.c | 60+++++++++++++++++++++++++++++-------------------------------
Msrc/obj/elf/reloc_x86_64.c | 4++--
Msrc/obj/macho/emit.c | 20++++++++++----------
Msrc/obj/macho/read.c | 16++++++++--------
Msrc/obj/obj.c | 35++++++++++++++++-------------------
Msrc/obj/obj.h | 47++++++++++++++++++++++++-----------------------
Msrc/obj/reloc.c | 2++
Msrc/obj/reloc_apply.c | 43++++++++++++++++++-------------------------
Mtest/link/reloc_apply_test.c | 10+++++-----
Mtest/link/reloc_desc_test.c | 36+++++++++++++++++-------------------
Mtest/link/reloc_uleb128_unit.c | 6+++---
25 files changed, 208 insertions(+), 234 deletions(-)

diff --git a/include/kit/object.h b/include/kit/object.h @@ -72,7 +72,7 @@ typedef enum KitRelocCode { KIT_RELOC_PC64 = 6, KIT_RELOC_GOT32 = 7, KIT_RELOC_PLT32 = 8, - KIT_RELOC_X64_PLT32 = 51, + KIT_RELOC_X64_PLT32 = 53, } KitRelocCode; typedef struct KitObjSecInfo { diff --git a/src/arch/aa64/link.c b/src/arch/aa64/link.c @@ -205,9 +205,6 @@ const LinkArchDesc link_arch_aa64 = { .reloc_desc = aa64_reloc_desc, .reloc_apply_insn = aa64_reloc_apply_insn, - /* AAPCS64 variant I: GOT TLS-IE slots hold (X - tls_vaddr) + TCB. */ - .tpoff64_reloc = R_AARCH64_TPOFF64, - .coff_chkstk_bytes = aa64_coff_chkstk, .coff_chkstk_len = sizeof aa64_coff_chkstk, }; diff --git a/src/arch/aa64/reloc.c b/src/arch/aa64/reloc.c @@ -7,17 +7,16 @@ * shared byte-patcher (src/obj/reloc_apply.c) until WS-C moves them here. * * Kinds with no row (the dynamic-only GLOB_DAT/JUMP_SLOT/RELATIVE/COPY, the - * MCEmitter-only INTRA_LABEL_ADDR, the internal slot-fill TPOFF64, and the - * unused TLSLE LDST variants) are never applied through the static reloc - * record path and intentionally carry no descriptor. */ + * MCEmitter-only INTRA_LABEL_ADDR, and the unused TLSLE LDST variants) are + * never applied through the static reloc record path and intentionally carry + * no descriptor. R_ABS16 and R_PREL16 are now neutral and live in the + * neutral_rows table; R_TPOFF64 is neutral and also lives there. */ #include "obj/reloc.h" #include "core/bytes.h" static const RelocDescRow aa64_rows[] = { - {R_AARCH64_ABS16, {2, 0}}, - {R_AARCH64_PREL16, {2, 0}}, {R_AARCH64_JUMP26, {4, RELOC_IS_BRANCH}}, {R_AARCH64_CALL26, {4, RELOC_IS_BRANCH}}, {R_AARCH64_CONDBR19, {4, 0}}, diff --git a/src/arch/riscv/link.c b/src/arch/riscv/link.c @@ -126,9 +126,6 @@ const LinkArchDesc link_arch_rv64 = { .emit_iplt_stub = rv64_emit_iplt_stub, .reloc_desc = rv_reloc_desc, .reloc_apply_insn = rv_reloc_apply_insn, - /* RISC-V variant I shares the internal raw-64-bit variant-I tpoff with - * AArch64 ((X - tls_vaddr) + TCB); there is no R_RV_TPOFF64. */ - .tpoff64_reloc = R_AARCH64_TPOFF64, }; /* RV32 link descriptor: identical to rv64 (PLT0/entry/stub byte sizes, @@ -146,6 +143,4 @@ const LinkArchDesc link_arch_rv32 = { .emit_iplt_stub = rv32_emit_iplt_stub, .reloc_desc = rv_reloc_desc, .reloc_apply_insn = rv_reloc_apply_insn, - /* See rv64: shares R_AARCH64_TPOFF64 (variant-I internal tpoff). */ - .tpoff64_reloc = R_AARCH64_TPOFF64, }; diff --git a/src/arch/riscv/reloc.c b/src/arch/riscv/reloc.c @@ -41,21 +41,18 @@ static const RelocDescRow rv_rows[] = { {R_RV_RVC_JUMP, {2, 0}}, {R_RV_RELAX, {4, RELOC_MARKER}}, {R_RV_TPREL_ADD, {4, RELOC_MARKER}}, - {R_RV_ADD8, {1, 0}}, - {R_RV_SUB8, {1, 0}}, - {R_RV_SUB6, {1, 0}}, - {R_RV_SET6, {1, 0}}, - {R_RV_SET8, {1, 0}}, - {R_RV_ADD16, {2, 0}}, - {R_RV_SUB16, {2, 0}}, - {R_RV_SET16, {2, 0}}, - {R_RV_ADD32, {4, 0}}, - {R_RV_SUB32, {4, 0}}, - {R_RV_SET32, {4, 0}}, - {R_RV_ADD64, {8, 0}}, - {R_RV_SUB64, {8, 0}}, - {R_RV_SET_ULEB128, {1, RELOC_WIDTH_DYN}}, - {R_RV_SUB_ULEB128, {1, RELOC_WIDTH_DYN}}, + {R_ADD8, {1, 0}}, + {R_SUB8, {1, 0}}, + {R_SUB6, {1, 0}}, + {R_SET6, {1, 0}}, + {R_ADD16, {2, 0}}, + {R_SUB16, {2, 0}}, + {R_ADD32, {4, 0}}, + {R_SUB32, {4, 0}}, + {R_ADD64, {8, 0}}, + {R_SUB64, {8, 0}}, + {R_SET_ULEB128, {1, RELOC_WIDTH_DYN}}, + {R_SUB_ULEB128, {1, RELOC_WIDTH_DYN}}, }; const RelocDesc* rv_reloc_desc(RelocKind k) { diff --git a/src/arch/x64/link.c b/src/arch/x64/link.c @@ -89,6 +89,5 @@ const LinkArchDesc link_arch_x64 = { .reloc_desc = x64_reloc_desc, .reloc_apply_insn = x64_reloc_apply_insn, - /* x86_64 variant II: GOT TLS-IE slots hold (X - tls_memsz). */ - .tpoff64_reloc = R_X64_TPOFF64, + .tls_variant_ii = 1, }; diff --git a/src/arch/x64/reloc.c b/src/arch/x64/reloc.c @@ -28,7 +28,6 @@ static const RelocDescRow x64_rows[] = { {R_X64_GOTPC32, {4, 0}}, {R_X64_GOTTPOFF, {4, RELOC_IS_TLS_GOT}}, {R_X64_TPOFF32, {4, 0}}, - {R_X64_TPOFF64, {8, 0}}, {R_X64_GLOB_DAT, {8, 0}}, {R_X64_JUMP_SLOT, {8, 0}}, {R_X64_RELATIVE, {8, 0}}, diff --git a/src/cg/data.c b/src/cg/data.c @@ -677,20 +677,20 @@ void kit_cg_data_symdiff(KitCg* g, KitCgSym lhs, KitCgSym rhs, int64_t addend, } switch (width) { case 1: - add_kind = R_RV_ADD8; - sub_kind = R_RV_SUB8; + add_kind = R_ADD8; + sub_kind = R_SUB8; break; case 2: - add_kind = R_RV_ADD16; - sub_kind = R_RV_SUB16; + add_kind = R_ADD16; + sub_kind = R_SUB16; break; case 4: - add_kind = R_RV_ADD32; - sub_kind = R_RV_SUB32; + add_kind = R_ADD32; + sub_kind = R_SUB32; break; case 8: - add_kind = R_RV_ADD64; - sub_kind = R_RV_SUB64; + add_kind = R_ADD64; + sub_kind = R_SUB64; break; default: return; diff --git a/src/link/link_arch.h b/src/link/link_arch.h @@ -98,13 +98,10 @@ typedef struct LinkArchDesc { int (*reloc_apply_insn)(Compiler* c, RelocKind k, u8* P_bytes, u64 S, i64 A, u64 P); - /* ---- TLS Initial-Exec GOT slot fill ---- - * The internal raw-64-bit local-exec tpoff written into a TLS GOT slot - * (link_emit_internal_tpoff64): x86_64 uses R_X64_TPOFF64 (variant II, - * X - tls_memsz); AArch64 and RISC-V share R_AARCH64_TPOFF64 (variant I, - * (X - tls_vaddr) + TCB). Per-arch so the GOT pass picks the right - * tpoff coordinate system without branching on target.arch. */ - RelocKind tpoff64_reloc; + /* TLS variant: 1 = variant II (x86-64, tpoff = X - tls_memsz_rounded); + * 0 = variant I (AArch64/RISC-V, tpoff = (X - tls_vaddr) + tcb_bias). + * Consulted by the ELF linker when applying R_TPOFF64. */ + u8 tls_variant_ii; /* ---- Optional COFF __chkstk stub ---- * Arches that cannot emit inline stack probes (aarch64) carry the bytes of a diff --git a/src/link/link_jit.c b/src/link/link_jit.c @@ -136,7 +136,7 @@ static i64 jit_rv_pcrel_lo12_disp(LinkImage* img, KitExecMemRegion* segs, * the static TLS image, so a symbol at image offset X is addressed as * X - tls_memsz. */ static int reloc_is_x64_tlsle(RelocKind k) { - return k == R_X64_TPOFF32 || k == R_X64_TPOFF64; + return k == R_X64_TPOFF32 || k == R_TPOFF64; } static int perms_for(u32 secflags) { diff --git a/src/link/link_reloc_layout.c b/src/link/link_reloc_layout.c @@ -523,13 +523,14 @@ void link_layout_jit_stubs(Linker* l, LinkImage* img, u32 map_size, /* Fill a TLS Initial-Exec GOT slot with the target's TP-relative offset. * Emitted as an internal raw-64-bit tpoff reloc so apply_all_relocs computes * the offset in the same coordinate system it uses for ordinary local-exec - * sites: x86_64 variant II (X - tls_memsz) via R_X64_TPOFF64, AArch64/RISC-V - * variant I ((X - tls_vaddr) + TCB) via R_AARCH64_TPOFF64. The slot is then + * sites via the neutral R_TPOFF64: x86_64 stores variant II (X - tls_memsz), + * AArch64/RISC-V store variant I ((X - tls_vaddr) + TCB). The slot is then * loaded by the GOTTPOFF / GOTTPREL site. */ static void link_emit_internal_tpoff64(LinkImage* img, Linker* l, LinkSectionId lsid, u32 offset, u64 write_vaddr, LinkSymId target) { LinkRelocApply rrec; + (void)l; memset(&rrec, 0, sizeof(rrec)); rrec.input_id = LINK_INPUT_NONE; rrec.section_id = OBJ_SEC_NONE; @@ -538,7 +539,7 @@ static void link_emit_internal_tpoff64(LinkImage* img, Linker* l, rrec.width = 8; rrec.write_vaddr = write_vaddr; rrec.write_file_offset = write_vaddr; - rrec.kind = link_arch_desc_for(l->c)->tpoff64_reloc; + rrec.kind = R_TPOFF64; rrec.target = target; rrec.addend = 0; *link_append_reloc_slot(img) = rrec; @@ -955,7 +956,7 @@ void link_emit_relocations(Linker* l, LinkImage* img, const LinkSymId* got_map, * Guard the offset against the section end here — where the size is * known — so the apply-time scan starts in-bounds even for a malformed * external object. */ - if ((rec.kind == R_RV_SET_ULEB128 || rec.kind == R_RV_SUB_ULEB128) && + if ((rec.kind == R_SET_ULEB128 || rec.kind == R_SUB_ULEB128) && rec.offset >= ls->size) compiler_panic(l->c, SRCLOC_NONE, "link: ULEB128 reloc offset past section end"); diff --git a/src/obj/elf/link.c b/src/obj/elf/link.c @@ -347,9 +347,10 @@ static void shift_image_addresses(LinkImage* img, u64 delta) { * the TPREL offset for both arches is (target - tls_vaddr) + 16. */ #define TLS_TCB_SIZE 16ull -static int reloc_is_tlsle(RelocKind k) { +static int reloc_is_tlsle(RelocKind k, int tls_variant_ii) { + if (k == R_TPOFF64 && !tls_variant_ii) return 1; return k == R_AARCH64_TLSLE_ADD_TPREL_HI12 || - k == R_AARCH64_TLSLE_ADD_TPREL_LO12_NC || k == R_AARCH64_TPOFF64 || + k == R_AARCH64_TLSLE_ADD_TPREL_LO12_NC || k == R_RV_TPREL_HI20 || k == R_RV_TPREL_LO12_I || k == R_RV_TPREL_LO12_S; } @@ -384,8 +385,9 @@ static u64 tls_tcb_bias(Compiler* c) { * (X - tls_memsz). The two ELF reloc kinds R_X86_64_TPOFF32/_TPOFF64 * encode that signed offset directly at the reloc site (no TCB bias — * variant II's TCB sits *after* the image, so TPOFF is negative). */ -static int reloc_is_x64_tlsle(RelocKind k) { - return k == R_X64_TPOFF32 || k == R_X64_TPOFF64; +static int reloc_is_x64_tlsle(RelocKind k, int tls_variant_ii) { + if (k == R_TPOFF64 && tls_variant_ii) return 1; + return k == R_X64_TPOFF32; } static int reloc_is_abs(RelocKind k) { return k == R_ABS32 || k == R_ABS64; } @@ -468,6 +470,7 @@ static i64 rv_pcrel_lo12_disp(LinkImage* img, u64 auipc_vaddr, u64 img_base) { static void apply_all_relocs(LinkImage* img, u64 img_base) { u32 i; int pie = img->pie; + int tls_vi = (int)link_arch_desc_for(img->c)->tls_variant_ii; for (i = 0; i < LinkRelocs_count(&img->relocs); ++i) { LinkRelocApply* r = LinkRelocs_at(&img->relocs, i); const LinkSymbol* tgt = LinkSyms_at(&img->syms, r->target - 1); @@ -493,13 +496,13 @@ static void apply_all_relocs(LinkImage* img, u64 img_base) { continue; } seg = &img->segments[sec->segment_id - 1]; - if (reloc_is_tlsle(r->kind)) { + if (reloc_is_tlsle(r->kind, tls_vi)) { /* S is the target's TP-relative offset: distance from the TLS image * start plus the arch/OS TCB bias (see tls_tcb_bias). Both vaddrs are * in the same (post-shift, image-relative) coordinate system, so * img_base cancels out. */ S = (tgt->vaddr - img->tls_vaddr) + tls_tcb_bias(img->c); - } else if (reloc_is_x64_tlsle(r->kind)) { + } else if (reloc_is_x64_tlsle(r->kind, tls_vi)) { /* x86_64 variant II: TP points just past the TLS image, so a symbol at * offset X within the image is at TP-relative offset (X - tls_size). * The runtime (FreeBSD/glibc _init_tls) allocates the block rounded up diff --git a/src/obj/elf/reloc_aarch64.c b/src/obj/elf/reloc_aarch64.c @@ -45,9 +45,9 @@ u32 elf_aarch64_reloc_to(u32 kind /* RelocKind */) { return ELF_R_AARCH64_ADR_PREL_PG_HI21_NC; case R_AARCH64_ADD_ABS_LO12_NC: return ELF_R_AARCH64_ADD_ABS_LO12_NC; - case R_AARCH64_ABS16: + case R_ABS16: return ELF_R_AARCH64_ABS16; - case R_AARCH64_PREL16: + case R_PREL16: return ELF_R_AARCH64_PREL16; case R_AARCH64_LDST8_ABS_LO12_NC: return ELF_R_AARCH64_LDST8_ABS_LO12_NC; @@ -133,9 +133,9 @@ u32 elf_aarch64_reloc_from(u32 elf_type) { case ELF_R_AARCH64_ADD_ABS_LO12_NC: return R_AARCH64_ADD_ABS_LO12_NC; case ELF_R_AARCH64_ABS16: - return R_AARCH64_ABS16; + return R_ABS16; case ELF_R_AARCH64_PREL16: - return R_AARCH64_PREL16; + return R_PREL16; case ELF_R_AARCH64_LDST8_ABS_LO12_NC: return R_AARCH64_LDST8_ABS_LO12_NC; case ELF_R_AARCH64_LDST16_ABS_LO12_NC: diff --git a/src/obj/elf/reloc_riscv32.c b/src/obj/elf/reloc_riscv32.c @@ -56,17 +56,17 @@ u32 elf_riscv32_reloc_to(u32 kind /* RelocKind */) { return ELF_R_RISCV_TPREL_LO12_S; case R_RV_TPREL_ADD: return ELF_R_RISCV_TPREL_ADD; - case R_RV_ADD8: + case R_ADD8: return ELF_R_RISCV_ADD8; - case R_RV_ADD16: + case R_ADD16: return ELF_R_RISCV_ADD16; - case R_RV_ADD32: + case R_ADD32: return ELF_R_RISCV_ADD32; - case R_RV_SUB8: + case R_SUB8: return ELF_R_RISCV_SUB8; - case R_RV_SUB16: + case R_SUB16: return ELF_R_RISCV_SUB16; - case R_RV_SUB32: + case R_SUB32: return ELF_R_RISCV_SUB32; case R_RV_ALIGN: return ELF_R_RISCV_ALIGN; @@ -76,19 +76,17 @@ u32 elf_riscv32_reloc_to(u32 kind /* RelocKind */) { return ELF_R_RISCV_RVC_JUMP; case R_RV_RELAX: return ELF_R_RISCV_RELAX; - case R_RV_SUB6: + case R_SUB6: return ELF_R_RISCV_SUB6; - case R_RV_SET6: + case R_SET6: return ELF_R_RISCV_SET6; - case R_RV_SET8: + case R_ABS8: return ELF_R_RISCV_SET8; - case R_RV_SET16: + case R_ABS16: return ELF_R_RISCV_SET16; - case R_RV_SET32: - return ELF_R_RISCV_SET32; - case R_RV_SET_ULEB128: + case R_SET_ULEB128: return ELF_R_RISCV_SET_ULEB128; - case R_RV_SUB_ULEB128: + case R_SUB_ULEB128: return ELF_R_RISCV_SUB_ULEB128; default: return ELF_R_RISCV_NONE; @@ -138,17 +136,17 @@ u32 elf_riscv32_reloc_from(u32 elf_type) { case ELF_R_RISCV_TPREL_ADD: return R_RV_TPREL_ADD; case ELF_R_RISCV_ADD8: - return R_RV_ADD8; + return R_ADD8; case ELF_R_RISCV_ADD16: - return R_RV_ADD16; + return R_ADD16; case ELF_R_RISCV_ADD32: - return R_RV_ADD32; + return R_ADD32; case ELF_R_RISCV_SUB8: - return R_RV_SUB8; + return R_SUB8; case ELF_R_RISCV_SUB16: - return R_RV_SUB16; + return R_SUB16; case ELF_R_RISCV_SUB32: - return R_RV_SUB32; + return R_SUB32; case ELF_R_RISCV_ALIGN: return R_RV_ALIGN; case ELF_R_RISCV_RVC_BRANCH: @@ -158,19 +156,19 @@ u32 elf_riscv32_reloc_from(u32 elf_type) { case ELF_R_RISCV_RELAX: return R_RV_RELAX; case ELF_R_RISCV_SUB6: - return R_RV_SUB6; + return R_SUB6; case ELF_R_RISCV_SET6: - return R_RV_SET6; + return R_SET6; case ELF_R_RISCV_SET8: - return R_RV_SET8; + return R_ABS8; case ELF_R_RISCV_SET16: - return R_RV_SET16; + return R_ABS16; case ELF_R_RISCV_SET32: - return R_RV_SET32; + return R_ABS32; case ELF_R_RISCV_SET_ULEB128: - return R_RV_SET_ULEB128; + return R_SET_ULEB128; case ELF_R_RISCV_SUB_ULEB128: - return R_RV_SUB_ULEB128; + return R_SUB_ULEB128; default: return (u32)-1; /* sentinel */ } diff --git a/src/obj/elf/reloc_riscv64.c b/src/obj/elf/reloc_riscv64.c @@ -53,21 +53,21 @@ u32 elf_riscv64_reloc_to(u32 kind /* RelocKind */) { return ELF_R_RISCV_TPREL_LO12_S; case R_RV_TPREL_ADD: return ELF_R_RISCV_TPREL_ADD; - case R_RV_ADD8: + case R_ADD8: return ELF_R_RISCV_ADD8; - case R_RV_ADD16: + case R_ADD16: return ELF_R_RISCV_ADD16; - case R_RV_ADD32: + case R_ADD32: return ELF_R_RISCV_ADD32; - case R_RV_ADD64: + case R_ADD64: return ELF_R_RISCV_ADD64; - case R_RV_SUB8: + case R_SUB8: return ELF_R_RISCV_SUB8; - case R_RV_SUB16: + case R_SUB16: return ELF_R_RISCV_SUB16; - case R_RV_SUB32: + case R_SUB32: return ELF_R_RISCV_SUB32; - case R_RV_SUB64: + case R_SUB64: return ELF_R_RISCV_SUB64; case R_RV_ALIGN: return ELF_R_RISCV_ALIGN; @@ -77,19 +77,17 @@ u32 elf_riscv64_reloc_to(u32 kind /* RelocKind */) { return ELF_R_RISCV_RVC_JUMP; case R_RV_RELAX: return ELF_R_RISCV_RELAX; - case R_RV_SUB6: + case R_SUB6: return ELF_R_RISCV_SUB6; - case R_RV_SET6: + case R_SET6: return ELF_R_RISCV_SET6; - case R_RV_SET8: + case R_ABS8: return ELF_R_RISCV_SET8; - case R_RV_SET16: + case R_ABS16: return ELF_R_RISCV_SET16; - case R_RV_SET32: - return ELF_R_RISCV_SET32; - case R_RV_SET_ULEB128: + case R_SET_ULEB128: return ELF_R_RISCV_SET_ULEB128; - case R_RV_SUB_ULEB128: + case R_SUB_ULEB128: return ELF_R_RISCV_SUB_ULEB128; default: return ELF_R_RISCV_NONE; @@ -139,21 +137,21 @@ u32 elf_riscv64_reloc_from(u32 elf_type) { case ELF_R_RISCV_TPREL_ADD: return R_RV_TPREL_ADD; case ELF_R_RISCV_ADD8: - return R_RV_ADD8; + return R_ADD8; case ELF_R_RISCV_ADD16: - return R_RV_ADD16; + return R_ADD16; case ELF_R_RISCV_ADD32: - return R_RV_ADD32; + return R_ADD32; case ELF_R_RISCV_ADD64: - return R_RV_ADD64; + return R_ADD64; case ELF_R_RISCV_SUB8: - return R_RV_SUB8; + return R_SUB8; case ELF_R_RISCV_SUB16: - return R_RV_SUB16; + return R_SUB16; case ELF_R_RISCV_SUB32: - return R_RV_SUB32; + return R_SUB32; case ELF_R_RISCV_SUB64: - return R_RV_SUB64; + return R_SUB64; case ELF_R_RISCV_ALIGN: return R_RV_ALIGN; case ELF_R_RISCV_RVC_BRANCH: @@ -163,19 +161,19 @@ u32 elf_riscv64_reloc_from(u32 elf_type) { case ELF_R_RISCV_RELAX: return R_RV_RELAX; case ELF_R_RISCV_SUB6: - return R_RV_SUB6; + return R_SUB6; case ELF_R_RISCV_SET6: - return R_RV_SET6; + return R_SET6; case ELF_R_RISCV_SET8: - return R_RV_SET8; + return R_ABS8; case ELF_R_RISCV_SET16: - return R_RV_SET16; + return R_ABS16; case ELF_R_RISCV_SET32: - return R_RV_SET32; + return R_ABS32; case ELF_R_RISCV_SET_ULEB128: - return R_RV_SET_ULEB128; + return R_SET_ULEB128; case ELF_R_RISCV_SUB_ULEB128: - return R_RV_SUB_ULEB128; + return R_SUB_ULEB128; default: return (u32)-1; /* sentinel */ } diff --git a/src/obj/elf/reloc_x86_64.c b/src/obj/elf/reloc_x86_64.c @@ -47,7 +47,7 @@ u32 elf_x86_64_reloc_to(u32 kind /* RelocKind */) { return ELF_R_X86_64_GOTOFF64; case R_X64_TPOFF32: return ELF_R_X86_64_TPOFF32; - case R_X64_TPOFF64: + case R_TPOFF64: return ELF_R_X86_64_TPOFF64; case R_X64_DTPOFF32: return ELF_R_X86_64_DTPOFF32; @@ -107,7 +107,7 @@ u32 elf_x86_64_reloc_from(u32 elf_type) { case ELF_R_X86_64_TPOFF32: return R_X64_TPOFF32; case ELF_R_X86_64_TPOFF64: - return R_X64_TPOFF64; + return R_TPOFF64; case ELF_R_X86_64_DTPOFF32: return R_X64_DTPOFF32; case ELF_R_X86_64_DTPMOD64: diff --git a/src/obj/macho/emit.c b/src/obj/macho/emit.c @@ -525,21 +525,21 @@ void emit_macho(Compiler* c, ObjBuilder* ob, Writer* w) { const Reloc* r = obj_reloc_at(ob, ri); if (r->removed) continue; if (r->section_id != m->obj_sec) continue; - if ((r->kind == R_RV_ADD8 || r->kind == R_RV_ADD16 || - r->kind == R_RV_ADD32 || r->kind == R_RV_ADD64) && + if ((r->kind == R_ADD8 || r->kind == R_ADD16 || + r->kind == R_ADD32 || r->kind == R_ADD64) && ri + 1u < total_relocs) { const Reloc* sub = obj_reloc_at(ob, ri + 1u); int paired = sub && sub->section_id == r->section_id && sub->offset == r->offset && - ((r->kind == R_RV_ADD8 && sub->kind == R_RV_SUB8) || - (r->kind == R_RV_ADD16 && sub->kind == R_RV_SUB16) || - (r->kind == R_RV_ADD32 && sub->kind == R_RV_SUB32) || - (r->kind == R_RV_ADD64 && sub->kind == R_RV_SUB64)); + ((r->kind == R_ADD8 && sub->kind == R_SUB8) || + (r->kind == R_ADD16 && sub->kind == R_SUB16) || + (r->kind == R_ADD32 && sub->kind == R_SUB32) || + (r->kind == R_ADD64 && sub->kind == R_SUB64)); if (paired) { - u32 length = (r->kind == R_RV_ADD64) ? 3u - : (r->kind == R_RV_ADD32) ? 2u - : (r->kind == R_RV_ADD16) ? 1u - : 0u; + u32 length = (r->kind == R_ADD64) ? 3u + : (r->kind == R_ADD32) ? 2u + : (r->kind == R_ADD16) ? 1u + : 0u; u32 add_idx; u32 sub_idx; u32 sub_type = c->target.arch == KIT_ARCH_ARM_64 diff --git a/src/obj/macho/read.c b/src/obj/macho/read.c @@ -702,10 +702,10 @@ ObjBuilder* read_macho(Compiler* c, const char* name, const u8* data, u32 kind; if (r_type == ARM64_RELOC_SUBTRACTOR) { - kind = (r_length == 3) ? R_RV_SUB64 - : (r_length == 2) ? R_RV_SUB32 - : (r_length == 1) ? R_RV_SUB16 - : R_RV_SUB8; + kind = (r_length == 3) ? R_SUB64 + : (r_length == 2) ? R_SUB32 + : (r_length == 1) ? R_SUB16 + : R_SUB8; } else { kind = macho->reloc_from(r_type); } @@ -719,10 +719,10 @@ ObjBuilder* read_macho(Compiler* c, const char* name, const u8* data, if (r_type == ARM64_RELOC_UNSIGNED) { if (pending_subtractor && pending_subtractor_offset == r_address && pending_subtractor_length == r_length) { - kind = (r_length == 3) ? R_RV_ADD64 - : (r_length == 2) ? R_RV_ADD32 - : (r_length == 1) ? R_RV_ADD16 - : R_RV_ADD8; + kind = (r_length == 3) ? R_ADD64 + : (r_length == 2) ? R_ADD32 + : (r_length == 1) ? R_ADD16 + : R_ADD8; pending_subtractor = 0; } else if (r_pcrel) { kind = (r_length == 3) ? R_PC64 : R_PC32; diff --git a/src/obj/obj.c b/src/obj/obj.c @@ -1086,6 +1086,10 @@ const char* reloc_kind_name(RelocKind k) { _CASE(R_PC64); _CASE(R_GOT32); _CASE(R_PLT32); + _CASE(R_ABS8); + _CASE(R_ABS16); + _CASE(R_PREL16); + _CASE(R_TPOFF64); _CASE(R_AARCH64_ADR_GOT_PAGE); _CASE(R_AARCH64_LD64_GOT_LO12_NC); _CASE(R_ARM_CALL); @@ -1107,8 +1111,6 @@ const char* reloc_kind_name(RelocKind k) { _CASE(R_AARCH64_LDST32_ABS_LO12_NC); _CASE(R_AARCH64_LDST64_ABS_LO12_NC); _CASE(R_AARCH64_LDST128_ABS_LO12_NC); - _CASE(R_AARCH64_ABS16); - _CASE(R_AARCH64_PREL16); _CASE(R_AARCH64_TLVP_LOAD_PAGE21); _CASE(R_AARCH64_TLVP_LOAD_PAGEOFF12); _CASE(R_AARCH64_TLSLE_ADD_TPREL_HI12); @@ -1124,7 +1126,6 @@ const char* reloc_kind_name(RelocKind k) { _CASE(R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC); _CASE(R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21); _CASE(R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC); - _CASE(R_AARCH64_TPOFF64); _CASE(R_COFF_ADDR32NB); _CASE(R_AARCH64_GLOB_DAT); _CASE(R_AARCH64_JUMP_SLOT); @@ -1139,7 +1140,6 @@ const char* reloc_kind_name(RelocKind k) { _CASE(R_X64_GOTPC32); _CASE(R_X64_GOTOFF64); _CASE(R_X64_TPOFF32); - _CASE(R_X64_TPOFF64); _CASE(R_X64_DTPOFF32); _CASE(R_X64_DTPMOD64); _CASE(R_X64_DTPOFF64); @@ -1166,25 +1166,22 @@ const char* reloc_kind_name(RelocKind k) { _CASE(R_RV_TPREL_LO12_I); _CASE(R_RV_TPREL_LO12_S); _CASE(R_RV_TPREL_ADD); - _CASE(R_RV_ADD8); - _CASE(R_RV_ADD16); - _CASE(R_RV_ADD32); - _CASE(R_RV_ADD64); - _CASE(R_RV_SUB8); - _CASE(R_RV_SUB16); - _CASE(R_RV_SUB32); - _CASE(R_RV_SUB64); + _CASE(R_ADD8); + _CASE(R_ADD16); + _CASE(R_ADD32); + _CASE(R_ADD64); + _CASE(R_SUB8); + _CASE(R_SUB16); + _CASE(R_SUB32); + _CASE(R_SUB64); _CASE(R_RV_ALIGN); _CASE(R_RV_RVC_BRANCH); _CASE(R_RV_RVC_JUMP); _CASE(R_RV_RELAX); - _CASE(R_RV_SUB6); - _CASE(R_RV_SET6); - _CASE(R_RV_SET8); - _CASE(R_RV_SET16); - _CASE(R_RV_SET32); - _CASE(R_RV_SET_ULEB128); - _CASE(R_RV_SUB_ULEB128); + _CASE(R_SUB6); + _CASE(R_SET6); + _CASE(R_SET_ULEB128); + _CASE(R_SUB_ULEB128); _CASE(R_WASM_FUNCIDX); _CASE(R_WASM_TABLEIDX); _CASE(R_WASM_MEMOFS); diff --git a/src/obj/obj.h b/src/obj/obj.h @@ -120,6 +120,16 @@ typedef enum RelocKind { R_PC64, R_GOT32, R_PLT32, + /* Neutral data-word kinds completing the ABS/PREL/TPOFF families. */ + R_ABS8, + R_ABS16, + R_PREL16, + /* Internal-only: a raw 64-bit local-exec tpoff written into a TLS GOT + * slot by link_emit_internal_tpoff64. Never appears on the wire. + * x86_64 stores variant-II (X - tls_memsz); AArch64 and RISC-V store + * variant-I ((X - tls_vaddr) + TCB). Byte encoding is identical on + * all three arches: a plain 64-bit little-endian write. */ + R_TPOFF64, R_AARCH64_ADR_GOT_PAGE, R_AARCH64_LD64_GOT_LO12_NC, R_ARM_CALL, @@ -144,8 +154,6 @@ typedef enum RelocKind { R_AARCH64_LDST32_ABS_LO12_NC, R_AARCH64_LDST64_ABS_LO12_NC, R_AARCH64_LDST128_ABS_LO12_NC, - R_AARCH64_ABS16, - R_AARCH64_PREL16, /* AArch64 Mach-O TLV (thread-local variable) descriptor access. The * compiler emits these to reference a TLV descriptor in * __DATA,__thread_vars; the linker routes both through a synthetic @@ -195,7 +203,6 @@ typedef enum RelocKind { R_X64_GOTPC32, R_X64_GOTOFF64, R_X64_TPOFF32, - R_X64_TPOFF64, R_X64_DTPOFF32, R_X64_DTPMOD64, R_X64_DTPOFF64, @@ -230,25 +237,22 @@ typedef enum RelocKind { R_RV_TPREL_LO12_I, R_RV_TPREL_LO12_S, R_RV_TPREL_ADD, - R_RV_ADD8, - R_RV_ADD16, - R_RV_ADD32, - R_RV_ADD64, - R_RV_SUB8, - R_RV_SUB16, - R_RV_SUB32, - R_RV_SUB64, + R_ADD8, + R_ADD16, + R_ADD32, + R_ADD64, + R_SUB8, + R_SUB16, + R_SUB32, + R_SUB64, R_RV_ALIGN, R_RV_RVC_BRANCH, R_RV_RVC_JUMP, R_RV_RELAX, - R_RV_SUB6, - R_RV_SET6, - R_RV_SET8, - R_RV_SET16, - R_RV_SET32, - R_RV_SET_ULEB128, - R_RV_SUB_ULEB128, + R_SUB6, + R_SET6, + R_SET_ULEB128, + R_SUB_ULEB128, R_WASM_FUNCIDX, R_WASM_TABLEIDX, R_WASM_MEMOFS, @@ -273,15 +277,12 @@ typedef enum RelocKind { R_COFF_AARCH64_SECREL_HIGH12A, /* AArch64 TLS Initial-Exec. The ADRP/LDR pair loads the symbol's * TP-relative offset from a GOT slot; the linker fills that slot with a - * 64-bit tpoff (R_AARCH64_TPOFF64) and redirects these to the slot, so they - * apply exactly like the regular ADR_GOT_PAGE / LD64_GOT_LO12_NC pair. + * 64-bit tpoff (R_TPOFF64) and redirects these to the slot, so they apply + * exactly like the regular ADR_GOT_PAGE / LD64_GOT_LO12_NC pair. * Appended at the enum tail so the public KIT_RELOC_* values (object.h) * keep their pinned numbering. */ R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21, R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, - /* Internal-only: a raw 64-bit AArch64/RISC-V local-exec tpoff written into - * a TLS GOT slot ((target - tls_vaddr) + TCB). Never appears on the wire. */ - R_AARCH64_TPOFF64, /* COFF ADDR32NB: 32-bit image-relative RVA (S + A - ImageBase), used by * PE exception tables and other image metadata. */ R_COFF_ADDR32NB, diff --git a/src/obj/reloc.c b/src/obj/reloc.c @@ -29,7 +29,9 @@ const RelocDesc* reloc_desc_row_find(const RelocDescRow* rows, u32 n, * first); this row supplies both the width fallback and the correct * "not a branch" answer on AArch64. */ static const RelocDescRow neutral_rows[] = { + {R_ABS8, {1, 0}}, {R_ABS16, {2, 0}}, {R_ABS32, {4, 0}}, {R_ABS64, {8, 0}}, + {R_PREL16, {2, 0}}, {R_TPOFF64, {8, 0}}, {R_REL32, {4, 0}}, {R_REL64, {8, 0}}, {R_PC32, {4, 0}}, {R_PC64, {8, 0}}, {R_GOT32, {4, 0}}, {R_PLT32, {4, 0}}, diff --git a/src/obj/reloc_apply.c b/src/obj/reloc_apply.c @@ -98,8 +98,7 @@ int reloc_apply_neutral(Compiler* c, RelocKind k, u8* P_bytes, u64 S, i64 A, return 1; } case R_ABS64: - case R_X64_TPOFF64: - case R_AARCH64_TPOFF64: + case R_TPOFF64: case R_X64_RELATIVE: { /* R_X64_RELATIVE: (S + A) — for static-with-relocs paths the * linker writes the relocated value directly; the dynamic @@ -153,80 +152,74 @@ int reloc_apply_neutral(Compiler* c, RelocKind k, u8* P_bytes, u64 S, i64 A, wr_u64_le(P_bytes, (u64)v); return 1; } - case R_AARCH64_ABS16: { + case R_ABS8: + P_bytes[0] = (u8)((S + (u64)A) & 0xffu); + return 1; + case R_ABS16: { u64 v = S + (u64)A; wr_u16_le(P_bytes, (u16)(v & 0xffffu)); return 1; } - case R_AARCH64_PREL16: { + case R_PREL16: { i64 v = (i64)S + A - (i64)P; wr_u16_le(P_bytes, (u16)((u64)v & 0xffffu)); return 1; } - case R_RV_ADD8: { + case R_ADD8: { /* word8 += S + A. Used (paired with a SUB8 against another sym * at the same site) to encode symbol differences. */ u8 cur = P_bytes[0]; P_bytes[0] = (u8)(cur + (u8)((S + (u64)A) & 0xffu)); return 1; } - case R_RV_SUB8: { + case R_SUB8: { u8 cur = P_bytes[0]; P_bytes[0] = (u8)(cur - (u8)((S + (u64)A) & 0xffu)); return 1; } - case R_RV_ADD16: { + case R_ADD16: { u16 cur = rd_u16_le(P_bytes); wr_u16_le(P_bytes, (u16)(cur + (u16)((S + (u64)A) & 0xffffu))); return 1; } - case R_RV_SUB16: { + case R_SUB16: { u16 cur = rd_u16_le(P_bytes); wr_u16_le(P_bytes, (u16)(cur - (u16)((S + (u64)A) & 0xffffu))); return 1; } - case R_RV_ADD32: { + case R_ADD32: { u32 cur = rd_u32_le(P_bytes); wr_u32_le(P_bytes, (u32)(cur + (u32)((S + (u64)A) & 0xffffffffu))); return 1; } - case R_RV_SUB32: { + case R_SUB32: { u32 cur = rd_u32_le(P_bytes); wr_u32_le(P_bytes, (u32)(cur - (u32)((S + (u64)A) & 0xffffffffu))); return 1; } - case R_RV_ADD64: { + case R_ADD64: { u64 cur = rd_u64_le(P_bytes); wr_u64_le(P_bytes, cur + S + (u64)A); return 1; } - case R_RV_SUB64: { + case R_SUB64: { u64 cur = rd_u64_le(P_bytes); wr_u64_le(P_bytes, cur - S - (u64)A); return 1; } - case R_RV_SUB6: { + case R_SUB6: { /* Bottom 6 bits of byte = (byte - (S + A)) & 0x3f. */ u8 cur = P_bytes[0]; u8 v = (u8)((cur & 0x3fu) - (u8)((S + (u64)A) & 0x3fu)); P_bytes[0] = (u8)((cur & 0xc0u) | (v & 0x3fu)); return 1; } - case R_RV_SET6: { + case R_SET6: { u8 cur = P_bytes[0]; P_bytes[0] = (u8)((cur & 0xc0u) | (u8)((S + (u64)A) & 0x3fu)); return 1; } - case R_RV_SET8: - P_bytes[0] = (u8)((S + (u64)A) & 0xffu); - return 1; - case R_RV_SET16: - wr_u16_le(P_bytes, (u16)((S + (u64)A) & 0xffffu)); - return 1; - case R_RV_SET32: - wr_u32_le(P_bytes, (u32)((S + (u64)A) & 0xffffffffu)); - return 1; - case R_RV_SET_ULEB128: { + case R_SET_ULEB128: { /* Variable-length ULEB128 field set to (S + A). These come as a * PAIR at the same offset (RISC-V psABI): SET_ULEB128 sets the * field, a following SUB_ULEB128 then subtracts the second @@ -238,7 +231,7 @@ int reloc_apply_neutral(Compiler* c, RelocKind k, u8* P_bytes, u64 S, i64 A, reloc_uleb128_write_fixed(P_bytes, v, width); return 1; } - case R_RV_SUB_ULEB128: { + case R_SUB_ULEB128: { /* field -= (S + A), preserving the original ULEB128 width. The * paired SET_ULEB128 ran first (same offset); we read back the * value it wrote and subtract this symbol's resolved address. */ diff --git a/test/link/reloc_apply_test.c b/test/link/reloc_apply_test.c @@ -98,9 +98,9 @@ static const ApplyCase kCases[] = { {"aa64 TLVP_LOAD_PAGEOFF12", KIT_ARCH_ARM_64, R_AARCH64_TLVP_LOAD_PAGEOFF12, 0xf9400000u, 4, 0x1100, 0, 0, 0xf9408000u}, /* ---- AArch64 neutral data words (kept in obj core) ---- */ - {"aa64 ABS16", KIT_ARCH_ARM_64, R_AARCH64_ABS16, 0x0000u, 2, 0x1234, 0, 0, + {"aa64 ABS16", KIT_ARCH_ARM_64, R_ABS16, 0x0000u, 2, 0x1234, 0, 0, 0x1234u}, - {"aa64 PREL16", KIT_ARCH_ARM_64, R_AARCH64_PREL16, 0x0000u, 2, 0x2000, 0, + {"aa64 PREL16", KIT_ARCH_ARM_64, R_PREL16, 0x0000u, 2, 0x2000, 0, 0x1000, 0x1000u}, /* ---- x86-64 instruction-immediate + neutral data words ---- */ @@ -153,11 +153,11 @@ static const ApplyCase kCases[] = { {"rv TPREL_ADD", KIT_ARCH_RV64, R_RV_TPREL_ADD, 0xdeadbeefu, 4, 0x1000, 0, 0x2000, 0xdeadbeefu}, /* ---- RISC-V neutral data-word arms (kept in obj core) ---- */ - {"rv ADD32", KIT_ARCH_RV64, R_RV_ADD32, 0x00000010u, 4, 0x20, 0, 0, + {"rv ADD32", KIT_ARCH_RV64, R_ADD32, 0x00000010u, 4, 0x20, 0, 0, 0x00000030u}, - {"rv SUB32", KIT_ARCH_RV64, R_RV_SUB32, 0x00000030u, 4, 0x10, 0, 0, + {"rv SUB32", KIT_ARCH_RV64, R_SUB32, 0x00000030u, 4, 0x10, 0, 0, 0x00000020u}, - {"rv SET8", KIT_ARCH_RV64, R_RV_SET8, 0x00u, 1, 0x2a, 0, 0, 0x2au}, + {"rv SET8", KIT_ARCH_RV64, R_ABS8, 0x00u, 1, 0x2a, 0, 0, 0x2au}, }; static KitCompiler* compiler_for(KitArchKind arch) { diff --git a/test/link/reloc_desc_test.c b/test/link/reloc_desc_test.c @@ -55,16 +55,17 @@ static u8 oracle_width(RelocKind k) { case R_ABS64: case R_REL64: case R_PC64: - case R_X64_TPOFF64: + case R_TPOFF64: case R_X64_GLOB_DAT: case R_X64_JUMP_SLOT: case R_X64_RELATIVE: return 8; - case R_AARCH64_ABS16: - case R_AARCH64_PREL16: - return 2; + case R_ABS8: case R_X64_PC8: return 1; + case R_ABS16: + case R_PREL16: + return 2; case R_AARCH64_JUMP26: case R_AARCH64_CALL26: case R_AARCH64_CONDBR19: @@ -110,25 +111,22 @@ static u8 oracle_width(RelocKind k) { case R_RV_RELAX: case R_RV_TPREL_ADD: return 4; - case R_RV_ADD8: - case R_RV_SUB8: - case R_RV_SUB6: - case R_RV_SET6: - case R_RV_SET8: + case R_ADD8: + case R_SUB8: + case R_SUB6: + case R_SET6: return 1; - case R_RV_ADD16: - case R_RV_SUB16: - case R_RV_SET16: + case R_ADD16: + case R_SUB16: return 2; - case R_RV_ADD32: - case R_RV_SUB32: - case R_RV_SET32: + case R_ADD32: + case R_SUB32: return 4; - case R_RV_ADD64: - case R_RV_SUB64: + case R_ADD64: + case R_SUB64: return 8; - case R_RV_SET_ULEB128: - case R_RV_SUB_ULEB128: + case R_SET_ULEB128: + case R_SUB_ULEB128: return ORACLE_RV_ULEB128_NOMINAL_WIDTH; case R_COFF_SECREL: case R_COFF_ADDR32NB: diff --git a/test/link/reloc_uleb128_unit.c b/test/link/reloc_uleb128_unit.c @@ -60,8 +60,8 @@ static uint64_t decode_uleb128(const uint8_t* p, uint32_t* len_out) { * width must be preserved. */ static void apply_pair(uint8_t* site, uint64_t s_hi, int64_t a_hi, uint64_t s_lo, int64_t a_lo) { - link_reloc_apply(NULL, R_RV_SET_ULEB128, site, s_hi, a_hi, 0); - link_reloc_apply(NULL, R_RV_SUB_ULEB128, site, s_lo, a_lo, 0); + link_reloc_apply(NULL, R_SET_ULEB128, site, s_hi, a_hi, 0); + link_reloc_apply(NULL, R_SUB_ULEB128, site, s_lo, a_lo, 0); } /* Verify the field at site decodes to want_val and occupies exactly @@ -150,7 +150,7 @@ int main(void) { /* ---- Case 6: standalone SET then SUB-to-zero leaves field == SET. ---- */ { uint8_t buf[2] = {0x00, 0x9d}; - link_reloc_apply(NULL, R_RV_SET_ULEB128, buf, 0x2a, 0, 0); + link_reloc_apply(NULL, R_SET_ULEB128, buf, 0x2a, 0, 0); expect_field("set-only", buf, 0x2au, 1u, 0x9d, buf[1]); }