* gdb.threads/Makefile.in (docdir): Removed.
[deliverable/binutils-gdb.git] / gdb / alpha-tdep.c
index ce06b818311a259d32d538b5f7b189f2ba802584..d778bf22e2915e9a94645f104f22f2c51fab615b 100644 (file)
@@ -1,5 +1,5 @@
 /* Target-dependent code for the ALPHA architecture, for GDB, the GNU Debugger.
-   Copyright 1993, 1994 Free Software Foundation, Inc.
+   Copyright 1993, 1994, 1995 Free Software Foundation, Inc.
 
 This file is part of GDB.
 
@@ -15,7 +15,7 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
 #include "frame.h"
@@ -27,6 +27,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "dis-asm.h"
 #include "symfile.h"
 #include "objfiles.h"
+#include "gdb_string.h"
 
 /* FIXME: Some of this code should perhaps be merged with mips-tdep.c.  */
 
@@ -36,28 +37,28 @@ extern struct obstack frame_cache_obstack;
 
 /* Forward declarations.  */
 
-static CORE_ADDR
-read_next_frame_reg PARAMS ((FRAME, int));
+static CORE_ADDR read_next_frame_reg PARAMS ((struct frame_info *, int));
 
-static CORE_ADDR
-heuristic_proc_start PARAMS ((CORE_ADDR));
+static CORE_ADDR heuristic_proc_start PARAMS ((CORE_ADDR));
 
-static alpha_extra_func_info_t
-heuristic_proc_desc PARAMS ((CORE_ADDR, CORE_ADDR, FRAME));
+static alpha_extra_func_info_t heuristic_proc_desc PARAMS ((CORE_ADDR,
+                                                           CORE_ADDR,
+                                                           struct frame_info *));
 
-static alpha_extra_func_info_t
-find_proc_desc PARAMS ((CORE_ADDR, FRAME));
+static alpha_extra_func_info_t find_proc_desc PARAMS ((CORE_ADDR,
+                                                      struct frame_info *));
 
-static int
-alpha_in_lenient_prologue PARAMS ((CORE_ADDR, CORE_ADDR));
+#if 0
+static int alpha_in_lenient_prologue PARAMS ((CORE_ADDR, CORE_ADDR));
+#endif
 
-static void
-reinit_frame_cache_sfunc PARAMS ((char *, int, struct cmd_list_element *));
+static void reinit_frame_cache_sfunc PARAMS ((char *, int,
+                                             struct cmd_list_element *));
 
 static CORE_ADDR after_prologue PARAMS ((CORE_ADDR pc,
                                         alpha_extra_func_info_t proc_desc));
 
