%pS is a kernel extension for printing the name and offset of a symbol. This is useful for function pointers/callbacks especially. When symbol lookup is enabled this can make for much easier debugging of driver ops and other places.
Signed-off-by: Casey Connolly <casey.conno...@linaro.org> --- lib/vsprintf.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index c7340a047b2e9385b9366d90e1363c99882db398..11cc3e6c0e9abd0440b76219b0d56056345ddd7f 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -24,8 +24,9 @@ #include <linux/ctype.h> #include <linux/err.h> #include <linux/types.h> #include <linux/string.h> +#include <symbols.h> /* we use this so that we can do without the ctype library */ #define is_digit(c) ((c) >= '0' && (c) <= '9') @@ -437,8 +438,25 @@ static char *uuid_string(char *buf, char *end, u8 *addr, int field_width, return string(buf, end, uuid, field_width, precision, flags); } #endif +/* + * Given an address, print the symbol name and offset to the address. + */ +static char *ptr_symbol(phys_addr_t addr, char *buf, char *end, + int field_width, int precision, int flags) +{ + unsigned long offset; + char namebuf[KSYM_NAME_LEN + 1] = { 0 }; + + symbol_lookup(addr, NULL, &offset, namebuf); + + strlcat(namebuf, "+0x", KSYM_NAME_LEN + 1); + + buf = string(buf, end, namebuf, field_width, precision, flags); + return number(buf, end, offset, 16, field_width, precision, flags); +} + /* * Show a '%p' thing. A kernel extension is that the '%p' is followed * by an extra set of alphanumeric characters that are extended format * specifiers. @@ -450,8 +468,9 @@ static char *uuid_string(char *buf, char *end, u8 *addr, int field_width, * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way (dot-separated * decimal for v4 and colon separated network-order 16 bit hex for v6) * - 'i' [46] for 'raw' IPv4/IPv6 addresses, IPv6 omits the colons, IPv4 is * currently the same + * - 'S' for a symbol address, it prints the symbol name and offset */ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field_width, int precision, int flags) { @@ -502,8 +521,14 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, return ip4_addr_string(buf, end, ptr, field_width, precision, flags); flags &= ~SPECIAL; break; + case 'S': + if (IS_ENABLED(CONFIG_SYMBOL_LOOKUP)) + return ptr_symbol((phys_addr_t)ptr, buf, end, + field_width, precision, flags); + flags |= SPECIAL; + break; #ifdef CONFIG_LIB_UUID case 'U': return uuid_string(buf, end, ptr, field_width, precision, flags, fmt); -- 2.50.0