📄 cfi_annotations.patch
字号:
There are some parts of the kernel where you simply cannot unwind past. Thisdoes not, however, stop GDB from trying, and getting stuck in an infinite loop(it will get garbage back, try and unwind that, repeat). The way to fix thisis to manually insert some DWARF2 information into the kernel so that GDB willcleanly (or almost cleanly, it will get the same frame twice, and stop) stop.George wrote much of the IMHO hard part here (i386 & the macros) and Iexpanded this to all of the other arches. This adds a small amount to theDEBUG_INFO=y kernel size, but that's not unexpected.Signed-off-by: Milind Dumbare <milind@linsyssoft.com>Signed-off-by: Todd Poynor <tpoynor@mvista.com>Signed-off-by: Tom Rini <trini@kernel.crashing.org> Makefile | 9 arch/arm/kernel/entry-armv.S | 2 arch/i386/kernel/entry.S | 111 +++++- arch/i386/kernel/head.S | 5 arch/i386/kernel/process.c | 20 + arch/i386/kernel/smpboot.c | 3 arch/x86_64/kernel/entry.S | 2 include/asm-arm/kgdb.h | 7 include/asm-generic/kgdb.h | 34 + include/asm-i386/kgdb.h | 59 +-- include/asm-mips/kgdb.h | 4 include/asm-powerpc/kgdb.h | 1 include/asm-sh/kgdb.h | 1 include/asm-x86_64/kgdb.h | 4 include/linux/dwarf2-lang.h | 300 ++++++++++++++++ include/linux/dwarf2.h | 775 +++++++++++++++++++++++++++++++++++++++++++ scripts/dwarfh.awk | 19 + 17 files changed, 1324 insertions(+), 32 deletions(-)Index: linux-2.6.16/Makefile===================================================================--- linux-2.6.16.orig/Makefile 2006-03-20 11:23:29.000000000 +0530+++ linux-2.6.16/Makefile 2006-04-25 11:43:49.000000000 +0530@@ -1001,7 +1001,8 @@ MRPROPER_DIRS += include/config include2 MRPROPER_FILES += .config .config.old include/asm .version .old_version \ include/linux/autoconf.h include/linux/version.h \- .kernelrelease Module.symvers tags TAGS cscope*+ include/linux/dwarf2-defs.h .kernelrelease \+ Module.symvers tags TAGS cscope* # clean - Delete most, but leave enough to build external modules #@@ -1347,4 +1348,8 @@ endif # skip-makefile -FORCE:+include/linux/dwarf2-defs.h: $(srctree)/include/linux/dwarf2.h $(srctree)/scripts/dwarfh.awk+ mkdir -p include/linux/+ awk -f $(srctree)/scripts/dwarfh.awk $(srctree)/include/linux/dwarf2.h > include/linux/dwarf2-defs.h++FORCE: include/linux/dwarf2-defs.hIndex: linux-2.6.16/arch/i386/kernel/process.c===================================================================--- linux-2.6.16.orig/arch/i386/kernel/process.c 2006-03-20 11:23:29.000000000 +0530+++ linux-2.6.16/arch/i386/kernel/process.c 2006-04-25 11:42:37.000000000 +0530@@ -330,7 +330,27 @@ "call *%ebx\n\t" "pushl %eax\n\t" "call do_exit\n"+ "kernel_thread_helper_end:\n\t" ".previous");+#ifdef CONFIG_KGDB+#include <linux/dwarf2-lang.h>++ /* This dwarf code tells gdb that this is the end of the unwind */+ /* This uses the CFA set up for pc=1 located in entry.S */+#define _ESP 4+#define _PC 8+#define _EIP 8+__asm__(+ QUOTE_THIS(+ CFI_preamble(dwarf_4,_PC,1,1)+ CFA_define_reference(_ESP,0) /* Stack pointer */+ CFA_undefine_reg(_EIP)+ CFI_postamble()++ FDE_preamble(dwarf_4,kernel_thread_helper,kernel_thread_helper_end)+ FDE_postamble()+ ));+#endif /* * Create a kernel threadIndex: linux-2.6.16/arch/i386/kernel/head.S===================================================================--- linux-2.6.16.orig/arch/i386/kernel/head.S 2006-03-20 11:23:29.000000000 +0530+++ linux-2.6.16/arch/i386/kernel/head.S 2006-04-25 11:42:37.000000000 +0530@@ -11,6 +11,7 @@ #include <linux/config.h> #include <linux/threads.h> #include <linux/linkage.h>+#include <asm/kgdb.h> #include <asm/segment.h> #include <asm/page.h> #include <asm/pgtable.h>@@ -332,7 +333,9 @@ L6: jmp L6 # main should never return here, but # just in case, we know what happens.-+ /* This dwarf code tells gdb that this is the end of the unwind */+ /* This uses the CFA set up for pc=1 located in entry.S */+ CFI_END_FRAME(is386) /* * We depend on ET to be correct. This checks for 287/387. */Index: linux-2.6.16/arch/i386/kernel/entry.S===================================================================--- linux-2.6.16.orig/arch/i386/kernel/entry.S 2006-03-20 11:23:29.000000000 +0530+++ linux-2.6.16/arch/i386/kernel/entry.S 2006-04-25 11:42:37.000000000 +0530@@ -123,7 +123,7 @@ .previous -ENTRY(ret_from_fork)+KPROBE_ENTRY(ret_from_fork) pushl %eax call schedule_tail GET_THREAD_INFO(%ebp)@@ -472,7 +472,7 @@ pushl $do_simd_coprocessor_error jmp error_code -ENTRY(device_not_available)+KPROBE_ENTRY(device_not_available) pushl $-1 # mark this as an int SAVE_ALL movl %cr0, %eax@@ -654,7 +654,7 @@ jmp error_code #endif -ENTRY(spurious_interrupt_bug)+KPROBE_ENTRY(spurious_interrupt_bug) pushl $0 pushl $do_spurious_interrupt_bug jmp error_code@@ -663,3 +663,108 @@ #include "syscall_table.S" syscall_table_size=(.-sys_call_table)++# Here we do call frames. We cheat a bit as we only really need+# correct frames at locations we can actually look at from a+# debugger. Since the break instruction trap actually goes thru+# some of this code, we don't really need info on those areas, but+# only after the fact. I.e. if we can not step or break in a+# location or end up with a return address pointing at the+# location, we don't need a correct call frame for it.++#ifdef CONFIG_KGDB++#include <linux/dwarf2-lang.h>+/*+ * The register numbers as known by gdb+ */++#define _EAX 0+#define _ECX 1+#define _EDX 2+#define _EBX 3+#define _ESP 4+#define _EBP 5+#define _ESI 6+#define _EDI 7+#define _PC 8+#define _EIP 8+#define _PS 9+#define _EFLAGS 9+#define _CS 10+#define _SS 11+#define _DS 12+#define _ES 13+#define _FS 14+#define _GS 15+ /*+ * This code uses macros defined in linux/dwarf2-lang.h+ * They attempt to follow the dwarf2 naming conventions... sort of..+ */+ENTRY(end_of_stack_stop_unwind_function)+ .long end_of_stack_stop_unwind_function+1++ .text++ CFI_preamble(c1,_PC,1,1)+ CFA_define_reference(_ESP,OLDESP) /* Stack pointer */+ CFA_expression(_EIP)+ CFA_exp_OP_dup /* copy old esp */+ CFA_exp_OP_consts(CS-OLDESP) /* offset to CS address */+ CFA_exp_OP_plus /* should be CS address */+ CFA_exp_OP_deref /* get the CS */+ CFA_exp_OP_const4s(VM_MASK|3) /* prepare to mask it */+ CFA_exp_OP_and /* mask it, zero means kernel */+ CFA_exp_OP_bra(eip_user_rtn) /* branch if user */+ CFA_exp_OP_const4s(EIP-OLDESP) /* offset to return address */+ CFA_exp_OP_plus /* add that in */+ CFA_exp_OP_skip(eip_end) /* done if kernel, skip out */+eip_user_rtn:+ CFA_exp_OP_addr(end_of_stack_stop_unwind_function)/*dummy function */+eip_end:+ CFA_expression_end+ CFA_define_offset(_EBX,EBX-OLDESP)+ CFA_define_offset(_ECX,ECX-OLDESP)+ CFA_define_offset(_EDX,EDX-OLDESP)+ CFA_define_offset(_ESI,ESI-OLDESP)+ CFA_define_offset(_EDI,EDI-OLDESP)+ CFA_define_offset(_EBP,EBP-OLDESP)+ CFA_define_offset(_EAX,EAX-OLDESP)+ CFA_define_offset(_EFLAGS,EFLAGS-OLDESP)+ CFI_postamble()++/*+ * This provides an uwind for our dummy end of unwind function.+ * Current convention is to provied an undefined return address.+ */+ CFI_preamble(c2,_PC,1,1)+ CFA_define_reference(_ESP,0) /* Stack pointer */+ CFA_undefine_reg(_EIP)+ CFI_postamble()++ FDE_preamble(c2,end_of_stack_stop_unwind_function, \+ end_of_stack_stop_unwind_function+5)+ FDE_postamble()+ /*+ * This is VERY sloppy. At this point all we want to do is get+ * the frame right for back tracing. It will not be good if+ * you try to single step. We use already defined labels.+ * We want to cover all call outs.+ * We could also recode this as just one FDE, but this works and+ * I want to get it out.+ */+ FDE_preamble(c1,ret_from_fork,ret_from_exception)+ CFA_define_cfa_offset(4) /* one extra word on stack */+ FDE_postamble()++ FDE_preamble(c1,ret_from_exception,device_not_available_emulate)+ FDE_postamble()++ FDE_preamble(c1,device_not_available_emulate,debug)+ CFA_define_cfa_offset(4) /* one extra word on stack */+ FDE_postamble()++ FDE_preamble(c1, debug,spurious_interrupt_bug)+ FDE_postamble()++#endifIndex: linux-2.6.16/arch/i386/kernel/smpboot.c===================================================================--- linux-2.6.16.orig/arch/i386/kernel/smpboot.c 2006-03-20 11:23:29.000000000 +0530+++ linux-2.6.16/arch/i386/kernel/smpboot.c 2006-04-25 11:42:37.000000000 +0530@@ -564,6 +564,9 @@ asm volatile( "movl %0,%%esp\n\t"+#ifdef CONFIG_KGDB+ "pushl end_of_stack_stop_unwind_function\n\t"+#endif "jmp *%1" : :"r" (current->thread.esp),"r" (current->thread.eip));Index: linux-2.6.16/arch/x86_64/kernel/entry.S===================================================================--- linux-2.6.16.orig/arch/x86_64/kernel/entry.S 2006-03-20 11:23:29.000000000 +0530+++ linux-2.6.16/arch/x86_64/kernel/entry.S 2006-04-25 11:43:02.000000000 +0530@@ -42,6 +42,7 @@ #include <asm/thread_info.h> #include <asm/hw_irq.h> #include <asm/page.h>+#include <asm/kgdb.h> .code64 @@ -860,6 +861,7 @@ UNFAKE_STACK_FRAME ret CFI_ENDPROC+ CFI_END_FRAME(kernel_thread) child_rip:Index: linux-2.6.16/arch/arm/kernel/entry-armv.S===================================================================--- linux-2.6.16.orig/arch/arm/kernel/entry-armv.S 2006-03-20 11:23:29.000000000 +0530+++ linux-2.6.16/arch/arm/kernel/entry-armv.S 2006-04-25 11:42:37.000000000 +0530@@ -16,6 +16,7 @@ */ #include <linux/config.h> +#include <asm/kgdb.h> #include <asm/memory.h> #include <asm/glue.h> #include <asm/vfpmacros.h>@@ -232,6 +233,7 @@ beq preempt_return @ go again b 1b #endif+ CFI_END_FRAME(__irq_svc) .align 5 __und_svc:Index: linux-2.6.16/include/asm-x86_64/kgdb.h===================================================================--- linux-2.6.16.orig/include/asm-x86_64/kgdb.h 2006-04-25 11:33:57.000000000 +0530+++ linux-2.6.16/include/asm-x86_64/kgdb.h 2006-04-25 11:42:37.000000000 +0530@@ -6,6 +6,8 @@ * Copyright (C) 2001-2004 Amit S. Kale */ +#include <asm-generic/kgdb.h>+ /* * Note that this register image is in a different order than * the register image that Linux produces at interrupt time.@@ -36,6 +38,8 @@ #define NUMREGBYTES ((_PS+1)*8) #define NUMCRITREGBYTES (8 * 8) /* 8 registers. */ +/* Help GDB to know when to stop backtracing. */+#define CFI_END_FRAME(func) __CFI_END_FRAME(_PC,_RSP,func) #ifndef __ASSEMBLY__ /* BUFMAX defines the maximum number of characters in inbound/outbound * buffers at least NUMREGBYTES*2 are needed for register packets, andIndex: linux-2.6.16/include/asm-powerpc/kgdb.h===================================================================--- linux-2.6.16.orig/include/asm-powerpc/kgdb.h 2006-04-25 11:31:05.000000000 +0530+++ linux-2.6.16/include/asm-powerpc/kgdb.h 2006-04-25 11:42:37.000000000 +0530@@ -23,6 +23,7 @@ #ifndef __POWERPC_KGDB_H__ #define __POWERPC_KGDB_H__ +#include <asm-generic/kgdb.h> #ifndef __ASSEMBLY__ #define BREAK_INSTR_SIZE 4Index: linux-2.6.16/include/asm-mips/kgdb.h===================================================================--- linux-2.6.16.orig/include/asm-mips/kgdb.h 2006-04-25 11:33:22.000000000 +0530+++ linux-2.6.16/include/asm-mips/kgdb.h 2006-04-25 11:42:37.000000000 +0530@@ -2,6 +2,9 @@ #ifndef _ASM_KGDB_H_ #define _ASM_KGDB_H_ +#include <asm-generic/kgdb.h>++#ifndef __ASSEMBLY__ #define BUFMAX 2048 #define NUMREGBYTES (90*sizeof(long)) #define NUMCRITREGBYTES (12*sizeof(long))@@ -17,5 +20,6 @@ extern int kgdb_early_setup; +#endif /* !__ASSEMBLY__ */ #endif /* _ASM_KGDB_H_ */ #endif /* __KERNEL__ */Index: linux-2.6.16/include/asm-generic/kgdb.h===================================================================--- linux-2.6.16.orig/include/asm-generic/kgdb.h 2006-04-25 10:59:23.506518750 +0530+++ linux-2.6.16/include/asm-generic/kgdb.h 2006-04-25 11:42:37.000000000 +0530@@ -0,0 +1,34 @@+/*+ * include/asm-generic/kgdb.h+ *+ * This provides the assembly level information so that KGDB can provide+ * a GDB that has been patched with enough information to know to stop+ * trying to unwind the function.+ *+ * Author: Tom Rini <trini@kernel.crashing.org>+ *+ * 2005 (c) MontaVista Software, Inc. This file is licensed under the terms+ * of the GNU General Public License version 2. This program is licensed+ * "as is" without any warranty of any kind, whether express or implied.+ */++#ifndef __ASM_GENERIC_KGDB_H__+#define __ASM_GENERIC_KGDB_H__++#include <linux/dwarf2-lang.h>+#ifdef __ASSEMBLY__+#ifdef CONFIG_KGDB+/* This MUST be put at the end of a given assembly function */+#define __CFI_END_FRAME(pc,sp,func) \+CAT3(.Lend_,func,:) \+ CFI_preamble(func,pc,0x1,-DATA_ALIGN_FACTOR) \+ CFA_define_reference(sp, 0) \+ CFA_undefine_reg(pc) \+ CFI_postamble() \+ FDE_preamble(func,func,CAT3(.Lend,_,func)) \+ FDE_postamble()+#else+#define __CFI_END_FRAME(pc,sp,fn)+#endif /* CONFIG_KGDB */+#endif /* __ASSEMBLY__ */+#endif /* __ASM_GENERIC_KGDB_H__ */Index: linux-2.6.16/include/linux/dwarf2.h===================================================================--- linux-2.6.16.orig/include/linux/dwarf2.h 2006-04-25 10:59:23.506518750 +0530+++ linux-2.6.16/include/linux/dwarf2.h 2006-04-25 11:42:37.000000000 +0530@@ -0,0 +1,775 @@+/* Declarations and definitions of codes relating to the DWARF2 symbolic+ debugging information format.+ Copyright (C) 1992, 1993, 1995, 1996, 1997, 1999, 2000, 2001, 2002,+ 2003 Free Software Foundation, Inc.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -