mirror of
git://c9x.me/qbe.git
synced 2026-08-02 15:44:39 +00:00
rv64: use pc-relative addressing for globals
When extern was added, the rv64 code switched regular globals from using la (a pseudo-instruction that uses pc-relative addressing with auipc + addi) to lui + addi (absolute addressing). Presumably, this was done to match gcc's output with -fPIC and -fno-PIC respectively. However, the key difference here is actually the directive `%option pic` vs `%option nopic`, which determines whether la uses the GOT or not. This broke linking as PIE (for instance in compilers with --enable-default-pie), even when there are no global references outside the executable. The other architectures always use pc-relative addressing, so rv64 should do the same. It turns out there are more specific pseudo-instructions lla and lga we can use instead. lla uses auipc+addi, and lga uses auipc+ld from the GOT. lga does not allow an offset. If you try to use one, it will assemble without error, but fail at link time with (.text+0x10): dangerous relocation: The addend isn't allowed for R_RISCV_GOT_HI20 For now, just add a check for this. A proper fix involves some changes to rv64/isel like is done for amd64.
This commit is contained in:
parent
80d745c842
commit
e786f06032
14
rv64/emit.c
14
rv64/emit.c
@ -133,9 +133,13 @@ emitaddr(Con *c, FILE *f)
|
|||||||
{
|
{
|
||||||
assert((c->sym.type & ~SExt) == SGlo);
|
assert((c->sym.type & ~SExt) == SGlo);
|
||||||
fputs(str(c->sym.id), f);
|
fputs(str(c->sym.id), f);
|
||||||
if (c->bits.i)
|
if (c->bits.i) {
|
||||||
|
/* TODO: fix isel to ensure no offset for SGlo */
|
||||||
|
if (c->sym.type & SExt)
|
||||||
|
die("extern with offset is not supported");
|
||||||
fprintf(f, "+%"PRIi64, c->bits.i);
|
fprintf(f, "+%"PRIi64, c->bits.i);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
emitf(char *s, Ins *i, Fn *fn, FILE *f)
|
emitf(char *s, Ins *i, Fn *fn, FILE *f)
|
||||||
@ -233,14 +237,8 @@ loadaddr(Con *c, char *rn, FILE *f)
|
|||||||
|
|
||||||
switch (c->sym.type) {
|
switch (c->sym.type) {
|
||||||
case SGlo:
|
case SGlo:
|
||||||
fprintf(f, "\tlui %s, %%hi(", rn);
|
|
||||||
emitaddr(c, f);
|
|
||||||
fprintf(f, ")\n\taddi %s, %s, %%lo(", rn, rn);
|
|
||||||
emitaddr(c, f);
|
|
||||||
fputs(")\n", f);
|
|
||||||
break;
|
|
||||||
case SExt:
|
case SExt:
|
||||||
fprintf(f, "\tla %s, ", rn);
|
fprintf(f, "\t%s %s, ", c->sym.type == SExt ? "lga" : "lla", rn);
|
||||||
emitaddr(c, f);
|
emitaddr(c, f);
|
||||||
fputc('\n', f);
|
fputc('\n', f);
|
||||||
break;
|
break;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user