Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

vsprintf: fix %ps on non symbols when using kallsyms

Using %ps in a printk format will sometimes fail silently and print the
empty string if the address passed in does not match a symbol that
kallsyms knows about. But using %pS will fall back to printing the full
address if kallsyms can't find the symbol. Make %ps act the same as %pS
by falling back to printing the address.

While we're here also make %ps print the module that a symbol comes from
so that it matches what %pS already does. Take this simple function for
example (in a module):

static void test_printk(void)
{
int test;
pr_info("with pS: %pS\n", &test);
pr_info("with ps: %ps\n", &test);
}

Before this patch:

with pS: 0xdff7df44
with ps:

After this patch:

with pS: 0xdff7df44
with ps: 0xdff7df44

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Stephen Boyd and committed by
Linus Torvalds
4796dd20 05a6c8a9

+32 -9
+7
include/linux/kallsyms.h
··· 36 36 37 37 /* Look up a kernel symbol and return it in a text buffer. */ 38 38 extern int sprint_symbol(char *buffer, unsigned long address); 39 + extern int sprint_symbol_no_offset(char *buffer, unsigned long address); 39 40 extern int sprint_backtrace(char *buffer, unsigned long address); 40 41 41 42 /* Look up a kernel symbol and print it to the kernel messages. */ ··· 76 75 } 77 76 78 77 static inline int sprint_symbol(char *buffer, unsigned long addr) 78 + { 79 + *buffer = '\0'; 80 + return 0; 81 + } 82 + 83 + static inline int sprint_symbol_no_offset(char *buffer, unsigned long addr) 79 84 { 80 85 *buffer = '\0'; 81 86 return 0;
+24 -8
kernel/kallsyms.c
··· 343 343 344 344 /* Look up a kernel symbol and return it in a text buffer. */ 345 345 static int __sprint_symbol(char *buffer, unsigned long address, 346 - int symbol_offset) 346 + int symbol_offset, int add_offset) 347 347 { 348 348 char *modname; 349 349 const char *name; ··· 358 358 if (name != buffer) 359 359 strcpy(buffer, name); 360 360 len = strlen(buffer); 361 - buffer += len; 362 361 offset -= symbol_offset; 363 362 363 + if (add_offset) 364 + len += sprintf(buffer + len, "+%#lx/%#lx", offset, size); 365 + 364 366 if (modname) 365 - len += sprintf(buffer, "+%#lx/%#lx [%s]", offset, size, modname); 366 - else 367 - len += sprintf(buffer, "+%#lx/%#lx", offset, size); 367 + len += sprintf(buffer + len, " [%s]", modname); 368 368 369 369 return len; 370 370 } ··· 382 382 */ 383 383 int sprint_symbol(char *buffer, unsigned long address) 384 384 { 385 - return __sprint_symbol(buffer, address, 0); 385 + return __sprint_symbol(buffer, address, 0, 1); 386 386 } 387 - 388 387 EXPORT_SYMBOL_GPL(sprint_symbol); 388 + 389 + /** 390 + * sprint_symbol_no_offset - Look up a kernel symbol and return it in a text buffer 391 + * @buffer: buffer to be stored 392 + * @address: address to lookup 393 + * 394 + * This function looks up a kernel symbol with @address and stores its name 395 + * and module name to @buffer if possible. If no symbol was found, just saves 396 + * its @address as is. 397 + * 398 + * This function returns the number of bytes stored in @buffer. 399 + */ 400 + int sprint_symbol_no_offset(char *buffer, unsigned long address) 401 + { 402 + return __sprint_symbol(buffer, address, 0, 0); 403 + } 404 + EXPORT_SYMBOL_GPL(sprint_symbol_no_offset); 389 405 390 406 /** 391 407 * sprint_backtrace - Look up a backtrace symbol and return it in a text buffer ··· 419 403 */ 420 404 int sprint_backtrace(char *buffer, unsigned long address) 421 405 { 422 - return __sprint_symbol(buffer, address, -1); 406 + return __sprint_symbol(buffer, address, -1, 1); 423 407 } 424 408 425 409 /* Look up a kernel symbol and print it to the kernel messages. */
+1 -1
lib/vsprintf.c
··· 436 436 else if (ext != 'f' && ext != 's') 437 437 sprint_symbol(sym, value); 438 438 else 439 - kallsyms_lookup(value, NULL, NULL, NULL, sym); 439 + sprint_symbol_no_offset(sym, value); 440 440 441 441 return string(buf, end, sym, spec); 442 442 #else