Commit 4ab07fd3 authored by Alexander Sverdlin's avatar Alexander Sverdlin Committed by Russell King (Oracle)
Browse files

ARM: 9252/1: module: Teach unwinder about PLTs

"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: default avatarKursad Oney <kursad.oney@broadcom.com>
Reviewed-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarAlexander Sverdlin <alexander.sverdlin@nokia.com>
Signed-off-by: default avatarRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
parent e66372ec
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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
+14 −0
Original line number Diff line number Diff line
@@ -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;
}
+12 −1
Original line number Diff line number Diff line
@@ -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;
	}