git: 8f9635dc99f5 - main - linux(4): Retire handmade DWARF annotations from signal trampolines

From: Dmitry Chagin <dchagin_at_FreeBSD.org>
Date: Sun, 15 May 2022 18:12:27 UTC
The branch main has been updated by dchagin:

URL: https://cgit.FreeBSD.org/src/commit/?id=8f9635dc99f571a0ae4e613b9a0439e68da7b160

commit 8f9635dc99f571a0ae4e613b9a0439e68da7b160
Author:     Dmitry Chagin <dchagin@FreeBSD.org>
AuthorDate: 2022-05-15 18:08:12 +0000
Commit:     Dmitry Chagin <dchagin@FreeBSD.org>
CommitDate: 2022-05-15 18:08:12 +0000

    linux(4): Retire handmade DWARF annotations from signal trampolines
    
    The Linux exports __kernel_sigreturn and __kernel_rt_sigreturn from the
    vdso. Modern glibc's sigaction sets the sa_restorer field of sigaction
    to the corresponding vdso __sigreturn, and sets the SA_RESTORER.
    Our signal trampolines uses the FreeBSD-way to call a signal handler,
    so does not use the sigaction's sa_restorer.
    
    However, as glibc's runtime linker depends on the existment of the vdso
    __sigreturn symbols, for all Linuxulators was added separate trampolines
    named __sigcode with DWARF anotations and left separate __sigreturn
    methods, which are exported.
    
    MFC after:              2 weeks
---
 sys/amd64/linux/linux_genassym.c     |  20 ++++-
 sys/amd64/linux/linux_locore.asm     |  92 ++++++++++++--------
 sys/amd64/linux32/linux32_genassym.c |  17 +++-
 sys/amd64/linux32/linux32_locore.asm | 161 ++++++++++++++++-------------------
 sys/amd64/linux32/linux32_sysvec.c   |   8 +-
 sys/amd64/linux32/linux32_vdso.lds.s |   2 +
 sys/i386/linux/linux_genassym.c      |  19 ++++-
 sys/i386/linux/linux_locore.asm      | 160 +++++++++++++++-------------------
 sys/i386/linux/linux_sysvec.c        |   8 +-
 sys/i386/linux/linux_vdso.lds.s      |   2 +
 10 files changed, 259 insertions(+), 230 deletions(-)

diff --git a/sys/amd64/linux/linux_genassym.c b/sys/amd64/linux/linux_genassym.c
index a9658b006be8..14880afcc89b 100644
--- a/sys/amd64/linux/linux_genassym.c
+++ b/sys/amd64/linux/linux_genassym.c
@@ -12,5 +12,23 @@ __FBSDID("$FreeBSD$");
 
 ASSYM(LINUX_RT_SIGF_UC, offsetof(struct l_rt_sigframe, sf_uc));
 ASSYM(LINUX_RT_SIGF_SC, offsetof(struct l_ucontext, uc_mcontext));
+ASSYM(L_SC_R8, offsetof(struct l_sigcontext, sc_r8));
+ASSYM(L_SC_R9, offsetof(struct l_sigcontext, sc_r9));
+ASSYM(L_SC_R10, offsetof(struct l_sigcontext, sc_r10));
+ASSYM(L_SC_R11, offsetof(struct l_sigcontext, sc_r11));
+ASSYM(L_SC_R12, offsetof(struct l_sigcontext, sc_r12));
+ASSYM(L_SC_R13, offsetof(struct l_sigcontext, sc_r13));
+ASSYM(L_SC_R14, offsetof(struct l_sigcontext, sc_r14));
+ASSYM(L_SC_R15, offsetof(struct l_sigcontext, sc_r15));
+ASSYM(L_SC_RDI, offsetof(struct l_sigcontext, sc_rdi));
+ASSYM(L_SC_RSI, offsetof(struct l_sigcontext, sc_rsi));
+ASSYM(L_SC_RBP, offsetof(struct l_sigcontext, sc_rbp));
+ASSYM(L_SC_RBX, offsetof(struct l_sigcontext, sc_rbx));
+ASSYM(L_SC_RDX, offsetof(struct l_sigcontext, sc_rdx));
+ASSYM(L_SC_RAX, offsetof(struct l_sigcontext, sc_rax));
+ASSYM(L_SC_RCX, offsetof(struct l_sigcontext, sc_rcx));
+ASSYM(L_SC_RSP, offsetof(struct l_sigcontext, sc_rsp));
+ASSYM(L_SC_RIP, offsetof(struct l_sigcontext, sc_rip));
+ASSYM(L_SC_RFLAGS, offsetof(struct l_sigcontext, sc_rflags));
+ASSYM(L_SC_CS, offsetof(struct l_sigcontext, sc_cs));
 ASSYM(LINUX_VERSION_CODE, LINUX_VERSION_CODE);
