Преглед изворни кода

riscv/flat: link with --no-relax

ld relaxes position independent sequences into absolute ones as soon as the
target address fits a 12 bit immediate.  That only happens in small images,
and a bFLT is loaded at an arbitrary base, so those addresses are simply
wrong.  It lands on the register_tm_clones / deregister_tm_clones pair that
.init_array calls before main, so a small binary dies with SIGSEGV before it
ever reaches main:

  small image:  li   a0,1024        <- absolute, no relocation
  large image:  addi a0,gp,-1796    <- gp relative, survives relocation

Diagnosed on uClibc-ng's testsuite, where the twelve failures of the
riscv32 noMMU FLAT target were exactly the binaries small enough for this:
tiny plus the tests whose main is compiled out by feature guards.  With
--no-relax five of the six recheck cleanly (getrpcent, bug-strspn1,
tst-strxfrm and exec-null, plus the -O2 twins).

Not a binutils regression: a cross link of the same objects with binutils
2.46 instead of 2.39 produces the same absolute form.  For ld the link *is*
a fixed address executable -- nothing in it says the image will be moved --
so the flag belongs on our side.  elf2flt's ld-elf2flt would be the better
place, since it already injects the linker script and --emit-relocs.

Signed-off-by: Ramin Moussavi <ramin.moussavi@yacoub.de>
Signed-off-by: Waldemar Brodkorb <wbx@openadk.org>
ramin пре 1 недеља
родитељ
комит
60cf03c056
1 измењених фајлова са 9 додато и 0 уклоњено
  1. 9 0
      mk/vars.mk

+ 9 - 0
mk/vars.mk

@@ -209,6 +209,15 @@ ifeq ($(ADK_TARGET_ARCH_RISCV64)$(ADK_TARGET_ARCH_RISCV32),y)
 ifeq ($(ADK_TARGET_BINFMT_FLAT),y)
 TARGET_CFLAGS+=		-fPIC
 TARGET_CXXFLAGS+=	-fPIC
+# ld relaxes position independent sequences into absolute ones as soon as the
+# target address fits a 12 bit immediate, which only happens in small images.
+# A bFLT is loaded at an arbitrary base, so those addresses are wrong: it hits
+# the register_tm_clones pair that .init_array runs before main, and every
+# small binary dies with SIGSEGV. binutils 2.46 does this exactly like 2.39 --
+# for ld the link is a fixed address executable, so saying no is our job.
+TARGET_LDFLAGS+=	-Wl,--no-relax
+TARGET_CFLAGS+=		-Wl,--no-relax
+TARGET_CXXFLAGS+=	-Wl,--no-relax
 endif
 endif