#include "os.h"
#include "arch.h"
#include "lispregs.h"
-#include "signal.h"
#include "alloc.h"
#include "interrupt.h"
#include "interr.h"
#include "genesis/symbol.h"
#define BREAKPOINT_INST 0xcc /* INT3 */
+#define UD2_INST 0x0b0f /* UD2 */
-unsigned long fast_random_state = 1;
+#ifndef LISP_FEATURE_UD2_BREAKPOINTS
+#define BREAKPOINT_WIDTH 1
+#else
+#define BREAKPOINT_WIDTH 2
+#endif
void arch_init(void)
{}
#elif defined __NetBSD__
return &(context->uc_mcontext.__gregs[_REG_EFL]);
#elif defined LISP_FEATURE_WIN32
- return (int *)&context->EFlags;
+ return (int *)&context->win32_context->EFlags;
#else
#error unsupported OS
#endif
case trap_FunEndBreakpoint: /* not tested */
break;
+#ifdef LISP_FEATURE_SB_SAFEPOINT
+ case trap_GlobalSafepoint:
+ case trap_CspSafepoint:
+#endif
case trap_PendingInterrupt:
case trap_Halt:
case trap_SingleStepAround:
{
unsigned int result = *(unsigned int*)pc;
+#ifndef LISP_FEATURE_UD2_BREAKPOINTS
*(char*)pc = BREAKPOINT_INST; /* x86 INT3 */
*((char*)pc+1) = trap_Breakpoint; /* Lisp trap code */
+#else
+ *(char*)pc = UD2_INST & 0xff;
+ *((char*)pc+1) = UD2_INST >> 8;
+ *((char*)pc+2) = trap_Breakpoint;
+#endif
return result;
}
{
*((char *)pc) = orig_inst & 0xff;
*((char *)pc + 1) = (orig_inst & 0xff00) >> 8;
+#if BREAKPOINT_WIDTH > 1
+ *((char *)pc + 2) = (orig_inst & 0xff0000) >> 16;
+#endif
}
\f
/* When single stepping, single_stepping holds the original instruction
unsigned int *pc = (unsigned int*)(*os_context_pc_addr(context));
/* Put the original instruction back. */
- *((char *)pc) = orig_inst & 0xff;
- *((char *)pc + 1) = (orig_inst & 0xff00) >> 8;
+ arch_remove_breakpoint(pc, orig_inst);
#ifdef CANNOT_GET_TO_SINGLE_STEP_FLAG
/* Install helper instructions for the single step:
*context_eflags_addr(context) &= ~0x100;
#endif
/* Re-install the breakpoint if possible. */
- if (*os_context_pc_addr(context) == (int)single_stepping + 1) {
+ if (((char *)*os_context_pc_addr(context) >
+ (char *)single_stepping) &&
+ ((char *)*os_context_pc_addr(context) <=
+ (char *)single_stepping + BREAKPOINT_WIDTH)) {
fprintf(stderr, "warning: couldn't reinstall breakpoint\n");
} else {
- *((char *)single_stepping) = BREAKPOINT_INST; /* x86 INT3 */
- *((char *)single_stepping+1) = trap_Breakpoint;
+ arch_install_breakpoint(single_stepping);
}
single_stepping = NULL;
void
arch_handle_breakpoint(os_context_t *context)
{
- --*os_context_pc_addr(context);
+ *os_context_pc_addr(context) -= BREAKPOINT_WIDTH;
handle_breakpoint(context);
}
void
arch_handle_fun_end_breakpoint(os_context_t *context)
{
- --*os_context_pc_addr(context);
+ *os_context_pc_addr(context) -= BREAKPOINT_WIDTH;
*os_context_pc_addr(context) =
(int)handle_fun_end_breakpoint(context);
}
{
unsigned int trap;
- if (single_stepping && (signal==SIGTRAP)) {
+ if (single_stepping) {
restore_breakpoint_from_single_step(context);
return;
}
/* This is just for info in case the monitor wants to print an
* approximation. */
- current_control_stack_pointer =
+ access_control_stack_pointer(arch_os_get_current_thread()) =
(lispobj *)*os_context_sp_addr(context);
#ifdef LISP_FEATURE_SUNOS
/* Triggering SIGTRAP using int3 is unreliable on OS X/x86, so
* we need to use illegal instructions for traps.
*/
-#if defined(LISP_FEATURE_DARWIN) && !defined(LISP_FEATURE_MACH_EXCEPTION_HANDLER)
- if (*((unsigned short *)*os_context_pc_addr(context)) == 0x0b0f) {
+#if defined(LISP_FEATURE_UD2_BREAKPOINTS) && !defined(LISP_FEATURE_MACH_EXCEPTION_HANDLER)
+ if (*((unsigned short *)*os_context_pc_addr(context)) == UD2_INST) {
*os_context_pc_addr(context) += 2;
return sigtrap_handler(signal, siginfo, context);
}