* hppah-tdep.c (frame_saved_pc): Use better test for outermost
authorStu Grossman <grossman@cygnus>
Mon, 28 Dec 1992 23:19:51 +0000 (23:19 +0000)
committerStu Grossman <grossman@cygnus>
Mon, 28 Dec 1992 23:19:51 +0000 (23:19 +0000)
frame.  Use find_return_regnum to find the caller.
* (find_unwind_entry):  New routine to locate stack frame info
associated with a procedure.  This looks in the $UNWIND_START$
section in the SOM file.
* (find_return_regnum):  New routine.  Uses find_unwind_entry() to
figure out where the caller's return address is stored.
* (find_proc_framesize):  New routine.  Uses find_unwind_entry()
to figure out the frame size for a procedure.
* (saved_pc_after_call):  New routine, moved from tm-hppa.h.
* (init_extra_frame_info):  New routine.  Corrects PC and FP for
outermost frame if necessary.
* (frame_chain):  New routine, moved from tm-hppa.h.
* (skip_trampoline_code):  Handle computed function calls (ie:
calls from $$dyncall).
* (unwind_command):  Temporary support function to allow user
to control/observe aspects of the unwind (stack frame) info.
* infcmd.c (read_pc):  (Temporary), put a hack in to see if the PC
was in a system call, if so, then read the PC from r31.
* tm-hppah.h (SKIP_TRAMPOLINE_CODE, IN_SOLIB_TRAMPOLINE):  Deal
with extra arg for skip_trampoline_code().
* (INIT_EXTRA_FRAME_INFO):  Define to point at subr (see above).
* (FRAME_CHAIN, FRAME_CHAIN_VALID):  Turn into real subroutines.
* tm-hppa.h (SAVED_PC_AFTER_CALL):  Turn into real subroutine.

gdb/ChangeLog
gdb/hppah-tdep.c
gdb/infcmd.c
gdb/tm-hppa.h
gdb/tm-hppah.h

index d062e413d6e7abce378220d63050d975d7349a01..690b59aa92585b2c8976b5163b9d74ff07139d6d 100644 (file)
@@ -1,3 +1,30 @@
+Mon Dec 28 15:00:01 1992  Stu Grossman  (grossman at cygnus.com)
+
+       * hppah-tdep.c (frame_saved_pc):  Use better test for outermost
+       frame.  Use find_return_regnum to find the caller.
+       * (find_unwind_entry):  New routine to locate stack frame info
+       associated with a procedure.  This looks in the $UNWIND_START$
+       section in the SOM file.
+       * (find_return_regnum):  New routine.  Uses find_unwind_entry() to
+       figure out where the caller's return address is stored.
+       * (find_proc_framesize):  New routine.  Uses find_unwind_entry()
+       to figure out the frame size for a procedure.
+       * (saved_pc_after_call):  New routine, moved from tm-hppa.h.
+       * (init_extra_frame_info):  New routine.  Corrects PC and FP for
+       outermost frame if necessary.
+       * (frame_chain):  New routine, moved from tm-hppa.h.
+       * (skip_trampoline_code):  Handle computed function calls (ie:
+       calls from $$dyncall).
+       * (unwind_command):  Temporary support function to allow user
+       to control/observe aspects of the unwind (stack frame) info.
+       * infcmd.c (read_pc):  (Temporary), put a hack in to see if the PC
+       was in a system call, if so, then read the PC from r31.
+       * tm-hppah.h (SKIP_TRAMPOLINE_CODE, IN_SOLIB_TRAMPOLINE):  Deal
+       with extra arg for skip_trampoline_code().
+       * (INIT_EXTRA_FRAME_INFO):  Define to point at subr (see above).
+       * (FRAME_CHAIN, FRAME_CHAIN_VALID):  Turn into real subroutines.
+       * tm-hppa.h (SAVED_PC_AFTER_CALL):  Turn into real subroutine.
+
 Sun Dec 27 17:34:15 1992  Fred Fish  (fnf@cygnus.com)
 
        * dbxread.c (dbx_symfile_init, elfstab_build_psymtabs):
