This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] Fix overlapping objfiles with discontiguous CUs (PR 13346) [Re: Multiple breakpoint issue when debugging loadable kernel module]


On Tue, 01 Nov 2011 21:12:47 +0100, Jan Kratochvil wrote:
> On Tue, 01 Nov 2011 16:31:29 +0100, Jan Kiszka wrote:
> > (gdb) b ieee80211_register_hw
> > Breakpoint 1 at 0xffffffffa01b31a0: file /data/linux/net/mac80211/main.c, line 646.
> > (gdb) l ieee80211_register_hw
> > No line number known for ieee80211_register_hw.
[...]
> 	https://bugzilla.redhat.com/show_bug.cgi?id=714824#c6
> 
> Sure it also may be a completely different bug and it may really be in GDB.

That was unrelated bug.


find_pc_sect_psymtab tries hard to properly recognize discontiguous CUs and
fallback to the old TEXTLOW/TEXTHIGH method only if there is no other choice.

The problem is the fallback happens already for a single objfile.  In the case
Linux kernel case there is overlapping vmlinux with module.ko as vmlinux spans
from the code at 0xffffffff81000000 to vDSOs at 0xffffffffff600000 while
kernel modules are between these.

The fallback really should not be needed for DWARF psymtabs.  Skip it.

No regressions on {x86_64,x86_64-m32,i686}-fedora16pre-linux-gnu.


Thanks,
Jan


gdb/
2011-11-08  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* dwarf2read.c (process_psymtab_comp_unit): Set
	PSYMTABS_ADDRMAP_SUPPORTED.
	* psympriv.h (struct partial_symtab): Comment textlow and texthigh
	validity.  New field psymtabs_addrmap_supported.
	* psymtab.c (find_pc_sect_psymtab_closer): New gdb_assert on
	psymtabs_addrmap_supported.
	(find_pc_sect_psymtab): Do not fallback to TEXTLOW and TEXTHIGH for
	!PSYMTABS_ADDRMAP_SUPPORTED.
	(dump_psymtab, maintenance_info_psymtabs): Print also
	psymtabs_addrmap_supported.

gdb/testsuite/
2011-11-08  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* gdb.dwarf2/dw2-objfile-overlap-inner.S: New file.
	* gdb.dwarf2/dw2-objfile-overlap-outer.S: New file.
	* gdb.dwarf2/dw2-objfile-overlap.exp: New file.

--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -3445,6 +3445,7 @@ process_psymtab_comp_unit (struct objfile *objfile,
 			      0,
 			      objfile->global_psymbols.next,
 			      objfile->static_psymbols.next);
+  pst->psymtabs_addrmap_supported = 1;
 
   attr = dwarf2_attr (comp_unit_die, DW_AT_comp_dir, &cu);
   if (attr != NULL)
--- a/gdb/psympriv.h
+++ b/gdb/psympriv.h
@@ -92,7 +92,8 @@ struct partial_symtab
   struct section_offsets *section_offsets;
 
   /* Range of text addresses covered by this file; texthigh is the
-     beginning of the next section.  */
+     beginning of the next section.  Do not use if PSYMTABS_ADDRMAP_SUPPORTED
+     is set.  */
 
   CORE_ADDR textlow;
   CORE_ADDR texthigh;
@@ -135,6 +136,12 @@ struct partial_symtab
 
   unsigned char readin;
 
+  /* True iff objfile->psymtabs_addrmap is properly populated for this
+     partial_symtab.  For discontiguous overlapping psymtabs is the only usable
+     info in PSYMTABS_ADDRMAP.  */
+
+  unsigned char psymtabs_addrmap_supported;
+
   /* Pointer to symtab eventually allocated for this source file, 0 if
      !readin or if we haven't looked for the symtab after it was readin.  */
 
--- a/gdb/psymtab.c
+++ b/gdb/psymtab.c
@@ -214,6 +214,8 @@ find_pc_sect_psymtab_closer (CORE_ADDR pc, struct obj_section *section,
   struct partial_symtab *best_pst = pst;
   CORE_ADDR best_addr = pst->textlow;
 
+  gdb_assert (!pst->psymtabs_addrmap_supported);
+
   /* An objfile that has its functions reordered might have
      many partial symbol tables containing the PC, but
      we want the partial symbol table that contains the
@@ -337,7 +339,8 @@ find_pc_sect_psymtab (struct objfile *objfile, CORE_ADDR pc,
      debug info type in single OBJFILE.  */
 
   ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, pst)
