You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
371 lines
15 KiB
371 lines
15 KiB
From e385593eef98ac92be57159e141f4b805dadbbb3 Mon Sep 17 00:00:00 2001 |
|
From: Jan Kratochvil <jan.kratochvil@redhat.com> |
|
Date: Mon, 30 May 2016 14:14:43 +0200 |
|
Subject: [PATCH 2/2] 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. |
|
--- |
|
gdb/ChangeLog | 10 ++++ |
|
gdb/dwarf2read.c | 53 ++++++++++------ |
|
gdb/testsuite/ChangeLog | 6 ++ |
|
gdb/testsuite/gdb.ada/out_of_line_in_inlined.exp | 6 -- |
|
.../gdb.dwarf2/dw2-lexical-block-bare.exp | 70 ++++++++++++++++++++++ |
|
5 files changed, 120 insertions(+), 25 deletions(-) |
|
create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-lexical-block-bare.exp |
|
|
|
### a/gdb/ChangeLog |
|
### b/gdb/ChangeLog |
|
## -1,5 +1,15 @@ |
|
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. |
|
+ |
|
+2016-05-30 Jan Kratochvil <jan.kratochvil@redhat.com> |
|
+ |
|
Code cleanup: dwarf2_get_pc_bounds: -1/0/+1 -> enum |
|
* dwarf2read.c (enum pc_bounds_kind) New. |
|
(dwarf2_get_pc_bounds): Use it in the declaration. |
|
Index: gdb-7.6.1/gdb/dwarf2read.c |
|
=================================================================== |
|
--- gdb-7.6.1.orig/gdb/dwarf2read.c 2016-05-30 15:07:34.285853679 +0200 |
|
+++ gdb-7.6.1/gdb/dwarf2read.c 2016-05-30 15:08:13.485197538 +0200 |
|
@@ -1486,13 +1486,16 @@ |
|
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, |
|
|
|
@@ -5027,7 +5030,7 @@ |
|
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'. */ |
|
@@ -5036,7 +5039,7 @@ |
|
|
|
/* 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; |
|
@@ -9606,7 +9609,7 @@ |
|
|
|
/* 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)) |
|
@@ -9763,9 +9766,20 @@ |
|
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 += baseaddr; |
|
highpc += baseaddr; |
|
|
|
@@ -9970,7 +9984,7 @@ |
|
|
|
/* 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]"), |
|
@@ -10249,7 +10263,7 @@ |
|
|
|
/* 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, |
|
@@ -10260,7 +10274,7 @@ |
|
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) |
|
@@ -10277,7 +10291,7 @@ |
|
} |
|
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; |
|
@@ -10299,15 +10313,17 @@ |
|
/* 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. |
|
@@ -10318,7 +10334,7 @@ |
|
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) |
|
@@ -10339,8 +10355,7 @@ |
|
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); |
|
@@ -10378,7 +10393,7 @@ |
|
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; |
|
--- /dev/null 2016-05-30 15:04:01.916990766 +0200 |
|
+++ gdb-7.6.1/gdb/testsuite/gdb.dwarf2/dw2-lexical-block-bare.exp 2016-05-30 15:19:22.236042134 +0200 |
|
@@ -0,0 +1,32 @@ |
|
+# Copyright 2016 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 |
|
+} |
|
+ |
|
+standard_testfile .S main.c |
|
+ |
|
+if { [prepare_for_testing ${testfile}.exp ${testfile} \ |
|
+ [list $srcfile2 $srcfile] {nodebug}] } { |
|
+ return -1 |
|
+} |
|
+ |
|
+runto_main |
|
+ |
|
+# FAILing GDB did print: No symbol "testvar" in current context. |
|
+gdb_test "p testvar" { = -?[0-9]+} |
|
--- /dev/null 2016-05-30 15:04:01.916990766 +0200 |
|
+++ gdb-7.6.1/gdb/testsuite/gdb.dwarf2/dw2-lexical-block-bare.S 2016-05-30 15:17:42.580173290 +0200 |
|
@@ -0,0 +1,89 @@ |
|
+ .section .debug_info |
|
+.Lcu1_begin: |
|
+ .4byte .Lcu1_end - .Lcu1_start |
|
+.Lcu1_start: |
|
+ .2byte 4 /* Version */ |
|
+ .4byte .Labbrev1_begin /* Abbrevs */ |
|
+ .byte 4 /* Pointer size */ |
|
+ .uleb128 2 /* Abbrev (DW_TAG_compile_unit) */ |
|
+ .4byte main_label |
|
+ .4byte main_label+0x10000 |
|
+.Llabel1: |
|
+ .uleb128 3 /* Abbrev (DW_TAG_base_type) */ |
|
+ .sleb128 4 |
|
+ .sleb128 0x5 |
|
+ .ascii "integer\0" |
|
+ .uleb128 4 /* Abbrev (DW_TAG_subprogram) */ |
|
+ .ascii "main\0" |
|
+ .byte 1 |
|
+ .4byte main_label |
|
+ .4byte main_label+0x10000 |
|
+ .uleb128 5 /* Abbrev (DW_TAG_lexical_block) */ |
|
+ .uleb128 6 /* Abbrev (DW_TAG_variable) */ |
|
+ .ascii "testvar\0" |
|
+ .4byte .Llabel1 - .Lcu1_begin |
|
+ .byte 1 |
|
+ .uleb128 .Lexpr_end3 - .Lexpr_start2/* expression */ |
|
+.Lexpr_start2: |
|
+ .byte 0x03 /* DW_OP_addr */ |
|
+ .4byte main |
|
+.Lexpr_end3: |
|
+ .byte 0x0 /* Terminate children */ |
|
+ .byte 0x0 /* Terminate children */ |
|
+ .byte 0x0 /* Terminate children */ |
|
+.Lcu1_end: |
|
+ .section .debug_abbrev |
|
+.Labbrev1_begin: |
|
+ .uleb128 2 /* Abbrev start */ |
|
+ .uleb128 0x11 /* DW_TAG_compile_unit */ |
|
+ .byte 1 /* has_children */ |
|
+ .uleb128 0x11 /* DW_AT_low_pc */ |
|
+ .uleb128 0x01 /* DW_FORM_addr */ |
|
+ .uleb128 0x12 /* DW_AT_high_pc */ |
|
+ .uleb128 0x01 /* DW_FORM_addr */ |
|
+ .byte 0x0 /* Terminator */ |
|
+ .byte 0x0 /* Terminator */ |
|
+ .uleb128 3 /* Abbrev start */ |
|
+ .uleb128 0x24 /* DW_TAG_base_type */ |
|
+ .byte 0 /* has_children */ |
|
+ .uleb128 0x0b /* DW_AT_byte_size */ |
|
+ .uleb128 0x0d /* DW_FORM_sdata */ |
|
+ .uleb128 0x3e /* DW_AT_encoding */ |
|
+ .uleb128 0x0d /* DW_FORM_sdata */ |
|
+ .uleb128 0x03 /* DW_AT_name */ |
|
+ .uleb128 0x08 /* DW_FORM_string */ |
|
+ .byte 0x0 /* Terminator */ |
|
+ .byte 0x0 /* Terminator */ |
|
+ .uleb128 4 /* Abbrev start */ |
|
+ .uleb128 0x2e /* DW_TAG_subprogram */ |
|
+ .byte 1 /* has_children */ |
|
+ .uleb128 0x03 /* DW_AT_name */ |
|
+ .uleb128 0x08 /* DW_FORM_string */ |
|
+ .uleb128 0x3f /* DW_AT_external */ |
|
+ .uleb128 0x0c /* DW_FORM_flag */ |
|
+ .uleb128 0x11 /* DW_AT_low_pc */ |
|
+ .uleb128 0x01 /* DW_FORM_addr */ |
|
+ .uleb128 0x12 /* DW_AT_high_pc */ |
|
+ .uleb128 0x01 /* DW_FORM_addr */ |
|
+ .byte 0x0 /* Terminator */ |
|
+ .byte 0x0 /* Terminator */ |
|
+ .uleb128 5 /* Abbrev start */ |
|
+ .uleb128 0x0b /* DW_TAG_lexical_block */ |
|
+ .byte 1 /* has_children */ |
|
+ .byte 0x0 /* Terminator */ |
|
+ .byte 0x0 /* Terminator */ |
|
+ .uleb128 6 /* Abbrev start */ |
|
+ .uleb128 0x34 /* DW_TAG_variable */ |
|
+ .byte 0 /* has_children */ |
|
+ .uleb128 0x03 /* DW_AT_name */ |
|
+ .uleb128 0x08 /* DW_FORM_string */ |
|
+ .uleb128 0x49 /* DW_AT_type */ |
|
+ .uleb128 0x13 /* DW_FORM_ref4 */ |
|
+ .uleb128 0x3f /* DW_AT_external */ |
|
+ .uleb128 0x0c /* DW_FORM_flag */ |
|
+ .uleb128 0x02 /* DW_AT_location */ |
|
+ .uleb128 0x09 /* SPECIAL_expr */ |
|
+ .byte 0x0 /* Terminator */ |
|
+ .byte 0x0 /* Terminator */ |
|
+ .byte 0x0 /* Terminator */ |
|
+ .byte 0x0 /* Terminator */ |
|
diff -dup -rup gdb-7.6.1/gdb/testsuite/gdb.dwarf2/main.c gdb-7.6.1-orig/gdb/testsuite/gdb.dwarf2/main.c |
|
--- gdb-7.6.1/gdb/testsuite/gdb.dwarf2/main.c 2013-01-01 07:41:22.000000000 +0100 |
|
+++ gdb-7.6.1-orig/gdb/testsuite/gdb.dwarf2/main.c 2017-03-08 22:20:21.085438961 +0100 |
|
@@ -20,5 +20,6 @@ |
|
int |
|
main() |
|
{ |
|
+ asm ("main_label: .globl main_label"); |
|
return 0; |
|
}
|
|
|