[Git][ghc/ghc][wip/supersven/riscv64-ncg] Linker: Use SymbolExtras for GOT relative relocations to local symbols

Sven Tennie (@supersven) gitlab at gitlab.haskell.org
Mon Mar 4 10:39:01 UTC 2024



Sven Tennie pushed to branch wip/supersven/riscv64-ncg at Glasgow Haskell Compiler / GHC


Commits:
c482cd0f by Sven Tennie at 2024-03-04T11:37:16+01:00
Linker: Use SymbolExtras for GOT relative relocations to local symbols

This is (hopefully!) faster than emitting real GOT entries for all local
labels (which was implemented before.)

- - - - -


5 changed files:

- rts/LinkerInternals.h
- rts/linker/SymbolExtras.c
- rts/linker/SymbolExtras.h
- rts/linker/elf_got.c
- rts/linker/elf_reloc_riscv64.c


Changes:

=====================================
rts/LinkerInternals.h
=====================================
@@ -208,7 +208,7 @@ typedef struct _Segment {
     int n_sections;
 } Segment;
 
-#if defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH) || defined(arm_HOST_ARCH) || defined(aarch64_HOST_ARCH)
+#if defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH) || defined(arm_HOST_ARCH) || defined(aarch64_HOST_ARCH) || defined(riscv64_HOST_ARCH)
 #define NEED_SYMBOL_EXTRAS 1
 #endif
 
@@ -237,6 +237,8 @@ typedef struct {
     uint8_t     jumpIsland[8];
 #elif defined(arm_HOST_ARCH)
     uint8_t     jumpIsland[16];
+#elif defined(riscv64_HOST_ARCH)
+    uint64_t    addr;
 #endif
 } SymbolExtra;
 


=====================================
rts/linker/SymbolExtras.c
=====================================
@@ -153,7 +153,7 @@ void ocProtectExtras(ObjectCode* oc)
 }
 
 
-#if defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH)
+#if defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH) || defined(riscv64_HOST_ARCH)
 SymbolExtra* makeSymbolExtra( ObjectCode const* oc,
                               unsigned long symbolNumber,
                               unsigned long target )
@@ -189,9 +189,12 @@ SymbolExtra* makeSymbolExtra( ObjectCode const* oc,
     extra->addr = target;
     memcpy(extra->jumpIsland, jmp, 8);
 #endif /* x86_64_HOST_ARCH */
-
+#if defined(riscv64_HOST_ARCH)
+    // Fake GOT entry (used like GOT, but located in symbol extras)
+    extra->addr = target;
+#endif
     return extra;
 }
-#endif /* powerpc_HOST_ARCH || x86_64_HOST_ARCH */
+#endif /* powerpc_HOST_ARCH || x86_64_HOST_ARCH || riscv64_HOST_ARCH */
 #endif /* !x86_64_HOST_ARCH) || !mingw32_HOST_OS */
 #endif // NEED_SYMBOL_EXTRAS


=====================================
rts/linker/SymbolExtras.h
=====================================
@@ -16,7 +16,7 @@ SymbolExtra* makeArmSymbolExtra( ObjectCode const* oc,
                                  unsigned long target,
                                  bool fromThumb,
                                  bool toThumb );
-#elif defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH)
+#elif defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH) || defined(riscv64_HOST_ARCH)
 SymbolExtra* makeSymbolExtra( ObjectCode const* oc,
                               unsigned long symbolNumber,
                               unsigned long target );


