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

Commits:

2 changed files:

Changes:

  • src/compiler/x86/insts.lisp
    ... ... @@ -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
    

  • src/lisp/x86-arch.c
    ... ... @@ -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
         /*