diff options
Diffstat (limited to 'main/libc0.9.32/0013-libc-x86-fix-stack-unwinding-and-backtrace-informati.patch')
-rw-r--r-- | main/libc0.9.32/0013-libc-x86-fix-stack-unwinding-and-backtrace-informati.patch | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/main/libc0.9.32/0013-libc-x86-fix-stack-unwinding-and-backtrace-informati.patch b/main/libc0.9.32/0013-libc-x86-fix-stack-unwinding-and-backtrace-informati.patch new file mode 100644 index 000000000..d8961b2bc --- /dev/null +++ b/main/libc0.9.32/0013-libc-x86-fix-stack-unwinding-and-backtrace-informati.patch @@ -0,0 +1,251 @@ +From 9d28002b230eb01a5db7aecab263d38bf0d6d6c7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi> +Date: Thu, 10 Nov 2011 09:36:44 +0200 +Subject: [PATCH] libc/x86: fix stack unwinding and backtrace information +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When compiled without framepointer, the DWARF-2 CFI data is required +for proper stack unwinding. + +This patch adds the CFI information to: + * syscalls (so we get proper backtrace even for release builds) + the ebx hack was removed as it would complicate the CFI generation + * new thread stub function (so the backtrace is clean for user + created threads) + +Also pads the signal return trampolines separate from other functions. +If CFI info was found for signal return code (which seems to happen if +it's located right next a valid function), it will not be recognized +as signal trampoline (gcc unwinder and gdb check first CFI info, and +only if it does not exists it compares the exact opcode sequence to +see if we are at signal return code block). This fixes a real crash +if thread is cancelled and the cancellation handler fails to detect the +signal return frame. + +Signed-off-by: Timo Teräs <timo.teras@iki.fi> +Signed-off-by: Natanael Copa <ncopa@alpinelinux.org> +--- + libc/sysdeps/linux/i386/bits/syscalls.h | 82 +++---------------------------- + libc/sysdeps/linux/i386/clone.S | 17 ++++++ + libc/sysdeps/linux/i386/sigaction.c | 4 ++ + 3 files changed, 28 insertions(+), 75 deletions(-) + +diff --git a/libc/sysdeps/linux/i386/bits/syscalls.h b/libc/sysdeps/linux/i386/bits/syscalls.h +index eeafb3a..1f60a44 100644 +--- a/libc/sysdeps/linux/i386/bits/syscalls.h ++++ b/libc/sysdeps/linux/i386/bits/syscalls.h +@@ -13,6 +13,7 @@ + #ifndef __ASSEMBLER__ + + #include <errno.h> ++#include <common/sysdep.h> + + #define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ + ({ \ +@@ -31,90 +32,21 @@ + + #if 1 /* defined __PIC__ || defined __pic__ */ + +-/* This code avoids pushing/popping ebx as much as possible. +- * I think the main reason was that older GCCs had problems +- * with proper saving/restoring of ebx if "b" constraint was used, +- * which was breaking -fPIC code really badly. +- * At least gcc 4.2.x seems to not need these tricks anymore, +- * but this code is still useful because it often avoids +- * using stack for saving ebx. +- * Keeping it unconditionally enabled for now. +- */ +- +-/* We need some help from the assembler to generate optimal code. +- * We define some macros here which later will be used. */ +-/* gcc>=4.6 with LTO need the same guards as IMA (a.k.a --combine) did. +- * See gcc.gnu.org/PR47577 */ +-/* FIXME: drop these b* macros! */ +- +-__asm__ ( +-#if defined __DOMULTI__ || __GNUC_PREREQ (4, 6) +- /* Protect against asm macro redefinition (happens in __DOMULTI__ mode). +- * Unfortunately, it ends up visible in .o files. */ +- ".ifndef _BITS_SYSCALLS_ASM\n\t" +- ".set _BITS_SYSCALLS_ASM,1\n\t" +-#endif +- ".L__X'%ebx = 1\n\t" +- ".L__X'%ecx = 2\n\t" +- ".L__X'%edx = 2\n\t" +- ".L__X'%eax = 3\n\t" +- ".L__X'%esi = 3\n\t" +- ".L__X'%edi = 3\n\t" +- ".L__X'%ebp = 3\n\t" +- ".L__X'%esp = 3\n\t" +- +- /* Loading param #1 (ebx) is done by loading it into +- * another register, and then performing bpushl+bmovl, +- * since we must preserve ebx */ +- +- ".macro bpushl name reg\n\t" +- ".if 1 - \\name\n\t" /* if reg!=ebx... */ +- ".if 2 - \\name\n\t" /* if reg can't be clobbered... */ +- "pushl %ebx\n\t" /* save ebx on stack */ +- ".else\n\t" +- "xchgl \\reg, %ebx\n\t" /* else save ebx in reg, and load reg to ebx */ +- ".endif\n\t" +- ".endif\n\t" +- ".endm\n\t" +- +- ".macro bmovl name reg\n\t" +- ".if 1 - \\name\n\t" +- ".if 2 - \\name\n\t" /* if reg can't be clobbered... */ +- "movl \\reg, %ebx\n\t" /* load reg to ebx */ +- ".endif\n\t" +- ".endif\n\t" +- ".endm\n\t" +- +- ".macro bpopl name reg\n\t" +- ".if 1 - \\name\n\t" +- ".if 2 - \\name\n\t" /* if reg can't be clobbered... */ +- "popl %ebx\n\t" /* restore ebx from stack */ +- ".else\n\t" +- "xchgl \\reg, %ebx\n\t" /* else restore ebx from reg */ +- ".endif\n\t" +- ".endif\n\t" +- ".endm\n\t" +- +-#if defined __DOMULTI__ || __GNUC_PREREQ (4, 6) +- ".endif\n\t" /* _BITS_SYSCALLS_ASM */ +-#endif +-); +- + #define LOADARGS_0 +-#define LOADARGS_1 "bpushl .L__X'%k2, %k2\n\t" "bmovl .L__X'%k2, %k2\n\t" ++#define LOADARGS_1 "push %%ebx\n\t" CFI_ADJUST_CFA_OFFSET(4) "\n\t" CFI_REL_OFFSET(ebx, 0) "\n\t" "movl %k2, %%ebx\n\t" + #define LOADARGS_2 LOADARGS_1 + #define LOADARGS_3 LOADARGS_1 + #define LOADARGS_4 LOADARGS_1 + #define LOADARGS_5 LOADARGS_1 +-#define LOADARGS_6 LOADARGS_1 "push %%ebp\n\t" "movl %7, %%ebp\n\t" ++#define LOADARGS_6 LOADARGS_1 "push %%ebp\n\t" CFI_ADJUST_CFA_OFFSET(4) "\n\t" CFI_REL_OFFSET(ebp, 0) "\n\t" "movl %7, %%ebp\n\t" + + #define RESTOREARGS_0 +-#define RESTOREARGS_1 "bpopl .L__X'%k2, %k2\n\t" ++#define RESTOREARGS_1 "pop %%ebx\n\t" CFI_ADJUST_CFA_OFFSET(-4) "\n\t" CFI_RESTORE(ebx) "\n\t" RESTOREARGS_0 + #define RESTOREARGS_2 RESTOREARGS_1 + #define RESTOREARGS_3 RESTOREARGS_1 + #define RESTOREARGS_4 RESTOREARGS_1 + #define RESTOREARGS_5 RESTOREARGS_1 +-#define RESTOREARGS_6 "pop %%ebp\n\t" RESTOREARGS_1 ++#define RESTOREARGS_6 "pop %%ebp\n\t" CFI_ADJUST_CFA_OFFSET(-4) "\n\t" CFI_RESTORE(ebp) "\n\t" RESTOREARGS_1 + + #define ASMFMT_0() + /* "acdSD" constraint would work too, but "SD" would use esi/edi and cause +@@ -162,7 +94,7 @@ __asm__ ( + #define LOADARGS_3 + #define LOADARGS_4 + #define LOADARGS_5 +-#define LOADARGS_6 "push %%ebp\n\t" "movl %7, %%ebp\n\t" ++#define LOADARGS_6 "push %%ebp\n\t" CFI_ADJUST_CFA_OFFSET(4) "\n\t" CFI_REL_OFFSET(ebp, 0) "\n\t" "movl %7, %%ebp\n\t" + + #define RESTOREARGS_0 + #define RESTOREARGS_1 +@@ -170,7 +102,7 @@ __asm__ ( + #define RESTOREARGS_3 + #define RESTOREARGS_4 + #define RESTOREARGS_5 +-#define RESTOREARGS_6 "pop %%ebp\n\t" ++#define RESTOREARGS_6 "pop %%ebp\n\t" CFI_ADJUST_CFA_OFFSET(-4) "\n\t" CFI_RESTORE(ebp) "\n\t" + + #define ASMFMT_0() + #define ASMFMT_1(arg1) \ +diff --git a/libc/sysdeps/linux/i386/clone.S b/libc/sysdeps/linux/i386/clone.S +index a7de3fe..cf6cd35 100644 +--- a/libc/sysdeps/linux/i386/clone.S ++++ b/libc/sysdeps/linux/i386/clone.S +@@ -25,6 +25,7 @@ + + #define _ERRNO_H 1 + #include <bits/errno.h> ++#include <sysdep.h> + #include <sys/syscall.h> + + /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, +@@ -45,6 +46,7 @@ + .global clone + .type clone,%function + clone: ++ cfi_startproc; + /* Sanity check arguments. */ + movl $-EINVAL,%eax + +@@ -86,17 +88,28 @@ clone: + + /* Do the system call */ + pushl %ebx ++ cfi_adjust_cfa_offset (4) + pushl %esi ++ cfi_adjust_cfa_offset (4) + pushl %edi ++ cfi_adjust_cfa_offset (4) ++ + movl TLS+12(%esp),%esi ++ cfi_rel_offset (esi, 4) + movl PTID+12(%esp),%edx + movl FLAGS+12(%esp),%ebx ++ cfi_rel_offset (ebx, 8) + movl CTID+12(%esp),%edi ++ cfi_rel_offset (edi, 0) + movl $__NR_clone,%eax + #ifdef RESET_PID + /* Remember the flag value. */ + movl %ebx, (%ecx) + #endif ++ /* End FDE now, because in the child the unwind info will be ++ wrong. */ ++ cfi_endproc ++ + int $0x80 + popl %edi + popl %esi +@@ -108,6 +121,9 @@ clone: + ret + + .Lthread_start: ++ cfi_startproc; ++ /* Clearing frame pointer is insufficient, use CFI. */ ++ cfi_undefined (eip); + /* Note: %esi is zero. */ + movl %esi,%ebp /* terminate the stack frame */ + call *%ebx +@@ -120,6 +136,7 @@ clone: + movl %eax, %ebx + movl $__NR_exit, %eax + int $0x80 ++ cfi_endproc; + + /* Need to indirect jump to syscall error + * or we end up with TEXTREL's +diff --git a/libc/sysdeps/linux/i386/sigaction.c b/libc/sysdeps/linux/i386/sigaction.c +index de0c75d..f9af3f7 100644 +--- a/libc/sysdeps/linux/i386/sigaction.c ++++ b/libc/sysdeps/linux/i386/sigaction.c +@@ -112,6 +112,9 @@ libc_hidden_weak(sigaction) + #define RESTORE2(name, syscall) \ + __asm__ ( \ + ".text\n" \ ++ ".align 8\n" \ ++ " nop\n" \ ++ ".align 16\n" \ + "__" #name ":\n" \ + " movl $" #syscall ", %eax\n" \ + " int $0x80\n" \ +@@ -128,6 +131,7 @@ RESTORE(restore_rt, __NR_rt_sigreturn) + # define RESTORE2(name, syscall) \ + __asm__ ( \ + ".text\n" \ ++ ".align 8\n" \ + "__" #name ":\n" \ + " popl %eax\n" \ + " movl $" #syscall ", %eax\n" \ +-- +1.7.8 + |