Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

1.0.36.9: UD2-BREAKPOINTS feature for x86oid systems

  * Add new feature UD2-BREAKPOINTS, enabled by default only on x86oid
darwin targets.

  * Use said feature instead of DARWIN for breakpoint trap selection.

  * Make breakpoints work when using UD2-BREAKPOINTS (tested on x86 and
x86-64 linux).

  * This patch brought to you by lp#309067, which remains valid for
three reasons: First, the test case is still disabled.  Second, this
only fixes for x86oids, not for PPC.  And third, I didn't actually test
this on a darwin system.
  • Loading branch information...
commit 11b5ac86a98f058fe0375b0a707c6ef9e24590c9 1 parent 8c564b7
Alastair Bridgewater authored
View
4 NEWS
@@ -17,6 +17,10 @@ changes relative to sbcl-1.0.36:
* 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
View
5 base-target-features.lisp-expr
@@ -237,6 +237,11 @@
;; 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
View
4 make-config.sh
@@ -240,10 +240,10 @@ case "$sbcl_os" in
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
View
26 src/compiler/x86-64/insts.lisp
@@ -2900,13 +2900,13 @@
(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))
@@ -2928,17 +2928,17 @@
(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)
View
4 src/compiler/x86-64/macros.lisp
@@ -236,7 +236,7 @@
;;;; 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
@@ -244,7 +244,7 @@
;; 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
View
16 src/compiler/x86/insts.lisp
@@ -2249,8 +2249,8 @@
;; 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))
@@ -2268,17 +2268,17 @@
(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)
View
4 src/compiler/x86/macros.lisp
@@ -290,7 +290,7 @@
;;;; 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
@@ -298,7 +298,7 @@
;; 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
View
39 src/runtime/x86-64-arch.c
@@ -31,6 +31,13 @@
#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;
@@ -155,8 +162,14 @@ arch_install_breakpoint(void *pc)
{
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;
}
@@ -166,6 +179,9 @@ arch_remove_breakpoint(void *pc, unsigned int orig_inst)
{
*((char *)pc) = orig_inst & 0xff;
*((char *)pc + 1) = (orig_inst & 0xff00) >> 8;
+#if BREAKPOINT_WIDTH > 1
+ *((char *)pc + 2) = (orig_inst & 0xff0000) >> 16;
+#endif
}
/* When single stepping, single_stepping holds the original instruction
@@ -183,8 +199,7 @@ arch_do_displaced_inst(os_context_t *context, unsigned int orig_inst)
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:
@@ -209,14 +224,14 @@ arch_do_displaced_inst(os_context_t *context, unsigned int orig_inst)
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);
}
@@ -236,8 +251,7 @@ sigtrap_handler(int signal, siginfo_t *info, os_context_t *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;
@@ -247,12 +261,13 @@ sigtrap_handler(int signal, siginfo_t *info, os_context_t *context)
*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;
@@ -278,8 +293,8 @@ sigill_handler(int signal, siginfo_t *siginfo, os_context_t *context) {
/* 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);
}
View
2  src/runtime/x86-64-assem.S
@@ -67,7 +67,7 @@
* 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
View
37 src/runtime/x86-arch.c
@@ -30,6 +30,13 @@
#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;
@@ -158,8 +165,14 @@ arch_install_breakpoint(void *pc)
{
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;
}
@@ -169,6 +182,9 @@ arch_remove_breakpoint(void *pc, unsigned int orig_inst)
{
*((char *)pc) = orig_inst & 0xff;
*((char *)pc + 1) = (orig_inst & 0xff00) >> 8;
+#if BREAKPOINT_WIDTH > 1
+ *((char *)pc + 2) = (orig_inst & 0xff0000) >> 16;
+#endif
}
/* When single stepping, single_stepping holds the original instruction
@@ -186,8 +202,7 @@ arch_do_displaced_inst(os_context_t *context, unsigned int orig_inst)
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:
@@ -222,11 +237,13 @@ restore_breakpoint_from_single_step(os_context_t * context)
*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;
@@ -236,14 +253,14 @@ restore_breakpoint_from_single_step(os_context_t * context)
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);
}
@@ -263,7 +280,7 @@ sigtrap_handler(int signal, siginfo_t *info, os_context_t *context)
{
unsigned int trap;
- if (single_stepping && (signal==SIGTRAP)) {
+ if (single_stepping) {
restore_breakpoint_from_single_step(context);
return;
}
@@ -297,8 +314,8 @@ sigill_handler(int signal, siginfo_t *siginfo, os_context_t *context) {
/* 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);
}
View
2  src/runtime/x86-assem.S
@@ -79,7 +79,7 @@
* 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
View
2  version.lisp-expr
@@ -17,4 +17,4 @@
;;; 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"
Please sign in to comment.
Something went wrong with that request. Please try again.