[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220722022416.137548-2-mfo@canonical.com>
Date: Thu, 21 Jul 2022 23:24:11 -0300
From: Mauricio Faria de Oliveira <mfo@...onical.com>
To: linux-kernel@...r.kernel.org, linux-modules@...r.kernel.org,
linux-kbuild@...r.kernel.org, linux-fsdevel@...r.kernel.org
Cc: Masahiro Yamada <masahiroy@...nel.org>,
Michal Marek <michal.lkml@...kovi.net>,
Nick Desaulniers <ndesaulniers@...gle.com>,
Luis Chamberlain <mcgrof@...nel.org>,
Kees Cook <keescook@...omium.org>,
Iurii Zaikin <yzaikin@...gle.com>
Subject: [RFC PATCH 1/6] modpost: factor out elf/arch-specific code from section_rel[a]()
There's elf/arch-specific code identical in both functions, with some
in section_rel() only.
In order to factor that out, generalize the different relocation types
Elf_Rela/Elf_Rel (relocation with/without an addend) with the Elf_Rela
type, that is just Elf_Rel with a '.r_addend' field.
Most of this code only uses Elf_Rel fields ('.r_offset' and '.r_info').
Make usage of '.r_addend' conditional on section header type SHT_RELA.
(Note, though, that '.r_addend' is used on SHT_REL in some archs/formats
for the _output_ relocation entry, but this is fine and existing code.)
This change also seems to help with readability of section_rel[a]().
Signed-off-by: Mauricio Faria de Oliveira <mfo@...onical.com>
---
scripts/mod/modpost.c | 141 +++++++++++++++++++++++++-----------------
1 file changed, 84 insertions(+), 57 deletions(-)
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index a0f59d7a8875..4c1038dccae0 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -1716,13 +1716,90 @@ static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
#define R_RISCV_SUB32 39
#endif
+/*
+ * RelX: refers to usage of Elf_Rela or Elf_Rel interchangeably where possible.
+ *
+ * The usage of Elf_Rela (relocation with an addend) even for Elf_Rel (without)
+ * as an input parameter is possible for .r_offset and .r_info (same offset on
+ * both struct types) *BUT* .r_addend can ONLY be accessed on SHT_RELA headers
+ * (i.e., where it is valid in the input).
+ *
+ * Note: .r_addend on SHT_REL is calculated/accessed for the _output_ parameter,
+ * via the addend_ARCH_rel() functions, but that is fine, as it's not the input.
+ *
+ * Return value 1 indicates to skip further processing on this relocation entry.
+ *
+ * Output parameters:
+ * - 'r' is the relocation entry (i.e., replace data at 'r.r_offset' in section
+ * w/ header 'sechdr' w/ data from symbol w/ symbol table index in 'r.r_info',
+ * w/ possible relocation addend 'r.r_addend').
+ * - 'sym' is that symbol (a pointer to the symbol table + symbol table index).
+ */
+static int get_relx_sym(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *rela,
+ Elf_Rela *out_r, Elf_Sym **out_sym)
+{
+ Elf_Sym *sym;
+ Elf_Rela r;
+ unsigned int r_sym;
+
+ /* Get .r_offset/.r_info and r_sym */
+ r.r_offset = TO_NATIVE(rela->r_offset);
+#if KERNEL_ELFCLASS == ELFCLASS64
+ if (elf->hdr->e_machine == EM_MIPS) {
+ unsigned int r_typ;
+
+ r_sym = ELF64_MIPS_R_SYM(rela->r_info);
+ r_sym = TO_NATIVE(r_sym);
+ r_typ = ELF64_MIPS_R_TYPE(rela->r_info);
+ r.r_info = ELF64_R_INFO(r_sym, r_typ);
+ } else {
+ r.r_info = TO_NATIVE(rela->r_info);
+ r_sym = ELF_R_SYM(r.r_info);
+ }
+#else
+ r.r_info = TO_NATIVE(rela->r_info);
+ r_sym = ELF_R_SYM(r.r_info);
+#endif
+
+ /* Get .r_addend (only output on SHT_REL) */
+ if (sechdr->sh_type == SHT_RELA) {
+ r.r_addend = TO_NATIVE(rela->r_addend);
+ } else if (sechdr->sh_type == SHT_REL) {
+ r.r_addend = 0;
+ switch (elf->hdr->e_machine) {
+ case EM_386:
+ if (addend_386_rel(elf, sechdr, &r))
+ return 1;
+ break;
+ case EM_ARM:
+ if (addend_arm_rel(elf, sechdr, &r))
+ return 1;
+ break;
+ case EM_MIPS:
+ if (addend_mips_rel(elf, sechdr, &r))
+ return 1;
+ break;
+ }
+ }
+
+ sym = elf->symtab_start + r_sym;
+
+ /* Skip special sections */
+ if (is_shndx_special(sym->st_shndx))
+ return 1;
+
+ /* Done */
+ *out_r = r;
+ *out_sym = sym;
+ return 0;
+}
+
static void section_rela(const char *modname, struct elf_info *elf,
Elf_Shdr *sechdr)
{
Elf_Sym *sym;
Elf_Rela *rela;
Elf_Rela r;
- unsigned int r_sym;
const char *fromsec;
Elf_Rela *start = (void *)elf->hdr + sechdr->sh_offset;
@@ -1735,23 +1812,9 @@ static void section_rela(const char *modname, struct elf_info *elf,
return;
for (rela = start; rela < stop; rela++) {
- r.r_offset = TO_NATIVE(rela->r_offset);
-#if KERNEL_ELFCLASS == ELFCLASS64
- if (elf->hdr->e_machine == EM_MIPS) {
- unsigned int r_typ;
- r_sym = ELF64_MIPS_R_SYM(rela->r_info);
- r_sym = TO_NATIVE(r_sym);
- r_typ = ELF64_MIPS_R_TYPE(rela->r_info);
- r.r_info = ELF64_R_INFO(r_sym, r_typ);
- } else {
- r.r_info = TO_NATIVE(rela->r_info);
- r_sym = ELF_R_SYM(r.r_info);
- }
-#else
- r.r_info = TO_NATIVE(rela->r_info);
- r_sym = ELF_R_SYM(r.r_info);
-#endif
- r.r_addend = TO_NATIVE(rela->r_addend);
+ if (get_relx_sym(elf, sechdr, rela, &r, &sym))
+ continue;
+
switch (elf->hdr->e_machine) {
case EM_RISCV:
if (!strcmp("__ex_table", fromsec) &&
@@ -1759,10 +1822,7 @@ static void section_rela(const char *modname, struct elf_info *elf,
continue;
break;
}
- sym = elf->symtab_start + r_sym;
- /* Skip special sections */
- if (is_shndx_special(sym->st_shndx))
- continue;
+
if (is_second_extable_reloc(start, rela, fromsec))
find_extable_entry_size(fromsec, &r);
check_section_mismatch(modname, elf, &r, sym, fromsec);
@@ -1775,7 +1835,6 @@ static void section_rel(const char *modname, struct elf_info *elf,
Elf_Sym *sym;
Elf_Rel *rel;
Elf_Rela r;
- unsigned int r_sym;
const char *fromsec;
Elf_Rel *start = (void *)elf->hdr + sechdr->sh_offset;
@@ -1788,41 +1847,9 @@ static void section_rel(const char *modname, struct elf_info *elf,
return;
for (rel = start; rel < stop; rel++) {
- r.r_offset = TO_NATIVE(rel->r_offset);
-#if KERNEL_ELFCLASS == ELFCLASS64
- if (elf->hdr->e_machine == EM_MIPS) {
- unsigned int r_typ;
- r_sym = ELF64_MIPS_R_SYM(rel->r_info);
- r_sym = TO_NATIVE(r_sym);
- r_typ = ELF64_MIPS_R_TYPE(rel->r_info);
- r.r_info = ELF64_R_INFO(r_sym, r_typ);
- } else {
- r.r_info = TO_NATIVE(rel->r_info);
- r_sym = ELF_R_SYM(r.r_info);
- }
-#else
- r.r_info = TO_NATIVE(rel->r_info);
- r_sym = ELF_R_SYM(r.r_info);
-#endif
- r.r_addend = 0;
- switch (elf->hdr->e_machine) {
- case EM_386:
- if (addend_386_rel(elf, sechdr, &r))
- continue;
- break;
- case EM_ARM:
- if (addend_arm_rel(elf, sechdr, &r))
- continue;
- break;
- case EM_MIPS:
- if (addend_mips_rel(elf, sechdr, &r))
- continue;
- break;
- }
- sym = elf->symtab_start + r_sym;
- /* Skip special sections */
- if (is_shndx_special(sym->st_shndx))
+ if (get_relx_sym(elf, sechdr, (Elf_Rela *)rel, &r, &sym)
continue;
+
if (is_second_extable_reloc(start, rel, fromsec))
find_extable_entry_size(fromsec, &r);
check_section_mismatch(modname, elf, &r, sym, fromsec);
--
2.25.1
Powered by blists - more mailing lists