aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.osdl.org>2006-12-15 11:43:13 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-15 11:47:51 -0500
commitd1526e2cda64d5a1de56aef50bad9e5df14245c2 (patch)
treed7b490b1a11dd9720c9918733ca0c06e0e82cfba
parentd1998ef38a13c4e74c69df55ccd38b0440c429b2 (diff)
Remove stack unwinder for now
It has caused more problems than it ever really solved, and is apparently not getting cleaned up and fixed. We can put it back when it's stable and isn't likely to make warning or bug events worse. In the meantime, enable frame pointers for more readable stack traces. Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--Makefile5
-rw-r--r--arch/i386/defconfig2
-rw-r--r--arch/i386/kernel/entry.S32
-rw-r--r--arch/i386/kernel/traps.c83
-rw-r--r--arch/x86_64/Makefile2
-rw-r--r--arch/x86_64/defconfig2
-rw-r--r--arch/x86_64/kernel/entry.S33
-rw-r--r--arch/x86_64/kernel/traps.c84
-rw-r--r--arch/x86_64/kernel/vmlinux.lds.S2
-rw-r--r--include/asm-generic/vmlinux.lds.h22
-rw-r--r--include/asm-i386/unwind.h91
-rw-r--r--include/asm-x86_64/unwind.h96
-rw-r--r--include/linux/unwind.h63
-rw-r--r--kernel/Makefile1
-rw-r--r--kernel/unwind.c1305
-rw-r--r--lib/Kconfig.debug18
-rw-r--r--lib/fault-inject.c32
17 files changed, 3 insertions, 1870 deletions
diff --git a/Makefile b/Makefile
index dc82462b68ba..4a4720387936 100644
--- a/Makefile
+++ b/Makefile
@@ -496,11 +496,6 @@ else
496CFLAGS += -fomit-frame-pointer 496CFLAGS += -fomit-frame-pointer
497endif 497endif
498 498
499ifdef CONFIG_UNWIND_INFO
500CFLAGS += -fasynchronous-unwind-tables
501LDFLAGS_vmlinux += --eh-frame-hdr
502endif
503
504ifdef CONFIG_DEBUG_INFO 499ifdef CONFIG_DEBUG_INFO
505CFLAGS += -g 500CFLAGS += -g
506endif 501endif
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index 3265208e5899..e075ff05c46d 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -1493,8 +1493,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
1493# CONFIG_DEBUG_VM is not set 1493# CONFIG_DEBUG_VM is not set
1494# CONFIG_DEBUG_LIST is not set 1494# CONFIG_DEBUG_LIST is not set
1495# CONFIG_FRAME_POINTER is not set 1495# CONFIG_FRAME_POINTER is not set
1496CONFIG_UNWIND_INFO=y
1497CONFIG_STACK_UNWIND=y
1498# CONFIG_FORCED_INLINING is not set 1496# CONFIG_FORCED_INLINING is not set
1499# CONFIG_HEADERS_CHECK is not set 1497# CONFIG_HEADERS_CHECK is not set
1500# CONFIG_RCU_TORTURE_TEST is not set 1498# CONFIG_RCU_TORTURE_TEST is not set
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index de34b7fed3c1..06461b8b715d 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -979,38 +979,6 @@ ENTRY(spurious_interrupt_bug)
979 jmp error_code 979 jmp error_code
980 CFI_ENDPROC 980 CFI_ENDPROC
981 981
982#ifdef CONFIG_STACK_UNWIND
983ENTRY(arch_unwind_init_running)
984 CFI_STARTPROC
985 movl 4(%esp), %edx
986 movl (%esp), %ecx
987 leal 4(%esp), %eax
988 movl %ebx, PT_EBX(%edx)
989 xorl %ebx, %ebx
990 movl %ebx, PT_ECX(%edx)
991 movl %ebx, PT_EDX(%edx)
992 movl %esi, PT_ESI(%edx)
993 movl %edi, PT_EDI(%edx)
994 movl %ebp, PT_EBP(%edx)
995 movl %ebx, PT_EAX(%edx)
996 movl $__USER_DS, PT_DS(%edx)
997 movl $__USER_DS, PT_ES(%edx)
998 movl $0, PT_GS(%edx)
999 movl %ebx, PT_ORIG_EAX(%edx)
1000 movl %ecx, PT_EIP(%edx)
1001 movl 12(%esp), %ecx
1002 movl $__KERNEL_CS, PT_CS(%edx)
1003 movl %ebx, PT_EFLAGS(%edx)
1004 movl %eax, PT_OLDESP(%edx)
1005 movl 8(%esp), %eax
1006 movl %ecx, 8(%esp)
1007 movl PT_EBX(%edx), %ebx
1008 movl $__KERNEL_DS, PT_OLDSS(%edx)
1009 jmpl *%eax
1010 CFI_ENDPROC
1011ENDPROC(arch_unwind_init_running)
1012#endif
1013
1014ENTRY(kernel_thread_helper) 982ENTRY(kernel_thread_helper)
1015 pushl $0 # fake return address for unwinder 983 pushl $0 # fake return address for unwinder
1016 CFI_STARTPROC 984 CFI_STARTPROC
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 2b30dbf8d117..0efad8aeb41a 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -94,11 +94,6 @@ asmlinkage void spurious_interrupt_bug(void);
94asmlinkage void machine_check(void); 94asmlinkage void machine_check(void);
95 95
96int kstack_depth_to_print = 24; 96int kstack_depth_to_print = 24;
97#ifdef CONFIG_STACK_UNWIND
98static int call_trace = 1;
99#else
100#define call_trace (-1)
101#endif
102ATOMIC_NOTIFIER_HEAD(i386die_chain); 97ATOMIC_NOTIFIER_HEAD(i386die_chain);
103 98
104int register_die_notifier(struct notifier_block *nb) 99int register_die_notifier(struct notifier_block *nb)
@@ -152,33 +147,6 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo,
152 return ebp; 147 return ebp;
153} 148}
154 149
155struct ops_and_data {
156 struct stacktrace_ops *ops;
157 void *data;
158};
159
160static asmlinkage int
161dump_trace_unwind(struct unwind_frame_info *info, void *data)
162{
163 struct ops_and_data *oad = (struct ops_and_data *)data;
164 int n = 0;
165 unsigned long sp = UNW_SP(info);
166
167 if (arch_unw_user_mode(info))
168 return -1;
169 while (unwind(info) == 0 && UNW_PC(info)) {
170 n++;
171 oad->ops->address(oad->data, UNW_PC(info));
172 if (arch_unw_user_mode(info))
173 break;
174 if ((sp & ~(PAGE_SIZE - 1)) == (UNW_SP(info) & ~(PAGE_SIZE - 1))
175 && sp > UNW_SP(info))
176 break;
177 sp = UNW_SP(info);
178 }
179 return n;
180}
181
182#define MSG(msg) ops->warning(data, msg) 150#define MSG(msg) ops->warning(data, msg)
183 151
184void dump_trace(struct task_struct *task, struct pt_regs *regs, 152void dump_trace(struct task_struct *task, struct pt_regs *regs,
@@ -190,41 +158,6 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
190 if (!task) 158 if (!task)
191 task = current; 159 task = current;
192 160
193 if (call_trace >= 0) {
194 int unw_ret = 0;
195 struct unwind_frame_info info;
196 struct ops_and_data oad = { .ops = ops, .data = data };
197
198 if (regs) {
199 if (unwind_init_frame_info(&info, task, regs) == 0)
200 unw_ret = dump_trace_unwind(&info, &oad);
201 } else if (task == current)
202 unw_ret = unwind_init_running(&info, dump_trace_unwind,
203 &oad);
204 else {
205 if (unwind_init_blocked(&info, task) == 0)
206 unw_ret = dump_trace_unwind(&info, &oad);
207 }
208 if (unw_ret > 0) {
209 if (call_trace == 1 && !arch_unw_user_mode(&info)) {
210 ops->warning_symbol(data,
211 "DWARF2 unwinder stuck at %s",
212 UNW_PC(&info));
213 if (UNW_SP(&info) >= PAGE_OFFSET) {
214 MSG("Leftover inexact backtrace:");
215 stack = (void *)UNW_SP(&info);
216 if (!stack)
217 return;
218 ebp = UNW_FP(&info);
219 } else
220 MSG("Full inexact backtrace again:");
221 } else if (call_trace >= 1)
222 return;
223 else
224 MSG("Full inexact backtrace again:");
225 } else
226 MSG("Inexact backtrace:");
227 }
228 if (!stack) { 161 if (!stack) {
229 unsigned long dummy; 162 unsigned long dummy;
230 stack = &dummy; 163 stack = &dummy;
@@ -1258,19 +1191,3 @@ static int __init kstack_setup(char *s)
1258 return 1; 1191 return 1;
1259} 1192}
1260__setup("kstack=", kstack_setup); 1193__setup("kstack=", kstack_setup);
1261
1262#ifdef CONFIG_STACK_UNWIND
1263static int __init call_trace_setup(char *s)
1264{
1265 if (strcmp(s, "old") == 0)
1266 call_trace = -1;
1267 else if (strcmp(s, "both") == 0)
1268 call_trace = 0;
1269 else if (strcmp(s, "newfallback") == 0)
1270 call_trace = 1;
1271 else if (strcmp(s, "new") == 2)
1272 call_trace = 2;
1273 return 1;
1274}
1275__setup("call_trace=", call_trace_setup);
1276#endif
diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile
index b471b8550d03..2941a915d4ef 100644
--- a/arch/x86_64/Makefile
+++ b/arch/x86_64/Makefile
@@ -45,9 +45,7 @@ cflags-kernel-$(CONFIG_REORDER) += -ffunction-sections
45# actually it makes the kernel smaller too. 45# actually it makes the kernel smaller too.
46cflags-y += -fno-reorder-blocks 46cflags-y += -fno-reorder-blocks
47cflags-y += -Wno-sign-compare 47cflags-y += -Wno-sign-compare
48ifneq ($(CONFIG_UNWIND_INFO),y)
49cflags-y += -fno-asynchronous-unwind-tables 48cflags-y += -fno-asynchronous-unwind-tables
50endif
51ifneq ($(CONFIG_DEBUG_INFO),y) 49ifneq ($(CONFIG_DEBUG_INFO),y)
52# -fweb shrinks the kernel a bit, but the difference is very small 50# -fweb shrinks the kernel a bit, but the difference is very small
53# it also messes up debugging, so don't use it for now. 51# it also messes up debugging, so don't use it for now.
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index 1a1c6a1a299b..ac80b1209fc0 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -1523,8 +1523,6 @@ CONFIG_DEBUG_FS=y
1523# CONFIG_DEBUG_VM is not set 1523# CONFIG_DEBUG_VM is not set
1524# CONFIG_DEBUG_LIST is not set 1524# CONFIG_DEBUG_LIST is not set
1525# CONFIG_FRAME_POINTER is not set 1525# CONFIG_FRAME_POINTER is not set
1526CONFIG_UNWIND_INFO=y
1527CONFIG_STACK_UNWIND=y
1528# CONFIG_FORCED_INLINING is not set 1526# CONFIG_FORCED_INLINING is not set
1529# CONFIG_HEADERS_CHECK is not set 1527# CONFIG_HEADERS_CHECK is not set
1530# CONFIG_RCU_TORTURE_TEST is not set 1528# CONFIG_RCU_TORTURE_TEST is not set
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index 601d332c4b79..9f5dac64aa8f 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -1155,36 +1155,3 @@ ENTRY(call_softirq)
1155 ret 1155 ret
1156 CFI_ENDPROC 1156 CFI_ENDPROC
1157ENDPROC(call_softirq) 1157ENDPROC(call_softirq)
1158
1159#ifdef CONFIG_STACK_UNWIND
1160ENTRY(arch_unwind_init_running)
1161 CFI_STARTPROC
1162 movq %r15, R15(%rdi)
1163 movq %r14, R14(%rdi)
1164 xchgq %rsi, %rdx
1165 movq %r13, R13(%rdi)
1166 movq %r12, R12(%rdi)
1167 xorl %eax, %eax
1168 movq %rbp, RBP(%rdi)
1169 movq %rbx, RBX(%rdi)
1170 movq (%rsp), %rcx
1171 movq %rax, R11(%rdi)
1172 movq %rax, R10(%rdi)
1173 movq %rax, R9(%rdi)
1174 movq %rax, R8(%rdi)
1175 movq %rax, RAX(%rdi)
1176 movq %rax, RCX(%rdi)
1177 movq %rax, RDX(%rdi)
1178 movq %rax, RSI(%rdi)
1179 movq %rax, RDI(%rdi)
1180 movq %rax, ORIG_RAX(%rdi)
1181 movq %rcx, RIP(%rdi)
1182 leaq 8(%rsp), %rcx
1183 movq $__KERNEL_CS, CS(%rdi)
1184 movq %rax, EFLAGS(%rdi)
1185 movq %rcx, RSP(%rdi)
1186 movq $__KERNEL_DS, SS(%rdi)
1187 jmpq *%rdx
1188 CFI_ENDPROC
1189ENDPROC(arch_unwind_init_running)
1190#endif
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index b54ccc07f379..1d9eb6db732a 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -110,11 +110,6 @@ static inline void preempt_conditional_cli(struct pt_regs *regs)
110} 110}
111 111
112int kstack_depth_to_print = 12; 112int kstack_depth_to_print = 12;
113#ifdef CONFIG_STACK_UNWIND
114static int call_trace = 1;
115#else
116#define call_trace (-1)
117#endif
118 113
119#ifdef CONFIG_KALLSYMS 114#ifdef CONFIG_KALLSYMS
120void printk_address(unsigned long address) 115void printk_address(unsigned long address)
@@ -217,32 +212,6 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
217 return NULL; 212 return NULL;
218} 213}
219 214
220struct ops_and_data {
221 struct stacktrace_ops *ops;
222 void *data;
223};
224
225static int dump_trace_unwind(struct unwind_frame_info *info, void *context)
226{
227 struct ops_and_data *oad = (struct ops_and_data *)context;
228 int n = 0;
229 unsigned long sp = UNW_SP(info);
230
231 if (arch_unw_user_mode(info))
232 return -1;
233 while (unwind(info) == 0 && UNW_PC(info)) {
234 n++;
235 oad->ops->address(oad->data, UNW_PC(info));
236 if (arch_unw_user_mode(info))
237 break;
238 if ((sp & ~(PAGE_SIZE - 1)) == (UNW_SP(info) & ~(PAGE_SIZE - 1))
239 && sp > UNW_SP(info))
240 break;
241 sp = UNW_SP(info);
242 }
243 return n;
244}
245
246#define MSG(txt) ops->warning(data, txt) 215#define MSG(txt) ops->warning(data, txt)
247 216
248/* 217/*
@@ -270,40 +239,6 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
270 if (!tsk) 239 if (!tsk)
271 tsk = current; 240 tsk = current;
272 241
273 if (call_trace >= 0) {
274 int unw_ret = 0;
275 struct unwind_frame_info info;
276 struct ops_and_data oad = { .ops = ops, .data = data };
277
278 if (regs) {
279 if (unwind_init_frame_info(&info, tsk, regs) == 0)
280 unw_ret = dump_trace_unwind(&info, &oad);
281 } else if (tsk == current)
282 unw_ret = unwind_init_running(&info, dump_trace_unwind,
283 &oad);
284 else {
285 if (unwind_init_blocked(&info, tsk) == 0)
286 unw_ret = dump_trace_unwind(&info, &oad);
287 }
288 if (unw_ret > 0) {
289 if (call_trace == 1 && !arch_unw_user_mode(&info)) {
290 ops->warning_symbol(data,
291 "DWARF2 unwinder stuck at %s",
292 UNW_PC(&info));
293 if ((long)UNW_SP(&info) < 0) {
294 MSG("Leftover inexact backtrace:");
295 stack = (unsigned long *)UNW_SP(&info);
296 if (!stack)
297 goto out;
298 } else
299 MSG("Full inexact backtrace again:");
300 } else if (call_trace >= 1)
301 goto out;
302 else
303 MSG("Full inexact backtrace again:");
304 } else
305 MSG("Inexact backtrace:");
306 }
307 if (!stack) { 242 if (!stack) {
308 unsigned long dummy; 243 unsigned long dummy;
309 stack = &dummy; 244 stack = &dummy;
@@ -387,7 +322,6 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
387 tinfo = current_thread_info(); 322 tinfo = current_thread_info();
388 HANDLE_STACK (valid_stack_ptr(tinfo, stack)); 323 HANDLE_STACK (valid_stack_ptr(tinfo, stack));
389#undef HANDLE_STACK 324#undef HANDLE_STACK
390out:
391 put_cpu(); 325 put_cpu();
392} 326}
393EXPORT_SYMBOL(dump_trace); 327EXPORT_SYMBOL(dump_trace);
@@ -1188,21 +1122,3 @@ static int __init kstack_setup(char *s)
1188 return 0; 1122 return 0;
1189} 1123}
1190early_param("kstack", kstack_setup); 1124early_param("kstack", kstack_setup);
1191
1192#ifdef CONFIG_STACK_UNWIND
1193static int __init call_trace_setup(char *s)
1194{
1195 if (!s)
1196 return -EINVAL;
1197 if (strcmp(s, "old") == 0)
1198 call_trace = -1;
1199 else if (strcmp(s, "both") == 0)
1200 call_trace = 0;
1201 else if (strcmp(s, "newfallback") == 0)
1202 call_trace = 1;
1203 else if (strcmp(s, "new") == 0)
1204 call_trace = 2;
1205 return 0;
1206}
1207early_param("call_trace", call_trace_setup);
1208#endif
diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
index 514be5dd2303..1e54ddf2338d 100644
--- a/arch/x86_64/kernel/vmlinux.lds.S
+++ b/arch/x86_64/kernel/vmlinux.lds.S
@@ -221,9 +221,7 @@ SECTIONS
221 /* Sections to be discarded */ 221 /* Sections to be discarded */
222 /DISCARD/ : { 222 /DISCARD/ : {
223 *(.exitcall.exit) 223 *(.exitcall.exit)
224#ifndef CONFIG_UNWIND_INFO
225 *(.eh_frame) 224 *(.eh_frame)
226#endif
227 } 225 }
228 226
229 STABS_DEBUG 227 STABS_DEBUG
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 7437ccaada77..1587121730c5 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -119,8 +119,6 @@
119 *(__ksymtab_strings) \ 119 *(__ksymtab_strings) \
120 } \ 120 } \
121 \ 121 \
122 EH_FRAME \
123 \
124 /* Built-in module parameters. */ \ 122 /* Built-in module parameters. */ \
125 __param : AT(ADDR(__param) - LOAD_OFFSET) { \ 123 __param : AT(ADDR(__param) - LOAD_OFFSET) { \
126 VMLINUX_SYMBOL(__start___param) = .; \ 124 VMLINUX_SYMBOL(__start___param) = .; \
@@ -160,26 +158,6 @@
160 *(.kprobes.text) \ 158 *(.kprobes.text) \
161 VMLINUX_SYMBOL(__kprobes_text_end) = .; 159 VMLINUX_SYMBOL(__kprobes_text_end) = .;
162 160
163#ifdef CONFIG_STACK_UNWIND
164#define EH_FRAME \
165 /* Unwind data binary search table */ \
166 . = ALIGN(8); \
167 .eh_frame_hdr : AT(ADDR(.eh_frame_hdr) - LOAD_OFFSET) { \
168 VMLINUX_SYMBOL(__start_unwind_hdr) = .; \
169 *(.eh_frame_hdr) \
170 VMLINUX_SYMBOL(__end_unwind_hdr) = .; \
171 } \
172 /* Unwind data */ \
173 . = ALIGN(8); \
174 .eh_frame : AT(ADDR(.eh_frame) - LOAD_OFFSET) { \
175 VMLINUX_SYMBOL(__start_unwind) = .; \
176 *(.eh_frame) \
177 VMLINUX_SYMBOL(__end_unwind) = .; \
178 }
179#else
180#define EH_FRAME
181#endif
182
183 /* DWARF debug sections. 161 /* DWARF debug sections.
184 Symbols in the DWARF debugging sections are relative to 162 Symbols in the DWARF debugging sections are relative to
185 the beginning of the section so we begin them at 0. */ 163 the beginning of the section so we begin them at 0. */
diff --git a/include/asm-i386/unwind.h b/include/asm-i386/unwind.h
index aa2c931e30db..43c70c3de2f9 100644
--- a/include/asm-i386/unwind.h
+++ b/include/asm-i386/unwind.h
@@ -1,95 +1,6 @@
1#ifndef _ASM_I386_UNWIND_H 1#ifndef _ASM_I386_UNWIND_H
2#define _ASM_I386_UNWIND_H 2#define _ASM_I386_UNWIND_H
3 3
4/*
5 * Copyright (C) 2002-2006 Novell, Inc.
6 * Jan Beulich <jbeulich@novell.com>
7 * This code is released under version 2 of the GNU GPL.
8 */
9
10#ifdef CONFIG_STACK_UNWIND
11
12#include <linux/sched.h>
13#include <asm/fixmap.h>
14#include <asm/ptrace.h>
15#include <asm/uaccess.h>
16
17struct unwind_frame_info
18{
19 struct pt_regs regs;
20 struct task_struct *task;
21 unsigned call_frame:1;
22};
23
24#define UNW_PC(frame) (frame)->regs.eip
25#define UNW_SP(frame) (frame)->regs.esp
26#ifdef CONFIG_FRAME_POINTER
27#define UNW_FP(frame) (frame)->regs.ebp
28#define FRAME_RETADDR_OFFSET 4
29#define FRAME_LINK_OFFSET 0
30#define STACK_BOTTOM(tsk) STACK_LIMIT((tsk)->thread.esp0)
31#define STACK_TOP(tsk) ((tsk)->thread.esp0)
32#else
33#define UNW_FP(frame) ((void)(frame), 0)
34#endif
35#define STACK_LIMIT(ptr) (((ptr) - 1) & ~(THREAD_SIZE - 1))
36
37#define UNW_REGISTER_INFO \
38 PTREGS_INFO(eax), \
39 PTREGS_INFO(ecx), \
40 PTREGS_INFO(edx), \
41 PTREGS_INFO(ebx), \
42 PTREGS_INFO(esp), \
43 PTREGS_INFO(ebp), \
44 PTREGS_INFO(esi), \
45 PTREGS_INFO(edi), \
46 PTREGS_INFO(eip)
47
48#define UNW_DEFAULT_RA(raItem, dataAlign) \
49 ((raItem).where == Memory && \
50 !((raItem).value * (dataAlign) + 4))
51
52static inline void arch_unw_init_frame_info(struct unwind_frame_info *info,
53 /*const*/ struct pt_regs *regs)
54{
55 if (user_mode_vm(regs))
56 info->regs = *regs;
57 else {
58 memcpy(&info->regs, regs, offsetof(struct pt_regs, esp));
59 info->regs.esp = (unsigned long)&regs->esp;
60 info->regs.xss = __KERNEL_DS;
61 }
62}
63
64static inline void arch_unw_init_blocked(struct unwind_frame_info *info)
65{
66 memset(&info->regs, 0, sizeof(info->regs));
67 info->regs.eip = info->task->thread.eip;
68 info->regs.xcs = __KERNEL_CS;
69 __get_user(info->regs.ebp, (long *)info->task->thread.esp);
70 info->regs.esp = info->task->thread.esp;
71 info->regs.xss = __KERNEL_DS;
72 info->regs.xds = __USER_DS;
73 info->regs.xes = __USER_DS;
74 info->regs.xgs = __KERNEL_PDA;
75}
76
77extern asmlinkage int arch_unwind_init_running(struct unwind_frame_info *,
78 asmlinkage int (*callback)(struct unwind_frame_info *,
79 void *arg),
80 void *arg);
81
82static inline int arch_unw_user_mode(/*const*/ struct unwind_frame_info *info)
83{
84 return user_mode_vm(&info->regs)
85 || info->regs.eip < PAGE_OFFSET
86 || (info->regs.eip >= __fix_to_virt(FIX_VDSO)
87 && info->regs.eip < __fix_to_virt(FIX_VDSO) + PAGE_SIZE)
88 || info->regs.esp < PAGE_OFFSET;
89}
90
91#else
92
93#define UNW_PC(frame) ((void)(frame), 0) 4#define UNW_PC(frame) ((void)(frame), 0)
94#define UNW_SP(frame) ((void)(frame), 0) 5#define UNW_SP(frame) ((void)(frame), 0)
95#define UNW_FP(frame) ((void)(frame), 0) 6#define UNW_FP(frame) ((void)(frame), 0)
@@ -99,6 +10,4 @@ static inline int arch_unw_user_mode(const void *info)
99 return 0; 10 return 0;
100} 11}
101 12
102#endif
103
104#endif /* _ASM_I386_UNWIND_H */ 13#endif /* _ASM_I386_UNWIND_H */
diff --git a/include/asm-x86_64/unwind.h b/include/asm-x86_64/unwind.h
index 2f6349e48717..02710f6a4560 100644
--- a/include/asm-x86_64/unwind.h
+++ b/include/asm-x86_64/unwind.h
@@ -1,100 +1,6 @@
1#ifndef _ASM_X86_64_UNWIND_H 1#ifndef _ASM_X86_64_UNWIND_H
2#define _ASM_X86_64_UNWIND_H 2#define _ASM_X86_64_UNWIND_H
3 3
4/*
5 * Copyright (C) 2002-2006 Novell, Inc.
6 * Jan Beulich <jbeulich@novell.com>
7 * This code is released under version 2 of the GNU GPL.
8 */
9
10#ifdef CONFIG_STACK_UNWIND
11
12#include <linux/sched.h>
13#include <asm/ptrace.h>
14#include <asm/uaccess.h>
15#include <asm/vsyscall.h>
16
17struct unwind_frame_info
18{
19 struct pt_regs regs;
20 struct task_struct *task;
21 unsigned call_frame:1;
22};
23
24#define UNW_PC(frame) (frame)->regs.rip
25#define UNW_SP(frame) (frame)->regs.rsp
26#ifdef CONFIG_FRAME_POINTER
27#define UNW_FP(frame) (frame)->regs.rbp
28#define FRAME_RETADDR_OFFSET 8
29#define FRAME_LINK_OFFSET 0
30#define STACK_BOTTOM(tsk) (((tsk)->thread.rsp0 - 1) & ~(THREAD_SIZE - 1))
31#define STACK_TOP(tsk) ((tsk)->thread.rsp0)
32#endif
33/* Might need to account for the special exception and interrupt handling
34 stacks here, since normally
35 EXCEPTION_STACK_ORDER < THREAD_ORDER < IRQSTACK_ORDER,
36 but the construct is needed only for getting across the stack switch to
37 the interrupt stack - thus considering the IRQ stack itself is unnecessary,
38 and the overhead of comparing against all exception handling stacks seems
39 not desirable. */
40#define STACK_LIMIT(ptr) (((ptr) - 1) & ~(THREAD_SIZE - 1))
41
42#define UNW_REGISTER_INFO \
43 PTREGS_INFO(rax), \
44 PTREGS_INFO(rdx), \
45 PTREGS_INFO(rcx), \
46 PTREGS_INFO(rbx), \
47 PTREGS_INFO(rsi), \
48 PTREGS_INFO(rdi), \
49 PTREGS_INFO(rbp), \
50 PTREGS_INFO(rsp), \
51 PTREGS_INFO(r8), \
52 PTREGS_INFO(r9), \
53 PTREGS_INFO(r10), \
54 PTREGS_INFO(r11), \
55 PTREGS_INFO(r12), \
56 PTREGS_INFO(r13), \
57 PTREGS_INFO(r14), \
58 PTREGS_INFO(r15), \
59 PTREGS_INFO(rip)
60
61#define UNW_DEFAULT_RA(raItem, dataAlign) \
62 ((raItem).where == Memory && \
63 !((raItem).value * (dataAlign) + 8))
64
65static inline void arch_unw_init_frame_info(struct unwind_frame_info *info,
66 /*const*/ struct pt_regs *regs)
67{
68 info->regs = *regs;
69}
70
71static inline void arch_unw_init_blocked(struct unwind_frame_info *info)
72{
73 extern const char thread_return[];
74
75 memset(&info->regs, 0, sizeof(info->regs));
76 info->regs.rip = (unsigned long)thread_return;
77 info->regs.cs = __KERNEL_CS;
78 __get_user(info->regs.rbp, (unsigned long *)info->task->thread.rsp);
79 info->regs.rsp = info->task->thread.rsp;
80 info->regs.ss = __KERNEL_DS;
81}
82
83extern int arch_unwind_init_running(struct unwind_frame_info *,
84 int (*callback)(struct unwind_frame_info *,
85 void *arg),
86 void *arg);
87
88static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
89{
90 return user_mode(&info->regs)
91 || (long)info->regs.rip >= 0
92 || (info->regs.rip >= VSYSCALL_START && info->regs.rip < VSYSCALL_END)
93 || (long)info->regs.rsp >= 0;
94}
95
96#else
97
98#define UNW_PC(frame) ((void)(frame), 0UL) 4#define UNW_PC(frame) ((void)(frame), 0UL)
99#define UNW_SP(frame) ((void)(frame), 0UL) 5#define UNW_SP(frame) ((void)(frame), 0UL)
100 6
@@ -103,6 +9,4 @@ static inline int arch_unw_user_mode(const void *info)
103 return 0; 9 return 0;
104} 10}
105 11
106#endif
107
108#endif /* _ASM_X86_64_UNWIND_H */ 12#endif /* _ASM_X86_64_UNWIND_H */
diff --git a/include/linux/unwind.h b/include/linux/unwind.h
index 749928c161fb..7760860fa170 100644
--- a/include/linux/unwind.h
+++ b/include/linux/unwind.h
@@ -14,63 +14,6 @@
14 14
15struct module; 15struct module;
16 16
17#ifdef CONFIG_STACK_UNWIND
18
19#include <asm/unwind.h>
20
21#ifndef ARCH_UNWIND_SECTION_NAME
22#define ARCH_UNWIND_SECTION_NAME ".eh_frame"
23#endif
24
25/*
26 * Initialize unwind support.
27 */
28extern void unwind_init(void);
29extern void unwind_setup(void);
30
31#ifdef CONFIG_MODULES
32
33extern void *unwind_add_table(struct module *,
34 const void *table_start,
35 unsigned long table_size);
36
37extern void unwind_remove_table(void *handle, int init_only);
38
39#endif
40
41extern int unwind_init_frame_info(struct unwind_frame_info *,
42 struct task_struct *,
43 /*const*/ struct pt_regs *);
44
45/*
46 * Prepare to unwind a blocked task.
47 */
48extern int unwind_init_blocked(struct unwind_frame_info *,
49 struct task_struct *);
50
51/*
52 * Prepare to unwind the currently running thread.
53 */
54extern int unwind_init_running(struct unwind_frame_info *,
55 asmlinkage int (*callback)(struct unwind_frame_info *,
56 void *arg),
57 void *arg);
58
59/*
60 * Unwind to previous to frame. Returns 0 if successful, negative
61 * number in case of an error.
62 */
63extern int unwind(struct unwind_frame_info *);
64
65/*
66 * Unwind until the return pointer is in user-land (or until an error
67 * occurs). Returns 0 if successful, negative number in case of
68 * error.
69 */
70extern int unwind_to_user(struct unwind_frame_info *);
71
72#else
73
74struct unwind_frame_info {}; 17struct unwind_frame_info {};
75 18
76static inline void unwind_init(void) {} 19static inline void unwind_init(void) {}
@@ -85,12 +28,12 @@ static inline void *unwind_add_table(struct module *mod,
85 return NULL; 28 return NULL;
86} 29}
87 30
88#endif
89
90static inline void unwind_remove_table(void *handle, int init_only) 31static inline void unwind_remove_table(void *handle, int init_only)
91{ 32{
92} 33}
93 34
35#endif
36
94static inline int unwind_init_frame_info(struct unwind_frame_info *info, 37static inline int unwind_init_frame_info(struct unwind_frame_info *info,
95 struct task_struct *tsk, 38 struct task_struct *tsk,
96 const struct pt_regs *regs) 39 const struct pt_regs *regs)
@@ -122,6 +65,4 @@ static inline int unwind_to_user(struct unwind_frame_info *info)
122 return -ENOSYS; 65 return -ENOSYS;
123} 66}
124 67
125#endif
126
127#endif /* _LINUX_UNWIND_H */ 68#endif /* _LINUX_UNWIND_H */
diff --git a/kernel/Makefile b/kernel/Makefile
index 5e3f3b75563a..14f4d45e0ae9 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -31,7 +31,6 @@ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o
31obj-$(CONFIG_UID16) += uid16.o 31obj-$(CONFIG_UID16) += uid16.o
32obj-$(CONFIG_MODULES) += module.o 32obj-$(CONFIG_MODULES) += module.o
33obj-$(CONFIG_KALLSYMS) += kallsyms.o 33obj-$(CONFIG_KALLSYMS) += kallsyms.o
34obj-$(CONFIG_STACK_UNWIND) += unwind.o
35obj-$(CONFIG_PM) += power/ 34obj-$(CONFIG_PM) += power/
36obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o 35obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
37obj-$(CONFIG_KEXEC) += kexec.o 36obj-$(CONFIG_KEXEC) += kexec.o
diff --git a/kernel/unwind.c b/kernel/unwind.c
deleted file mode 100644
index 09c261329249..000000000000
--- a/kernel/unwind.c
+++ /dev/null
@@ -1,1305 +0,0 @@
1/*
2 * Copyright (C) 2002-2006 Novell, Inc.
3 * Jan Beulich <jbeulich@novell.com>
4 * This code is released under version 2 of the GNU GPL.
5 *
6 * A simple API for unwinding kernel stacks. This is used for
7 * debugging and error reporting purposes. The kernel doesn't need
8 * full-blown stack unwinding with all the bells and whistles, so there
9 * is not much point in implementing the full Dwarf2 unwind API.
10 */
11
12#include <linux/unwind.h>
13#include <linux/module.h>
14#include <linux/bootmem.h>
15#include <linux/sort.h>
16#include <linux/stop_machine.h>
17#include <linux/uaccess.h>
18#include <asm/sections.h>
19#include <asm/uaccess.h>
20#include <asm/unaligned.h>
21
22extern const char __start_unwind[], __end_unwind[];
23extern const u8 __start_unwind_hdr[], __end_unwind_hdr[];
24
25#define MAX_STACK_DEPTH 8
26
27#define EXTRA_INFO(f) { \
28 BUILD_BUG_ON_ZERO(offsetof(struct unwind_frame_info, f) \
29 % FIELD_SIZEOF(struct unwind_frame_info, f)) \
30 + offsetof(struct unwind_frame_info, f) \
31 / FIELD_SIZEOF(struct unwind_frame_info, f), \
32 FIELD_SIZEOF(struct unwind_frame_info, f) \
33 }
34#define PTREGS_INFO(f) EXTRA_INFO(regs.f)
35
36static const struct {
37 unsigned offs:BITS_PER_LONG / 2;
38 unsigned width:BITS_PER_LONG / 2;
39} reg_info[] = {
40 UNW_REGISTER_INFO
41};
42
43#undef PTREGS_INFO
44#undef EXTRA_INFO
45
46#ifndef REG_INVALID
47#define REG_INVALID(r) (reg_info[r].width == 0)
48#endif
49
50#define DW_CFA_nop 0x00
51#define DW_CFA_set_loc 0x01
52#define DW_CFA_advance_loc1 0x02
53#define DW_CFA_advance_loc2 0x03
54#define DW_CFA_advance_loc4 0x04
55#define DW_CFA_offset_extended 0x05
56#define DW_CFA_restore_extended 0x06
57#define DW_CFA_undefined 0x07
58#define DW_CFA_same_value 0x08
59#define DW_CFA_register 0x09
60#define DW_CFA_remember_state 0x0a
61#define DW_CFA_restore_state 0x0b
62#define DW_CFA_def_cfa 0x0c
63#define DW_CFA_def_cfa_register 0x0d
64#define DW_CFA_def_cfa_offset 0x0e
65#define DW_CFA_def_cfa_expression 0x0f
66#define DW_CFA_expression 0x10
67#define DW_CFA_offset_extended_sf 0x11
68#define DW_CFA_def_cfa_sf 0x12
69#define DW_CFA_def_cfa_offset_sf 0x13
70#define DW_CFA_val_offset 0x14
71#define DW_CFA_val_offset_sf 0x15
72#define DW_CFA_val_expression 0x16
73#define DW_CFA_lo_user 0x1c
74#define DW_CFA_GNU_window_save 0x2d
75#define DW_CFA_GNU_args_size 0x2e
76#define DW_CFA_GNU_negative_offset_extended 0x2f
77#define DW_CFA_hi_user 0x3f
78
79#define DW_EH_PE_FORM 0x07
80#define DW_EH_PE_native 0x00
81#define DW_EH_PE_leb128 0x01
82#define DW_EH_PE_data2 0x02
83#define DW_EH_PE_data4 0x03
84#define DW_EH_PE_data8 0x04
85#define DW_EH_PE_signed 0x08
86#define DW_EH_PE_ADJUST 0x70
87#define DW_EH_PE_abs 0x00
88#define DW_EH_PE_pcrel 0x10
89#define DW_EH_PE_textrel 0x20
90#define DW_EH_PE_datarel 0x30
91#define DW_EH_PE_funcrel 0x40
92#define DW_EH_PE_aligned 0x50
93#define DW_EH_PE_indirect 0x80
94#define DW_EH_PE_omit 0xff
95
96typedef unsigned long uleb128_t;
97typedef signed long sleb128_t;
98#define sleb128abs __builtin_labs
99
100static struct unwind_table {
101 struct {
102 unsigned long pc;
103 unsigned long range;
104 } core, init;
105 const void *address;
106 unsigned long size;
107 const unsigned char *header;
108 unsigned long hdrsz;
109 struct unwind_table *link;
110 const char *name;
111} root_table;
112
113struct unwind_item {
114 enum item_location {
115 Nowhere,
116 Memory,
117 Register,
118 Value
119 } where;
120 uleb128_t value;
121};
122
123struct unwind_state {
124 uleb128_t loc, org;
125 const u8 *cieStart, *cieEnd;
126 uleb128_t codeAlign;
127 sleb128_t dataAlign;
128 struct cfa {
129 uleb128_t reg, offs;
130 } cfa;
131 struct unwind_item regs[ARRAY_SIZE(reg_info)];
132 unsigned stackDepth:8;
133 unsigned version:8;
134 const u8 *label;
135 const u8 *stack[MAX_STACK_DEPTH];
136};
137
138static const struct cfa badCFA = { ARRAY_SIZE(reg_info), 1 };
139
140static unsigned unwind_debug;
141static int __init unwind_debug_setup(char *s)
142{
143 unwind_debug = simple_strtoul(s, NULL, 0);
144 return 1;
145}
146__setup("unwind_debug=", unwind_debug_setup);
147#define dprintk(lvl, fmt, args...) \
148 ((void)(lvl > unwind_debug \
149 || printk(KERN_DEBUG "unwind: " fmt "\n", ##args)))
150
151static struct unwind_table *find_table(unsigned long pc)
152{
153 struct unwind_table *table;
154
155 for (table = &root_table; table; table = table->link)
156 if ((pc >= table->core.pc
157 && pc < table->core.pc + table->core.range)
158 || (pc >= table->init.pc
159 && pc < table->init.pc + table->init.range))
160 break;
161
162 return table;
163}
164
165static unsigned long read_pointer(const u8 **pLoc,
166 const void *end,
167 signed ptrType,
168 unsigned long text_base,
169 unsigned long data_base);
170
171static void init_unwind_table(struct unwind_table *table,
172 const char *name,
173 const void *core_start,
174 unsigned long core_size,
175 const void *init_start,
176 unsigned long init_size,
177 const void *table_start,
178 unsigned long table_size,
179 const u8 *header_start,
180 unsigned long header_size)
181{
182 const u8 *ptr = header_start + 4;
183 const u8 *end = header_start + header_size;
184
185 table->core.pc = (unsigned long)core_start;
186 table->core.range = core_size;
187 table->init.pc = (unsigned long)init_start;
188 table->init.range = init_size;
189 table->address = table_start;
190 table->size = table_size;
191 /* See if the linker provided table looks valid. */
192 if (header_size <= 4
193 || header_start[0] != 1
194 || (void *)read_pointer(&ptr, end, header_start[1], 0, 0)
195 != table_start
196 || !read_pointer(&ptr, end, header_start[2], 0, 0)
197 || !read_pointer(&ptr, end, header_start[3], 0,
198 (unsigned long)header_start)
199 || !read_pointer(&ptr, end, header_start[3], 0,
200 (unsigned long)header_start))
201 header_start = NULL;
202 table->hdrsz = header_size;
203 smp_wmb();
204 table->header = header_start;
205 table->link = NULL;
206 table->name = name;
207}
208
209void __init unwind_init(void)
210{
211 init_unwind_table(&root_table, "kernel",
212 _text, _end - _text,
213 NULL, 0,
214 __start_unwind, __end_unwind - __start_unwind,
215 __start_unwind_hdr, __end_unwind_hdr - __start_unwind_hdr);
216}
217
218static const u32 bad_cie, not_fde;
219static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *);
220static signed fde_pointer_type(const u32 *cie);
221
222struct eh_frame_hdr_table_entry {
223 unsigned long start, fde;
224};
225
226static int cmp_eh_frame_hdr_table_entries(const void *p1, const void *p2)
227{
228 const struct eh_frame_hdr_table_entry *e1 = p1;
229 const struct eh_frame_hdr_table_entry *e2 = p2;
230
231 return (e1->start > e2->start) - (e1->start < e2->start);
232}
233
234static void swap_eh_frame_hdr_table_entries(void *p1, void *p2, int size)
235{
236 struct eh_frame_hdr_table_entry *e1 = p1;
237 struct eh_frame_hdr_table_entry *e2 = p2;
238 unsigned long v;
239
240 v = e1->start;
241 e1->start = e2->start;
242 e2->start = v;
243 v = e1->fde;
244 e1->fde = e2->fde;
245 e2->fde = v;
246}
247
248static void __init setup_unwind_table(struct unwind_table *table,
249 void *(*alloc)(unsigned long))
250{
251 const u8 *ptr;
252 unsigned long tableSize = table->size, hdrSize;
253 unsigned n;
254 const u32 *fde;
255 struct {
256 u8 version;
257 u8 eh_frame_ptr_enc;
258 u8 fde_count_enc;
259 u8 table_enc;
260 unsigned long eh_frame_ptr;
261 unsigned int fde_count;
262 struct eh_frame_hdr_table_entry table[];
263 } __attribute__((__packed__)) *header;
264
265 if (table->header)
266 return;
267
268 if (table->hdrsz)
269 printk(KERN_WARNING ".eh_frame_hdr for '%s' present but unusable\n",
270 table->name);
271
272 if (tableSize & (sizeof(*fde) - 1))
273 return;
274
275 for (fde = table->address, n = 0;
276 tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
277 tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
278 const u32 *cie = cie_for_fde(fde, table);
279 signed ptrType;
280
281 if (cie == &not_fde)
282 continue;
283 if (cie == NULL
284 || cie == &bad_cie
285 || (ptrType = fde_pointer_type(cie)) < 0)
286 return;
287 ptr = (const u8 *)(fde + 2);
288 if (!read_pointer(&ptr,
289 (const u8 *)(fde + 1) + *fde,
290 ptrType, 0, 0))
291 return;
292 ++n;
293 }
294
295 if (tableSize || !n)
296 return;
297
298 hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int)
299 + 2 * n * sizeof(unsigned long);
300 dprintk(2, "Binary lookup table size for %s: %lu bytes", table->name, hdrSize);
301 header = alloc(hdrSize);
302 if (!header)
303 return;
304 header->version = 1;
305 header->eh_frame_ptr_enc = DW_EH_PE_abs|DW_EH_PE_native;
306 header->fde_count_enc = DW_EH_PE_abs|DW_EH_PE_data4;
307 header->table_enc = DW_EH_PE_abs|DW_EH_PE_native;
308 put_unaligned((unsigned long)table->address, &header->eh_frame_ptr);
309 BUILD_BUG_ON(offsetof(typeof(*header), fde_count)
310 % __alignof(typeof(header->fde_count)));
311 header->fde_count = n;
312
313 BUILD_BUG_ON(offsetof(typeof(*header), table)
314 % __alignof(typeof(*header->table)));
315 for (fde = table->address, tableSize = table->size, n = 0;
316 tableSize;
317 tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
318 const u32 *cie = fde + 1 - fde[1] / sizeof(*fde);
319
320 if (!fde[1])
321 continue; /* this is a CIE */
322 ptr = (const u8 *)(fde + 2);
323 header->table[n].start = read_pointer(&ptr,
324 (const u8 *)(fde + 1) + *fde,
325 fde_pointer_type(cie), 0, 0);
326 header->table[n].fde = (unsigned long)fde;
327 ++n;
328 }
329 WARN_ON(n != header->fde_count);
330
331 sort(header->table,
332 n,
333 sizeof(*header->table),
334 cmp_eh_frame_hdr_table_entries,
335 swap_eh_frame_hdr_table_entries);
336
337 table->hdrsz = hdrSize;
338 smp_wmb();
339 table->header = (const void *)header;
340}
341
342static void *__init balloc(unsigned long sz)
343{
344 return __alloc_bootmem_nopanic(sz,
345 sizeof(unsigned int),
346 __pa(MAX_DMA_ADDRESS));
347}
348
349void __init unwind_setup(void)
350{
351 setup_unwind_table(&root_table, balloc);
352}
353
354#ifdef CONFIG_MODULES
355
356static struct unwind_table *last_table;
357
358/* Must be called with module_mutex held. */
359void *unwind_add_table(struct module *module,
360 const void *table_start,
361 unsigned long table_size)
362{
363 struct unwind_table *table;
364
365 if (table_size <= 0)
366 return NULL;
367
368 table = kmalloc(sizeof(*table), GFP_KERNEL);
369 if (!table)
370 return NULL;
371
372 init_unwind_table(table, module->name,
373 module->module_core, module->core_size,
374 module->module_init, module->init_size,
375 table_start, table_size,
376 NULL, 0);
377
378 if (last_table)
379 last_table->link = table;
380 else
381 root_table.link = table;
382 last_table = table;
383
384 return table;
385}
386
387struct unlink_table_info
388{
389 struct unwind_table *table;
390 int init_only;
391};
392
393static int unlink_table(void *arg)
394{
395 struct unlink_table_info *info = arg;
396 struct unwind_table *table = info->table, *prev;
397
398 for (prev = &root_table; prev->link && prev->link != table; prev = prev->link)
399 ;
400
401 if (prev->link) {
402 if (info->init_only) {
403 table->init.pc = 0;
404 table->init.range = 0;
405 info->table = NULL;
406 } else {
407 prev->link = table->link;
408 if (!prev->link)
409 last_table = prev;
410 }
411 } else
412 info->table = NULL;
413
414 return 0;
415}
416
417/* Must be called with module_mutex held. */
418void unwind_remove_table(void *handle, int init_only)
419{
420 struct unwind_table *table = handle;
421 struct unlink_table_info info;
422
423 if (!table || table == &root_table)
424 return;
425
426 if (init_only && table == last_table) {
427 table->init.pc = 0;
428 table->init.range = 0;
429 return;
430 }
431
432 info.table = table;
433 info.init_only = init_only;
434 stop_machine_run(unlink_table, &info, NR_CPUS);
435
436 if (info.table)
437 kfree(table);
438}
439
440#endif /* CONFIG_MODULES */
441
442static uleb128_t get_uleb128(const u8 **pcur, const u8 *end)
443{
444 const u8 *cur = *pcur;
445 uleb128_t value;
446 unsigned shift;
447
448 for (shift = 0, value = 0; cur < end; shift += 7) {
449 if (shift + 7 > 8 * sizeof(value)
450 && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
451 cur = end + 1;
452 break;
453 }
454 value |= (uleb128_t)(*cur & 0x7f) << shift;
455 if (!(*cur++ & 0x80))
456 break;
457 }
458 *pcur = cur;
459
460 return value;
461}
462
463static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
464{
465 const u8 *cur = *pcur;
466 sleb128_t value;
467 unsigned shift;
468
469 for (shift = 0, value = 0; cur < end; shift += 7) {
470 if (shift + 7 > 8 * sizeof(value)
471 && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
472 cur = end + 1;
473 break;
474 }
475 value |= (sleb128_t)(*cur & 0x7f) << shift;
476 if (!(*cur & 0x80)) {
477 value |= -(*cur++ & 0x40) << shift;
478 break;
479 }
480 }
481 *pcur = cur;
482
483 return value;
484}
485
486static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *table)
487{
488 const u32 *cie;
489
490 if (!*fde || (*fde & (sizeof(*fde) - 1)))
491 return &bad_cie;
492 if (!fde[1])
493 return &not_fde; /* this is a CIE */
494 if ((fde[1] & (sizeof(*fde) - 1))
495 || fde[1] > (unsigned long)(fde + 1) - (unsigned long)table->address)
496 return NULL; /* this is not a valid FDE */
497 cie = fde + 1 - fde[1] / sizeof(*fde);
498 if (*cie <= sizeof(*cie) + 4
499 || *cie >= fde[1] - sizeof(*fde)
500 || (*cie & (sizeof(*cie) - 1))
501 || cie[1])
502 return NULL; /* this is not a (valid) CIE */
503 return cie;
504}
505
506static unsigned long read_pointer(const u8 **pLoc,
507 const void *end,
508 signed ptrType,
509 unsigned long text_base,
510 unsigned long data_base)
511{
512 unsigned long value = 0;
513 union {
514 const u8 *p8;
515 const u16 *p16u;
516 const s16 *p16s;
517 const u32 *p32u;
518 const s32 *p32s;
519 const unsigned long *pul;
520 } ptr;
521
522 if (ptrType < 0 || ptrType == DW_EH_PE_omit) {
523 dprintk(1, "Invalid pointer encoding %02X (%p,%p).", ptrType, *pLoc, end);
524 return 0;
525 }
526 ptr.p8 = *pLoc;
527 switch(ptrType & DW_EH_PE_FORM) {
528 case DW_EH_PE_data2:
529 if (end < (const void *)(ptr.p16u + 1)) {
530 dprintk(1, "Data16 overrun (%p,%p).", ptr.p8, end);
531 return 0;
532 }
533 if(ptrType & DW_EH_PE_signed)
534 value = get_unaligned(ptr.p16s++);
535 else
536 value = get_unaligned(ptr.p16u++);
537 break;
538 case DW_EH_PE_data4:
539#ifdef CONFIG_64BIT
540 if (end < (const void *)(ptr.p32u + 1)) {
541 dprintk(1, "Data32 overrun (%p,%p).", ptr.p8, end);
542 return 0;
543 }
544 if(ptrType & DW_EH_PE_signed)
545 value = get_unaligned(ptr.p32s++);
546 else
547 value = get_unaligned(ptr.p32u++);
548 break;
549 case DW_EH_PE_data8:
550 BUILD_BUG_ON(sizeof(u64) != sizeof(value));
551#else
552 BUILD_BUG_ON(sizeof(u32) != sizeof(value));
553#endif
554 case DW_EH_PE_native:
555 if (end < (const void *)(ptr.pul + 1)) {
556 dprintk(1, "DataUL overrun (%p,%p).", ptr.p8, end);
557 return 0;
558 }
559 value = get_unaligned(ptr.pul++);
560 break;
561 case DW_EH_PE_leb128:
562 BUILD_BUG_ON(sizeof(uleb128_t) > sizeof(value));
563 value = ptrType & DW_EH_PE_signed
564 ? get_sleb128(&ptr.p8, end)
565 : get_uleb128(&ptr.p8, end);
566 if ((const void *)ptr.p8 > end) {
567 dprintk(1, "DataLEB overrun (%p,%p).", ptr.p8, end);
568 return 0;
569 }
570 break;
571 default:
572 dprintk(2, "Cannot decode pointer type %02X (%p,%p).",
573 ptrType, ptr.p8, end);
574 return 0;
575 }
576 switch(ptrType & DW_EH_PE_ADJUST) {
577 case DW_EH_PE_abs:
578 break;
579 case DW_EH_PE_pcrel:
580 value += (unsigned long)*pLoc;
581 break;
582 case DW_EH_PE_textrel:
583 if (likely(text_base)) {
584 value += text_base;
585 break;
586 }
587 dprintk(2, "Text-relative encoding %02X (%p,%p), but zero text base.",
588 ptrType, *pLoc, end);
589 return 0;
590 case DW_EH_PE_datarel:
591 if (likely(data_base)) {
592 value += data_base;
593 break;
594 }
595 dprintk(2, "Data-relative encoding %02X (%p,%p), but zero data base.",
596 ptrType, *pLoc, end);
597 return 0;
598 default:
599 dprintk(2, "Cannot adjust pointer type %02X (%p,%p).",
600 ptrType, *pLoc, end);
601 return 0;
602 }
603 if ((ptrType & DW_EH_PE_indirect)
604 && probe_kernel_address((unsigned long *)value, value)) {
605 dprintk(1, "Cannot read indirect value %lx (%p,%p).",
606 value, *pLoc, end);
607 return 0;
608 }
609 *pLoc = ptr.p8;
610
611 return value;
612}
613
614static signed fde_pointer_type(const u32 *cie)
615{
616 const u8 *ptr = (const u8 *)(cie + 2);
617 unsigned version = *ptr;
618
619 if (version != 1)
620 return -1; /* unsupported */
621 if (*++ptr) {
622 const char *aug;
623 const u8 *end = (const u8 *)(cie + 1) + *cie;
624 uleb128_t len;
625
626 /* check if augmentation size is first (and thus present) */
627 if (*ptr != 'z')
628 return -1;
629 /* check if augmentation string is nul-terminated */
630 if ((ptr = memchr(aug = (const void *)ptr, 0, end - ptr)) == NULL)
631 return -1;
632 ++ptr; /* skip terminator */
633 get_uleb128(&ptr, end); /* skip code alignment */
634 get_sleb128(&ptr, end); /* skip data alignment */
635 /* skip return address column */
636 version <= 1 ? (void)++ptr : (void)get_uleb128(&ptr, end);
637 len = get_uleb128(&ptr, end); /* augmentation length */
638 if (ptr + len < ptr || ptr + len > end)
639 return -1;
640 end = ptr + len;
641 while (*++aug) {
642 if (ptr >= end)
643 return -1;
644 switch(*aug) {
645 case 'L':
646 ++ptr;
647 break;
648 case 'P': {
649 signed ptrType = *ptr++;
650
651 if (!read_pointer(&ptr, end, ptrType, 0, 0)
652 || ptr > end)
653 return -1;
654 }
655 break;
656 case 'R':
657 return *ptr;
658 default:
659 return -1;
660 }
661 }
662 }
663 return DW_EH_PE_native|DW_EH_PE_abs;
664}
665
666static int advance_loc(unsigned long delta, struct unwind_state *state)
667{
668 state->loc += delta * state->codeAlign;
669
670 return delta > 0;
671}
672
673static void set_rule(uleb128_t reg,
674 enum item_location where,
675 uleb128_t value,
676 struct unwind_state *state)
677{
678 if (reg < ARRAY_SIZE(state->regs)) {
679 state->regs[reg].where = where;
680 state->regs[reg].value = value;
681 }
682}
683
684static int processCFI(const u8 *start,
685 const u8 *end,
686 unsigned long targetLoc,
687 signed ptrType,
688 struct unwind_state *state)
689{
690 union {
691 const u8 *p8;
692 const u16 *p16;
693 const u32 *p32;
694 } ptr;
695 int result = 1;
696
697 if (start != state->cieStart) {
698 state->loc = state->org;
699 result = processCFI(state->cieStart, state->cieEnd, 0, ptrType, state);
700 if (targetLoc == 0 && state->label == NULL)
701 return result;
702 }
703 for (ptr.p8 = start; result && ptr.p8 < end; ) {
704 switch(*ptr.p8 >> 6) {
705 uleb128_t value;
706
707 case 0:
708 switch(*ptr.p8++) {
709 case DW_CFA_nop:
710 break;
711 case DW_CFA_set_loc:
712 state->loc = read_pointer(&ptr.p8, end, ptrType, 0, 0);
713 if (state->loc == 0)
714 result = 0;
715 break;
716 case DW_CFA_advance_loc1:
717 result = ptr.p8 < end && advance_loc(*ptr.p8++, state);
718 break;
719 case DW_CFA_advance_loc2:
720 result = ptr.p8 <= end + 2
721 && advance_loc(*ptr.p16++, state);
722 break;
723 case DW_CFA_advance_loc4:
724 result = ptr.p8 <= end + 4
725 && advance_loc(*ptr.p32++, state);
726 break;
727 case DW_CFA_offset_extended:
728 value = get_uleb128(&ptr.p8, end);
729 set_rule(value, Memory, get_uleb128(&ptr.p8, end), state);
730 break;
731 case DW_CFA_val_offset:
732 value = get_uleb128(&ptr.p8, end);
733 set_rule(value, Value, get_uleb128(&ptr.p8, end), state);
734 break;
735 case DW_CFA_offset_extended_sf:
736 value = get_uleb128(&ptr.p8, end);
737 set_rule(value, Memory, get_sleb128(&ptr.p8, end), state);
738 break;
739 case DW_CFA_val_offset_sf:
740 value = get_uleb128(&ptr.p8, end);
741 set_rule(value, Value, get_sleb128(&ptr.p8, end), state);
742 break;
743 case DW_CFA_restore_extended:
744 case DW_CFA_undefined:
745 case DW_CFA_same_value:
746 set_rule(get_uleb128(&ptr.p8, end), Nowhere, 0, state);
747 break;
748 case DW_CFA_register:
749 value = get_uleb128(&ptr.p8, end);
750 set_rule(value,
751 Register,
752 get_uleb128(&ptr.p8, end), state);
753 break;
754 case DW_CFA_remember_state:
755 if (ptr.p8 == state->label) {
756 state->label = NULL;
757 return 1;
758 }
759 if (state->stackDepth >= MAX_STACK_DEPTH) {
760 dprintk(1, "State stack overflow (%p,%p).", ptr.p8, end);
761 return 0;
762 }
763 state->stack[state->stackDepth++] = ptr.p8;
764 break;
765 case DW_CFA_restore_state:
766 if (state->stackDepth) {
767 const uleb128_t loc = state->loc;
768 const u8 *label = state->label;
769
770 state->label = state->stack[state->stackDepth - 1];
771 memcpy(&state->cfa, &badCFA, sizeof(state->cfa));
772 memset(state->regs, 0, sizeof(state->regs));
773 state->stackDepth = 0;
774 result = processCFI(start, end, 0, ptrType, state);
775 state->loc = loc;
776 state->label = label;
777 } else {
778 dprintk(1, "State stack underflow (%p,%p).", ptr.p8, end);
779 return 0;
780 }
781 break;
782 case DW_CFA_def_cfa:
783 state->cfa.reg = get_uleb128(&ptr.p8, end);
784 /*nobreak*/
785 case DW_CFA_def_cfa_offset:
786 state->cfa.offs = get_uleb128(&ptr.p8, end);
787 break;
788 case DW_CFA_def_cfa_sf:
789 state->cfa.reg = get_uleb128(&ptr.p8, end);
790 /*nobreak*/
791 case DW_CFA_def_cfa_offset_sf:
792 state->cfa.offs = get_sleb128(&ptr.p8, end)
793 * state->dataAlign;
794 break;
795 case DW_CFA_def_cfa_register:
796 state->cfa.reg = get_uleb128(&ptr.p8, end);
797 break;
798 /*todo case DW_CFA_def_cfa_expression: */
799 /*todo case DW_CFA_expression: */
800 /*todo case DW_CFA_val_expression: */
801 case DW_CFA_GNU_args_size:
802 get_uleb128(&ptr.p8, end);
803 break;
804 case DW_CFA_GNU_negative_offset_extended:
805 value = get_uleb128(&ptr.p8, end);
806 set_rule(value,
807 Memory,
808 (uleb128_t)0 - get_uleb128(&ptr.p8, end), state);
809 break;
810 case DW_CFA_GNU_window_save:
811 default:
812 dprintk(1, "Unrecognized CFI op %02X (%p,%p).", ptr.p8[-1], ptr.p8 - 1, end);
813 result = 0;
814 break;
815 }
816 break;
817 case 1:
818 result = advance_loc(*ptr.p8++ & 0x3f, state);
819 break;
820 case 2:
821 value = *ptr.p8++ & 0x3f;
822 set_rule(value, Memory, get_uleb128(&ptr.p8, end), state);
823 break;
824 case 3:
825 set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state);
826 break;
827 }
828 if (ptr.p8 > end) {
829 dprintk(1, "Data overrun (%p,%p).", ptr.p8, end);
830 result = 0;
831 }
832 if (result && targetLoc != 0 && targetLoc < state->loc)
833 return 1;
834 }
835
836 if (result && ptr.p8 < end)
837 dprintk(1, "Data underrun (%p,%p).", ptr.p8, end);
838
839 return result
840 && ptr.p8 == end
841 && (targetLoc == 0
842 || (/*todo While in theory this should apply, gcc in practice omits
843 everything past the function prolog, and hence the location
844 never reaches the end of the function.
845 targetLoc < state->loc &&*/ state->label == NULL));
846}
847
848/* Unwind to previous to frame. Returns 0 if successful, negative
849 * number in case of an error. */
850int unwind(struct unwind_frame_info *frame)
851{
852#define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs])
853 const u32 *fde = NULL, *cie = NULL;
854 const u8 *ptr = NULL, *end = NULL;
855 unsigned long pc = UNW_PC(frame) - frame->call_frame, sp;
856 unsigned long startLoc = 0, endLoc = 0, cfa;
857 unsigned i;
858 signed ptrType = -1;
859 uleb128_t retAddrReg = 0;
860 const struct unwind_table *table;
861 struct unwind_state state;
862
863 if (UNW_PC(frame) == 0)
864 return -EINVAL;
865 if ((table = find_table(pc)) != NULL
866 && !(table->size & (sizeof(*fde) - 1))) {
867 const u8 *hdr = table->header;
868 unsigned long tableSize;
869
870 smp_rmb();
871 if (hdr && hdr[0] == 1) {
872 switch(hdr[3] & DW_EH_PE_FORM) {
873 case DW_EH_PE_native: tableSize = sizeof(unsigned long); break;
874 case DW_EH_PE_data2: tableSize = 2; break;
875 case DW_EH_PE_data4: tableSize = 4; break;
876 case DW_EH_PE_data8: tableSize = 8; break;
877 default: tableSize = 0; break;
878 }
879 ptr = hdr + 4;
880 end = hdr + table->hdrsz;
881 if (tableSize
882 && read_pointer(&ptr, end, hdr[1], 0, 0)
883 == (unsigned long)table->address
884 && (i = read_pointer(&ptr, end, hdr[2], 0, 0)) > 0
885 && i == (end - ptr) / (2 * tableSize)
886 && !((end - ptr) % (2 * tableSize))) {
887 do {
888 const u8 *cur = ptr + (i / 2) * (2 * tableSize);
889
890 startLoc = read_pointer(&cur,
891 cur + tableSize,
892 hdr[3], 0,
893 (unsigned long)hdr);
894 if (pc < startLoc)
895 i /= 2;
896 else {
897 ptr = cur - tableSize;
898 i = (i + 1) / 2;
899 }
900 } while (startLoc && i > 1);
901 if (i == 1
902 && (startLoc = read_pointer(&ptr,
903 ptr + tableSize,
904 hdr[3], 0,
905 (unsigned long)hdr)) != 0
906 && pc >= startLoc)
907 fde = (void *)read_pointer(&ptr,
908 ptr + tableSize,
909 hdr[3], 0,
910 (unsigned long)hdr);
911 }
912 }
913 if(hdr && !fde)
914 dprintk(3, "Binary lookup for %lx failed.", pc);
915
916 if (fde != NULL) {
917 cie = cie_for_fde(fde, table);
918 ptr = (const u8 *)(fde + 2);
919 if(cie != NULL
920 && cie != &bad_cie
921 && cie != &not_fde
922 && (ptrType = fde_pointer_type(cie)) >= 0
923 && read_pointer(&ptr,
924 (const u8 *)(fde + 1) + *fde,
925 ptrType, 0, 0) == startLoc) {
926 if (!(ptrType & DW_EH_PE_indirect))
927 ptrType &= DW_EH_PE_FORM|DW_EH_PE_signed;
928 endLoc = startLoc
929 + read_pointer(&ptr,
930 (const u8 *)(fde + 1) + *fde,
931 ptrType, 0, 0);
932 if(pc >= endLoc)
933 fde = NULL;
934 } else
935 fde = NULL;
936 if(!fde)
937 dprintk(1, "Binary lookup result for %lx discarded.", pc);
938 }
939 if (fde == NULL) {
940 for (fde = table->address, tableSize = table->size;
941 cie = NULL, tableSize > sizeof(*fde)
942 && tableSize - sizeof(*fde) >= *fde;
943 tableSize -= sizeof(*fde) + *fde,
944 fde += 1 + *fde / sizeof(*fde)) {
945 cie = cie_for_fde(fde, table);
946 if (cie == &bad_cie) {
947 cie = NULL;
948 break;
949 }
950 if (cie == NULL
951 || cie == &not_fde
952 || (ptrType = fde_pointer_type(cie)) < 0)
953 continue;
954 ptr = (const u8 *)(fde + 2);
955 startLoc = read_pointer(&ptr,
956 (const u8 *)(fde + 1) + *fde,
957 ptrType, 0, 0);
958 if (!startLoc)
959 continue;
960 if (!(ptrType & DW_EH_PE_indirect))
961 ptrType &= DW_EH_PE_FORM|DW_EH_PE_signed;
962 endLoc = startLoc
963 + read_pointer(&ptr,
964 (const u8 *)(fde + 1) + *fde,
965 ptrType, 0, 0);
966 if (pc >= startLoc && pc < endLoc)
967 break;
968 }
969 if(!fde)
970 dprintk(3, "Linear lookup for %lx failed.", pc);
971 }
972 }
973 if (cie != NULL) {
974 memset(&state, 0, sizeof(state));
975 state.cieEnd = ptr; /* keep here temporarily */
976 ptr = (const u8 *)(cie + 2);
977 end = (const u8 *)(cie + 1) + *cie;
978 frame->call_frame = 1;
979 if ((state.version = *ptr) != 1)
980 cie = NULL; /* unsupported version */
981 else if (*++ptr) {
982 /* check if augmentation size is first (and thus present) */
983 if (*ptr == 'z') {
984 while (++ptr < end && *ptr) {
985 switch(*ptr) {
986 /* check for ignorable (or already handled)
987 * nul-terminated augmentation string */
988 case 'L':
989 case 'P':
990 case 'R':
991 continue;
992 case 'S':
993 frame->call_frame = 0;
994 continue;
995 default:
996 break;
997 }
998 break;
999 }
1000 }
1001 if (ptr >= end || *ptr)
1002 cie = NULL;
1003 }
1004 if(!cie)
1005 dprintk(1, "CIE unusable (%p,%p).", ptr, end);
1006 ++ptr;
1007 }
1008 if (cie != NULL) {
1009 /* get code aligment factor */
1010 state.codeAlign = get_uleb128(&ptr, end);
1011 /* get data aligment factor */
1012 state.dataAlign = get_sleb128(&ptr, end);
1013 if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end)
1014 cie = NULL;
1015 else if (UNW_PC(frame) % state.codeAlign
1016 || UNW_SP(frame) % sleb128abs(state.dataAlign)) {
1017 dprintk(1, "Input pointer(s) misaligned (%lx,%lx).",
1018 UNW_PC(frame), UNW_SP(frame));
1019 return -EPERM;
1020 } else {
1021 retAddrReg = state.version <= 1 ? *ptr++ : get_uleb128(&ptr, end);
1022 /* skip augmentation */
1023 if (((const char *)(cie + 2))[1] == 'z') {
1024 uleb128_t augSize = get_uleb128(&ptr, end);
1025
1026 ptr += augSize;
1027 }
1028 if (ptr > end
1029 || retAddrReg >= ARRAY_SIZE(reg_info)
1030 || REG_INVALID(retAddrReg)
1031 || reg_info[retAddrReg].width != sizeof(unsigned long))
1032 cie = NULL;
1033 }
1034 if(!cie)
1035 dprintk(1, "CIE validation failed (%p,%p).", ptr, end);
1036 }
1037 if (cie != NULL) {
1038 state.cieStart = ptr;
1039 ptr = state.cieEnd;
1040 state.cieEnd = end;
1041 end = (const u8 *)(fde + 1) + *fde;
1042 /* skip augmentation */
1043 if (((const char *)(cie + 2))[1] == 'z') {
1044 uleb128_t augSize = get_uleb128(&ptr, end);
1045
1046 if ((ptr += augSize) > end)
1047 fde = NULL;
1048 }
1049 if(!fde)
1050 dprintk(1, "FDE validation failed (%p,%p).", ptr, end);
1051 }
1052 if (cie == NULL || fde == NULL) {
1053#ifdef CONFIG_FRAME_POINTER
1054 unsigned long top, bottom;
1055
1056 if ((UNW_SP(frame) | UNW_FP(frame)) % sizeof(unsigned long))
1057 return -EPERM;
1058 top = STACK_TOP(frame->task);
1059 bottom = STACK_BOTTOM(frame->task);
1060# if FRAME_RETADDR_OFFSET < 0
1061 if (UNW_SP(frame) < top
1062 && UNW_FP(frame) <= UNW_SP(frame)
1063 && bottom < UNW_FP(frame)
1064# else
1065 if (UNW_SP(frame) > top
1066 && UNW_FP(frame) >= UNW_SP(frame)
1067 && bottom > UNW_FP(frame)
1068# endif
1069 && !((UNW_SP(frame) | UNW_FP(frame))
1070 & (sizeof(unsigned long) - 1))) {
1071 unsigned long link;
1072
1073 if (!probe_kernel_address(
1074 (unsigned long *)(UNW_FP(frame)
1075 + FRAME_LINK_OFFSET),
1076 link)
1077# if FRAME_RETADDR_OFFSET < 0
1078 && link > bottom && link < UNW_FP(frame)
1079# else
1080 && link > UNW_FP(frame) && link < bottom
1081# endif
1082 && !(link & (sizeof(link) - 1))
1083 && !probe_kernel_address(
1084 (unsigned long *)(UNW_FP(frame)
1085 + FRAME_RETADDR_OFFSET), UNW_PC(frame))) {
1086 UNW_SP(frame) = UNW_FP(frame) + FRAME_RETADDR_OFFSET
1087# if FRAME_RETADDR_OFFSET < 0
1088 -
1089# else
1090 +
1091# endif
1092 sizeof(UNW_PC(frame));
1093 UNW_FP(frame) = link;
1094 return 0;
1095 }
1096 }
1097#endif
1098 return -ENXIO;
1099 }
1100 state.org = startLoc;
1101 memcpy(&state.cfa, &badCFA, sizeof(state.cfa));
1102 /* process instructions */
1103 if (!processCFI(ptr, end, pc, ptrType, &state)
1104 || state.loc > endLoc
1105 || state.regs[retAddrReg].where == Nowhere
1106 || state.cfa.reg >= ARRAY_SIZE(reg_info)
1107 || reg_info[state.cfa.reg].width != sizeof(unsigned long)
1108 || FRAME_REG(state.cfa.reg, unsigned long) % sizeof(unsigned long)
1109 || state.cfa.offs % sizeof(unsigned long)) {
1110 dprintk(1, "Unusable unwind info (%p,%p).", ptr, end);
1111 return -EIO;
1112 }
1113 /* update frame */
1114#ifndef CONFIG_AS_CFI_SIGNAL_FRAME
1115 if(frame->call_frame
1116 && !UNW_DEFAULT_RA(state.regs[retAddrReg], state.dataAlign))
1117 frame->call_frame = 0;
1118#endif
1119 cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs;
1120 startLoc = min((unsigned long)UNW_SP(frame), cfa);
1121 endLoc = max((unsigned long)UNW_SP(frame), cfa);
1122 if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) {
1123 startLoc = min(STACK_LIMIT(cfa), cfa);
1124 endLoc = max(STACK_LIMIT(cfa), cfa);
1125 }
1126#ifndef CONFIG_64BIT
1127# define CASES CASE(8); CASE(16); CASE(32)
1128#else
1129# define CASES CASE(8); CASE(16); CASE(32); CASE(64)
1130#endif
1131 pc = UNW_PC(frame);
1132 sp = UNW_SP(frame);
1133 for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
1134 if (REG_INVALID(i)) {
1135 if (state.regs[i].where == Nowhere)
1136 continue;
1137 dprintk(1, "Cannot restore register %u (%d).",
1138 i, state.regs[i].where);
1139 return -EIO;
1140 }
1141 switch(state.regs[i].where) {
1142 default:
1143 break;
1144 case Register:
1145 if (state.regs[i].value >= ARRAY_SIZE(reg_info)
1146 || REG_INVALID(state.regs[i].value)
1147 || reg_info[i].width > reg_info[state.regs[i].value].width) {
1148 dprintk(1, "Cannot restore register %u from register %lu.",
1149 i, state.regs[i].value);
1150 return -EIO;
1151 }
1152 switch(reg_info[state.regs[i].value].width) {
1153#define CASE(n) \
1154 case sizeof(u##n): \
1155 state.regs[i].value = FRAME_REG(state.regs[i].value, \
1156 const u##n); \
1157 break
1158 CASES;
1159#undef CASE
1160 default:
1161 dprintk(1, "Unsupported register size %u (%lu).",
1162 reg_info[state.regs[i].value].width,
1163 state.regs[i].value);
1164 return -EIO;
1165 }
1166 break;
1167 }
1168 }
1169 for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
1170 if (REG_INVALID(i))
1171 continue;
1172 switch(state.regs[i].where) {
1173 case Nowhere:
1174 if (reg_info[i].width != sizeof(UNW_SP(frame))
1175 || &FRAME_REG(i, __typeof__(UNW_SP(frame)))
1176 != &UNW_SP(frame))
1177 continue;
1178 UNW_SP(frame) = cfa;
1179 break;
1180 case Register:
1181 switch(reg_info[i].width) {
1182#define CASE(n) case sizeof(u##n): \
1183 FRAME_REG(i, u##n) = state.regs[i].value; \
1184 break
1185 CASES;
1186#undef CASE
1187 default:
1188 dprintk(1, "Unsupported register size %u (%u).",
1189 reg_info[i].width, i);
1190 return -EIO;
1191 }
1192 break;
1193 case Value:
1194 if (reg_info[i].width != sizeof(unsigned long)) {
1195 dprintk(1, "Unsupported value size %u (%u).",
1196 reg_info[i].width, i);
1197 return -EIO;
1198 }
1199 FRAME_REG(i, unsigned long) = cfa + state.regs[i].value
1200 * state.dataAlign;
1201 break;
1202 case Memory: {
1203 unsigned long addr = cfa + state.regs[i].value
1204 * state.dataAlign;
1205
1206 if ((state.regs[i].value * state.dataAlign)
1207 % sizeof(unsigned long)
1208 || addr < startLoc
1209 || addr + sizeof(unsigned long) < addr
1210 || addr + sizeof(unsigned long) > endLoc) {
1211 dprintk(1, "Bad memory location %lx (%lx).",
1212 addr, state.regs[i].value);
1213 return -EIO;
1214 }
1215 switch(reg_info[i].width) {
1216#define CASE(n) case sizeof(u##n): \
1217 probe_kernel_address((u##n *)addr, FRAME_REG(i, u##n)); \
1218 break
1219 CASES;
1220#undef CASE
1221 default:
1222 dprintk(1, "Unsupported memory size %u (%u).",
1223 reg_info[i].width, i);
1224 return -EIO;
1225 }
1226 }
1227 break;
1228 }
1229 }
1230
1231 if (UNW_PC(frame) % state.codeAlign
1232 || UNW_SP(frame) % sleb128abs(state.dataAlign)) {
1233 dprintk(1, "Output pointer(s) misaligned (%lx,%lx).",
1234 UNW_PC(frame), UNW_SP(frame));
1235 return -EIO;
1236 }
1237 if (pc == UNW_PC(frame) && sp == UNW_SP(frame)) {
1238 dprintk(1, "No progress (%lx,%lx).", pc, sp);
1239 return -EIO;
1240 }
1241
1242 return 0;
1243#undef CASES
1244#undef FRAME_REG
1245}
1246EXPORT_SYMBOL(unwind);
1247
1248int unwind_init_frame_info(struct unwind_frame_info *info,
1249 struct task_struct *tsk,
1250 /*const*/ struct pt_regs *regs)
1251{
1252 info->task = tsk;
1253 info->call_frame = 0;
1254 arch_unw_init_frame_info(info, regs);
1255
1256 return 0;
1257}
1258EXPORT_SYMBOL(unwind_init_frame_info);
1259
1260/*
1261 * Prepare to unwind a blocked task.
1262 */
1263int unwind_init_blocked(struct unwind_frame_info *info,
1264 struct task_struct *tsk)
1265{
1266 info->task = tsk;
1267 info->call_frame = 0;
1268 arch_unw_init_blocked(info);
1269
1270 return 0;
1271}
1272EXPORT_SYMBOL(unwind_init_blocked);
1273
1274/*
1275 * Prepare to unwind the currently running thread.
1276 */
1277int unwind_init_running(struct unwind_frame_info *info,
1278 asmlinkage int (*callback)(struct unwind_frame_info *,
1279 void *arg),
1280 void *arg)
1281{
1282 info->task = current;
1283 info->call_frame = 0;
1284
1285 return arch_unwind_init_running(info, callback, arg);
1286}
1287EXPORT_SYMBOL(unwind_init_running);
1288
1289/*
1290 * Unwind until the return pointer is in user-land (or until an error
1291 * occurs). Returns 0 if successful, negative number in case of
1292 * error.
1293 */
1294int unwind_to_user(struct unwind_frame_info *info)
1295{
1296 while (!arch_unw_user_mode(info)) {
1297 int err = unwind(info);
1298
1299 if (err < 0)
1300 return err;
1301 }
1302
1303 return 0;
1304}
1305EXPORT_SYMBOL(unwind_to_user);
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 818e4589f718..5c2681875b9a 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -354,24 +354,6 @@ config FRAME_POINTER
354 some architectures or if you use external debuggers. 354 some architectures or if you use external debuggers.
355 If you don't debug the kernel, you can say N. 355 If you don't debug the kernel, you can say N.
356 356
357config UNWIND_INFO
358 bool "Compile the kernel with frame unwind information"
359 depends on !IA64 && !PARISC && !ARM
360 depends on !MODULES || !(MIPS || PPC || SUPERH || V850)
361 help
362 If you say Y here the resulting kernel image will be slightly larger
363 but not slower, and it will give very useful debugging information.
364 If you don't debug the kernel, you can say N, but we may not be able
365 to solve problems without frame unwind information or frame pointers.
366
367config STACK_UNWIND
368 bool "Stack unwind support"
369 depends on UNWIND_INFO
370 depends on X86
371 help
372 This enables more precise stack traces, omitting all unrelated
373 occurrences of pointers into kernel code from the dump.
374
375config FORCED_INLINING 357config FORCED_INLINING
376 bool "Force gcc to inline functions marked 'inline'" 358 bool "Force gcc to inline functions marked 'inline'"
377 depends on DEBUG_KERNEL 359 depends on DEBUG_KERNEL
diff --git a/lib/fault-inject.c b/lib/fault-inject.c
index d143c0faf248..b5a90fc056d3 100644
--- a/lib/fault-inject.c
+++ b/lib/fault-inject.c
@@ -55,37 +55,7 @@ static bool fail_task(struct fault_attr *attr, struct task_struct *task)
55 55
56#define MAX_STACK_TRACE_DEPTH 32 56#define MAX_STACK_TRACE_DEPTH 32
57 57
58#ifdef CONFIG_STACK_UNWIND 58#if defined(CONFIG_STACKTRACE)
59
60static asmlinkage int fail_stacktrace_callback(struct unwind_frame_info *info,
61 void *arg)
62{
63 int depth;
64 struct fault_attr *attr = arg;
65 bool found = (attr->require_start == 0 && attr->require_end == ULONG_MAX);
66
67 for (depth = 0; depth < attr->stacktrace_depth
68 && unwind(info) == 0 && UNW_PC(info); depth++) {
69 if (arch_unw_user_mode(info))
70 break;
71 if (attr->reject_start <= UNW_PC(info) &&
72 UNW_PC(info) < attr->reject_end)
73 return false;
74 if (attr->require_start <= UNW_PC(info) &&
75 UNW_PC(info) < attr->require_end)
76 found = true;
77 }
78 return found;
79}
80
81static bool fail_stacktrace(struct fault_attr *attr)
82{
83 struct unwind_frame_info info;
84
85 return unwind_init_running(&info, fail_stacktrace_callback, attr);
86}
87
88#elif defined(CONFIG_STACKTRACE)
89 59
90static bool fail_stacktrace(struct fault_attr *attr) 60static bool fail_stacktrace(struct fault_attr *attr)
91{ 61{