* dwarf2-frame.c (dwarf2_frame_eh_frame_regnum): Rename to...
authorDaniel Jacobowitz <drow@false.org>
Tue, 27 Mar 2007 19:02:42 +0000 (19:02 +0000)
committerDaniel Jacobowitz <drow@false.org>
Tue, 27 Mar 2007 19:02:42 +0000 (19:02 +0000)
(dwarf2_frame_adjust_regnum): ...this.  Make static.  Add eh_frame_p
argument.  Update all callers.
(struct dwarf2_frame_ops): Replace eh_frame_regnum with adjust_regnum.
(dwarf2_frame_set_eh_frame_regnum): Rename to...
(dwarf2_frame_set_adjust_regnum): ...this.  Update argument type.
* dwarf2frame.h (dwarf2_frame_set_eh_frame_regnum): Rename to...
(dwarf2_frame_set_adjust_regnum): ...this.
(dwarf2_frame_eh_frame_regnum): Delete prototype.
* rs6000-tdep.c: Include "dwarf2-frame.h".
(rs6000_adjust_frame_regnum): Define.
(rs6000_gdbarch_init): Enable use of DWARF CFI frame unwinder.
Register rs6000_adjust_frame_regnum.

* Makefile.in (rs6000-tdep.o): Update dependencies.

gdb/ChangeLog
gdb/Makefile.in
gdb/dwarf2-frame.c
gdb/dwarf2-frame.h
gdb/rs6000-tdep.c

index b69d208..e8aa047 100644 (file)
@@ -1,3 +1,22 @@
+2007-03-27  Andreas Schwab  <schwab@suse.de>
+           Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * dwarf2-frame.c (dwarf2_frame_eh_frame_regnum): Rename to...
+       (dwarf2_frame_adjust_regnum): ...this.  Make static.  Add eh_frame_p
+       argument.  Update all callers.
+       (struct dwarf2_frame_ops): Replace eh_frame_regnum with adjust_regnum.
+       (dwarf2_frame_set_eh_frame_regnum): Rename to...
+       (dwarf2_frame_set_adjust_regnum): ...this.  Update argument type.
+       * dwarf2frame.h (dwarf2_frame_set_eh_frame_regnum): Rename to...
+       (dwarf2_frame_set_adjust_regnum): ...this.
+       (dwarf2_frame_eh_frame_regnum): Delete prototype.
+       * rs6000-tdep.c: Include "dwarf2-frame.h".
+       (rs6000_adjust_frame_regnum): Define.
+       (rs6000_gdbarch_init): Enable use of DWARF CFI frame unwinder.
+       Register rs6000_adjust_frame_regnum.
+
+       * Makefile.in (rs6000-tdep.o): Update dependencies.
+
 2007-03-27  Brooks Moses  <brooks.moses@codesourcery.com>
 
        * Makefile.in: Add support for a "pdf" target.
index 199715c..52e7bd5 100644 (file)
@@ -2586,7 +2586,7 @@ rs6000-tdep.o: rs6000-tdep.c $(defs_h) $(frame_h) $(inferior_h) $(symtab_h) \
        $(reggroups_h) $(libbfd_h) $(coff_internal_h) $(libcoff_h) \
        $(coff_xcoff_h) $(libxcoff_h) $(elf_bfd_h) $(solib_svr4_h) \
        $(ppc_tdep_h) $(gdb_assert_h) $(dis_asm_h) $(trad_frame_h) \
-       $(frame_unwind_h) $(frame_base_h) $(rs6000_tdep_h)
+       $(frame_unwind_h) $(frame_base_h) $(rs6000_tdep_h) $(dwarf2_frame_h)
 rs6000-aix-tdep.o: rs6000-aix-tdep.c $(defs_h) $(osabi_h) $(rs6000_tdep_h) \
        $(ppc_tdep_h)
 s390-nat.o: s390-nat.c $(defs_h) $(regcache_h) $(inferior_h) \
index be61a0e..1e1d395 100644 (file)
@@ -107,6 +107,9 @@ struct dwarf2_fde
 };
 
 static struct dwarf2_fde *dwarf2_frame_find_fde (CORE_ADDR *pc);
+
+static int dwarf2_frame_adjust_regnum (struct gdbarch *gdbarch, int regnum,
+                                      int eh_frame_p);
 \f
 
 /* Structure describing a frame state.  */
