All of lore.kernel.org
 help / color / mirror / Atom feed
From: Xi Ruoyao <xry111@xry111.site>
To: loongarch@lists.linux.dev
Cc: linux-kernel@vger.kernel.org, WANG Xuerui <kernel@xen0n.name>,
	Huacai Chen <chenhuacai@kernel.org>
Subject: [PATCH 1/5] LoongArch: Add section of GOT for kernel module
Date: Thu, 28 Jul 2022 00:26:19 +0800	[thread overview]
Message-ID: <3f43d51d530344f73a0a7087407799ff9dff3ba8.camel@xry111.site> (raw)
In-Reply-To: <385f63bcbee8e37c42f479ce9cdc7e7d731d419b.camel@xry111.site>

The address of external symbols will locate more than 32-bit offset.  We
were using the `-Wa,-mla-global-with-abs` and `-Wa,-mla-local-with-abs`
to prevent the compiler and assembler from generating GOT relocations,
but these options are undocumented hacks and do not work anymore with
GAS 2.40 and GCC 13.

Let the module loader emit GOT entries for data symbols so we would be
able to handle GOT relocations.  The GOT entry is just the data symbol
address.

Signed-off-by: Xi Ruoyao <xry111@xry111.site>
---
 arch/loongarch/include/asm/module.h     | 23 +++++++++++++
 arch/loongarch/include/asm/module.lds.h |  1 +
 arch/loongarch/kernel/module-sections.c | 43 ++++++++++++++++++++++---
 3 files changed, 63 insertions(+), 4 deletions(-)

diff --git a/arch/loongarch/include/asm/module.h b/arch/loongarch/include/asm/module.h
index 9f6718df1854..76a98a0ab8a0 100644
--- a/arch/loongarch/include/asm/module.h
+++ b/arch/loongarch/include/asm/module.h
@@ -19,6 +19,7 @@ struct mod_section {
 struct mod_arch_specific {
 	struct mod_section plt;
 	struct mod_section plt_idx;
+	struct mod_section got;
 };
 
 struct plt_entry {
@@ -28,11 +29,16 @@ struct plt_entry {
 	u32 inst_jirl;
 };
 
+struct got_entry {
+	Elf_Addr symbol_addr;
+};
+
 struct plt_idx_entry {
 	unsigned long symbol_addr;
 };
 
 Elf_Addr module_emit_plt_entry(struct module *mod, unsigned long val);
+Elf_Addr module_emit_got_entry(struct module *mod, Elf_Addr val);
 
 static inline struct plt_entry emit_plt_entry(unsigned long val)
 {
@@ -51,6 +57,11 @@ static inline struct plt_idx_entry emit_plt_idx_entry(unsigned long val)
 	return (struct plt_idx_entry) { val };
 }
 
+static inline struct got_entry emit_got_entry(Elf_Addr val)
+{
+	return (struct got_entry) { val };
+}
+
 static inline int get_plt_idx(unsigned long val, const struct mod_section *sec)
 {
 	int i;
@@ -77,4 +88,16 @@ static inline struct plt_entry *get_plt_entry(unsigned long val,
 	return plt + plt_idx;
 }
 
+static inline struct got_entry *get_got_entry(Elf_Addr val,
+					      const struct mod_section *sec)
+{
+	struct got_entry *got = (struct got_entry *)sec->shdr->sh_addr;
+	int i;
+
+	for (i = 0; i < sec->num_entries; i++)
+		if (got[i].symbol_addr == val)
+			return &got[i];
+	return NULL;
+}
+
 #endif /* _ASM_MODULE_H */
diff --git a/arch/loongarch/include/asm/module.lds.h b/arch/loongarch/include/asm/module.lds.h
index 31c1c0db11a3..57bbd0cedd26 100644
--- a/arch/loongarch/include/asm/module.lds.h
+++ b/arch/loongarch/include/asm/module.lds.h
@@ -4,4 +4,5 @@ SECTIONS {
 	. = ALIGN(4);
 	.plt : { BYTE(0) }
 	.plt.idx : { BYTE(0) }
+	.got : { BYTE(0) }
 }
diff --git a/arch/loongarch/kernel/module-sections.c b/arch/loongarch/kernel/module-sections.c
index 6d498288977d..509c0b86b1e9 100644
--- a/arch/loongarch/kernel/module-sections.c
+++ b/arch/loongarch/kernel/module-sections.c
@@ -33,6 +33,25 @@ Elf_Addr module_emit_plt_entry(struct module *mod, unsigned long val)
 	return (Elf_Addr)&plt[nr];
 }
 
+Elf_Addr module_emit_got_entry(struct module *mod, Elf_Addr val)
+{
+	struct mod_section *got_sec = &mod->arch.got;
+	int i = got_sec->num_entries;
+	struct got_entry *got = get_got_entry(val, got_sec);
+
+	if (got)
+		return (Elf_Addr)got;
+
+	/* There is no GOT entry existing for val yet.  Create a new one.  */
+	got = (struct got_entry *)got_sec->shdr->sh_addr;
+	got[i] = emit_got_entry(val);
+
+	got_sec->num_entries++;
+	BUG_ON(got_sec->num_entries > got_sec->max_entries);
+
+	return (Elf_Addr)&got[i];
+}
+
 static int is_rela_equal(const Elf_Rela *x, const Elf_Rela *y)
 {
 	return x->r_info == y->r_info && x->r_addend == y->r_addend;
@@ -50,7 +69,8 @@ static bool duplicate_rela(const Elf_Rela *rela, int idx)
 	return false;
 }
 
-static void count_max_entries(Elf_Rela *relas, int num, unsigned int *plts)
+static void count_max_entries(Elf_Rela *relas, int num,
+			      unsigned int *plts, unsigned int *gots)
 {
 	unsigned int i, type;
 
@@ -59,14 +79,16 @@ static void count_max_entries(Elf_Rela *relas, int num, unsigned int *plts)
 		if (type == R_LARCH_SOP_PUSH_PLT_PCREL) {
 			if (!duplicate_rela(relas, i))
 				(*plts)++;
-		}
+		} else if (type == R_LARCH_SOP_PUSH_GPREL)
+			if (!duplicate_rela(relas, i))
+				(*gots)++;
 	}
 }
 
 int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
 			      char *secstrings, struct module *mod)
 {
-	unsigned int i, num_plts = 0;
+	unsigned int i, num_plts = 0, num_gots = 0;
 
 	/*
 	 * Find the empty .plt sections.
@@ -76,6 +98,8 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
 			mod->arch.plt.shdr = sechdrs + i;
 		else if (!strcmp(secstrings + sechdrs[i].sh_name, ".plt.idx"))
 			mod->arch.plt_idx.shdr = sechdrs + i;
+		else if (!strcmp(secstrings + sechdrs[i].sh_name, ".got"))
+			mod->arch.got.shdr = sechdrs + i;
 	}
 
 	if (!mod->arch.plt.shdr) {
@@ -86,6 +110,10 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
 		pr_err("%s: module PLT.IDX section(s) missing\n", mod->name);
 		return -ENOEXEC;
 	}
+	if (!mod->arch.got.shdr) {
+		pr_err("%s: module GOT section(s) missing\n", mod->name);
+		return -ENOEXEC;
+	}
 
 	/* Calculate the maxinum number of entries */
 	for (i = 0; i < ehdr->e_shnum; i++) {
@@ -100,7 +128,7 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
 		if (!(dst_sec->sh_flags & SHF_EXECINSTR))
 			continue;
 
-		count_max_entries(relas, num_rela, &num_plts);
+		count_max_entries(relas, num_rela, &num_plts, &num_gots);
 	}
 
 	mod->arch.plt.shdr->sh_type = SHT_NOBITS;
@@ -117,5 +145,12 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
 	mod->arch.plt_idx.num_entries = 0;
 	mod->arch.plt_idx.max_entries = num_plts;
 
+	mod->arch.got.shdr->sh_type = SHT_NOBITS;
+	mod->arch.got.shdr->sh_flags = SHF_ALLOC;
+	mod->arch.got.shdr->sh_addralign = L1_CACHE_BYTES;
+	mod->arch.got.shdr->sh_size = (num_plts + 1) * sizeof(struct plt_entry);
+	mod->arch.got.num_entries = 0;
+	mod->arch.got.max_entries = num_plts;
+
 	return 0;
 }