-ASSYM(LINUX_SC_RSP, offsetof(struct l_sigcontext, sc_rsp));
diff --git a/sys/amd64/linux/linux_locore.asm b/sys/amd64/linux/linux_locore.asm
index 8b6833d7352f..f26996980007 100644
--- a/sys/amd64/linux/linux_locore.asm
+++ b/sys/amd64/linux/linux_locore.asm
@@ -1,4 +1,31 @@
-/* $FreeBSD$ */
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2015-2022 Dmitry Chagin <dchagin@freeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
 
 #include "linux_assym.h"			/* system definitions */
 #include <machine/asmacros.h>			/* miscellaneous asm macros */
@@ -14,15 +41,37 @@ linux_platform:
 	.text
 
 ENTRY(linux_rt_sigcode)
+	.cfi_startproc
+	.cfi_signal_frame
+	.cfi_def_cfa	%rsp, LINUX_RT_SIGF_SC
+	.cfi_offset	%r8, L_SC_R8
+	.cfi_offset	%r9, L_SC_R9
+	.cfi_offset	%r10, L_SC_R10
+	.cfi_offset	%r11, L_SC_R11
+	.cfi_offset	%r12, L_SC_R12
+	.cfi_offset	%r13, L_SC_R13
+	.cfi_offset	%r14, L_SC_R14
+	.cfi_offset	%r15, L_SC_R15
+	.cfi_offset	%rdi, L_SC_RDI
+	.cfi_offset	%rsi, L_SC_RSI
+	.cfi_offset	%rbp, L_SC_RBP
+	.cfi_offset	%rbx, L_SC_RBX
+	.cfi_offset	%rdx, L_SC_RDX
+	.cfi_offset	%rax, L_SC_RAX
+	.cfi_offset	%rcx, L_SC_RCX
+	.cfi_offset	%rip, L_SC_RIP
+	.cfi_offset	49, L_SC_RFLAGS
+	.cfi_offset	%cs, L_SC_CS
+	.cfi_offset	%rsp, L_SC_RSP
+
 	movq	%rsp, %rbx			/* rt_sigframe for rt_sigreturn */
 	call	*%rcx				/* call signal handler */
-.startrtsigcode:
 	movq	$LINUX_SYS_linux_rt_sigreturn, %rax
 	syscall
-	hlt
-.endrtsigcode:
-0:	jmp	0b
-
+0:	hlt
+	jmp	0b
+	.cfi_endproc
+END(linux_rt_sigcode)
 
 #if 0
 	.section .note.Linux, "a",@note
@@ -40,34 +89,3 @@ ENTRY(linux_rt_sigcode)
 	.balign 4
 	.previous
 #endif
-
-	.section .eh_frame,"a",@progbits
-.LSTARTFRAMEDLSI0:
-	.long .LENDCIEDLSI0-.LSTARTCIEDLSI0
-.LSTARTCIEDLSI0:
-	.long 0					/* CIE ID */
-	.byte 1					/* Version number */
-	.string "zR"				/* NULL-terminated
-						 * augmentation string
-						 */
-	.uleb128 1				/* Code alignment factor */
-	.sleb128 -4				/* Data alignment factor */
-	.byte 8					/* Return address register column */
-	.uleb128 1				/* Augmentation value length */
-	.byte 0x1b				/* DW_EH_PE_pcrel|DW_EH_PE_sdata4. */
-	.byte 0x0c				/* DW_CFA_def_cfa */
-	.uleb128 4
-	.uleb128 4
-	.byte 0x88				/* DW_CFA_offset, column 0x8 */
-	.uleb128 1
-	.align 4
-.LENDCIEDLSI0:
-	.long .LENDFDEDLSI0-.LSTARTFDEDLSI0	/* Length FDE */
-.LSTARTFDEDLSI0:
-	.long .LSTARTFDEDLSI0-.LSTARTFRAMEDLSI0	/* CIE pointer */
-	.long .startrtsigcode-.			/* PC-relative start address */
-	.long .endrtsigcode-.startrtsigcode
-	.uleb128 0
-	.align 4
-.LENDFDEDLSI0:
-	.previous
diff --git a/sys/amd64/linux32/linux32_genassym.c b/sys/amd64/linux32/linux32_genassym.c
index 1465863dd08c..4a87b5a423bc 100644
--- a/sys/amd64/linux32/linux32_genassym.c
+++ b/sys/amd64/linux32/linux32_genassym.c
@@ -14,5 +14,20 @@ __FBSDID("$FreeBSD$");
 ASSYM(LINUX_SIGF_SC, offsetof(struct l_sigframe, sf_sc));
 ASSYM(LINUX_RT_SIGF_UC, offsetof(struct l_rt_sigframe, sf_uc));
 ASSYM(LINUX_RT_SIGF_SC, offsetof(struct l_ucontext, uc_mcontext));
