Index: contrib/gcc/config/i386/freebsd.h =================================================================== --- contrib/gcc/config/i386/freebsd.h (版本 187994) +++ contrib/gcc/config/i386/freebsd.h (工作副本) @@ -239,3 +239,5 @@ XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); \ fprintf (asm_out_file, "\n"); \ } while (0) + +#define MD_UNWIND_SUPPORT "config/i386/freebsd-unwind.h" --- /dev/null 2009-02-03 14:45:38.000000000 +0800 +++ contrib/gcc/config/i386/freebsd-unwind.h 2009-02-02 14:44:42.000000000 +0800 @@ -0,0 +1,168 @@ +/* DWARF2 EH unwinding support for AMD x86-64 and x86. + Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file with other programs, and to distribute +those programs without any restriction coming from the use of this +file. (The General Public License restrictions do apply in other +respects; for example, they cover modification of the file, and +distribution when not linked into another program.) + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING. If not, write to +the Free Software Foundation, 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ + +/* Do code reading to identify a signal frame, and set the frame + state data appropriately. See unwind-dw2.c for the structs. + is used. */ + +#include +#include +#include +#include +#include + + +#define REG_NAME(reg) sf_uc.uc_mcontext.mc_## reg + +static void +x86_sigtramp_range (unsigned char **start, unsigned char **end) +{ + static unsigned long ps_strings = 0; + int mib[2]; + size_t len; + + if (ps_strings == 0) + { + mib[0] = CTL_KERN; + mib[1] = KERN_PS_STRINGS; + len = sizeof (ps_strings); + sysctl (mib, 2, &ps_strings, &len, NULL, 0); + } + + *start = (unsigned char *)ps_strings - 128; + *end = (unsigned char *)ps_strings; +} + +#ifdef __x86_64__ + +#define MD_FALLBACK_FRAME_STATE_FOR x86_64_fallback_frame_state + +static _Unwind_Reason_Code +x86_64_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + unsigned char *pc = context->ra; + unsigned char *sigtramp_start, *sigtramp_end; + struct sigframe *sf; + long new_cfa; + + x86_sigtramp_range(&sigtramp_start, &sigtramp_end); + if (pc >= sigtramp_end || pc < sigtramp_start) + return _URC_END_OF_STACK; + + sf = (struct sigframe *) context->cfa; + new_cfa = sf->REG_NAME(rsp); + fs->cfa_how = CFA_REG_OFFSET; + /* Register 7 is rsp */ + fs->cfa_reg = 7; + fs->cfa_offset = new_cfa - (long) context->cfa; + + /* The SVR4 register numbering macros aren't usable in libgcc. */ + fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.reg[0].loc.offset = (long)&sf->REG_NAME(rax) - new_cfa; + fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.reg[1].loc.offset = (long)&sf->REG_NAME(rdx) - new_cfa; + fs->regs.reg[2].how = REG_SAVED_OFFSET; + fs->regs.reg[2].loc.offset = (long)&sf->REG_NAME(rcx) - new_cfa; + fs->regs.reg[3].how = REG_SAVED_OFFSET; + fs->regs.reg[3].loc.offset = (long)&sf->REG_NAME(rbx) - new_cfa; + fs->regs.reg[4].how = REG_SAVED_OFFSET; + fs->regs.reg[4].loc.offset = (long)&sf->REG_NAME(rsi) - new_cfa; + fs->regs.reg[5].how = REG_SAVED_OFFSET; + fs->regs.reg[5].loc.offset = (long)&sf->REG_NAME(rdi) - new_cfa; + fs->regs.reg[6].how = REG_SAVED_OFFSET; + fs->regs.reg[6].loc.offset = (long)&sf->REG_NAME(rbp) - new_cfa; + fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.reg[8].loc.offset = (long)&sf->REG_NAME(r8) - new_cfa; + fs->regs.reg[9].how = REG_SAVED_OFFSET; + fs->regs.reg[9].loc.offset = (long)&sf->REG_NAME(r9) - new_cfa; + fs->regs.reg[10].how = REG_SAVED_OFFSET; + fs->regs.reg[10].loc.offset = (long)&sf->REG_NAME(r10) - new_cfa; + fs->regs.reg[11].how = REG_SAVED_OFFSET; + fs->regs.reg[11].loc.offset = (long)&sf->REG_NAME(r11) - new_cfa; + fs->regs.reg[12].how = REG_SAVED_OFFSET; + fs->regs.reg[12].loc.offset = (long)&sf->REG_NAME(r12) - new_cfa; + fs->regs.reg[13].how = REG_SAVED_OFFSET; + fs->regs.reg[13].loc.offset = (long)&sf->REG_NAME(r13) - new_cfa; + fs->regs.reg[14].how = REG_SAVED_OFFSET; + fs->regs.reg[14].loc.offset = (long)&sf->REG_NAME(r14) - new_cfa; + fs->regs.reg[15].how = REG_SAVED_OFFSET; + fs->regs.reg[15].loc.offset = (long)&sf->REG_NAME(r15) - new_cfa; + fs->regs.reg[16].how = REG_SAVED_OFFSET; + fs->regs.reg[16].loc.offset = (long)&sf->REG_NAME(rip) - new_cfa; + fs->retaddr_column = 16; + fs->signal_frame = 1; + return _URC_NO_REASON; +} + +#else /* ifdef __x86_64__ */ + +#define MD_FALLBACK_FRAME_STATE_FOR x86_fallback_frame_state + +static _Unwind_Reason_Code +x86_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + unsigned char *pc = context->ra; + unsigned char *sigtramp_start, *sigtramp_end; + struct sigframe *sf; + long new_cfa; + + x86_sigtramp_range(&sigtramp_start, &sigtramp_end); + + if (pc >= sigtramp_end || pc < sigtramp_start) + return _URC_END_OF_STACK; + + sf = (struct sigframe *) context->cfa; + new_cfa = sf->REG_NAME(esp); + fs->cfa_how = CFA_REG_OFFSET; + fs->cfa_reg = 4; + fs->cfa_offset = new_cfa - (long) context->cfa; + + /* The SVR4 register numbering macros aren't usable in libgcc. */ + fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.reg[0].loc.offset = (long)&sf->REG_NAME(eax) - new_cfa; + fs->regs.reg[3].how = REG_SAVED_OFFSET; + fs->regs.reg[3].loc.offset = (long)&sf->REG_NAME(ebx) - new_cfa; + fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.reg[1].loc.offset = (long)&sf->REG_NAME(ecx) - new_cfa; + fs->regs.reg[2].how = REG_SAVED_OFFSET; + fs->regs.reg[2].loc.offset = (long)&sf->REG_NAME(edx) - new_cfa; + fs->regs.reg[6].how = REG_SAVED_OFFSET; + fs->regs.reg[6].loc.offset = (long)&sf->REG_NAME(esi) - new_cfa; + fs->regs.reg[7].how = REG_SAVED_OFFSET; + fs->regs.reg[7].loc.offset = (long)&sf->REG_NAME(edi) - new_cfa; + fs->regs.reg[5].how = REG_SAVED_OFFSET; + fs->regs.reg[5].loc.offset = (long)&sf->REG_NAME(ebp) - new_cfa; + fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.reg[8].loc.offset = (long)&sf->REG_NAME(eip) - new_cfa; + fs->retaddr_column = 8; + fs->signal_frame = 1; + return _URC_NO_REASON; +} +#endif /* ifdef __x86_64__ */ Index: libexec/rtld-elf/Symbol.map =================================================================== --- libexec/rtld-elf/Symbol.map (版本 187994) +++ libexec/rtld-elf/Symbol.map (工作副本) @@ -17,6 +17,10 @@ __tls_get_addr; }; +FBSD_1.1 { + _rtld_stack_end; +}; + FBSDprivate_1.0 { _rtld_thread_init; _rtld_allocate_tls; Index: libexec/rtld-elf/rtld.c =================================================================== --- libexec/rtld-elf/rtld.c (版本 187994) +++ libexec/rtld-elf/rtld.c (工作副本) @@ -183,6 +183,8 @@ #define RTLD_IS_DYNAMIC() (&_DYNAMIC != NULL) #endif +void *_rtld_stack_end; + /* * These are the functions the dynamic linker exports to application * programs. They are the only symbols the dynamic linker is willing @@ -208,6 +210,7 @@ (func_ptr_type) &dl_iterate_phdr, (func_ptr_type) &_rtld_atfork_pre, (func_ptr_type) &_rtld_atfork_post, + (func_ptr_type) &_rtld_stack_end, NULL }; @@ -350,6 +353,8 @@ argv0 = argv[0] != NULL ? argv[0] : "(null)"; environ = env; + _rtld_stack_end = __builtin_frame_address(0); + trust = !issetugid(); ld_bind_now = getenv(LD_ "BIND_NOW"); Index: libexec/rtld-elf/i386/rtld_start.S =================================================================== --- libexec/rtld-elf/i386/rtld_start.S (版本 187994) +++ libexec/rtld-elf/i386/rtld_start.S (工作副本) @@ -25,6 +25,7 @@ * $FreeBSD$ */ +#include .text .align 4 .globl .rtld_start @@ -71,21 +72,36 @@ .globl _rtld_bind_start .type _rtld_bind_start,@function _rtld_bind_start: + CFI_STARTPROC + CFI_ADJUST_CFA_OFFSET 8 pushf # Save eflags + CFI_ADJUST_CFA_OFFSET 4 pushl %eax # Save %eax + CFI_ADJUST_CFA_OFFSET 4 pushl %edx # Save %edx + CFI_ADJUST_CFA_OFFSET 4 pushl %ecx # Save %ecx + CFI_ADJUST_CFA_OFFSET 4 pushl 20(%esp) # Copy reloff argument + CFI_ADJUST_CFA_OFFSET 4 pushl 20(%esp) # Copy obj argument + CFI_ADJUST_CFA_OFFSET 4 call _rtld_bind@PLT # Transfer control to the binder /* Now %eax contains the entry point of the function being called. */ addl $8,%esp # Discard binder arguments + CFI_ADJUST_CFA_OFFSET -8 movl %eax,20(%esp) # Store target over obj argument popl %ecx # Restore %ecx + CFI_ADJUST_CFA_OFFSET -4 popl %edx # Restore %edx + CFI_ADJUST_CFA_OFFSET -4 popl %eax # Restore %eax + CFI_ADJUST_CFA_OFFSET -4 popf # Restore eflags + CFI_ADJUST_CFA_OFFSET -4 leal 4(%esp),%esp # Discard reloff, do not change eflags + CFI_ADJUST_CFA_OFFSET -4 ret # "Return" to target address + CFI_ENDPROC Index: libexec/rtld-elf/amd64/rtld_start.S =================================================================== --- libexec/rtld-elf/amd64/rtld_start.S (版本 187994) +++ libexec/rtld-elf/amd64/rtld_start.S (工作副本) @@ -25,6 +25,8 @@ * $FreeBSD$ */ +#include + .text .align 4 .globl .rtld_start @@ -79,17 +81,39 @@ .globl _rtld_bind_start .type _rtld_bind_start,@function _rtld_bind_start: + CFI_STARTPROC + CFI_ADJUST_CFA_OFFSET 16 subq $8,%rsp + CFI_ADJUST_CFA_OFFSET 8 pushfq # Save rflags + CFI_ADJUST_CFA_OFFSET 8 pushq %rax # Save %rax + CFI_ADJUST_CFA_OFFSET 8 + CFI_REL_OFFSET rax, 0 pushq %rdx # Save %rdx + CFI_ADJUST_CFA_OFFSET 8 + CFI_REL_OFFSET rdx, 0 pushq %rcx # Save %rcx + CFI_ADJUST_CFA_OFFSET 8 + CFI_REL_OFFSET rcx, 0 pushq %rsi # Save %rsi + CFI_ADJUST_CFA_OFFSET 8 + CFI_REL_OFFSET rsi, 0 pushq %rdi # Save %rdi + CFI_ADJUST_CFA_OFFSET 8 + CFI_REL_OFFSET rdi, 0 pushq %r8 # Save %r8 + CFI_ADJUST_CFA_OFFSET 8 + CFI_REL_OFFSET r8, 0 pushq %r9 # Save %r9 + CFI_ADJUST_CFA_OFFSET 8 + CFI_REL_OFFSET r9, 0 pushq %r10 # Save %r10 + CFI_ADJUST_CFA_OFFSET 8 + CFI_REL_OFFSET r10, 0 pushq %r11 # Save %r11 + CFI_ADJUST_CFA_OFFSET 8 + CFI_REL_OFFSET r11, 0 movq 0x58(%rsp),%rdi # Fetch obj argument movq 0x60(%rsp),%rsi # Fetch reloff argument @@ -101,14 +125,35 @@ movq %rax,0x60(%rsp) # Store target over reloff argument popq %r11 # Restore %r11 + CFI_ADJUST_CFA_OFFSET -8 + CFI_RESTORE r11 popq %r10 # Restore %r10 + CFI_ADJUST_CFA_OFFSET -8 + CFI_RESTORE r10 popq %r9 # Restore %r9 + CFI_ADJUST_CFA_OFFSET -8 + CFI_RESTORE r9 popq %r8 # Restore %r8 + CFI_ADJUST_CFA_OFFSET -8 + CFI_RESTORE r8 popq %rdi # Restore %rdi + CFI_ADJUST_CFA_OFFSET -8 + CFI_RESTORE rdi popq %rsi # Restore %rsi + CFI_ADJUST_CFA_OFFSET -8 + CFI_RESTORE rsi popq %rcx # Restore %rcx + CFI_ADJUST_CFA_OFFSET -8 + CFI_RESTORE rcx popq %rdx # Restore %rdx + CFI_ADJUST_CFA_OFFSET -8 + CFI_RESTORE rdx popq %rax # Restore %rax + CFI_ADJUST_CFA_OFFSET -8 + CFI_RESTORE rax popfq # Restore rflags + CFI_ADJUST_CFA_OFFSET -8 leaq 16(%rsp),%rsp # Discard spare, obj, do not change rflags + CFI_ADJUST_CFA_OFFSET -16 ret # "Return" to target address + CFI_ENDPROC Index: lib/csu/amd64/crt1.c =================================================================== --- lib/csu/amd64/crt1.c (版本 187994) +++ lib/csu/amd64/crt1.c (工作副本) @@ -77,8 +77,10 @@ if (&_DYNAMIC != NULL) atexit(cleanup); - else + else { + _rtld_stack_end = __builtin_frame_address(0); _init_tls(); + } #ifdef GCRT atexit(_mcleanup); Index: lib/csu/i386-elf/crt1.c =================================================================== --- lib/csu/i386-elf/crt1.c (版本 187994) +++ lib/csu/i386-elf/crt1.c (工作副本) @@ -95,8 +95,10 @@ if (&_DYNAMIC != NULL) atexit(cleanup); - else + else { + _rtld_stack_end = __builtin_frame_address(0); _init_tls(); + } #ifdef GCRT atexit(_mcleanup); Index: lib/libc/i386/SYS.h =================================================================== --- lib/libc/i386/SYS.h (版本 187994) +++ lib/libc/i386/SYS.h (工作副本) @@ -35,6 +35,7 @@ #include #include +#include #define SYSCALL(x) 2: PIC_PROLOGUE; jmp PIC_PLT(HIDENAME(cerror)); \ ENTRY(__CONCAT(__sys_,x)); \ @@ -44,13 +45,24 @@ .set CNAME(__CONCAT(_,x)),CNAME(__CONCAT(__sys_,x)); \ mov __CONCAT($SYS_,x),%eax; KERNCALL; jb 2b -#define RSYSCALL(x) SYSCALL(x); ret; END(__CONCAT(__sys_,x)) +#define RSYSCALL(x) CFI_STARTPROC; \ + ENTRY(__CONCAT(__sys_,x)); \ + .weak CNAME(x); \ + .set CNAME(x),CNAME(__CONCAT(__sys_,x)); \ + .weak CNAME(__CONCAT(_,x)); \ + .set CNAME(__CONCAT(_,x)),CNAME(__CONCAT(__sys_,x)); \ + mov __CONCAT($SYS_,x),%eax; KERNCALL; jb 2f; ret; \ + 2: CFI_PIC_PROLOGUE; jmp PIC_PLT(HIDENAME(cerror)); \ + CFI_ENDPROC; \ + END(__CONCAT(__sys_,x)) -#define PSEUDO(x) 2: PIC_PROLOGUE; jmp PIC_PLT(HIDENAME(cerror)); \ +#define PSEUDO(x) CFI_STARTPROC; \ ENTRY(__CONCAT(__sys_,x)); \ .weak CNAME(__CONCAT(_,x)); \ .set CNAME(__CONCAT(_,x)),CNAME(__CONCAT(__sys_,x)); \ - mov __CONCAT($SYS_,x),%eax; KERNCALL; jb 2b; ret; \ + mov __CONCAT($SYS_,x),%eax; KERNCALL; jb 2f; ret; \ + 2: CFI_PIC_PROLOGUE; jmp PIC_PLT(HIDENAME(cerror)); \ + CFI_ENDPROC; \ END(__CONCAT(__sys_,x)) /* gas messes up offset -- although we don't currently need it, do for BCS */ Index: lib/libc/i386/sys/cerror.S =================================================================== --- lib/libc/i386/sys/cerror.S (版本 187994) +++ lib/libc/i386/sys/cerror.S (工作副本) @@ -48,18 +48,23 @@ .globl CNAME(__error) .type CNAME(__error),@function HIDENAME(cerror): + CFI_STARTPROC pushl %eax + CFI_ADJUST_CFA_OFFSET 4 #ifdef PIC /* The caller must execute the PIC prologue before jumping to cerror. */ call PIC_PLT(CNAME(__error)) popl %ecx - PIC_EPILOGUE + CFI_ADJUST_CFA_OFFSET -4 + CFI_PIC_EPILOGUE #else call CNAME(__error) popl %ecx + CFI_ADJUST_CFA_OFFSET -4 #endif movl %ecx,(%eax) movl $-1,%eax movl $-1,%edx ret + CFI_ENDPROC Index: lib/libc/amd64/sys/cerror.S =================================================================== --- lib/libc/amd64/sys/cerror.S (版本 187994) +++ lib/libc/amd64/sys/cerror.S (工作副本) @@ -48,11 +48,15 @@ .globl CNAME(__error) .type CNAME(__error),@function HIDENAME(cerror): + CFI_STARTPROC pushq %rax + CFI_ADJUST_CFA_OFFSET 8 + CFI_REL_OFFSET rax, 0 call PIC_PLT(CNAME(__error)) popq %rcx + CFI_ADJUST_CFA_OFFSET -8 movl %ecx,(%rax) movq $-1,%rax movq $-1,%rdx ret - + CFI_ENDPROC Index: lib/libthr/thread/thr_private.h =================================================================== --- lib/libthr/thread/thr_private.h (版本 187948) +++ lib/libthr/thread/thr_private.h (工作副本) @@ -60,6 +60,10 @@ #include "thr_umtx.h" #include "thread_db.h" +#ifdef PTHREAD_FORCED_UNWIND +#include +#endif + typedef TAILQ_HEAD(pthreadlist, pthread) pthreadlist; typedef TAILQ_HEAD(atfork_head, pthread_atfork) atfork_head; TAILQ_HEAD(mutex_queue, pthread_mutex); @@ -426,6 +430,11 @@ /* Cleanup handlers Link List */ struct pthread_cleanup *cleanup; +#ifdef PTHREAD_FORCED_UNWIND + struct _Unwind_Exception ex; + void *unwind_stackend; +#endif + /* * Magic value to help recognize a valid thread structure * from an invalid one: @@ -546,7 +555,8 @@ (curthr->report_events && \ (((curthr)->event_mask | _thread_event_mask ) & e) != 0) -extern int __isthreaded; +extern int __isthreaded; +extern void *_rtld_stack_end; /* * Global variables for the pthread kernel. @@ -613,7 +623,6 @@ void _libpthread_init(struct pthread *) __hidden; struct pthread *_thr_alloc(struct pthread *) __hidden; void _thread_exit(const char *, int, const char *) __hidden __dead2; -void _thr_exit_cleanup(void) __hidden; int _thr_ref_add(struct pthread *, struct pthread *, int) __hidden; void _thr_ref_delete(struct pthread *, struct pthread *) __hidden; void _thr_ref_delete_unlocked(struct pthread *, struct pthread *) __hidden; @@ -663,6 +672,7 @@ void _pthread_cleanup_push(void (*)(void *), void *); void _pthread_cleanup_pop(int); +void _pthread_exit_imp(void *status); /* #include */ #ifdef _SYS_FCNTL_H_ Index: lib/libthr/thread/thr_cancel.c =================================================================== --- lib/libthr/thread/thr_cancel.c (版本 187948) +++ lib/libthr/thread/thr_cancel.c (工作副本) @@ -43,7 +43,7 @@ { if (__predict_false(SHOULD_CANCEL(curthread) && !THR_IN_CRITICAL(curthread) && curthread->cancel_defer == 0)) - _pthread_exit(PTHREAD_CANCELED); + _pthread_exit_imp(PTHREAD_CANCELED); } void Index: lib/libthr/thread/thr_init.c =================================================================== --- lib/libthr/thread/thr_init.c (版本 187948) +++ lib/libthr/thread/thr_init.c (工作副本) @@ -397,6 +397,10 @@ thread->attr.guardsize_attr = _thr_guard_default; thread->attr.flags |= THR_STACK_USER; +#ifdef PTHREAD_FORCED_UNWIND + thread->unwind_stackend = _usrstack; +#endif + /* * Write a magic value to the thread structure * to help identify valid ones: Index: lib/libthr/thread/thr_create.c =================================================================== --- lib/libthr/thread/thr_create.c (版本 187948) +++ lib/libthr/thread/thr_create.c (工作副本) @@ -261,7 +261,7 @@ THR_UNLOCK(curthread); if (curthread->force_exit) - _pthread_exit(PTHREAD_CANCELED); + _pthread_exit_imp(PTHREAD_CANCELED); if (curthread->unblock_sigcancel) { sigset_t set1; @@ -284,8 +284,13 @@ __sys_sigprocmask(SIG_SETMASK, &set, NULL); } +#ifdef PTHREAD_FORCED_UNWIND + curthread->unwind_stackend = (char *)curthread->attr.stackaddr_attr + + curthread->attr.stacksize_attr; +#endif + /* Run the current thread's start routine with argument: */ - _pthread_exit(curthread->start_routine(curthread->arg)); + _pthread_exit_imp(curthread->start_routine(curthread->arg)); /* This point should never be reached. */ PANIC("Thread has resumed after exit"); Index: lib/libthr/thread/thr_exit.c =================================================================== --- lib/libthr/thread/thr_exit.c (版本 187948) +++ lib/libthr/thread/thr_exit.c (工作副本) @@ -31,6 +31,7 @@ #include "namespace.h" #include +#include #include #include #include @@ -39,9 +40,10 @@ #include "libc_private.h" #include "thr_private.h" -void _pthread_exit(void *status); +__weak_reference(_pthread_exit_imp, pthread_exit); +__weak_reference(_pthread_exit_imp, _pthread_exit); -__weak_reference(_pthread_exit, pthread_exit); +static void _thr_exit_thread(void); void _thread_exit(const char *fname, int lineno, const char *msg) @@ -55,19 +57,122 @@ abort(); } -/* - * Only called when a thread is cancelled. It may be more useful - * to call it from pthread_exit() if other ways of asynchronous or - * abnormal thread termination can be found. - */ +#ifdef PTHREAD_FORCED_UNWIND + +static void _thr_unwind(void); +static _Unwind_Reason_Code thr_unwind_stop(int version, _Unwind_Action actions, + _Unwind_Exception_Class exc_class, + struct _Unwind_Exception *exc_obj, + struct _Unwind_Context *context, void *stop_parameter); +static void _thr_exit_init(void); + +static _Unwind_Reason_Code (*libgcc_s_forcedunwind)(struct _Unwind_Exception *, + _Unwind_Stop_Fn, void *); +static void (*libgcc_s_resume)(struct _Unwind_Exception *exc); +static _Unwind_Word (*libgcc_s_getcfa)(struct _Unwind_Context *); + +static void +_thr_exit_init(void) +{ + void *forcedunwind, *resume, *getcfa; + void *handle; + + if (libgcc_s_getcfa != NULL) + return; + + handle = dlopen("libgcc_s.so.1", RTLD_LAZY); + if ((handle == NULL) || + (forcedunwind = dlsym(handle, "_Unwind_ForcedUnwind")) == NULL || + (resume = dlsym(handle, "_Unwind_Resume")) == NULL || + (getcfa = dlsym(handle, "_Unwind_GetCFA")) == NULL) { + PANIC("Thread exiting needs libgcc_s.so.1 to be installed."); + } + + libgcc_s_forcedunwind = forcedunwind; + libgcc_s_resume = resume; + libgcc_s_getcfa = getcfa; +} + void -_thr_exit_cleanup(void) +_Unwind_Resume(struct _Unwind_Exception *ex) { + if (libgcc_s_resume == NULL) + _thr_exit_init(); + libgcc_s_resume(ex); } +_Unwind_Reason_Code +_Unwind_ForcedUnwind(struct _Unwind_Exception *ex, _Unwind_Stop_Fn stop_func, + void *stop_arg) +{ + if (libgcc_s_forcedunwind == NULL) + _thr_exit_init(); + return (libgcc_s_forcedunwind(ex, stop_func, stop_arg)); +} + +_Unwind_Word +_Unwind_GetCFA(struct _Unwind_Context *context) +{ + if (libgcc_s_getcfa == NULL) + _thr_exit_init(); + return (libgcc_s_getcfa(context)); +} + +static void +thr_unwind_cleanup(_Unwind_Reason_Code code, struct _Unwind_Exception *e) +{ + if (code == _URC_FOREIGN_EXCEPTION_CAUGHT) + _Unwind_Resume(e); + else + PANIC("unhandled exception"); +} + +static _Unwind_Reason_Code +thr_unwind_stop(int version, _Unwind_Action actions, + _Unwind_Exception_Class exc_class, + struct _Unwind_Exception *exc_obj, + struct _Unwind_Context *context, void *stop_parameter) +{ + struct pthread *curthread = _get_curthread(); + struct pthread_cleanup *cur; + uintptr_t cfa; + int done = 0; + + cfa = _Unwind_GetCFA(context); + if (actions & _UA_END_OF_STACK) { + done = 1; + } else if (cfa >= (uintptr_t)curthread->unwind_stackend) { + done = 1; + } + + while ((cur = curthread->cleanup) != NULL && + (done || + ((uintptr_t)cur < (uintptr_t)curthread->unwind_stackend && + (uintptr_t)cur >= cfa))) { + _pthread_cleanup_pop(1); + } + + if (done) + _thr_exit_thread(); /* Never return! */ + + return (_URC_NO_REASON); +} + void -_pthread_exit(void *status) +_thr_unwind(void) { + struct pthread *curthread = _get_curthread(); + + curthread->ex.exception_class = 0; + curthread->ex.exception_cleanup = thr_unwind_cleanup; + _Unwind_ForcedUnwind(&curthread->ex, thr_unwind_stop, NULL); + PANIC("_Unwind_ForcedUnwind returned"); +} +#endif + +void +_pthread_exit_imp(void *status) +{ struct pthread *curthread = _get_curthread(); /* Check if this thread is already in the process of exiting: */ @@ -82,14 +187,31 @@ /* Flag this thread as exiting. */ curthread->cancelling = 1; - _thr_exit_cleanup(); + /* + * POSIX states that cancellation/termination of a thread should + * not release any visible resources (such as mutexes) and that + * it is the applications responsibility. Resources that are + * internal to the threads library, including file and fd locks, + * are not visible to the application and need to be released. + */ /* Save the return value: */ curthread->ret = status; - while (curthread->cleanup != NULL) { + +#ifdef PTHREAD_FORCED_UNWIND + _thr_unwind(); +#else + while (curthread->cleanup != NULL) _pthread_cleanup_pop(1); - } + _thr_exit_thread(); +#endif +} +static void +_thr_exit_thread(void) +{ + struct pthread *curthread = _get_curthread(); + /* Check if there is thread specific data: */ if (curthread->specific != NULL) { /* Run the thread-specific data destructors: */ Index: lib/libthr/Makefile =================================================================== --- lib/libthr/Makefile (版本 187948) +++ lib/libthr/Makefile (工作副本) @@ -28,7 +28,13 @@ CFLAGS+=-I${.CURDIR}/../../libexec/rtld-elf/${MACHINE_ARCH} CFLAGS+=-I${.CURDIR}/../libthread_db CFLAGS+=-Winline +THREAD_UNWIND_STACK=yes +.ifdef THREAD_UNWIND_STACK +CFLAGS+=-I${.CURDIR}/../../contrib/gcc -fexceptions -fasynchronous-unwind-tables +CFLAGS+=-DPTHREAD_FORCED_UNWIND +.endif + VERSION_DEF=${.CURDIR}/../libc/Versions.def SYMBOL_MAPS=${.CURDIR}/pthread.map --- /dev/null 2009-02-03 14:45:38.000000000 +0800 +++ sys/i386/include/dwarf2.h 2009-02-02 12:05:25.000000000 +0800 @@ -0,0 +1,51 @@ +#ifndef _MACHINE_DWARF2_H +#define _MACHINE_DWARF2_H + +#ifndef __ASSEMBLER__ +#warning "machine/dwarf2.h should be only used in pure assembly files" +#endif + +/* Macros for dwarf2 CFI unwind table entries. */ + +#ifndef NO_ASM_CFI + +#define CFI_STARTPROC .cfi_startproc +#define CFI_ENDPROC .cfi_endproc +#define CFI_DEF_CFA .cfi_def_cfa +#define CFI_DEF_CFA_REGISTER .cfi_def_cfa_register +#define CFI_DEF_CFA_OFFSET .cfi_def_cfa_offset +#define CFI_ADJUST_CFA_OFFSET .cfi_adjust_cfa_offset +#define CFI_OFFSET .cfi_offset +#define CFI_REL_OFFSET .cfi_rel_offset +#define CFI_REGISTER .cfi_register +#define CFI_RESTORE .cfi_restore +#define CFI_REMEMBER_STATE .cfi_remember_state +#define CFI_RESTORE_STATE .cfi_restore_state +#define CFI_RETURN_COLUMN .cfi_return_column +#define CFI_SAME_VALUE .cfi_same_value +#define CFI_UNDEFINED .cfi_undefined + +#else + +.macro cfi_null a1=0, a2=0, a3=0, a4=0 +.endm + +#define CFI_STARTPROC cfi_null +#define CFI_ENDPROC cfi_null +#define CFI_DEF_CFA cfi_null +#define CFI_DEF_CFA_REGISTER cfi_null +#define CFI_DEF_CFA_OFFSET cfi_null +#define CFI_ADJUST_CFA_OFFSET cfi_null +#define CFI_OFFSET cfi_null +#define CFI_REL_OFFSET cfi_null +#define CFI_REGISTER cfi_null +#define CFI_RESTORE cfi_null +#define CFI_REMEMBER_STATE cfi_null +#define CFI_RESTORE_STATE cfi_null +#define CFI_RETURN_COLUMN cfi_null +#define CFI_SAME_VALUE cfi_null +#define CFI_UNDEFINED cfi_null + +#endif + +#endif /* _MACHINE_DWARF2_H */ Index: sys/i386/include/asm.h =================================================================== --- sys/i386/include/asm.h (版本 187994) +++ sys/i386/include/asm.h (工作副本) @@ -37,6 +37,7 @@ #define _MACHINE_ASM_H_ #include +#include #ifdef PIC #define PIC_PROLOGUE \ @@ -45,13 +46,32 @@ 1: \ popl %ebx; \ addl $_GLOBAL_OFFSET_TABLE_+[.-1b],%ebx + +#define CFI_PIC_PROLOGUE \ + pushl %ebx; \ + CFI_ADJUST_CFA_OFFSET 4; \ + CFI_REL_OFFSET ebx, 0; \ + call 1f; \ +1: \ + CFI_ADJUST_CFA_OFFSET 4; \ + popl %ebx; \ + CFI_ADJUST_CFA_OFFSET -4; \ + addl $_GLOBAL_OFFSET_TABLE_+[.-1b],%ebx + +#define CFI_PIC_EPILOGUE \ + popl %ebx; \ + CFI_ADJUST_CFA_OFFSET -4; \ + CFI_RESTORE ebx #define PIC_EPILOGUE \ popl %ebx + #define PIC_PLT(x) x@PLT #define PIC_GOT(x) x@GOT(%ebx) #else #define PIC_PROLOGUE +#define CFI_PIC_PROLOGUE #define PIC_EPILOGUE +#define CFI_PIC_EPILOGUE #define PIC_PLT(x) x #define PIC_GOT(x) x #endif @@ -84,9 +104,20 @@ call PIC_PLT(HIDENAME(mcount)); \ popl %ebp; \ 9: +#define CFI_ENTRY(x) _ENTRY(x); \ + pushl %ebp; \ + CFI_ADJUST_CFA_OFFSET 4; \ + CFI_REL_OFFSET ebp, 0; \ + movl %esp,%ebp; \ + call PIC_PLT(HIDENAME(mcount)); \ + popl %ebp; \ + CFI_ADJUST_CFA_OFFSET -4; \ + CFI_RESTORE ebp; \ + 9: #else #define ALTENTRY(x) _ENTRY(x) #define ENTRY(x) _ENTRY(x) +#define CFI_ENTRY(x) _ENTRY(x) #endif #define RCSID(x) .text; .asciz x --- /dev/null 2009-02-03 14:45:38.000000000 +0800 +++ sys/amd64/include/dwarf2.h 2009-02-02 12:05:20.000000000 +0800 @@ -0,0 +1,51 @@ +#ifndef _MACHINE_DWARF2_H +#define _MACHINE_DWARF2_H + +#ifndef __ASSEMBLER__ +#warning "machine/dwarf2.h should be only used in pure assembly files" +#endif + +/* Macros for dwarf2 CFI unwind table entries. */ + +#ifndef NO_ASM_CFI + +#define CFI_STARTPROC .cfi_startproc +#define CFI_ENDPROC .cfi_endproc +#define CFI_DEF_CFA .cfi_def_cfa +#define CFI_DEF_CFA_REGISTER .cfi_def_cfa_register +#define CFI_DEF_CFA_OFFSET .cfi_def_cfa_offset +#define CFI_ADJUST_CFA_OFFSET .cfi_adjust_cfa_offset +#define CFI_OFFSET .cfi_offset +#define CFI_REL_OFFSET .cfi_rel_offset +#define CFI_REGISTER .cfi_register +#define CFI_RESTORE .cfi_restore +#define CFI_REMEMBER_STATE .cfi_remember_state +#define CFI_RESTORE_STATE .cfi_restore_state +#define CFI_RETURN_COLUMN .cfi_return_column +#define CFI_SAME_VALUE .cfi_same_value +#define CFI_UNDEFINED .cfi_undefined + +#else + +.macro cfi_null a1=0, a2=0, a3=0, a4=0 +.endm + +#define CFI_STARTPROC cfi_null +#define CFI_ENDPROC cfi_null +#define CFI_DEF_CFA cfi_null +#define CFI_DEF_CFA_REGISTER cfi_null +#define CFI_DEF_CFA_OFFSET cfi_null +#define CFI_ADJUST_CFA_OFFSET cfi_null +#define CFI_OFFSET cfi_null +#define CFI_REL_OFFSET cfi_null +#define CFI_REGISTER cfi_null +#define CFI_RESTORE cfi_null +#define CFI_REMEMBER_STATE cfi_null +#define CFI_RESTORE_STATE cfi_null +#define CFI_RETURN_COLUMN cfi_null +#define CFI_SAME_VALUE cfi_null +#define CFI_UNDEFINED cfi_null + +#endif + +#endif /* _MACHINE_DWARF2_H */ Index: sys/amd64/include/asm.h =================================================================== --- sys/amd64/include/asm.h (版本 187994) +++ sys/amd64/include/asm.h (工作副本) @@ -72,9 +72,20 @@ call PIC_PLT(HIDENAME(mcount)); \ popq %rbp; \ 9: +#define CFI_ENTRY(x) _ENTRY(x); \ + pushq %rbp;\ + CFI_ADJUST_CFA_OFFSET 8; \ + CFI_REL_OFFSET rbp, 0; \ + movq %rsp,%rbp; \ + call PIC_PLT(HIDENAME(mcount)); \ + popq %rbp; \ + CFI_ADJUST_CFA_OFFSET -8; \ + CFI_RESTORE rbp; \ + 9: #else #define ALTENTRY(x) _ENTRY(x) #define ENTRY(x) _ENTRY(x) +#define CFI_ENTRY(x) _ENTRY(x) #endif #define END(x) .size x, . - x