@@ -314,8 +317,7 @@ execute_cfa_program (gdb_byte *insn_ptr, gdb_byte *insn_end,
       else if ((insn & 0xc0) == DW_CFA_offset)
        {
          reg = insn & 0x3f;
-         if (eh_frame_p)
-           reg = dwarf2_frame_eh_frame_regnum (gdbarch, reg);
+         reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p);
          insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
          offset = utmp * fs->data_align;
          dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
@@ -326,8 +328,7 @@ execute_cfa_program (gdb_byte *insn_ptr, gdb_byte *insn_end,
        {
          gdb_assert (fs->initial.reg);
          reg = insn & 0x3f;
-         if (eh_frame_p)
-           reg = dwarf2_frame_eh_frame_regnum (gdbarch, reg);
+         reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p);
          dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
          if (reg < fs->initial.num_regs)
            fs->regs.reg[reg] = fs->initial.reg[reg];
@@ -368,8 +369,7 @@ register %s (#%d) at 0x%s"),
 
            case DW_CFA_offset_extended:
              insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
-             if (eh_frame_p)
-               reg = dwarf2_frame_eh_frame_regnum (gdbarch, reg);
+             reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p);
              insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
              offset = utmp * fs->data_align;
              dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
@@ -380,35 +380,30 @@ register %s (#%d) at 0x%s"),
            case DW_CFA_restore_extended:
              gdb_assert (fs->initial.reg);
              insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
-             if (eh_frame_p)
-               reg = dwarf2_frame_eh_frame_regnum (gdbarch, reg);
+             reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p);
              dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
              fs->regs.reg[reg] = fs->initial.reg[reg];
              break;
 
            case DW_CFA_undefined:
              insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
-             if (eh_frame_p)
-               reg = dwarf2_frame_eh_frame_regnum (gdbarch, reg);
+             reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p);
              dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
              fs->regs.reg[reg].how = DWARF2_FRAME_REG_UNDEFINED;
              break;
 
            case DW_CFA_same_value:
              insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
-             if (eh_frame_p)
-               reg = dwarf2_frame_eh_frame_regnum (gdbarch, reg);
+             reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p);
              dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
              fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAME_VALUE;
              break;
 
            case DW_CFA_register:
              insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
-             if (eh_frame_p)
-               reg = dwarf2_frame_eh_frame_regnum (gdbarch, reg);
+             reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p);
              insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
-             if (eh_frame_p)
-               utmp = dwarf2_frame_eh_frame_regnum (gdbarch, utmp);
+             utmp = dwarf2_frame_adjust_regnum (gdbarch, utmp, eh_frame_p);
              dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
              fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_REG;
              fs->regs.reg[reg].loc.reg = utmp;
@@ -456,9 +451,8 @@ bad CFI data; mismatched DW_CFA_restore_state at 0x%s"), paddr (fs->pc));
 
            case DW_CFA_def_cfa_register:
              insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->cfa_reg);
-             if (eh_frame_p)
-               fs->cfa_reg = dwarf2_frame_eh_frame_regnum (gdbarch,
-                                                           fs->cfa_reg);
+             fs->cfa_reg = dwarf2_frame_adjust_regnum (gdbarch, fs->cfa_reg,
+                                                       eh_frame_p);
              fs->cfa_how = CFA_REG_OFFSET;
              break;
 
@@ -484,8 +478,7 @@ bad CFI data; mismatched DW_CFA_restore_state at 0x%s"), paddr (fs->pc));
 
            case DW_CFA_expression:
              insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
-             if (eh_frame_p)
-               reg = dwarf2_frame_eh_frame_regnum (gdbarch, reg);
+             reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p);
              dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
              insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
              fs->regs.reg[reg].loc.exp = insn_ptr;
@@ -496,8 +489,7 @@ bad CFI data; mismatched DW_CFA_restore_state at 0x%s"), paddr (fs->pc));
 
            case DW_CFA_offset_extended_sf:
              insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
-             if (eh_frame_p)
-               reg = dwarf2_frame_eh_frame_regnum (gdbarch, reg);
+             reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p);
              insn_ptr = read_sleb128 (insn_ptr, insn_end, &offset);
              offset *= fs->data_align;
              dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
