Files
ww/cmd/w6l/pass.c
Hojun-Cho 62b9d20383 toolchain: banner purge + WHY-only comment sweep (rule 8)
selfhost/, cmd/, internal/ join the tree-wide sweep: every section
banner dies (91 selfhost + the cmd C-style dividers -> 0); narration
and stale contracts deleted (pre-#22 bundler notes, retired
single-PT_LOAD and no-archive claims, superseded ABI tables); every
ref/harec/qbe cite, task cite, encoding/ELF contract, and rule-10
twin pointer kept; lost lifetime/rationale lines restored where the
sweep over-cut (elf_globals ownership, kwtab linear-scan). Comment-
only proven: all five wwstage tool binaries byte-identical across
the sweep; test-commit, test-byteid (161+1399, 0 pinned-divergent),
and test-bootstrap (fixed point + 991-995 byte-id) all exit 0.
The read-through banked 66 latent-bug leads (checkpoint).
2026-08-08 23:14:03 +09:00

109 lines
2.7 KiB
C

#include "l.h"
#include <stdio.h>
#include <string.h>
#define R_X86_64_64 1
#define R_X86_64_PC32 2
#define R_X86_64_PLT32 4
int
l_resolve(Lnk *l)
{
/* Initialise dynamic-linking fields. plt_idx and dynsym_idx
* default to -1; l_intern sets is_dyn/dyn_lib to 0/NULL via
* calloc, but we make the invariants explicit here for clarity. */
for (Lsym *s = l->syms; s; s = s->next) {
s->plt_idx = -1;
s->dynsym_idx = -1;
}
/* Promote each undefined sym that some Lso exports to "dynamic"
* and hand it a PLT slot. Order is the iteration order over the
* relocation list; that determines slot numbering and is stable
* across runs (rels are pushed onto the head as objects load). */
for (Lrel *r = l->rels; r; r = r->next) {
if (r->sym == NULL || r->sym->defined) continue;
if (r->sym->is_dyn) continue;
for (Lso *so = l->sos; so; so = so->next) {
const char *ver = NULL;
if (l_so_provides_v(so, r->sym->name, &ver)) {
r->sym->is_dyn = 1;
r->sym->dyn_lib = so;
r->sym->dyn_version = ver; /* may be NULL */
r->sym->plt_idx = l->dyn_n++;
break;
}
}
}
for (Lrel *r = l->rels; r; r = r->next) {
if (r->sym == NULL) continue;
if (!r->sym->defined && !r->sym->is_dyn) {
fprintf(stderr, "w6l: undefined reference to '%s'\n",
r->sym->name);
l->errs++;
}
}
return l->errs;
}
static void
patch_u32(u8 *p, u32 v)
{
p[0] = (u8)(v & 0xff);
p[1] = (u8)((v >> 8) & 0xff);
p[2] = (u8)((v >> 16) & 0xff);
p[3] = (u8)((v >> 24) & 0xff);
}
static void
patch_u64(u8 *p, u64 v)
{
for (int i = 0; i < 8; i++)
p[i] = (u8)((v >> (i * 8)) & 0xff);
}
int
l_relocate(Lnk *l, u64 text_va, u64 data_va)
{
for (Lrel *r = l->rels; r; r = r->next) {
if (r->sym == NULL) continue;
/* Dynamic syms are patched later, in l_emit_elf, once the
* PLT's virtual address is known. */
if (r->sym->is_dyn) continue;
if (!r->sym->defined) continue;
u64 sym_va = r->sym->in_data
? data_va + r->sym->val
: text_va + r->sym->val;
switch (r->kind) {
case R_X86_64_PC32:
case R_X86_64_PLT32: {
/* PC-relative 32-bit displacement; lands in .text.
* For static linking PLT32 collapses to PC32. */
u64 site = text_va + r->off;
i64 rel = (i64)sym_va - (i64)site + r->addend;
patch_u32(l->text + r->off, (u32)(i32)rel);
break;
}
case R_X86_64_64: {
/* Absolute 64-bit: patch the 8-byte slot at the
* given offset within the section. Currently only
* used for data slots holding symbol addresses
* (DATAR). */
u64 v = (u64)((i64)sym_va + r->addend);
if (r->section == 1) {
patch_u64(l->data + r->off, v);
} else {
patch_u64(l->text + r->off, v);
}
break;
}
default:
fprintf(stderr, "w6l: unsupported reloc kind %d\n",
r->kind);
l->errs++;
}
}
return l->errs;
}