* solib-sunos.c [HAVE_STRUCT_SO_MAP_WITH_SOM_MEMBERS] (link_map)
[deliverable/binutils-gdb.git] / gdb / hppa-tdep.c
index a872e4f89a44bb891a0acd3517eb4796187b4df8..1209584e93e0bb3ccf0c3b8489704e23018c9ec2 100644 (file)
@@ -64,11 +64,6 @@ const struct objfile_data *hppa_objfile_priv_data = NULL;
 #define MASK_14 0x3fff
 #define MASK_21 0x1fffff
 
-/* Define offsets into the call dummy for the _sr4export address.
-   See comments related to CALL_DUMMY for more info.  */
-#define SR4EXPORT_LDIL_OFFSET (HPPA_INSTRUCTION_SIZE * 12)
-#define SR4EXPORT_LDO_OFFSET (HPPA_INSTRUCTION_SIZE * 13)
-
 /* Sizes (in bytes) of the native unwind entries.  */
 #define UNWIND_ENTRY_SIZE 16
 #define STUB_UNWIND_ENTRY_SIZE 8
@@ -267,6 +262,18 @@ hppa_extract_17 (unsigned word)
                      hppa_get_field (word, 11, 15) << 11 |
                      (word & 0x1) << 16, 17) << 2;
 }
+
+CORE_ADDR 
+hppa_symbol_address(const char *sym)
+{
+  struct minimal_symbol *minsym;
+
+  minsym = lookup_minimal_symbol (sym, NULL, NULL);
+  if (minsym)
+    return SYMBOL_VALUE_ADDRESS (minsym);
+  else
+    return (CORE_ADDR)-1;
+}
 \f
 
 /* Compare the start address for two unwind entries returning 1 if 
@@ -714,7 +721,7 @@ hppa64_register_name (int i)
    arguments into their proper slots.  */
    
 CORE_ADDR
-hppa32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
+hppa32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                        struct regcache *regcache, CORE_ADDR bp_addr,
                        int nargs, struct value **args, CORE_ADDR sp,
                        int struct_return, CORE_ADDR struct_addr)
@@ -732,6 +739,12 @@ hppa32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
   /* Two passes.  First pass computes the location of everything,
      second pass writes the bytes out.  */
   int write_pass;
+
+  /* Global pointer (r19) of the function we are trying to call.  */
+  CORE_ADDR gp;
+
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
   for (write_pass = 0; write_pass < 2; write_pass++)
     {
       CORE_ADDR struct_ptr = 0;
@@ -790,7 +803,7 @@ hppa32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                 the higher-ordered word is stored in the lower-ordered
                 argument, and even though it is a 8-byte quantity the
                 registers need not be 8-byte aligned.  */
-             if (param_len > 4)
+             if (param_len > 4 && param_len < 8)
                small_struct = 1;
            }
 
@@ -852,6 +865,11 @@ hppa32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
   if (struct_return)
     write_register (28, struct_addr);
 
+  gp = tdep->find_global_pointer (function);
+
+  if (gp != 0)
+    write_register (19, gp);
+
   /* Set the return address.  */
   regcache_cooked_write_unsigned (regcache, HPPA_RP_REGNUM, bp_addr);
 
@@ -875,7 +893,7 @@ hppa32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
    to the callee, so we do that too.  */
    
 CORE_ADDR
-hppa64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
+hppa64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                        struct regcache *regcache, CORE_ADDR bp_addr,
                        int nargs, struct value **args, CORE_ADDR sp,
                        int struct_return, CORE_ADDR struct_addr)
@@ -984,6 +1002,22 @@ hppa64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
   return param_end + 64;
 }
 