+ASSYM(L_SC_GS, offsetof(struct l_sigcontext, sc_gs));
+ASSYM(L_SC_FS, offsetof(struct l_sigcontext, sc_fs));
+ASSYM(L_SC_ES, offsetof(struct l_sigcontext, sc_es));
+ASSYM(L_SC_DS, offsetof(struct l_sigcontext, sc_ds));
+ASSYM(L_SC_CS, offsetof(struct l_sigcontext, sc_cs));
+ASSYM(L_SC_SS, offsetof(struct l_sigcontext, sc_ss));
+ASSYM(L_SC_EFLAGS, offsetof(struct l_sigcontext, sc_eflags));
+ASSYM(L_SC_EDI, offsetof(struct l_sigcontext, sc_edi));
+ASSYM(L_SC_ESI, offsetof(struct l_sigcontext, sc_esi));
+ASSYM(L_SC_EBP, offsetof(struct l_sigcontext, sc_ebp));
+ASSYM(L_SC_EBX, offsetof(struct l_sigcontext, sc_ebx));
+ASSYM(L_SC_EDX, offsetof(struct l_sigcontext, sc_edx));
+ASSYM(L_SC_ECX, offsetof(struct l_sigcontext, sc_ecx));
+ASSYM(L_SC_EAX, offsetof(struct l_sigcontext, sc_eax));
+ASSYM(L_SC_EIP, offsetof(struct l_sigcontext, sc_eip));
+ASSYM(L_SC_ESP, offsetof(struct l_sigcontext, sc_esp_at_signal));
 ASSYM(LINUX_VERSION_CODE, LINUX_VERSION_CODE);
-ASSYM(LINUX_SC_ESP, offsetof(struct l_sigcontext, sc_esp));
diff --git a/sys/amd64/linux32/linux32_locore.asm b/sys/amd64/linux32/linux32_locore.asm
index e0409969ee3b..f4cdc5fc1559 100644
--- a/sys/amd64/linux32/linux32_locore.asm
+++ b/sys/amd64/linux32/linux32_locore.asm
@@ -14,30 +14,96 @@ linux_platform:
 .text
 .code32
 
+ENTRY(linux32_vdso_sigcode)
+	.cfi_startproc
+	.cfi_signal_frame
+	.cfi_def_cfa	%esp, LINUX_SIGF_SC
+	.cfi_offset	%gs, L_SC_GS
+	.cfi_offset	%fs, L_SC_FS
+	.cfi_offset	%es, L_SC_ES
+	.cfi_offset	%ds, L_SC_DS
+	.cfi_offset	%cs, L_SC_CS
+	.cfi_offset	%ss, L_SC_SS
+	.cfi_offset	%flags, L_SC_EFLAGS
+	.cfi_offset	%edi, L_SC_EDI
+	.cfi_offset	%esi, L_SC_ESI
+	.cfi_offset	%ebp, L_SC_EBP
+	.cfi_offset	%ebx, L_SC_EBX
+	.cfi_offset	%edx, L_SC_EDX
+	.cfi_offset	%ecx, L_SC_ECX
+	.cfi_offset	%eax, L_SC_EAX
+	.cfi_offset	%eip, L_SC_EIP
+	.cfi_offset	%esp, L_SC_ESP
+
+	movl	%esp, %ebx			/* sigframe for sigreturn */
+	call	*%edi				/* call signal handler */
+	popl	%eax				/* gcc unwind code need this */
+	.cfi_def_cfa	%esp, LINUX_SIGF_SC-4
+	movl	$LINUX32_SYS_linux_sigreturn, %eax
+	int	$0x80
+0:	jmp	0b
+	.cfi_endproc
+END(linux32_vdso_sigcode)
+
+
+ENTRY(linux32_vdso_rt_sigcode)
+	.cfi_startproc
+	.cfi_signal_frame
+	.cfi_def_cfa	%esp, LINUX_RT_SIGF_UC + LINUX_RT_SIGF_SC
+	.cfi_offset	%gs, L_SC_GS
+	.cfi_offset	%fs, L_SC_FS
+	.cfi_offset	%es, L_SC_ES
+	.cfi_offset	%ds, L_SC_DS
+	.cfi_offset	%cs, L_SC_CS
+	.cfi_offset	%ss, L_SC_SS
+	.cfi_offset	%flags, L_SC_EFLAGS
+	.cfi_offset	%edi, L_SC_EDI
+	.cfi_offset	%esi, L_SC_ESI
+	.cfi_offset	%ebp, L_SC_EBP
+	.cfi_offset	%ebx, L_SC_EBX
+	.cfi_offset	%edx, L_SC_EDX
+	.cfi_offset	%ecx, L_SC_ECX
+	.cfi_offset	%eax, L_SC_EAX
+	.cfi_offset	%eip, L_SC_EIP
+	.cfi_offset	%esp, L_SC_ESP
+
+	leal	LINUX_RT_SIGF_UC(%esp), %ebx	/* linux ucontext for rt_sigreturn */
+	call	*%edi				/* call signal handler */
+	movl	$LINUX32_SYS_linux_rt_sigreturn, %eax
+	int	$0x80
+0:	jmp	0b
+	.cfi_endproc
+END(linux32_vdso_rt_sigcode)
+
 ENTRY(__kernel_sigreturn)
