2004-05-17 Andrew Cagney <cagney@redhat.com>
[deliverable/binutils-gdb.git] / gdb / hppa-linux-tdep.c
index bdcb4a7455af3de4451b40feab02fea26e29b3a3..8f3c632a152e7b8d8e2be1c6bf54425351894f25 100644 (file)
@@ -42,7 +42,7 @@ hppa_dwarf_reg_to_regnum (int reg)
 
   /* dwarf regs 32 to 85 are fpregs 4 - 31 */
   if (reg >= 32 && reg <= 85)
-    return FP4_REGNUM + (reg - 32);
+    return HPPA_FP4_REGNUM + (reg - 32);
 
   warning ("Unmapped DWARF Register #%d encountered\n", reg);
   return -1;
@@ -53,8 +53,8 @@ static void
 hppa_linux_target_write_pc (CORE_ADDR v, ptid_t ptid)
 {
   /* Probably this should be done by the kernel, but it isn't.  */
-  write_register_pid (PCOQ_HEAD_REGNUM, v | 0x3, ptid);
-  write_register_pid (PCOQ_TAIL_REGNUM, (v + 4) | 0x3, ptid);
+  write_register_pid (HPPA_PCOQ_HEAD_REGNUM, v | 0x3, ptid);
+  write_register_pid (HPPA_PCOQ_TAIL_REGNUM, (v + 4) | 0x3, ptid);
 }
 
 /* An instruction to match.  */
@@ -146,7 +146,10 @@ insns_match_pattern (CORE_ADDR pc,
 
   for (i = 0; pattern[i].mask; i++)
     {
-      insn[i] = read_memory_unsigned_integer (npc, 4);
+      char buf[4];
+
+      read_memory_nobpt (npc, buf, 4);
+      insn[i] = extract_unsigned_integer (buf, 4);
       if ((insn[i] & pattern[i].mask) == pattern[i].data)
         npc += 4;
       else
@@ -282,7 +285,7 @@ hppa_linux_skip_trampoline_code (CORE_ADDR pc)
    Note that with a 2.4 64-bit kernel, the signal context is not properly
    passed back to userspace so the unwind will not work correctly.  */
 static CORE_ADDR
-hppa_linux_sigtramp_find_sigcontext (CORE_ADDR sp)
+hppa_linux_sigtramp_find_sigcontext (CORE_ADDR pc)
 {
   unsigned int dummy[HPPA_MAX_INSN_PATTERN_LEN];
   int offs = 0;
@@ -291,6 +294,12 @@ hppa_linux_sigtramp_find_sigcontext (CORE_ADDR sp)
   static int pcoffs[] = { 0, 4*4, 5*4 };
   /* offsets to the rt_sigframe structure */
   static int sfoffs[] = { 4*4, 10*4, 10*4 };
+  CORE_ADDR sp;
+
+  /* Most of the time, this will be correct.  The one case when this will
+     fail is if the user defined an alternate stack, in which case the
+     beginning of the stack will not be align_down (pc, 64).  */
+  sp = align_down (pc, 64);
 
   /* rt_sigreturn trampoline:
      3419000x ldi 0, %r25 or ldi 1, %r25   (x = 0 or 2)
@@ -308,7 +317,20 @@ hppa_linux_sigtramp_find_sigcontext (CORE_ADDR sp)
     }
 
   if (offs == 0)
-    return 0;
+    {
+      if (insns_match_pattern (pc, hppa_sigtramp, dummy))
+       {
+         /* sigaltstack case: we have no way of knowing which offset to 
+            use in this case; default to new kernel handling. If this is
+            wrong the unwinding will fail.  */
+         try = 2;
+         sp = pc - pcoffs[try];
+       }
+      else
+      {
+        return 0;
+      }
+    }
 
   /* sp + sfoffs[try] points to a struct rt_sigframe, which contains
      a struct siginfo and a struct ucontext.  struct ucontext contains
@@ -331,7 +353,7 @@ hppa_linux_sigtramp_frame_unwind_cache (struct frame_info *next_frame,
 {
   struct gdbarch *gdbarch = get_frame_arch (next_frame);
   struct hppa_linux_sigtramp_unwind_cache *info;
-  CORE_ADDR sp, pc, scptr;
+  CORE_ADDR pc, scptr;
   int i;
 
   if (*this_cache)
@@ -342,8 +364,7 @@ hppa_linux_sigtramp_frame_unwind_cache (struct frame_info *next_frame,
   info->saved_regs = trad_frame_alloc_saved_regs (next_frame);
 
   pc = frame_pc_unwind (next_frame);
-  sp = (pc & ~63);
-  scptr = hppa_linux_sigtramp_find_sigcontext (sp);
+  scptr = hppa_linux_sigtramp_find_sigcontext (pc);
 
   /* structure of struct sigcontext:
    
@@ -364,7 +385,7 @@ hppa_linux_sigtramp_frame_unwind_cache (struct frame_info *next_frame,
   /* General registers.  */
   for (i = 1; i < 32; i++)
     {
-      info->saved_regs[R0_REGNUM + i].addr = scptr;
+      info->saved_regs[HPPA_R0_REGNUM + i].addr = scptr;
       scptr += 4;
     }
 
@@ -383,18 +404,17 @@ hppa_linux_sigtramp_frame_unwind_cache (struct frame_info *next_frame,
     }
 
   /* IASQ/IAOQ. */
-  info->saved_regs[PCSQ_HEAD_REGNUM].addr = scptr;
+  info->saved_regs[HPPA_PCSQ_HEAD_REGNUM].addr = scptr;
   scptr += 4;
-  info->saved_regs[PCSQ_TAIL_REGNUM].addr = scptr;
+  info->saved_regs[HPPA_PCSQ_TAIL_REGNUM].addr = scptr;
   scptr += 4;
 
-  info->saved_regs[PCOQ_HEAD_REGNUM].addr = scptr;
+  info->saved_regs[HPPA_PCOQ_HEAD_REGNUM].addr = scptr;
   scptr += 4;
-  info->saved_regs[PCOQ_TAIL_REGNUM].addr = scptr;
+  info->saved_regs[HPPA_PCOQ_TAIL_REGNUM].addr = scptr;
   scptr += 4;
 
-  info->base = read_memory_unsigned_integer (
-                 info->saved_regs[HPPA_SP_REGNUM].addr, 4);
+  info->base = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM);
 
   return info;
 }