=====================================
rts/linker/elf_got.c
=====================================
@@ -22,22 +22,7 @@ bool needGotSlot(Elf_Sym *symbol) {
          ELF_ST_BIND(symbol->st_info) == STB_WEAK
          // Section symbols exist primarily for relocation
          // and as such may need a GOT slot.
-         || ELF_ST_TYPE(symbol->st_info) == STT_SECTION
-#if defined(riscv64_HOST_ARCH)
-         // RISCV relies much on relocations and relaxations, leaving most of
-         // the addressing mode heavy lifting to the linker. We're using LA to
-         // load local label addresses (e.g. to access `*_closure`.) This
-         // implies (in the medany memory model) relocation via the GOT unless
-         // the instruction gets relaxed to e.g. direct or PC-relative
-         // addressing. So, for now, we've got the special case to add GOT
-         // symbols for all local labels here. This could be optimized by e.g.
-         // adding symbols to GOT on demand: I.e. if we spot a symbol related
-         // relocation which cannot be relaxed to direct or PC-relative
-         // addressing, then add it to GOT (otherwise not.)
-         || (ELF_ST_BIND(symbol->st_info) == STB_LOCAL &&
-             ELF_ST_TYPE(symbol->st_info) == STT_NOTYPE && symbol->st_name != 0)
-#endif
-      ;
+         || ELF_ST_TYPE(symbol->st_info) == STT_SECTION;
 }
 
 bool


=====================================
rts/linker/elf_reloc_riscv64.c
=====================================
@@ -1,6 +1,8 @@
 #include "elf_reloc_riscv64.h"
+#include "LinkerInternals.h"
 #include "Rts.h"
 #include "Stg.h"
+#include "SymbolExtras.h"
 #include "elf.h"
 #include "elf_plt.h"
 #include "elf_util.h"
@@ -442,8 +444,8 @@ int32_t computeAddend(Section *section, Elf_Rel *rel, ElfSymbol *symbol,
                        symbol_prime->addr, symbol_prime->name));
           int32_t result = computeAddend(targetSection, (Elf_Rel *)rel_prime,
                                          symbol_prime, addend_prime, oc);
-          IF_DEBUG(linker,
-            debugBelch("Result of computeAddend: 0x%x (%d)\n", result, result));
+          IF_DEBUG(linker, debugBelch("Result of computeAddend: 0x%x (%d)\n",
+                                      result, result));
           return result;
         }
       }
@@ -509,9 +511,28 @@ int32_t computeAddend(Section *section, Elf_Rel *rel, ElfSymbol *symbol,
   case R_RISCV_32_PCREL:
     return S + A - P;
   case R_RISCV_GOT_HI20: {
-    // Ensure that the GOT entry is set up.
-    CHECK(0x0 != GOT_S);
-    return GOT_S + A - P;
+    // TODO: Allocating extra memory for every symbol just to play this trick
+    // seems to be a bit obscene. (GOT relocations hitting local symbols
+    // happens, but not very often.) It would be better to allocate only what we
+    // really need.
+
+    // There are two cases here: 1. The symbol is public and has an entry in the
+    // GOT. 2. It's local and has no corresponding GOT entry. The first case is
+    // easy: We simply calculate the addend with the GOT address. In the second
+    // case we create a symbol extra entry and pretend it's the GOT.
+    if (GOT_S != 0) {
+      // 1. Public symbol with GOT entry.
+      return GOT_S + A - P;
+    } else {
+      // 2. Fake GOT entry with symbol extra entry.
+      SymbolExtra *symbolExtra = makeSymbolExtra(oc, ELF_R_SYM(rel->r_info), S);
+      addr_t* FAKE_GOT_S = &symbolExtra->addr;
+      addr_t res = (addr_t) FAKE_GOT_S + A - P;
+      IF_DEBUG(linker, debugBelch("R_RISCV_GOT_HI20 w/ SymbolExtra = %p , "
+                                  "entry = 0x%lx , reloc-addend = 0x%lu ",
+                                  symbolExtra, FAKE_GOT_S, res));
+      return res;
+    }
   }
   default:
     debugBelch("Unimplemented relocation: 0x%lx\n (%lu)",



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/c482cd0f92ab04287357673d5e4253fc6795ec08

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/c482cd0f92ab04287357673d5e4253fc6795ec08
You're receiving this email because of your account on gitlab.haskell.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20240304/73fcc017/attachment-0001.html>


More information about the ghc-commits mailing list