with commit '82b37e632513 ("kallsyms: print module name in %ps/S case when KALLSYMS is disabled"), module name printing was enhanced. As per suggestion from Petr Mladek <pmladek@xxxxxxxx>, covering other flavours also to print build id also. for %pB no change as it needs to know symbol name to adjust address value which can't be done without KALLSYMS. original output with KALLSYMS: [8.842129] ps function_1 [crash] [8.842735] pS function_1+0x4/0x2c [crash] [8.842890] pSb function_1+0x4/0x2c [crash b367e79021b9f3b0172f9a36d4261c1f528ca1b3] [8.843175] pB function_1+0x4/0x2c [crash] [8.843362] pBb function_1+0x4/0x2c [crash b367e79021b9f3b0172f9a36d4261c1f528ca1b3] original output without KALLSYMS: [12.487424] ps 0xffff800000eb008c [12.487598] pS 0xffff800000eb008c [12.487723] pSb 0xffff800000eb008c [12.487850] pB 0xffff800000eb008c [12.487967] pBb 0xffff800000eb008c With patched kernel without KALLSYMS: [9.205207] ps 0xffff800000eb008c [crash] [9.205564] pS 0xffff800000eb0000+0x8c [crash] [9.205757] pSb 0xffff800000eb0000+0x8c [crash b367e79021b9f3b0172f9a36d4261c1f528ca1b3] [9.206066] pB 0xffff800000eb0000+0x8c [crash] [9.206257] pBb 0xffff800000eb0000+0x8c [crash b367e79021b9f3b0172f9a36d4261c1f528ca1b3] Suggested-by: Petr Mladek <pmladek@xxxxxxxx> Co-developed-by: Vaneet Narang <v.narang@xxxxxxxxxxx> Signed-off-by: Vaneet Narang <v.narang@xxxxxxxxxxx> Signed-off-by: Maninder Singh <maninder1.s@xxxxxxxxxxx> --- earlier discussion: https://lkml.org/lkml/2022/2/10/185 include/linux/kallsyms.h | 27 -------------- kernel/module.c | 4 +-- lib/vsprintf.c | 76 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 76 insertions(+), 31 deletions(-) diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h index ebfeb6099c28..5fb17dd4b6fa 100644 --- a/include/linux/kallsyms.h +++ b/include/linux/kallsyms.h @@ -163,33 +163,6 @@ static inline bool kallsyms_show_value(const struct cred *cred) return false; } -#ifdef CONFIG_MODULES -static inline int fill_minimal_module_info(char *sym, int size, unsigned long value) -{ - struct module *mod; - unsigned long offset; - int ret = 0; - - preempt_disable(); - mod = __module_address(value); - if (mod) { - offset = value - (unsigned long)mod->core_layout.base; - snprintf(sym, size - 1, "0x%lx+0x%lx [%s]", - (unsigned long)mod->core_layout.base, offset, mod->name); - - sym[size - 1] = '\0'; - ret = 1; - } - - preempt_enable(); - return ret; -} -#else -static inline int fill_minimal_module_info(char *sym, int size, unsigned long value) -{ - return 0; -} -#endif /*CONFIG_MODULES*/ #endif /*CONFIG_KALLSYMS*/ static inline void print_ip_sym(const char *loglvl, unsigned long ip) diff --git a/kernel/module.c b/kernel/module.c index 46a5c2ed1928..ccccb135c7fe 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1465,12 +1465,10 @@ resolve_symbol_wait(struct module *mod, return ksym; } -#ifdef CONFIG_KALLSYMS static inline bool sect_empty(const Elf_Shdr *sect) { return !(sect->sh_flags & SHF_ALLOC) || sect->sh_size == 0; } -#endif /* * /sys/module/foo/sections stuff @@ -2799,7 +2797,7 @@ static void add_kallsyms(struct module *mod, const struct load_info *info) } #endif /* CONFIG_KALLSYMS */ -#if IS_ENABLED(CONFIG_KALLSYMS) && IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) +#if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) static void init_build_id(struct module *mod, const struct load_info *info) { const Elf_Shdr *sechdr; diff --git a/lib/vsprintf.c b/lib/vsprintf.c index cb7345ff57f3..d4a24fd29494 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -980,6 +980,80 @@ char *bdev_name(char *buf, char *end, struct block_device *bdev, } #endif +#if !defined(CONFIG_KALLSYMS) && defined(CONFIG_MODULES) +static int sprint_module_info(char *buf, char *end, unsigned long value, + const char *fmt) +{ + struct module *mod; + unsigned long offset = 1; + unsigned long base; + int ret = 0; + const char *modname; + int modbuildid = 0; + int len; +#if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) + const unsigned char *buildid = NULL; +#endif + + if (is_ksym_addr(value)) + return 0; + + if (*fmt == 'B' && fmt[1] == 'b') + modbuildid = 1; + else if (*fmt == 'S' && (fmt[1] == 'b' || (fmt[1] == 'R' && fmt[2] == 'b'))) + modbuildid = 1; + else if (*fmt != 's') { + /* + * do nothing. + */ + } else + offset = 0; + + preempt_disable(); + mod = __module_address(value); + if (mod) { + ret = 1; + modname = mod->name; +#if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) + if (modbuildid) + buildid = mod->build_id; +#endif + if (offset) { + base = (unsigned long)mod->core_layout.base; + offset = value - base; + } + } + + preempt_enable(); + if (!ret) + return 0; + + /* address belongs to module */ + if (offset) + len = sprintf(buf, "0x%lx+0x%lx", base, offset); + else + len = sprintf(buf, "0x%lx", value); + + len += sprintf(buf + len, " [%s", modname); +#if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) + if (modbuildid && buildid) { + /* build ID should match length of sprintf */ + static_assert(sizeof(typeof_member(struct module, build_id)) == 20); + len += sprintf(buf + len, " %20phN", buildid); + } +#endif + len += sprintf(buf + len, "]"); + + return len; +} +#else +static inline int sprint_module_info(char *buf, char *end, unsigned long value, + const char *fmt) +{ + return 0; +} +#endif + static noinline_for_stack char *symbol_string(char *buf, char *end, void *ptr, struct printf_spec spec, const char *fmt) @@ -1005,7 +1079,7 @@ char *symbol_string(char *buf, char *end, void *ptr, return string_nocheck(buf, end, sym, spec); #else - if (fill_minimal_module_info(sym, KSYM_SYMBOL_LEN, value)) + if (sprint_module_info(sym, end, value, fmt)) return string_nocheck(buf, end, sym, spec); return special_hex_number(buf, end, value, sizeof(void *)); -- 2.17.1