* config/pa/tm-hppa.h (unwind_table_entry): Use one of the
authorJeff Law <law@redhat.com>
Tue, 18 Jan 1994 04:04:36 +0000 (04:04 +0000)
committerJeff Law <law@redhat.com>
Tue, 18 Jan 1994 04:04:36 +0000 (04:04 +0000)
        reserved fields to hold a stub unwind entry type.  Fix typo.
        (stub_unwind_entry): New structure for raw stub unwind entries.
        (stub_unwind_types): The types of stubs we may encounter.
        (UNWIND_ENTRY_SIZE, STUB_UNWIND_ENTRY_SIZE): New defines.
        * hppa-tdep.c (rp_saved): Use additional information provided
        by linker stub unwind descriptors.
        (frameless_function_invocation): Likewise.
        (frame_chain_valid): Likewise.
        * paread.c (compare_unwind_entries): New function for sorting
        unwind table entries.
        (read_unwind_info): Rewrite to remove dependency on host endianness.
        Read in data from the $UNWIND_END$ subspace which contains linker
        stub unwind descriptors.  Merge that data into the basic unwind
        table.

gdb/ChangeLog
gdb/config/pa/tm-hppa.h
gdb/hppa-tdep.c
gdb/paread.c

index d582acaa200c63e4e9e46e068b3de1eb995d70ab..a574b583eae6c0440a0d089520fa5595d671ac26 100644 (file)
@@ -1,5 +1,21 @@
 Mon Jan 17 20:00:51 1994  Jeffrey A. Law  (law@snake.cs.utah.edu)
 
+       * config/pa/tm-hppa.h (unwind_table_entry): Use one of the
+       reserved fields to hold a stub unwind entry type.  Fix typo.
+       (stub_unwind_entry): New structure for raw stub unwind entries.
+       (stub_unwind_types): The types of stubs we may encounter.
+       (UNWIND_ENTRY_SIZE, STUB_UNWIND_ENTRY_SIZE): New defines.
+       * hppa-tdep.c (rp_saved): Use additional information provided
+       by linker stub unwind descriptors.
+       (frameless_function_invocation): Likewise.
+       (frame_chain_valid): Likewise.
+       * paread.c (compare_unwind_entries): New function for sorting
+       unwind table entries.
+       (read_unwind_info): Rewrite to remove dependency on host endianness.
+       Read in data from the $UNWIND_END$ subspace which contains linker
+       stub unwind descriptors.  Merge that data into the basic unwind
+       table.
+
        * hppab-nat.c (_initialize_kernel_u_addr): Delete unwanted functions.
 
 Mon Jan 17 22:00:15 1994  Jim Kingdon  (kingdon@lioth.cygnus.com)
index 23d9fe5a9b45b826285f6a6acb39cf9221f7785d..f2afcc13973095c0e0a30bc6e307fe244440b449 100644 (file)
@@ -156,7 +156,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #define FLAGS_REGNUM 0         /* Various status flags */
 #define RP_REGNUM 2            /* return pointer */
-#define FP_REGNUM 4            /* Contains address of executing stack */
+#define FP_REGNUM 3            /* Contains address of executing stack */
                                /* frame */
 #define SP_REGNUM 30           /* Contains address of top of stack */
 #define SAR_REGNUM 32          /* shift amount register */
@@ -319,97 +319,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #define FRAME_ARGS_SKIP 0
 
