%pS always prints an offset, which can look confusing outside of debug output. Add a %ps variant like Linux also has.
Signed-off-by: Ahmad Fatoum <a.fat...@pengutronix.de> --- commands/kallsyms.c | 2 +- common/kallsyms.c | 6 +++++- include/kallsyms.h | 4 +++- lib/vsprintf.c | 14 ++++++++++---- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/commands/kallsyms.c b/commands/kallsyms.c index 163cd99c1079..121d245500f9 100644 --- a/commands/kallsyms.c +++ b/commands/kallsyms.c @@ -22,7 +22,7 @@ static int do_kallsyms(int argc, char *argv[]) if (kstrtoul(argv[1], 16, &addr) == 0) { char sym[KSYM_SYMBOL_LEN]; - sprint_symbol(sym, addr); + sprint_symbol(sym, addr, true); printf("%s\n", sym); return 0; diff --git a/common/kallsyms.c b/common/kallsyms.c index 3c5904f8a833..61eae2794537 100644 --- a/common/kallsyms.c +++ b/common/kallsyms.c @@ -189,7 +189,7 @@ const char *kallsyms_lookup(unsigned long addr, } /* Look up a kernel symbol and return it in a text buffer. */ -int sprint_symbol(char *buffer, unsigned long address) +int sprint_symbol(char *buffer, unsigned long address, bool with_offset) { char *modname; const char *name; @@ -205,12 +205,16 @@ int sprint_symbol(char *buffer, unsigned long address) len = strlen(buffer); buffer += len; + if (!with_offset) + goto out; + if (modname) len += sprintf(buffer, "+%#lx/%#lx [%s]", offset, size, modname); else len += sprintf(buffer, "+%#lx/%#lx", offset, size); +out: return len; } EXPORT_SYMBOL_GPL(sprint_symbol); diff --git a/include/kallsyms.h b/include/kallsyms.h index f61efc9e0c42..c93287302bde 100644 --- a/include/kallsyms.h +++ b/include/kallsyms.h @@ -2,6 +2,8 @@ #ifndef __KALLSYMS_H #define __KALLSYMS_H +#include <linux/types.h> + #define KSYM_NAME_LEN 128 #define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN - 1) + \ 2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + 1) @@ -12,6 +14,6 @@ const char *kallsyms_lookup(unsigned long addr, char **modname, char *namebuf); /* Look up a kernel symbol and return it in a text buffer. */ -int sprint_symbol(char *buffer, unsigned long address); +int sprint_symbol(char *buffer, unsigned long address, bool with_offset); #endif /* __KALLSYMS_H */ diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 32429dd76c23..ba87f6c210d2 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -254,12 +254,12 @@ static char *raw_pointer(char *buf, const char *end, const void *ptr, int field_ #if IN_PROPER static char *symbol_string(char *buf, const char *end, const void *ptr, int field_width, - int precision, int flags) + int precision, int flags, bool with_offset) { unsigned long value = (unsigned long) ptr; #ifdef CONFIG_KALLSYMS char sym[KSYM_SYMBOL_LEN]; - sprint_symbol(sym, value); + sprint_symbol(sym, value, with_offset); return string(buf, end, sym, field_width, precision, flags); #else field_width = 2*sizeof(void *); @@ -484,7 +484,8 @@ char *device_node_string(char *buf, const char *end, const struct device_node *n * * Right now we handle following Linux-compatible format specifiers: * - * - 'S' For symbolic direct pointers + * - 'S' For symbolic direct pointers (or function descriptors) with offset + * - 's' For symbolic direct pointers (or function descriptors) without offset * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form * "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" * Options for %pU are: @@ -523,9 +524,14 @@ char *device_node_string(char *buf, const char *end, const struct device_node *n static char *pointer(const char *fmt, char *buf, const char *end, const void *ptr, int field_width, int precision, int flags) { + bool with_offset = false; + switch (*fmt) { case 'S': - return symbol_string(buf, end, ptr, field_width, precision, flags); + with_offset = true; + fallthrough; + case 's': + return symbol_string(buf, end, ptr, field_width, precision, flags, with_offset); case 'U': if (IS_ENABLED(CONFIG_PRINTF_UUID)) return uuid_string(buf, end, ptr, field_width, precision, flags, fmt); -- 2.39.5