[PATCH v3 07/10] lib: vsprintf: implement %pS format specifier
Casey Connolly
casey.connolly at linaro.org
Tue Jul 29 17:50:05 CEST 2025
%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.connolly at 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
More information about the U-Boot
mailing list