@@ -535,9 +527,8 @@ bad CFI data; mismatched DW_CFA_restore_state at 0x%s"), paddr (fs->pc));
 
            case DW_CFA_def_cfa_sf:
              insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->cfa_reg);
-             if (eh_frame_p)
-               fs->cfa_reg = dwarf2_frame_eh_frame_regnum (gdbarch,
-                                                           fs->cfa_reg);
+             fs->cfa_reg = dwarf2_frame_adjust_regnum (gdbarch, fs->cfa_reg,
+                                                       eh_frame_p);
              insn_ptr = read_sleb128 (insn_ptr, insn_end, &offset);
              fs->cfa_offset = offset * fs->data_align;
              fs->cfa_how = CFA_REG_OFFSET;
@@ -581,8 +572,7 @@ bad CFI data; mismatched DW_CFA_restore_state at 0x%s"), paddr (fs->pc));
 
            case DW_CFA_GNU_negative_offset_extended:
              insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
-             if (eh_frame_p)
-               reg = dwarf2_frame_eh_frame_regnum (gdbarch, reg);
+             reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p);
              insn_ptr = read_uleb128 (insn_ptr, insn_end, &offset);
              offset *= fs->data_align;
              dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
@@ -617,8 +607,9 @@ struct dwarf2_frame_ops
      trampoline.  */
   int (*signal_frame_p) (struct gdbarch *, struct frame_info *);
 
-  /* Convert .eh_frame register number to DWARF register number.  */
-  int (*eh_frame_regnum) (struct gdbarch *, int);
+  /* Convert .eh_frame register number to DWARF register number, or
+     adjust .debug_frame register number.  */
+  int (*adjust_regnum) (struct gdbarch *, int, int);
 };
 
 /* Default architecture-specific register state initialization
@@ -726,29 +717,30 @@ dwarf2_frame_signal_frame_p (struct gdbarch *gdbarch,
   return ops->signal_frame_p (gdbarch, next_frame);
 }
 
-/* Set the architecture-specific mapping of .eh_frame register numbers to
-   DWARF register numbers.  */
+/* Set the architecture-specific adjustment of .eh_frame and .debug_frame
+   register numbers.  */
 
 void
-dwarf2_frame_set_eh_frame_regnum (struct gdbarch *gdbarch,
-                                 int (*eh_frame_regnum) (struct gdbarch *,
-                                                         int))
+dwarf2_frame_set_adjust_regnum (struct gdbarch *gdbarch,
+                               int (*adjust_regnum) (struct gdbarch *,
+                                                     int, int))
 {
   struct dwarf2_frame_ops *ops = gdbarch_data (gdbarch, dwarf2_frame_data);
 
-  ops->eh_frame_regnum = eh_frame_regnum;
+  ops->adjust_regnum = adjust_regnum;
 }
 
-/* Translate a .eh_frame register to DWARF register.  */
+/* Translate a .eh_frame register to DWARF register, or adjust a .debug_frame
+   register.  */
 
-int
-dwarf2_frame_eh_frame_regnum (struct gdbarch *gdbarch, int regnum)
+static int
+dwarf2_frame_adjust_regnum (struct gdbarch *gdbarch, int regnum, int eh_frame_p)
 {
   struct dwarf2_frame_ops *ops = gdbarch_data (gdbarch, dwarf2_frame_data);
 
-  if (ops->eh_frame_regnum == NULL)
+  if (ops->adjust_regnum == NULL)
     return regnum;
-  return ops->eh_frame_regnum (gdbarch, regnum);
+  return ops->adjust_regnum (gdbarch, regnum, eh_frame_p);
 }
 
 static void
@@ -1726,10 +1718,10 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p)
       else
        cie->return_address_register = read_unsigned_leb128 (unit->abfd, buf,
                                                             &bytes_read);
-      if (eh_frame_p)
-       cie->return_address_register
-         = dwarf2_frame_eh_frame_regnum (current_gdbarch,
-                                         cie->return_address_register);
+      cie->return_address_register
+       = dwarf2_frame_adjust_regnum (current_gdbarch,
+                                     cie->return_address_register,
+                                     eh_frame_p);
 
       buf += bytes_read;
 
index a92a79d..862273b 100644 (file)
@@ -94,18 +94,13 @@ extern void
                                   int (*signal_frame_p) (struct gdbarch *,
                                                          struct frame_info *));
 
