This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[commit] Record range information for DWARF compilation units without any
- From: Daniel Jacobowitz <drow at false dot org>
- To: gdb-patches at sourceware dot org
- Cc: John Hughes <john at Calva dot COM>
- Date: Sat, 7 Feb 2009 15:47:41 -0500
- Subject: [commit] Record range information for DWARF compilation units without any
This is Debian bug #513816. The symptom is that when debugging a
Linux kernel, we attribute most of the text section as belonging to
the first source file - even in the addrmap, which exists to solve
this problem.
We have debug info that looks like this:
Compilation unit with no PC information
Function in .text
Function in .init.text
Because the CU does not have DW_AT_ranges, we fall back to putting its
low and high bounds in the addrmap; not useful when those bounds are
computed in GDB as the union of all contained functions. We should
only do that for CUs with explicit bounds, DW_AT_high_pc and
DW_AT_low_pc.
This patch causes us to add each function to the addrmap as a
reference to the current psymtab, fixing the bug.
It does waste a bit of memory. Functions are laid out as
"function; padding; function; padding; function" and the padding gets
an entry with value NULL in the addrmap. I have a patch to
coalesce entries in this case, but I decided against including
it; the patch adds 1MB in addrmap usage for the Linux kernel, of which
only 220K is padding. And the coalescing patch violates the abstract
definition of the addrmap type. I think the usage is acceptable,
for a binary with 40MB debug info already.
Tested on x86_64-linux and checked in.
--
Daniel Jacobowitz
CodeSourcery
2009-02-07 Daniel Jacobowitz <dan@codesourcery.com>
* dwarf2read.c (dwarf2_build_psymtabs_hard): Move lowpc and highpc
inside the loop. Only call addrmap_set_empty if the compilation unit
had DW_AT_high_pc and DW_AT_low_pc. Update call to
scan_partial_symbols.
(scan_partial_symbols): Take NEED_PC argument and pass it along with
LOWPC and HIGHPC.
(add_partial_namespace): Take NEED_PC argument and pass it through.
(add_partial_subprogram): Take NEED_PC argument. Update the addrmap
if necessary.
---
gdb/dwarf2read.c | 59 +++++++++++++++++++++++++++++++++++--------------------
1 file changed, 38 insertions(+), 21 deletions(-)
Index: src/gdb/dwarf2read.c
===================================================================
--- src.orig/gdb/dwarf2read.c 2009-02-07 13:25:47.000000000 -0500
+++ src/gdb/dwarf2read.c 2009-02-07 13:26:31.000000000 -0500
@@ -763,7 +763,7 @@ static void dwarf2_build_psymtabs_hard (
static void scan_partial_symbols (struct partial_die_info *,
CORE_ADDR *, CORE_ADDR *,
- struct dwarf2_cu *);
+ int, struct dwarf2_cu *);
static void add_partial_symbol (struct partial_die_info *,
struct dwarf2_cu *);
@@ -772,14 +772,14 @@ static int pdi_needs_namespace (enum dwa
static void add_partial_namespace (struct partial_die_info *pdi,
CORE_ADDR *lowpc, CORE_ADDR *highpc,
- struct dwarf2_cu *cu);
+ int need_pc, struct dwarf2_cu *cu);
static void add_partial_enumeration (struct partial_die_info *enum_pdi,
struct dwarf2_cu *cu);
static void add_partial_subprogram (struct partial_die_info *pdi,
CORE_ADDR *lowpc, CORE_ADDR *highpc,
- struct dwarf2_cu *cu);
+ int need_pc, struct dwarf2_cu *cu);
static gdb_byte *locate_pdi_sibling (struct partial_die_info *orig_pdi,
gdb_byte *info_ptr,
@@ -1486,7 +1486,7 @@ dwarf2_build_psymtabs_hard (struct objfi
struct partial_die_info comp_unit_die;
struct partial_symtab *pst;
struct cleanup *back_to;
- CORE_ADDR lowpc, highpc, baseaddr;
+ CORE_ADDR baseaddr;
info_ptr = dwarf2_per_objfile->info_buffer;
@@ -1607,6 +1607,13 @@ dwarf2_build_psymtabs_hard (struct objfi
&comp_unit_die.highpc, &cu, pst))
comp_unit_die.has_pc_info = 1;
}
+ else if (comp_unit_die.has_pc_info
+ && comp_unit_die.lowpc < comp_unit_die.highpc)
+ /* Store the contiguous range if it is not empty; it can be empty for
+ CUs with no code. */
+ addrmap_set_empty (objfile->psymtabs_addrmap,
+ comp_unit_die.lowpc + baseaddr,
+ comp_unit_die.highpc + baseaddr - 1, pst);
/* Check if comp unit has_children.
If so, read the rest of the partial symbols from this comp unit.
@@ -1614,13 +1621,15 @@ dwarf2_build_psymtabs_hard (struct objfi
if (comp_unit_die.has_children)
{
struct partial_die_info *first_die;
+ CORE_ADDR lowpc, highpc;
lowpc = ((CORE_ADDR) -1);
highpc = ((CORE_ADDR) 0);
first_die = load_partial_dies (abfd, info_ptr, 1, &cu);
- scan_partial_symbols (first_die, &lowpc, &highpc, &cu);
+ scan_partial_symbols (first_die, &lowpc, &highpc,
+ ! comp_unit_die.has_pc_info, &cu);
/* If we didn't find a lowpc, set it to highpc to avoid
complaints from `maint check'. */
@@ -1638,12 +1647,6 @@ dwarf2_build_psymtabs_hard (struct objfi
pst->textlow = comp_unit_die.lowpc + baseaddr;
pst->texthigh = comp_unit_die.highpc + baseaddr;
- /* Store the contiguous range; `DW_AT_ranges' range is stored above. The
- range can be also empty for CUs with no code. */
- if (!cu.has_ranges_offset && pst->textlow < pst->texthigh)
- addrmap_set_empty (objfile->psymtabs_addrmap, pst->textlow,
- pst->texthigh - 1, pst);
-
pst->n_global_syms = objfile->global_psymbols.next -
(objfile->global_psymbols.list + pst->globals_offset);
pst->n_static_syms = objfile->static_psymbols.next -
@@ -1788,13 +1791,16 @@ create_all_comp_units (struct objfile *o
dwarf2_per_objfile->n_comp_units = n_comp_units;
}
-/* Process all loaded DIEs for compilation unit CU, starting at FIRST_DIE.
- Also set *LOWPC and *HIGHPC to the lowest and highest PC values found
- in CU. */
+/* Process all loaded DIEs for compilation unit CU, starting at
+ FIRST_DIE. The caller should pass NEED_PC == 1 if the compilation
+ unit DIE did not have PC info (DW_AT_low_pc and DW_AT_high_pc, or
+ DW_AT_ranges). If NEED_PC is set, then this function will set
+ *LOWPC and *HIGHPC to the lowest and highest PC values found in CU
+ and record the covered ranges in the addrmap. */
static void
scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
- CORE_ADDR *highpc, struct dwarf2_cu *cu)
+ CORE_ADDR *highpc, int need_pc, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
bfd *abfd = objfile->obfd;
@@ -1820,7 +1826,7 @@ scan_partial_symbols (struct partial_die
switch (pdi->tag)
{
case DW_TAG_subprogram:
- add_partial_subprogram (pdi, lowpc, highpc, cu);
+ add_partial_subprogram (pdi, lowpc, highpc, need_pc, cu);
break;
case DW_TAG_variable:
case DW_TAG_typedef:
@@ -1849,7 +1855,7 @@ scan_partial_symbols (struct partial_die
add_partial_symbol (pdi, cu);
break;
case DW_TAG_namespace:
- add_partial_namespace (pdi, lowpc, highpc, cu);
+ add_partial_namespace (pdi, lowpc, highpc, need_pc, cu);
break;
default:
break;
@@ -2156,7 +2162,7 @@ pdi_needs_namespace (enum dwarf_tag tag)
static void
add_partial_namespace (struct partial_die_info *pdi,
CORE_ADDR *lowpc, CORE_ADDR *highpc,
- struct dwarf2_cu *cu)
+ int need_pc, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
@@ -2167,7 +2173,7 @@ add_partial_namespace (struct partial_di
/* Now scan partial symbols in that namespace. */
if (pdi->has_children)
- scan_partial_symbols (pdi->die_child, lowpc, highpc, cu);
+ scan_partial_symbols (pdi->die_child, lowpc, highpc, need_pc, cu);
}
/* Read a partial die corresponding to a subprogram and create a partial
@@ -2183,7 +2189,7 @@ add_partial_namespace (struct partial_di
static void
add_partial_subprogram (struct partial_die_info *pdi,
CORE_ADDR *lowpc, CORE_ADDR *highpc,
- struct dwarf2_cu *cu)
+ int need_pc, struct dwarf2_cu *cu)
{
if (pdi->tag == DW_TAG_subprogram)
{
@@ -2193,6 +2199,17 @@ add_partial_subprogram (struct partial_d
*lowpc = pdi->lowpc;
if (pdi->highpc > *highpc)
*highpc = pdi->highpc;
+ if (need_pc)
+ {
+ CORE_ADDR baseaddr;
+ struct objfile *objfile = cu->objfile;
+
+ baseaddr = ANOFFSET (objfile->section_offsets,
+ SECT_OFF_TEXT (objfile));
+ addrmap_set_empty (objfile->psymtabs_addrmap,
+ pdi->lowpc, pdi->highpc - 1,
+ cu->per_cu->psymtab);
+ }
if (!pdi->is_declaration)
add_partial_symbol (pdi, cu);
}
@@ -2209,7 +2226,7 @@ add_partial_subprogram (struct partial_d
fixup_partial_die (pdi, cu);
if (pdi->tag == DW_TAG_subprogram
|| pdi->tag == DW_TAG_lexical_block)
- add_partial_subprogram (pdi, lowpc, highpc, cu);
+ add_partial_subprogram (pdi, lowpc, highpc, need_pc, cu);
pdi = pdi->die_sibling;
}
}