mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-22 15:45:09 +07:00
93d77e7f14
Thumb-2 functions have the lowest bit set in the symbol value in the symtab. When kallsyms are generated for the vmlinux, the kallsyms are generated from the output of nm, and nm clears the lowest bit. $ arm-linux-gnueabihf-readelf -a vmlinux | grep show_interrupts 95947: 8015dc89 686 FUNC GLOBAL DEFAULT 2 show_interrupts $ arm-linux-gnueabihf-nm vmlinux | grep show_interrupts 8015dc88 T show_interrupts $ cat /proc/kallsyms | grep show_interrupts 8015dc88 T show_interrupts However, for modules, the kallsyms uses the values in the symbol table without modification, so for functions in modules, the lowest bit is set in kallsyms. $ arm-linux-gnueabihf-readelf -a drivers/net/tun.ko | grep tun_get_socket 333: 00002d4d 36 FUNC GLOBAL DEFAULT 1 tun_get_socket $ arm-linux-gnueabihf-nm drivers/net/tun.ko | grep tun_get_socket 00002d4c T tun_get_socket $ cat /proc/kallsyms | grep tun_get_socket 7f802d4d t tun_get_socket [tun] Because of this, the symbol+offset of the crashing instruction shown in oopses is incorrect when the crash is in a module. For example, given a tun_get_socket which starts like this, 00002d4c <tun_get_socket>: 2d4c: 6943 ldr r3, [r0, #20] 2d4e: 4a07 ldr r2, [pc, #28] 2d50: 4293 cmp r3, r2 a crash when tun_get_socket is called with NULL results in: PC is at tun_xdp+0xa3/0xa4 [tun] pc : [<7f802d4c>] As can be seen, the "PC is at" line reports the wrong symbol name, and the symbol+offset will point to the wrong source line if it is passed to gdb. To solve this, add a way for archs to fixup the reading of these module kallsyms values, and use that to clear the lowest bit for function symbols on Thumb-2. After the fix: # cat /proc/kallsyms | grep tun_get_socket 7f802d4c t tun_get_socket [tun] PC is at tun_get_socket+0x0/0x24 [tun] pc : [<7f802d4c>] Signed-off-by: Vincent Whitchurch <vincent.whitchurch@axis.com> Signed-off-by: Jessica Yu <jeyu@kernel.org>
76 lines
1.6 KiB
C
76 lines
1.6 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef _ASM_ARM_MODULE_H
|
|
#define _ASM_ARM_MODULE_H
|
|
|
|
#include <asm-generic/module.h>
|
|
|
|
struct unwind_table;
|
|
|
|
#ifdef CONFIG_ARM_UNWIND
|
|
enum {
|
|
ARM_SEC_INIT,
|
|
ARM_SEC_DEVINIT,
|
|
ARM_SEC_CORE,
|
|
ARM_SEC_EXIT,
|
|
ARM_SEC_DEVEXIT,
|
|
ARM_SEC_HOT,
|
|
ARM_SEC_UNLIKELY,
|
|
ARM_SEC_MAX,
|
|
};
|
|
#endif
|
|
|
|
struct mod_plt_sec {
|
|
struct elf32_shdr *plt;
|
|
int plt_count;
|
|
};
|
|
|
|
struct mod_arch_specific {
|
|
#ifdef CONFIG_ARM_UNWIND
|
|
struct unwind_table *unwind[ARM_SEC_MAX];
|
|
#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);
|
|
|
|
/*
|
|
* Add the ARM architecture version to the version magic string
|
|
*/
|
|
#define MODULE_ARCH_VERMAGIC_ARMVSN "ARMv" __stringify(__LINUX_ARM_ARCH__) " "
|
|
|
|
/* Add __virt_to_phys patching state as well */
|
|
#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
|
|
#define MODULE_ARCH_VERMAGIC_P2V "p2v8 "
|
|
#else
|
|
#define MODULE_ARCH_VERMAGIC_P2V ""
|
|
#endif
|
|
|
|
/* Add instruction set architecture tag to distinguish ARM/Thumb kernels */
|
|
#ifdef CONFIG_THUMB2_KERNEL
|
|
#define MODULE_ARCH_VERMAGIC_ARMTHUMB "thumb2 "
|
|
#else
|
|
#define MODULE_ARCH_VERMAGIC_ARMTHUMB ""
|
|
#endif
|
|
|
|
#define MODULE_ARCH_VERMAGIC \
|
|
MODULE_ARCH_VERMAGIC_ARMVSN \
|
|
MODULE_ARCH_VERMAGIC_ARMTHUMB \
|
|
MODULE_ARCH_VERMAGIC_P2V
|
|
|
|
#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 */
|