+static CORE_ADDR
+hppa32_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
+                                  CORE_ADDR addr,
+                                  struct target_ops *targ)
+{
+  if (addr & 2)
+    {
+      CORE_ADDR plabel;
+
+      plabel = addr & ~3;
+      target_read_memory(plabel, (char *)&addr, 4);
+    }
+
+  return addr;
+}
+
 static CORE_ADDR
 hppa32_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
 {
@@ -1293,7 +1327,7 @@ restart:
       old_save_sp = save_sp;
       old_stack_remaining = stack_remaining;
 
-      status = read_memory_nobpt (pc, buf, 4);
+      status = deprecated_read_memory_nobpt (pc, buf, 4);
       inst = extract_unsigned_integer (buf, 4);
 
       /* Yow! */
@@ -1342,7 +1376,7 @@ restart:
          while (reg_num >= (TARGET_PTR_BIT == 64 ? 19 : 23) && reg_num <= 26)
            {
              pc += 4;
-             status = read_memory_nobpt (pc, buf, 4);
+             status = deprecated_read_memory_nobpt (pc, buf, 4);
              inst = extract_unsigned_integer (buf, 4);
              if (status != 0)
                return pc;
@@ -1355,7 +1389,7 @@ restart:
       reg_num = inst_saves_fr (inst);
       save_fr &= ~(1 << reg_num);
 
-      status = read_memory_nobpt (pc + 4, buf, 4);
+      status = deprecated_read_memory_nobpt (pc + 4, buf, 4);
       next_inst = extract_unsigned_integer (buf, 4);
 
       /* Yow! */
@@ -1382,13 +1416,13 @@ restart:
          while (reg_num >= 4 && reg_num <= (TARGET_PTR_BIT == 64 ? 11 : 7))
            {
              pc += 8;
-             status = read_memory_nobpt (pc, buf, 4);
+             status = deprecated_read_memory_nobpt (pc, buf, 4);
              inst = extract_unsigned_integer (buf, 4);
              if (status != 0)
                return pc;
              if ((inst & 0xfc000000) != 0x34000000)
                break;
-             status = read_memory_nobpt (pc + 4, buf, 4);
+             status = deprecated_read_memory_nobpt (pc + 4, buf, 4);
              next_inst = extract_unsigned_integer (buf, 4);
              if (status != 0)
                return pc;
@@ -1613,7 +1647,7 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
       {
        int reg;
        char buf4[4];
-       long status = read_memory_nobpt (pc, buf4, sizeof buf4);
+       long status = deprecated_read_memory_nobpt (pc, buf4, sizeof buf4);
        long inst = extract_unsigned_integer (buf4, sizeof buf4);
 
        /* Note the interesting effects of this instruction.  */
@@ -1725,6 +1759,7 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
        the current function (and is thus equivalent to the "saved"
        stack pointer.  */
     CORE_ADDR this_sp = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM);
+    CORE_ADDR fp;
 
     if (hppa_debug)
       fprintf_unfiltered (gdb_stdlog, " (this_sp=0x%s, pc=0x%s, "
@@ -1733,10 +1768,41 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
                          paddr_nz (frame_pc_unwind (next_frame)),
                          paddr_nz (prologue_end));
 
-    if (frame_pc_unwind (next_frame) >= prologue_end)
+     /* Check to see if a frame pointer is available, and use it for
+        frame unwinding if it is.
+        There are some situations where we need to rely on the frame
+        pointer to do stack unwinding.  For example, if a function calls
+        alloca (), the stack pointer can get adjusted inside the body of
+        the function.  In this case, the ABI requires that the compiler
+        maintain a frame pointer for the function.
+        The unwind record has a flag (alloca_frame) that indicates that
+        a function has a variable frame; unfortunately, gcc/binutils 
+        does not set this flag.  Instead, whenever a frame pointer is used
+        and saved on the stack, the Save_SP flag is set.  We use this to
+        decide whether to use the frame pointer for unwinding.
+       
+       fp may be zero if it is not available in an inner frame because
+       it has been modified by not yet saved.
+       
+        TODO: For the HP compiler, maybe we should use the alloca_frame flag 
+       instead of Save_SP.  */
+     fp = frame_unwind_register_unsigned (next_frame, HPPA_FP_REGNUM);
+     if (frame_pc_unwind (next_frame) >= prologue_end
+         && u->Save_SP && fp != 0)
+      {
+       cache->base = fp;
+       if (hppa_debug)
+         fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [frame pointer] }",
+           paddr_nz (cache->base));
+      }
+     else if (u->Save_SP 
+             && trad_frame_addr_p (cache->saved_regs, HPPA_SP_REGNUM))
       {
-        if (u->Save_SP && trad_frame_addr_p (cache->saved_regs, HPPA_SP_REGNUM))
-          {
             /* Both we're expecting the SP to be saved and the SP has been
               saved.  The entry SP value is saved at this frame's SP
               address.  */
@@ -1745,29 +1811,17 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
            if (hppa_debug)
              fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [saved] }",
                                  paddr_nz (cache->base));
-          }
-        else
-          {
-            /* The prologue has been slowly allocating stack space.  Adjust
-            the SP back.  */
-            cache->base = this_sp - frame_size;
-           if (hppa_debug)
-             fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [unwind adjust] } ",
-                                 paddr_nz (cache->base));
-
-          }
       }
     else
       {
-       /* This frame has not yet been created. */
-        cache->base = this_sp;
-
+        /* The prologue has been slowly allocating stack space.  Adjust
+          the SP back.  */
+        cache->base = this_sp - frame_size;
        if (hppa_debug)
-         fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [before prologue] } ",
+         fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [unwind adjust] } ",
                              paddr_nz (cache->base));
 
       }
-
     trad_frame_set_value (cache->saved_regs, HPPA_SP_REGNUM, cache->base);
   }
 
