aboutsummaryrefslogtreecommitdiff
path: root/gdb/rs6000-tdep.c
diff options
context:
space:
mode:
authorDaniel Jacobowitz <drow@false.org>2007-03-27 19:02:42 +0000
committerDaniel Jacobowitz <drow@false.org>2007-03-27 19:02:42 +0000
commit4fc771b8c4b03069118fcfcea6c9385b592e8098 (patch)
tree9cfb45a80d8d8d2eb8fd2da4d0066a958db69439 /gdb/rs6000-tdep.c
parent1f81bd395c9103c6f44e8b18a90961a039aac25c (diff)
downloadgdb-4fc771b8c4b03069118fcfcea6c9385b592e8098.zip
gdb-4fc771b8c4b03069118fcfcea6c9385b592e8098.tar.gz
gdb-4fc771b8c4b03069118fcfcea6c9385b592e8098.tar.bz2
* 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.
Diffstat (limited to 'gdb/rs6000-tdep.c')
-rw-r--r--gdb/rs6000-tdep.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index cc2f074..4319626 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);