diff --git a/gdb.changes b/gdb.changes index 50195e8..059b910 100644 --- a/gdb.changes +++ b/gdb.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Mon Mar 12 18:07:07 CET 2007 - schwab@suse.de + +- Update ppc DWARF patch to also handle broken debug info from old + compilers. + ------------------------------------------------------------------- Thu Mar 8 15:04:28 CET 2007 - schwab@suse.de diff --git a/gdb.spec b/gdb.spec index db87072..a1d3cd3 100644 --- a/gdb.spec +++ b/gdb.spec @@ -21,7 +21,7 @@ Group: Development/Tools/Debuggers Autoreqprov: on PreReq: %{install_info_prereq} Version: 6.6 -Release: 16 +Release: 18 Summary: The GNU Debugger Source: gdb-%{version}.tar.bz2 Patch1: gdb-misc.patch @@ -74,7 +74,9 @@ Authors: %patch3 %patch4 %patch5 +cd gdb %patch7 +cd .. %patch8 %patch9 %patch10 @@ -145,6 +147,9 @@ rm -rf $RPM_BUILD_ROOT %endif %changelog +* Mon Mar 12 2007 - schwab@suse.de +- Update ppc DWARF patch to also handle broken debug info from old + compilers. * Thu Mar 08 2007 - schwab@suse.de - Deal with stepping over sequence of atomic insns [#154486]. * Wed Mar 07 2007 - schwab@suse.de diff --git a/ppc-dwarf2-cfi.patch b/ppc-dwarf2-cfi.patch index 6787b33..1584c01 100644 --- a/ppc-dwarf2-cfi.patch +++ b/ppc-dwarf2-cfi.patch @@ -1,16 +1,323 @@ ---- gdb/Makefile.in -+++ gdb/Makefile.in -@@ -2538,7 +2538,7 @@ +From nobody Mon Mar 12 17:19:12 2007 +From: Daniel Jacobowitz +Subject: Enable CFI for PowerPC, try 3 +To: gdb-patches@sourceware.org +Date: Mon, 12 Mar 2007 12:12:19 -0400 +Mail-Followup-To: gdb-patches@sourceware.org + +The last two times that we (Jim B, and then Andreas) tried to enable +PowerPC CFI, we ran into problems with GCC. It used to emit bogus +unwind tables. This has since been fixed - see the comment in the +patch below for the gory details - but if you get it wrong it's such a +messy and terrible outcome. So here's some workarounds. + ++ /* 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. */ + +I tested this, before and after, with GCC 3.3.6, 3.4.4, and 4.1.1. It +fixed 23, 24, and 25 failures respectively - most notably we can now +backtrace out of glibc in tls.exp. The others may be weaknesses in +the prologue analyzer - I didn't look deeply. + +I also verified that with CFI, but without the rest of the workaround, +GCC 3.4.4 is unhappy. + +Any comments? And would anyone else like to try this patch before I +check it in? + +-- +Daniel Jacobowitz +CodeSourcery + +2007-03-12 Andreas Schwab + Daniel Jacobowitz + + * 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. + +Index: Makefile.in +=================================================================== +RCS file: /home/gcc/repos/src/src/gdb/Makefile.in,v +retrieving revision 1.883 +diff -u -p -r1.883 Makefile.in +--- Makefile.in 2 Mar 2007 21:28:18 -0000 1.883 ++++ Makefile.in 12 Mar 2007 12:23:24 -0000 +@@ -2584,7 +2584,7 @@ rs6000-tdep.o: rs6000-tdep.c $(defs_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) - s390-nat.o: s390-nat.c $(defs_h) $(tm_h) $(regcache_h) $(inferior_h) \ + s390-nat.o: s390-nat.c $(defs_h) $(regcache_h) $(inferior_h) \ $(s390_tdep_h) $(target_h) $(linux_nat_h) ---- gdb/rs6000-tdep.c -+++ gdb/rs6000-tdep.c +Index: dwarf2-frame.c +=================================================================== +RCS file: /home/gcc/repos/src/src/gdb/dwarf2-frame.c,v +retrieving revision 1.68 +diff -u -p -r1.68 dwarf2-frame.c +--- dwarf2-frame.c 27 Feb 2007 20:17:18 -0000 1.68 ++++ dwarf2-frame.c 12 Mar 2007 13:36:31 -0000 +@@ -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, + 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_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, ®); +- 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, ®); +- 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, ®); +- 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, ®); +- 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, ®); +- 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_ + + 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_ + + case DW_CFA_expression: + insn_ptr = read_uleb128 (insn_ptr, insn_end, ®); +- 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_ + + case DW_CFA_offset_extended_sf: + insn_ptr = read_uleb128 (insn_ptr, insn_end, ®); +- 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_ + + 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; +@@ -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 gdba + 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 * + 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: dwarf2-frame.h +=================================================================== +RCS file: /home/gcc/repos/src/src/gdb/dwarf2-frame.h,v +retrieving revision 1.14 +diff -u -p -r1.14 dwarf2-frame.h +--- dwarf2-frame.h 9 Jan 2007 17:58:50 -0000 1.14 ++++ dwarf2-frame.h 12 Mar 2007 13:26:48 -0000 +@@ -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: rs6000-tdep.c +=================================================================== +RCS file: /home/gcc/repos/src/src/gdb/rs6000-tdep.c,v +retrieving revision 1.265 +diff -u -p -r1.265 rs6000-tdep.c +--- rs6000-tdep.c 27 Feb 2007 23:04:28 -0000 1.265 ++++ rs6000-tdep.c 12 Mar 2007 13:36:01 -0000 @@ -40,6 +40,7 @@ #include "sim-regno.h" #include "gdb/sim-ppc.h" @@ -19,14 +326,44 @@ #include "libbfd.h" /* for bfd_default_set_arch_mach */ #include "coff/internal.h" /* for libcoff.h */ -@@ -2243,6 +2244,40 @@ +@@ -2211,6 +2212,70 @@ e500_pseudo_register_read (struct gdbarc + } } - -+/* Convert a .eh_frame register number to a Dwarf 2 register number. */ ++/* Translate a .eh_frame register to DWARF register, or adjust a ++ .debug_frame register. */ ++ +static int -+rs6000_eh_frame_regnum (struct gdbarch *gdbarch, int num) ++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 */ @@ -57,17 +394,18 @@ + } +} + + static void rs6000_store_return_value (struct type *type, - struct regcache *regcache, -@@ -3461,6 +3496,10 @@ - /* Helpers for function argument information. */ - set_gdbarch_fetch_pointer_argument (gdbarch, rs6000_fetch_pointer_argument); +@@ -3471,6 +3536,10 @@ rs6000_gdbarch_init (struct gdbarch_info + (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_eh_frame_regnum (gdbarch, rs6000_eh_frame_regnum); ++ 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); +