+	.cfi_startproc
+	.cfi_signal_frame
 	movl	%esp, %ebx			/* sigframe for sigreturn */
 	call	*%edi				/* call signal handler */
-.startsigcode:
 	popl	%eax				/* gcc unwind code need this */
 	movl	$LINUX32_SYS_linux_sigreturn, %eax
 	int	$0x80
-.endsigcode:
 0:	jmp	0b
+	.cfi_endproc
+END(__kernel_sigreturn)
 
 ENTRY(__kernel_rt_sigreturn)
+	.cfi_startproc
+	.cfi_signal_frame
 	leal	LINUX_RT_SIGF_UC(%esp), %ebx	/* linux ucontext for rt_sigreturn */
 	call	*%edi				/* call signal handler */
-.startrtsigcode:
 	movl	$LINUX32_SYS_linux_rt_sigreturn, %eax
 	int	$0x80
-.endrtsigcode:
 0:	jmp	0b
+	.cfi_endproc
+END(__kernel_rt_sigreturn)
 
 ENTRY(__kernel_vsyscall)
-.startvsyscall:
+	.cfi_startproc
 	int $0x80
 	ret
-.endvsyscall:
+	.cfi_endproc
+END(__kernel_vsyscall)
 
 #if 0
 	.section .note.Linux, "a",@note
@@ -55,86 +121,3 @@ ENTRY(__kernel_vsyscall)
 	.balign 4
 	.previous
 #endif
