(defun memory-fault-error ()
(error 'memory-fault-error
:address current-memory-fault-address))
+
+;;; This is SIGTRAP / EXCEPTION_BREAKPOINT that runtime could not deal
+;;; with. Prior to Windows we just had a Lisp side handler for
+;;; SIGTRAP, but now we need to deal this portably.
+(defun unhandled-trap-error (context-sap)
+ (declare (type system-area-pointer context-sap))
+ (infinite-error-protect
+ (let ((context (sap-alien context-sap (* os-context-t))))
+ (error "Unhandled breakpoint/trap at #x~X."
+ (sap-int (sb!vm:context-pc context))))))
(define-signal-handler sigint-handler "interrupted" sigint-%break)
(define-signal-handler sigill-handler "illegal instruction")
-(define-signal-handler sigtrap-handler "breakpoint/trap")
#!-linux
(define-signal-handler sigemt-handler "SIGEMT")
(define-signal-handler sigbus-handler "bus error")
(enable-interrupt sigint #'sigint-handler)
(enable-interrupt sigterm #'sigterm-handler)
(enable-interrupt sigill #'sigill-handler)
- (enable-interrupt sigtrap #'sigtrap-handler)
(enable-interrupt sigiot #'sigiot-handler)
#!-linux
(enable-interrupt sigemt #'sigemt-handler)
sb!kernel::undefined-alien-variable-error
sb!kernel::undefined-alien-function-error
sb!kernel::memory-fault-error
+ sb!kernel::unhandled-trap-error
sb!di::handle-breakpoint
sb!di::handle-single-step-trap
fdefinition-object
} else
/* a "system service" */
code=*((u32 *)(*os_context_pc_addr(context)));
- if (!maybe_handle_trap(context, code))
- interrupt_handle_now(signal, siginfo, context);
+ handle_trap(context, code);
}
unsigned long
interrupt_handle_now(signal, siginfo, context);
else {
int im5 = bad_inst & 0x1f;
- if (!maybe_handle_trap(context, trap))
- interrupt_handle_now(signal, sigingo, context);
+ handle_trap(context, trap);
}
}
void
interrupt_handle_pending(os_context_t *context)
{
- struct thread *thread;
- struct interrupt_data *data;
+#ifdef LISP_FEATURE_WIN32
+ /* Actually this part looks almost good to go for
+ * Windows too, but currently we never save anything
+ * on Windows, so ending up here would be pretty bad. */
+ lose("Pending interrupts unimplemented on Windows.");
+#else
+ struct thread *thread = arch_os_get_current_thread();
+ struct interrupt_data *data = thread->interrupt_data;
FSHOW_SIGNAL((stderr, "/entering interrupt_handle_pending\n"));
check_blockables_blocked_or_lose();
- thread=arch_os_get_current_thread();
- data=thread->interrupt_data;
/* If pseudo_atomic_interrupted is set then the interrupt is going
* to be handled now, ergo it's safe to clear it. */
* PSEUDO_ATOMIC_INTERRUPTED only if interrupts are enabled.*/
SetSymbolValue(INTERRUPT_PENDING, NIL,thread);
-#ifndef LISP_FEATURE_WIN32
/* restore the saved signal mask from the original signal (the
* one that interrupted us during the critical section) into the
* os_context for the signal we're currently in the handler for.
sigcopyset(os_context_sigmask_addr(context), &data->pending_mask);
sigemptyset(&data->pending_mask);
-#endif
/* This will break on sparc linux: the deferred handler really wants
* to be called with a void_context */
run_deferred_handler(data,(void *)context);
}
}
+#endif
}
\f
/*
}
#endif
+void
+unhandled_trap_error(os_context_t *context)
+{
+ lispobj context_sap;
+ fake_foreign_function_call(context);
+ context_sap = alloc_sap(context);
+#ifndef LISP_FEATURE_WIN32
+ thread_sigmask(SIG_SETMASK, os_context_sigmask_addr(context), 0);
+#endif
+ funcall1(SymbolFunction(UNHANDLED_TRAP_ERROR), context_sap);
+ lose("UNHANDLED-TRAP-ERROR fell through");
+}
+
/* Common logic far trapping instructions. How we actually handle each
* case is highly architecture dependant, but the overall shape is
* this. */
-boolean
-maybe_handle_trap(os_context_t *context, int trap)
+void
+handle_trap(os_context_t *context, int trap)
{
switch(trap) {
case trap_PendingInterrupt:
fake_foreign_function_call(context);
lose("%%PRIMITIVE HALT called; the party is over.\n");
default:
- FSHOW((stderr,"/[C--trap default %d %d %x]\n",
- signal, trap, context));
- /* Not our trap! */
- return 0;
+ unhandled_trap_error(context);
}
- return 1;
}
* "cleanly" with union types is in fact a mess. */
#define ARE_SAME_HANDLER(x, y) ((void*)(x) == (void*)(y))
-extern boolean maybe_handle_trap(os_context_t *context, int trap);
+extern void handle_trap(os_context_t *context, int trap);
#ifndef LISP_FEATURE_WIN32
extern void lisp_memory_fault_error(os_context_t *context, os_vm_address_t addr);
os_context_t *context = arch_os_get_context(&void_context);
unsigned int code = (os_context_insn(context) >> 6) & 0xfffff;
/* FIXME: WTF is this magic number? Needs to become a #define
- * and go into maybe_handle_trap. */
+ * and go into handle_trap. */
if (code==0x10) {
arch_clear_pseudo_atomic_interrupted(context);
arch_skip_instruction(context);
interrupt_handle_pending(context);
- } else if (!maybe_handle_trap(context,code))
- interrupt_handle_now(signal, info, void_context);
+ } else
+ handle_trap(context,code);
}
#define FIXNUM_VALUE(lispobj) (((int)lispobj) >> N_FIXNUM_TAG_BITS)
if ((code >> 16) == ((3 << 10) | (6 << 5))) {
/* twllei reg_ZERO,N will always trap if reg_ZERO = 0 */
int trap = code & 0x1f;
-
- if (!maybe_handle_trap(context,trap))
- interrupt_handle_now(signal, siginfo, context);
+ handle_trap(context,trap);
#ifdef LISP_FEATURE_DARWIN
DARWIN_FIX_CONTEXT(context);
inst = *pc;
trap = inst & 0x3fffff;
- if (!maybe_handle_trap(context,trap))
- interrupt_handle_now(signal, siginfo, context);
+ handle_trap(context,trap);
}
else if ((siginfo->si_code) == ILL_ILLTRP
#ifdef LISP_FEATURE_LINUX
return 0;
}
-/*
- * any OS-dependent special low-level handling for signals
- */
-
/* A tiny bit of interrupt.c state we want our paws on. */
extern boolean internal_errors_enabled;
}
if (exception_record->ExceptionCode == EXCEPTION_BREAKPOINT) {
- /* Pick off sigtrap case first. */
-
- extern void sigtrap_handler(int signal, siginfo_t *info, void *context);
- /*
- * Unlike some other operating systems, Win32 leaves EIP
- * pointing to the breakpoint instruction.
- */
+ /* This is just for info in case the monitor wants to print an
+ * approximation. */
+ current_control_stack_pointer =
+ (lispobj *)*os_context_sp_addr(context);
+ /* Unlike some other operating systems, Win32 leaves EIP
+ * pointing to the breakpoint instruction. */
context->Eip++;
-
- sigtrap_handler(0, NULL, context);
-
+ /* Now EIP points just after the INT3 byte and aims at the
+ * 'kind' value (eg trap_Cerror). */
+ trap = *(unsigned char *)(*os_context_pc_addr(context));
+ handle_trap(context, trap);
+ /* Done, we're good to go! */
return ExceptionContinueExecution;
}
else if (exception_record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION &&
fflush(stderr);
fake_foreign_function_call(context);
- lose("fake_foreign_function_call fell through");
+ lose("Exception too early in cold init, cannot continue.");
/* FIXME: WTF? How are we supposed to end up here? */
return ExceptionContinueSearch;
* arguments to follow. */
trap = *(unsigned char *)(*os_context_pc_addr(context));
- if (!maybe_handle_trap(context, trap))
- interrupt_handle_now(signal, info, context);
+ handle_trap(context, trap);
}
void
#endif
fake_foreign_function_call(context);
- lose("fake_foreign_function_call fell through");
+ lose("Unhandled SIGILL.");
}
#ifdef X86_64_SIGFPE_FIXUP
handle_single_step_trap(context, trap, 0);
}
+#ifndef LISP_FEATURE_WIN32
void
sigtrap_handler(int signal, siginfo_t *info, void *void_context)
{
os_context_t *context = (os_context_t*)void_context;
unsigned int trap;
-#ifndef LISP_FEATURE_WIN32
- /* On Windows this is done in the SE handler. */
if (single_stepping && (signal==SIGTRAP)) {
restore_breakpoint_from_single_step(context);
return;
}
-#endif
/* This is just for info in case the monitor wants to print an
* approximation. */
os_restore_fp_control(context);
#endif
-
#ifdef LISP_FEATURE_SUNOS
/* For some reason the breakpoints that :ENCAPSULATE NIL tracing sets up
* cause a trace trap (i.e. processor single-stepping trap) on the following
* number of bytes will follow, the first is the length of the byte
* arguments to follow. */
trap = *(unsigned char *)(*os_context_pc_addr(context));
- if (!maybe_handle_trap(context, trap))
- interrupt_handle_now(signal, info, context);
+ handle_trap(context, trap);
}
void
return sigtrap_handler(signal, siginfo, void_context);
}
#endif
-
fake_foreign_function_call(context);
- lose("fake_foreign_call fell through");
+ lose("Unhandled SIGILL");
}
+#endif /* not LISP_FEATURE_WIN32 */
void
arch_install_interrupt_handlers()
undoably_install_low_level_interrupt_handler(SIGILL , sigill_handler);
undoably_install_low_level_interrupt_handler(SIGTRAP, sigtrap_handler);
#endif
-
SHOW("returning from arch_install_interrupt_handlers()");
}
\f
;;; checkins which aren't released. (And occasionally for internal
;;; versions, especially for internal versions off the main CVS
;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"1.0.4.17"
+"1.0.4.18"