w6a: branch labels stay out of the symtab (isglobal wired)
Every interned symbol -- including branch labels defined via p.label -- was emitted STB_GLOBAL, so labels were collide-able across objects and the header's "GLOBAL symbols only" contract was enforced nowhere (asym.isglobal was set but never read). Labels stay interned for fixup resolution; the symtab now carries only exported definitions, undefined externs, and reloc-referenced syms (a reloc pre-pass marks those). rt/ensure.o drops from 15 emitted syms to 2. Bootstrap 991-995 hold byte-identical on the new format.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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 <stdlib.h>
|
||||
@@ -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) {
|
||||
|
||||
@@ -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; };
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user