diff mbox series

ARM: module: Teach unwinder about PLTs

Message ID 20220706163135.53874-1-alexander.sverdlin@nokia.com (mailing list archive)
State New, archived
Headers show
Series ARM: module: Teach unwinder about PLTs | expand

Commit Message

Alexander Sverdlin July 6, 2022, 4:31 p.m. UTC
From: Alexander Sverdlin <alexander.sverdlin@nokia.com>

"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.

Tested-by: Kursad Oney <kursad.oney@broadcom.com>
Link: https://lore.kernel.org/linux-arm-kernel/20200402153845.30985-1-kursad.oney@broadcom.com/
Signed-off-by: Alexander Sverdlin <alexander.sverdlin@nokia.com>
---
 arch/arm/include/asm/module.h |  5 +++++
 arch/arm/kernel/module-plts.c | 14 ++++++++++++++
 arch/arm/kernel/unwind.c      | 13 ++++++++++++-
 3 files changed, 31 insertions(+), 1 deletion(-)

Comments

Florian Fainelli July 6, 2022, 6:09 p.m. UTC | #1
On 7/6/22 09:31, Alexander A Sverdlin wrote:
> From: Alexander Sverdlin <alexander.sverdlin@nokia.com>
> 
> "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.
> 
> Tested-by: Kursad Oney <kursad.oney@broadcom.com>
> Link: https://lore.kernel.org/linux-arm-kernel/20200402153845.30985-1-kursad.oney@broadcom.com/
> Signed-off-by: Alexander Sverdlin <alexander.sverdlin@nokia.com>

I would be inclined to slap a Fixes tag to this patch so we get it back 
ported where appropriate, however it is not clear to me which specific
commit(s) we should be listing here.

Thanks Alexander!
Alexander Sverdlin July 7, 2022, 6:34 a.m. UTC | #2
Hello Florian,

On 06/07/2022 20:09, Florian Fainelli wrote:
>>
>> "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.
>>
>> Tested-by: Kursad Oney <kursad.oney@broadcom.com>
>> Link: https://lore.kernel.org/linux-arm-kernel/20200402153845.30985-1-kursad.oney@broadcom.com/
>> Signed-off-by: Alexander Sverdlin <alexander.sverdlin@nokia.com>
> 
> I would be inclined to slap a Fixes tag to this patch so we get it back ported where appropriate, however it is not clear to me which specific
> commit(s) we should be listing here.

usually I don't hesitate to add "Fixes:" tag and this patch definitely could be ported to some
stable versions, but it's hard to say what it fixes. It's actually a combination of rarely
(if at all) used ARM_MODULE_PLTS functionality and other *debug* features, where unwinder is
used. In very similar case of commit 79f32b221b18c15a98507b101ef4beb52444cc6f
("ARM: 9079/1: ftrace: Add MODULE_PLTS support") I wasn't able to figure out which commit
I'm fixing.

I expect those who use ARM_MODULE_PLT and any kind of debugging to be able to backport the
patch downstream ;)
Alexander Sverdlin Aug. 24, 2022, 1:04 p.m. UTC | #3
Hello Russel,

shall I add this one to your patch tracker?
There is little interest to this patch, but also no complaints, as I can tell.

On 06/07/2022 18:31, Alexander A Sverdlin wrote:
> From: Alexander Sverdlin <alexander.sverdlin@nokia.com>
> 
> "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.
> 
> Tested-by: Kursad Oney <kursad.oney@broadcom.com>
> Link: https://lore.kernel.org/linux-arm-kernel/20200402153845.30985-1-kursad.oney@broadcom.com/
> Signed-off-by: Alexander Sverdlin <alexander.sverdlin@nokia.com>
> ---
>  arch/arm/include/asm/module.h |  5 +++++
>  arch/arm/kernel/module-plts.c | 14 ++++++++++++++
>  arch/arm/kernel/unwind.c      | 13 ++++++++++++-
>  3 files changed, 31 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h
> index 5546c9751478c..07c51a34f77d5 100644
> --- a/arch/arm/include/asm/module.h
> +++ b/arch/arm/include/asm/module.h
> @@ -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
> diff --git a/arch/arm/kernel/module-plts.c b/arch/arm/kernel/module-plts.c
> index 1fc309b41f944..af7c322ebed68 100644
> --- a/arch/arm/kernel/module-plts.c
> +++ b/arch/arm/kernel/module-plts.c
> @@ -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;
> +}
> diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c
> index a37ea6c772cd5..53be7ea6181b3 100644
> --- a/arch/arm/kernel/unwind.c
> +++ b/arch/arm/kernel/unwind.c
> @@ -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;
>  	}
>
Linus Walleij Sept. 16, 2022, 11:15 a.m. UTC | #4
On Wed, Jul 6, 2022 at 6:33 PM Alexander A Sverdlin
<alexander.sverdlin@nokia.com> wrote:

> From: Alexander Sverdlin <alexander.sverdlin@nokia.com>
>
> "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.
>
> Tested-by: Kursad Oney <kursad.oney@broadcom.com>
> Link: https://lore.kernel.org/linux-arm-kernel/20200402153845.30985-1-kursad.oney@broadcom.com/
> Signed-off-by: Alexander Sverdlin <alexander.sverdlin@nokia.com>

This looks correct to me.
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Please add this to Russell's patch tracker.

Yours,
Linus Walleij
diff mbox series

Patch

diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h
index 5546c9751478c..07c51a34f77d5 100644
--- a/arch/arm/include/asm/module.h
+++ b/arch/arm/include/asm/module.h
@@ -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
diff --git a/arch/arm/kernel/module-plts.c b/arch/arm/kernel/module-plts.c
index 1fc309b41f944..af7c322ebed68 100644
--- a/arch/arm/kernel/module-plts.c
+++ b/arch/arm/kernel/module-plts.c
@@ -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;
+}
diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c
index a37ea6c772cd5..53be7ea6181b3 100644
--- a/arch/arm/kernel/unwind.c
+++ b/arch/arm/kernel/unwind.c
@@ -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;
 	}