-/* Put here the code to store, into a struct frame_saved_regs,
-   the addresses of the saved registers of frame described by FRAME_INFO.
-   This includes special registers such as pc and fp saved in special
-   ways in the stack frame.  sp is even more special:
-   the address we return for it IS the sp for the next frame.  */
-
-/* Deal with dummy functions later. */
-
-#define STW_P(INSN) (((INSN) & 0xfc000000) == 0x68000000)
-#define ADDIL_P(INSN) (((INSN) & 0xfc000000) == 0x28000000)
-#define LDO_P(INSN) (((INSN) & 0xfc00c000) == 0x34000000)
-
-#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs)            \
-{ register int regnum;                                                 \
-  register CORE_ADDR next_addr;                                                \
-  register CORE_ADDR pc;                                               \
-  unsigned this_insn;                                                  \
-  unsigned address;                                                    \
-                                                                       \
-  memset (&frame_saved_regs, '\0', sizeof frame_saved_regs);                   \
-  if ((frame_info->pc >= (frame_info)->frame                            \
-       && (frame_info)->pc <= ((frame_info)->frame + CALL_DUMMY_LENGTH  \
-                              + 32 * 4 + (NUM_REGS - FP0_REGNUM) * 8   \
-                              + 6 * 4)))                               \
-    find_dummy_frame_regs ((frame_info), &(frame_saved_regs));         \
-  else                                                                 \
-    { pc = get_pc_function_start ((frame_info)->pc);                   \
-      if (read_memory_integer (pc, 4) == 0x6BC23FD9)                   \
-       { (frame_saved_regs).regs[RP_REGNUM] = (frame_info)->frame - 20;\
-         pc = pc + 4;                                                  \
-       }                                                               \
-      if (read_memory_integer (pc, 4) != 0x8040241) goto lose;         \
-      pc += 8;                 /* skip "copy 4,1; copy 30, 4" */       \
-      /* skip either "stw 1,0(4);addil L'fsize,30;ldo R'fsize(1),30"   \
-        or "stwm 1,fsize(30)" */                                       \
-      if ((read_memory_integer (pc, 4) & ~MASK_14) == 0x68810000)      \
-       pc += 12;                                                       \
-      else                                                             \
-       pc += 4;                                                        \
-      while (1)                                                                \
-       { this_insn = read_memory_integer(pc, 4);                       \
-         if (STW_P (this_insn)) /* stw */                              \
-           { regnum = GET_FIELD (this_insn, 11, 15);                   \
-             if (!regnum) goto lose;                                   \
-             (frame_saved_regs).regs[regnum] = (frame_info)->frame +   \
-               extract_14 (this_insn);                                 \
-             pc += 4;                                                  \
-           }                                                           \
-         else if (ADDIL_P (this_insn)) /* addil */                     \
-           { int next_insn;                                            \
-             next_insn = read_memory_integer(pc + 4, 4);               \
-             if (STW_P (next_insn)) /* stw */                          \
-               { regnum = GET_FIELD (this_insn, 6, 10);                \
-                 if (!regnum) goto lose;                               \
-                 (frame_saved_regs).regs[regnum] = (frame_info)->frame +\
-                   (extract_21 (this_insn) << 11) + extract_14 (next_insn);\
-                 pc += 8;                                              \
-               }                                                       \
-             else                                                      \
-               break;                                                  \
-           }                                                           \
-         else                                                          \
-           { pc += 4;                                                  \
-             break;                                                    \
-           }                                                           \
-       }                                                               \
-      this_insn = read_memory_integer (pc, 4);                         \
-      if (LDO_P (this_insn))                                           \
-       { next_addr = (frame_info)->frame + extract_14 (this_insn);     \
-         pc += 4;                                                      \
-       }                                                               \
-      else if (ADDIL_P (this_insn))                                    \
-       { next_addr = (frame_info)->frame + (extract_21 (this_insn) << 11)\
-           + extract_14 (read_memory_integer (pc + 4, 4));             \
-           pc += 8;                                                    \
-         }                                                             \
-      while (1)                                                                \
-       { this_insn = read_memory_integer (pc, 4);                      \
-         if ((this_insn & 0xfc001fe0) == 0x2c001220) /* fstds,ma */    \
-           { regnum = GET_FIELD (this_insn, 27, 31);                   \
-             (frame_saved_regs).regs[regnum + FP0_REGNUM] = next_addr; \
-             next_addr += 8;                                           \
-              pc += 4;                                                  \
-           }                                                           \
-         else                                                          \
-           break;                                                      \
-       }                                                               \
-    lose:                                                              \
-      (frame_saved_regs).regs[FP_REGNUM] = (frame_info)->frame;                \
-      (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame -4;     \
-    }}
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+  hppa_frame_find_saved_regs (frame_info, &frame_saved_regs)
+
 \f
 /* Things needed for making the inferior call functions.  */
 
@@ -439,7 +351,7 @@ call_dummy
        fldds -12(0, r1), fr7
        ldil 0, r22                     ; target will be placed here.
        ldo 0(r22), r22
-       ldsid (0,r22), r3
+       ldsid (0,r22), r4
        ldil 0, r1                      ; _sr4export will be placed here.
        ldo 0(r1), r1
        ldsid (0,r1), r19
@@ -467,8 +379,8 @@ text_space                          ; Otherwise, go through _sr4export,
 
 #define CALL_DUMMY {0x4BDA3FB9, 0x4BD93FB1, 0x4BD83FA9, 0x4BD73FA1,\
                     0x37C13FB9, 0x24201004, 0x2C391005, 0x24311006,\
-                    0x2C291007, 0x22C00000, 0x36D60000, 0x02C010A3,\
-                    0x20200000, 0x34210000, 0x002010b3, 0x82632022,\
+                    0x2C291007, 0x22C00000, 0x36D60000, 0x02C010A4,\
+                    0x20200000, 0x34210000, 0x002010b3, 0x82642022,\
                     0xe6c06000, 0x081f0242, 0x00010004, 0x00151820,\
                     0xe6c00002, 0xe4202000, 0x6bdf3fd1, 0x00010004,\
                     0x00151820, 0xe6c00002}