-
-#define do_cfa_expr(offset)						\
-	.byte 0x0f;			/* DW_CFA_def_cfa_expression */	\
-	.uleb128 11f-10f;		/*   length */			\
-10:	.byte 0x74;			/*     DW_OP_breg4 */		\
-	.sleb128 offset;		/*      offset */		\
-	.byte 0x06;			/*     DW_OP_deref */		\
-11:
-
-
-	/* CIE */
-	.section .eh_frame,"a",@progbits
-.LSTARTFRAMEDLSI1:
-	.long .LENDCIEDLSI1-.LSTARTCIEDLSI1
-.LSTARTCIEDLSI1:
-	.long 0					/* CIE ID */
-	.byte 1					/* Version number */
-	.string "zRS"				/* NULL-terminated
-						 * augmentation string
-						 */
-	.uleb128 1				/* Code alignment factor */
-	.sleb128 -4				/* Data alignment factor */
-	.byte 8					/* Return address
-						 * register column
-						 */
-	.uleb128 1				/* Augmentation value length */
-	.byte 0x1b				/* DW_EH_PE_pcrel|DW_EH_PE_sdata4. */
-	.byte 0					/* DW_CFA_nop */
-	.align 4
-.LENDCIEDLSI1:
-
-	/* FDE */
-	.long .LENDFDEDLSI1-.LSTARTFDEDLSI1	/* Length FDE */
-.LSTARTFDEDLSI1:
-	.long .LSTARTFDEDLSI1-.LSTARTFRAMEDLSI1 /* CIE pointer */
-	.long .startsigcode-.			/* PC-relative start address */
-	.long .endsigcode-.startsigcode
-	.uleb128 0				/* Augmentation */
-	do_cfa_expr(LINUX_SIGF_SC-8)
-	.align 4
-.LENDFDEDLSI1:
-
-	.long .LENDFDEDLSI2-.LSTARTFDEDLSI2	/* Length FDE */
-.LSTARTFDEDLSI2:
-	.long .LSTARTFDEDLSI2-.LSTARTFRAMEDLSI1	/* CIE pointer */
-	.long .startrtsigcode-.			/* PC-relative start address */
-	.long .endrtsigcode-.startrtsigcode
-	.uleb128 0				/* Augmentation */
-	do_cfa_expr(LINUX_RT_SIGF_SC-4+LINUX_SC_ESP)
-	.align 4
-.LENDFDEDLSI2:
-	.previous
-
-	.section .eh_frame,"a",@progbits
-.LSTARTFRAMEDLSI2:
-	.long .LENDCIEDLSI2-.LSTARTCIEDLSI2
-.LSTARTCIEDLSI2:
-	.long 0					/* CIE ID */
-	.byte 1					/* Version number */
-	.string "zR"				/* NULL-terminated
-						 * augmentation string
-						 */
-	.uleb128 1				/* Code alignment factor */
-	.sleb128 -4				/* Data alignment factor */
-	.byte 8					/* Return address register column */
-	.uleb128 1				/* Augmentation value length */
-	.byte 0x1b				/* DW_EH_PE_pcrel|DW_EH_PE_sdata4. */
-	.byte 0x0c				/* DW_CFA_def_cfa */
-	.uleb128 4
-	.uleb128 4
-	.byte 0x88				/* DW_CFA_offset, column 0x8 */
-	.uleb128 1
-	.align 4
-.LENDCIEDLSI2:
-	.long .LENDFDEDLSI3-.LSTARTFDEDLSI3 /* Length FDE */
-.LSTARTFDEDLSI3:
-	.long .LSTARTFDEDLSI3-.LSTARTFRAMEDLSI2 /* CIE pointer */
-	.long .startvsyscall-.			/* PC-relative start address */
-	.long .endvsyscall-.startvsyscall
-	.uleb128 0
-	.align 4
-.LENDFDEDLSI3:
-	.previous
diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c
index 729c000cc628..79409fc63828 100644
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -183,8 +183,8 @@ struct linux32_ps_strings {
 				    sizeof(struct linux32_ps_strings))
 
 LINUX_VDSO_SYM_INTPTR(__kernel_vsyscall);
-LINUX_VDSO_SYM_INTPTR(__kernel_sigreturn);
-LINUX_VDSO_SYM_INTPTR(__kernel_rt_sigreturn);
+LINUX_VDSO_SYM_INTPTR(linux32_vdso_sigcode);
+LINUX_VDSO_SYM_INTPTR(linux32_vdso_rt_sigcode);
 LINUX_VDSO_SYM_INTPTR(kern_timekeep_base);
 LINUX_VDSO_SYM_INTPTR(kern_tsc_selector);
 LINUX_VDSO_SYM_INTPTR(kern_cpu_selector);
@@ -367,7 +367,7 @@ linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
 
 	/* Build context to run handler in. */
 	regs->tf_rsp = PTROUT(fp);
-	regs->tf_rip = __kernel_rt_sigreturn;
+	regs->tf_rip = linux32_vdso_rt_sigcode;
 	regs->tf_rdi = PTROUT(catcher);
 	regs->tf_rflags &= ~(PSL_T | PSL_D);
 	regs->tf_cs = _ucode32sel;
@@ -473,7 +473,7 @@ linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
 
 	/* Build context to run handler in. */
 	regs->tf_rsp = PTROUT(fp);
-	regs->tf_rip = __kernel_sigreturn;
+	regs->tf_rip = linux32_vdso_sigcode;
 	regs->tf_rdi = PTROUT(catcher);
 	regs->tf_rflags &= ~(PSL_T | PSL_D);
 	regs->tf_cs = _ucode32sel;
diff --git a/sys/amd64/linux32/linux32_vdso.lds.s b/sys/amd64/linux32/linux32_vdso.lds.s
index cd5b4a20dee0..6b47a120847e 100644
--- a/sys/amd64/linux32/linux32_vdso.lds.s
+++ b/sys/amd64/linux32/linux32_vdso.lds.s
@@ -77,6 +77,8 @@ VERSION
 		kern_timekeep_base;
 		kern_tsc_selector;
 		kern_cpu_selector;
+		linux32_vdso_sigcode;
+		linux32_vdso_rt_sigcode;
 	local: *;
 	};
 }
