* bug fix: bogus style warnings from certain (SETF SLOT-VALUE) and
WITH-SLOTS usages during compilation.
* bug fix: SB-C::CLASS-INFO now prints correctly (lp#514762)
+ * enhancement: Can now build with ud2 instead of int3 as trap instruction on
+ all x86oid platforms (except win32) with :UD2-BREAKPOINTS target feature.
+ * bug fix: Breakpoints now work when using ud2 instead of int3 as trap
+ instruction (tested on x86oid linux with ud2-breakpoints).
changes in sbcl-1.0.36 relative to sbcl-1.0.35:
* new feature: SB-EXT:TYPEXPAND-1, SB-EXT:TYPEXPAND, and
;; local storage.
; :restore-tls-segment-register-from-tls
+ ;; On some x86oid operating systems (darwin) SIGTRAP is not reliably
+ ;; delivered for the INT3 instruction, so we use the UD2 instruction
+ ;; which generates SIGILL instead.
+ ; :ud2-breakpoints
+
;; Support for detection of unportable code (when applied to the
;; COMMON-LISP package, or SBCL-internal pacakges) or bad-neighbourly
;; code (when applied to user-level packages), relating to material
printf ' :bsd' >> $ltf
printf ' :darwin' >> $ltf
if [ $sbcl_arch = "x86" ]; then
- printf ' :mach-exception-handler :sb-lutex :restore-fs-segment-register-from-tls' >> $ltf
+ printf ' :mach-exception-handler :sb-lutex :restore-fs-segment-register-from-tls :ud2-breakpoints' >> $ltf
fi
if [ $sbcl_arch = "x86-64" ]; then
- printf ' :mach-exception-handler :sb-lutex' >> $ltf
+ printf ' :mach-exception-handler :sb-lutex :ud2-breakpoints' >> $ltf
fi
link_or_copy $sbcl_arch-darwin-os.h target-arch-os.h
link_or_copy bsd-os.h target-os.h
(defun break-control (chunk inst stream dstate)
(declare (ignore inst))
(flet ((nt (x) (if stream (sb!disassem:note x dstate))))
- ;; FIXME: Make sure that BYTE-IMM-CODE is defined. The genesis
- ;; map has it undefined; and it should be easier to look in the target
- ;; Lisp (with (DESCRIBE 'BYTE-IMM-CODE)) than to definitively deduce
- ;; from first principles whether it's defined in some way that genesis
- ;; can't grok.
- (case #!-darwin (byte-imm-code chunk dstate)
- #!+darwin (word-imm-code chunk dstate)
+ ;; XXX: {BYTE,WORD}-IMM-CODE below is a macro defined by the
+ ;; DEFINE-INSTRUCTION-FORMAT for {BYTE,WORD}-IMM above. Due to
+ ;; the spectacular design for DEFINE-INSTRUCTION-FORMAT (involving
+ ;; a call to EVAL in order to define the macros at compile-time
+ ;; only) they do not even show up as symbols in the target core.
+ (case #!-ud2-breakpoints (byte-imm-code chunk dstate)
+ #!+ud2-breakpoints (word-imm-code chunk dstate)
(#.error-trap
(nt "error trap")
(sb!disassem:handle-break-args #'snarf-error-junk stream dstate))
(define-instruction break (segment code)
(:declare (type (unsigned-byte 8) code))
- #!-darwin (:printer byte-imm ((op #b11001100)) '(:name :tab code)
- :control #'break-control)
- #!+darwin (:printer word-imm ((op #b0000101100001111)) '(:name :tab code)
- :control #'break-control)
+ #!-ud2-breakpoints (:printer byte-imm ((op #b11001100)) '(:name :tab code)
+ :control #'break-control)
+ #!+ud2-breakpoints (:printer word-imm ((op #b0000101100001111)) '(:name :tab code)
+ :control #'break-control)
(:emitter
- #!-darwin (emit-byte segment #b11001100)
+ #!-ud2-breakpoints (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)
+ #!+ud2-breakpoints (emit-word segment #b0000101100001111)
(emit-byte segment code)))
(define-instruction int (segment number)
;;;; error code
(defun emit-error-break (vop kind code values)
(assemble ()
- #!-darwin
+ #!-ud2-breakpoints
(inst int 3) ; i386 breakpoint instruction
;; On Darwin, we need to use #x0b0f instead of int3 in order
;; to generate a SIGILL instead of a SIGTRAP as darwin/x86
;; handlers. Hopefully this will be fixed by Apple at a
;; later date. Do the same on x86-64 as we do on x86 until this gets
;; sorted out.
- #!+darwin
+ #!+ud2-breakpoints
(inst word #x0b0f)
;; The return PC points here; note the location for the debugger.
(when vop
;; Lisp (with (DESCRIBE 'BYTE-IMM-CODE)) than to definitively deduce
;; from first principles whether it's defined in some way that genesis
;; can't grok.
- (case #!-darwin (byte-imm-code chunk dstate)
- #!+darwin (word-imm-code chunk dstate)
+ (case #!-ud2-breakpoints (byte-imm-code chunk dstate)
+ #!+ud2-breakpoints (word-imm-code chunk dstate)
(#.error-trap
(nt "error trap")
(sb!disassem:handle-break-args #'snarf-error-junk stream dstate))
(define-instruction break (segment code)
(:declare (type (unsigned-byte 8) code))
- #!-darwin (:printer byte-imm ((op #b11001100)) '(:name :tab code)
- :control #'break-control)
- #!+darwin (:printer word-imm ((op #b0000101100001111)) '(:name :tab code)
- :control #'break-control)
+ #!-ud2-breakpoints (:printer byte-imm ((op #b11001100)) '(:name :tab code)
+ :control #'break-control)
+ #!+ud2-breakpoints (:printer word-imm ((op #b0000101100001111)) '(:name :tab code)
+ :control #'break-control)
(:emitter
- #!-darwin (emit-byte segment #b11001100)
+ #!-ud2-breakpoints (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)
+ #!+ud2-breakpoints (emit-word segment #b0000101100001111)
(emit-byte segment code)))
(define-instruction int (segment number)
;;;; error code
(defun emit-error-break (vop kind code values)
(assemble ()
- #!-darwin
+ #!-ud2-breakpoints
(inst int 3) ; i386 breakpoint instruction
;; CLH 20060314
;; On Darwin, we need to use #x0b0f instead of int3 in order
;; doesn't seem to be reliably firing SIGTRAP
;; handlers. Hopefully this will be fixed by Apple at a
;; later date.
- #!+darwin
+ #!+ud2-breakpoints
(inst word #x0b0f)
;; The return PC points here; note the location for the debugger.
(when vop
#include "genesis/symbol.h"
#define BREAKPOINT_INST 0xcc /* INT3 */
+#define UD2_INST 0x0b0f /* UD2 */
+
+#ifndef LISP_FEATURE_UD2_BREAKPOINTS
+#define BREAKPOINT_WIDTH 1
+#else
+#define BREAKPOINT_WIDTH 2
+#endif
unsigned long fast_random_state = 1;
{
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:
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) =
(unsigned long)handle_fun_end_breakpoint(context);
}
{
unsigned int trap;
- if (single_stepping && (signal==SIGTRAP))
- {
+ if (single_stepping) {
#ifdef CANNOT_GET_TO_SINGLE_STEP_FLAG
/* Un-install single step helper instructions. */
*(single_stepping-3) = single_step_save1;
*context_eflags_addr(context) ^= 0x100;
#endif
/* Re-install the breakpoint if possible. */
- if ((char *)*os_context_pc_addr(context) ==
- (char *)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;
/* 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);
}
* 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)
+#if defined(LISP_FEATURE_UD2_BREAKPOINTS)
#define TRAP ud2
#else
#define TRAP int3
#include "genesis/symbol.h"
#define BREAKPOINT_INST 0xcc /* INT3 */
+#define UD2_INST 0x0b0f /* UD2 */
+
+#ifndef LISP_FEATURE_UD2_BREAKPOINTS
+#define BREAKPOINT_WIDTH 1
+#else
+#define BREAKPOINT_WIDTH 2
+#endif
unsigned long fast_random_state = 1;
{
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;
}
/* 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);
}
* 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)
+#if defined(LISP_FEATURE_UD2_BREAKPOINTS)
#define END()
#define TRAP ud2
#else
;;; 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.36.8"
+"1.0.36.9"