The vdso32 sigreturn.S contains open-coded DWARF bytecode, which
includes a hack for gdb to not try to step back to a previous call
instruction when backtracing from a signal handler.

Neither of those are necessary anymore: the backtracing issue is
handled by ".cfi_entry simple" and ".cfi_signal_frame", both of which
have been supported for a very long time now, which allows the
remaining frame to be built using regular .cfi annotations.

Add a few more register offsets to the signal frame just for good
measure.

Replace the nop on fallthrough of the system call (which should never,
ever happen) with a ud2a trap.

Signed-off-by: H. Peter Anvin (Intel) <[email protected]>
---
 arch/x86/entry/vdso/vdso32/sigreturn.S | 146 ++++++-------------------
 arch/x86/include/asm/dwarf2.h          |   1 +
 arch/x86/kernel/asm-offsets.c          |   6 +
 3 files changed, 39 insertions(+), 114 deletions(-)

diff --git a/arch/x86/entry/vdso/vdso32/sigreturn.S 
b/arch/x86/entry/vdso/vdso32/sigreturn.S
index 965900c6763b..25b0ac4b4bfe 100644
--- a/arch/x86/entry/vdso/vdso32/sigreturn.S
+++ b/arch/x86/entry/vdso/vdso32/sigreturn.S
@@ -1,136 +1,54 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 #include <linux/linkage.h>
 #include <asm/unistd_32.h>
+#include <asm/dwarf2.h>
 #include <asm/asm-offsets.h>
 
+.macro STARTPROC_SIGNAL_FRAME sc
+       CFI_STARTPROC   simple
+       CFI_SIGNAL_FRAME
+       /* -4 as pretcode has already been popped */
+       CFI_DEF_CFA     esp,    \sc - 4
+       CFI_OFFSET      eip,    IA32_SIGCONTEXT_ip
+       CFI_OFFSET      eax,    IA32_SIGCONTEXT_ax
+       CFI_OFFSET      ebx,    IA32_SIGCONTEXT_bx
+       CFI_OFFSET      ecx,    IA32_SIGCONTEXT_cx
+       CFI_OFFSET      edx,    IA32_SIGCONTEXT_dx
+       CFI_OFFSET      esp,    IA32_SIGCONTEXT_sp
+       CFI_OFFSET      ebp,    IA32_SIGCONTEXT_bp
+       CFI_OFFSET      esi,    IA32_SIGCONTEXT_si
+       CFI_OFFSET      edi,    IA32_SIGCONTEXT_di
+       CFI_OFFSET      es,     IA32_SIGCONTEXT_es
+       CFI_OFFSET      cs,     IA32_SIGCONTEXT_cs
+       CFI_OFFSET      ss,     IA32_SIGCONTEXT_ss
+       CFI_OFFSET      ds,     IA32_SIGCONTEXT_ds
+       CFI_OFFSET      eflags, IA32_SIGCONTEXT_flags
+.endm
+
        .text
        .globl __kernel_sigreturn
        .type __kernel_sigreturn,@function
-       nop /* this guy is needed for .LSTARTFDEDLSI1 below (watch for HACK) */
        ALIGN
 __kernel_sigreturn:
-.LSTART_sigreturn:
-       popl %eax               /* XXX does this mean it needs unwind info? */
+       STARTPROC_SIGNAL_FRAME IA32_SIGFRAME_sigcontext
+       popl %eax
+       CFI_ADJUST_CFA_OFFSET -4
        movl $__NR_sigreturn, %eax
        int $0x80
-.LEND_sigreturn:
 SYM_INNER_LABEL(vdso32_sigreturn_landing_pad, SYM_L_GLOBAL)
-       nop
-       .size __kernel_sigreturn,.-.LSTART_sigreturn
+       ud2a
+       CFI_ENDPROC
+       .size __kernel_sigreturn,.-__kernel_sigreturn
 
        .globl __kernel_rt_sigreturn
        .type __kernel_rt_sigreturn,@function
        ALIGN
 __kernel_rt_sigreturn:
-.LSTART_rt_sigreturn:
+       STARTPROC_SIGNAL_FRAME IA32_RT_SIGFRAME_sigcontext
        movl $__NR_rt_sigreturn, %eax
        int $0x80
-.LEND_rt_sigreturn:
 SYM_INNER_LABEL(vdso32_rt_sigreturn_landing_pad, SYM_L_GLOBAL)
