From 5de74c72e5a9522c7fdd3dbb31a39641e9de8877 Mon Sep 17 00:00:00 2001 From: Cyrus Harmon Date: Wed, 15 Mar 2006 03:01:46 +0000 Subject: [PATCH] 0.9.10.30: Fix Darwin instability problems. Darwin isn't reliably firing SIGTRAP handlers, so use UD2 to generate a SIGILL instead of INT3 to generate a SIGTRAP and we check for this in the SIGILL handler and DTRT if we see this by calling the sigtrap_handler ... Define TRAP that uses UD2 (0x0b0f or 0F 0B) instead on Darwin and INT3 elsewhere in x86-assem.S ... Removed the bogus sigaltstack (was Darwin only, now gone) in bsd-os.c that I added in the course of trying to fix this problem ... #+darwin use UD2 instead of INT3 in compiler/x86 and add support for disassembling this as break --- src/compiler/x86/insts.lisp | 23 +++++++++++++++++++---- src/compiler/x86/macros.lisp | 10 +++++++++- src/runtime/bsd-os.c | 20 -------------------- src/runtime/x86-arch.c | 8 ++++++++ src/runtime/x86-assem.S | 20 +++++++++++++++----- 5 files changed, 51 insertions(+), 30 deletions(-) diff --git a/src/compiler/x86/insts.lisp b/src/compiler/x86/insts.lisp index 9eed6f8..f58b42a 100644 --- a/src/compiler/x86/insts.lisp +++ b/src/compiler/x86/insts.lisp @@ -628,6 +628,14 @@ :default-printer '(:name :tab code)) (op :field (byte 8 0)) (code :field (byte 8 8))) + +;;; Two byte instruction with an immediate byte argument. +;;; +(sb!disassem:define-instruction-format (word-imm 24 + :default-printer '(:name :tab code)) + (op :field (byte 16 0)) + (code :field (byte 8 16))) + ;;;; primitive emitters @@ -1951,10 +1959,17 @@ (define-instruction break (segment code) (:declare (type (unsigned-byte 8) code)) - (:printer byte-imm ((op #b11001100)) '(:name :tab code) - :control #'break-control) - (:emitter - (emit-byte segment #b11001100) + #-darwin (:printer byte-imm ((op #b11001100)) '(:name :tab code) + :control #'break-control) + #+darwin (:printer word-imm ((op #b0000101100001111)) '(:name :tab code) + :control #'break-control) + (:emitter + #-darwin (emit-byte segment #b11001100) + ;; On darwin, trap handling via SIGTRAP is unreliable, therefore we + ;; throw a sigill with 0x0b0f instead and check for this in the + ;; SIGILL handler and pass it on to the sigtrap handler if + ;; appropriate + #+darwin (emit-word segment #b0000101100001111) (emit-byte segment code))) (define-instruction int (segment number) diff --git a/src/compiler/x86/macros.lisp b/src/compiler/x86/macros.lisp index 73254c0..8a1dc87 100644 --- a/src/compiler/x86/macros.lisp +++ b/src/compiler/x86/macros.lisp @@ -276,7 +276,15 @@ (eval-when (#-sb-xc :compile-toplevel :load-toplevel :execute) (defun emit-error-break (vop kind code values) (let ((vector (gensym))) - `((inst int 3) ; i386 breakpoint instruction + `((progn + #-darwin (inst int 3) ; i386 breakpoint instruction + ;; CLH 20060314 + ;; On Darwin, we need to use #x0b0f instead of int3 in order + ;; to generate a SIGILL instead of a SIGTRAP as darwin/x86 + ;; doesn't seem to be reliably firing SIGTRAP + ;; handlers. Hopefully this will be fixed by Apple at a + ;; later date. + #+darwin (inst word #x0b0f)) ;; The return PC points here; note the location for the debugger. (let ((vop ,vop)) (when vop diff --git a/src/runtime/bsd-os.c b/src/runtime/bsd-os.c index 6372c42..f9cf70c 100644 --- a/src/runtime/bsd-os.c +++ b/src/runtime/bsd-os.c @@ -58,10 +58,6 @@ static void netbsd_init(); static void freebsd_init(); #endif /* __FreeBSD__ */ -#if defined(LISP_FEATURE_DARWIN) && defined(LISP_FEATURE_X86) -static void x86_darwin_init(); -#endif - void os_init(char *argv[], char *envp[]) { @@ -73,9 +69,6 @@ os_init(char *argv[], char *envp[]) #ifdef __FreeBSD__ freebsd_init(); #endif /* __FreeBSD__ */ -#if defined(LISP_FEATURE_DARWIN) && defined(LISP_FEATURE_X86) - x86_darwin_init(); -#endif } int *os_context_pc_addr(os_context_t *context) @@ -353,19 +346,6 @@ int arch_os_thread_cleanup(struct thread *thread) { } #endif -#if defined(LISP_FEATURE_DARWIN) && defined(LISP_FEATURE_X86) -static void x86_darwin_init() -{ - struct sigaltstack sigstack; - sigstack.ss_sp = os_allocate(32*SIGSTKSZ); - if (sigstack.ss_sp) { - sigstack.ss_flags=0; - sigstack.ss_size = 32*SIGSTKSZ; - sigaltstack(&sigstack,0); - } -} -#endif - #ifdef LISP_FEATURE_DARWIN /* defined in ppc-darwin-os.c instead */ #elif defined(LISP_FEATURE_FREEBSD) diff --git a/src/runtime/x86-arch.c b/src/runtime/x86-arch.c index 5b98eb3..9d76b93 100644 --- a/src/runtime/x86-arch.c +++ b/src/runtime/x86-arch.c @@ -304,6 +304,14 @@ sigtrap_handler(int signal, siginfo_t *info, void *void_context) static void sigill_handler(int signal, siginfo_t *siginfo, void *void_context) { os_context_t *context = (os_context_t*)void_context; + +#if defined(LISP_FEATURE_DARWIN) + if (*((unsigned short *)*os_context_pc_addr(context)) == 0x0b0f) { + *os_context_pc_addr(context) += 2; + return sigtrap_handler(signal, siginfo, void_context); + } +#endif + fake_foreign_function_call(context); monitor_or_something(); } diff --git a/src/runtime/x86-assem.S b/src/runtime/x86-assem.S index 33820b4..0deae4f 100644 --- a/src/runtime/x86-assem.S +++ b/src/runtime/x86-assem.S @@ -82,10 +82,20 @@ #define SIZE(name) #endif +/* + * x86/darwin (as of MacOS X 10.4.5) doesn't reliably file signal + * handlers (SIGTRAP or Mach exception handlers) for 0xCC, wo we have + * to use ud2 instead. ud2 is an undefined opcode, #x0b0f, or + * 0F 0B in low-endian notation, that causes SIGILL to fire. We check + * for this instruction in the SIGILL handler and if we see it, we + * advance the EIP by two bytes to skip over ud2 instruction and + * call sigtrap_handler. */ #if defined(LISP_FEATURE_DARWIN) #define END() +#define TRAP ud2 #else #define END() .end +#define TRAP int3 #endif .text @@ -336,7 +346,7 @@ GNAME(fpu_restore): TYPE(GNAME(undefined_tramp)) .byte 0, 0, 0, SIMPLE_FUN_HEADER_WIDETAG GNAME(undefined_tramp): - int3 + TRAP .byte trap_Error .byte 2 .byte UNDEFINED_FUN_ERROR @@ -385,7 +395,7 @@ multiple_value_return: .globl GNAME(fun_end_breakpoint_trap) GNAME(fun_end_breakpoint_trap): - int3 + TRAP .byte trap_FunEndBreakpoint hlt # We should never return here. @@ -397,7 +407,7 @@ GNAME(fun_end_breakpoint_end): TYPE(GNAME(do_pending_interrupt)) .align align_4byte,0x90 GNAME(do_pending_interrupt): - int3 + TRAP .byte trap_PendingInterrupt ret SIZE(GNAME(do_pending_interrupt)) @@ -861,7 +871,7 @@ GNAME(sigtrap_trampoline): call GNAME(sigtrap_wrapper) pop %eax pop %eax - int3 + TRAP .byte trap_ContextRestore hlt # We should never return here. @@ -877,7 +887,7 @@ GNAME(exception_trampoline): call GNAME(handle_win32_exception_wrapper) pop %eax pop %eax - int3 + TRAP .byte trap_ContextRestore hlt # We should never return here. #endif -- 1.7.10.4