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:
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]);
}