[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