@@ -514,7 +426,7 @@ struct unwind_table_entry {
   unsigned int Millicode             :  1;
   unsigned int Millicode_save_sr0    :  1;
   unsigned int Region_description    :  2;
-  unsigned int reserverd1            :  1;
+  unsigned int reserved1             :  1;
   unsigned int Entry_SR              :  1;
   unsigned int Entry_FR              :  4; /* number saved */
   unsigned int Entry_GR              :  5; /* number saved */
@@ -525,6 +437,8 @@ struct unwind_table_entry {
   unsigned int Stack_Overflow_Check  :  1;
   unsigned int Two_Instruction_SP_Increment:1;
   unsigned int Ada_Region           :  1;
+/* Use this field to store a stub unwind type.  */
+#define stub_type reserved2
   unsigned int reserved2            :  4;
   unsigned int Save_SP               :  1;
   unsigned int Save_RP               :  1;
@@ -539,6 +453,41 @@ struct unwind_table_entry {
   unsigned int Total_frame_size      : 27;
 };
 
+/* HP linkers also generate unwinds for various linker-generated stubs.
+   GDB reads in the stubs from the $UNWIND_END$ subspace, then 
+   "converts" them into normal unwind entries using some of the reserved
+   fields to store the stub type.  */
+
+struct stub_unwind_entry
+{
+  /* The offset within the executable for the associated stub.  */
+  unsigned stub_offset;
+
+  /* The type of stub this unwind entry describes.  */
+  char type;
+
+  /* Unknown.  Not needed by GDB at this time.  */
+  char prs_info;
+
+  /* Length (in instructions) of the associated stub.  */
+  short stub_length;
+};
+
+/* Sizes (in bytes) of the native unwind entries.  */
+#define UNWIND_ENTRY_SIZE 16
+#define STUB_UNWIND_ENTRY_SIZE 8
+
+/* The gaps represent linker stubs used in MPE and space for future
+   expansion.  */
+enum unwind_stub_types
+{
+  LONG_BRANCH = 1,
+  PARAMETER_RELOCATION = 2,
+  EXPORT = 10,
+  IMPORT = 11,
+};
+
+       
 /* Info about the unwind table associated with an object file.  This is hung
    off of the objfile->obj_private pointer, and is allocated in the objfile's
    psymbol obstack.  This allows us to have unique unwind info for each
index e0266bdcb2add885ea3c113ab89b3f8172177a10..ca849c5a1199dc42e6551894c983103a021b07ff 100644 (file)
@@ -434,6 +434,18 @@ rp_saved (pc)
 
   if (u->Save_RP)
     return -20;
+  else if (u->stub_type != 0)
+    {
+      switch (u->stub_type)
+       {
+       case EXPORT:
+         return -24;
+       case PARAMETER_RELOCATION:
+         return -8;
+       default:
+         return 0;
+       }
+    }
   else
     return 0;
 }
@@ -449,7 +461,7 @@ frameless_function_invocation (frame)
   if (u == 0)
     return frameless_look_for_prologue (frame);
 
-  return (u->Total_frame_size == 0);
+  return (u->Total_frame_size == 0 && u->stub_type == 0);
 }
 
 CORE_ADDR
@@ -671,7 +683,7 @@ frame_chain_valid (chain, thisframe)
   if (u == NULL)
     return 1;
 
-  if (u->Save_SP || u->Total_frame_size)
+  if (u->Save_SP || u->Total_frame_size || u->stub_type != 0)
     return 1;
 
   if (pc_in_linker_stub (thisframe->pc))
index 7c24fdd80c6902135a623a03ee143d166dd9134c..efc8b2bcb3b2e9b8860306d8fb7ef3ff0ca16a22 100644 (file)
@@ -47,6 +47,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 static void
 pa_symfile_init PARAMS ((struct objfile *));
 
+static int
+compare_unwind_entries PARAMS ((struct unwind_table_entry *,   
+                               struct unwind_table_entry *));
+
 static void
 pa_new_init PARAMS ((struct objfile *));
 
@@ -232,6 +236,23 @@ pa_symtab_read (abfd, addr, objfile)
   install_minimal_symbols (objfile);
 }
 
+/* Compare the start address for two unwind entries returning 1 if 
+   the first address is larger than the second, -1 if the second is
+   larger than the first, and zero if they are equal.  */
+
+static int
+compare_unwind_entries (a, b)
+     struct unwind_table_entry *a;
+     struct unwind_table_entry *b;
+{
+  if (a->region_start > b->region_start)
+    return 1;
+  else if (a->region_start < b->region_start)
+    return -1;
+  else
+    return 0;
+}
+
 /* Read in the backtrace information stored in the `$UNWIND_START$' section of
    the object file.  This info is used mainly by find_unwind_entry() to find
    out the stack frame size and frame pointer used by procedures.  We put
@@ -242,7 +263,9 @@ static void
 read_unwind_info (objfile)
      struct objfile *objfile;
 {
-  asection *unwind_sec;
+  asection *unwind_sec, *stub_unwind_sec;
+  unsigned unwind_size, stub_unwind_size, total_size;
+  unsigned index, unwind_entries, stub_entries, total_entries;
   struct obj_unwind_info *ui;
 
   ui = obstack_alloc (&objfile->psymbol_obstack,
@@ -252,22 +275,132 @@ read_unwind_info (objfile)
   ui->cache = NULL;
   ui->last = -1;
 
-  unwind_sec = bfd_get_section_by_name (objfile->obfd,
-                                       "$UNWIND_START$");
+  /* Get hooks to both unwind sections.  */
+  unwind_sec = bfd_get_section_by_name (objfile->obfd, "$UNWIND_START$");
+  stub_unwind_sec = bfd_get_section_by_name (objfile->obfd, "$UNWIND_END$");
+
+  /* Get sizes and unwind counts for both sections.  */
   if (unwind_sec)
     {
-      int size;
-      int i, *ip;
+      unwind_size = bfd_section_size (objfile->obfd, unwind_sec);
+      unwind_entries = unwind_size / UNWIND_ENTRY_SIZE;
+    }
+  else
+    {
+      unwind_size = 0;
+      unwind_entries = 0;
+    }
+
+  if (stub_unwind_sec)
+    {
+      stub_unwind_size = bfd_section_size (objfile->obfd, stub_unwind_sec);
+      stub_entries = stub_unwind_size / STUB_UNWIND_ENTRY_SIZE;
+    }
+  else
+    {
+      stub_unwind_size = 0;
+      stub_entries = 0;
+    }
+
+  /* Compute total number of stubs.  */
+  total_entries = unwind_entries + stub_entries;
+  total_size = total_entries * sizeof (struct unwind_table_entry);
+
+  /* Allocate memory for the unwind table.  */
+  ui->table = obstack_alloc (&objfile->psymbol_obstack, total_size);
+  ui->last = total_entries + 1;
+
+  /* We will read the unwind entries into temporary memory, then
+     fill in the actual unwind table.  */
+  if (unwind_size > 0)
+    {
+      unsigned long tmp;
+      unsigned i;
+      char *buf = alloca (unwind_size);
+
+      bfd_get_section_contents (objfile->obfd, unwind_sec, buf, 0, unwind_size);
+
+      /* Now internalize the information being careful to handle host/target
+        endian issues.  */
+      for (i = 0; i < unwind_entries; i++)
+       {
+         ui->table[i].region_start = bfd_get_32 (objfile->obfd,
+                                                 (bfd_byte *)buf);
+         buf += 4;
+         ui->table[i].region_end = bfd_get_32 (objfile->obfd, (bfd_byte *)buf);
+         buf += 4;
+         tmp = bfd_get_32 (objfile->obfd, (bfd_byte *)buf);
+         buf += 4;
+         ui->table[i].Cannot_unwind = (tmp >> 31) & 0x1;;
+         ui->table[i].Millicode = (tmp >> 30) & 0x1;
+         ui->table[i].Millicode_save_sr0 = (tmp >> 29) & 0x1;
+         ui->table[i].Region_description = (tmp >> 27) & 0x3;
+         ui->table[i].reserved1 = (tmp >> 26) & 0x1;
+         ui->table[i].Entry_SR = (tmp >> 25) & 0x1;
+         ui->table[i].Entry_FR = (tmp >> 21) & 0xf;
+         ui->table[i].Entry_GR = (tmp >> 16) & 0x1f;
+         ui->table[i].Args_stored = (tmp >> 15) & 0x1;
+         ui->table[i].Variable_Frame = (tmp >> 14) & 0x1;
+         ui->table[i].Separate_Package_Body = (tmp >> 13) & 0x1;
+         ui->table[i].Frame_Extension_Millicode = (tmp >> 12 ) & 0x1;
+         ui->table[i].Stack_Overflow_Check = (tmp >> 11) & 0x1;
+         ui->table[i].Two_Instruction_SP_Increment = (tmp >> 10) & 0x1;
+         ui->table[i].Ada_Region = (tmp >> 9) & 0x1;
+         ui->table[i].reserved2 = (tmp >> 5) & 0xf;
+         ui->table[i].Save_SP = (tmp >> 4) & 0x1;
+         ui->table[i].Save_RP = (tmp >> 3) & 0x1;
+         ui->table[i].Save_MRP_in_frame = (tmp >> 2) & 0x1;
+         ui->table[i].extn_ptr_defined = (tmp >> 1) & 0x1;
+         ui->table[i].Cleanup_defined = tmp & 0x1;
+         tmp = bfd_get_32 (objfile->obfd, (bfd_byte *)buf);
+         buf += 4;
+         ui->table[i].MPE_XL_interrupt_marker = (tmp >> 31) & 0x1;
+         ui->table[i].HP_UX_interrupt_marker = (tmp >> 30) & 0x1;
+         ui->table[i].Large_frame = (tmp >> 29) & 0x1;
+         ui->table[i].reserved4 = (tmp >> 27) & 0x3;
+         ui->table[i].Total_frame_size = tmp & 0x7ffffff;
+       }
+      
+    }
+     
+  if (stub_unwind_size > 0)
+    {
+      unsigned int i;
+      char *buf = alloca (stub_unwind_size);
 
-      size = bfd_section_size (objfile->obfd, unwind_sec);
-      ui->table = obstack_alloc (&objfile->psymbol_obstack, size);
-      ui->last = size / sizeof (struct unwind_table_entry) - 1;
+      /* Read in the stub unwind entries.  */
+      bfd_get_section_contents (objfile->obfd, stub_unwind_sec, buf,
+                               0, stub_unwind_size);
 
-      bfd_get_section_contents (objfile->obfd, unwind_sec, ui->table,
-                               0, size);
+      /* Now convert them into regular unwind entries.  */
+      index = unwind_entries;
+      for (i = 0; i < stub_entries; i++, index++)
+       {
+         /* Clear out the next unwind entry.  */
+         memset (&ui->table[index], 0, sizeof (struct unwind_table_entry));
+
+         /* Convert offset & size into region_start and region_end.  
+            Stuff away the stub type into "reserved" fields.  */
+         ui->table[index].region_start = bfd_get_32 (objfile->obfd,
+                                                     (bfd_byte *) buf);
+         buf += 4;
+         ui->table[index].stub_type = bfd_get_8 (objfile->obfd,
+                                                 (bfd_byte *) buf);
+         buf += 2;
+         ui->table[index].region_end
+           = ui->table[index].region_start + 4 * bfd_get_16 (objfile->obfd,
+                                                             (bfd_byte *) buf);
+         buf += 2;
+       }
 
-      OBJ_UNWIND_INFO (objfile) = ui;
     }
+
+  /* Unwind table needs to be kept sorted.  */
+  qsort (ui->table, total_entries, sizeof (struct unwind_table_entry),
+        compare_unwind_entries);
+
+  /* Keep a pointer to the unwind information.  */
+  OBJ_UNWIND_INFO (objfile) = ui;
 }
 
 /* Scan and build partial symbols for a symbol file.