diff options
author | Jan Kratochvil <jan.kratochvil@redhat.com> | 2016-05-30 14:14:43 +0200 |
---|---|---|
committer | Jan Kratochvil <jan.kratochvil@redhat.com> | 2016-05-30 14:14:43 +0200 |
commit | e385593eef98ac92be57159e141f4b805dadbbb3 (patch) | |
tree | bc4fbe6b519a043582391334abf47438bff24a68 /gdb/dwarf2read.c | |
parent | 3a2b436ae9958a1029545c03201b7223ff33c150 (diff) | |
download | fsf-binutils-gdb-e385593eef98ac92be57159e141f4b805dadbbb3.zip fsf-binutils-gdb-e385593eef98ac92be57159e141f4b805dadbbb3.tar.gz fsf-binutils-gdb-e385593eef98ac92be57159e141f4b805dadbbb3.tar.bz2 |
PR 15231: import bare DW_TAG_lexical_block
Local variables in lambdas are not accessible
https://sourceware.org/bugzilla/show_bug.cgi?id=15231
GDB: read_lexical_block_scope
/* Ignore blocks with missing or invalid low and high pc attributes. */
[...]
if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL))
return;
But sometimes there is:
FAIL: gcc-5.3.1-6.fc23.x86_64
<2><92>: Abbrev Number: 11 (DW_TAG_lexical_block)
<3><9c>: Abbrev Number: 13 (DW_TAG_structure_type)
<9d> DW_AT_name : (indirect string, offset: 0x3c): <lambda()>
[...]
Where DW_TAG_lexical_block has no attributes. Such whole subtree is currently
dropped by GDB while I think it should just import all its children DIEs.
It even XFAIL->XPASSes gdb.ada/out_of_line_in_inlined.exp:
commit 0fa7fe506c242b459c4c05d331e7c7d66fb52390
Author: Joel Brobecker <brobecker@adacore.com>
out of line functions nested inside inline functions.
So I have removed that xfail.
gdb/ChangeLog
2016-05-30 Jan Kratochvil <jan.kratochvil@redhat.com>
PR c++/15231
* dwarf2read.c (enum pc_bounds_kind): Add PC_BOUNDS_INVALID.
(process_psymtab_comp_unit_reader, read_func_scope): Adjust callers.
(read_lexical_block_scope): Import DIEs from bare DW_TAG_lexical_block.
(read_call_site_scope): Adjust callers.
(dwarf2_get_pc_bounds): Implement pc_bounds_invalid.
(dwarf2_get_subprogram_pc_bounds, get_scope_pc_bounds): Adjust callers.
gdb/testsuite/ChangeLog
2016-05-30 Jan Kratochvil <jan.kratochvil@redhat.com>
PR c++/15231
* gdb.ada/out_of_line_in_inlined.exp: Remove xfails.
* gdb.dwarf2/dw2-lexical-block-bare.exp: New file.
Diffstat (limited to 'gdb/dwarf2read.c')
-rw-r--r-- | gdb/dwarf2read.c | 53 |
1 files changed, 34 insertions, 19 deletions
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index f90db00..6658a38 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -1607,13 +1607,16 @@ static int dwarf2_ranges_read (unsigned, CORE_ADDR *, CORE_ADDR *, struct dwarf2_cu *, struct partial_symtab *); /* How dwarf2_get_pc_bounds constructed its *LOWPC and *HIGHPC return - values. */ + values. Keep the items ordered with increasing constraints compliance. */ enum pc_bounds_kind { - /* No valid combination of DW_AT_low_pc, DW_AT_high_pc or DW_AT_ranges - was found. */ + /* No attribute DW_AT_low_pc, DW_AT_high_pc or DW_AT_ranges was found. */ PC_BOUNDS_NOT_PRESENT, + /* Some of the attributes DW_AT_low_pc, DW_AT_high_pc or DW_AT_ranges + were present but they do not form a valid range of PC addresses. */ + PC_BOUNDS_INVALID, + /* Discontiguous range was found - that is DW_AT_ranges was found. */ PC_BOUNDS_RANGES, @@ -6019,7 +6022,7 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader, first_die = load_partial_dies (reader, info_ptr, 1); scan_partial_symbols (first_die, &lowpc, &highpc, - cu_bounds_kind == PC_BOUNDS_NOT_PRESENT, cu); + cu_bounds_kind <= PC_BOUNDS_INVALID, cu); /* If we didn't find a lowpc, set it to highpc to avoid complaints from `maint check'. */ @@ -6028,7 +6031,7 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader, /* If the compilation unit didn't have an explicit address range, then use the information extracted from its child dies. */ - if (cu_bounds_kind == PC_BOUNDS_NOT_PRESENT) + if (cu_bounds_kind <= PC_BOUNDS_INVALID) { best_lowpc = lowpc; best_highpc = highpc; @@ -11390,7 +11393,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) /* Ignore functions with missing or invalid low and high pc attributes. */ if (dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL) - == PC_BOUNDS_NOT_PRESENT) + <= PC_BOUNDS_INVALID) { attr = dwarf2_attr (die, DW_AT_external, cu); if (!attr || !DW_UNSND (attr)) @@ -11552,9 +11555,20 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu) as multiple lexical blocks? Handling children in a sane way would be nasty. Might be easier to properly extend generic blocks to describe ranges. */ - if (dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL) - == PC_BOUNDS_NOT_PRESENT) - return; + switch (dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL)) + { + case PC_BOUNDS_NOT_PRESENT: + /* DW_TAG_lexical_block has no attributes, process its children as if + there was no wrapping by that DW_TAG_lexical_block. + GCC does no longer produces such DWARF since GCC r224161. */ + for (child_die = die->child; + child_die != NULL && child_die->tag; + child_die = sibling_die (child_die)) + process_die (child_die, cu); + return; + case PC_BOUNDS_INVALID: + return; + } lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr); highpc = gdbarch_adjust_dwarf2_addr (gdbarch, highpc + baseaddr); @@ -11764,7 +11778,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) /* DW_AT_entry_pc should be preferred. */ if (dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu, NULL) - == PC_BOUNDS_NOT_PRESENT) + <= PC_BOUNDS_INVALID) complaint (&symfile_complaints, _("DW_AT_GNU_call_site_target target DIE has invalid " "low pc, for referencing DIE 0x%x [in module %s]"), @@ -12041,7 +12055,7 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return, /* Get low and high pc attributes from a die. See enum pc_bounds_kind definition for the return value. *LOWPC and *HIGHPC are set iff - PC_BOUNDS_NOT_PRESENT is not returned. */ + neither PC_BOUNDS_NOT_PRESENT nor PC_BOUNDS_INVALID are returned. */ static enum pc_bounds_kind dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, @@ -12052,7 +12066,7 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, struct attribute *attr_high; CORE_ADDR low = 0; CORE_ADDR high = 0; - enum pc_bounds_kind ret = PC_BOUNDS_NOT_PRESENT; + enum pc_bounds_kind ret; attr_high = dwarf2_attr (die, DW_AT_high_pc, cu); if (attr_high) @@ -12067,7 +12081,7 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, } else /* Found high w/o low attribute. */ - return PC_BOUNDS_NOT_PRESENT; + return PC_BOUNDS_INVALID; /* Found consecutive range of addresses. */ ret = PC_BOUNDS_HIGH_LOW; @@ -12089,15 +12103,17 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, /* Value of the DW_AT_ranges attribute is the offset in the .debug_ranges section. */ if (!dwarf2_ranges_read (ranges_offset, &low, &high, cu, pst)) - return PC_BOUNDS_NOT_PRESENT; + return PC_BOUNDS_INVALID; /* Found discontinuous range of addresses. */ ret = PC_BOUNDS_RANGES; } + else + return PC_BOUNDS_NOT_PRESENT; } /* read_partial_die has also the strict LOW < HIGH requirement. */ if (high <= low) - return PC_BOUNDS_NOT_PRESENT; + return PC_BOUNDS_INVALID; /* When using the GNU linker, .gnu.linkonce. sections are used to eliminate duplicate copies of functions and vtables and such. @@ -12108,7 +12124,7 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, If this is a discarded function, mark the pc bounds as invalid, so that GDB will ignore it. */ if (low == 0 && !dwarf2_per_objfile->has_section_at_zero) - return PC_BOUNDS_NOT_PRESENT; + return PC_BOUNDS_INVALID; *lowpc = low; if (highpc) @@ -12129,8 +12145,7 @@ dwarf2_get_subprogram_pc_bounds (struct die_info *die, CORE_ADDR low, high; struct die_info *child = die->child; - if (dwarf2_get_pc_bounds (die, &low, &high, cu, NULL) - != PC_BOUNDS_NOT_PRESENT) + if (dwarf2_get_pc_bounds (die, &low, &high, cu, NULL) >= PC_BOUNDS_RANGES) { *lowpc = min (*lowpc, low); *highpc = max (*highpc, high); @@ -12168,7 +12183,7 @@ get_scope_pc_bounds (struct die_info *die, CORE_ADDR current_low, current_high; if (dwarf2_get_pc_bounds (die, ¤t_low, ¤t_high, cu, NULL) - != PC_BOUNDS_NOT_PRESENT) + >= PC_BOUNDS_RANGES) { best_low = current_low; best_high = current_high; |