diff options
| -rw-r--r-- | Documentation/printk-formats.txt | 35 | ||||
| -rw-r--r-- | include/linux/kallsyms.h | 54 | ||||
| -rw-r--r-- | kernel/kallsyms.c | 35 | ||||
| -rw-r--r-- | lib/vsprintf.c | 5 |
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 | ||
| 61 | The ``F`` and ``f`` specifiers are for printing function pointers, | 61 | The ``S`` and ``s`` specifiers are used for printing a pointer in symbolic |
| 62 | for example, f->func, &gettimeofday. They have the same result as | 62 | format. They result in the symbol name with (``S``) or without (``s``) |
| 63 | ``S`` and ``s`` specifiers. But they do an extra conversion on | 63 | offsets. If KALLSYMS are disabled then the symbol address is printed instead. |
| 64 | ia64, ppc64 and parisc64 architectures where the function pointers | ||
| 65 | are actually function descriptors. | ||
| 66 | 64 | ||
| 67 | The ``S`` and ``s`` specifiers can be used for printing symbols | 65 | Note, that the ``F`` and ``f`` specifiers are identical to ``S`` (``s``) |
| 68 | from direct addresses, for example, __builtin_return_address(0), | 66 | and 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 | 67 | parisc64 function pointers are indirect and, in fact, are function |
| 70 | without (``s``) offsets. If KALLSYMS are disabled then the symbol | 68 | descriptors, which require additional dereferencing before we can lookup |
| 71 | address is printed instead. | 69 | the symbol. As of now, ``S`` and ``s`` perform dereferencing on those |
| 70 | platforms (when needed), so ``F`` and ``f`` exist for compatibility | ||
| 71 | reasons only. | ||
| 72 | 72 | ||
| 73 | The ``B`` specifier results in the symbol name with offsets and should be | 73 | The ``B`` specifier results in the symbol name with offsets and should be |
| 74 | used when printing stack backtraces. The specifier takes into | 74 | used when printing stack backtraces. The specifier takes into |
| 75 | consideration the effect of compiler optimisations which may occur | 75 | consideration the effect of compiler optimisations which may occur |
| 76 | when tail-call``s are used and marked with the noreturn GCC attribute. | 76 | when tail-call``s are used and marked with the noreturn GCC attribute. |
| 77 | 77 | ||
| 78 | Examples:: | ||
| 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 | |||
| 89 | Kernel Pointers | 78 | Kernel 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 | ||
| 23 | struct module; | 27 | struct module; |
| 24 | 28 | ||
| 29 | static 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 | |||
| 37 | static 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 | |||
| 45 | static 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 | |||
| 52 | static 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 | |||
| 60 | static 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. */ |
| 27 | unsigned long kallsyms_lookup_name(const char *name); | 81 | unsigned 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 | ||
| 53 | extern const unsigned long kallsyms_markers[] __weak; | 49 | extern const unsigned long kallsyms_markers[] __weak; |
| 54 | 50 | ||
| 55 | static 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 | |||
| 63 | static 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 | |||
| 71 | static 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 | |||
| 78 | static 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': |
