summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/admin-guide/kernel-parameters.txt14
-rw-r--r--Documentation/core-api/printk-formats.rst34
-rw-r--r--Documentation/filesystems/sysfs.txt4
-rw-r--r--Documentation/translations/zh_CN/filesystems/sysfs.txt4
-rw-r--r--arch/arm/kernel/process.c5
-rw-r--r--arch/arm64/kernel/process.c5
-rw-r--r--arch/c6x/kernel/traps.c4
-rw-r--r--arch/ia64/include/asm/sections.h10
-rw-r--r--arch/ia64/kernel/module.c12
-rw-r--r--arch/ia64/kernel/process.c10
-rw-r--r--arch/ia64/kernel/vmlinux.lds.S2
-rw-r--r--arch/mn10300/kernel/traps.c4
-rw-r--r--arch/openrisc/kernel/traps.c3
-rw-r--r--arch/parisc/boot/compressed/vmlinux.lds.S2
-rw-r--r--arch/parisc/include/asm/sections.h6
-rw-r--r--arch/parisc/kernel/module.c16
-rw-r--r--arch/parisc/kernel/process.c9
-rw-r--r--arch/parisc/kernel/vmlinux.lds.S2
-rw-r--r--arch/powerpc/include/asm/module.h3
-rw-r--r--arch/powerpc/include/asm/sections.h12
-rw-r--r--arch/powerpc/kernel/module_64.c14
-rw-r--r--arch/powerpc/kernel/vmlinux.lds.S2
-rw-r--r--arch/sh/kernel/process_32.c5
-rw-r--r--arch/unicore32/kernel/process.c5
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c3
-rw-r--r--arch/x86/mm/mmio-mod.c5
-rw-r--r--drivers/base/core.c5
-rw-r--r--fs/sysfs/file.c5
-rw-r--r--include/asm-generic/sections.h8
-rw-r--r--include/linux/kallsyms.h72
-rw-r--r--include/linux/module.h10
-rw-r--r--kernel/irq/debug.h14
-rw-r--r--kernel/kallsyms.c46
-rw-r--r--kernel/module.c6
-rw-r--r--kernel/printk/printk.c215
-rw-r--r--kernel/sched/autogroup.c5
-rw-r--r--lib/smp_processor_id.c3
-rw-r--r--lib/vsprintf.c5
-rwxr-xr-xscripts/checkpatch.pl11
39 files changed, 428 insertions, 172 deletions
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index dc63e5bddf78..90cefbddf1ed 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -646,6 +646,20 @@
646 console=brl,ttyS0 646 console=brl,ttyS0
647 For now, only VisioBraille is supported. 647 For now, only VisioBraille is supported.
648 648
649 console_msg_format=
650 [KNL] Change console messages format
651 default
652 By default we print messages on consoles in
653 "[time stamp] text\n" format (time stamp may not be
654 printed, depending on CONFIG_PRINTK_TIME or
655 `printk_time' param).
656 syslog
657 Switch to syslog format: "<%u>[time stamp] text\n"
658 IOW, each message will have a facility and loglevel
659 prefix. The format is similar to one used by syslog()
660 syscall, or to executing "dmesg -S --raw" or to reading
661 from /proc/kmsg.
662
649 consoleblank= [KNL] The console blank (screen saver) timeout in 663 consoleblank= [KNL] The console blank (screen saver) timeout in
650 seconds. A value of 0 disables the blank timer. 664 seconds. A value of 0 disables the blank timer.
651 Defaults to 0. 665 Defaults to 0.
diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst
index 258b46435320..934559b3c130 100644
--- a/Documentation/core-api/printk-formats.rst
+++ b/Documentation/core-api/printk-formats.rst
@@ -68,42 +68,32 @@ Symbols/Function Pointers
68 68
69:: 69::
70 70
71 %pS versatile_init+0x0/0x110
72 %ps versatile_init
71 %pF versatile_init+0x0/0x110 73 %pF versatile_init+0x0/0x110
72 %pf versatile_init 74 %pf versatile_init
73 %pS versatile_init+0x0/0x110
74 %pSR versatile_init+0x9/0x110 75 %pSR versatile_init+0x9/0x110
75 (with __builtin_extract_return_addr() translation) 76 (with __builtin_extract_return_addr() translation)
76 %ps versatile_init
77 %pB prev_fn_of_versatile_init+0x88/0x88 77 %pB prev_fn_of_versatile_init+0x88/0x88
78 78
79 79
80The ``F`` and ``f`` specifiers are for printing function pointers, 80The ``S`` and ``s`` specifiers are used for printing a pointer in symbolic
81for example, f->func, &gettimeofday. They have the same result as 81format. They result in the symbol name with (S) or without (s)
82``S`` and ``s`` specifiers. But they do an extra conversion on 82offsets. If KALLSYMS are disabled then the symbol address is printed instead.
83ia64, ppc64 and parisc64 architectures where the function pointers
84are actually function descriptors.
85 83
86The ``S`` and ``s`` specifiers can be used for printing symbols 84Note, that the ``F`` and ``f`` specifiers are identical to ``S`` (``s``)
87from direct addresses, for example, __builtin_return_address(0), 85and thus deprecated. We have ``F`` and ``f`` because on ia64, ppc64 and
88(void *)regs->ip. They result in the symbol name with (S) or 86parisc64 function pointers are indirect and, in fact, are function
89without (s) offsets. If KALLSYMS are disabled then the symbol 87descriptors, which require additional dereferencing before we can lookup
90address is printed instead. 88the symbol. As of now, ``S`` and ``s`` perform dereferencing on those
89platforms (when needed), so ``F`` and ``f`` exist for compatibility
90reasons only.
91 91
92The ``B`` specifier results in the symbol name with offsets and should be 92The ``B`` specifier results in the symbol name with offsets and should be
93used when printing stack backtraces. The specifier takes into 93used when printing stack backtraces. The specifier takes into
94consideration the effect of compiler optimisations which may occur 94consideration the effect of compiler optimisations which may occur
95when tail-calls are used and marked with the noreturn GCC attribute. 95when tail-calls are used and marked with the noreturn GCC attribute.
96 96
97Examples::
98
99 printk("Going to call: %pF\n", gettimeofday);
100 printk("Going to call: %pF\n", p->func);
101 printk("%s: called from %pS\n", __func__, (void *)_RET_IP_);
102 printk("%s: called from %pS\n", __func__,
103 (void *)__builtin_return_address(0));
104 printk("Faulted at %pS\n", (void *)regs->ip);
105 printk(" %s%pB\n", (reliable ? "" : "? "), (void *)*stack);
106
107Kernel Pointers 97Kernel Pointers
108--------------- 98---------------
109 99
diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt
index 9a3658cc399e..a1426cabcef1 100644
--- a/Documentation/filesystems/sysfs.txt
+++ b/Documentation/filesystems/sysfs.txt
@@ -154,8 +154,8 @@ static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr,
154 if (dev_attr->show) 154 if (dev_attr->show)
155 ret = dev_attr->show(dev, dev_attr, buf); 155 ret = dev_attr->show(dev, dev_attr, buf);
156 if (ret >= (ssize_t)PAGE_SIZE) { 156 if (ret >= (ssize_t)PAGE_SIZE) {
157 print_symbol("dev_attr_show: %s returned bad count\n", 157 printk("dev_attr_show: %pS returned bad count\n",
158 (unsigned long)dev_attr->show); 158 dev_attr->show);
159 } 159 }
160 return ret; 160 return ret;
161} 161}
diff --git a/Documentation/translations/zh_CN/filesystems/sysfs.txt b/Documentation/translations/zh_CN/filesystems/sysfs.txt
index 7d3b05edb8ce..452271dda141 100644
--- a/Documentation/translations/zh_CN/filesystems/sysfs.txt
+++ b/Documentation/translations/zh_CN/filesystems/sysfs.txt
@@ -167,8 +167,8 @@ static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr,
167 if (dev_attr->show) 167 if (dev_attr->show)
168 ret = dev_attr->show(dev, dev_attr, buf); 168 ret = dev_attr->show(dev, dev_attr, buf);
169 if (ret >= (ssize_t)PAGE_SIZE) { 169 if (ret >= (ssize_t)PAGE_SIZE) {
170 print_symbol("dev_attr_show: %s returned bad count\n", 170 printk("dev_attr_show: %pS returned bad count\n",
171 (unsigned long)dev_attr->show); 171 dev_attr->show);
172 } 172 }
173 return ret; 173 return ret;
174} 174}
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index d96714e1858c..1523cb18b109 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -21,7 +21,6 @@
21#include <linux/unistd.h> 21#include <linux/unistd.h>
22#include <linux/user.h> 22#include <linux/user.h>
23#include <linux/interrupt.h> 23#include <linux/interrupt.h>
24#include <linux/kallsyms.h>
25#include <linux/init.h> 24#include <linux/init.h>
26#include <linux/elfcore.h> 25#include <linux/elfcore.h>
27#include <linux/pm.h> 26#include <linux/pm.h>
@@ -121,8 +120,8 @@ void __show_regs(struct pt_regs *regs)
121 120
122 show_regs_print_info(KERN_DEFAULT); 121 show_regs_print_info(KERN_DEFAULT);
123 122
124 print_symbol("PC is at %s\n", instruction_pointer(regs)); 123 printk("PC is at %pS\n", (void *)instruction_pointer(regs));
125 print_symbol("LR is at %s\n", regs->ARM_lr); 124 printk("LR is at %pS\n", (void *)regs->ARM_lr);
126 printk("pc : [<%08lx>] lr : [<%08lx>] psr: %08lx\n", 125 printk("pc : [<%08lx>] lr : [<%08lx>] psr: %08lx\n",
127 regs->ARM_pc, regs->ARM_lr, regs->ARM_cpsr); 126 regs->ARM_pc, regs->ARM_lr, regs->ARM_cpsr);
128 printk("sp : %08lx ip : %08lx fp : %08lx\n", 127 printk("sp : %08lx ip : %08lx fp : %08lx\n",
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 583fd8154695..ad8aeb098b31 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -35,7 +35,6 @@
35#include <linux/delay.h> 35#include <linux/delay.h>
36#include <linux/reboot.h> 36#include <linux/reboot.h>
37#include <linux/interrupt.h> 37#include <linux/interrupt.h>
38#include <linux/kallsyms.h>
39#include <linux/init.h> 38#include <linux/init.h>
40#include <linux/cpu.h> 39#include <linux/cpu.h>
41#include <linux/elfcore.h> 40#include <linux/elfcore.h>
@@ -221,8 +220,8 @@ void __show_regs(struct pt_regs *regs)
221 220
222 show_regs_print_info(KERN_DEFAULT); 221 show_regs_print_info(KERN_DEFAULT);
223 print_pstate(regs); 222 print_pstate(regs);
224 print_symbol("pc : %s\n", regs->pc); 223 printk("pc : %pS\n", (void *)regs->pc);
225 print_symbol("lr : %s\n", lr); 224 printk("lr : %pS\n", (void *)lr);
226 printk("sp : %016llx\n", sp); 225 printk("sp : %016llx\n", sp);
227 226
228 i = top_reg; 227 i = top_reg;
diff --git a/arch/c6x/kernel/traps.c b/arch/c6x/kernel/traps.c
index 09b8a40d5680..4c1d4b84dd2b 100644
--- a/arch/c6x/kernel/traps.c
+++ b/arch/c6x/kernel/traps.c
@@ -11,7 +11,6 @@
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/ptrace.h> 12#include <linux/ptrace.h>
13#include <linux/sched/debug.h> 13#include <linux/sched/debug.h>
14#include <linux/kallsyms.h>
15#include <linux/bug.h> 14#include <linux/bug.h>
16 15
17#include <asm/soc.h> 16#include <asm/soc.h>
@@ -375,8 +374,7 @@ static void show_trace(unsigned long *stack, unsigned long *endstack)
375 if (i % 5 == 0) 374 if (i % 5 == 0)
376 pr_debug("\n "); 375 pr_debug("\n ");
377#endif 376#endif
378 pr_debug(" [<%08lx>]", addr); 377 pr_debug(" [<%08lx>] %pS\n", addr, (void *)addr);
379 print_symbol(" %s\n", addr);
380 i++; 378 i++;
381 } 379 }
382 } 380 }
diff --git a/arch/ia64/include/asm/sections.h b/arch/ia64/include/asm/sections.h
index f3481408594e..cea15f2dd38d 100644
--- a/arch/ia64/include/asm/sections.h
+++ b/arch/ia64/include/asm/sections.h
@@ -27,6 +27,8 @@ extern char __start_gate_brl_fsys_bubble_down_patchlist[], __end_gate_brl_fsys_b
27extern char __start_unwind[], __end_unwind[]; 27extern char __start_unwind[], __end_unwind[];
28extern char __start_ivt_text[], __end_ivt_text[]; 28extern char __start_ivt_text[], __end_ivt_text[];
29 29
30#define HAVE_DEREFERENCE_FUNCTION_DESCRIPTOR 1
31
30#undef dereference_function_descriptor 32#undef dereference_function_descriptor
31static inline void *dereference_function_descriptor(void *ptr) 33static inline void *dereference_function_descriptor(void *ptr)
32{ 34{
@@ -38,6 +40,12 @@ static inline void *dereference_function_descriptor(void *ptr)
38 return ptr; 40 return ptr;
39} 41}
40 42
43#undef dereference_kernel_function_descriptor
44static inline void *dereference_kernel_function_descriptor(void *ptr)
45{
46 if (ptr < (void *)__start_opd || ptr >= (void *)__end_opd)
47 return ptr;
48 return dereference_function_descriptor(ptr);
49}
41 50
42#endif /* _ASM_IA64_SECTIONS_H */ 51#endif /* _ASM_IA64_SECTIONS_H */
43
diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c
index 853b5611a894..326448f9df16 100644
--- a/arch/ia64/kernel/module.c
+++ b/arch/ia64/kernel/module.c
@@ -36,6 +36,7 @@
36 36
37#include <asm/patch.h> 37#include <asm/patch.h>
38#include <asm/unaligned.h> 38#include <asm/unaligned.h>
39#include <asm/sections.h>
39 40
40#define ARCH_MODULE_DEBUG 0 41#define ARCH_MODULE_DEBUG 0
41 42
@@ -918,3 +919,14 @@ module_arch_cleanup (struct module *mod)
918 if (mod->arch.core_unw_table) 919 if (mod->arch.core_unw_table)
919 unw_remove_unwind_table(mod->arch.core_unw_table); 920 unw_remove_unwind_table(mod->arch.core_unw_table);
920} 921}
922
923void *dereference_module_function_descriptor(struct module *mod, void *ptr)
924{
925 Elf64_Shdr *opd = mod->arch.opd;
926
927 if (ptr < (void *)opd->sh_addr ||
928 ptr >= (void *)(opd->sh_addr + opd->sh_size))
929 return ptr;
930
931 return dereference_function_descriptor(ptr);
932}
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index dda0082056b3..968b5f33e725 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -13,7 +13,6 @@
13#include <linux/pm.h> 13#include <linux/pm.h>
14#include <linux/elf.h> 14#include <linux/elf.h>
15#include <linux/errno.h> 15#include <linux/errno.h>
16#include <linux/kallsyms.h>
17#include <linux/kernel.h> 16#include <linux/kernel.h>
18#include <linux/mm.h> 17#include <linux/mm.h>
19#include <linux/slab.h> 18#include <linux/slab.h>
@@ -69,7 +68,6 @@ void
69ia64_do_show_stack (struct unw_frame_info *info, void *arg) 68ia64_do_show_stack (struct unw_frame_info *info, void *arg)
70{ 69{
71 unsigned long ip, sp, bsp; 70 unsigned long ip, sp, bsp;
72 char buf[128]; /* don't make it so big that it overflows the stack! */
73 71
74 printk("\nCall Trace:\n"); 72 printk("\nCall Trace:\n");
75 do { 73 do {
@@ -79,11 +77,9 @@ ia64_do_show_stack (struct unw_frame_info *info, void *arg)
79 77
80 unw_get_sp(info, &sp); 78 unw_get_sp(info, &sp);
81 unw_get_bsp(info, &bsp); 79 unw_get_bsp(info, &bsp);
82 snprintf(buf, sizeof(buf), 80 printk(" [<%016lx>] %pS\n"
83 " [<%016lx>] %%s\n"
84 " sp=%016lx bsp=%016lx\n", 81 " sp=%016lx bsp=%016lx\n",
85 ip, sp, bsp); 82 ip, (void *)ip, sp, bsp);
86 print_symbol(buf, ip);
87 } while (unw_unwind(info) >= 0); 83 } while (unw_unwind(info) >= 0);
88} 84}
89 85
@@ -111,7 +107,7 @@ show_regs (struct pt_regs *regs)
111 printk("psr : %016lx ifs : %016lx ip : [<%016lx>] %s (%s)\n", 107 printk("psr : %016lx ifs : %016lx ip : [<%016lx>] %s (%s)\n",
112 regs->cr_ipsr, regs->cr_ifs, ip, print_tainted(), 108 regs->cr_ipsr, regs->cr_ifs, ip, print_tainted(),
113 init_utsname()->release); 109 init_utsname()->release);
114 print_symbol("ip is at %s\n", ip); 110 printk("ip is at %pS\n", (void *)ip);
115 printk("unat: %016lx pfs : %016lx rsc : %016lx\n", 111 printk("unat: %016lx pfs : %016lx rsc : %016lx\n",
116 regs->ar_unat, regs->ar_pfs, regs->ar_rsc); 112 regs->ar_unat, regs->ar_pfs, regs->ar_rsc);
117 printk("rnat: %016lx bsps: %016lx pr : %016lx\n", 113 printk("rnat: %016lx bsps: %016lx pr : %016lx\n",
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index b0b2070e0591..0da58cf8e213 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -109,7 +109,9 @@ SECTIONS {
109 RODATA 109 RODATA
110 110
111 .opd : AT(ADDR(.opd) - LOAD_OFFSET) { 111 .opd : AT(ADDR(.opd) - LOAD_OFFSET) {
112 __start_opd = .;
112 *(.opd) 113 *(.opd)
114 __end_opd = .;
113 } 115 }
114 116
115 /* 117 /*
diff --git a/arch/mn10300/kernel/traps.c b/arch/mn10300/kernel/traps.c
index 800fd0801969..72d1015b2ae7 100644
--- a/arch/mn10300/kernel/traps.c
+++ b/arch/mn10300/kernel/traps.c
@@ -22,7 +22,6 @@
22#include <linux/delay.h> 22#include <linux/delay.h>
23#include <linux/spinlock.h> 23#include <linux/spinlock.h>
24#include <linux/interrupt.h> 24#include <linux/interrupt.h>
25#include <linux/kallsyms.h>
26#include <linux/pci.h> 25#include <linux/pci.h>
27#include <linux/kdebug.h> 26#include <linux/kdebug.h>
28#include <linux/bug.h> 27#include <linux/bug.h>
@@ -262,8 +261,7 @@ void show_trace(unsigned long *sp)
262 raslot = ULONG_MAX; 261 raslot = ULONG_MAX;
263 else 262 else
264 printk(" ?"); 263 printk(" ?");
265 print_symbol(" %s", addr); 264 printk(" %pS\n", (void *)addr);
266 printk("\n");
267 } 265 }
268 } 266 }
269 267
diff --git a/arch/openrisc/kernel/traps.c b/arch/openrisc/kernel/traps.c
index 9e38dc66c9e4..113c175fe469 100644
--- a/arch/openrisc/kernel/traps.c
+++ b/arch/openrisc/kernel/traps.c
@@ -39,8 +39,7 @@
39#include <asm/io.h> 39#include <asm/io.h>
40#include <asm/pgtable.h> 40#include <asm/pgtable.h>
41#include <asm/unwinder.h> 41#include <asm/unwinder.h>
42 42#include <asm/sections.h>
43extern char _etext, _stext;
44 43
45int kstack_depth_to_print = 0x180; 44int kstack_depth_to_print = 0x180;
46int lwa_flag; 45int lwa_flag;
diff --git a/arch/parisc/boot/compressed/vmlinux.lds.S b/arch/parisc/boot/compressed/vmlinux.lds.S
index a4ce3314e78e..4ebd4e65524c 100644
--- a/arch/parisc/boot/compressed/vmlinux.lds.S
+++ b/arch/parisc/boot/compressed/vmlinux.lds.S
@@ -29,7 +29,9 @@ SECTIONS
29 . = ALIGN(16); 29 . = ALIGN(16);
30 /* Linkage tables */ 30 /* Linkage tables */
31 .opd : { 31 .opd : {
32 __start_opd = .;
32 *(.opd) 33 *(.opd)
34 __end_opd = .;
33 } PROVIDE (__gp = .); 35 } PROVIDE (__gp = .);
34 .plt : { 36 .plt : {
35 *(.plt) 37 *(.plt)
diff --git a/arch/parisc/include/asm/sections.h b/arch/parisc/include/asm/sections.h
index accdf40aa5b7..5a40b51df80c 100644
--- a/arch/parisc/include/asm/sections.h
+++ b/arch/parisc/include/asm/sections.h
@@ -6,8 +6,14 @@
6#include <asm-generic/sections.h> 6#include <asm-generic/sections.h>
7 7
8#ifdef CONFIG_64BIT 8#ifdef CONFIG_64BIT
9
10#define HAVE_DEREFERENCE_FUNCTION_DESCRIPTOR 1
11
9#undef dereference_function_descriptor 12#undef dereference_function_descriptor
10void *dereference_function_descriptor(void *); 13void *dereference_function_descriptor(void *);
14
15#undef dereference_kernel_function_descriptor
16void *dereference_kernel_function_descriptor(void *);
11#endif 17#endif
12 18
13#endif 19#endif
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c
index f1a76935a314..b5b3cb00f1fb 100644
--- a/arch/parisc/kernel/module.c
+++ b/arch/parisc/kernel/module.c
@@ -66,6 +66,7 @@
66 66
67#include <asm/pgtable.h> 67#include <asm/pgtable.h>
68#include <asm/unwind.h> 68#include <asm/unwind.h>
69#include <asm/sections.h>
69 70
70#if 0 71#if 0
71#define DEBUGP printk 72#define DEBUGP printk
@@ -954,3 +955,18 @@ void module_arch_cleanup(struct module *mod)
954{ 955{
955 deregister_unwind_table(mod); 956 deregister_unwind_table(mod);
956} 957}
958
959#ifdef CONFIG_64BIT
960void *dereference_module_function_descriptor(struct module *mod, void *ptr)
961{
962 unsigned long start_opd = (Elf64_Addr)mod->core_layout.base +
963 mod->arch.fdesc_offset;
964 unsigned long end_opd = start_opd +
965 mod->arch.fdesc_count * sizeof(Elf64_Fdesc);
966
967 if (ptr < (void *)start_opd || ptr >= (void *)end_opd)
968 return ptr;
969
970 return dereference_function_descriptor(ptr);
971}
972#endif
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
index cad3e8661cd6..6975a0627078 100644
--- a/arch/parisc/kernel/process.c
+++ b/arch/parisc/kernel/process.c
@@ -315,6 +315,15 @@ void *dereference_function_descriptor(void *ptr)
315 ptr = p; 315 ptr = p;
316 return ptr; 316 return ptr;
317} 317}
318
319void *dereference_kernel_function_descriptor(void *ptr)
320{
321 if (ptr < (void *)__start_opd ||
322 ptr >= (void *)__end_opd)
323 return ptr;
324
325 return dereference_function_descriptor(ptr);
326}
318#endif 327#endif
319 328
320static inline unsigned long brk_rnd(void) 329static inline unsigned long brk_rnd(void)
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 159a2ec0b4e0..da2e31190efa 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -100,7 +100,9 @@ SECTIONS
100 . = ALIGN(16); 100 . = ALIGN(16);
101 /* Linkage tables */ 101 /* Linkage tables */
102 .opd : { 102 .opd : {
103 __start_opd = .;
103 *(.opd) 104 *(.opd)
105 __end_opd = .;
104 } PROVIDE (__gp = .); 106 } PROVIDE (__gp = .);
105 .plt : { 107 .plt : {
106 *(.plt) 108 *(.plt)
diff --git a/arch/powerpc/include/asm/module.h b/arch/powerpc/include/asm/module.h
index 6c0132c7212f..7e28442827f1 100644
--- a/arch/powerpc/include/asm/module.h
+++ b/arch/powerpc/include/asm/module.h
@@ -45,6 +45,9 @@ struct mod_arch_specific {
45 unsigned long tramp; 45 unsigned long tramp;
46#endif 46#endif
47 47
48 /* For module function descriptor dereference */
49 unsigned long start_opd;
50 unsigned long end_opd;
48#else /* powerpc64 */ 51#else /* powerpc64 */
49 /* Indices of PLT sections within module. */ 52 /* Indices of PLT sections within module. */
50 unsigned int core_plt_section; 53 unsigned int core_plt_section;
diff --git a/arch/powerpc/include/asm/sections.h b/arch/powerpc/include/asm/sections.h
index 82bec63bbd4f..e335a8f846af 100644
--- a/arch/powerpc/include/asm/sections.h
+++ b/arch/powerpc/include/asm/sections.h
@@ -66,6 +66,9 @@ static inline int overlaps_kvm_tmp(unsigned long start, unsigned long end)
66} 66}
67 67
68#ifdef PPC64_ELF_ABI_v1 68#ifdef PPC64_ELF_ABI_v1
69
70#define HAVE_DEREFERENCE_FUNCTION_DESCRIPTOR 1
71
69#undef dereference_function_descriptor 72#undef dereference_function_descriptor
70static inline void *dereference_function_descriptor(void *ptr) 73static inline void *dereference_function_descriptor(void *ptr)
71{ 74{
@@ -76,6 +79,15 @@ static inline void *dereference_function_descriptor(void *ptr)
76 ptr = p; 79 ptr = p;
77 return ptr; 80 return ptr;
78} 81}
82
83#undef dereference_kernel_function_descriptor
84static inline void *dereference_kernel_function_descriptor(void *ptr)
85{
86 if (ptr < (void *)__start_opd || ptr >= (void *)__end_opd)
87 return ptr;
88
89 return dereference_function_descriptor(ptr);
90}
79#endif /* PPC64_ELF_ABI_v1 */ 91#endif /* PPC64_ELF_ABI_v1 */
80 92
81#endif 93#endif
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index 759104b99f9f..218971ac7e04 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -93,6 +93,15 @@ static unsigned int local_entry_offset(const Elf64_Sym *sym)
93{ 93{
94 return 0; 94 return 0;
95} 95}
96
97void *dereference_module_function_descriptor(struct module *mod, void *ptr)
98{
99 if (ptr < (void *)mod->arch.start_opd ||
100 ptr >= (void *)mod->arch.end_opd)
101 return ptr;
102
103 return dereference_function_descriptor(ptr);
104}
96#endif 105#endif
97 106
98#define STUB_MAGIC 0x73747562 /* stub */ 107#define STUB_MAGIC 0x73747562 /* stub */
@@ -344,6 +353,11 @@ int module_frob_arch_sections(Elf64_Ehdr *hdr,
344 else if (strcmp(secstrings+sechdrs[i].sh_name,"__versions")==0) 353 else if (strcmp(secstrings+sechdrs[i].sh_name,"__versions")==0)
345 dedotify_versions((void *)hdr + sechdrs[i].sh_offset, 354 dedotify_versions((void *)hdr + sechdrs[i].sh_offset,
346 sechdrs[i].sh_size); 355 sechdrs[i].sh_size);
356 else if (!strcmp(secstrings + sechdrs[i].sh_name, ".opd")) {
357 me->arch.start_opd = sechdrs[i].sh_addr;
358 me->arch.end_opd = sechdrs[i].sh_addr +
359 sechdrs[i].sh_size;
360 }
347 361
348 /* We don't handle .init for the moment: rename to _init */ 362 /* We don't handle .init for the moment: rename to _init */
349 while ((p = strstr(secstrings + sechdrs[i].sh_name, ".init"))) 363 while ((p = strstr(secstrings + sechdrs[i].sh_name, ".init")))
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 307843d23682..74901a87bf7a 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -287,7 +287,9 @@ SECTIONS
287 } 287 }
288 288
289 .opd : AT(ADDR(.opd) - LOAD_OFFSET) { 289 .opd : AT(ADDR(.opd) - LOAD_OFFSET) {
290 __start_opd = .;
290 *(.opd) 291 *(.opd)
292 __end_opd = .;
291 } 293 }
292 294
293 . = ALIGN(256); 295 . = ALIGN(256);
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c
index 2c7bdf8cb934..93522069cb15 100644
--- a/arch/sh/kernel/process_32.c
+++ b/arch/sh/kernel/process_32.c
@@ -20,7 +20,6 @@
20#include <linux/sched/task_stack.h> 20#include <linux/sched/task_stack.h>
21#include <linux/slab.h> 21#include <linux/slab.h>
22#include <linux/elfcore.h> 22#include <linux/elfcore.h>
23#include <linux/kallsyms.h>
24#include <linux/fs.h> 23#include <linux/fs.h>
25#include <linux/ftrace.h> 24#include <linux/ftrace.h>
26#include <linux/hw_breakpoint.h> 25#include <linux/hw_breakpoint.h>
@@ -37,8 +36,8 @@ void show_regs(struct pt_regs * regs)
37 printk("\n"); 36 printk("\n");
38 show_regs_print_info(KERN_DEFAULT); 37 show_regs_print_info(KERN_DEFAULT);
39 38
40 print_symbol("PC is at %s\n", instruction_pointer(regs)); 39 printk("PC is at %pS\n", (void *)instruction_pointer(regs));
41 print_symbol("PR is at %s\n", regs->pr); 40 printk("PR is at %pS\n", (void *)regs->pr);
42 41
43 printk("PC : %08lx SP : %08lx SR : %08lx ", 42 printk("PC : %08lx SP : %08lx SR : %08lx ",
44 regs->pc, regs->regs[15], regs->sr); 43 regs->pc, regs->regs[15], regs->sr);
diff --git a/arch/unicore32/kernel/process.c b/arch/unicore32/kernel/process.c
index ddaf78ae6854..2bc10b8e9cf4 100644
--- a/arch/unicore32/kernel/process.c
+++ b/arch/unicore32/kernel/process.c
@@ -23,7 +23,6 @@
23#include <linux/delay.h> 23#include <linux/delay.h>
24#include <linux/reboot.h> 24#include <linux/reboot.h>
25#include <linux/interrupt.h> 25#include <linux/interrupt.h>
26#include <linux/kallsyms.h>
27#include <linux/init.h> 26#include <linux/init.h>
28#include <linux/cpu.h> 27#include <linux/cpu.h>
29#include <linux/elfcore.h> 28#include <linux/elfcore.h>
@@ -139,8 +138,8 @@ void __show_regs(struct pt_regs *regs)
139 char buf[64]; 138 char buf[64];
140 139
141 show_regs_print_info(KERN_DEFAULT); 140 show_regs_print_info(KERN_DEFAULT);
142 print_symbol("PC is at %s\n", instruction_pointer(regs)); 141 printk("PC is at %pS\n", (void *)instruction_pointer(regs));
143 print_symbol("LR is at %s\n", regs->UCreg_lr); 142 printk("LR is at %pS\n", (void *)regs->UCreg_lr);
144 printk(KERN_DEFAULT "pc : [<%08lx>] lr : [<%08lx>] psr: %08lx\n" 143 printk(KERN_DEFAULT "pc : [<%08lx>] lr : [<%08lx>] psr: %08lx\n"
145 "sp : %08lx ip : %08lx fp : %08lx\n", 144 "sp : %08lx ip : %08lx fp : %08lx\n",
146 regs->UCreg_pc, regs->UCreg_lr, regs->UCreg_asr, 145 regs->UCreg_pc, regs->UCreg_lr, regs->UCreg_asr,
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index ba1f9555fbc5..3a8e88a611eb 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -14,7 +14,6 @@
14#include <linux/capability.h> 14#include <linux/capability.h>
15#include <linux/miscdevice.h> 15#include <linux/miscdevice.h>
16#include <linux/ratelimit.h> 16#include <linux/ratelimit.h>
17#include <linux/kallsyms.h>
18#include <linux/rcupdate.h> 17#include <linux/rcupdate.h>
19#include <linux/kobject.h> 18#include <linux/kobject.h>
20#include <linux/uaccess.h> 19#include <linux/uaccess.h>
@@ -235,7 +234,7 @@ static void __print_mce(struct mce *m)
235 m->cs, m->ip); 234 m->cs, m->ip);
236 235
237 if (m->cs == __KERNEL_CS) 236 if (m->cs == __KERNEL_CS)
238 print_symbol("{%s}", m->ip); 237 pr_cont("{%pS}", (void *)m->ip);
239 pr_cont("\n"); 238 pr_cont("\n");
240 } 239 }
241 240
diff --git a/arch/x86/mm/mmio-mod.c b/arch/x86/mm/mmio-mod.c
index 4d434ddb75db..2c1ecf4763c4 100644
--- a/arch/x86/mm/mmio-mod.c
+++ b/arch/x86/mm/mmio-mod.c
@@ -29,7 +29,6 @@
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/uaccess.h> 30#include <linux/uaccess.h>
31#include <linux/io.h> 31#include <linux/io.h>
32#include <linux/kallsyms.h>
33#include <asm/pgtable.h> 32#include <asm/pgtable.h>
34#include <linux/mmiotrace.h> 33#include <linux/mmiotrace.h>
35#include <asm/e820/api.h> /* for ISA_START_ADDRESS */ 34#include <asm/e820/api.h> /* for ISA_START_ADDRESS */
@@ -123,8 +122,8 @@ static void die_kmmio_nesting_error(struct pt_regs *regs, unsigned long addr)
123 pr_emerg("unexpected fault for address: 0x%08lx, last fault for address: 0x%08lx\n", 122 pr_emerg("unexpected fault for address: 0x%08lx, last fault for address: 0x%08lx\n",
124 addr, my_reason->addr); 123 addr, my_reason->addr);
125 print_pte(addr); 124 print_pte(addr);
126 print_symbol(KERN_EMERG "faulting IP is at %s\n", regs->ip); 125 pr_emerg("faulting IP is at %pS\n", (void *)regs->ip);
127 print_symbol(KERN_EMERG "last faulting IP was at %s\n", my_reason->ip); 126 pr_emerg("last faulting IP was at %pS\n", (void *)my_reason->ip);
128#ifdef __i386__ 127#ifdef __i386__
129 pr_emerg("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n", 128 pr_emerg("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
130 regs->ax, regs->bx, regs->cx, regs->dx); 129 regs->ax, regs->bx, regs->cx, regs->dx);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 61515ef91184..b2261f92f2f1 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -20,7 +20,6 @@
20#include <linux/of.h> 20#include <linux/of.h>
21#include <linux/of_device.h> 21#include <linux/of_device.h>
22#include <linux/genhd.h> 22#include <linux/genhd.h>
23#include <linux/kallsyms.h>
24#include <linux/mutex.h> 23#include <linux/mutex.h>
25#include <linux/pm_runtime.h> 24#include <linux/pm_runtime.h>
26#include <linux/netdevice.h> 25#include <linux/netdevice.h>
@@ -685,8 +684,8 @@ static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr,
685 if (dev_attr->show) 684 if (dev_attr->show)
686 ret = dev_attr->show(dev, dev_attr, buf); 685 ret = dev_attr->show(dev, dev_attr, buf);
687 if (ret >= (ssize_t)PAGE_SIZE) { 686 if (ret >= (ssize_t)PAGE_SIZE) {
688 print_symbol("dev_attr_show: %s returned bad count\n", 687 printk("dev_attr_show: %pS returned bad count\n",
689 (unsigned long)dev_attr->show); 688 dev_attr->show);
690 } 689 }
691 return ret; 690 return ret;
692} 691}
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 39da8e86f10a..5c13f29bfcdb 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -11,7 +11,6 @@
11 11
12#include <linux/module.h> 12#include <linux/module.h>
13#include <linux/kobject.h> 13#include <linux/kobject.h>
14#include <linux/kallsyms.h>
15#include <linux/slab.h> 14#include <linux/slab.h>
16#include <linux/list.h> 15#include <linux/list.h>
17#include <linux/mutex.h> 16#include <linux/mutex.h>
@@ -69,8 +68,8 @@ static int sysfs_kf_seq_show(struct seq_file *sf, void *v)
69 * indicate truncated result or overflow in normal use cases. 68 * indicate truncated result or overflow in normal use cases.
70 */ 69 */
71 if (count >= (ssize_t)PAGE_SIZE) { 70 if (count >= (ssize_t)PAGE_SIZE) {
72 print_symbol("fill_read_buffer: %s returned bad count\n", 71 printk("fill_read_buffer: %pS returned bad count\n",
73 (unsigned long)ops->show); 72 ops->show);
74 /* Try to struggle along */ 73 /* Try to struggle along */
75 count = PAGE_SIZE - 1; 74 count = PAGE_SIZE - 1;
76 } 75 }
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 03cc5f9bba71..849cd8eb5ca0 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -30,6 +30,7 @@
30 * __ctors_start, __ctors_end 30 * __ctors_start, __ctors_end
31 * __irqentry_text_start, __irqentry_text_end 31 * __irqentry_text_start, __irqentry_text_end
32 * __softirqentry_text_start, __softirqentry_text_end 32 * __softirqentry_text_start, __softirqentry_text_end
33 * __start_opd, __end_opd
33 */ 34 */
34extern char _text[], _stext[], _etext[]; 35extern char _text[], _stext[], _etext[];
35extern char _data[], _sdata[], _edata[]; 36extern char _data[], _sdata[], _edata[];
@@ -49,12 +50,15 @@ extern char __start_once[], __end_once[];
49/* Start and end of .ctors section - used for constructor calls. */ 50/* Start and end of .ctors section - used for constructor calls. */
50extern char __ctors_start[], __ctors_end[]; 51extern char __ctors_start[], __ctors_end[];
51 52
53/* Start and end of .opd section - used for function descriptors. */
54extern char __start_opd[], __end_opd[];
55
52extern __visible const void __nosave_begin, __nosave_end; 56extern __visible const void __nosave_begin, __nosave_end;
53 57
54/* function descriptor handling (if any). Override 58/* Function descriptor handling (if any). Override in asm/sections.h */
55 * in asm/sections.h */
56#ifndef dereference_function_descriptor 59#ifndef dereference_function_descriptor
57#define dereference_function_descriptor(p) (p) 60#define dereference_function_descriptor(p) (p)
61#define dereference_kernel_function_descriptor(p) (p)
58#endif 62#endif
59 63
60/* random extra sections (if any). Override 64/* random extra sections (if any). Override
diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h
index bd118a6c60cb..d79d1e7486bd 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) + \
@@ -16,6 +20,56 @@
16 20
17struct module; 21struct module;
18 22
23static inline int is_kernel_inittext(unsigned long addr)
24{
25 if (addr >= (unsigned long)_sinittext
26 && addr <= (unsigned long)_einittext)
27 return 1;
28 return 0;
29}
30
31static inline int is_kernel_text(unsigned long addr)
32{
33 if ((addr >= (unsigned long)_stext && addr <= (unsigned long)_etext) ||
34 arch_is_kernel_text(addr))
35 return 1;
36 return in_gate_area_no_mm(addr);
37}
38
39static inline int is_kernel(unsigned long addr)
40{
41 if (addr >= (unsigned long)_stext && addr <= (unsigned long)_end)
42 return 1;
43 return in_gate_area_no_mm(addr);
44}
45
46static inline int is_ksym_addr(unsigned long addr)
47{
48 if (IS_ENABLED(CONFIG_KALLSYMS_ALL))
49 return is_kernel(addr);
50
51 return is_kernel_text(addr) || is_kernel_inittext(addr);
52}
53
54static inline void *dereference_symbol_descriptor(void *ptr)
55{
56#ifdef HAVE_DEREFERENCE_FUNCTION_DESCRIPTOR
57 struct module *mod;
58
59 ptr = dereference_kernel_function_descriptor(ptr);
60 if (is_ksym_addr((unsigned long)ptr))
61 return ptr;
62
63 preempt_disable();
64 mod = __module_address((unsigned long)ptr);
65 preempt_enable();
66
67 if (mod)
68 ptr = dereference_module_function_descriptor(mod, ptr);
69#endif
70 return ptr;
71}
72
19#ifdef CONFIG_KALLSYMS 73#ifdef CONFIG_KALLSYMS
20/* Lookup the address for a symbol. Returns 0 if not found. */ 74/* Lookup the address for a symbol. Returns 0 if not found. */
21unsigned long kallsyms_lookup_name(const char *name); 75unsigned long kallsyms_lookup_name(const char *name);
@@ -40,9 +94,6 @@ extern int sprint_symbol(char *buffer, unsigned long address);
40extern int sprint_symbol_no_offset(char *buffer, unsigned long address); 94extern int sprint_symbol_no_offset(char *buffer, unsigned long address);
41extern int sprint_backtrace(char *buffer, unsigned long address); 95extern int sprint_backtrace(char *buffer, unsigned long address);
42 96
43/* Look up a kernel symbol and print it to the kernel messages. */
44extern void __print_symbol(const char *fmt, unsigned long address);
45
46int lookup_symbol_name(unsigned long addr, char *symname); 97int lookup_symbol_name(unsigned long addr, char *symname);
47int lookup_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, char *name); 98int lookup_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, char *name);
48 99
@@ -112,23 +163,8 @@ static inline int kallsyms_show_value(void)
112 return false; 163 return false;
113} 164}
114 165
115/* Stupid that this does nothing, but I didn't create this mess. */
116#define __print_symbol(fmt, addr)
117#endif /*CONFIG_KALLSYMS*/ 166#endif /*CONFIG_KALLSYMS*/
118 167
119/* This macro allows us to keep printk typechecking */
120static __printf(1, 2)
121void __check_printsym_format(const char *fmt, ...)
122{
123}
124
125static inline void print_symbol(const char *fmt, unsigned long addr)
126{
127 __check_printsym_format(fmt, "");
128 __print_symbol(fmt, (unsigned long)
129 __builtin_extract_return_addr((void *)addr));
130}
131
132static inline void print_ip_sym(unsigned long ip) 168static inline void print_ip_sym(unsigned long ip)
133{ 169{
134 printk("[<%p>] %pS\n", (void *) ip, (void *) ip); 170 printk("[<%p>] %pS\n", (void *) ip, (void *) ip);
diff --git a/include/linux/module.h b/include/linux/module.h
index 70245f1a3590..8dc7065d904d 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -612,6 +612,9 @@ int ref_module(struct module *a, struct module *b);
612 __mod ? __mod->name : "kernel"; \ 612 __mod ? __mod->name : "kernel"; \
613}) 613})
614 614
615/* Dereference module function descriptor */
616void *dereference_module_function_descriptor(struct module *mod, void *ptr);
617
615/* For kallsyms to ask for address resolution. namebuf should be at 618/* For kallsyms to ask for address resolution. namebuf should be at
616 * least KSYM_NAME_LEN long: a pointer to namebuf is returned if 619 * least KSYM_NAME_LEN long: a pointer to namebuf is returned if
617 * found, otherwise NULL. */ 620 * found, otherwise NULL. */
@@ -766,6 +769,13 @@ static inline bool is_module_sig_enforced(void)
766 return false; 769 return false;
767} 770}
768 771
772/* Dereference module function descriptor */
773static inline
774void *dereference_module_function_descriptor(struct module *mod, void *ptr)
775{
776 return ptr;
777}
778
769#endif /* CONFIG_MODULES */ 779#endif /* CONFIG_MODULES */
770 780
771#ifdef CONFIG_SYSFS 781#ifdef CONFIG_SYSFS
diff --git a/kernel/irq/debug.h b/kernel/irq/debug.h
index e4d3819a91cc..8ccb326d2977 100644
--- a/kernel/irq/debug.h
+++ b/kernel/irq/debug.h
@@ -3,8 +3,6 @@
3 * Debugging printout: 3 * Debugging printout:
4 */ 4 */
5 5
6#include <linux/kallsyms.h>
7
8#define ___P(f) if (desc->status_use_accessors & f) printk("%14s set\n", #f) 6#define ___P(f) if (desc->status_use_accessors & f) printk("%14s set\n", #f)
9#define ___PS(f) if (desc->istate & f) printk("%14s set\n", #f) 7#define ___PS(f) if (desc->istate & f) printk("%14s set\n", #f)
10/* FIXME */ 8/* FIXME */
@@ -19,14 +17,14 @@ static inline void print_irq_desc(unsigned int irq, struct irq_desc *desc)
19 17
20 printk("irq %d, desc: %p, depth: %d, count: %d, unhandled: %d\n", 18 printk("irq %d, desc: %p, depth: %d, count: %d, unhandled: %d\n",
21 irq, desc, desc->depth, desc->irq_count, desc->irqs_unhandled); 19 irq, desc, desc->depth, desc->irq_count, desc->irqs_unhandled);
22 printk("->handle_irq(): %p, ", desc->handle_irq); 20 printk("->handle_irq(): %p, %pS\n",
23 print_symbol("%s\n", (unsigned long)desc->handle_irq); 21 desc->handle_irq, desc->handle_irq);
24 printk("->irq_data.chip(): %p, ", desc->irq_data.chip); 22 printk("->irq_data.chip(): %p, %pS\n",
25 print_symbol("%s\n", (unsigned long)desc->irq_data.chip); 23 desc->irq_data.chip, desc->irq_data.chip);
26 printk("->action(): %p\n", desc->action); 24 printk("->action(): %p\n", desc->action);
27 if (desc->action) { 25 if (desc->action) {
28 printk("->action->handler(): %p, ", desc->action->handler); 26 printk("->action->handler(): %p, %pS\n",
29 print_symbol("%s\n", (unsigned long)desc->action->handler); 27 desc->action->handler, desc->action->handler);
30 } 28 }
31 29
32 ___P(IRQ_LEVEL); 30 ___P(IRQ_LEVEL);
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index d5fa4116688a..a23e21ada81b 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,
@@ -464,17 +429,6 @@ int sprint_backtrace(char *buffer, unsigned long address)
464 return __sprint_symbol(buffer, address, -1, 1); 429 return __sprint_symbol(buffer, address, -1, 1);
465} 430}
466 431
467/* Look up a kernel symbol and print it to the kernel messages. */
468void __print_symbol(const char *fmt, unsigned long address)
469{
470 char buffer[KSYM_SYMBOL_LEN];
471
472 sprint_symbol(buffer, address);
473
474 printk(fmt, buffer);
475}
476EXPORT_SYMBOL(__print_symbol);
477
478/* To avoid using get_symbol_offset for every symbol, we carry prefix along. */ 432/* To avoid using get_symbol_offset for every symbol, we carry prefix along. */
479struct kallsym_iter { 433struct kallsym_iter {
480 loff_t pos; 434 loff_t pos;
diff --git a/kernel/module.c b/kernel/module.c
index 1d65b2cc4f80..ccdf24c4949e 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -3953,6 +3953,12 @@ static const char *get_ksymbol(struct module *mod,
3953 return symname(kallsyms, best); 3953 return symname(kallsyms, best);
3954} 3954}
3955 3955
3956void * __weak dereference_module_function_descriptor(struct module *mod,
3957 void *ptr)
3958{
3959 return ptr;
3960}
3961
3956/* For kallsyms to ask for address resolution. NULL means not found. Careful 3962/* For kallsyms to ask for address resolution. NULL means not found. Careful
3957 * not to lock to avoid deadlock on oopses, simply disable preemption. */ 3963 * not to lock to avoid deadlock on oopses, simply disable preemption. */
3958const char *module_address_lookup(unsigned long addr, 3964const char *module_address_lookup(unsigned long addr,
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index c2e713f6ae2e..db4b9b8929eb 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -131,13 +131,10 @@ static int __init control_devkmsg(char *str)
131 /* 131 /*
132 * Set sysctl string accordingly: 132 * Set sysctl string accordingly:
133 */ 133 */
134 if (devkmsg_log == DEVKMSG_LOG_MASK_ON) { 134 if (devkmsg_log == DEVKMSG_LOG_MASK_ON)
135 memset(devkmsg_log_str, 0, DEVKMSG_STR_MAX_SIZE); 135 strcpy(devkmsg_log_str, "on");
136 strncpy(devkmsg_log_str, "on", 2); 136 else if (devkmsg_log == DEVKMSG_LOG_MASK_OFF)
137 } else if (devkmsg_log == DEVKMSG_LOG_MASK_OFF) { 137 strcpy(devkmsg_log_str, "off");
138 memset(devkmsg_log_str, 0, DEVKMSG_STR_MAX_SIZE);
139 strncpy(devkmsg_log_str, "off", 3);
140 }
141 /* else "ratelimit" which is set by default. */ 138 /* else "ratelimit" which is set by default. */
142 139
143 /* 140 /*
@@ -277,6 +274,13 @@ EXPORT_SYMBOL(console_set_on_cmdline);
277/* Flag: console code may call schedule() */ 274/* Flag: console code may call schedule() */
278static int console_may_schedule; 275static int console_may_schedule;
279 276
277enum con_msg_format_flags {
278 MSG_FORMAT_DEFAULT = 0,
279 MSG_FORMAT_SYSLOG = (1 << 0),
280};
281
282static int console_msg_format = MSG_FORMAT_DEFAULT;
283
280/* 284/*
281 * The printk log buffer consists of a chain of concatenated variable 285 * The printk log buffer consists of a chain of concatenated variable
282 * length records. Every record starts with a record header, containing 286 * length records. Every record starts with a record header, containing
@@ -1544,6 +1548,146 @@ SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len)
1544} 1548}
1545 1549
1546/* 1550/*
1551 * Special console_lock variants that help to reduce the risk of soft-lockups.
1552 * They allow to pass console_lock to another printk() call using a busy wait.
1553 */
1554
1555#ifdef CONFIG_LOCKDEP
1556static struct lockdep_map console_owner_dep_map = {
1557 .name = "console_owner"
1558};
1559#endif
1560
1561static DEFINE_RAW_SPINLOCK(console_owner_lock);
1562static struct task_struct *console_owner;
1563static bool console_waiter;
1564
1565/**
1566 * console_lock_spinning_enable - mark beginning of code where another
1567 * thread might safely busy wait
1568 *
1569 * This basically converts console_lock into a spinlock. This marks
1570 * the section where the console_lock owner can not sleep, because
1571 * there may be a waiter spinning (like a spinlock). Also it must be
1572 * ready to hand over the lock at the end of the section.
1573 */
1574static void console_lock_spinning_enable(void)
1575{
1576 raw_spin_lock(&console_owner_lock);
1577 console_owner = current;
1578 raw_spin_unlock(&console_owner_lock);
1579
1580 /* The waiter may spin on us after setting console_owner */
1581 spin_acquire(&console_owner_dep_map, 0, 0, _THIS_IP_);
1582}
1583
1584/**
1585 * console_lock_spinning_disable_and_check - mark end of code where another
1586 * thread was able to busy wait and check if there is a waiter
1587 *
1588 * This is called at the end of the section where spinning is allowed.
1589 * It has two functions. First, it is a signal that it is no longer
1590 * safe to start busy waiting for the lock. Second, it checks if
1591 * there is a busy waiter and passes the lock rights to her.
1592 *
1593 * Important: Callers lose the lock if there was a busy waiter.
1594 * They must not touch items synchronized by console_lock
1595 * in this case.
1596 *
1597 * Return: 1 if the lock rights were passed, 0 otherwise.
1598 */
1599static int console_lock_spinning_disable_and_check(void)
1600{
1601 int waiter;
1602
1603 raw_spin_lock(&console_owner_lock);
1604 waiter = READ_ONCE(console_waiter);
1605 console_owner = NULL;
1606 raw_spin_unlock(&console_owner_lock);
1607
1608 if (!waiter) {
1609 spin_release(&console_owner_dep_map, 1, _THIS_IP_);
1610 return 0;
1611 }
1612
1613 /* The waiter is now free to continue */
1614 WRITE_ONCE(console_waiter, false);
1615
1616 spin_release(&console_owner_dep_map, 1, _THIS_IP_);
1617
1618 /*
1619 * Hand off console_lock to waiter. The waiter will perform
1620 * the up(). After this, the waiter is the console_lock owner.
1621 */
1622 mutex_release(&console_lock_dep_map, 1, _THIS_IP_);
1623 return 1;
1624}
1625
1626/**
1627 * console_trylock_spinning - try to get console_lock by busy waiting
1628 *
1629 * This allows to busy wait for the console_lock when the current
1630 * owner is running in specially marked sections. It means that
1631 * the current owner is running and cannot reschedule until it
1632 * is ready to lose the lock.
1633 *
1634 * Return: 1 if we got the lock, 0 othrewise
1635 */
1636static int console_trylock_spinning(void)
1637{
1638 struct task_struct *owner = NULL;
1639 bool waiter;
1640 bool spin = false;
1641 unsigned long flags;
1642
1643 if (console_trylock())
1644 return 1;
1645
1646 printk_safe_enter_irqsave(flags);
1647
1648 raw_spin_lock(&console_owner_lock);
1649 owner = READ_ONCE(console_owner);
1650 waiter = READ_ONCE(console_waiter);
1651 if (!waiter && owner && owner != current) {
1652 WRITE_ONCE(console_waiter, true);
1653 spin = true;
1654 }
1655 raw_spin_unlock(&console_owner_lock);
1656
1657 /*
1658 * If there is an active printk() writing to the
1659 * consoles, instead of having it write our data too,
1660 * see if we can offload that load from the active
1661 * printer, and do some printing ourselves.
1662 * Go into a spin only if there isn't already a waiter
1663 * spinning, and there is an active printer, and
1664 * that active printer isn't us (recursive printk?).
1665 */
1666 if (!spin) {
1667 printk_safe_exit_irqrestore(flags);
1668 return 0;
1669 }
1670
1671 /* We spin waiting for the owner to release us */
1672 spin_acquire(&console_owner_dep_map, 0, 0, _THIS_IP_);
1673 /* Owner will clear console_waiter on hand off */
1674 while (READ_ONCE(console_waiter))
1675 cpu_relax();
1676 spin_release(&console_owner_dep_map, 1, _THIS_IP_);
1677
1678 printk_safe_exit_irqrestore(flags);
1679 /*
1680 * The owner passed the console lock to us.
1681 * Since we did not spin on console lock, annotate
1682 * this as a trylock. Otherwise lockdep will
1683 * complain.
1684 */
1685 mutex_acquire(&console_lock_dep_map, 0, 1, _THIS_IP_);
1686
1687 return 1;
1688}
1689
1690/*
1547 * Call the console drivers, asking them to write out 1691 * Call the console drivers, asking them to write out
1548 * log_buf[start] to log_buf[end - 1]. 1692 * log_buf[start] to log_buf[end - 1].
1549 * The console_lock must be held. 1693 * The console_lock must be held.
@@ -1749,12 +1893,19 @@ asmlinkage int vprintk_emit(int facility, int level,
1749 /* If called from the scheduler, we can not call up(). */ 1893 /* If called from the scheduler, we can not call up(). */
1750 if (!in_sched) { 1894 if (!in_sched) {
1751 /* 1895 /*
1896 * Disable preemption to avoid being preempted while holding
1897 * console_sem which would prevent anyone from printing to
1898 * console
1899 */
1900 preempt_disable();
1901 /*
1752 * Try to acquire and then immediately release the console 1902 * Try to acquire and then immediately release the console
1753 * semaphore. The release will print out buffers and wake up 1903 * semaphore. The release will print out buffers and wake up
1754 * /dev/kmsg and syslog() users. 1904 * /dev/kmsg and syslog() users.
1755 */ 1905 */
1756 if (console_trylock()) 1906 if (console_trylock_spinning())
1757 console_unlock(); 1907 console_unlock();
1908 preempt_enable();
1758 } 1909 }
1759 1910
1760 return printed_len; 1911 return printed_len;
@@ -1855,6 +2006,8 @@ static ssize_t msg_print_ext_header(char *buf, size_t size,
1855static ssize_t msg_print_ext_body(char *buf, size_t size, 2006static ssize_t msg_print_ext_body(char *buf, size_t size,
1856 char *dict, size_t dict_len, 2007 char *dict, size_t dict_len,
1857 char *text, size_t text_len) { return 0; } 2008 char *text, size_t text_len) { return 0; }
2009static void console_lock_spinning_enable(void) { }
2010static int console_lock_spinning_disable_and_check(void) { return 0; }
1858static void call_console_drivers(const char *ext_text, size_t ext_len, 2011static void call_console_drivers(const char *ext_text, size_t ext_len,
1859 const char *text, size_t len) {} 2012 const char *text, size_t len) {}
1860static size_t msg_print_text(const struct printk_log *msg, 2013static size_t msg_print_text(const struct printk_log *msg,
@@ -1913,6 +2066,17 @@ static int __add_preferred_console(char *name, int idx, char *options,
1913 c->index = idx; 2066 c->index = idx;
1914 return 0; 2067 return 0;
1915} 2068}
2069
2070static int __init console_msg_format_setup(char *str)
2071{
2072 if (!strcmp(str, "syslog"))
2073 console_msg_format = MSG_FORMAT_SYSLOG;
2074 if (!strcmp(str, "default"))
2075 console_msg_format = MSG_FORMAT_DEFAULT;
2076 return 1;
2077}
2078__setup("console_msg_format=", console_msg_format_setup);
2079
1916/* 2080/*
1917 * Set up a console. Called via do_early_param() in init/main.c 2081 * Set up a console. Called via do_early_param() in init/main.c
1918 * for each "console=" parameter in the boot command line. 2082 * for each "console=" parameter in the boot command line.
@@ -2069,20 +2233,7 @@ int console_trylock(void)
2069 return 0; 2233 return 0;
2070 } 2234 }
2071 console_locked = 1; 2235 console_locked = 1;
2072 /* 2236 console_may_schedule = 0;
2073 * When PREEMPT_COUNT disabled we can't reliably detect if it's
2074 * safe to schedule (e.g. calling printk while holding a spin_lock),
2075 * because preempt_disable()/preempt_enable() are just barriers there
2076 * and preempt_count() is always 0.
2077 *
2078 * RCU read sections have a separate preemption counter when
2079 * PREEMPT_RCU enabled thus we must take extra care and check
2080 * rcu_preempt_depth(), otherwise RCU read sections modify
2081 * preempt_count().
2082 */
2083 console_may_schedule = !oops_in_progress &&
2084 preemptible() &&
2085 !rcu_preempt_depth();
2086 return 1; 2237 return 1;
2087} 2238}
2088EXPORT_SYMBOL(console_trylock); 2239EXPORT_SYMBOL(console_trylock);
@@ -2215,7 +2366,10 @@ skip:
2215 goto skip; 2366 goto skip;
2216 } 2367 }
2217 2368
2218 len += msg_print_text(msg, false, text + len, sizeof(text) - len); 2369 len += msg_print_text(msg,
2370 console_msg_format & MSG_FORMAT_SYSLOG,
2371 text + len,
2372 sizeof(text) - len);
2219 if (nr_ext_console_drivers) { 2373 if (nr_ext_console_drivers) {
2220 ext_len = msg_print_ext_header(ext_text, 2374 ext_len = msg_print_ext_header(ext_text,
2221 sizeof(ext_text), 2375 sizeof(ext_text),
@@ -2229,14 +2383,29 @@ skip:
2229 console_seq++; 2383 console_seq++;
2230 raw_spin_unlock(&logbuf_lock); 2384 raw_spin_unlock(&logbuf_lock);
2231 2385
2386 /*
2387 * While actively printing out messages, if another printk()
2388 * were to occur on another CPU, it may wait for this one to
2389 * finish. This task can not be preempted if there is a
2390 * waiter waiting to take over.
2391 */
2392 console_lock_spinning_enable();
2393
2232 stop_critical_timings(); /* don't trace print latency */ 2394 stop_critical_timings(); /* don't trace print latency */
2233 call_console_drivers(ext_text, ext_len, text, len); 2395 call_console_drivers(ext_text, ext_len, text, len);
2234 start_critical_timings(); 2396 start_critical_timings();
2397
2398 if (console_lock_spinning_disable_and_check()) {
2399 printk_safe_exit_irqrestore(flags);
2400 return;
2401 }
2402
2235 printk_safe_exit_irqrestore(flags); 2403 printk_safe_exit_irqrestore(flags);
2236 2404
2237 if (do_cond_resched) 2405 if (do_cond_resched)
2238 cond_resched(); 2406 cond_resched();
2239 } 2407 }
2408
2240 console_locked = 0; 2409 console_locked = 0;
2241 2410
2242 /* Release the exclusive_console once it is used */ 2411 /* Release the exclusive_console once it is used */
diff --git a/kernel/sched/autogroup.c b/kernel/sched/autogroup.c
index a43df5193538..bb4b9fe026a1 100644
--- a/kernel/sched/autogroup.c
+++ b/kernel/sched/autogroup.c
@@ -1,13 +1,12 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: GPL-2.0
2#include "sched.h"
3
4#include <linux/proc_fs.h> 2#include <linux/proc_fs.h>
5#include <linux/seq_file.h> 3#include <linux/seq_file.h>
6#include <linux/kallsyms.h>
7#include <linux/utsname.h> 4#include <linux/utsname.h>
8#include <linux/security.h> 5#include <linux/security.h>
9#include <linux/export.h> 6#include <linux/export.h>
10 7
8#include "sched.h"
9
11unsigned int __read_mostly sysctl_sched_autogroup_enabled = 1; 10unsigned int __read_mostly sysctl_sched_autogroup_enabled = 1;
12static struct autogroup autogroup_default; 11static struct autogroup autogroup_default;
13static atomic_t autogroup_seq_nr; 12static atomic_t autogroup_seq_nr;
diff --git a/lib/smp_processor_id.c b/lib/smp_processor_id.c
index 835cc6df2776..85925aaa4fff 100644
--- a/lib/smp_processor_id.c
+++ b/lib/smp_processor_id.c
@@ -5,7 +5,6 @@
5 * DEBUG_PREEMPT variant of smp_processor_id(). 5 * DEBUG_PREEMPT variant of smp_processor_id().
6 */ 6 */
7#include <linux/export.h> 7#include <linux/export.h>
8#include <linux/kallsyms.h>
9#include <linux/sched.h> 8#include <linux/sched.h>
10 9
11notrace static unsigned int check_preemption_disabled(const char *what1, 10notrace static unsigned int check_preemption_disabled(const char *what1,
@@ -43,7 +42,7 @@ notrace static unsigned int check_preemption_disabled(const char *what1,
43 printk(KERN_ERR "BUG: using %s%s() in preemptible [%08x] code: %s/%d\n", 42 printk(KERN_ERR "BUG: using %s%s() in preemptible [%08x] code: %s/%d\n",
44 what1, what2, preempt_count() - 1, current->comm, current->pid); 43 what1, what2, preempt_count() - 1, current->comm, current->pid);
45 44
46 print_symbol("caller is %s\n", (long)__builtin_return_address(0)); 45 printk("caller is %pS\n", __builtin_return_address(0));
47 dump_stack(); 46 dump_stack();
48 47
49out_enable: 48out_enable:
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 8f56cdd52149..77ee6ced11b1 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -42,7 +42,6 @@
42#include "../mm/internal.h" /* For the trace_print_flags arrays */ 42#include "../mm/internal.h" /* For the trace_print_flags arrays */
43 43
44#include <asm/page.h> /* for PAGE_SIZE */ 44#include <asm/page.h> /* for PAGE_SIZE */
45#include <asm/sections.h> /* for dereference_function_descriptor() */
46#include <asm/byteorder.h> /* cpu_to_le16 */ 45#include <asm/byteorder.h> /* cpu_to_le16 */
47 46
48#include <linux/string_helpers.h> 47#include <linux/string_helpers.h>
@@ -1863,10 +1862,10 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
1863 switch (*fmt) { 1862 switch (*fmt) {
1864 case 'F': 1863 case 'F':
1865 case 'f': 1864 case 'f':
1866 ptr = dereference_function_descriptor(ptr);
1867 /* Fallthrough */
1868 case 'S': 1865 case 'S':
1869 case 's': 1866 case 's':
1867 ptr = dereference_symbol_descriptor(ptr);
1868 /* Fallthrough */
1870 case 'B': 1869 case 'B':
1871 return symbol_string(buf, end, ptr, spec, fmt); 1870 return symbol_string(buf, end, ptr, spec, fmt);
1872 case 'R': 1871 case 'R':
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index ba03f17ff662..e954df2b2077 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -5759,18 +5759,25 @@ sub process {
5759 for (my $count = $linenr; $count <= $lc; $count++) { 5759 for (my $count = $linenr; $count <= $lc; $count++) {
5760 my $fmt = get_quoted_string($lines[$count - 1], raw_line($count, 0)); 5760 my $fmt = get_quoted_string($lines[$count - 1], raw_line($count, 0));
5761 $fmt =~ s/%%//g; 5761 $fmt =~ s/%%//g;
5762 if ($fmt =~ /(\%[\*\d\.]*p(?![\WFfSsBKRraEhMmIiUDdgVCbGNOx]).)/) { 5762 if ($fmt =~ /(\%[\*\d\.]*p(?![\WSsBKRraEhMmIiUDdgVCbGNOx]).)/) {
5763 $bad_extension = $1; 5763 $bad_extension = $1;
5764 last; 5764 last;
5765 } 5765 }
5766 } 5766 }
5767 if ($bad_extension ne "") { 5767 if ($bad_extension ne "") {
5768 my $stat_real = raw_line($linenr, 0); 5768 my $stat_real = raw_line($linenr, 0);
5769 my $ext_type = "Invalid";
5770 my $use = "";
5769 for (my $count = $linenr + 1; $count <= $lc; $count++) { 5771 for (my $count = $linenr + 1; $count <= $lc; $count++) {
5770 $stat_real = $stat_real . "\n" . raw_line($count, 0); 5772 $stat_real = $stat_real . "\n" . raw_line($count, 0);
5771 } 5773 }
5774 if ($bad_extension =~ /p[Ff]/) {
5775 $ext_type = "Deprecated";
5776 $use = " - use %pS instead";
5777 $use =~ s/pS/ps/ if ($bad_extension =~ /pf/);
5778 }
5772 WARN("VSPRINTF_POINTER_EXTENSION", 5779 WARN("VSPRINTF_POINTER_EXTENSION",
5773 "Invalid vsprintf pointer extension '$bad_extension'\n" . "$here\n$stat_real\n"); 5780 "$ext_type vsprintf pointer extension '$bad_extension'$use\n" . "$here\n$stat_real\n");
5774 } 5781 }
5775 } 5782 }
5776 5783