@@ -415,21 +435,12 @@ hppa_linux_sigtramp_frame_prev_register (struct frame_info *next_frame,
                                         int regnum, int *optimizedp,
                                         enum lval_type *lvalp, 
                                         CORE_ADDR *addrp,
-                                        int *realnump, void *bufferp)
+                                        int *realnump, void *valuep)
 {
   struct hppa_linux_sigtramp_unwind_cache *info
     = hppa_linux_sigtramp_frame_unwind_cache (next_frame, this_prologue_cache);
-  int pcoqt = (regnum == PCOQ_TAIL_REGNUM);
-
-  if (pcoqt)
-    regnum = PCOQ_HEAD_REGNUM;
-
-  trad_frame_prev_register (next_frame, info->saved_regs, regnum,
-                            optimizedp, lvalp, addrp, realnump, bufferp);
-
-  if (pcoqt)
-    store_unsigned_integer (bufferp, 4, 
-                           extract_unsigned_integer (bufferp, 4) + 4);
+  hppa_frame_prev_register_helper (next_frame, info->saved_regs, regnum,
+                                  optimizedp, lvalp, addrp, realnump, valuep);
 }
 
 static const struct frame_unwind hppa_linux_sigtramp_frame_unwind = {
@@ -448,9 +459,8 @@ static const struct frame_unwind *
 hppa_linux_sigtramp_unwind_sniffer (struct frame_info *next_frame)
 {
   CORE_ADDR pc = frame_pc_unwind (next_frame);
-  CORE_ADDR sp = (pc & ~63);
 
-  if (hppa_linux_sigtramp_find_sigcontext (sp))
+  if (hppa_linux_sigtramp_find_sigcontext (pc))
     return &hppa_linux_sigtramp_frame_unwind;
 
   return NULL;
This page took 0.025774 seconds and 4 git commands to generate.