-    if (pc >= pst->textlow && pc < pst->texthigh)
+    if (!pst->psymtabs_addrmap_supported
+	&& pc >= pst->textlow && pc < pst->texthigh)
       {
 	struct partial_symtab *best_pst;
 
@@ -969,6 +972,8 @@ dump_psymtab (struct objfile *objfile, struct partial_symtab *psymtab,
   fprintf_filtered (outfile, "-");
   fputs_filtered (paddress (gdbarch, psymtab->texthigh), outfile);
   fprintf_filtered (outfile, "\n");
+  fprintf_filtered (outfile, "  Address map supported - %s.\n",
+		    psymtab->psymtabs_addrmap_supported ? "yes" : "no");
   fprintf_filtered (outfile, "  Depends on %d other partial symtabs.\n",
 		    psymtab->number_of_dependencies);
   for (i = 0; i < psymtab->number_of_dependencies; i++)
@@ -1765,6 +1770,9 @@ maintenance_info_psymtabs (char *regexp, int from_tty)
 	      fputs_filtered (paddress (gdbarch, psymtab->texthigh),
 			      gdb_stdout);
 	      printf_filtered ("\n");
+	      printf_filtered ("    psymtabs_addrmap_supported %s\n",
+			       (psymtab->psymtabs_addrmap_supported
+				? "yes" : "no"));
 	      printf_filtered ("    globals ");
 	      if (psymtab->n_global_syms)
 		{
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-objfile-overlap-inner.S
@@ -0,0 +1,177 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2011 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 <http://www.gnu.org/licenses/>.  */
+
+	.text
+
+	.globl _start
+_start:
+
+	.globl inner
+	.type inner, %function
+inner:
+.Lbegin_inner:
+	.int 0
+.Lend_inner:
+	.size inner, . - inner
+
+/* Debug information */
+
+	.section .debug_info
+.Lcu1_begin:
+	/* CU header */
+	.4byte	.Lcu1_end - .Lcu1_start		/* Length of Compilation Unit */
+.Lcu1_start:
+	.2byte	2				/* DWARF Version */
+	.4byte	.Labbrev1_begin			/* Offset into abbrev section */
+	.byte	4				/* Pointer size */
+
+	/* CU die */
+	.uleb128 1				/* Abbrev: DW_TAG_compile_unit */
+	.4byte	.Lline1_begin			/* DW_AT_stmt_list */
+	.4byte	.Ldebug_ranges			/* DW_AT_ranges */
+	.ascii	"inner.c\0"			/* DW_AT_name */
+        .ascii  "/tmp\0"			/* DW_AT_comp_dir */
+	.ascii	"GNU C 3.3.3\0"			/* DW_AT_producer */
+	.byte	1				/* DW_AT_language (C) */
+
+	/* inner */
+	.uleb128	2			/* Abbrev: DW_TAG_subprogram */
+	.byte		1			/* DW_AT_external */
+	.byte		1			/* DW_AT_decl_file */
+	.byte		1			/* DW_AT_decl_line */
+	.ascii		"inner\0"		/* DW_AT_name */
+	.4byte		.Lbegin_inner		/* DW_AT_low_pc */
+	.4byte		.Lend_inner		/* DW_AT_high_pc */
+
+	.byte		0			/* End of children of CU */
+
+.Lcu1_end:
+
+/* DW_AT_ranges.  */
+	.section	.debug_ranges
+.Ldebug_ranges:
+	.4byte	.Lbegin_inner
+	.4byte	.Lend_inner
+	.4byte	0
+	.4byte	0
+
+/* Abbrev table */
+	.section .debug_abbrev
+.Labbrev1_begin:
+	.uleb128	1			/* Abbrev code */
+	.uleb128	0x11			/* DW_TAG_compile_unit */
+	.byte		1			/* has_children */
+	.uleb128	0x10			/* DW_AT_stmt_list */
+	.uleb128	0x6			/* DW_FORM_data4 */
+	.uleb128	0x55			/* DW_AT_ranges */
+	.uleb128	0x6			/* DW_FORM_data4 */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128        0x1b                    /* DW_AT_comp_dir */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x25			/* DW_AT_producer */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x13			/* DW_AT_language */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	2			/* Abbrev code */
+	.uleb128	0x2e			/* DW_TAG_subprogram */
+	.byte		0			/* has_children */
+	.uleb128	0x3f			/* DW_AT_external */
+	.uleb128	0xc			/* DW_FORM_flag */
+	.uleb128	0x3a			/* DW_AT_decl_file */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.uleb128	0x3b			/* DW_AT_decl_line */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x11			/* DW_AT_low_pc */
+	.uleb128	0x1			/* DW_FORM_addr */
+	.uleb128	0x12			/* DW_AT_high_pc */
+	.uleb128	0x1			/* DW_FORM_addr */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+/* Line table */
+	.section .debug_line
+.Lline1_begin:
+	.4byte		.Lline1_end - .Lline1_start	/* Initial length */
+.Lline1_start:
+	.2byte		2			/* Version */
+	.4byte		.Lline1_lines - .Lline1_hdr	/* header_length */
+.Lline1_hdr:
+	.byte		1			/* Minimum insn length */
+	.byte		1			/* default_is_stmt */
+	.byte		1			/* line_base */
+ 	.byte		1			/* line_range */
+	.byte		0x10			/* opcode_base */
+
+	/* Standard lengths */
+	.byte		0
+	.byte		1
+	.byte		1
+	.byte		1
+	.byte		1
+	.byte		0
+	.byte		0
+	.byte		0
+	.byte		1
+	.byte		0
+	.byte		0
+	.byte		1
+	.byte		0
+	.byte		0
+	.byte		0
+
+	/* Include directories */
+        .ascii  "/tmp\0"
+	.byte		0
+
+	/* File names */
+	.ascii		"inner.c\0"
+	.uleb128	1
+	.uleb128	0
+	.uleb128	0
+
+	.byte		0
+
+.Lline1_lines:
+	.byte		0	/* DW_LNE_set_address */
+	.uleb128	5
+	.byte		2
+	.4byte		.Lbegin_inner
+
+	.byte		3	/* DW_LNS_advance_line */
+	.sleb128	1	/* ... to 2 */
+
+	.byte		1	/* DW_LNS_copy */
+
+	.byte		0	/* DW_LNE_set_address */
+	.uleb128	5
+	.byte		2
+	.4byte		.Lend_inner
+
+	.byte		0	/* DW_LNE_end_of_sequence */
+	.uleb128	1
+	.byte		1
+
+.Lline1_end:
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-objfile-overlap-outer.S
@@ -0,0 +1,208 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2011 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 <http://www.gnu.org/licenses/>.  */
+
+	.text
+
+	.globl _start
+_start:
+
+	.globl outer_before
+	.type outer_before, %function
+outer_before:
+.Lbegin_outer_before:
+	.int 0
+.Lend_outer_before:
+	.size outer_before, . - outer_before
+
+	.globl outer_inner
+outer_inner:
+
+	.int 0
+
+	.globl outer_after
+	.type outer_after, %function
+outer_after:
+.Lbegin_outer_after:
+	.int 0
+.Lend_outer_after:
+	.size outer_after, . - outer_after
+
+/* Debug information */
+
+	.section .debug_info
+.Lcu1_begin:
+	/* CU header */
+	.4byte	.Lcu1_end - .Lcu1_start		/* Length of Compilation Unit */
+.Lcu1_start:
+	.2byte	2				/* DWARF Version */
+	.4byte	.Labbrev1_begin			/* Offset into abbrev section */
+	.byte	4				/* Pointer size */
+
+	/* CU die */
+	.uleb128 1				/* Abbrev: DW_TAG_compile_unit */
+	.4byte	.Lline1_begin			/* DW_AT_stmt_list */
+	.4byte	.Ldebug_ranges			/* DW_AT_ranges */
+	.ascii	"outer.c\0"			/* DW_AT_name */
+        .ascii  "/tmp\0"			/* DW_AT_comp_dir */
+	.ascii	"GNU C 3.3.3\0"			/* DW_AT_producer */
+	.byte	1				/* DW_AT_language (C) */
+
+	/* outer_before */
+	.uleb128	2			/* Abbrev: DW_TAG_subprogram */
+	.byte		1			/* DW_AT_external */
+	.byte		1			/* DW_AT_decl_file */
+	.byte		1			/* DW_AT_decl_line */
+	.ascii		"outer_before\0"	/* DW_AT_name */
+	.4byte		.Lbegin_outer_before	/* DW_AT_low_pc */
+	.4byte		.Lend_outer_before	/* DW_AT_high_pc */
+
+	/* outer_after */
+	.uleb128	2			/* Abbrev: DW_TAG_subprogram */
+	.byte		1			/* DW_AT_external */
+	.byte		1			/* DW_AT_decl_file */
+	.byte		2			/* DW_AT_decl_line */
+	.ascii		"outer_after\0"		/* DW_AT_name */
+	.4byte		.Lbegin_outer_after	/* DW_AT_low_pc */
+	.4byte		.Lend_outer_after	/* DW_AT_high_pc */
+
+	.byte		0			/* End of children of CU */
+
+.Lcu1_end:
+
+/* DW_AT_ranges.  */
+	.section	.debug_ranges
+.Ldebug_ranges:
+	.4byte	.Lbegin_outer_before
+	.4byte	.Lend_outer_before
+	.4byte	.Lbegin_outer_after
+	.4byte	.Lend_outer_after
+	.4byte	0
+	.4byte	0
+
+/* Abbrev table */
+	.section .debug_abbrev
+.Labbrev1_begin:
+	.uleb128	1			/* Abbrev code */
+	.uleb128	0x11			/* DW_TAG_compile_unit */
+	.byte		1			/* has_children */
+	.uleb128	0x10			/* DW_AT_stmt_list */
+	.uleb128	0x6			/* DW_FORM_data4 */
+	.uleb128	0x55			/* DW_AT_ranges */
+	.uleb128	0x6			/* DW_FORM_data4 */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128        0x1b                    /* DW_AT_comp_dir */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x25			/* DW_AT_producer */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x13			/* DW_AT_language */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	2			/* Abbrev code */
+	.uleb128	0x2e			/* DW_TAG_subprogram */
+	.byte		0			/* has_children */
+	.uleb128	0x3f			/* DW_AT_external */
+	.uleb128	0xc			/* DW_FORM_flag */
+	.uleb128	0x3a			/* DW_AT_decl_file */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.uleb128	0x3b			/* DW_AT_decl_line */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x11			/* DW_AT_low_pc */
+	.uleb128	0x1			/* DW_FORM_addr */
+	.uleb128	0x12			/* DW_AT_high_pc */
+	.uleb128	0x1			/* DW_FORM_addr */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+/* Line table */
+	.section .debug_line
+.Lline1_begin:
+	.4byte		.Lline1_end - .Lline1_start	/* Initial length */
+.Lline1_start:
+	.2byte		2			/* Version */
+	.4byte		.Lline1_lines - .Lline1_hdr	/* header_length */
+.Lline1_hdr:
+	.byte		1			/* Minimum insn length */
+	.byte		1			/* default_is_stmt */
+	.byte		1			/* line_base */
+ 	.byte		1			/* line_range */
+	.byte		0x10			/* opcode_base */
+
+	/* Standard lengths */
+	.byte		0
+	.byte		1
+	.byte		1
+	.byte		1
+	.byte		1
+	.byte		0
+	.byte		0
+	.byte		0
+	.byte		1
+	.byte		0
+	.byte		0
+	.byte		1
+	.byte		0
+	.byte		0
+	.byte		0
+
+	/* Include directories */
+        .ascii  "/tmp\0"
+	.byte		0
+
+	/* File names */
+	.ascii		"outer.c\0"
+	.uleb128	1
+	.uleb128	0
+	.uleb128	0
+
+	.byte		0
+
+.Lline1_lines:
+	.byte		0	/* DW_LNE_set_address */
+	.uleb128	5
+	.byte		2
+	.4byte		.Lbegin_outer_before
+
+	.byte		1	/* DW_LNS_copy */
+
+	.byte		0	/* DW_LNE_set_address */
+	.uleb128	5
+	.byte		2
+	.4byte		.Lbegin_outer_after
+
+	.byte		3	/* DW_LNS_advance_line */
+	.sleb128	2	/* ... to 3 */
+
+	.byte		1	/* DW_LNS_copy */
+
+	.byte		0	/* DW_LNE_set_address */
+	.uleb128	5
+	.byte		2
+	.4byte		.Lend_outer_after
+
+	.byte		0	/* DW_LNE_end_of_sequence */
+	.uleb128	1
+	.byte		1
+
+.Lline1_end:
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-objfile-overlap.exp
@@ -0,0 +1,47 @@
+# Copyright 2011 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 <http://www.gnu.org/licenses/>.
+load_lib dwarf.exp
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+if {![dwarf2_support]} {
+    return 0  
+}
+
+set testfile "dw2-objfile-overlap"
+set srcfile_outer ${testfile}-outer.S
+set srcfile_inner ${testfile}-inner.S
+set executable_outer ${testfile}-outer.x
+set binfile_outer ${objdir}/${subdir}/${executable_outer}
+set binfile_inner ${objdir}/${subdir}/${testfile}-inner.x
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile_outer}" "${binfile_outer}" \
+      object {}] != ""
+     || [gdb_compile "${srcdir}/${subdir}/${srcfile_inner}" "${binfile_inner}" \
+      object {}] != "" } {
+    return -1
+}
+
+clean_restart $executable_outer
+
+gdb_test "add-symbol-file $binfile_inner outer_inner" \
+         {Reading symbols from .*\.\.\.done\.} "add-symbol-file" \
+	 "\r\n\t\\.text_addr = 0x\[0-9a-f\]+\r\n\\(y or n\\) \$" "y"
+
+# Expand symtab for ${binfile_outer}.
+gdb_breakpoint "*outer_before"
+
+# FAIL was:
+# No line number information available for address 0x4 <outer_inner>
+gdb_test "info line inner" {Line 2 of "inner\.c" starts at address .*}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]