@@ -1775,7 +1829,7 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
      as the return register while normal code uses "rp".  */
   if (u->Millicode)
     {
-      if (trad_frame_addr_p (cache->saved_regs, HPPA_RP_REGNUM))
+      if (trad_frame_addr_p (cache->saved_regs, 31))
         cache->saved_regs[HPPA_PCOQ_HEAD_REGNUM] = cache->saved_regs[31];
       else
        {
@@ -1794,6 +1848,14 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
        }
     }
 
+  /* If the frame pointer was not saved in this frame, but we should be saving
+     it, set it to an invalid value so that another frame will not pick up the 
+     wrong frame pointer.  This can happen if we start unwinding after the 
+     frame pointer has been modified, but before we've saved it to the
+     stack.  */
+  if (u->Save_SP && !trad_frame_addr_p (cache->saved_regs, HPPA_FP_REGNUM))
+    trad_frame_set_value (cache->saved_regs, HPPA_FP_REGNUM, 0);
+
   {
     /* Convert all the offsets into addresses.  */
     int reg;
@@ -1860,6 +1922,7 @@ static struct hppa_frame_cache *
 hppa_fallback_frame_cache (struct frame_info *next_frame, void **this_cache)
 {
   struct hppa_frame_cache *cache;
+  unsigned int frame_size;
   CORE_ADDR pc, start_pc, end_pc, cur_pc;
 
   cache = FRAME_OBSTACK_ZALLOC (struct hppa_frame_cache);
@@ -1868,6 +1931,7 @@ hppa_fallback_frame_cache (struct frame_info *next_frame, void **this_cache)
 
   pc = frame_func_unwind (next_frame);
   cur_pc = frame_pc_unwind (next_frame);
+  frame_size = 0;
 
   find_pc_partial_function (pc, NULL, &start_pc, &end_pc);
 
@@ -1887,21 +1951,18 @@ hppa_fallback_frame_cache (struct frame_info *next_frame, void **this_cache)
 
       insn = read_memory_unsigned_integer (pc, 4);
 
+      frame_size += prologue_inst_adjust_sp (insn);
+
       /* There are limited ways to store the return pointer into the
         stack.  */
       if (insn == 0x6bc23fd9) /* stw rp,-0x14(sr0,sp) */
-       {
-         cache->saved_regs[HPPA_RP_REGNUM].addr = -20;
-         break;
-       }
+        cache->saved_regs[HPPA_RP_REGNUM].addr = -20;
       else if (insn == 0x0fc212c1) /* std rp,-0x10(sr0,sp) */
-       {
-         cache->saved_regs[HPPA_RP_REGNUM].addr = -16;
-         break;
-       }
+        cache->saved_regs[HPPA_RP_REGNUM].addr = -16;
     }
 
-  cache->base = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM);
+  cache->base = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM) - frame_size;
+  trad_frame_set_value (cache->saved_regs, HPPA_SP_REGNUM, cache->base);
 
   if (trad_frame_addr_p (cache->saved_regs, HPPA_RP_REGNUM))
     {
@@ -1952,28 +2013,6 @@ hppa_fallback_unwind_sniffer (struct frame_info *next_frame)
   return &hppa_fallback_frame_unwind;
 }
 
