aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNamhyung Kim <namhyung@gmail.com>2011-03-23 22:42:29 -0400
committerIngo Molnar <mingo@elte.hu>2011-03-24 03:36:10 -0400
commit0f77a8d378254f27df4a114a5da67223af1fe93f (patch)
treeedc37c211adce744100d4776e4a28fb868c8b3c0
parentdec2960827c85253d76938dbfa909df3be34958b (diff)
vsprintf: Introduce %pB format specifier
The %pB format specifier is for stack backtrace. Its handler sprint_backtrace() does symbol lookup using (address-1) to ensure the address will not point outside of the function. If there is a tail-call to the function marked "noreturn", gcc optimized out the code after the call then causes saved return address points outside of the function (i.e. the start of the next function), so pollutes call trace somewhat. This patch adds the %pB printk mechanism that allows architecture call-trace printout functions to improve backtrace printouts. Signed-off-by: Namhyung Kim <namhyung@gmail.com> Acked-by: Steven Rostedt <rostedt@goodmis.org> Acked-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: linux-arch@vger.kernel.org LKML-Reference: <1300934550-21394-1-git-send-email-namhyung@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--include/linux/kallsyms.h7
-rw-r--r--kernel/kallsyms.c44
-rw-r--r--lib/vsprintf.c7
3 files changed, 54 insertions, 4 deletions
diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h
index d8e9b3d1c23c..0df513b7a9f8 100644
--- a/include/linux/kallsyms.h
+++ b/include/linux/kallsyms.h
@@ -36,6 +36,7 @@ const char *kallsyms_lookup(unsigned long addr,
36 36
37/* Look up a kernel symbol and return it in a text buffer. */ 37/* Look up a kernel symbol and return it in a text buffer. */
38extern int sprint_symbol(char *buffer, unsigned long address); 38extern int sprint_symbol(char *buffer, unsigned long address);
39extern int sprint_backtrace(char *buffer, unsigned long address);
39 40
40/* Look up a kernel symbol and print it to the kernel messages. */ 41/* Look up a kernel symbol and print it to the kernel messages. */
41extern void __print_symbol(const char *fmt, unsigned long address); 42extern void __print_symbol(const char *fmt, unsigned long address);
@@ -79,6 +80,12 @@ static inline int sprint_symbol(char *buffer, unsigned long addr)
79 return 0; 80 return 0;
80} 81}
81 82
83static inline int sprint_backtrace(char *buffer, unsigned long addr)
84{
85 *buffer = '\0';
86 return 0;
87}
88
82static inline int lookup_symbol_name(unsigned long addr, char *symname) 89static inline int lookup_symbol_name(unsigned long addr, char *symname)
83{ 90{
84 return -ERANGE; 91 return -ERANGE;
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index 6f6d091b5757..59e879929b17 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -342,13 +342,15 @@ int lookup_symbol_attrs(unsigned long addr, unsigned long *size,
342} 342}
343 343
344/* Look up a kernel symbol and return it in a text buffer. */ 344/* Look up a kernel symbol and return it in a text buffer. */
345int sprint_symbol(char *buffer, unsigned long address) 345static int __sprint_symbol(char *buffer, unsigned long address,
346 int symbol_offset)
346{ 347{
347 char *modname; 348 char *modname;
348 const char *name; 349 const char *name;
349 unsigned long offset, size; 350 unsigned long offset, size;
350 int len; 351 int len;
351 352
353 address += symbol_offset;
352 name = kallsyms_lookup(address, &size, &offset, &modname, buffer); 354 name = kallsyms_lookup(address, &size, &offset, &modname, buffer);
353 if (!name) 355 if (!name)
354 return sprintf(buffer, "0x%lx", address); 356 return sprintf(buffer, "0x%lx", address);
@@ -357,17 +359,53 @@ int sprint_symbol(char *buffer, unsigned long address)
357 strcpy(buffer, name); 359 strcpy(buffer, name);
358 len = strlen(buffer); 360 len = strlen(buffer);
359 buffer += len; 361 buffer += len;
362 offset -= symbol_offset;
360 363
361 if (modname) 364 if (modname)
362 len += sprintf(buffer, "+%#lx/%#lx [%s]", 365 len += sprintf(buffer, "+%#lx/%#lx [%s]", offset, size, modname);
363 offset, size, modname);
364 else 366 else
365 len += sprintf(buffer, "+%#lx/%#lx", offset, size); 367 len += sprintf(buffer, "+%#lx/%#lx", offset, size);
366 368
367 return len; 369 return len;
368} 370}
371
372/**
373 * sprint_symbol - Look up a kernel symbol and return it in a text buffer
374 * @buffer: buffer to be stored
375 * @address: address to lookup
376 *
377 * This function looks up a kernel symbol with @address and stores its name,
378 * offset, size and module name to @buffer if possible. If no symbol was found,
379 * just saves its @address as is.
380 *
381 * This function returns the number of bytes stored in @buffer.
382 */
383int sprint_symbol(char *buffer, unsigned long address)
384{
385 return __sprint_symbol(buffer, address, 0);
386}
387
369EXPORT_SYMBOL_GPL(sprint_symbol); 388EXPORT_SYMBOL_GPL(sprint_symbol);
370 389
390/**
391 * sprint_backtrace - Look up a backtrace symbol and return it in a text buffer
392 * @buffer: buffer to be stored
393 * @address: address to lookup
394 *
395 * This function is for stack backtrace and does the same thing as
396 * sprint_symbol() but with modified/decreased @address. If there is a
397 * tail-call to the function marked "noreturn", gcc optimized out code after
398 * the call so that the stack-saved return address could point outside of the
399 * caller. This function ensures that kallsyms will find the original caller
400 * by decreasing @address.
401 *
402 * This function returns the number of bytes stored in @buffer.
403 */
404int sprint_backtrace(char *buffer, unsigned long address)
405{
406 return __sprint_symbol(buffer, address, -1);
407}
408
371/* Look up a kernel symbol and print it to the kernel messages. */ 409/* Look up a kernel symbol and print it to the kernel messages. */
372void __print_symbol(const char *fmt, unsigned long address) 410void __print_symbol(const char *fmt, unsigned long address)
373{ 411{
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index d3023df8477f..d9e01fc3168e 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -574,7 +574,9 @@ char *symbol_string(char *buf, char *end, void *ptr,
574 unsigned long value = (unsigned long) ptr; 574 unsigned long value = (unsigned long) ptr;
575#ifdef CONFIG_KALLSYMS 575#ifdef CONFIG_KALLSYMS
576 char sym[KSYM_SYMBOL_LEN]; 576 char sym[KSYM_SYMBOL_LEN];
577 if (ext != 'f' && ext != 's') 577 if (ext == 'B')
578 sprint_backtrace(sym, value);
579 else if (ext != 'f' && ext != 's')
578 sprint_symbol(sym, value); 580 sprint_symbol(sym, value);
579 else 581 else
580 kallsyms_lookup(value, NULL, NULL, NULL, sym); 582 kallsyms_lookup(value, NULL, NULL, NULL, sym);
@@ -949,6 +951,7 @@ int kptr_restrict = 1;
949 * - 'f' For simple symbolic function names without offset 951 * - 'f' For simple symbolic function names without offset
950 * - 'S' For symbolic direct pointers with offset 952 * - 'S' For symbolic direct pointers with offset
951 * - 's' For symbolic direct pointers without offset 953 * - 's' For symbolic direct pointers without offset
954 * - 'B' For backtraced symbolic direct pointers with offset
952 * - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref] 955 * - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref]
953 * - 'r' For raw struct resource, e.g., [mem 0x0-0x1f flags 0x201] 956 * - 'r' For raw struct resource, e.g., [mem 0x0-0x1f flags 0x201]
954 * - 'M' For a 6-byte MAC address, it prints the address in the 957 * - 'M' For a 6-byte MAC address, it prints the address in the
@@ -1008,6 +1011,7 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
1008 /* Fallthrough */ 1011 /* Fallthrough */
1009 case 'S': 1012 case 'S':
1010 case 's': 1013 case 's':
1014 case 'B':
1011 return symbol_string(buf, end, ptr, spec, *fmt); 1015 return symbol_string(buf, end, ptr, spec, *fmt);
1012 case 'R': 1016 case 'R':
1013 case 'r': 1017 case 'r':
@@ -1279,6 +1283,7 @@ qualifier:
1279 * %ps output the name of a text symbol without offset 1283 * %ps output the name of a text symbol without offset
1280 * %pF output the name of a function pointer with its offset 1284 * %pF output the name of a function pointer with its offset
1281 * %pf output the name of a function pointer without its offset 1285 * %pf output the name of a function pointer without its offset
1286 * %pB output the name of a backtrace symbol with its offset
1282 * %pR output the address range in a struct resource with decoded flags 1287 * %pR output the address range in a struct resource with decoded flags
1283 * %pr output the address range in a struct resource with raw flags 1288 * %pr output the address range in a struct resource with raw flags
1284 * %pM output a 6-byte MAC address with colons 1289 * %pM output a 6-byte MAC address with colons