For EABI stack unwinding, when loading .ko module the EXIDX sections will be added to a unwind_table list. However not all EXIDX sections are added because EXIDX sections are searched by hardcoded section names. For functions in other sections such as .ref.text or .kprobes.text, gcc generates seprated EXIDX sections (such as .ARM.exidx.ref.text or .ARM.exidx.kprobes.text). These extra EXIDX sections are not loaded, so when unwinding functions in these sections, we will failed with: unwind: Index not found xxx To fix that, I refactor the code for searching and adding EXIDX sections: - Check section type to search EXIDX tables (0x70000001) instead of strcmp() the hardcoded names. Then find the corresponding text sections by their section names. - Add a unwind_table list in module->arch to save their own unwind_table instead of the fixed-lenth array. - Save .ARM.exidx.init.text section ptr, because it should be cleaned after module init. Now all EXIDX sections of .ko can be added correctly. Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com> Acked-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
52 lines
1.1 KiB
C
52 lines
1.1 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef _ASM_ARM_MODULE_H
|
|
#define _ASM_ARM_MODULE_H
|
|
|
|
#include <asm-generic/module.h>
|
|
#include <asm/unwind.h>
|
|
|
|
#ifdef CONFIG_ARM_UNWIND
|
|
#define ELF_SECTION_UNWIND 0x70000001
|
|
#endif
|
|
|
|
#define PLT_ENT_STRIDE L1_CACHE_BYTES
|
|
#define PLT_ENT_COUNT (PLT_ENT_STRIDE / sizeof(u32))
|
|
#define PLT_ENT_SIZE (sizeof(struct plt_entries) / PLT_ENT_COUNT)
|
|
|
|
struct plt_entries {
|
|
u32 ldr[PLT_ENT_COUNT];
|
|
u32 lit[PLT_ENT_COUNT];
|
|
};
|
|
|
|
struct mod_plt_sec {
|
|
struct elf32_shdr *plt;
|
|
struct plt_entries *plt_ent;
|
|
int plt_count;
|
|
};
|
|
|
|
struct mod_arch_specific {
|
|
#ifdef CONFIG_ARM_UNWIND
|
|
struct list_head unwind_list;
|
|
struct unwind_table *init_table;
|
|
#endif
|
|
#ifdef CONFIG_ARM_MODULE_PLTS
|
|
struct mod_plt_sec core;
|
|
struct mod_plt_sec init;
|
|
#endif
|
|
};
|
|
|
|
struct module;
|
|
u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val);
|
|
|
|
#ifdef CONFIG_THUMB2_KERNEL
|
|
#define HAVE_ARCH_KALLSYMS_SYMBOL_VALUE
|
|
static inline unsigned long kallsyms_symbol_value(const Elf_Sym *sym)
|
|
{
|
|
if (ELF_ST_TYPE(sym->st_info) == STT_FUNC)
|
|
return sym->st_value & ~1;
|
|
|
|
return sym->st_value;
|
|
}
|
|
#endif
|
|
|
|
#endif /* _ASM_ARM_MODULE_H */
|