aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2006-09-26 04:52:41 -0400
committerAndi Kleen <andi@basil.nowhere.org>2006-09-26 04:52:41 -0400
commitadf1423698f00d00b267f7dca8231340ce7d65ef (patch)
treeec2e28a32d467cc3c618c8ee0cedd3d1a49f9c43 /arch/x86_64
parentab2e0b46cb9a197fab7d98e147cac7cd41a14047 (diff)
[PATCH] i386/x86-64: Work around gcc bug with noreturn functions in unwinder
Current gcc generates calls not jumps to noreturn functions. When that happens the return address can point to the next function, which confuses the unwinder. This patch works around it by marking asynchronous exception frames in contrast normal call frames in the unwind information. Then teach the unwinder to decode this. For normal call frames the unwinder now subtracts one from the address which avoids this problem. The standard libgcc unwinder uses the same trick. It doesn't include adjustment of the printed address (i.e. for the original example, it'd still be kernel_math_error+0 that gets displayed, but the unwinder wouldn't get confused anymore. This only works with binutils 2.6.17+ and some versions of H.J.Lu's 2.6.16 unfortunately because earlier binutils don't support .cfi_signal_frame [AK: added automatic detection of the new binutils and wrote description] Signed-off-by: Jan Beulich <jbeulich@novell.com> Signed-off-by: Andi Kleen <ak@suse.de>
Diffstat (limited to 'arch/x86_64')
-rw-r--r--arch/x86_64/Makefile4
-rw-r--r--arch/x86_64/ia32/ia32entry.S4
-rw-r--r--arch/x86_64/kernel/entry.S4
3 files changed, 12 insertions, 0 deletions
diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile
index 2b8d07c70106..1c0f18d4f887 100644
--- a/arch/x86_64/Makefile
+++ b/arch/x86_64/Makefile
@@ -58,6 +58,10 @@ cflags-y += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
58cflags-y += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) 58cflags-y += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
59AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) 59AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
60 60
61# is .cfi_signal_frame supported too?
62cflags-y += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
63AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
64
61cflags-$(CONFIG_CC_STACKPROTECTOR) += $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh $(CC) -fstack-protector ) 65cflags-$(CONFIG_CC_STACKPROTECTOR) += $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh $(CC) -fstack-protector )
62cflags-$(CONFIG_CC_STACKPROTECTOR_ALL) += $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh $(CC) -fstack-protector-all ) 66cflags-$(CONFIG_CC_STACKPROTECTOR_ALL) += $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh $(CC) -fstack-protector-all )
63 67
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 32fd32bea07c..b4aa875e175b 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -71,6 +71,7 @@
71 */ 71 */
72ENTRY(ia32_sysenter_target) 72ENTRY(ia32_sysenter_target)
73 CFI_STARTPROC32 simple 73 CFI_STARTPROC32 simple
74 CFI_SIGNAL_FRAME
74 CFI_DEF_CFA rsp,0 75 CFI_DEF_CFA rsp,0
75 CFI_REGISTER rsp,rbp 76 CFI_REGISTER rsp,rbp
76 swapgs 77 swapgs
@@ -186,6 +187,7 @@ ENDPROC(ia32_sysenter_target)
186 */ 187 */
187ENTRY(ia32_cstar_target) 188ENTRY(ia32_cstar_target)
188 CFI_STARTPROC32 simple 189 CFI_STARTPROC32 simple
190 CFI_SIGNAL_FRAME
189 CFI_DEF_CFA rsp,PDA_STACKOFFSET 191 CFI_DEF_CFA rsp,PDA_STACKOFFSET
190 CFI_REGISTER rip,rcx 192 CFI_REGISTER rip,rcx
191 /*CFI_REGISTER rflags,r11*/ 193 /*CFI_REGISTER rflags,r11*/
@@ -293,6 +295,7 @@ ia32_badarg:
293 295
294ENTRY(ia32_syscall) 296ENTRY(ia32_syscall)
295 CFI_STARTPROC simple 297 CFI_STARTPROC simple
298 CFI_SIGNAL_FRAME
296 CFI_DEF_CFA rsp,SS+8-RIP 299 CFI_DEF_CFA rsp,SS+8-RIP
297 /*CFI_REL_OFFSET ss,SS-RIP*/ 300 /*CFI_REL_OFFSET ss,SS-RIP*/
298 CFI_REL_OFFSET rsp,RSP-RIP 301 CFI_REL_OFFSET rsp,RSP-RIP
@@ -370,6 +373,7 @@ ENTRY(ia32_ptregs_common)
370 popq %r11 373 popq %r11
371 CFI_ENDPROC 374 CFI_ENDPROC
372 CFI_STARTPROC32 simple 375 CFI_STARTPROC32 simple
376 CFI_SIGNAL_FRAME
373 CFI_DEF_CFA rsp,SS+8-ARGOFFSET 377 CFI_DEF_CFA rsp,SS+8-ARGOFFSET
374 CFI_REL_OFFSET rax,RAX-ARGOFFSET 378 CFI_REL_OFFSET rax,RAX-ARGOFFSET
375 CFI_REL_OFFSET rcx,RCX-ARGOFFSET 379 CFI_REL_OFFSET rcx,RCX-ARGOFFSET
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index ea32688386fd..4cbc65290ae7 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -123,6 +123,7 @@
123 .macro CFI_DEFAULT_STACK start=1 123 .macro CFI_DEFAULT_STACK start=1
124 .if \start 124 .if \start
125 CFI_STARTPROC simple 125 CFI_STARTPROC simple
126 CFI_SIGNAL_FRAME
126 CFI_DEF_CFA rsp,SS+8 127 CFI_DEF_CFA rsp,SS+8
127 .else 128 .else
128 CFI_DEF_CFA_OFFSET SS+8 129 CFI_DEF_CFA_OFFSET SS+8
@@ -207,6 +208,7 @@ END(ret_from_fork)
207 208
208ENTRY(system_call) 209ENTRY(system_call)
209 CFI_STARTPROC simple 210 CFI_STARTPROC simple
211 CFI_SIGNAL_FRAME
210 CFI_DEF_CFA rsp,PDA_STACKOFFSET 212 CFI_DEF_CFA rsp,PDA_STACKOFFSET
211 CFI_REGISTER rip,rcx 213 CFI_REGISTER rip,rcx
212 /*CFI_REGISTER rflags,r11*/ 214 /*CFI_REGISTER rflags,r11*/
@@ -324,6 +326,7 @@ END(system_call)
324 */ 326 */
325ENTRY(int_ret_from_sys_call) 327ENTRY(int_ret_from_sys_call)
326 CFI_STARTPROC simple 328 CFI_STARTPROC simple
329 CFI_SIGNAL_FRAME
327 CFI_DEF_CFA rsp,SS+8-ARGOFFSET 330 CFI_DEF_CFA rsp,SS+8-ARGOFFSET
328 /*CFI_REL_OFFSET ss,SS-ARGOFFSET*/ 331 /*CFI_REL_OFFSET ss,SS-ARGOFFSET*/
329 CFI_REL_OFFSET rsp,RSP-ARGOFFSET 332 CFI_REL_OFFSET rsp,RSP-ARGOFFSET
@@ -484,6 +487,7 @@ END(stub_rt_sigreturn)
484 */ 487 */
485 .macro _frame ref 488 .macro _frame ref
486 CFI_STARTPROC simple 489 CFI_STARTPROC simple
490 CFI_SIGNAL_FRAME
487 CFI_DEF_CFA rsp,SS+8-\ref 491 CFI_DEF_CFA rsp,SS+8-\ref
488 /*CFI_REL_OFFSET ss,SS-\ref*/ 492 /*CFI_REL_OFFSET ss,SS-\ref*/
489 CFI_REL_OFFSET rsp,RSP-\ref 493 CFI_REL_OFFSET rsp,RSP-\ref