index 67aae83e9a58fe347f9b11df1fe266698860b7c8..51608eea77ba7cef613eb1b45cd0ffb170c56eb1 100644 (file)
@@ -260,29 +260,150 @@ extract_17 (word)
                      (word & 0x1) << 16, 17) << 2;
 }
 \f
+int use_unwind = 0;
+
+static struct unwind_table_entry *
+find_unwind_entry(pc)
+     CORE_ADDR pc;
+{
+  static struct unwind_table_entry *unwind = NULL, *unwind_end;
+  struct unwind_table_entry *u;
+
+  if (!use_unwind)
+    return NULL;
+
+  if (!unwind)
+    {
+      asection *unwind_sec;
+
+      unwind_sec = bfd_get_section_by_name (exec_bfd, "$UNWIND_START$");
+      if (unwind_sec)
+       {
+         int size;
+
+         size = bfd_section_size (exec_bfd, unwind_sec);
+         unwind = malloc (size);
+         unwind_end = unwind + size/sizeof (struct unwind_table_entry);
+
+         bfd_get_section_contents (exec_bfd, unwind_sec, unwind, 0, size);
+       }
+    }
+
+  for (u = unwind; u < unwind_end; u++)
+    {
+      if (pc >= u->region_start
+         && pc <= u->region_end)
+       return u;
+    }
+  return NULL;
+}
+
+static int
+find_return_regnum(pc)
+     CORE_ADDR pc;
+{
+  struct unwind_table_entry *u;
+
+  u = find_unwind_entry (pc);
+
+  if (!u)
+    return RP_REGNUM;
+
+  if (u->Millicode)
+    return 31;
+
+  return RP_REGNUM;
+}
+
+int
+find_proc_framesize(pc)
+     CORE_ADDR pc;
+{
+  struct unwind_table_entry *u;
+
+  u = find_unwind_entry (pc);
+
+  if (!u)
+    return -1;
+
+  return u->Total_frame_size << 3;
+}
+\f
+CORE_ADDR
+saved_pc_after_call (frame)
+     FRAME frame;
+{
+  int ret_regnum;
+
+  ret_regnum = find_return_regnum (get_frame_pc (frame));
+
+  return read_register (ret_regnum) & ~0x3;
+}
+\f
 CORE_ADDR
 frame_saved_pc (frame)
      FRAME frame;
 {
-  if (get_current_frame () == frame)
+  if (!frame->next)
     {
-      struct frame_saved_regs saved_regs;
       CORE_ADDR pc = get_frame_pc (frame);
-      int flags;
-
-      flags = read_register (FLAGS_REGNUM);
-      get_frame_saved_regs (frame, &saved_regs);
-      if (pc >= millicode_start && pc < millicode_end
-         || (flags & 2))       /* In system call? */
-       return read_register (31) & ~3;
-      else if (saved_regs.regs[RP_REGNUM])
-       return read_memory_integer (saved_regs.regs[RP_REGNUM], 4) & ~3;
-      else
-       return read_register (RP_REGNUM) & ~3;
+      int ret_regnum;
+
+      ret_regnum = find_return_regnum (pc);
+
+      return read_register (ret_regnum) & ~0x3;
     }
   return read_memory_integer (frame->frame - 20, 4) & ~0x3;
 }
