[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <99733532831377ab6585d43ee40bf314a2d4c5a3.camel@xry111.site>
Date: Thu, 28 Jul 2022 00:28:39 +0800
From: Xi Ruoyao <xry111@...111.site>
To: loongarch@...ts.linux.dev
Cc: linux-kernel@...r.kernel.org, WANG Xuerui <kernel@...0n.name>,
Huacai Chen <chenhuacai@...nel.org>
Subject: [PATCH 3/5] LoongArch: Support relocation against
_GLOBAL_OFFSET_TABLE_
With the stack-based relocations, the assembler emits three relocations
to push the PC-relative offset of a GOT entry:
R_LARCH_SOP_PUSH_PCREL _GLOBAL_OFFSET_TABLE_
R_LARCH_SOP_PUSH_GPREL foo
R_LARCH_SOP_ADD
"_GLOBAL_OFFSET_TABLE_" does not really exist in the symtab and the BFD
linker handles it with special hack. Implement a similar hack for
kernel so we will be able to really use R_LARCH_SOP_PUSH_GPREL
relocation.
Signed-off-by: Xi Ruoyao <xry111@...111.site>
---
arch/loongarch/kernel/module-sections.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/arch/loongarch/kernel/module-sections.c b/arch/loongarch/kernel/module-sections.c
index 509c0b86b1e9..73976addbf60 100644
--- a/arch/loongarch/kernel/module-sections.c
+++ b/arch/loongarch/kernel/module-sections.c
@@ -89,6 +89,9 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
char *secstrings, struct module *mod)
{
unsigned int i, num_plts = 0, num_gots = 0;
+ Elf_Shdr *symtab = NULL;
+ Elf_Sym *symbols;
+ char *strings;
/*
* Find the empty .plt sections.
@@ -100,6 +103,8 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
mod->arch.plt_idx.shdr = sechdrs + i;
else if (!strcmp(secstrings + sechdrs[i].sh_name, ".got"))
mod->arch.got.shdr = sechdrs + i;
+ else if (sechdrs[i].sh_type == SHT_SYMTAB)
+ symtab = sechdrs + i;
}
if (!mod->arch.plt.shdr) {
@@ -115,6 +120,22 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
return -ENOEXEC;
}
+ if (!symtab) {
+ pr_err("%s: module symbol table missing\n", mod->name);
+ return -ENOEXEC;
+ }
+
+ symbols = (void *) ehdr + symtab->sh_offset;
+ strings = (void *) ehdr + sechdrs[symtab->sh_link].sh_offset;
+
+ for (i = 0; i < symtab->sh_size / sizeof(Elf_Sym); i++)
+ if (symbols[i].st_shndx == SHN_UNDEF &&
+ strcmp(strings + symbols[i].st_name,
+ "_GLOBAL_OFFSET_TABLE_") == 0) {
+ symbols[i].st_shndx = mod->arch.got.shdr - sechdrs;
+ symbols[i].st_value = 0;
+ }
+
/* Calculate the maxinum number of entries */
for (i = 0; i < ehdr->e_shnum; i++) {
int num_rela = sechdrs[i].sh_size / sizeof(Elf_Rela);
--
2.37.0
Powered by blists - more mailing lists