aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/printk-formats.txt35
-rw-r--r--include/linux/kallsyms.h54
-rw-r--r--kernel/kallsyms.c35
-rw-r--r--lib/vsprintf.c5
4 files changed, 68 insertions, 61 deletions
diff --git a/Documentation/printk-formats.txt b/Documentation/printk-formats.txt
index 361789df51ec..58c44cce90b6 100644
--- a/Documentation/printk-formats.txt
+++ b/Documentation/printk-formats.txt
@@ -50,42 +50,31 @@ Symbols/Function Pointers
50 50
51:: 51::
52 52
53 %pS versatile_init+0x0/0x110
54 %ps versatile_init
53 %pF versatile_init+0x0/0x110 55 %pF versatile_init+0x0/0x110
54 %pf versatile_init 56 %pf versatile_init
55 %pS versatile_init+0x0/0x110
56 %pSR versatile_init+0x9/0x110 57 %pSR versatile_init+0x9/0x110
57 (with __builtin_extract_return_addr() translation) 58 (with __builtin_extract_return_addr() translation)
58 %ps versatile_init
59 %pB prev_fn_of_versatile_init+0x88/0x88 59 %pB prev_fn_of_versatile_init+0x88/0x88
60 60
61The ``F`` and ``f`` specifiers are for printing function pointers, 61The ``S`` and ``s`` specifiers are used for printing a pointer in symbolic
62for example, f->func, &gettimeofday. They have the same result as 62format. They result in the symbol name with (``S``) or without (``s``)
63``S`` and ``s`` specifiers. But they do an extra conversion on 63offsets. If KALLSYMS are disabled then the symbol address is printed instead.
64ia64, ppc64 and parisc64 architectures where the function pointers
65are actually function descriptors.
66 64
67The ``S`` and ``s`` specifiers can be used for printing symbols 65Note, that the ``F`` and ``f`` specifiers are identical to ``S`` (``s``)
68from direct addresses, for example, __builtin_return_address(0), 66and thus deprecated. We have ``F`` and ``f`` because on ia64, ppc64 and
69(void *)regs->ip. They result in the symbol name with (``S``) or 67parisc64 function pointers are indirect and, in fact, are function
70without (``s``) offsets. If KALLSYMS are disabled then the symbol 68descriptors, which require additional dereferencing before we can lookup
71address is printed instead. 69the symbol. As of now, ``S`` and ``s`` perform dereferencing on those
70platforms (when needed), so ``F`` and ``f`` exist for compatibility
71reasons only.
72 72
73The ``B`` specifier results in the symbol name with offsets and should be 73The ``B`` specifier results in the symbol name with offsets and should be
74used when printing stack backtraces. The specifier takes into 74used when printing stack backtraces. The specifier takes into
75consideration the effect of compiler optimisations which may occur 75consideration the effect of compiler optimisations which may occur
76when tail-call``s are used and marked with the noreturn GCC attribute. 76when tail-call``s are used and marked with the noreturn GCC attribute.
77 77
78Examples::
79
80 printk("Going to call: %pF\n", gettimeofday);
81 printk("Going to call: %pF\n", p->func);
82 printk("%s: called from %pS\n", __func__, (void *)_RET_IP_);
83 printk("%s: called from %pS\n", __func__,
84 (void *)__builtin_return_address(0));
85 printk("Faulted at %pS\n", (void *)regs->ip);
86 printk(" %s%pB\n", (reliable ? "" : "? "), (void *)*stack);
87
88
89Kernel Pointers 78Kernel Pointers
90=============== 79===============
91 80
diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h
index 708f337d780b..e4f2e5a65f14 100644
--- a/include/linux/kallsyms.h
+++ b/include/linux/kallsyms.h
@@ -9,6 +9,10 @@
9#include <linux/errno.h> 9#include <linux/errno.h>
10#include <linux/kernel.h> 10#include <linux/kernel.h>
11#include <linux/stddef.h> 11#include <linux/stddef.h>
12#include <linux/mm.h>
13#include <linux/module.h>
14
15#include <asm/sections.h>
12 16
13#define KSYM_NAME_LEN 128 17#define KSYM_NAME_LEN 128
14#define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN - 1) + \ 18#define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN - 1) + \
@@ -22,6 +26,56 @@
22 26
23struct module; 27struct module;
24 28
29static inline int is_kernel_inittext(unsigned long addr)
30{
31 if (addr >= (unsigned long)_sinittext
32 && addr <= (unsigned long)_einittext)
33 return 1;
34 return 0;
35}
36
37static inline int is_kernel_text(unsigned long addr)
38{
39 if ((addr >= (unsigned long)_stext && addr <= (unsigned long)_etext) ||
40 arch_is_kernel_text(addr))
41 return 1;
42 return in_gate_area_no_mm(addr);
43}
44
45static inline int is_kernel(unsigned long addr)
46{
47 if (addr >= (unsigned long)_stext && addr <= (unsigned long)_end)
48 return 1;
49 return in_gate_area_no_mm(addr);
50}
51
52static inline int is_ksym_addr(unsigned long addr)
53{
54 if (IS_ENABLED(CONFIG_KALLSYMS_ALL))
55 return is_kernel(addr);
56
57 return is_kernel_text(addr) || is_kernel_inittext(addr);
58}
59
60static inline void *dereference_symbol_descriptor(void *ptr)
61{
62#ifdef HAVE_DEREFERENCE_FUNCTION_DESCRIPTOR
63 struct module *mod;
64
65 ptr = dereference_kernel_function_descriptor(ptr);
66 if (is_ksym_addr((unsigned long)ptr))
67 return ptr;
68
69 preempt_disable();
70 mod = __module_address((unsigned long)ptr);
71 preempt_enable();
72
73 if (mod)
74 ptr = dereference_module_function_descriptor(mod, ptr);
75#endif
76 return ptr;
77}
78
25#ifdef CONFIG_KALLSYMS 79#ifdef CONFIG_KALLSYMS
26/* Lookup the address for a symbol. Returns 0 if not found. */ 80/* Lookup the address for a symbol. Returns 0 if not found. */
27unsigned long kallsyms_lookup_name(const char *name); 81unsigned long kallsyms_lookup_name(const char *name);
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index 531ffa984bc2..0e4c0922908a 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -12,7 +12,6 @@
12 * compression (see scripts/kallsyms.c for a more complete description) 12 * compression (see scripts/kallsyms.c for a more complete description)
13 */ 13 */
14#include <linux/kallsyms.h> 14#include <linux/kallsyms.h>
15#include <linux/module.h>
16#include <linux/init.h> 15#include <linux/init.h>
17#include <linux/seq_file.h> 16#include <linux/seq_file.h>
18#include <linux/fs.h> 17#include <linux/fs.h>
@@ -20,15 +19,12 @@
20#include <linux/err.h> 19#include <linux/err.h>
21#include <linux/proc_fs.h> 20#include <linux/proc_fs.h>
22#include <linux/sched.h> /* for cond_resched */ 21#include <linux/sched.h> /* for cond_resched */
23#include <linux/mm.h>
24#include <linux/ctype.h> 22#include <linux/ctype.h>
25#include <linux/slab.h> 23#include <linux/slab.h>
26#include <linux/filter.h> 24#include <linux/filter.h>
27#include <linux/ftrace.h> 25#include <linux/ftrace.h>
28#include <linux/compiler.h> 26#include <linux/compiler.h>
29 27
30#include <asm/sections.h>
31
32/* 28/*
33 * These will be re-linked against their real values 29 * These will be re-linked against their real values
34 * during the second link stage. 30 * during the second link stage.
@@ -52,37 +48,6 @@ extern const u16 kallsyms_token_index[] __weak;
52 48
53extern const unsigned long kallsyms_markers[] __weak; 49extern const unsigned long kallsyms_markers[] __weak;
54 50
55static inline int is_kernel_inittext(unsigned long addr)
56{
57 if (addr >= (unsigned long)_sinittext
58 && addr <= (unsigned long)_einittext)
59 return 1;
60 return 0;
61}
62
63static inline int is_kernel_text(unsigned long addr)
64{
65 if ((addr >= (unsigned long)_stext && addr <= (unsigned long)_etext) ||
66 arch_is_kernel_text(addr))
67 return 1;
68 return in_gate_area_no_mm(addr);
69}
70
71static inline int is_kernel(unsigned long addr)
72{
73 if (addr >= (unsigned long)_stext && addr <= (unsigned long)_end)
74 return 1;
75 return in_gate_area_no_mm(addr);
76}
77
78static int is_ksym_addr(unsigned long addr)
79{
80 if (IS_ENABLED(CONFIG_KALLSYMS_ALL))
81 return is_kernel(addr);
82
83 return is_kernel_text(addr) || is_kernel_inittext(addr);
84}
85
86/* 51/*
87 * Expand a compressed symbol data into the resulting uncompressed string, 52 * Expand a compressed symbol data into the resulting uncompressed string,
88 * if uncompressed string is too long (>= maxlen), it will be truncated, 53 * if uncompressed string is too long (>= maxlen), it will be truncated,
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 1746bae94d41..16e2eefb0f79 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -40,7 +40,6 @@
40#include "../mm/internal.h" /* For the trace_print_flags arrays */ 40#include "../mm/internal.h" /* For the trace_print_flags arrays */
41 41
42#include <asm/page.h> /* for PAGE_SIZE */ 42#include <asm/page.h> /* for PAGE_SIZE */
43#include <asm/sections.h> /* for dereference_function_descriptor() */
44#include <asm/byteorder.h> /* cpu_to_le16 */ 43#include <asm/byteorder.h> /* cpu_to_le16 */
45 44
46#include <linux/string_helpers.h> 45#include <linux/string_helpers.h>
@@ -1723,10 +1722,10 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
1723 switch (*fmt) { 1722 switch (*fmt) {
1724 case 'F': 1723 case 'F':
1725 case 'f': 1724 case 'f':
1726 ptr = dereference_function_descriptor(ptr);
1727 /* Fallthrough */
1728 case 'S': 1725 case 'S':
1729 case 's': 1726 case 's':
1727 ptr = dereference_symbol_descriptor(ptr);
1728 /* Fallthrough */
1730 case 'B': 1729 case 'B':
1731 return symbol_string(buf, end, ptr, spec, fmt); 1730 return symbol_string(buf, end, ptr, spec, fmt);
1732 case 'R': 1731 case 'R':