[klibc] [klibc:master] riscv64: Make linker relaxation work and enable it

klibc-bot for Ben Hutchings ben at decadent.org.uk
Sat Dec 12 15:27:04 PST 2020


Commit-ID:  f41ee37972fb5b319bf19c9bc88e550b30f624c1
Gitweb:     http://git.kernel.org/?p=libs/klibc/klibc.git;a=commit;h=f41ee37972fb5b319bf19c9bc88e550b30f624c1
Author:     Ben Hutchings <ben at decadent.org.uk>
AuthorDate: Sat, 29 Aug 2020 21:59:24 +0100
Committer:  Ben Hutchings <ben at decadent.org.uk>
CommitDate: Sat, 12 Dec 2020 21:58:15 +0100

[klibc] riscv64: Make linker relaxation work and enable it

RISC-V code generally needs two instructions to address static data,
but up to 4K of static data in an executable can be addressed using a
single instruction.  The linker "relaxes" a two-instruction sequence
to one instruction, assuming that the gp register is initialised
appropriately.

In my initial port, I had this working for static executables but not
for those using the shared library, so I disabled relaxation.
gp-relative relaxation is *not* meant to be used in shared libraries,
but we should enable it in executables.  pc-relative relaxation can be
enabled in all cases.

* When linking the shared library, define __global_pointer$ as 0 to
  disable gp-relative relaxation
* For executables using the shared-library, add a _main routine in
  _main.S that initialises gp and tail-calls main
* Add _main.o to $(KLIBCCRTSHARED) and change the entry point to _main
* Install _main.o so klcc can use it
* Drop the --no-relax linker option

Thanks: Jessica Clarke <jrtc27 at jrtc27.com>
Signed-off-by: Ben Hutchings <ben at decadent.org.uk>

---
 usr/klibc/arch/riscv64/Kbuild  |  8 ++++++--
 usr/klibc/arch/riscv64/MCONFIG |  7 ++++---
 usr/klibc/arch/riscv64/_main.S | 17 +++++++++++++++++
 3 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/usr/klibc/arch/riscv64/Kbuild b/usr/klibc/arch/riscv64/Kbuild
index 242ac5bb..218f3869 100644
--- a/usr/klibc/arch/riscv64/Kbuild
+++ b/usr/klibc/arch/riscv64/Kbuild
@@ -2,7 +2,11 @@
 #
 # klibc files for riscv64
 
-always  := crt0.o
-targets := crt0.o
+always  := crt0.o _main.o
+targets := crt0.o _main.o
 
 klib-y := setjmp.o syscall.o
+
+install-rule:
+	$(Q)$(shell $(install-data) $(call objectify,_main.o) \
+	          $(INSTALLROOT)$(INSTALLDIR)/$(KLIBCCROSS)lib)
diff --git a/usr/klibc/arch/riscv64/MCONFIG b/usr/klibc/arch/riscv64/MCONFIG
index 9bc7bd24..34061086 100644
--- a/usr/klibc/arch/riscv64/MCONFIG
+++ b/usr/klibc/arch/riscv64/MCONFIG
@@ -7,9 +7,6 @@
 # accordingly.
 #
 
-# We should get klibc.so and the executables to agree on what gp
-# should be.  For now, disable gp-relative addressing.
-KLIBCLDFLAGS      = --no-relax
 KLIBCOPTFLAGS	  += -Os -fomit-frame-pointer
 ifeq ($(DEBUG),y)
 KLIBCOPTFLAGS     += -g
@@ -18,6 +15,10 @@ KLIBCBITSIZE      = 64
 
 # Normal binaries start at 64 KB, so start the libary at 2 MB.
 KLIBCSHAREDFLAGS  = $(LD_IMAGE_BASE_OPT) 0x00200000
+KLIBCSHAREDFLAGS  += --defsym '__global_pointer$$=0'
 
 # Kernel has never used stack trampolines
 KLIBCEXECSTACK := n
+
+KLIBCEMAIN        := -e _main
+KLIBCCRTSHARED    += $(KLIBCOBJ)/arch/riscv64/_main.o
diff --git a/usr/klibc/arch/riscv64/_main.S b/usr/klibc/arch/riscv64/_main.S
new file mode 100644
index 00000000..284a2222
--- /dev/null
+++ b/usr/klibc/arch/riscv64/_main.S
@@ -0,0 +1,17 @@
+#
+# arch/riscv64/_main.S
+#
+# Does arch-specific initialization and invokes main with the
+# appropriate arguments.
+#
+
+#include <machine/asm.h>
+
+ENTRY(_main)
+	.option push
+	.option norelax
+	lla	gp, __global_pointer$
+	.option pop
+
+	j	main
+END(_main)


More information about the klibc mailing list