diff --git a/sys/i386/linux/linux_genassym.c b/sys/i386/linux/linux_genassym.c
index 65757a51a190..a775a2525d4c 100644
--- a/sys/i386/linux/linux_genassym.c
+++ b/sys/i386/linux/linux_genassym.c
@@ -11,9 +11,22 @@ __FBSDID("$FreeBSD$");
 #include <x86/linux/linux_x86_sigframe.h>
 
 ASSYM(LINUX_SIGF_SC, offsetof(struct l_sigframe, sf_sc));
-ASSYM(LINUX_SC_GS, offsetof(struct l_sigcontext, sc_gs));
-ASSYM(LINUX_SC_EFLAGS, offsetof(struct l_sigcontext, sc_eflags));
 ASSYM(LINUX_RT_SIGF_UC, offsetof(struct l_rt_sigframe, sf_uc));
 ASSYM(LINUX_RT_SIGF_SC, offsetof(struct l_ucontext, uc_mcontext));
-ASSYM(LINUX_SC_ESP, offsetof(struct l_sigcontext, sc_esp));
+ASSYM(L_SC_GS, offsetof(struct l_sigcontext, sc_gs));
+ASSYM(L_SC_FS, offsetof(struct l_sigcontext, sc_fs));
+ASSYM(L_SC_ES, offsetof(struct l_sigcontext, sc_es));
+ASSYM(L_SC_DS, offsetof(struct l_sigcontext, sc_ds));
+ASSYM(L_SC_CS, offsetof(struct l_sigcontext, sc_cs));
+ASSYM(L_SC_SS, offsetof(struct l_sigcontext, sc_ss));
+ASSYM(L_SC_EFLAGS, offsetof(struct l_sigcontext, sc_eflags));
+ASSYM(L_SC_EDI, offsetof(struct l_sigcontext, sc_edi));
+ASSYM(L_SC_ESI, offsetof(struct l_sigcontext, sc_esi));
+ASSYM(L_SC_EBP, offsetof(struct l_sigcontext, sc_ebp));
+ASSYM(L_SC_EBX, offsetof(struct l_sigcontext, sc_ebx));
+ASSYM(L_SC_EDX, offsetof(struct l_sigcontext, sc_edx));
+ASSYM(L_SC_ECX, offsetof(struct l_sigcontext, sc_ecx));
+ASSYM(L_SC_EAX, offsetof(struct l_sigcontext, sc_eax));
+ASSYM(L_SC_EIP, offsetof(struct l_sigcontext, sc_eip));
+ASSYM(L_SC_ESP, offsetof(struct l_sigcontext, sc_esp_at_signal));
 ASSYM(LINUX_VERSION_CODE, LINUX_VERSION_CODE);
diff --git a/sys/i386/linux/linux_locore.asm b/sys/i386/linux/linux_locore.asm
index 3459fb5a56de..6b3cf01a8edc 100644
--- a/sys/i386/linux/linux_locore.asm
+++ b/sys/i386/linux/linux_locore.asm
@@ -15,30 +15,91 @@ linux_platform:
 
 	.text
 
-ENTRY(__kernel_sigreturn)
+ENTRY(linux_vdso_sigcode)
+	.cfi_startproc
+	.cfi_signal_frame
+	.cfi_def_cfa	%esp, LINUX_SIGF_SC
+	.cfi_offset	%gs, L_SC_GS
+	.cfi_offset	%fs, L_SC_FS
+	.cfi_offset	%es, L_SC_ES
+	.cfi_offset	%ds, L_SC_DS
+	.cfi_offset	%cs, L_SC_CS
+	.cfi_offset	%ss, L_SC_SS
+	.cfi_offset	%flags, L_SC_EFLAGS
+	.cfi_offset	%edi, L_SC_EDI
+	.cfi_offset	%esi, L_SC_ESI
+	.cfi_offset	%ebp, L_SC_EBP
+	.cfi_offset	%ebx, L_SC_EBX
+	.cfi_offset	%edx, L_SC_EDX
+	.cfi_offset	%ecx, L_SC_ECX
+	.cfi_offset	%eax, L_SC_EAX
+	.cfi_offset	%eip, L_SC_EIP
+	.cfi_offset	%esp, L_SC_ESP
+
 	movl	%esp, %ebx			/* sigframe for sigreturn */
 	call	*%edi				/* call signal handler */
-.startsigcode:
 	popl	%eax				/* gcc unwind code need this */
+	.cfi_def_cfa	%esp, LINUX_SIGF_SC-4
 	movl	$LINUX_SYS_linux_sigreturn, %eax
 	int	$0x80
-.endsigcode:
 0:	jmp	0b