-       nop
-       .size __kernel_rt_sigreturn,.-.LSTART_rt_sigreturn
-       .previous
-
-       .section .eh_frame,"a",@progbits
-.LSTARTFRAMEDLSI1:
-       .long .LENDCIEDLSI1-.LSTARTCIEDLSI1
-.LSTARTCIEDLSI1:
-       .long 0                 /* CIE ID */
-       .byte 1                 /* Version number */
-       .string "zRS"           /* NUL-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:
-       .long .LENDFDEDLSI1-.LSTARTFDEDLSI1 /* Length FDE */
-.LSTARTFDEDLSI1:
-       .long .LSTARTFDEDLSI1-.LSTARTFRAMEDLSI1 /* CIE pointer */
-       /* HACK: The dwarf2 unwind routines will subtract 1 from the
-          return address to get an address in the middle of the
-          presumed call instruction.  Since we didn't get here via
-          a call, we need to include the nop before the real start
-          to make up for it.  */
-       .long .LSTART_sigreturn-1-.     /* PC-relative start address */
-       .long .LEND_sigreturn-.LSTART_sigreturn+1
-       .uleb128 0                      /* Augmentation */
-       /* What follows are the instructions for the table generation.
-          We record the locations of each register saved.  This is
-          complicated by the fact that the "CFA" is always assumed to
-          be the value of the stack pointer in the caller.  This means
-          that we must define the CFA of this body of code to be the
-          saved value of the stack pointer in the sigcontext.  Which
-          also means that there is no fixed relation to the other
-          saved registers, which means that we must use DW_CFA_expression
-          to compute their addresses.  It also means that when we
-          adjust the stack with the popl, we have to do it all over again.  */
-
-#define do_cfa_expr(offset)                                            \
-       .byte 0x0f;                     /* DW_CFA_def_cfa_expression */ \
-       .uleb128 1f-0f;                 /*   length */                  \
-0:     .byte 0x74;                     /*     DW_OP_breg4 */           \
-       .sleb128 offset;                /*      offset */               \
-       .byte 0x06;                     /*     DW_OP_deref */           \
-1:
-
-#define do_expr(regno, offset)                                         \
-       .byte 0x10;                     /* DW_CFA_expression */         \
-       .uleb128 regno;                 /*   regno */                   \
-       .uleb128 1f-0f;                 /*   length */                  \
-0:     .byte 0x74;                     /*     DW_OP_breg4 */           \
-       .sleb128 offset;                /*       offset */              \
-1:
-
-       do_cfa_expr(IA32_SIGCONTEXT_sp+4)
-       do_expr(0, IA32_SIGCONTEXT_ax+4)
-       do_expr(1, IA32_SIGCONTEXT_cx+4)
-       do_expr(2, IA32_SIGCONTEXT_dx+4)
-       do_expr(3, IA32_SIGCONTEXT_bx+4)
-       do_expr(5, IA32_SIGCONTEXT_bp+4)
-       do_expr(6, IA32_SIGCONTEXT_si+4)
-       do_expr(7, IA32_SIGCONTEXT_di+4)
-       do_expr(8, IA32_SIGCONTEXT_ip+4)
-
-       .byte 0x42      /* DW_CFA_advance_loc 2 -- nop; popl eax. */
-
-       do_cfa_expr(IA32_SIGCONTEXT_sp)
-       do_expr(0, IA32_SIGCONTEXT_ax)
-       do_expr(1, IA32_SIGCONTEXT_cx)
-       do_expr(2, IA32_SIGCONTEXT_dx)
-       do_expr(3, IA32_SIGCONTEXT_bx)
-       do_expr(5, IA32_SIGCONTEXT_bp)
-       do_expr(6, IA32_SIGCONTEXT_si)
-       do_expr(7, IA32_SIGCONTEXT_di)
-       do_expr(8, IA32_SIGCONTEXT_ip)
-
-       .align 4
-.LENDFDEDLSI1:
-
-       .long .LENDFDEDLSI2-.LSTARTFDEDLSI2 /* Length FDE */
-.LSTARTFDEDLSI2:
-       .long .LSTARTFDEDLSI2-.LSTARTFRAMEDLSI1 /* CIE pointer */
-       /* HACK: See above wrt unwind library assumptions.  */
-       .long .LSTART_rt_sigreturn-1-.  /* PC-relative start address */
-       .long .LEND_rt_sigreturn-.LSTART_rt_sigreturn+1
-       .uleb128 0                      /* Augmentation */
-       /* What follows are the instructions for the table generation.
-          We record the locations of each register saved.  This is
-          slightly less complicated than the above, since we don't
-          modify the stack pointer in the process.  */
-
-       do_cfa_expr(IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_sp)
-       do_expr(0, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_ax)
-       do_expr(1, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_cx)
-       do_expr(2, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_dx)
-       do_expr(3, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_bx)
-       do_expr(5, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_bp)
-       do_expr(6, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_si)
-       do_expr(7, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_di)
-       do_expr(8, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_ip)
-
-       .align 4
-.LENDFDEDLSI2:
+       ud2a
+       CFI_ENDPROC
+       .size __kernel_rt_sigreturn,.-__kernel_rt_sigreturn
        .previous
diff --git a/arch/x86/include/asm/dwarf2.h b/arch/x86/include/asm/dwarf2.h
index 302e11b15da8..09c9684d3ad6 100644
--- a/arch/x86/include/asm/dwarf2.h
+++ b/arch/x86/include/asm/dwarf2.h
@@ -20,6 +20,7 @@
 #define CFI_RESTORE_STATE      .cfi_restore_state
 #define CFI_UNDEFINED          .cfi_undefined
 #define CFI_ESCAPE             .cfi_escape
+#define CFI_SIGNAL_FRAME       .cfi_signal_frame
 
 #ifndef BUILD_VDSO
        /*
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
index 32ba599a51f8..a7e7df837405 100644
--- a/arch/x86/kernel/asm-offsets.c
+++ b/arch/x86/kernel/asm-offsets.c
@@ -63,8 +63,14 @@ static void __used common(void)
        OFFSET(IA32_SIGCONTEXT_bp, sigcontext_32, bp);
        OFFSET(IA32_SIGCONTEXT_sp, sigcontext_32, sp);
        OFFSET(IA32_SIGCONTEXT_ip, sigcontext_32, ip);
+       OFFSET(IA32_SIGCONTEXT_es, sigcontext_32, es);
+       OFFSET(IA32_SIGCONTEXT_cs, sigcontext_32, cs);
+       OFFSET(IA32_SIGCONTEXT_ss, sigcontext_32, ss);
+       OFFSET(IA32_SIGCONTEXT_ds, sigcontext_32, ds);
+       OFFSET(IA32_SIGCONTEXT_flags, sigcontext_32, flags);
 
        BLANK();
+       OFFSET(IA32_SIGFRAME_sigcontext,    sigframe_ia32,    sc);
        OFFSET(IA32_RT_SIGFRAME_sigcontext, rt_sigframe_ia32, uc.uc_mcontext);
 #endif
 
-- 
2.51.1


Reply via email to