diff --git a/cmd/w6a/a.h b/cmd/w6a/a.h index 1febfe13..ee3a081d 100644 --- a/cmd/w6a/a.h +++ b/cmd/w6a/a.h @@ -50,7 +50,8 @@ struct Asym { int defined; /* 1 if we own its address */ int is_text; /* if 1, address is in .text */ int is_data; /* if 1, address is in .data (mutually exclusive with is_text) */ - int is_global; /* exported (TEXT) */ + int is_global; /* exported (TEXT/DATA/DATAW) */ + int has_reloc; /* referenced by a relocation — must be in the symtab */ u64 addr; /* offset within section if defined */ int idx; /* ELF symtab index, filled at emit time */ Asym *next; diff --git a/cmd/w6a/obj.c b/cmd/w6a/obj.c index 81dcf917..9bc8569c 100644 --- a/cmd/w6a/obj.c +++ b/cmd/w6a/obj.c @@ -13,9 +13,9 @@ * omitted entirely so output stays byte-identical to the pre-DATAW * format. Test 991 (selfhost .o byte-diff) depends on this. * - * Symtab indices: 0 = STN_UNDEF, 1 = file (skipped), 2.. = our syms. - * For simplicity we emit GLOBAL symbols only (no LOCAL ordering rules - * to worry about). + * Symtab indices: 0 = STN_UNDEF, 1.. = our syms (no file entry). + * Every emitted symbol is GLOBAL (no LOCAL ordering rules); defined + * non-exported label syms are pruned unless a reloc references them. */ #include "a.h" #include @@ -156,8 +156,17 @@ a_emit_elf(Asm *a, FILE *f) /* Data symbols carry STT_OBJECT and st_shndx=SH_DATA; everything * else keeps the legacy STT_FUNC/SH_TEXT shape so non-DATAW * outputs stay byte-identical. */ + /* Branch labels are interned for fixup resolution but are NOT + * link-visible: emitting them (all bindings here are GLOBAL) + * made every label collide-able across objects. Only exported + * definitions (is_global), undefined externs, and reloc- + * referenced syms reach the symtab. */ + for (Areloc *r = a->relocs; r; r = r->next) + r->sym->has_reloc = 1; int idx = 1; for (Asym *s = a->syms; s; s = s->next) { + if (s->defined && !s->is_global && !s->has_reloc) + continue; Sym64 e = {0}; e.st_name = stput(&str, s->name); if (s->defined) { diff --git a/selfhost/cmd/w6a/obj.ww b/selfhost/cmd/w6a/obj.ww index d0d5d041..7f504cfd 100644 --- a/selfhost/cmd/w6a/obj.ww +++ b/selfhost/cmd/w6a/obj.ww @@ -187,9 +187,23 @@ export fn emitelf(a: *asm_, fd: i32) i32 = { for (zi < 24) { zsym[zi] = 0u8; zi += 1; }; bufputb(&sym, zsym.ptr, 24u64); + // Branch labels are interned for fixup resolution but are NOT + // link-visible: emitting them (all bindings here are GLOBAL) + // made every label collide-able across objects. Only exported + // definitions (isglobal), undefined externs, and reloc- + // referenced syms reach the symtab. + let rr: *areloc = a.relocs; + for (rr != nil) { + rr.asy.hasreloc = 1; + rr = rr.rnext; + }; let idx: i32 = 1; let s: *asym = a.syms; for (s != nil) { + if (s.defined != 0 && s.isglobal == 0 && s.hasreloc == 0) { + s = s.snext; + continue; + }; let entry: [24]u8; let ei: i32 = 0; for (ei < 24) { entry[ei] = 0u8; ei += 1; }; diff --git a/selfhost/cmd/w6a/opcodes.ww b/selfhost/cmd/w6a/opcodes.ww index 9d5455d9..950bd0cd 100644 --- a/selfhost/cmd/w6a/opcodes.ww +++ b/selfhost/cmd/w6a/opcodes.ww @@ -170,6 +170,7 @@ type asym = struct { istext: i32, isdata: i32, // mutually exclusive with istext; DATAW symbols isglobal: i32, + hasreloc: i32, // referenced by a relocation — must be in the symtab addr: u64, // offset within its section (.text or .data) idx: i32, snext: *asym,