[Git][ghc/ghc][wip/supersven/riscv64-ncg] 3 commits: Linker: Add local labels to the GOT
Sven Tennie (@supersven)
gitlab at gitlab.haskell.org
Fri Mar 1 09:35:20 UTC 2024
Sven Tennie pushed to branch wip/supersven/riscv64-ncg at Glasgow Haskell Compiler / GHC
Commits:
c0eb04d3 by Sven Tennie at 2024-03-01T10:01:58+01:00
Linker: Add local labels to the GOT
- - - - -
b5050132 by Sven Tennie at 2024-03-01T10:05:17+01:00
Linker: uint32_t addend
This seems to be a good representation:
- We're dealing with negative values as well (e.g. negative PC offset)
- We cannot deal with more than 20 + 12 = 32 bits
- - - - -
77b14c9a by Sven Tennie at 2024-03-01T10:12:03+01:00
Linker: Rework debug traces
- - - - -
2 changed files:
- rts/linker/elf_got.c
- rts/linker/elf_reloc_riscv64.c
Changes:
=====================================
rts/linker/elf_got.c
=====================================
@@ -9,22 +9,35 @@
* Check if we need a global offset table slot for a
* given symbol
*/
-bool
-needGotSlot(Elf_Sym * symbol) {
- /* using global here should give an upper bound */
- /* I don't believe we need to relocate STB_LOCAL
- * symbols via the GOT; however I'm unsure about
- * STB_WEAK.
- *
- * Any more restrictive filter here would result
- * in a smaller GOT, which is preferable.
- */
- return ELF_ST_BIND(symbol->st_info) == STB_GLOBAL
- || 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;
-
+bool needGotSlot(Elf_Sym *symbol) {
+ /* using global here should give an upper bound */
+ /* I don't believe we need to relocate STB_LOCAL
+ * symbols via the GOT; however I'm unsure about
+ * STB_WEAK.
+ *
+ * Any more restrictive filter here would result
+ * in a smaller GOT, which is preferable.
+ */
+ return ELF_ST_BIND(symbol->st_info) == STB_GLOBAL ||
+ 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
+ ;
}
bool
=====================================
rts/linker/elf_reloc_riscv64.c
=====================================
@@ -73,8 +73,8 @@ char *relocationTypeToString(Elf64_Xword type) {
typedef uint64_t addr_t;
-int64_t decodeAddendRISCV64(Section *section, Elf_Rel *rel) STG_NORETURN;
-bool encodeAddendRISCV64(Section *section, Elf_Rel *rel, int64_t addend);
+int32_t decodeAddendRISCV64(Section *section, Elf_Rel *rel) STG_NORETURN;
+bool encodeAddendRISCV64(Section *section, Elf_Rel *rel, int32_t addend);
/* regular instructions are 32bit */
typedef uint32_t inst_t;
@@ -83,7 +83,7 @@ typedef uint32_t inst_t;
typedef uint16_t cinst_t;
// TODO: Decide which functions should be static and/or inlined.
-int64_t decodeAddendRISCV64(Section *section STG_UNUSED,
+int32_t decodeAddendRISCV64(Section *section STG_UNUSED,
Elf_Rel *rel STG_UNUSED) {
debugBelch("decodeAddendRISCV64: Relocations with explicit addend are not "
"supported.");
@@ -146,10 +146,11 @@ uint32_t setLO12_S(uint32_t insn, uint32_t imm) {
(extractBits(imm, 4, 0) << 7);
}
-void setUType(inst_t *loc, uint32_t val) {
+void setUType(inst_t *loc, int32_t val) {
const unsigned bits = 32;
- uint64_t hi = val + 0x800;
+ uint32_t hi = val + 0x800;
checkInt(loc, SignExtend64(hi, bits) >> 12, 20);
+ debugBelch("setUType: hi 0x%x val 0x%x\n", hi, val);
write32le(loc, (read32le(loc) & 0xFFF) | (hi & 0xFFFFF000));
}
@@ -227,16 +228,15 @@ void setCJType(cinst_t *loc, uint32_t val) {
write16le(loc, insn);
}
-bool encodeAddendRISCV64(Section *section, Elf_Rel *rel, int64_t addend) {
+bool encodeAddendRISCV64(Section *section, Elf_Rel *rel, int32_t addend) {
addr_t P = (addr_t)((uint8_t *)section->start + rel->r_offset);
- IF_DEBUG(
- linker,
- debugBelch(
- "Relocation type %s 0x%lx (%lu) symbol 0x%lx addend 0x%lx (%lu / "
- "%ld) P 0x%lx\n",
- relocationTypeToString(rel->r_info), ELF64_R_TYPE(rel->r_info),
- ELF64_R_TYPE(rel->r_info), ELF64_R_SYM(rel->r_info), addend, addend,
- addend, P));
+ IF_DEBUG(linker,
+ debugBelch(
+ "Relocation type %s 0x%lx (%lu) symbol 0x%lx addend 0x%x (%u / "
+ "%d) P 0x%lx\n",
+ relocationTypeToString(rel->r_info), ELF64_R_TYPE(rel->r_info),
+ ELF64_R_TYPE(rel->r_info), ELF64_R_SYM(rel->r_info), addend,
+ addend, addend, P));
switch (ELF64_R_TYPE(rel->r_info)) {
case R_RISCV_32_PCREL:
case R_RISCV_32:
@@ -352,7 +352,7 @@ bool encodeAddendRISCV64(Section *section, Elf_Rel *rel, int64_t addend) {
* @param addend The existing addend. Either explicit or implicit.
* @return The new computed addend.
*/
-int64_t computeAddend(Section *section, Elf_Rel *rel, ElfSymbol *symbol,
+int32_t computeAddend(Section *section, Elf_Rel *rel, ElfSymbol *symbol,
int64_t addend, ObjectCode *oc) {
/* Position where something is relocated */
@@ -438,8 +438,11 @@ int64_t computeAddend(Section *section, Elf_Rel *rel, ElfSymbol *symbol,
relocationTypeToString(rel->r_info), P, S, symbol->name,
relocationTypeToString(rel_prime->r_info), P_prime,
symbol_prime->addr, symbol_prime->name));
- return computeAddend(targetSection, (Elf_Rel *)rel_prime,
- symbol_prime, addend_prime, oc);
+ 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));
+ return result;
}
}
}
@@ -462,10 +465,9 @@ int64_t computeAddend(Section *section, Elf_Rel *rel, ElfSymbol *symbol,
abort(/* could not find or make stub */);
}
}
- IF_DEBUG(
- linker,
- debugBelch("S = 0x%lx A = 0x%lx P = 0x%lx (S + A) - P = 0x%lx \n", S,
- A, P, (S + A) - P));
+ IF_DEBUG(linker, debugBelch("R_RISCV_CALL_PLT: S = 0x%lx A = 0x%lx P = "
+ "0x%lx (S + A) - P = 0x%lx \n",
+ S, A, P, (S + A) - P));
return (S + A) - P;
}
case R_RISCV_ADD8:
@@ -504,9 +506,11 @@ int64_t computeAddend(Section *section, Elf_Rel *rel, ElfSymbol *symbol,
return 0;
case R_RISCV_32_PCREL:
return S + A - P;
- case R_RISCV_GOT_HI20:
- // reduced G + GOT to GOT_S - This might be wrong!
+ case R_RISCV_GOT_HI20: {
+ // Ensure that the GOT entry is set up.
+ CHECK(0x0 != GOT_S);
return GOT_S + A - P;
+ }
default:
debugBelch("Unimplemented relocation: 0x%lx\n (%lu)",
ELF64_R_TYPE(rel->r_info), ELF64_R_TYPE(rel->r_info));
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/c36bf10472d3243b25c4480dad55b9c7c7fb865c...77b14c9a1db2bf15b4a46443f7c5eb5e70257cd1
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/c36bf10472d3243b25c4480dad55b9c7c7fb865c...77b14c9a1db2bf15b4a46443f7c5eb5e70257cd1
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/20240301/f95d4441/attachment-0001.html>
More information about the ghc-commits
mailing list