* elf32-xtensa.c (ebb_propose_action): Fix argument order.
[deliverable/binutils-gdb.git] / gdb / hppa-tdep.c
index 1209584e93e0bb3ccf0c3b8489704e23018c9ec2..f4cca55a34e42f8ab49f943a77ee06ab1a408dca 100644 (file)
@@ -632,7 +632,7 @@ hppa_breakpoint_from_pc (CORE_ADDR *pc, int *len)
 
 /* Return the name of a register.  */
 
-const char *
+static const char *
 hppa32_register_name (int i)
 {
   static char *names[] = {
@@ -675,7 +675,7 @@ hppa32_register_name (int i)
     return names[i];
 }
 
-const char *
+static const char *
 hppa64_register_name (int i)
 {
   static char *names[] = {
@@ -720,7 +720,7 @@ hppa64_register_name (int i)
    We simply allocate the appropriate amount of stack space and put
    arguments into their proper slots.  */
    
-CORE_ADDR
+static CORE_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,
@@ -758,7 +758,7 @@ hppa32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
       for (i = 0; i < nargs; i++)
        {
          struct value *arg = args[i];
-         struct type *type = check_typedef (VALUE_TYPE (arg));
+         struct type *type = check_typedef (value_type (arg));
          /* The corresponding parameter that is pushed onto the
             stack, and [possibly] passed in a register.  */
          char param_val[8];
@@ -892,7 +892,7 @@ hppa32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
    This ABI also requires that the caller provide an argument pointer
    to the callee, so we do that too.  */
    
-CORE_ADDR
+static CORE_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,
@@ -922,7 +922,7 @@ hppa64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
       for (i = 0; i < nargs; i++)
        {
          struct value *arg = args[i];
-         struct type *type = check_typedef (VALUE_TYPE (arg));
+         struct type *type = check_typedef (value_type (arg));
          if ((TYPE_CODE (type) == TYPE_CODE_INT
               || TYPE_CODE (type) == TYPE_CODE_ENUM)
              && TYPE_LENGTH (type) <= 8)
@@ -1247,14 +1247,15 @@ inst_saves_fr (unsigned long inst)
    be in the prologue.  */
 
 
-CORE_ADDR
-skip_prologue_hard_way (CORE_ADDR pc)
+static CORE_ADDR
+skip_prologue_hard_way (CORE_ADDR pc, int stop_before_branch)
 {
   char buf[4];
   CORE_ADDR orig_pc = pc;
   unsigned long inst, stack_remaining, save_gr, save_fr, save_rp, save_sp;
   unsigned long args_stored, status, i, restart_gr, restart_fr;
   struct unwind_table_entry *u;
+  int final_iteration;
 
   restart_gr = 0;
   restart_fr = 0;
@@ -1298,6 +1299,8 @@ restart:
     save_fr |= (1 << i);
   save_fr &= ~restart_fr;
 
+  final_iteration = 0;
+
   /* Loop until we find everything of interest or hit a branch.
 
      For unoptimized GCC code and for any HP CC code this will never ever
@@ -1434,7 +1437,7 @@ restart:
 
       /* Quit if we hit any kind of branch.  This can happen if a prologue
          instruction is in the delay slot of the first call/branch.  */
-      if (is_branch (inst))
+      if (is_branch (inst) && stop_before_branch)
        break;
 
       /* What a crock.  The HP compilers set args_stored even if no
@@ -1455,6 +1458,13 @@ restart:
 
       /* Bump the PC.  */
       pc += 4;
+
+      /* !stop_before_branch, so also look at the insn in the delay slot 
+         of the branch.  */
+      if (final_iteration)
+       break;
+      if (is_branch (inst))
+       final_iteration = 1;
     }
 
   /* We've got a tenative location for the end of the prologue.  However
@@ -1513,12 +1523,13 @@ after_prologue (CORE_ADDR pc)
 
 /* To skip prologues, I use this predicate.  Returns either PC itself
    if the code at PC does not look like a function prologue; otherwise
-   returns an address that (if we're lucky) follows the prologue.  If
-   LENIENT, then we must skip everything which is involved in setting
-   up the frame (it's OK to skip more, just so long as we don't skip
-   anything which might clobber the registers which are being saved.
-   Currently we must not skip more on the alpha, but we might the lenient
-   stuff some day.  */
+   returns an address that (if we're lucky) follows the prologue.  
+   
+   hppa_skip_prologue is called by gdb to place a breakpoint in a function.
+   It doesn't necessarily skips all the insns in the prologue. In fact
+   we might not want to skip all the insns because a prologue insn may
+   appear in the delay slot of the first branch, and we don't want to
+   skip over the branch in that case.  */
 
 static CORE_ADDR
 hppa_skip_prologue (CORE_ADDR pc)
@@ -1543,7 +1554,7 @@ hppa_skip_prologue (CORE_ADDR pc)
   if (post_prologue_pc != 0)
     return max (pc, post_prologue_pc);
   else
-    return (skip_prologue_hard_way (pc));
+    return (skip_prologue_hard_way (pc, 1));
 }
 
 struct hppa_frame_cache
@@ -1562,6 +1573,7 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
   long frame_size;
   struct unwind_table_entry *u;
   CORE_ADDR prologue_end;
+  int fp_in_r1 = 0;
   int i;
 
   if (hppa_debug)
@@ -1580,7 +1592,7 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
   cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
 
   /* Yow! */
-  u = find_unwind_entry (frame_func_unwind (next_frame));
+  u = find_unwind_entry (frame_pc_unwind (next_frame));
   if (!u)
     {
       if (hppa_debug)
@@ -1625,12 +1637,24 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
     int looking_for_rp = u->Save_RP;
     int fp_loc = -1;
 
-    /* We have to use hppa_skip_prologue instead of just 
+    /* We have to use skip_prologue_hard_way instead of just 
        skip_prologue_using_sal, in case we stepped into a function without
        symbol information.  hppa_skip_prologue also bounds the returned
        pc by the passed in pc, so it will not return a pc in the next
-       function.  */
-    prologue_end = hppa_skip_prologue (frame_func_unwind (next_frame));
+       function.  
+       
+       We used to call hppa_skip_prologue to find the end of the prologue,
+       but if some non-prologue instructions get scheduled into the prologue,
+       and the program is compiled with debug information, the "easy" way
+       in hppa_skip_prologue will return a prologue end that is too early
+       for us to notice any potential frame adjustments.  */
+
+    /* We used to use frame_func_unwind () to locate the beginning of the
+       function to pass to skip_prologue ().  However, when objects are 
+       compiled without debug symbols, frame_func_unwind can return the wrong 
+       function (or 0).  We can do better than that by using unwind records.  */
+
+    prologue_end = skip_prologue_hard_way (u->region_start, 0);
     end_pc = frame_pc_unwind (next_frame);
 
     if (prologue_end != 0 && end_pc > prologue_end)
@@ -1638,7 +1662,7 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
 
     frame_size = 0;
 
-    for (pc = frame_func_unwind (next_frame);
+    for (pc = u->region_start;
         ((saved_gr_mask || saved_fr_mask
           || looking_for_sp || looking_for_rp
           || frame_size < (u->Total_frame_size << 3))
@@ -1647,8 +1671,16 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
       {
        int reg;
        char buf4[4];
-       long status = deprecated_read_memory_nobpt (pc, buf4, sizeof buf4);
-       long inst = extract_unsigned_integer (buf4, sizeof buf4);
+       long inst;
+
+       if (!safe_frame_unwind_memory (next_frame, pc, buf4, 
+                                      sizeof buf4)) 
+         {
+           error ("Cannot read instruction at 0x%s\n", paddr_nz (pc));
+           return (*this_cache);
+         }
+
+       inst = extract_unsigned_integer (buf4, sizeof buf4);
 
        /* Note the interesting effects of this instruction.  */
        frame_size += prologue_inst_adjust_sp (inst);
@@ -1660,6 +1692,11 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
            looking_for_rp = 0;
            cache->saved_regs[HPPA_RP_REGNUM].addr = -20;
          }
+       else if (inst == 0x6bc23fd1) /* stw rp,-0x18(sr0,sp) */
+         {
+           looking_for_rp = 0;
+           cache->saved_regs[HPPA_RP_REGNUM].addr = -24;
+         }
        else if (inst == 0x0fc212c1) /* std rp,-0x10(sr0,sp) */
          {
            looking_for_rp = 0;
@@ -1675,6 +1712,10 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
            looking_for_sp = 0;
            cache->saved_regs[HPPA_FP_REGNUM].addr = 0;
          }
+       else if (inst == 0x08030241) /* copy %r3, %r1 */
+         {
+           fp_in_r1 = 1;
+         }
        
        /* Account for general and floating-point register saves.  */
        reg = inst_saves_gr (inst);
@@ -1783,9 +1824,6 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
         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.  */
  
@@ -1848,13 +1886,26 @@ 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);
+  /* If Save_SP is set, then we expect the frame pointer to be saved in the
+     frame.  However, there is a one-insn window where we haven't saved it
+     yet, but we've already clobbered it.  Detect this case and fix it up.
+
+     The prologue sequence for frame-pointer functions is:
+       0: stw %rp, -20(%sp)
+       4: copy %r3, %r1
+       8: copy %sp, %r3
+       c: stw,ma %r1, XX(%sp)
+
+     So if we are at offset c, the r3 value that we want is not yet saved
+     on the stack, but it's been overwritten.  The prologue analyzer will
+     set fp_in_r1 when it sees the copy insn so we know to get the value 
+     from r1 instead.  */
+  if (u->Save_SP && !trad_frame_addr_p (cache->saved_regs, HPPA_FP_REGNUM)
+      && fp_in_r1)
+    {
+      ULONGEST r1 = frame_unwind_register_unsigned (next_frame, 1);
+      trad_frame_set_value (cache->saved_regs, HPPA_FP_REGNUM, r1);
+    }
 
   {
     /* Convert all the offsets into addresses.  */
@@ -1876,8 +1927,14 @@ static void
 hppa_frame_this_id (struct frame_info *next_frame, void **this_cache,
                           struct frame_id *this_id)
 {
-  struct hppa_frame_cache *info = hppa_frame_cache (next_frame, this_cache);
-  (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame));
+  struct hppa_frame_cache *info;
+  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  struct unwind_table_entry *u;
+
+  info = hppa_frame_cache (next_frame, this_cache);
+  u = find_unwind_entry (pc);
+
+  (*this_id) = frame_id_build (info->base, u->region_start);
 }
 
 static void
@@ -1923,8 +1980,13 @@ hppa_fallback_frame_cache (struct frame_info *next_frame, void **this_cache)
 {
   struct hppa_frame_cache *cache;
   unsigned int frame_size;
+  int found_rp;
   CORE_ADDR pc, start_pc, end_pc, cur_pc;
 
+  if (hppa_debug)
+    fprintf_unfiltered (gdb_stdlog, "{ hppa_fallback_frame_cache (frame=%d)-> ",
+      frame_relative_level(next_frame));
+
   cache = FRAME_OBSTACK_ZALLOC (struct hppa_frame_cache);
   (*this_cache) = cache;
   cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
@@ -1932,6 +1994,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;
+  found_rp = 0;
 
   find_pc_partial_function (pc, NULL, &start_pc, &end_pc);
 
@@ -1956,11 +2019,21 @@ hppa_fallback_frame_cache (struct frame_info *next_frame, void **this_cache)
       /* 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;
+        {
+          cache->saved_regs[HPPA_RP_REGNUM].addr = -20;
+          found_rp = 1;
+        }
       else if (insn == 0x0fc212c1) /* std rp,-0x10(sr0,sp) */
-        cache->saved_regs[HPPA_RP_REGNUM].addr = -16;
+        {
+          cache->saved_regs[HPPA_RP_REGNUM].addr = -16;
+          found_rp = 1;
+        }
     }
 
+  if (hppa_debug)
+    fprintf_unfiltered (gdb_stdlog, " frame_size = %d, found_rp = %d }\n",
+      frame_size, found_rp);
+
   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);
 
@@ -2091,9 +2164,12 @@ static const struct frame_unwind *
 hppa_stub_unwind_sniffer (struct frame_info *next_frame)
 {
   CORE_ADDR pc = frame_pc_unwind (next_frame);
+  struct gdbarch *gdbarch = get_frame_arch (next_frame);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   if (pc == 0
-      || IN_SOLIB_CALL_TRAMPOLINE (pc, NULL)
+      || (tdep->in_solib_call_trampoline != NULL
+         && tdep->in_solib_call_trampoline (pc, NULL))
       || IN_SOLIB_RETURN_TRAMPOLINE (pc, NULL))
     return &hppa_stub_frame_unwind;
   return NULL;
@@ -2149,9 +2225,11 @@ unwind_command (char *exp, int from_tty)
 
   printf_unfiltered ("\tregion_start = ");
   print_address (u->region_start, gdb_stdout);
+  gdb_flush (gdb_stdout);
 
   printf_unfiltered ("\n\tregion_end = ");
   print_address (u->region_end, gdb_stdout);
+  gdb_flush (gdb_stdout);
 
 #define pif(FLD) if (u->FLD) printf_unfiltered (" "#FLD);
 
@@ -2186,30 +2264,6 @@ unwind_command (char *exp, int from_tty)
   pin (Total_frame_size);
 }
 
-void
-hppa_skip_permanent_breakpoint (void)
-{
-  /* To step over a breakpoint instruction on the PA takes some
-     fiddling with the instruction address queue.
-
-     When we stop at a breakpoint, the IA queue front (the instruction
-     we're executing now) points at the breakpoint instruction, and
-     the IA queue back (the next instruction to execute) points to
-     whatever instruction we would execute after the breakpoint, if it
-     were an ordinary instruction.  This is the case even if the
-     breakpoint is in the delay slot of a branch instruction.
-
-     Clearly, to step past the breakpoint, we need to set the queue
-     front to the back.  But what do we put in the back?  What
-     instruction comes after that one?  Because of the branch delay
-     slot, the next insn is always at the back + 4.  */
-  write_register (HPPA_PCOQ_HEAD_REGNUM, read_register (HPPA_PCOQ_TAIL_REGNUM));
-  write_register (HPPA_PCSQ_HEAD_REGNUM, read_register (HPPA_PCSQ_TAIL_REGNUM));
-
-  write_register (HPPA_PCOQ_TAIL_REGNUM, read_register (HPPA_PCOQ_TAIL_REGNUM) + 4);
-  /* We can leave the tail's space the same, since there's no jump.  */
-}
-
 int
 hppa_pc_requires_run_before_use (CORE_ADDR pc)
 {
@@ -2301,7 +2355,7 @@ hppa_smash_text_address (CORE_ADDR addr)
 }
 
 /* Get the ith function argument for the current function.  */
-CORE_ADDR
+static CORE_ADDR
 hppa_fetch_pointer_argument (struct frame_info *frame, int argi, 
                             struct type *type)
 {
@@ -2589,9 +2643,11 @@ 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. */
-  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);
+  add_setshow_boolean_cmd ("hppa", class_maintenance, &hppa_debug, "\
+Set whether hppa target specific debugging information should be displayed.", "\
+Show whether hppa target specific debugging information is displayed.", "\
+This flag controls whether hppa target specific debugging information is\n\
+displayed.  This information is particularly useful for debugging frame\n\
+unwinding problems.", "hppa debug flag is %s.",
+                          NULL, NULL, &setdebuglist, &showdebuglist);
 }
This page took 0.033029 seconds and 4 git commands to generate.