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 defined; /* 1 if we own its address */
|
||||||
int is_text; /* if 1, address is in .text */
|
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_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 */
|
u64 addr; /* offset within section if defined */
|
||||||
int idx; /* ELF symtab index, filled at emit time */
|
int idx; /* ELF symtab index, filled at emit time */
|
||||||
Asym *next;
|
Asym *next;
|
||||||
|
|||||||
@@ -13,9 +13,9 @@
|
|||||||
* omitted entirely so output stays byte-identical to the pre-DATAW
|
* omitted entirely so output stays byte-identical to the pre-DATAW
|
||||||
* format. Test 991 (selfhost .o byte-diff) depends on this.
|
* format. Test 991 (selfhost .o byte-diff) depends on this.
|
||||||
*
|
*
|
||||||
* Symtab indices: 0 = STN_UNDEF, 1 = file (skipped), 2.. = our syms.
|
* Symtab indices: 0 = STN_UNDEF, 1.. = our syms (no file entry).
|
||||||
* For simplicity we emit GLOBAL symbols only (no LOCAL ordering rules
|
* Every emitted symbol is GLOBAL (no LOCAL ordering rules); defined
|
||||||
* to worry about).
|
* non-exported label syms are pruned unless a reloc references them.
|
||||||
*/
|
*/
|
||||||
#include "a.h"
|
#include "a.h"
|
||||||
#include <stdlib.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
|
/* Data symbols carry STT_OBJECT and st_shndx=SH_DATA; everything
|
||||||
* else keeps the legacy STT_FUNC/SH_TEXT shape so non-DATAW
|
* else keeps the legacy STT_FUNC/SH_TEXT shape so non-DATAW
|
||||||
* outputs stay byte-identical. */
|
* 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;
|
int idx = 1;
|
||||||
for (Asym *s = a->syms; s; s = s->next) {
|
for (Asym *s = a->syms; s; s = s->next) {
|
||||||
|
if (s->defined && !s->is_global && !s->has_reloc)
|
||||||
|
continue;
|
||||||
Sym64 e = {0};
|
Sym64 e = {0};
|
||||||
e.st_name = stput(&str, s->name);
|
e.st_name = stput(&str, s->name);
|
||||||
if (s->defined) {
|
if (s->defined) {
|
||||||
|
|||||||
@@ -187,9 +187,23 @@ export fn emitelf(a: *asm_, fd: i32) i32 = {
|
|||||||
for (zi < 24) { zsym[zi] = 0u8; zi += 1; };
|
for (zi < 24) { zsym[zi] = 0u8; zi += 1; };
|
||||||
bufputb(&sym, zsym.ptr, 24u64);
|
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 idx: i32 = 1;
|
||||||
let s: *asym = a.syms;
|
let s: *asym = a.syms;
|
||||||
for (s != nil) {
|
for (s != nil) {
|
||||||
|
if (s.defined != 0 && s.isglobal == 0 && s.hasreloc == 0) {
|
||||||
|
s = s.snext;
|
||||||
|
continue;
|
||||||
|
};
|
||||||
let entry: [24]u8;
|
let entry: [24]u8;
|
||||||
let ei: i32 = 0;
|
let ei: i32 = 0;
|
||||||
for (ei < 24) { entry[ei] = 0u8; ei += 1; };
|
for (ei < 24) { entry[ei] = 0u8; ei += 1; };
|
||||||
|
|||||||
@@ -170,6 +170,7 @@ type asym = struct {
|
|||||||
istext: i32,
|
istext: i32,
|
||||||
isdata: i32, // mutually exclusive with istext; DATAW symbols
|
isdata: i32, // mutually exclusive with istext; DATAW symbols
|
||||||
isglobal: i32,
|
isglobal: i32,
|
||||||
|
hasreloc: i32, // referenced by a relocation — must be in the symtab
|
||||||
addr: u64, // offset within its section (.text or .data)
|
addr: u64, // offset within its section (.text or .data)
|
||||||
idx: i32,
|
idx: i32,
|
||||||
snext: *asym,
|
snext: *asym,
|
||||||
|
|||||||
Reference in New Issue
Block a user