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>
51 lines
1.2 KiB
C
51 lines
1.2 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* arch/arm/include/asm/unwind.h
|
|
*
|
|
* Copyright (C) 2008 ARM Limited
|
|
*/
|
|
|
|
#ifndef __ASM_UNWIND_H
|
|
#define __ASM_UNWIND_H
|
|
|
|
#ifndef __ASSEMBLY__
|
|
|
|
/* Unwind reason code according the the ARM EABI documents */
|
|
enum unwind_reason_code {
|
|
URC_OK = 0, /* operation completed successfully */
|
|
URC_CONTINUE_UNWIND = 8,
|
|
URC_FAILURE = 9 /* unspecified failure of some kind */
|
|
};
|
|
|
|
struct unwind_idx {
|
|
unsigned long addr_offset;
|
|
unsigned long insn;
|
|
};
|
|
|
|
struct unwind_table {
|
|
struct list_head list;
|
|
struct list_head mod_list;
|
|
const struct unwind_idx *start;
|
|
const struct unwind_idx *origin;
|
|
const struct unwind_idx *stop;
|
|
unsigned long begin_addr;
|
|
unsigned long end_addr;
|
|
};
|
|
|
|
extern struct unwind_table *unwind_table_add(unsigned long start,
|
|
unsigned long size,
|
|
unsigned long text_addr,
|
|
unsigned long text_size);
|
|
extern void unwind_table_del(struct unwind_table *tab);
|
|
extern void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk,
|
|
const char *loglvl);
|
|
|
|
#endif /* !__ASSEMBLY__ */
|
|
|
|
#ifdef CONFIG_ARM_UNWIND
|
|
#define UNWIND(code...) code
|
|
#else
|
|
#define UNWIND(code...)
|
|
#endif
|
|
|
|
#endif /* __ASM_UNWIND_H */
|