aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arm64-gen.c45
1 files changed, 24 insertions, 21 deletions
diff --git a/arm64-gen.c b/arm64-gen.c
index 737a7be..814fa16 100644
--- a/arm64-gen.c
+++ b/arm64-gen.c
@@ -400,27 +400,30 @@ static void gen_fstore(int sz, int dst, int bas, uint64_t off)
static void gen_addr(int r, Sym *sym, unsigned long addend)
{
-#if 0
- // This is normally the right way to do it, I think,
- // but it does not work with "-run" when stdin or stderr is
- // used by the program: "R_AARCH64_ADR_PREL_PG_HI21 relocation failed".
- greloca(cur_text_section, sym, ind, R_AARCH64_ADR_PREL_PG_HI21, addend);
- o(0x90000000 | r);
- greloca(cur_text_section, sym, ind, R_AARCH64_ADD_ABS_LO12_NC, addend);
- o(0x91000000 | r | r << 5);
-#else
- // This seems to work in all cases, unless you try to use an old buggy
- // GCC for linking, which says: "unresolvable R_AARCH64_MOVW_UABS_G0_NC
- // relocation against symbol `stderr@@GLIBC_2.17'".
- greloca(cur_text_section, sym, ind, R_AARCH64_MOVW_UABS_G0_NC, addend);
- o(0xf2800000 | r); // movk x(rt),#...,lsl #0
- greloca(cur_text_section, sym, ind, R_AARCH64_MOVW_UABS_G1_NC, addend);
- o(0xf2a00000 | r); // movk x(rt),#...,lsl #16
- greloca(cur_text_section, sym, ind, R_AARCH64_MOVW_UABS_G2_NC, addend);
- o(0xf2c00000 | r); // movk x(rt),#...,lsl #32
- greloca(cur_text_section, sym, ind, R_AARCH64_MOVW_UABS_G3, addend);
- o(0xf2e00000 | r); // movk x(rt),#...,lsl #48
-#endif
+ // Currently TCC's linker does not generate COPY relocations for
+ // STT_OBJECTs when tcc is invoked with "-run". This typically
+ // results in "R_AARCH64_ADR_PREL_PG_HI21 relocation failed" when
+ // a program refers to stdin. A workaround is to avoid that
+ // relocation and use only relocations with unlimited range.
+ int avoid_adrp = 1;
+
+ if (avoid_adrp || (sym->type.t & VT_WEAK)) {
+ // (GCC uses a R_AARCH64_ABS64 in this case.)
+ greloca(cur_text_section, sym, ind, R_AARCH64_MOVW_UABS_G0_NC, addend);
+ o(0xd2800000 | r); // mov x(rt),#0,lsl #0
+ greloca(cur_text_section, sym, ind, R_AARCH64_MOVW_UABS_G1_NC, addend);
+ o(0xf2a00000 | r); // movk x(rt),#0,lsl #16
+ greloca(cur_text_section, sym, ind, R_AARCH64_MOVW_UABS_G2_NC, addend);
+ o(0xf2c00000 | r); // movk x(rt),#0,lsl #32
+ greloca(cur_text_section, sym, ind, R_AARCH64_MOVW_UABS_G3, addend);
+ o(0xf2e00000 | r); // movk x(rt),#0,lsl #48
+ }
+ else {
+ greloca(cur_text_section, sym, ind, R_AARCH64_ADR_PREL_PG_HI21, addend);
+ o(0x90000000 | r);
+ greloca(cur_text_section, sym, ind, R_AARCH64_ADD_ABS_LO12_NC, addend);
+ o(0x91000000 | r | r << 5);
+ }
}
ST_FUNC void load(int r, SValue *sv)