+\f
+/* We need to correct the PC and the FP for the outermost frame when we are
+   in a system call.  */
+
+void
+init_extra_frame_info (fromleaf, frame)
+     int fromleaf;
+     struct frame_info *frame;
+{
+  int flags;
+  int framesize;
+
+  if (frame->next)             /* Only do this for outermost frame */
+    return;
 
+  flags = read_register (FLAGS_REGNUM);
+  if (flags & 2)       /* In system call? */
+    frame->pc = read_register (31) & ~0x3;
+
+  /* The outermost frame is always derived from PC-framesize */
+  framesize = find_proc_framesize(frame->pc);
+  if (framesize == -1)
+    frame->frame = read_register (FP_REGNUM);
+  else
+    frame->frame = read_register (SP_REGNUM) - framesize;
+
+  if (framesize != 0)          /* Frameless? */
+    return;
+
+  /* For frameless functions, we need to look at the caller's frame */
+  framesize = find_proc_framesize(FRAME_SAVED_PC(frame));
+  if (framesize != -1)
+    frame->frame -= framesize;
+}
+\f
+FRAME_ADDR
+frame_chain (frame)
+     struct frame_info *frame;
+{
+  int framesize;
+
+  framesize = find_proc_framesize(FRAME_SAVED_PC(frame));
+
+  if (framesize != -1)
+    return frame->frame - framesize;
+
+  return read_memory_integer (frame->frame, 4);
+}
+\f
 /* To see if a frame chain is valid, see if the caller looks like it
    was compiled with gcc. */
 