-static CORE_ADDR
-hppa_frame_base_address (struct frame_info *next_frame,
-                               void **this_cache)
-{
-  struct hppa_frame_cache *info = hppa_frame_cache (next_frame,
-                                                          this_cache);
-  return info->base;
-}
-
-static const struct frame_base hppa_frame_base = {
-  &hppa_frame_unwind,
-  hppa_frame_base_address,
-  hppa_frame_base_address,
-  hppa_frame_base_address
-};
-
-static const struct frame_base *
-hppa_frame_base_sniffer (struct frame_info *next_frame)
-{
-  return &hppa_frame_base;
-}
-
 /* Stub frames, used for all kinds of call stubs.  */
 struct hppa_stub_unwind_cache
 {
@@ -1998,8 +2037,7 @@ hppa_stub_frame_unwind_cache (struct frame_info *next_frame,
 
   info->base = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM);
 
-  if (gdbarch_osabi (gdbarch) == GDB_OSABI_HPUX_ELF 
-      || gdbarch_osabi (gdbarch) == GDB_OSABI_HPUX_SOM)
+  if (gdbarch_osabi (gdbarch) == GDB_OSABI_HPUX_SOM)
     {
       /* HPUX uses export stubs in function calls; the export stub clobbers
          the return value of the caller, and, later restores it from the
@@ -2054,7 +2092,8 @@ hppa_stub_unwind_sniffer (struct frame_info *next_frame)
 {
   CORE_ADDR pc = frame_pc_unwind (next_frame);
 
-  if (IN_SOLIB_CALL_TRAMPOLINE (pc, NULL)
+  if (pc == 0
+      || IN_SOLIB_CALL_TRAMPOLINE (pc, NULL)
       || IN_SOLIB_RETURN_TRAMPOLINE (pc, NULL))
     return &hppa_stub_frame_unwind;
   return NULL;
@@ -2283,6 +2322,12 @@ hppa_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
     store_unsigned_integer (buf, sizeof(tmp), tmp);
 }
 
+static CORE_ADDR
+hppa_find_global_pointer (struct value *function)
+{
+  return 0;
+}
+
 void
 hppa_frame_prev_register_helper (struct frame_info *next_frame,
                                 struct trad_frame_saved_reg saved_regs[],
@@ -2290,20 +2335,32 @@ hppa_frame_prev_register_helper (struct frame_info *next_frame,
                                 enum lval_type *lvalp, CORE_ADDR *addrp,
                                 int *realnump, void *valuep)
 {
-  int pcoqt = (regnum == HPPA_PCOQ_TAIL_REGNUM);
-  struct gdbarch *gdbarch = get_frame_arch (next_frame);
-  int regsize = register_size (gdbarch, HPPA_PCOQ_HEAD_REGNUM);
+  if (regnum == HPPA_PCOQ_TAIL_REGNUM)
+    {
+      if (valuep)
+       {
+         CORE_ADDR pc;
 
-  if (pcoqt)
-    regnum = HPPA_PCOQ_HEAD_REGNUM;
+         trad_frame_get_prev_register (next_frame, saved_regs,
+                                       HPPA_PCOQ_HEAD_REGNUM, optimizedp,
+                                       lvalp, addrp, realnump, valuep);
 
-  trad_frame_prev_register (next_frame, saved_regs, regnum,
-                            optimizedp, lvalp, addrp, realnump, valuep);
+         pc = extract_unsigned_integer (valuep, 4);
+         store_unsigned_integer (valuep, 4, pc + 4);
+       }
+
+      /* It's a computed value.  */
+      *optimizedp = 0;
+      *lvalp = not_lval;
+      *addrp = 0;
+      *realnump = -1;
+      return;
+    }
 
-  if (pcoqt)
-    store_unsigned_integer (valuep, regsize, 
-                           extract_unsigned_integer (valuep, regsize) + 4);
+  trad_frame_get_prev_register (next_frame, saved_regs, regnum,
+                               optimizedp, lvalp, addrp, realnump, valuep);
 }
+\f
 
 /* Here is a table of C type sizes on hppa with various compiles
    and options.  I measured this on PA 9000/800 with HP-UX 11.11
@@ -2372,6 +2429,8 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   else
     tdep->bytes_per_address = 4;
 
+  tdep->find_global_pointer = hppa_find_global_pointer;
+
   /* Some parts of the gdbarch vector depend on whether we are running
      on a 32 bits or 64 bits target.  */
   switch (tdep->bytes_per_address)
@@ -2431,6 +2490,8 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     case 4:
       set_gdbarch_push_dummy_call (gdbarch, hppa32_push_dummy_call);
       set_gdbarch_frame_align (gdbarch, hppa32_frame_align);
+      set_gdbarch_convert_from_func_ptr_addr
+        (gdbarch, hppa32_convert_from_func_ptr_addr);
       break;
     case 8:
       set_gdbarch_push_dummy_call (gdbarch, hppa64_push_dummy_call);
@@ -2467,7 +2528,6 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   frame_unwind_append_sniffer (gdbarch, hppa_stub_unwind_sniffer);
   frame_unwind_append_sniffer (gdbarch, hppa_frame_unwind_sniffer);
   frame_unwind_append_sniffer (gdbarch, hppa_fallback_unwind_sniffer);
-  frame_base_append_sniffer (gdbarch, hppa_frame_base_sniffer);
 
   return gdbarch;
 }
@@ -2529,8 +2589,9 @@ be no argument or the argument must be a depth.\n"), NULL);
 be no argument or the argument must be a depth.\n"), NULL);
 
   /* Debug this files internals. */
-  add_show_from_set (add_set_cmd ("hppa", class_maintenance, var_zinteger,
-                                 &hppa_debug, "Set hppa debugging.\n\
-When non-zero, hppa specific debugging is enabled.", &setdebuglist), &showdebuglist);
+  deprecated_add_show_from_set
+    (add_set_cmd ("hppa", class_maintenance, var_zinteger,
+                 &hppa_debug, "Set hppa debugging.\n\
+When non-zero, hppa specific debugging is enabled.", &setdebuglist),
+     &showdebuglist);
 }
-
This page took 0.029302 seconds and 4 git commands to generate.