diff --git a/gdb-6.6-cu-ranges.patch b/gdb-6.6-cu-ranges.patch new file mode 100644 index 0000000..bff659f --- /dev/null +++ b/gdb-6.6-cu-ranges.patch @@ -0,0 +1,422 @@ +2007-10-09 Jan Kratochvil + + * dwarf2read.c (dwarf2_get_pc_bounds): Moved the `DW_AT_ranges' parsing + code with its variables OBJFILE, CU_HEADER and OBFD into ... + (dwarf2_ranges_read): ... a new function. + (read_partial_die): Implemented the parsing of `DW_AT_ranges'. + +2007-10-09 Jan Kratochvil + + * gdb.dwarf2/dw2-ranges.S, gdb.dwarf2/dw2-ranges.exp, + gdb.dwarf2/dw2-ranges.lds: New files. + +--- ./gdb/dwarf2read.c 26 Sep 2007 13:59:54 -0000 1.232 ++++ ./gdb/dwarf2read.c 9 Oct 2007 15:03:09 -0000 +@@ -3075,6 +3075,124 @@ read_lexical_block_scope (struct die_inf + local_symbols = new->locals; + } + ++/* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET. ++ Return 1 if the attributes are present and valid, otherwise, return 0. */ ++ ++static int ++dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return, ++ CORE_ADDR *high_return, struct dwarf2_cu *cu) ++{ ++ struct objfile *objfile = cu->objfile; ++ struct comp_unit_head *cu_header = &cu->header; ++ bfd *obfd = objfile->obfd; ++ unsigned int addr_size = cu_header->addr_size; ++ CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1)); ++ /* Base address selection entry. */ ++ CORE_ADDR base; ++ int found_base; ++ unsigned int dummy; ++ gdb_byte *buffer; ++ CORE_ADDR marker; ++ int low_set; ++ CORE_ADDR low = 0; ++ CORE_ADDR high = 0; ++ ++ found_base = cu_header->base_known; ++ base = cu_header->base_address; ++ ++ if (offset >= dwarf2_per_objfile->ranges_size) ++ { ++ complaint (&symfile_complaints, ++ _("Offset %d out of bounds for DW_AT_ranges attribute"), ++ offset); ++ return 0; ++ } ++ buffer = dwarf2_per_objfile->ranges_buffer + offset; ++ ++ /* Read in the largest possible address. */ ++ marker = read_address (obfd, buffer, cu, &dummy); ++ if ((marker & mask) == mask) ++ { ++ /* If we found the largest possible address, then ++ read the base address. */ ++ base = read_address (obfd, buffer + addr_size, cu, &dummy); ++ buffer += 2 * addr_size; ++ offset += 2 * addr_size; ++ found_base = 1; ++ } ++ ++ low_set = 0; ++ ++ while (1) ++ { ++ CORE_ADDR range_beginning, range_end; ++ ++ range_beginning = read_address (obfd, buffer, cu, &dummy); ++ buffer += addr_size; ++ range_end = read_address (obfd, buffer, cu, &dummy); ++ buffer += addr_size; ++ offset += 2 * addr_size; ++ ++ /* An end of list marker is a pair of zero addresses. */ ++ if (range_beginning == 0 && range_end == 0) ++ /* Found the end of list entry. */ ++ break; ++ ++ /* Each base address selection entry is a pair of 2 values. ++ The first is the largest possible address, the second is ++ the base address. Check for a base address here. */ ++ if ((range_beginning & mask) == mask) ++ { ++ /* If we found the largest possible address, then ++ read the base address. */ ++ base = read_address (obfd, buffer + addr_size, cu, &dummy); ++ found_base = 1; ++ continue; ++ } ++ ++ if (!found_base) ++ { ++ /* We have no valid base address for the ranges ++ data. */ ++ complaint (&symfile_complaints, ++ _("Invalid .debug_ranges data (no base address)")); ++ return 0; ++ } ++ ++ range_beginning += base; ++ range_end += base; ++ ++ /* FIXME: This is recording everything as a low-high ++ segment of consecutive addresses. We should have a ++ data structure for discontiguous block ranges ++ instead. */ ++ if (! low_set) ++ { ++ low = range_beginning; ++ high = range_end; ++ low_set = 1; ++ } ++ else ++ { ++ if (range_beginning < low) ++ low = range_beginning; ++ if (range_end > high) ++ high = range_end; ++ } ++ } ++ ++ if (! low_set) ++ /* If the first entry is an end-of-list marker, the range ++ describes an empty scope, i.e. no instructions. */ ++ return 0; ++ ++ if (low_return) ++ *low_return = low; ++ if (high_return) ++ *high_return = high; ++ return 1; ++} ++ + /* Get low and high pc attributes from a die. Return 1 if the attributes + are present and valid, otherwise, return 0. Return -1 if the range is + discontinuous, i.e. derived from DW_AT_ranges information. */ +@@ -3082,10 +3200,7 @@ static int + dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, + CORE_ADDR *highpc, struct dwarf2_cu *cu) + { +- struct objfile *objfile = cu->objfile; +- struct comp_unit_head *cu_header = &cu->header; + struct attribute *attr; +- bfd *obfd = objfile->obfd; + CORE_ADDR low = 0; + CORE_ADDR high = 0; + int ret = 0; +@@ -3109,108 +3224,11 @@ dwarf2_get_pc_bounds (struct die_info *d + attr = dwarf2_attr (die, DW_AT_ranges, cu); + if (attr != NULL) + { +- unsigned int addr_size = cu_header->addr_size; +- CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1)); + /* Value of the DW_AT_ranges attribute is the offset in the + .debug_ranges section. */ +- unsigned int offset = DW_UNSND (attr); +- /* Base address selection entry. */ +- CORE_ADDR base; +- int found_base; +- unsigned int dummy; +- gdb_byte *buffer; +- CORE_ADDR marker; +- int low_set; +- +- found_base = cu_header->base_known; +- base = cu_header->base_address; +- +- if (offset >= dwarf2_per_objfile->ranges_size) +- { +- complaint (&symfile_complaints, +- _("Offset %d out of bounds for DW_AT_ranges attribute"), +- offset); +- return 0; +- } +- buffer = dwarf2_per_objfile->ranges_buffer + offset; +- +- /* Read in the largest possible address. */ +- marker = read_address (obfd, buffer, cu, &dummy); +- if ((marker & mask) == mask) +- { +- /* If we found the largest possible address, then +- read the base address. */ +- base = read_address (obfd, buffer + addr_size, cu, &dummy); +- buffer += 2 * addr_size; +- offset += 2 * addr_size; +- found_base = 1; +- } +- +- low_set = 0; +- +- while (1) +- { +- CORE_ADDR range_beginning, range_end; +- +- range_beginning = read_address (obfd, buffer, cu, &dummy); +- buffer += addr_size; +- range_end = read_address (obfd, buffer, cu, &dummy); +- buffer += addr_size; +- offset += 2 * addr_size; +- +- /* An end of list marker is a pair of zero addresses. */ +- if (range_beginning == 0 && range_end == 0) +- /* Found the end of list entry. */ +- break; +- +- /* Each base address selection entry is a pair of 2 values. +- The first is the largest possible address, the second is +- the base address. Check for a base address here. */ +- if ((range_beginning & mask) == mask) +- { +- /* If we found the largest possible address, then +- read the base address. */ +- base = read_address (obfd, buffer + addr_size, cu, &dummy); +- found_base = 1; +- continue; +- } +- +- if (!found_base) +- { +- /* We have no valid base address for the ranges +- data. */ +- complaint (&symfile_complaints, +- _("Invalid .debug_ranges data (no base address)")); +- return 0; +- } +- +- range_beginning += base; +- range_end += base; +- +- /* FIXME: This is recording everything as a low-high +- segment of consecutive addresses. We should have a +- data structure for discontiguous block ranges +- instead. */ +- if (! low_set) +- { +- low = range_beginning; +- high = range_end; +- low_set = 1; +- } +- else +- { +- if (range_beginning < low) +- low = range_beginning; +- if (range_end > high) +- high = range_end; +- } +- } +- +- if (! low_set) +- /* If the first entry is an end-of-list marker, the range +- describes an empty scope, i.e. no instructions. */ ++ if (!dwarf2_ranges_read (DW_UNSND (attr), &low, &high, cu)) + return 0; +- ++ /* Found discontinuous range of addresses. */ + ret = -1; + } + } +@@ -5571,6 +5589,11 @@ read_partial_die (struct partial_die_inf + has_high_pc_attr = 1; + part_die->highpc = DW_ADDR (&attr); + break; ++ case DW_AT_ranges: ++ if (dwarf2_ranges_read (DW_UNSND (&attr), &part_die->lowpc, ++ &part_die->highpc, cu)) ++ has_low_pc_attr = has_high_pc_attr = 1; ++ break; + case DW_AT_location: + /* Support the .debug_loc offsets */ + if (attr_form_is_block (&attr)) +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.dwarf2/dw2-ranges.S 9 Oct 2007 15:03:10 -0000 +@@ -0,0 +1,33 @@ ++/* ++ Copyright 2007 Free Software Foundation, Inc. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . ++ */ ++ ++ .text ++ ++ .section .text._start, "ax", @progbits ++ .globl _start ++ .func _start ++_start: call func ++ .endfunc ++ .size _start, . - _start ++ ++ .section .text.func, "ax", @progbits ++ .globl func ++ .func func ++func: int3 ++ nop ++ .endfunc ++ .size func, . - func +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.dwarf2/dw2-ranges.exp 9 Oct 2007 15:03:10 -0000 +@@ -0,0 +1,82 @@ ++# Copyright 2007 Free Software Foundation, Inc. ++ ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++# Test DW_TAG_compile_unit with no children and with neither DW_AT_low_pc nor ++# DW_AT_high_pc but with DW_AT_ranges instead. We created the hole there for ++# DW_AT_ranges by the linker script. ++ ++# This test can only be run on targets which support DWARF-2 and use gas. ++# For now pick a sampling of likely targets. ++if {![istarget *-*-linux*] ++ && ![istarget *-*-gnu*] ++ && ![istarget *-*-elf*] ++ && ![istarget *-*-openbsd*] ++ && ![istarget arm-*-eabi*] ++ && ![istarget powerpc-*-eabi*]} { ++ verbose "Skipping i386/amd64 DW_AT_ranges test." ++ return 0 ++} ++if { ![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"] } then { ++ verbose "Skipping i386/amd64 DW_AT_ranges test." ++ return 0 ++} ++ ++set testfile "dw2-ranges" ++set srcfile ${testfile}.S ++set ldsfile ${testfile}.lds ++set binfile ${objdir}/${subdir}/${testfile} ++ ++# Avoid `-lm' from `lib/ada.exp' as it would fail with out `-nostdlib'. ++# Provide BOARD for SET_BOARD_INFO. ++set board [target_info name] ++set_board_info mathlib "" ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "additional_flags=-Wl,--script=${srcdir}/${subdir}/${ldsfile} -nostdlib"]] != "" } { ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++# Former wrong output: ++# Program received signal SIGTRAP, Trace/breakpoint trap. ++# 0x000000000000002b in func () ++# (gdb) bt ++# #0 0x000000000000002b in func () ++# #1 0x0000000000000029 in _start () ++# (gdb) _ ++# Correct output: ++# Program received signal SIGTRAP, Trace/breakpoint trap. ++# func () at dw2-ranges.S:14 ++# 14 nop ++# Current language: auto; currently asm ++# (gdb) bt ++# #0 func () at dw2-ranges.S:14 ++# #1 0x0000000000000029 in _start () at dw2-ranges.S:6 ++# (gdb) _ ++# The entry #1 is missing on i386. ++# "#0 +func \\(\\) at .*dw2-ranges.S:\[0-9\]+\r\n#1 .*in _start \\(\\) at .*dw2-ranges.S:\[0-9\]+" ++ ++gdb_run_cmd ++set test "run" ++gdb_test_multiple "" "$test" { ++ -re "Program received signal SIGTRAP,.*$gdb_prompt $" { ++ pass $test ++ } ++} ++ ++gdb_test "backtrace" "#0 +func \\(\\) at .*dw2-ranges.S:\[0-9\]+" +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.dwarf2/dw2-ranges.lds 9 Oct 2007 15:03:10 -0000 +@@ -0,0 +1,25 @@ ++/* ++ Copyright 2007 Free Software Foundation, Inc. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . ++ */ ++ ++SECTIONS ++{ ++ .text._start : { *(.text._start) } ++ /* Create the hole. */ ++ . = . + 1; ++ .text.func : { *(.text.func) } ++} ++ENTRY(_start) diff --git a/gdb.spec b/gdb.spec index 662e0fc..2c16ef1 100644 --- a/gdb.spec +++ b/gdb.spec @@ -11,7 +11,7 @@ Name: gdb Version: 6.6 # The release always contains a leading reserved number, start it at 1. -Release: 32%{?dist} +Release: 33%{?dist} License: GPL Group: Development/Debuggers @@ -380,6 +380,9 @@ Patch276: gdb-6.6-bfd-vdso8k.patch # Fixed the kernel i386-on-x86_64 VDSO loading (producing `Lowest section in'). Patch277: gdb-6.6-vdso-i386-on-amd64-warning.patch +# Fix debug load for sparse assembler files (such as vDSO32 for i386-on-x86_64). +Patch278: gdb-6.6-cu-ranges.patch + BuildRequires: ncurses-devel glibc-devel gcc make gzip texinfo dejagnu gettext BuildRequires: flex bison sharutils expat-devel Requires: readline @@ -537,6 +540,7 @@ rm -f gdb/jv-exp.c gdb/m2-exp.c gdb/objc-exp.c gdb/p-exp.c %patch274 -p1 %patch276 -p1 %patch277 -p1 +%patch278 -p1 # Change the version that gets printed at GDB startup, so it is RedHat # specific. @@ -693,6 +697,9 @@ fi # don't include the files in include, they are part of binutils %changelog +* Tue Oct 9 2007 Jan Kratochvil - 6.6-33 +- Fix debug load for sparse assembler files (such as vDSO32 for i386-on-x86_64). + * Mon Oct 8 2007 Jan Kratochvil - 6.6-32 - Set the breakpoints always to all the ctors/dtors variants (BZ 301701). - Fix a TUI visual corruption due to the build-id warnings (BZ 320061).