+	.cfi_endproc
+END(linux_vdso_sigcode)
+
+ENTRY(linux_vdso_rt_sigcode)
+	.cfi_startproc
+	.cfi_signal_frame
+	.cfi_def_cfa	%esp, LINUX_RT_SIGF_UC + LINUX_RT_SIGF_SC
+	.cfi_offset	%gs, L_SC_GS
+	.cfi_offset	%fs, L_SC_FS
+	.cfi_offset	%es, L_SC_ES
+	.cfi_offset	%ds, L_SC_DS
+	.cfi_offset	%cs, L_SC_CS
+	.cfi_offset	%ss, L_SC_SS
+	.cfi_offset	%flags, L_SC_EFLAGS
+	.cfi_offset	%edi, L_SC_EDI
+	.cfi_offset	%esi, L_SC_ESI
+	.cfi_offset	%ebp, L_SC_EBP
+	.cfi_offset	%ebx, L_SC_EBX
+	.cfi_offset	%edx, L_SC_EDX
+	.cfi_offset	%ecx, L_SC_ECX
+	.cfi_offset	%eax, L_SC_EAX
+	.cfi_offset	%eip, L_SC_EIP
+	.cfi_offset	%esp, L_SC_ESP
 
-ENTRY(__kernel_rt_sigreturn)
 	leal	LINUX_RT_SIGF_UC(%esp), %ebx	/* linux ucontext for rt_sigreturn */
 	call	*%edi				/* call signal handler */
-.startrtsigcode:
 	movl	$LINUX_SYS_linux_rt_sigreturn, %eax
 	int	$0x80
-.endrtsigcode:
 0:	jmp	0b
+	.cfi_endproc
+END(linux_vdso_rt_sigcode)
+
+ENTRY(__kernel_sigreturn)
+	.cfi_startproc
+	.cfi_signal_frame
+	popl	%eax				/* gcc unwind code need this */
+	movl	$LINUX_SYS_linux_sigreturn, %eax
+	int	$0x80
+0:	jmp	0b
+	.cfi_endproc
+END(__kernel_sigreturn)
+
+ENTRY(__kernel_rt_sigreturn)
+	.cfi_startproc
+	.cfi_signal_frame
+	movl	$LINUX_SYS_linux_rt_sigreturn, %eax
+	int	$0x80
+0:	jmp	0b
+	.cfi_endproc
+END(__kernel_rt_sigreturn)
 
 ENTRY(__kernel_vsyscall)
-.startvsyscall:
+	.cfi_startproc
 	int $0x80
 	ret
-.endvsyscall:
+	.cfi_endproc
+END(__kernel_vsyscall)
 
 #if 0
 	.section .note.Linux, "a",@note
@@ -56,86 +117,3 @@ ENTRY(__kernel_vsyscall)
 	.balign 4
 	.previous
 #endif
