w6a+w6l: DATAR directive for absolute-address relocs in .data
Unblock literal initialisers for str/slice/struct globals by wiring
an R_X86_64_64 relocation kind through both assembler and static
linker.
w6a:
- new A_DATAR directive, syntax `DATAR slot+off(SB),target(SB)`,
records an R_X86_64_64 reloc at slot+off in .data pointing at
target. The slot must be pre-defined by a prior DATAW;
- parse_operand learned the `name+disp(SB)` shape so the slot's
byte offset can be addressed explicitly;
- Areloc carries a `section` flag (0=.text / 1=.data) and obj.c
splits the reloc list into .rela.text and .rela.data, emitting
the latter conditionally with sh_info pointing at .data.
w6l:
- Lrel grows the same `section` flag; obj.c loads `.rela.data`
sections into the global reloc list with offsets shifted by
each input's data_off;
- pass.c handles R_X86_64_64: target VA is data_va+sym.val for
in_data symbols (else text_va+sym.val), addend is added, and
the 8-byte slot is patched in l->data (or l->text).
Inputs without DATAR are unaffected — bootstrap, 991 (selfhost .o
diff) and 992 (selfhost exe diff) keep their byte-identical
output. 520_datar covers the new path: asm a DATAW+DATAR pair,
verify .rela.data has exactly one R_X86_64_64 entry, link, run,
confirm the relocated pointer feeds a 5-byte write that prints
"hello".
Selfhost mirror + w6c emission for str/slice/struct literal init
land in follow-ups.
This commit is contained in:
@@ -70,6 +70,23 @@ a_addreloc(Asm *a, u64 off, int kind, Asym *s, i64 add)
|
||||
{
|
||||
Areloc *r = calloc(1, sizeof *r);
|
||||
r->off = off;
|
||||
r->section = 0; /* .text */
|
||||
r->kind = kind;
|
||||
r->sym = s;
|
||||
r->addend = add;
|
||||
r->next = a->relocs;
|
||||
a->relocs = r;
|
||||
}
|
||||
|
||||
/* Record a relocation that lives in the .data section. Used by
|
||||
* DATAR to patch a 64-bit slot with a symbol's runtime VA. obj.c
|
||||
* separates these into .rela.data when emitting the .o. */
|
||||
void
|
||||
a_addreloc_data(Asm *a, u64 off, int kind, Asym *s, i64 add)
|
||||
{
|
||||
Areloc *r = calloc(1, sizeof *r);
|
||||
r->off = off;
|
||||
r->section = 1; /* .data */
|
||||
r->kind = kind;
|
||||
r->sym = s;
|
||||
r->addend = add;
|
||||
@@ -335,6 +352,26 @@ a_encode(Asm *a)
|
||||
a_emit_data_byte(a, p->bytes[i]);
|
||||
break;
|
||||
}
|
||||
case A_DATAR: {
|
||||
/* DATAR slot+off(SB), target(SB) — record an
|
||||
* R_X86_64_64 relocation at slot+off in .data
|
||||
* pointing at target. The slot must already be
|
||||
* defined by a prior DATAW (which emitted zero
|
||||
* placeholder bytes the linker will overwrite). */
|
||||
Asym *holder = a_intern(a, p->from.sym);
|
||||
if (!holder->defined || !holder->is_data) {
|
||||
fprintf(stderr,
|
||||
"w6a: line %d: DATAR slot %s not yet defined as DATAW\n",
|
||||
p->line, p->from.sym);
|
||||
a->errs++;
|
||||
break;
|
||||
}
|
||||
Asym *target = a_intern(a, p->to.sym);
|
||||
u64 reloff = holder->addr + (u64)p->from.offset;
|
||||
a_addreloc_data(a, reloff, 1 /* R_X86_64_64 */,
|
||||
target, 0);
|
||||
break;
|
||||
}
|
||||
case A_RET:
|
||||
a_emit_byte(a, 0xC3);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user