-- 
2.37.0



  reply	other threads:[~2022-07-27 16:26 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-07-27 16:24 [PATCH 0/5] LoongArch: Support new relocation types Xi Ruoyao
2022-07-27 16:26 ` Xi Ruoyao [this message]
     [not found]   ` <849f514e-f78a-72a2-b94e-6974074b75eb@loongson.cn>
2022-07-28  9:02     ` [PATCH 1/5] LoongArch: Add section of GOT for kernel module Xi Ruoyao
2022-07-28  9:21       ` Youling Tang
2022-07-28 10:53         ` Xi Ruoyao
2022-07-27 16:27 ` [PATCH 2/5] LoongArch: Support R_LARCH_SOP_PUSH_GPREL relocation type in " Xi Ruoyao
2022-07-27 16:28 ` [PATCH 3/5] LoongArch: Support relocation against _GLOBAL_OFFSET_TABLE_ Xi Ruoyao
2022-07-28  1:02   ` Jinyang He
2022-07-28  6:41     ` Xi Ruoyao
2022-07-28  9:14       ` Jinyang He
2022-07-28 10:57         ` Xi Ruoyao
2022-07-28 11:21           ` Jinyang He
2022-07-27 16:29 ` [PATCH 4/5] LoongArch: Stop using undocumented assembler options Xi Ruoyao
2022-07-28  9:46   ` Youling Tang
2022-07-28 10:58     ` Xi Ruoyao
2022-07-27 16:31 ` [PATCH 5/5] LoongArch: Support modules with new relocation types Xi Ruoyao
2022-07-27 16:46 ` [PATCH 0/5] LoongArch: Support " Xi Ruoyao

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3f43d51d530344f73a0a7087407799ff9dff3ba8.camel@xry111.site \
    --to=xry111@xry111.site \
    --cc=chenhuacai@kernel.org \
    --cc=kernel@xen0n.name \
    --cc=linux-kernel@vger.kernel.org \
    --cc=loongarch@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.