-
-#define do_cfa_expr(offset)						\
-	.byte 0x0f;			/* DW_CFA_def_cfa_expression */	\
-	.uleb128 11f-10f;		/*   length */			\
-10:	.byte 0x74;			/*     DW_OP_breg4 */		\
-	.sleb128 offset;		/*      offset */		\
-	.byte 0x06;			/*     DW_OP_deref */		\
-11:
-
-
-	/* CIE */
-	.section .eh_frame,"a",@progbits
-.LSTARTFRAMEDLSI1:
-	.long .LENDCIEDLSI1-.LSTARTCIEDLSI1
-.LSTARTCIEDLSI1:
-	.long 0					/* CIE ID */
-	.byte 1					/* Version number */
-	.string "zRS"				/* NULL-terminated
-						 * augmentation string
-						 */
-	.uleb128 1				/* Code alignment factor */
-	.sleb128 -4				/* Data alignment factor */
-	.byte 8					/* Return address
-						 * register column
-						 */
-	.uleb128 1				/* Augmentation value length */
-	.byte 0x1b				/* DW_EH_PE_pcrel|DW_EH_PE_sdata4. */
-	.byte 0					/* DW_CFA_nop */
-	.align 4
-.LENDCIEDLSI1:
-
-	/* FDE */
-	.long .LENDFDEDLSI1-.LSTARTFDEDLSI1	/* Length FDE */
-.LSTARTFDEDLSI1:
-	.long .LSTARTFDEDLSI1-.LSTARTFRAMEDLSI1 /* CIE pointer */
-	.long .startsigcode-.			/* PC-relative start address */
-	.long .endsigcode-.startsigcode
-	.uleb128 0				/* Augmentation */
-	do_cfa_expr(LINUX_SIGF_SC-8)
-	.align 4
-.LENDFDEDLSI1:
-
-	.long .LENDFDEDLSI2-.LSTARTFDEDLSI2	/* Length FDE */
-.LSTARTFDEDLSI2:
-	.long .LSTARTFDEDLSI2-.LSTARTFRAMEDLSI1	/* CIE pointer */
-	.long .startrtsigcode-.			/* PC-relative start address */
-	.long .endrtsigcode-.startrtsigcode
-	.uleb128 0				/* Augmentation */
-	do_cfa_expr(LINUX_RT_SIGF_SC-4+LINUX_SC_ESP)
-	.align 4
-.LENDFDEDLSI2:
-	.previous
-
-	.section .eh_frame,"a",@progbits
-.LSTARTFRAMEDLSI2:
-	.long .LENDCIEDLSI2-.LSTARTCIEDLSI2
-.LSTARTCIEDLSI2:
-	.long 0					/* CIE ID */
-	.byte 1					/* Version number */
-	.string "zR"				/* NULL-terminated
-						 * augmentation string
-						 */
-	.uleb128 1				/* Code alignment factor */
-	.sleb128 -4				/* Data alignment factor */
-	.byte 8					/* Return address register column */
-	.uleb128 1				/* Augmentation value length */
-	.byte 0x1b				/* DW_EH_PE_pcrel|DW_EH_PE_sdata4. */
-	.byte 0x0c				/* DW_CFA_def_cfa */
-	.uleb128 4
-	.uleb128 4
-	.byte 0x88				/* DW_CFA_offset, column 0x8 */
-	.uleb128 1
-	.align 4
-.LENDCIEDLSI2:
-	.long .LENDFDEDLSI3-.LSTARTFDEDLSI3 /* Length FDE */
-.LSTARTFDEDLSI3:
-	.long .LSTARTFDEDLSI3-.LSTARTFRAMEDLSI2 /* CIE pointer */
-	.long .startvsyscall-.			/* PC-relative start address */
-	.long .endvsyscall-.startvsyscall
-	.uleb128 0
-	.align 4
-.LENDFDEDLSI3:
-	.previous
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
index ab53ccbf6bb1..a4d1980fd33e 100644
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -158,8 +158,8 @@ static int _bsd_to_linux_trapcode[] = {
 
 LINUX_VDSO_SYM_CHAR(linux_platform);
 LINUX_VDSO_SYM_INTPTR(__kernel_vsyscall);
-LINUX_VDSO_SYM_INTPTR(__kernel_sigreturn);
-LINUX_VDSO_SYM_INTPTR(__kernel_rt_sigreturn);
+LINUX_VDSO_SYM_INTPTR(linux_vdso_sigcode);
+LINUX_VDSO_SYM_INTPTR(linux_vdso_rt_sigcode);
 LINUX_VDSO_SYM_INTPTR(kern_timekeep_base);
 LINUX_VDSO_SYM_INTPTR(kern_tsc_selector);
 LINUX_VDSO_SYM_INTPTR(kern_cpu_selector);
@@ -473,7 +473,7 @@ linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
 
 	/* Build context to run handler in. */
 	regs->tf_esp = PTROUT(fp);
-	regs->tf_eip = __kernel_rt_sigreturn;
+	regs->tf_eip = linux_vdso_rt_sigcode;
 	regs->tf_edi = PTROUT(catcher);
 	regs->tf_eflags &= ~(PSL_T | PSL_VM | PSL_D);
 	regs->tf_cs = _ucodesel;
@@ -574,7 +574,7 @@ linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
 
 	/* Build context to run handler in. */
 	regs->tf_esp = PTROUT(fp);
-	regs->tf_eip = __kernel_sigreturn;
+	regs->tf_eip = linux_vdso_sigcode;
 	regs->tf_edi = PTROUT(catcher);
 	regs->tf_eflags &= ~(PSL_T | PSL_VM | PSL_D);
 	regs->tf_cs = _ucodesel;
diff --git a/sys/i386/linux/linux_vdso.lds.s b/sys/i386/linux/linux_vdso.lds.s
index cd5b4a20dee0..818685800d83 100644
--- a/sys/i386/linux/linux_vdso.lds.s
+++ b/sys/i386/linux/linux_vdso.lds.s
@@ -77,6 +77,8 @@ VERSION
 		kern_timekeep_base;
 		kern_tsc_selector;
 		kern_cpu_selector;
+		linux_vdso_sigcode;
+		linux_vdso_rt_sigcode;
 	local: *;
 	};
 }