[Git][cmucl/cmucl][issue-97-define-ud2-inst] 3 commits: Change disassembly note for trap codes

Raymond Toy gitlab at common-lisp.net
Sat Apr 10 16:17:13 UTC 2021



Raymond Toy pushed to branch issue-97-define-ud2-inst at cmucl / cmucl


Commits:
9a86d9f0 by Raymond Toy at 2021-04-10T08:42:04-07:00
Change disassembly note for trap codes

Minor tweak to print the trap number first before the description of
the trap.

- - - - -
9b09c6d9 by Raymond Toy at 2021-04-10T08:50:17-07:00
Add comments

- - - - -
46620f56 by Raymond Toy at 2021-04-10T09:15:38-07:00
Address review comments and add more comments

Fixed up a few things mentioned in the review.

Add a more comments on how things work, and added a TODO on computing
the instruction length and inserting a int3/ud1 after it, kind of like
how other archs handle it.

- - - - -


2 changed files:

- src/compiler/x86/insts.lisp
- src/lisp/x86-arch.c


Changes:

=====================================
src/compiler/x86/insts.lisp
=====================================
@@ -2110,32 +2110,39 @@
 (defun ud1-control (chunk inst stream dstate)
   (declare (ignore inst))
   (flet ((nt (x) (if stream (disassem:note x dstate))))
-    (case (ldb (byte 6 16) chunk)
-      (#.vm:error-trap
-       (nt #.(format nil "Error trap: ~D" vm:error-trap))
-       (disassem:handle-break-args #'snarf-error-junk stream dstate))
-      (#.vm:cerror-trap
-       (nt #.(format nil "Cerror trap: ~D" vm:cerror-trap))
-       (disassem:handle-break-args #'snarf-error-junk stream dstate))
-      (#.vm:breakpoint-trap
-       (nt #.(format nil "Breakpoint trap: ~D" vm:breakpoint-trap)))
-      (#.vm:pending-interrupt-trap
-       (nt #.(format nil "Pending interrupt trap: ~D" vm:pending-interrupt-trap)))
-      (#.vm:halt-trap
-       (nt #.(format nil "Halt trap: ~D" vm:halt-trap)))
-      (#.vm:function-end-breakpoint-trap
-       (nt #.(format nil "Function end breakpoint trap: ~D" vm:function-end-breakpoint-trap)))
-    )))
+    (let ((code (ldb (byte 6 16) chunk)))
+      (case code
+	(#.vm:error-trap
+	 (nt #.(format nil "Trap ~D: Error trap" vm:error-trap))
+	 (disassem:handle-break-args #'snarf-error-junk stream dstate))
+	(#.vm:cerror-trap
+	 (nt #.(format nil "Trap ~D: Cerror trap" vm:cerror-trap))
+	 (disassem:handle-break-args #'snarf-error-junk stream dstate))
+	(#.vm:pending-interrupt-trap
+	 (nt #.(format nil "Trap ~D: Pending interrupt trap" vm:pending-interrupt-trap)))
+	(#.vm:halt-trap
+	 (nt #.(format nil "Trap ~D: Halt trap" vm:halt-trap)))
+	(#.vm:function-end-breakpoint-trap
+	 (nt #.(format nil "Trap ~D: Function end breakpoint trap"
+		       vm:function-end-breakpoint-trap)))
+	(t
+	 (nt #.(format nil "Trap ~D: Unexpected trap type!!!!" )))))))
 
 ;; The ud1 instruction where we smash the code (trap type) into the
-;; mod r/m byte.  We don't care about what that actually encodes to.
-;; We just want the trap code in the third byte of the instruction.
+;; low 6 bits of the mod r/m byte.  The mod bits are set to #b11 to
+;; make sure the reg/mem part is interpreted to be a register and not
+;; memory.
 (define-instruction ud1 (segment code)
   (:declare (type (unsigned-byte 8) code))
   (:printer ud1 ((op #b10111001) (reg nil :type 'word-reg))
 	    :default
 	    :control #'ud1-control)
   (:emitter
+   ;; We should not be using the breakpoint trap with UD1 anymore.
+   ;; Breakpoint traps are handled in C now, using plain int3.
+   (assert (/= code vm:breakpoint-trap))
+
+   ;; Emit the bytes of the instruction.
    (emit-byte segment #x0f)
    (emit-byte segment #xb9)
    (emit-mod-reg-r/m-byte segment


=====================================
src/lisp/x86-arch.c
=====================================
@@ -260,6 +260,23 @@ unsigned int single_step_save2;
 unsigned int single_step_save3;
 #endif
 
+/*
+ * This is called when we need to continue after a breakpoint.  This
+ * works by putting the original byte back into the code, and then
+ * enabling single-step mode to step one instruction.  When we return,
+ * the instruction will get run and a sigtrap will get triggered when
+ * the one instruction is done.
+ *
+ * TODO: Be more like other archs where the original inst is put back,
+ * and the next inst is replaced with a afterBreakpoint trap.  When we
+ * run, the afterBreakpoint trap is hit at the next instruction and
+ * then we can put back the original breakpoint and replace the
+ * afterBreakpoint trap with the original inst there too.
+ *
+ * For x86, this means computing how many bytes are used in the
+ * current instruction, and then placing an int3 (or maybe ud1) after
+ * it.
+ */
 void
 arch_do_displaced_inst(os_context_t * context, unsigned long orig_inst)
 {
@@ -273,7 +290,7 @@ arch_do_displaced_inst(os_context_t * context, unsigned long orig_inst)
      * Put the original instruction back.
      */
 
-    *((char *) pc) = orig_inst & 0xff;
+    *pc = orig_inst & 0xff;
 
     /*
      * If we have the SC_EFLAGS macro, we can enable single-stepping
@@ -318,9 +335,8 @@ arch_do_displaced_inst(os_context_t * context, unsigned long orig_inst)
 
 
 /*
- * Handles the break instruction from lisp, which is now UD2 followed
- * by the trap code.  In particular, this does not handle the
- * breakpoint traps.
+ * Handles the ud1 instruction from lisp that is used to signal
+ * errors.  In particular, this does not handle the breakpoint traps.
  */
 void
 sigill_handler(HANDLER_ARGS)
@@ -351,10 +367,10 @@ sigill_handler(HANDLER_ARGS)
     RESTORE_FPU(os_context);
 
     /*
-     * On entry %eip points just after the INT3 byte and aims at the
-     * 'kind' value (eg trap_Cerror). For error-trap and Cerror-trap a
-     * number of bytes will follow, the first is the length of the byte
-     * arguments to follow.
+     * On entry %eip points just to the beginning of the UD1
+     * instruction.  For error-trap and cerror-trap a number of bytes
+     * will follow, the first is the length of the byte arguments to
+     * follow.
      */
 
     DPRINTF(debug_handlers,
@@ -459,7 +475,13 @@ sigtrap_handler(HANDLER_ARGS)
              *((unsigned char*)SC_PC(context) + 3),
              *(unsigned char*)(SC_PC(context) + 4)));
 
-    if (single_stepping && (signal == SIGTRAP)) {
+    if (single_stepping) {
+        /*
+         * We were single-stepping so we now need to disable
+         * single-stepping.  We want to put back the breakpoint (int3)
+         * instruction so that the next time the breakpoint will be
+         * hit again as expected.
+         */
 	DPRINTF(debug_handlers, (stderr, "* Single step trap %p\n", single_stepping));
 
 #ifdef SC_EFLAGS
@@ -492,6 +514,9 @@ sigtrap_handler(HANDLER_ARGS)
 	return;
     }
 
+    /*
+     * We weren't single-stepping, so this we've just hit the breakpoint (int3).  Handle it.
+     */
     DPRINTF(debug_handlers, (stderr, "*C break\n"));
 
     /*



View it on GitLab: https://gitlab.common-lisp.net/cmucl/cmucl/-/compare/cfb35624edee9113a81d900066dc2a9d70e7117c...46620f562160be1e6adcb6490eb993f612c18a39

-- 
View it on GitLab: https://gitlab.common-lisp.net/cmucl/cmucl/-/compare/cfb35624edee9113a81d900066dc2a9d70e7117c...46620f562160be1e6adcb6490eb993f612c18a39
You're receiving this email because of your account on gitlab.common-lisp.net.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.common-lisp.net/pipermail/cmucl-cvs/attachments/20210410/99a8edaf/attachment-0001.html>


More information about the cmucl-cvs mailing list