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
-
9b09c6d9
by Raymond Toy at 2021-04-10T08:50:17-07:00
-
46620f56
by Raymond Toy at 2021-04-10T09:15:38-07:00
2 changed files:
Changes:
... | ... | @@ -2110,32 +2110,39 @@ |
2110 | 2110 |
(defun ud1-control (chunk inst stream dstate)
|
2111 | 2111 |
(declare (ignore inst))
|
2112 | 2112 |
(flet ((nt (x) (if stream (disassem:note x dstate))))
|
2113 |
- (case (ldb (byte 6 16) chunk)
|
|
2114 |
- (#.vm:error-trap
|
|
2115 |
- (nt #.(format nil "Error trap: ~D" vm:error-trap))
|
|
2116 |
- (disassem:handle-break-args #'snarf-error-junk stream dstate))
|
|
2117 |
- (#.vm:cerror-trap
|
|
2118 |
- (nt #.(format nil "Cerror trap: ~D" vm:cerror-trap))
|
|
2119 |
- (disassem:handle-break-args #'snarf-error-junk stream dstate))
|
|
2120 |
- (#.vm:breakpoint-trap
|
|
2121 |
- (nt #.(format nil "Breakpoint trap: ~D" vm:breakpoint-trap)))
|
|
2122 |
- (#.vm:pending-interrupt-trap
|
|
2123 |
- (nt #.(format nil "Pending interrupt trap: ~D" vm:pending-interrupt-trap)))
|
|
2124 |
- (#.vm:halt-trap
|
|
2125 |
- (nt #.(format nil "Halt trap: ~D" vm:halt-trap)))
|
|
2126 |
- (#.vm:function-end-breakpoint-trap
|
|
2127 |
- (nt #.(format nil "Function end breakpoint trap: ~D" vm:function-end-breakpoint-trap)))
|
|
2128 |
- )))
|
|
2113 |
+ (let ((code (ldb (byte 6 16) chunk)))
|
|
2114 |
+ (case code
|
|
2115 |
+ (#.vm:error-trap
|
|
2116 |
+ (nt #.(format nil "Trap ~D: Error trap" vm:error-trap))
|
|
2117 |
+ (disassem:handle-break-args #'snarf-error-junk stream dstate))
|
|
2118 |
+ (#.vm:cerror-trap
|
|
2119 |
+ (nt #.(format nil "Trap ~D: Cerror trap" vm:cerror-trap))
|
|
2120 |
+ (disassem:handle-break-args #'snarf-error-junk stream dstate))
|
|
2121 |
+ (#.vm:pending-interrupt-trap
|
|
2122 |
+ (nt #.(format nil "Trap ~D: Pending interrupt trap" vm:pending-interrupt-trap)))
|
|
2123 |
+ (#.vm:halt-trap
|
|
2124 |
+ (nt #.(format nil "Trap ~D: Halt trap" vm:halt-trap)))
|
|
2125 |
+ (#.vm:function-end-breakpoint-trap
|
|
2126 |
+ (nt #.(format nil "Trap ~D: Function end breakpoint trap"
|
|
2127 |
+ vm:function-end-breakpoint-trap)))
|
|
2128 |
+ (t
|
|
2129 |
+ (nt #.(format nil "Trap ~D: Unexpected trap type!!!!" )))))))
|
|
2129 | 2130 |
|
2130 | 2131 |
;; The ud1 instruction where we smash the code (trap type) into the
|
2131 |
-;; mod r/m byte. We don't care about what that actually encodes to.
|
|
2132 |
-;; We just want the trap code in the third byte of the instruction.
|
|
2132 |
+;; low 6 bits of the mod r/m byte. The mod bits are set to #b11 to
|
|
2133 |
+;; make sure the reg/mem part is interpreted to be a register and not
|
|
2134 |
+;; memory.
|
|
2133 | 2135 |
(define-instruction ud1 (segment code)
|
2134 | 2136 |
(:declare (type (unsigned-byte 8) code))
|
2135 | 2137 |
(:printer ud1 ((op #b10111001) (reg nil :type 'word-reg))
|
2136 | 2138 |
:default
|
2137 | 2139 |
:control #'ud1-control)
|
2138 | 2140 |
(:emitter
|
2141 |
+ ;; We should not be using the breakpoint trap with UD1 anymore.
|
|
2142 |
+ ;; Breakpoint traps are handled in C now, using plain int3.
|
|
2143 |
+ (assert (/= code vm:breakpoint-trap))
|
|
2144 |
+ |
|
2145 |
+ ;; Emit the bytes of the instruction.
|
|
2139 | 2146 |
(emit-byte segment #x0f)
|
2140 | 2147 |
(emit-byte segment #xb9)
|
2141 | 2148 |
(emit-mod-reg-r/m-byte segment
|
... | ... | @@ -260,6 +260,23 @@ unsigned int single_step_save2; |
260 | 260 |
unsigned int single_step_save3;
|
261 | 261 |
#endif
|
262 | 262 |
|
263 |
+/*
|
|
264 |
+ * This is called when we need to continue after a breakpoint. This
|
|
265 |
+ * works by putting the original byte back into the code, and then
|
|
266 |
+ * enabling single-step mode to step one instruction. When we return,
|
|
267 |
+ * the instruction will get run and a sigtrap will get triggered when
|
|
268 |
+ * the one instruction is done.
|
|
269 |
+ *
|
|
270 |
+ * TODO: Be more like other archs where the original inst is put back,
|
|
271 |
+ * and the next inst is replaced with a afterBreakpoint trap. When we
|
|
272 |
+ * run, the afterBreakpoint trap is hit at the next instruction and
|
|
273 |
+ * then we can put back the original breakpoint and replace the
|
|
274 |
+ * afterBreakpoint trap with the original inst there too.
|
|
275 |
+ *
|
|
276 |
+ * For x86, this means computing how many bytes are used in the
|
|
277 |
+ * current instruction, and then placing an int3 (or maybe ud1) after
|
|
278 |
+ * it.
|
|
279 |
+ */
|
|
263 | 280 |
void
|
264 | 281 |
arch_do_displaced_inst(os_context_t * context, unsigned long orig_inst)
|
265 | 282 |
{
|
... | ... | @@ -273,7 +290,7 @@ arch_do_displaced_inst(os_context_t * context, unsigned long orig_inst) |
273 | 290 |
* Put the original instruction back.
|
274 | 291 |
*/
|
275 | 292 |
|
276 |
- *((char *) pc) = orig_inst & 0xff;
|
|
293 |
+ *pc = orig_inst & 0xff;
|
|
277 | 294 |
|
278 | 295 |
/*
|
279 | 296 |
* 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) |
318 | 335 |
|
319 | 336 |
|
320 | 337 |
/*
|
321 |
- * Handles the break instruction from lisp, which is now UD2 followed
|
|
322 |
- * by the trap code. In particular, this does not handle the
|
|
323 |
- * breakpoint traps.
|
|
338 |
+ * Handles the ud1 instruction from lisp that is used to signal
|
|
339 |
+ * errors. In particular, this does not handle the breakpoint traps.
|
|
324 | 340 |
*/
|
325 | 341 |
void
|
326 | 342 |
sigill_handler(HANDLER_ARGS)
|
... | ... | @@ -351,10 +367,10 @@ sigill_handler(HANDLER_ARGS) |
351 | 367 |
RESTORE_FPU(os_context);
|
352 | 368 |
|
353 | 369 |
/*
|
354 |
- * On entry %eip points just after the INT3 byte and aims at the
|
|
355 |
- * 'kind' value (eg trap_Cerror). For error-trap and Cerror-trap a
|
|
356 |
- * number of bytes will follow, the first is the length of the byte
|
|
357 |
- * arguments to follow.
|
|
370 |
+ * On entry %eip points just to the beginning of the UD1
|
|
371 |
+ * instruction. For error-trap and cerror-trap a number of bytes
|
|
372 |
+ * will follow, the first is the length of the byte arguments to
|
|
373 |
+ * follow.
|
|
358 | 374 |
*/
|
359 | 375 |
|
360 | 376 |
DPRINTF(debug_handlers,
|
... | ... | @@ -459,7 +475,13 @@ sigtrap_handler(HANDLER_ARGS) |
459 | 475 |
*((unsigned char*)SC_PC(context) + 3),
|
460 | 476 |
*(unsigned char*)(SC_PC(context) + 4)));
|
461 | 477 |
|
462 |
- if (single_stepping && (signal == SIGTRAP)) {
|
|
478 |
+ if (single_stepping) {
|
|
479 |
+ /*
|
|
480 |
+ * We were single-stepping so we now need to disable
|
|
481 |
+ * single-stepping. We want to put back the breakpoint (int3)
|
|
482 |
+ * instruction so that the next time the breakpoint will be
|
|
483 |
+ * hit again as expected.
|
|
484 |
+ */
|
|
463 | 485 |
DPRINTF(debug_handlers, (stderr, "* Single step trap %p\n", single_stepping));
|
464 | 486 |
|
465 | 487 |
#ifdef SC_EFLAGS
|
... | ... | @@ -492,6 +514,9 @@ sigtrap_handler(HANDLER_ARGS) |
492 | 514 |
return;
|
493 | 515 |
}
|
494 | 516 |
|
517 |
+ /*
|
|
518 |
+ * We weren't single-stepping, so this we've just hit the breakpoint (int3). Handle it.
|
|
519 |
+ */
|
|
495 | 520 |
DPRINTF(debug_handlers, (stderr, "*C break\n"));
|
496 | 521 |
|
497 | 522 |
/*
|