summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog19
-rw-r--r--gdb/Makefile.in2
-rw-r--r--gdb/dwarf2-frame.c82
-rw-r--r--gdb/dwarf2-frame.h15
-rw-r--r--gdb/rs6000-tdep.c68
5 files changed, 130 insertions, 56 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index b69d208eb31..e8aa047ed9d 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 199715c2097..52e7bd5e0a8 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -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) \
diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
index be61a0eca89..1e1d395e870 100644
--- a/gdb/dwarf2-frame.c
+++ b/gdb/dwarf2-frame.c
@@ -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);
/* 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;
diff --git a/gdb/dwarf2-frame.h b/gdb/dwarf2-frame.h
index a92a79d244a..862273ba857 100644
--- a/gdb/dwarf2-frame.h
+++ b/gdb/dwarf2-frame.h
@@ -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. */
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index cc2f074121b..4319626da32 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -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;
+ }
+}
/* 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);