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:
@@ -121,6 +121,7 @@ opcode_lookup(const char *m)
|
||||
{ "TEXT", A_TEXT },
|
||||
{ "DATA", A_DATA },
|
||||
{ "DATAW", A_DATAW },
|
||||
{ "DATAR", A_DATAR },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
for (int i = 0; tab[i].m; i++)
|
||||
@@ -211,6 +212,17 @@ parse_operand(Asm *a, const char *s, Aoperand *out)
|
||||
while (a_isidcont((unsigned char)*s) && n < 63) buf[n++] = *s++;
|
||||
buf[n] = 0;
|
||||
|
||||
/* Optional `+disp` between the ident and `(SB)`. Used by
|
||||
* DATAR to address bytes inside an existing .data slot
|
||||
* (e.g. `DATAR s+8(SB),...`). */
|
||||
i64 sym_disp = 0;
|
||||
if (*s == '+') {
|
||||
s++;
|
||||
char *end;
|
||||
sym_disp = a_parsenum(s, &end);
|
||||
s = end;
|
||||
}
|
||||
|
||||
/* ID(SB) means external symbol */
|
||||
if (*s == '(') {
|
||||
char rbuf[8] = {0};
|
||||
@@ -223,6 +235,7 @@ parse_operand(Asm *a, const char *s, Aoperand *out)
|
||||
if (r == D_PSB) {
|
||||
out->type = D_EXTERN;
|
||||
out->sym = strdup(buf);
|
||||
out->offset = sym_disp;
|
||||
return 0;
|
||||
}
|
||||
out->type = D_INDIR;
|
||||
|
||||
Reference in New Issue
Block a user