]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ARM: 9252/1: module: Teach unwinder about PLTs
authorAlex Sverdlin <alexander.sverdlin@nokia.com>
Tue, 27 Sep 2022 12:08:37 +0000 (13:08 +0100)
committerRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
Mon, 7 Nov 2022 14:18:59 +0000 (14:18 +0000)
"unwind: Index not found eef26358" warnings keep popping up on
CONFIG_ARM_MODULE_PLTS-enabled systems if the PC points to a PLT veneer.
Teach the unwinder how to deal with them, taking into account they don't
change state of the stack or register file except loading PC.

Link: https://lore.kernel.org/linux-arm-kernel/20200402153845.30985-1-kursad.oney@broadcom.com/
Tested-by: Kursad Oney <kursad.oney@broadcom.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Alexander Sverdlin <alexander.sverdlin@nokia.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
arch/arm/include/asm/module.h
arch/arm/kernel/module-plts.c
arch/arm/kernel/unwind.c

index 5546c9751478c348fb41344073812600afecebc0..07c51a34f77d5fc666237132d3c9d292bbe160b8 100644 (file)
@@ -37,6 +37,11 @@ struct mod_arch_specific {
 
 struct module;
 u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val);
+#ifdef CONFIG_ARM_MODULE_PLTS
+bool in_module_plt(unsigned long loc);
+#else
+static inline bool in_module_plt(unsigned long loc) { return false; }
+#endif
 
 #ifdef CONFIG_THUMB2_KERNEL
 #define HAVE_ARCH_KALLSYMS_SYMBOL_VALUE
index 1fc309b41f9449725db0069165fec8789fce8e91..af7c322ebed68240b523afd585543c6c7742e5c5 100644 (file)
@@ -284,3 +284,17 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
                 mod->arch.core.plt->sh_size, mod->arch.init.plt->sh_size);
        return 0;
 }
+
+bool in_module_plt(unsigned long loc)
+{
+       struct module *mod;
+       bool ret;
+
+       preempt_disable();
+       mod = __module_text_address(loc);
+       ret = mod && (loc - (u32)mod->arch.core.plt_ent < mod->arch.core.plt_count * PLT_ENT_SIZE ||
+                     loc - (u32)mod->arch.init.plt_ent < mod->arch.init.plt_count * PLT_ENT_SIZE);
+       preempt_enable();
+
+       return ret;
+}
index a37ea6c772cd52367163da08fc3dd7fb3775e0d2..53be7ea6181b356604201f821f84086fca304341 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/list.h>
+#include <linux/module.h>
 
 #include <asm/stacktrace.h>
 #include <asm/traps.h>
@@ -395,8 +396,18 @@ int unwind_frame(struct stackframe *frame)
 
        idx = unwind_find_idx(frame->pc);
        if (!idx) {
-               if (frame->pc && kernel_text_address(frame->pc))
+               if (frame->pc && kernel_text_address(frame->pc)) {
+                       if (in_module_plt(frame->pc) && frame->pc != frame->lr) {
+                               /*
+                                * Quoting Ard: Veneers only set PC using a
+                                * PC+immediate LDR, and so they don't affect
+                                * the state of the stack or the register file
+                                */
+                               frame->pc = frame->lr;
+                               return URC_OK;
+                       }
                        pr_warn("unwind: Index not found %08lx\n", frame->pc);
+               }
                return -URC_FAILURE;
        }