0.pre7.9:
authorWilliam Harold Newman <william.newman@airmail.net>
Fri, 10 Aug 2001 18:50:46 +0000 (18:50 +0000)
committerWilliam Harold Newman <william.newman@airmail.net>
Fri, 10 Aug 2001 18:50:46 +0000 (18:50 +0000)
merged Dan Barlow patch from sbcl-devel 2001-08-10 (fix for
TRACE on Alpha, fix for os_flush_icache() on Alpha,
fix for environ in shared libs, and misc. tidying)

src/code/debug-int.lisp
src/code/run-program.lisp
src/cold/shared.lisp
src/compiler/alpha/insts.lisp
src/runtime/alpha-arch.c
src/runtime/alpha-assem.S
src/runtime/alpha-linux-os.c
src/runtime/breakpoint.c
src/runtime/interrupt.c
version.lisp-expr

index 83378bd..d01cafd 100644 (file)
       ;; so we just leave it up to the C code.
       (breakpoint-do-displaced-inst signal-context
                                    (breakpoint-data-instruction data))
-      ; Under HPUX we can't sigreturn so bp-do-disp-i has to return.
-      #!-(or hpux irix x86)
+      ;; Some platforms have no usable sigreturn() call.  If your
+      ;; implementation of arch_do_displaced_inst() doesn't sigreturn(),
+      ;; add it to this list.
+      #!-(or hpux irix x86 alpha)
       (error "BREAKPOINT-DO-DISPLACED-INST returned?"))))
 
 (defun invoke-breakpoint-hooks (breakpoints component offset)
index b7fb7c8..1dad7f9 100644 (file)
 ;;;; visible at GENESIS time.
 
 (def-alien-variable "environ" (* c-string))
+(push (lambda ()
+       ;; We redo this here to protect ourselves from this scenario:
+       ;;   * Build under one version of shared lib, save a core.
+       ;;   * Load core under another version of shared lib. ("Now
+       ;;     where was environ again?" SIGSEGV, etc.)
+       ;; Obviously it's a KLUDGE to do this hack for every alien
+       ;; variable, but as it happens, as of sbcl-0.7.0 this is the
+       ;; only alien variable used to implement SBCL, so it's not
+       ;; worth coming up with a general solution. (A general
+       ;; solution would be nice for users who want to have their
+       ;; alien code be preserved across a save/load cycle, but this
+       ;; problem with alien variables is only one of several
+       ;; problems which'd need to be solved before that can happen.)
+        (def-alien-variable "environ" (* c-string)))
+      *after-save-initializations*)
 
 (defun posix-environ ()
   "Return the Unix environment (\"man environ\") as a list of SIMPLE-STRINGs."
index d088aa2..8fe5a54 100644 (file)
@@ -32,7 +32,7 @@
 #+(and sbcl alpha) ; SBCL/Alpha uses stop-and-copy, and Alphas have lotso RAM.
 (progn
   (sb-ext:gc-off)
-  (setf (bytes-consed-between-gcs) (* 20 (expt 10 6)))
+  (setf (sb-ext:bytes-consed-between-gcs) (* 20 (expt 10 6)))
   (sb-ext:gc-on)
   (sb-ext:gc))
 
index 1442cb7..147b872 100644 (file)
 (define-instruction gentrap (segment code)
   (:printer call-pal ((palcode #xaa0000)))
   (:emitter
-   (emit-lword segment #x000080)
+   (emit-lword segment #x000081)        ;actually bugchk
    (emit-lword segment code)))
 
 (define-instruction-macro move (src dst)
index 001bc18..066355f 100644 (file)
@@ -136,7 +136,6 @@ unsigned long arch_install_breakpoint(void *pc)
     unsigned int *ptr = (unsigned int *)pc;
     unsigned long result = (unsigned long) *ptr;
     *ptr = BREAKPOINT_INST;
-    *(ptr+1)=trap_Breakpoint;
     
     os_flush_icache((os_vm_address_t)ptr, sizeof(unsigned long));
     
@@ -164,7 +163,6 @@ emulate_branch(os_context_t *context,unsigned long orig_inst)
   int op = orig_inst >> 26;
   int reg_a = (orig_inst >> 21) & 0x1f;
   int reg_b = (orig_inst >> 16) & 0x1f;
-  int fn = orig_inst & 0xffff;
   int disp = (orig_inst&(1<<20)) ? orig_inst | (-1 << 21) : orig_inst&0x1fffff;
   int next_pc = *os_context_pc_addr(context);
   int branch = 0; /* was NULL;        */
@@ -231,70 +229,101 @@ emulate_branch(os_context_t *context,unsigned long orig_inst)
 
 static sigset_t orig_sigmask;
 
+/* Perform the instruction that we overwrote with a breakpoint.  As we
+ * don't have a single-step facility, this means we have to:
+ * - put the instruction back
+ * - put a second breakpoint at the following instruction, 
+ *   set after_breakpoint and continue execution.
+ *
+ * When the second breakpoint is hit (very shortly thereafter, we hope)
+ * sigtrap_handler gets called again, but follows the AfterBreakpoint 
+ * arm, which 
+ * - puts a bpt back in the first breakpoint place (running across a 
+ *   breakpoint shouldn't cause it to be uninstalled)
+ * - replaces the second bpt with the instruction it was meant to be
+ * - carries on 
+ *
+ * Clear?
+ */
+
 void arch_do_displaced_inst(os_context_t *context,unsigned int orig_inst)
 {
+    /* Apparent off-by-one errors ahoy.  If you consult the Alpha ARM,
+     * it will tell you that after a BPT, the saved PC is the address
+     * of the instruction _after_ the instruction that caused the trap.
+     *
+     * However, we decremented PC by 4 before calling the Lisp-level
+     * handler that calls this routine (see alpha-arch.c line 322 and
+     * friends) so when we get to this point PC is actually pointing
+     * at the BPT instruction itself.  This is good, because this is
+     * where we want to restart execution when we do that */
+
   unsigned int *pc=(unsigned int *)(*os_context_pc_addr(context));
   unsigned int *next_pc;
-  unsigned int next_inst;
   int op = orig_inst >> 26;;
-  fprintf(stderr,"arch_do_displaced_inst depends on sigreturn, which is not implemented and will\nalways fail\n");
+
   orig_sigmask = *os_context_sigmask_addr(context);
   sigaddset_blockable(os_context_sigmask_addr(context));
 
-  /* Figure out where the displaced inst is going. */
-  if(op == 0x1a || (op&0xf) == 0x30) /* branch...ugh */
-    /* The cast to long is just to shut gcc up. */
-    next_pc = (unsigned int *)((long)emulate_branch(context,orig_inst));
-  else
-    next_pc = pc+1;
-
   /* Put the original instruction back. */
   *pc = orig_inst;
   os_flush_icache((os_vm_address_t)pc, sizeof(unsigned long));
   skipped_break_addr = pc;
 
+    /* Figure out where we will end up after running the displaced 
+     * instruction */
+    if(op == 0x1a || (op&0xf) == 0x30) /* a branch */
+       /* The cast to long is just to shut gcc up. */
+       next_pc = (unsigned int *)((long)emulate_branch(context,orig_inst));
+    else
+       next_pc = pc+1;
+    
   /* Set the after breakpoint. */
   displaced_after_inst = *next_pc;
   *next_pc = BREAKPOINT_INST;
   after_breakpoint=1;
   os_flush_icache((os_vm_address_t)next_pc, sizeof(unsigned long));
-
-  monitor_or_something();
-  sigreturn(context);
-}
-
-#define AfterBreakpoint 100
-
-static void
-sigill_handler(int signal, siginfo_t *siginfo, os_context_t *context) {
-    fake_foreign_function_call(context);
-    monitor_or_something();
 }
 
 static void
 sigtrap_handler(int signal, siginfo_t *siginfo, os_context_t *context)
 {
+    unsigned int code;
+
     /* Don't disallow recursive breakpoint traps.  Otherwise, we can't */
     /* use debugger breakpoints anywhere in here. */
-
     sigset_t *mask=(os_context_sigmask_addr(context));
-    unsigned int code;
-    fprintf(stderr,"sigtrap_handler:signal %d context=%p ",signal,context);
     sigsetmask(mask); 
 
-    /* this is different from how CMUCL does it.  CMUCL used
-     * "call_pal PAL_gentrap", which doesn't do anything on Linux
-     * so screwed up our offsets in odd ways.  We use "bpt" instead
-     */
-
-    /* probably we should
-    assert(*(unsigned int*)(*os_context_pc_addr(context)-4) == BREAKPOINT_INST)
-    but I've not decided a good way to handle it if it turns out not to be
-    */
+    /* this is different from how CMUCL does it.  CMUCL used "call_pal
+     * PAL_gentrap", which doesn't do anything on Linux (unless NL0
+     * contains certain specific values).  We use "bugchk" instead.
+     * It's (for our purposes) just the same as bpt but has a
+     * different opcode so we can test whether we're dealing with a
+     * breakpoint or a "system service" */
+
+    if((*(unsigned int*)(*os_context_pc_addr(context)-4))== BREAKPOINT_INST) {
+       if(after_breakpoint) {
+           /* see comments above arch_do_displaced_inst.  This is where
+            * we reinsert the breakpoint that we removed earlier */
+
+           *os_context_pc_addr(context) -=4;
+           *skipped_break_addr = BREAKPOINT_INST;
+           os_flush_icache((os_vm_address_t)skipped_break_addr,
+                           sizeof(unsigned long));
+           skipped_break_addr = NULL;
+           *(unsigned int *)*os_context_pc_addr(context) =
+               displaced_after_inst;
+           os_flush_icache((os_vm_address_t)*os_context_pc_addr(context), sizeof(unsigned long));
+           *os_context_sigmask_addr(context)= orig_sigmask;
+           after_breakpoint=0; /* false */
+           return;
+       } else 
+           code = trap_Breakpoint;
+    } else
+       /* a "system service" */
     code=*((u32 *)(*os_context_pc_addr(context)));
-    fprintf(stderr,"pc=%lx  code=%d, inst=%x\n",
-           *os_context_pc_addr(context),  code,
-           *(unsigned int*)(*os_context_pc_addr(context)-4));
+    
     switch (code) {
       case trap_PendingInterrupt:
        arch_skip_instruction(context);
@@ -310,43 +339,33 @@ sigtrap_handler(int signal, siginfo_t *siginfo, os_context_t *context)
        interrupt_internal_error(signal, siginfo, context, code==trap_Cerror);
        break;
 
-      case trap_Breakpoint:
+    case trap_Breakpoint:       /* call lisp-level handler */
         *os_context_pc_addr(context) -=4;
        handle_breakpoint(signal, siginfo, context);
        break;
 
       case trap_FunctionEndBreakpoint:
         *os_context_pc_addr(context) -=4;
-       *os_context_pc_addr(context) = (int)handle_function_end_breakpoint(signal, siginfo, context);
-       break;
-
-      case AfterBreakpoint:
-        *os_context_pc_addr(context) -=4;
-       *skipped_break_addr = BREAKPOINT_INST;
-       os_flush_icache((os_vm_address_t)skipped_break_addr,
-                       sizeof(unsigned long));
-       skipped_break_addr = NULL;
-       *(unsigned int *)*os_context_pc_addr(context) = displaced_after_inst;
-       os_flush_icache((os_vm_address_t)*os_context_pc_addr(context), sizeof(unsigned long));
-        *os_context_sigmask_addr(context)= orig_sigmask;
-        after_breakpoint=0; /* NULL; */
+       *os_context_pc_addr(context) =
+           (int)handle_function_end_breakpoint(signal, siginfo, context);
        break;
 
       default:
+       fprintf(stderr, "unidetified breakpoint/trap %d\n",code);
        interrupt_handle_now(signal, siginfo, context);
        break;
     }
 }
 
-#define FIXNUM_VALUE(lispobj) (((int)lispobj)>>2)
-
 static void sigfpe_handler(int signal, int code, os_context_t *context)
 {
+    /* what should this contain?  interesting question.  If it really
+     * is empty, why don't we just ignore the signal? -dan 2001.08.10
+     */
 }
 
 void arch_install_interrupt_handlers()
 {
-    undoably_install_low_level_interrupt_handler(SIGILL,  sigill_handler);
     undoably_install_low_level_interrupt_handler(SIGTRAP, sigtrap_handler);
     undoably_install_low_level_interrupt_handler(SIGFPE,  sigfpe_handler);
 }
@@ -393,12 +412,3 @@ lispobj funcall3(lispobj function, lispobj arg0, lispobj arg1, lispobj arg2)
     return call_into_lisp(function, args, 3);
 }
 
-
-/* This is apparently called by emulate_branch, but isn't defined.  So */
-/* just do nothing and hope it works... */
-void cacheflush(void)
-{
-    /* hoping probably isn't _actually_ enough.  we should call_pal imb,
-       according to the arch ref manual
-    */
-}
index 56d0047..ba97b81 100644 (file)
@@ -257,7 +257,7 @@ start_of_tramps:
         .ent    undefined_tramp_offset
 undefined_tramp = /* ### undefined_tramp_offset-call_into_lisp_LRA*/ 0x140+call_into_lisp_LRA_page
 undefined_tramp_offset:
-       bpt
+       call_pal PAL_bugchk
        .long    trap_Error
         .byte    4                         /* what are these numbers? */
         .byte    23
@@ -311,7 +311,7 @@ function_end_breakpoint_guts:
 
        .globl  function_end_breakpoint_trap
 function_end_breakpoint_trap:
-       call_pal PAL_gentrap
+       call_pal PAL_bugchk
        .long   trap_FunctionEndBreakpoint
        br      zero, function_end_breakpoint_trap
 
index 8ea7001..3cb67b3 100644 (file)
@@ -1,7 +1,6 @@
 /*
- * This is the x86 Linux incarnation of arch-dependent OS-dependent
- * routines. See also "linux-os.c".
- */
+ * This is the Compaq/Digital Alpha Linux incarnation of
+ * arch-dependent OS-dependent routines. See also "linux-os.c".  */
 
 /*
  * This software is part of the SBCL system. See the README file for
@@ -32,7 +31,6 @@
 
 #include <sys/types.h>
 #include <signal.h>
-/* #include <sys/sysinfo.h> */
 #include <sys/time.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -41,6 +39,7 @@
 size_t os_vm_page_size;
 
 #if defined GENCGC             /* unlikely ... */
+#error SBCL Alpha does not work with the GENCGC
 #include "gencgc.h"
 #endif
 
@@ -76,11 +75,5 @@ os_context_sigmask_addr(os_context_t *context)
 
 void os_flush_icache(os_vm_address_t address, os_vm_size_t length)
 {
-    /* XXX this really shouldn't be empty
-
-<dhd> dan_b: asm volatile ("call_pal imb")
-<dhd> or just "imb"
-<dhd> also : : "memory" 
-
-     */
+    asm volatile ("imb" : : : "memory" );
 }
index 9e95a8a..48f8aed 100644 (file)
@@ -54,7 +54,15 @@ void breakpoint_remove(lispobj code_obj, int pc_offset,
 void breakpoint_do_displaced_inst(os_context_t* context,
                                  unsigned long orig_inst)
 {
-#if !defined(hpux) && !defined(irix) && !defined(__i386__)
+    /* on platforms with sigreturn(), we go directly back from
+     * arch_do_displaced_inst() to lisp code, so we need to clean up
+     * our bindings now.  (side note: I'd love to know in exactly what
+     * scenario the speed of breakpoint handling is critical enough to
+     * justify this maintenance mess)
+     *
+     * -dan 2001.08.09 */
+
+#if !(defined(hpux) || defined(irix) || defined(__i386__) || defined(alpha))
     undo_fake_foreign_function_call(context);
 #endif
     arch_do_displaced_inst(context, orig_inst);
@@ -122,7 +130,10 @@ static int compute_offset(os_context_t *context, lispobj code)
        }
     }
 }
-
+/* FIXME: I can see no really good reason these couldn't be merged, but haven't
+ * tried.  The sigprocmask() call would work just as well on alpha as it
+ * presumably does on x86   -dan 2001.08.10
+ */
 #ifndef __i386__
 void handle_breakpoint(int signal, siginfo_t *info, os_context_t *context)
 {
index 4b42d13..c516822 100644 (file)
@@ -214,6 +214,7 @@ undo_fake_foreign_function_call(os_context_t *context)
      * FREE_INTERRUPT_CONTEXT_INDEX? If so, we should say so. And
      * perhaps yes, unbind_to_here() really would be clearer and less
      * fragile.. */
+    /* dan (2001.08.10) thinks the above supposition is probably correct */
     unbind();
 
 #ifdef reg_ALLOC
index bfb8e16..c6a13a5 100644 (file)
@@ -16,4 +16,4 @@
 ;;; four numeric fields, is used for versions which aren't released
 ;;; but correspond only to CVS tags or snapshots.
 
-"0.pre7.8"
+"0.pre7.9"