@@ -293,7 +414,6 @@ int frame_chain_valid (chain, thisframe)
   if (chain && (chain > 0x60000000))
     {
       CORE_ADDR pc = get_pc_function_start (FRAME_SAVED_PC (thisframe));
-
       if (inside_entry_file (pc))
        return 0;
       /* look for stw rp, -20(0,sp); copy 4,1; copy sp, 4 */
@@ -629,13 +749,32 @@ pa_print_fp_reg (i)
    small piece of code that does long format (`external' in HPPA parlance)
    jumps.  We figure out where the trampoline is going to end up, and return
    the PC of the final destination.  If we aren't in a trampoline, we just
-   return NULL. */
+   return NULL. 
+
+   For computed calls, we just extract the new PC from r22.  */
 
 CORE_ADDR
-skip_trampoline_code (pc)
+skip_trampoline_code (pc, name)
      CORE_ADDR pc;
+     char *name;
 {
   long inst0, inst1;
+  static CORE_ADDR dyncall = 0;
+  struct minimal_symbol *msym;
+
+/* FIXME XXX - dyncall must be initialized whenever we get a new exec file */
+
+  if (!dyncall)
+    {
+      msym = lookup_minimal_symbol ("$$dyncall", NULL);
+      if (msym)
+       dyncall = msym->address;
+      else
+       dyncall = -1;
+    }
+
+  if (pc == dyncall)
+    return (CORE_ADDR)(read_register (22) & ~0x3);
 
   inst0 = read_memory_integer (pc, 4);
   inst1 = read_memory_integer (pc+4, 4);
@@ -644,7 +783,49 @@ skip_trampoline_code (pc)
       && (inst1 & 0xffe0e002) == 0xe0202002) /* be,n yyy(sr4, r1) */
     pc = extract_21 (inst0) + extract_17 (inst1);
   else
-    pc = NULL;
+    pc = (CORE_ADDR)NULL;
 
   return pc;
 }
+
+static void
+unwind_command (exp, from_tty)
+     char *exp;
+     int from_tty;
+{
+  CORE_ADDR address;
+  union
+    {
+      int *foo;
+      struct unwind_table_entry *u;
+    } xxx;
+
+  /* If we have an expression, evaluate it and use it as the address.  */
+
+  if (exp != 0 && *exp != 0)
+    address = parse_and_eval_address (exp);
+  else
+    return;
+
+  xxx.u = find_unwind_entry (address);
+
+  if (!xxx.u)
+    {
+      printf ("Can't find unwind table entry for PC 0x%x\n", address);
+      return;
+    }
+
+  printf ("%08x\n%08X\n%08X\n%08X\n", xxx.foo[0], xxx.foo[1], xxx.foo[2],
+         xxx.foo[3]);
+}
+
+void
+_initialize_hppah_tdep ()
+{
+  add_com ("unwind", class_obscure, unwind_command, "Print unwind info\n");
+  add_show_from_set
+    (add_set_cmd ("use_unwind", class_obscure, var_boolean,
+                 (char *)&use_unwind,
+                 "Control the useage of unwind info.\n", &setlist),
+     &showlist);
+}
index c190ffe5bb3d598b4305cea03435523812aa2719..05d22148595352372276a62c30204b5ebd3bbe1d 100644 (file)
@@ -877,6 +877,13 @@ path_command (dirname, from_tty)
 CORE_ADDR
 read_pc ()
 {
+#if GDB_TARGET_IS_HPPA
+  int flags = read_register(FLAGS_REGNUM);
+
+  if (flags & 2)
+    return read_register(31) & ~0x3;
+#endif
+
   return ADDR_BITS_REMOVE ((CORE_ADDR) read_register (PC_REGNUM));
 }
 
index 285e93275a29839c54e401f93ffcdad97122d4c3..97cf7b43c67b898269a70a0314e3538193702b55 100644 (file)
@@ -75,11 +75,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 /* If PC is in some function-call trampoline code, return the PC
    where the function itself actually starts.  If not, return NULL.  */
 
-#define        SKIP_TRAMPOLINE_CODE(pc) skip_trampoline_code (pc)
+#define        SKIP_TRAMPOLINE_CODE(pc) skip_trampoline_code (pc, NULL)
 
 /* Return non-zero if we are in some sort of a trampoline. */
 
-#define IN_SOLIB_TRAMPOLINE(pc,name) skip_trampoline_code (pc)
+#define IN_SOLIB_TRAMPOLINE(pc, name) skip_trampoline_code (pc, name)
 
 /* Immediately after a function call, return the saved pc.
    Can't go through the frames for this because on some machines
@@ -290,11 +290,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
                    ((regno) >= PCSQ_TAIL_REGNUM && (regno) < IPSW_REGNUM) ||  \
                    ((regno) > IPSW_REGNUM && (regno) < FP4_REGNUM)
 
-/* This is a piece of magic that is given a register number REGNO
-   and as BLOCKEND the address in the system of the end of the user structure
-   and stores in ADDR the address in the kernel or core dump
-   of that register.  */
-
+#define INIT_EXTRA_FRAME_INFO(fromleaf, frame) init_extra_frame_info (fromleaf, frame)
 
 /* Describe the pointer in each stack frame to the previous stack frame
    (its caller).  */
@@ -313,13 +309,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
    is the address of a 4-byte word containing the calling frame's
    address (previous FP).  */
 
-#define FRAME_CHAIN(thisframe)  \
-  (!inside_entry_file ((thisframe)->pc) ? \
-   read_memory_integer ((thisframe)->frame, 4) :\
-   0)
+#define FRAME_CHAIN(thisframe) frame_chain (thisframe)
 
+#if 0
 #define FRAME_CHAIN_VALID(chain, thisframe) \
   frame_chain_valid (chain, thisframe)
+#endif
 
 #define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
 
index 42632ef8a03289caa46731e27f7d7ccdeef54cde..05720cdf884d99b85d9c4ef4817bea2af90752c8 100644 (file)
@@ -32,11 +32,7 @@ extern CORE_ADDR millicode_start, millicode_end;
    some instructions.  */
 
 #undef SAVED_PC_AFTER_CALL
-#define SAVED_PC_AFTER_CALL(frame)              \
-  ((get_frame_pc (frame) >= millicode_start     \
-    && get_frame_pc (frame) < millicode_end) ?  \
-   read_register (31) & ~3                      \
-   : read_register (RP_REGNUM) & ~3)
+#define SAVED_PC_AFTER_CALL(frame) saved_pc_after_call (frame)
 
 /* We need to figure out where the text region is so that we use the
    appropriate ptrace operator to manipulate text.  Simply reading/writing