-/* Set the architecture-specific mapping of .eh_frame register numbers to
-   DWARF register numbers.  */
+/* Set the architecture-specific adjustment of .eh_frame and .debug_frame
+   register numbers.  */
 
 extern void
-  dwarf2_frame_set_eh_frame_regnum (struct gdbarch *gdbarch,
-                                   int (*eh_frame_regnum) (struct gdbarch *,
-                                                           int));
-
-/* Translate a .eh_frame register to DWARF register.  */
-
-extern int
-  dwarf2_frame_eh_frame_regnum (struct gdbarch *gdbarch, int regnum);
+  dwarf2_frame_set_adjust_regnum (struct gdbarch *gdbarch,
+                                 int (*adjust_regnum) (struct gdbarch *,
+                                                       int, int));
 
 /* Return the frame unwind methods for the function that contains PC,
    or NULL if it can't be handled by DWARF CFI frame unwinder.  */
index cc2f074..4319626 100644 (file)
@@ -40,6 +40,7 @@
 #include "sim-regno.h"
 #include "gdb/sim-ppc.h"
 #include "reggroups.h"
+#include "dwarf2-frame.h"
 
 #include "libbfd.h"            /* for bfd_default_set_arch_mach */
 #include "coff/internal.h"     /* for libcoff.h */
@@ -2294,6 +2295,69 @@ rs6000_dwarf2_reg_to_regnum (int num)
       }
 }
 
+/* Translate a .eh_frame register to DWARF register, or adjust a
+   .debug_frame register.  */
+
+static int
+rs6000_adjust_frame_regnum (struct gdbarch *gdbarch, int num, int eh_frame_p)
+{
+  /* GCC releases before 3.4 use GCC internal register numbering in
+     .debug_frame (and .debug_info, et cetera).  The numbering is
+     different from the standard SysV numbering for everything except
+     for GPRs and FPRs.  We can not detect this problem in most cases
+     - to get accurate debug info for variables living in lr, ctr, v0,
+     et cetera, use a newer version of GCC.  But we must detect
+     one important case - lr is in column 65 in .debug_frame output,
+     instead of 108.
+
+     GCC 3.4, and the "hammer" branch, have a related problem.  They
+     record lr register saves in .debug_frame as 108, but still record
+     the return column as 65.  We fix that up too.
+
+     We can do this because 65 is assigned to fpsr, and GCC never
+     generates debug info referring to it.  To add support for
+     handwritten debug info that restores fpsr, we would need to add a
+     producer version check to this.  */
+  if (!eh_frame_p)
+    {
+      if (num == 65)
+       return 108;
+      else
+       return num;
+    }
+
+  /* .eh_frame is GCC specific.  For binary compatibility, it uses GCC
+     internal register numbering; translate that to the standard DWARF2
+     register numbering.  */
+  if (0 <= num && num <= 63)   /* r0-r31,fp0-fp31 */
+    return num;
+  else if (68 <= num && num <= 75) /* cr0-cr8 */
+    return num - 68 + 86;
+  else if (77 <= num && num <= 108) /* vr0-vr31 */
+    return num - 77 + 1124;
+  else
+    switch (num)
+      {
+      case 64: /* mq */
+       return 100;
+      case 65: /* lr */
+       return 108;
+      case 66: /* ctr */
+       return 109;
+      case 76: /* xer */
+       return 101;
+      case 109: /* vrsave */
+       return 356;
+      case 110: /* vscr */
+       return 67;
+      case 111: /* spe_acc */
+       return 99;
+      case 112: /* spefscr */
+       return 612;
+      default:
+       return num;
+      }
+}
 \f
 /* Support for CONVERT_FROM_FUNC_PTR_ADDR (ARCH, ADDR, TARG).
 
@@ -3428,6 +3492,10 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     (gdbarch, rs6000_in_solib_return_trampoline);
   set_gdbarch_skip_trampoline_code (gdbarch, rs6000_skip_trampoline_code);
 
+  /* Hook in the DWARF CFI frame unwinder.  */
+  frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
+  dwarf2_frame_set_adjust_regnum (gdbarch, rs6000_adjust_frame_regnum);
+
   /* Hook in ABI-specific overrides, if they have been registered.  */
   gdbarch_init_osabi (info, gdbarch);