-static int in_prologue PARAMS ((CORE_ADDR pc,
+static int alpha_in_prologue PARAMS ((CORE_ADDR pc,
                                alpha_extra_func_info_t proc_desc));
 
 /* Heuristic_proc_start may hunt through the text section for a long
@@ -131,12 +132,116 @@ struct linked_proc_info
 } *linked_proc_desc_table = NULL;
 
 \f
-/* Guaranteed to set fci->saved_regs to some values (it never leaves it
+/* Under Linux, signal handler invocations can be identified by the
+   designated code sequence that is used to return from a signal
+   handler.  In particular, the return address of a signal handler
+   points to the following sequence (the first instruction is quadword
+   aligned):
+
+       bis $30,$30,$16
+       addq $31,0x67,$0
+       call_pal callsys
+
+   Each instruction has a unique encoding, so we simply attempt to
+   match the instruction the pc is pointing to with any of the above
+   instructions.  If there is a hit, we know the offset to the start
+   of the designated sequence and can then check whether we really are
+   executing in a designated sequence.  If not, -1 is returned,
+   otherwise the offset from the start of the desingated sequence is
+   returned.
+
+   There is a slight chance of false hits: code could jump into the
+   middle of the designated sequence, in which case there is no
+   guarantee that we are in the middle of a sigreturn syscall.  Don't
+   think this will be a problem in praxis, though.
+*/
+long
+alpha_linux_sigtramp_offset (CORE_ADDR pc)
+{
+  unsigned int i[3], w;
+  long off, res;
+
+  if (read_memory_nobpt(pc, (char *) &w, 4) != 0)
+    return -1;
+
+  off = -1;
+  switch (w)
+    {
+    case 0x47de0410: off = 0; break;   /* bis $30,$30,$16 */
+    case 0x43ecf400: off = 4; break;   /* addq $31,0x67,$0 */
+    case 0x00000083: off = 8; break;   /* call_pal callsys */
+    default:        return -1;
+    }
+  pc -= off;
+  if (pc & 0x7)
+    {
+      /* designated sequence is not quadword aligned */
+      return -1;
+    }
+
+  if (read_memory_nobpt(pc, (char *) i, sizeof(i)) != 0)
+    return -1;
+
+  if (i[0] == 0x47de0410 && i[1] == 0x43ecf400 && i[2] == 0x00000083)
+    return off;
+
+  return -1;
+}
+
+\f
+/* Under OSF/1, the __sigtramp routine is frameless and has a frame
+   size of zero, but we are able to backtrace through it.  */
+CORE_ADDR
+alpha_osf_skip_sigtramp_frame (frame, pc)
+     struct frame_info *frame;
+     CORE_ADDR pc;
+{
+  char *name;
+  find_pc_partial_function (pc, &name, (CORE_ADDR *)NULL, (CORE_ADDR *)NULL);
+  if (IN_SIGTRAMP (pc, name))
+    return frame->frame;
+  else
+    return 0;
+}
+
+\f
+/* Dynamically create a signal-handler caller procedure descriptor for
+   the signal-handler return code starting at address LOW_ADDR.  The
+   descriptor is added to the linked_proc_desc_table.  */
+
+alpha_extra_func_info_t
+push_sigtramp_desc (CORE_ADDR low_addr)
+{
+  struct linked_proc_info *link;
+  alpha_extra_func_info_t proc_desc;
+
+  link = (struct linked_proc_info *)
+    xmalloc (sizeof (struct linked_proc_info));
+  link->next = linked_proc_desc_table;
+  linked_proc_desc_table = link;
+
+  proc_desc = &link->info;
+
+  proc_desc->numargs = 0;
+  PROC_LOW_ADDR (proc_desc)    = low_addr;
+  PROC_HIGH_ADDR (proc_desc)   = low_addr + 3 * 4;
+  PROC_DUMMY_FRAME (proc_desc) = 0;
+  PROC_FRAME_OFFSET (proc_desc)        = 0x298; /* sizeof(struct sigcontext_struct) */
+  PROC_FRAME_REG (proc_desc)   = SP_REGNUM;
+  PROC_REG_MASK (proc_desc)    = 0xffff;
+  PROC_FREG_MASK (proc_desc)   = 0xffff;
+  PROC_PC_REG (proc_desc)      = 26;
+  PROC_LOCALOFF (proc_desc)    = 0;
+  SET_PROC_DESC_IS_DYN_SIGTRAMP (proc_desc);
+}
+
+\f
+/* Guaranteed to set frame->saved_regs to some values (it never leaves it
    NULL).  */
 
 void
-alpha_find_saved_regs (fci)
-     FRAME fci;
+alpha_find_saved_regs (frame)
+     struct frame_info *frame;
 {
   int ireg;
   CORE_ADDR reg_position;
@@ -144,11 +249,40 @@ alpha_find_saved_regs (fci)
   alpha_extra_func_info_t proc_desc;
   int returnreg;
 
-  fci->saved_regs = (struct frame_saved_regs *)
+  frame->saved_regs = (struct frame_saved_regs *)
     obstack_alloc (&frame_cache_obstack, sizeof(struct frame_saved_regs));
-  memset (fci->saved_regs, 0, sizeof (struct frame_saved_regs));
+  memset (frame->saved_regs, 0, sizeof (struct frame_saved_regs));
+
+  /* If it is the frame for __sigtramp, the saved registers are located
+     in a sigcontext structure somewhere on the stack. __sigtramp
+     passes a pointer to the sigcontext structure on the stack.
+     If the stack layout for __sigtramp changes, or if sigcontext offsets
+     change, we might have to update this code.  */
+#ifndef SIGFRAME_PC_OFF
+#define SIGFRAME_PC_OFF                (2 * 8)
+#define SIGFRAME_REGSAVE_OFF   (4 * 8)
+#define SIGFRAME_FPREGSAVE_OFF (SIGFRAME_REGSAVE_OFF + 32 * 8 + 8)
+#endif
+  if (frame->signal_handler_caller)
+    {
+      CORE_ADDR sigcontext_addr;
+
+      sigcontext_addr = SIGCONTEXT_ADDR (frame);
+      for (ireg = 0; ireg < 32; ireg++)
+       {
+         reg_position = sigcontext_addr + SIGFRAME_REGSAVE_OFF + ireg * 8;
+         frame->saved_regs->regs[ireg] = reg_position;
+       }
+      for (ireg = 0; ireg < 32; ireg++)
+       {
+         reg_position = sigcontext_addr + SIGFRAME_FPREGSAVE_OFF + ireg * 8;
+         frame->saved_regs->regs[FP0_REGNUM + ireg] = reg_position;
+       }
+      frame->saved_regs->regs[PC_REGNUM] = sigcontext_addr + SIGFRAME_PC_OFF;
+      return;
+    }
 
-  proc_desc = fci->proc_desc;
+  proc_desc = frame->proc_desc;
   if (proc_desc == NULL)
     /* I'm not sure how/whether this can happen.  Normally when we can't
        find a proc_desc, we "synthesize" one using heuristic_proc_desc
@@ -158,16 +292,16 @@ alpha_find_saved_regs (fci)
   /* Fill in the offsets for the registers which gen_mask says
      were saved.  */
 
-  reg_position = fci->frame + PROC_REG_OFFSET (proc_desc);
+  reg_position = frame->frame + PROC_REG_OFFSET (proc_desc);
   mask = PROC_REG_MASK (proc_desc);
 
   returnreg = PROC_PC_REG (proc_desc);
 
-  /* Note that RA is always saved first, regardless of it's actual
+  /* Note that RA is always saved first, regardless of its actual
      register number.  */
   if (mask & (1 << returnreg))
     {
-      fci->saved_regs->regs[returnreg] = reg_position;
+      frame->saved_regs->regs[returnreg] = reg_position;
       reg_position += 8;
       mask &= ~(1 << returnreg); /* Clear bit for RA so we
                                    don't save again later. */
@@ -176,55 +310,36 @@ alpha_find_saved_regs (fci)
   for (ireg = 0; ireg <= 31 ; ++ireg)
     if (mask & (1 << ireg))
       {
-       fci->saved_regs->regs[ireg] = reg_position;
+       frame->saved_regs->regs[ireg] = reg_position;
        reg_position += 8;
       }
 
   /* Fill in the offsets for the registers which float_mask says
      were saved.  */
 
-  reg_position = fci->frame + PROC_FREG_OFFSET (proc_desc);
+  reg_position = frame->frame + PROC_FREG_OFFSET (proc_desc);
   mask = PROC_FREG_MASK (proc_desc);
 
   for (ireg = 0; ireg <= 31 ; ++ireg)
     if (mask & (1 << ireg))
       {
-       fci->saved_regs->regs[FP0_REGNUM+ireg] = reg_position;
+       frame->saved_regs->regs[FP0_REGNUM+ireg] = reg_position;
        reg_position += 8;
       }
 
-  fci->saved_regs->regs[PC_REGNUM] = fci->saved_regs->regs[returnreg];
+  frame->saved_regs->regs[PC_REGNUM] = frame->saved_regs->regs[returnreg];
 }
 
 static CORE_ADDR
 read_next_frame_reg(fi, regno)
-     FRAME fi;
+     struct frame_info *fi;
      int regno;
 {
-  /* If it is the frame for sigtramp we have a pointer to the sigcontext
-     on the stack.
-     If the stack layout for __sigtramp changes or if sigcontext offsets
-     change we might have to update this code.  */
-#ifndef SIGFRAME_PC_OFF
-#define SIGFRAME_PC_OFF                (2 * 8)
-#define SIGFRAME_REGSAVE_OFF   (4 * 8)
-#endif
   for (; fi; fi = fi->next)
     {
-      if (fi->signal_handler_caller)
-       {
-         int offset;
-         CORE_ADDR sigcontext_addr = read_memory_integer(fi->frame, 8);
-
-         if (regno == PC_REGNUM)
-           offset = SIGFRAME_PC_OFF;
-         else if (regno < 32)
-           offset = SIGFRAME_REGSAVE_OFF + regno * 8;
-         else
-           return 0;
-         return read_memory_integer(sigcontext_addr + offset, 8);
-        }
-      else if (regno == SP_REGNUM)
+      /* We have to get the saved sp from the sigcontext
+        if it is a signal handler frame.  */
+      if (regno == SP_REGNUM && !fi->signal_handler_caller)
        return fi->frame;
       else
        {
@@ -239,13 +354,12 @@ read_next_frame_reg(fi, regno)
 
 CORE_ADDR
 alpha_frame_saved_pc(frame)
-     FRAME frame;
+     struct frame_info *frame;
 {
   alpha_extra_func_info_t proc_desc = frame->proc_desc;
   /* We have to get the saved pc from the sigcontext
      if it is a signal handler frame.  */
-  int pcreg = frame->signal_handler_caller ? PC_REGNUM
-             : (proc_desc ? PROC_PC_REG(proc_desc) : RA_REGNUM);
+  int pcreg = frame->signal_handler_caller ? PC_REGNUM : frame->pc_reg;
 
   if (proc_desc && PROC_DESC_IS_DUMMY(proc_desc))
       return read_memory_integer(frame->frame - 8, 8);
@@ -255,12 +369,25 @@ alpha_frame_saved_pc(frame)
 
 CORE_ADDR
 alpha_saved_pc_after_call (frame)
-     FRAME frame;
+     struct frame_info *frame;
 {
-  alpha_extra_func_info_t proc_desc = find_proc_desc (frame->pc, frame->next);
-  int pcreg = proc_desc ? PROC_PC_REG (proc_desc) : RA_REGNUM;
+  CORE_ADDR pc = frame->pc;
+  CORE_ADDR tmp;
+  alpha_extra_func_info_t proc_desc;
+  int pcreg;
 
-  return read_register (pcreg);
+  /* Skip over shared library trampoline if necessary.  */
+  tmp = SKIP_TRAMPOLINE_CODE (pc);
+  if (tmp != 0)
+    pc = tmp;
+
+  proc_desc = find_proc_desc (pc, frame->next);
+  pcreg = proc_desc ? PROC_PC_REG (proc_desc) : RA_REGNUM;
+
+  if (frame->signal_handler_caller)
+    return alpha_frame_saved_pc (frame);
+  else
+    return read_register (pcreg);
 }
 
 
@@ -327,19 +454,20 @@ Otherwise, you told GDB there was a function where there isn't one, or\n\
 static alpha_extra_func_info_t
 heuristic_proc_desc(start_pc, limit_pc, next_frame)
     CORE_ADDR start_pc, limit_pc;
-    FRAME next_frame;
+    struct frame_info *next_frame;
 {
-    CORE_ADDR sp = next_frame ? next_frame->frame : read_register (SP_REGNUM);
+    CORE_ADDR sp = read_next_frame_reg (next_frame, SP_REGNUM);
     CORE_ADDR cur_pc;
     int frame_size;
     int has_frame_reg = 0;
     unsigned long reg_mask = 0;
+    int pcreg = -1;
 
     if (start_pc == 0)
       return NULL;
-    memset(&temp_proc_desc, '\0', sizeof(temp_proc_desc));
-    memset(&temp_saved_regs, '\0', sizeof(struct frame_saved_regs));
-    PROC_LOW_ADDR(&temp_proc_desc) = start_pc;
+    memset (&temp_proc_desc, '\0', sizeof(temp_proc_desc));
+    memset (&temp_saved_regs, '\0', sizeof(struct frame_saved_regs));
+    PROC_LOW_ADDR (&temp_proc_desc) = start_pc;
 
     if (start_pc + 200 < limit_pc)
       limit_pc = start_pc + 200;
@@ -363,17 +491,68 @@ heuristic_proc_desc(start_pc, limit_pc, next_frame)
            int reg = (word & 0x03e00000) >> 21;
            reg_mask |= 1 << reg;
            temp_saved_regs.regs[reg] = sp + (short)word;
+
+           /* Starting with OSF/1-3.2C, the system libraries are shipped
+              without local symbols, but they still contain procedure
+              descriptors without a symbol reference. GDB is currently
+              unable to find these procedure descriptors and uses
+              heuristic_proc_desc instead.
+              As some low level compiler support routines (__div*, __add*)
+              use a non-standard return address register, we have to
+              add some heuristics to determine the return address register,
+              or stepping over these routines will fail.
+              Usually the return address register is the first register
+              saved on the stack, but assembler optimization might
+              rearrange the register saves.
+              So we recognize only a few registers (t7, t9, ra) within
+              the procedure prologue as valid return address registers.
+
+              FIXME: Rewriting GDB to access the procedure descriptors,
+              e.g. via the minimal symbol table, might obviate this hack.  */
+           if (pcreg == -1
+               && cur_pc < (start_pc + 20)
+               && (reg == T7_REGNUM || reg == T9_REGNUM || reg == RA_REGNUM))
+             pcreg = reg;
          }
        else if (word == 0x47de040f)                    /* bis sp,sp fp */
          has_frame_reg = 1;
       }
+    if (pcreg == -1)
+      {
+       /* If we haven't found a valid return address register yet,
+          keep searching in the procedure prologue.  */
+       while (cur_pc < (limit_pc + 20) && cur_pc < (start_pc + 20))
+         {
+           char buf[4];
+           unsigned long word;
+           int status;
+
+           status = read_memory_nobpt (cur_pc, buf, 4); 
+           if (status)
+             memory_error (status, cur_pc);
+           cur_pc += 4;
+           word = extract_unsigned_integer (buf, 4);
+
+           if ((word & 0xfc1f0000) == 0xb41e0000       /* stq reg,n($sp) */
+               && (word & 0xffff0000) != 0xb7fe0000)   /* reg != $zero */
+             {
+               int reg = (word & 0x03e00000) >> 21;
+               if (reg == T7_REGNUM || reg == T9_REGNUM || reg == RA_REGNUM)
+                 {
+                   pcreg = reg;
+                   break;
+                 }
+             }
+         }
+      }
+
     if (has_frame_reg)
       PROC_FRAME_REG(&temp_proc_desc) = GCC_FP_REGNUM;
     else
       PROC_FRAME_REG(&temp_proc_desc) = SP_REGNUM;
     PROC_FRAME_OFFSET(&temp_proc_desc) = frame_size;
     PROC_REG_MASK(&temp_proc_desc) = reg_mask;
-    PROC_PC_REG(&temp_proc_desc) = RA_REGNUM;
+    PROC_PC_REG(&temp_proc_desc) = (pcreg == -1) ? RA_REGNUM : pcreg;
     PROC_LOCALOFF(&temp_proc_desc) = 0;        /* XXX - bogus */
     return &temp_proc_desc;
 }
@@ -386,7 +565,6 @@ after_prologue (pc, proc_desc)
      CORE_ADDR pc;
      alpha_extra_func_info_t proc_desc;
 {
-  struct block *b;
   struct symtab_and_line sal;
   CORE_ADDR func_addr, func_end;
 
@@ -395,6 +573,9 @@ after_prologue (pc, proc_desc)
 
   if (proc_desc)
     {
+      if (PROC_DESC_IS_DYN_SIGTRAMP (proc_desc))
+       return PROC_LOW_ADDR (proc_desc);       /* "prologue" is in kernel */
+
       /* If function is frameless, then we need to do it the hard way.  I
         strongly suspect that frameless always means prologueless... */
       if (PROC_FRAME_REG (proc_desc) == SP_REGNUM
@@ -417,10 +598,10 @@ after_prologue (pc, proc_desc)
 }
 
 /* Return non-zero if we *might* be in a function prologue.  Return zero if we
-   are definatly *not* in a function prologue.  */
+   are definitively *not* in a function prologue.  */
 
 static int
-in_prologue (pc, proc_desc)
+alpha_in_prologue (pc, proc_desc)
      CORE_ADDR pc;
      alpha_extra_func_info_t proc_desc;
 {
@@ -436,9 +617,9 @@ in_prologue (pc, proc_desc)
 }
 
 static alpha_extra_func_info_t
-find_proc_desc(pc, next_frame)
+find_proc_desc (pc, next_frame)
     CORE_ADDR pc;
-    FRAME next_frame;
+    struct frame_info *next_frame;
 {
   alpha_extra_func_info_t proc_desc;
   struct block *b;
@@ -456,7 +637,7 @@ find_proc_desc(pc, next_frame)
   if (PC_IN_CALL_DUMMY (pc, 0, 0))
     {
       struct linked_proc_info *link;
-      CORE_ADDR sp = next_frame ? next_frame->frame : read_register (SP_REGNUM);
+      CORE_ADDR sp = read_next_frame_reg (next_frame, SP_REGNUM);
       alpha_extra_func_info_t found_proc_desc = NULL;
       long min_distance = LONG_MAX;
 
@@ -490,6 +671,11 @@ find_proc_desc(pc, next_frame)
                             0, NULL);
     }
 
+  /* If we never found a PDR for this function in symbol reading, then
+     examine prologues to find the information.  */
+  if (sym && ((mips_extra_func_info_t) SYMBOL_VALUE (sym))->pdr.framereg == -1)
+    sym = NULL;
+
   if (sym)
     {
        /* IF this is the topmost frame AND
@@ -501,19 +687,25 @@ find_proc_desc(pc, next_frame)
        proc_desc = (alpha_extra_func_info_t)SYMBOL_VALUE(sym);
        if (next_frame == NULL)
          {
-           if (PROC_DESC_IS_DUMMY (proc_desc) || in_prologue (pc, proc_desc))
+           if (PROC_DESC_IS_DUMMY (proc_desc) || alpha_in_prologue (pc, proc_desc))
              {
                alpha_extra_func_info_t found_heuristic =
                  heuristic_proc_desc (PROC_LOW_ADDR (proc_desc),
                                       pc, next_frame);
-               PROC_LOCALOFF (found_heuristic) = PROC_LOCALOFF (proc_desc);
                if (found_heuristic)
-                 proc_desc = found_heuristic;
+                 {
+                   PROC_LOCALOFF (found_heuristic) =
+                     PROC_LOCALOFF (proc_desc);
+                   PROC_PC_REG (found_heuristic) = PROC_PC_REG (proc_desc);
+                   proc_desc = found_heuristic;
+                 }
              }
          }
     }
   else
     {
+      long offset;
+
       /* Is linked_proc_desc_table really necessary?  It only seems to be used
         by procedure call dummys.  However, the procedures being called ought
         to have their own proc_descs, and even if they don't,
@@ -525,6 +717,12 @@ find_proc_desc(pc, next_frame)
              && PROC_HIGH_ADDR(&link->info) > pc)
              return &link->info;
 
+      /* If PC is inside a dynamically generated sigtramp handler,
+        create and push a procedure descriptor for that code: */
+      offset = DYNAMIC_SIGTRAMP_OFFSET (pc);
+      if (offset >= 0)
+       return push_sigtramp_desc (pc - offset);
+
       if (startaddr == 0)
        startaddr = heuristic_proc_start (pc);
 
@@ -536,9 +734,9 @@ find_proc_desc(pc, next_frame)
 
 alpha_extra_func_info_t cached_proc_desc;
 
-FRAME_ADDR
+CORE_ADDR
 alpha_frame_chain(frame)
-    FRAME frame;
+    struct frame_info *frame;
 {
     alpha_extra_func_info_t proc_desc;
     CORE_ADDR saved_pc = FRAME_SAVED_PC(frame);
@@ -555,7 +753,7 @@ alpha_frame_chain(frame)
     /* Fetch the frame pointer for a dummy frame from the procedure
        descriptor.  */
     if (PROC_DESC_IS_DUMMY(proc_desc))
-      return (FRAME_ADDR) PROC_DUMMY_FRAME(proc_desc);
+      return (CORE_ADDR) PROC_DUMMY_FRAME(proc_desc);
 
     /* If no frame pointer and frame size is zero, we must be at end
        of stack (or otherwise hosed).  If we don't check frame size,
@@ -565,62 +763,67 @@ alpha_frame_chain(frame)
        /* The previous frame from a sigtramp frame might be frameless
           and have frame size zero.  */
        && !frame->signal_handler_caller)
-      {
-       /* The alpha __sigtramp routine is frameless and has a frame size
-          of zero, but we are able to backtrace through it. */
-       char *name;
-       find_pc_partial_function (saved_pc, &name,
-                                 (CORE_ADDR *)NULL, (CORE_ADDR *)NULL);
-       if (IN_SIGTRAMP (saved_pc, name))
-         return frame->frame;
-       else
-         return 0;
-      }
+      return FRAME_PAST_SIGTRAMP_FRAME (frame, saved_pc);
     else
       return read_next_frame_reg(frame, PROC_FRAME_REG(proc_desc))
             + PROC_FRAME_OFFSET(proc_desc);
 }
 
 void
-init_extra_frame_info(fci)
-     struct frame_info *fci;
+init_extra_frame_info (frame)
+     struct frame_info *frame;
 {
   /* Use proc_desc calculated in frame_chain */
   alpha_extra_func_info_t proc_desc =
-    fci->next ? cached_proc_desc : find_proc_desc(fci->pc, fci->next);
+    frame->next ? cached_proc_desc : find_proc_desc(frame->pc, frame->next);
 
-  fci->saved_regs = NULL;
-  fci->proc_desc =
-    proc_desc == &temp_proc_desc ? 0 : proc_desc;
+  frame->saved_regs = NULL;
+  frame->localoff = 0;
+  frame->pc_reg = RA_REGNUM;
+  frame->proc_desc = proc_desc == &temp_proc_desc ? 0 : proc_desc;
   if (proc_desc)
     {
-      /* Get the locals offset from the procedure descriptor, it is valid
-        even if we are in the middle of the prologue.  */
-      fci->localoff = PROC_LOCALOFF(proc_desc);
+      /* Get the locals offset and the saved pc register from the
+        procedure descriptor, they are valid even if we are in the
+        middle of the prologue.  */
+      frame->localoff = PROC_LOCALOFF(proc_desc);
+      frame->pc_reg = PROC_PC_REG(proc_desc);
 
       /* Fixup frame-pointer - only needed for top frame */
 
       /* Fetch the frame pointer for a dummy frame from the procedure
         descriptor.  */
       if (PROC_DESC_IS_DUMMY(proc_desc))
-       fci->frame = (FRAME_ADDR) PROC_DUMMY_FRAME(proc_desc);
+       frame->frame = (CORE_ADDR) PROC_DUMMY_FRAME(proc_desc);
 
       /* This may not be quite right, if proc has a real frame register.
         Get the value of the frame relative sp, procedure might have been
         interrupted by a signal at it's very start.  */
-      else if (fci->pc == PROC_LOW_ADDR (proc_desc) && !PROC_DESC_IS_DUMMY (proc_desc))
-       fci->frame = read_next_frame_reg (fci->next, SP_REGNUM);
+      else if (frame->pc == PROC_LOW_ADDR (proc_desc)
+              && !PROC_DESC_IS_DYN_SIGTRAMP (proc_desc))
+       frame->frame = read_next_frame_reg (frame->next, SP_REGNUM);
       else
-       fci->frame = read_next_frame_reg (fci->next, PROC_FRAME_REG (proc_desc))
-                       + PROC_FRAME_OFFSET (proc_desc);
+       frame->frame = read_next_frame_reg (frame->next, PROC_FRAME_REG (proc_desc))
+         + PROC_FRAME_OFFSET (proc_desc);
 
       if (proc_desc == &temp_proc_desc)
        {
-         fci->saved_regs = (struct frame_saved_regs*)
-           obstack_alloc (&frame_cache_obstack,
-                          sizeof (struct frame_saved_regs));
-         *fci->saved_regs = temp_saved_regs;
-         fci->saved_regs->regs[PC_REGNUM] = fci->saved_regs->regs[RA_REGNUM];
+         char *name;
+
+         /* Do not set the saved registers for a sigtramp frame,
+            alpha_find_saved_registers will do that for us.
+            We can't use frame->signal_handler_caller, it is not yet set.  */
+         find_pc_partial_function (frame->pc, &name,
+                                   (CORE_ADDR *)NULL,(CORE_ADDR *)NULL);
+         if (!IN_SIGTRAMP (frame->pc, name))
+           {
+             frame->saved_regs = (struct frame_saved_regs*)
+               obstack_alloc (&frame_cache_obstack,
+                              sizeof (struct frame_saved_regs));
+             *frame->saved_regs = temp_saved_regs;
+             frame->saved_regs->regs[PC_REGNUM]
+               = frame->saved_regs->regs[RA_REGNUM];
+           }
        }
     }
 }
@@ -640,10 +843,10 @@ init_extra_frame_info(fci)
    cache.  This allows the rest of info frame to extract the important
    arguments without difficulty.  */
 
-FRAME
+struct frame_info *
 setup_arbitrary_frame (argc, argv)
      int argc;
-     FRAME_ADDR *argv;
+     CORE_ADDR *argv;
 {
   if (argc != 2)
     error ("ALPHA frame specifications require two arguments: sp and pc");
@@ -681,11 +884,26 @@ alpha_push_arguments (nargs, args, sp, struct_return, struct_addr)
 
   for (i = 0, m_arg = alpha_args; i < nargs; i++, m_arg++)
     {
-      value_ptr arg = value_arg_coerce (args[i]);
+      value_ptr arg = args[i];
+      struct type *arg_type = check_typedef (VALUE_TYPE (arg));
       /* Cast argument to long if necessary as the compiler does it too.  */
-      if (TYPE_LENGTH (VALUE_TYPE (arg)) < TYPE_LENGTH (builtin_type_long))
-        arg = value_cast (builtin_type_long, arg);
-      m_arg->len = TYPE_LENGTH (VALUE_TYPE (arg));
+      switch (TYPE_CODE (arg_type))
+       {
+       case TYPE_CODE_INT:
+       case TYPE_CODE_BOOL:
+       case TYPE_CODE_CHAR:
+       case TYPE_CODE_RANGE:
+       case TYPE_CODE_ENUM:
+         if (TYPE_LENGTH (arg_type) < TYPE_LENGTH (builtin_type_long))
+           {
+             arg_type = builtin_type_long;
+             arg = value_cast (arg_type, arg);
+           }
+         break;
+       default:
+         break;
+       }
+      m_arg->len = TYPE_LENGTH (arg_type);
       m_arg->offset = accumulate_size;
       accumulate_size = (accumulate_size + m_arg->len + 7) & ~7;
       m_arg->contents = VALUE_CONTENTS(arg);
@@ -847,7 +1065,7 @@ void
 alpha_pop_frame()
 {
   register int regnum;
-  FRAME frame = get_current_frame ();
+  struct frame_info *frame = get_current_frame ();
   CORE_ADDR new_sp = frame->frame;
 
   alpha_extra_func_info_t proc_desc = frame->proc_desc;
@@ -869,10 +1087,9 @@ alpha_pop_frame()
     }
   write_register (SP_REGNUM, new_sp);
   flush_cached_frames ();
-  /* We let init_extra_frame_info figure out the frame pointer */
-  set_current_frame (create_new_frame (0, read_pc ()));
 
-  if (proc_desc && PROC_DESC_IS_DUMMY(proc_desc))
+  if (proc_desc && (PROC_DESC_IS_DUMMY(proc_desc)
+                   || PROC_DESC_IS_DYN_SIGTRAMP (proc_desc)))
     {
       struct linked_proc_info *pi_ptr, *prev_ptr;
 
@@ -913,6 +1130,18 @@ alpha_skip_prologue (pc, lenient)
     unsigned long inst;
     int offset;
     CORE_ADDR post_prologue_pc;
+    char buf[4];
+
+#ifdef GDB_TARGET_HAS_SHARED_LIBS
+    /* Silently return the unaltered pc upon memory errors.
+       This could happen on OSF/1 if decode_line_1 tries to skip the
+       prologue for quickstarted shared library functions when the
+       shared library is not yet mapped in.
+       Reading target memory is slow over serial lines, so we perform
+       this check only if the target has shared libraries.  */
+    if (target_read_memory (pc, buf, 4))
+      return pc;
+#endif
 
     /* See if we can determine the end of the prologue via the symbol table.
        If so, then return either PC, or the PC after the prologue, whichever
@@ -931,7 +1160,6 @@ alpha_skip_prologue (pc, lenient)
        or in the gcc frame.  */
     for (offset = 0; offset < 100; offset += 4)
       {
-       char buf[4];
        int status;
 
        status = read_memory_nobpt (pc + offset, buf, 4);
@@ -966,6 +1194,7 @@ alpha_skip_prologue (pc, lenient)
     return pc + offset;
 }
 
+#if 0
 /* Is address PC in the prologue (loosely defined) for function at
    STARTADDR?  */
 
@@ -977,6 +1206,7 @@ alpha_in_lenient_prologue (startaddr, pc)
   CORE_ADDR end_prologue = alpha_skip_prologue (startaddr, 1);
   return pc >= startaddr && pc < end_prologue;
 }
+#endif
 
 /* The alpha needs a conversion between register and memory format if
    the register is a floating point register and
@@ -1047,52 +1277,48 @@ alpha_register_convert_to_raw (valtype, regnum, virtual_buffer, raw_buffer)
 
 /* Given a return value in `regbuf' with a type `valtype', 
    extract and copy its value into `valbuf'.  */
+
 void
 alpha_extract_return_value (valtype, regbuf, valbuf)
     struct type *valtype;
     char regbuf[REGISTER_BYTES];
     char *valbuf;
 {
-  int regnum;
-  
-  regnum = TYPE_CODE (valtype) == TYPE_CODE_FLT ? FP0_REGNUM : V0_REGNUM;
-
-  memcpy (valbuf, regbuf + REGISTER_BYTE (regnum), TYPE_LENGTH (valtype));
+  if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
+    alpha_register_convert_to_virtual (FP0_REGNUM, valtype,
+                                      regbuf + REGISTER_BYTE (FP0_REGNUM),
+                                      valbuf);
+  else
+    memcpy (valbuf, regbuf + REGISTER_BYTE (V0_REGNUM), TYPE_LENGTH (valtype));
 }
 
 /* Given a return value in `regbuf' with a type `valtype', 
    write its value into the appropriate register.  */
+
 void
 alpha_store_return_value (valtype, valbuf)
     struct type *valtype;
     char *valbuf;
 {
-  int regnum;
   char raw_buffer[MAX_REGISTER_RAW_SIZE];
+  int regnum = V0_REGNUM;
+  int length = TYPE_LENGTH (valtype);
   
-  regnum = TYPE_CODE (valtype) == TYPE_CODE_FLT ? FP0_REGNUM : V0_REGNUM;
-  memcpy(raw_buffer, valbuf, TYPE_LENGTH (valtype));
-
-  write_register_bytes(REGISTER_BYTE (regnum), raw_buffer, TYPE_LENGTH (valtype));
-}
-
-/* Print the instruction at address MEMADDR in debugged memory,
-   on STREAM.  Returns length of the instruction, in bytes.  */
-
-int
-print_insn (memaddr, stream)
-     CORE_ADDR memaddr;
-     GDB_FILE *stream;
-{
-  disassemble_info info;
-
-  GDB_INIT_DISASSEMBLE_INFO(info, stream);
+  if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
+    {
+      regnum = FP0_REGNUM;
+      length = REGISTER_RAW_SIZE (regnum);
+      alpha_register_convert_to_raw (valtype, regnum, valbuf, raw_buffer);
+    }
+  else
+    memcpy (raw_buffer, valbuf, length);
 
-  return print_insn_alpha (memaddr, &info);
+  write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, length);
 }
 
 /* Just like reinit_frame_cache, but with the right arguments to be
    callable as an sfunc.  */
+
 static void
 reinit_frame_cache_sfunc (args, from_tty, c)
      char *args;
@@ -1118,7 +1344,7 @@ alpha_call_dummy_address ()
   if (entry != 0)
     return entry;
 
-  sym = lookup_minimal_symbol ("_Prelude", symfile_objfile);
+  sym = lookup_minimal_symbol ("_Prelude", NULL, symfile_objfile);
 
   if (!sym || MSYMBOL_TYPE (sym) != mst_text)
     return 0;
@@ -1131,6 +1357,8 @@ _initialize_alpha_tdep ()
 {
   struct cmd_list_element *c;
 
+  tm_print_insn = print_insn_alpha;
+
   /* Let the user set the fence post for heuristic_proc_start.  */
 
   /* We really would like to have both "0" and "unlimited" work, but
This page took 0.035245 seconds and 4 git commands to generate.