Re: [patch/rfc] Recognize non-DW_AT_location symbols [Re: [patch] Racy FAIL: gdb.base/auxv.exp + gdb.base/callfuncs.exp]

Jan Kratochvil
2009-03-24T21:40:42Z

On Mon, 23 Mar 2009 23:47:36 +0100, Joel Brobecker wrote:
> > (the original patch for optimized-out variables is being tested and looks OK)
>
> Excellent! How about officially resubmitting the latest version of
> the patch, to give everyone a chance to look at it again, before
> we decide to check it in?

I was not completely convinced that time I would like to submit it that way.

Written there a rationale as I do not find the reasons for the
die_is_declaration() condition there to be obvious.

Also submitted to http://dwarfstd.org/Issues.php that DWARF3 section 2.13.2 is
IMO ambiguous as was discussed at:
http://sourceware.org/ml/gdb-patches/2004-04/threads.html#00296
suggesting to add:
DW_AT_declaration and DW_AT_sibling attributes are not being inherited from
the debugging information entry referenced by the specification attribute.

The testcase probably breaks on Alpha (as its default executable addresses do
not fit in 32 bits) compared to its original variant.

No regressions on x86_64-unknown-linux-gnu, tested also on gcc-4.4 (Fedora 11).

Thanks,
Jan

gdb/
2009-03-24 Joel Brobecker <brobecker@adacore.com>
Jan Kratochvil <jan.kratochvil@redhat.com>

Recognize missing DW_AT_location as <value optimized out>.
* dwarf2read.c
(new_symbol <DW_TAG_variable> <!DW_AT_location> <!DW_AT_external>):
Call add_symbol_to_list.

gdb/testsuite/
2009-03-24 Jan Kratochvil <jan.kratochvil@redhat.com>

* gdb.dwarf2/dw2-noloc-main.c: New file.
* gdb.dwarf2/dw2-noloc.S (.text): Remove.
(.data): New.
(DW_AT_stmt_list, .debug_line, DW_AT_frame_base): Remove.
(DW_AT_low_pc, DW_AT_high_pc): Reference `dw2-noloc-main.c'.
(DW_TAG_subprogram func_cu1, noloc): Remove.
(file_location, file_optimized_out, extern_location, extern_resolvable)
(extern_unresolvable, main, func_location, func_optimized_out)
(func_extern_location, func_extern_resolvable)
(func_extern_unresolvable): New.
* gdb.dwarf2/dw2-noloc.exp: Use prepare_for_testing, compile also
`dw2-noloc-main.c'. Test the new DIEs from `dw2-noloc.S'.
(globals): New procedure.

--- gdb/dwarf2read.c 20 Mar 2009 22:00:10 -0000 1.297
+++ gdb/dwarf2read.c 24 Mar 2009 21:05:16 -0000
@@ -7659,6 +7659,26 @@ new_symbol (struct die_info *die, struct
SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
add_symbol_to_list (sym, &global_symbols);
}
+ /* Catch local optimized-out variables but do not create symbols
+ for DIEs later being completed (by their DW_AT_location or
+ DW_AT_const_value).
+
+ C++ declaration refering to a definition in the same file (and
+ therefore not using DW_AT_external) would be
+ DW_TAG_imported_declaration (not DW_TAG_variable) as the
+ target DIE can be referenced as it is in the same CU.
+
+ Therefore such DW_TAG_variable having DW_AT_declaration would
+ be present only to be later completed through
+ DW_AT_specification. As GDB looks up the first symbol in its
+ scope we will rather defer creating the symbol to the later
+ DIE completing this DIE. */
+ else if (!die_is_declaration (die, cu))
+ {
+ /* Use the default LOC_OPTIMIZED_OUT class. */
+ gdb_assert (SYMBOL_CLASS (sym) == LOC_OPTIMIZED_OUT);
+ add_symbol_to_list (sym, cu->list_in_scope);
+ }
}
break;
case DW_TAG_formal_parameter:
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gdb/testsuite/gdb.dwarf2/dw2-noloc-main.c 24 Mar 2009 21:05:16 -0000
@@ -0,0 +1,28 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2009 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/>. */
+
+asm (".globl cu_text_start");
+asm ("cu_text_start:");
+
+int
+main (void)
+{
+ return 0;
+}
+
+asm (".globl cu_text_end");
+asm ("cu_text_end:");
--- gdb/testsuite/gdb.dwarf2/dw2-noloc.S 3 Jan 2009 05:58:04 -0000 1.4
+++ gdb/testsuite/gdb.dwarf2/dw2-noloc.S 24 Mar 2009 21:05:16 -0000
@@ -15,16 +15,13 @@
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
-.Lbegin_text1:
- .globl func_cu1
- .type func_cu1, %function
-func_cu1:
-.Lbegin_func_cu1:
- .int 0
-.Lend_func_cu1:
- .size func_cu1, .-func_cu1
-.Lend_text1:
+ .data
+ .globl func_extern_resolvable
+func_extern_resolvable:
+ .globl extern_resolvable
+extern_resolvable:
+resolvable:
+ .4byte 1234567890

/* Debug information */

@@ -39,36 +36,89 @@ func_cu1:

/* CU die */
.uleb128 1 /* Abbrev: DW_TAG_compile_unit */
- .4byte .Lline1_begin /* DW_AT_stmt_list */
- .4byte .Lend_text1 /* DW_AT_high_pc */
- .4byte .Lbegin_text1 /* DW_AT_low_pc */
+ .4byte cu_text_end /* DW_AT_high_pc */
+ .4byte cu_text_start /* DW_AT_low_pc */
.ascii "file1.txt\0" /* DW_AT_name */
.ascii "GNU C 3.3.3\0" /* DW_AT_producer */
.byte 1 /* DW_AT_language (C) */

- /* func_cu1 */
- .uleb128 2 /* Abbrev: DW_TAG_subprogram */
- .byte 1 /* DW_AT_external */
- .byte 1 /* DW_AT_decl_file */
- .byte 2 /* DW_AT_decl_line */
- .ascii "func_cu1\0" /* DW_AT_name */
- .4byte .Ltype_int-.Lcu1_begin /* DW_AT_type */
- .4byte .Lbegin_func_cu1 /* DW_AT_low_pc */
- .4byte .Lend_func_cu1 /* DW_AT_high_pc */
- .byte 1 /* DW_AT_frame_base: length */
- .byte 0x55 /* DW_AT_frame_base: DW_OP_reg5 */
-
.Ltype_int:
.uleb128 3 /* Abbrev: DW_TAG_base_type */
.ascii "int\0" /* DW_AT_name */
.byte 4 /* DW_AT_byte_size */
.byte 5 /* DW_AT_encoding */

- .uleb128 4 /* Abbrev: DW_TAG_variable */
- .ascii "noloc\0" /* DW_AT_name */
+ .uleb128 7 /* Abbrev: DW_TAG_variable (location) */
+ .ascii "file_location\0" /* DW_AT_name */
+ .byte 2f - 1f /* DW_AT_location */
+1: .byte 3 /* DW_OP_addr */
+ .4byte resolvable /* <addr> */
+2: .4byte .Ltype_int-.Lcu1_begin /* DW_AT_type */
+
+ .uleb128 5 /* Abbrev: DW_TAG_variable (bare) */
+ .ascii "file_optimized_out\0" /* DW_AT_name */
+ .4byte .Ltype_int-.Lcu1_begin /* DW_AT_type */
+
+ .uleb128 8 /* Abbrev: DW_TAG_variable (location+extern) */
+ .ascii "extern_location\0" /* DW_AT_name */
+ .4byte .Ltype_int-.Lcu1_begin /* DW_AT_type */
+ .byte 2f - 1f /* DW_AT_location */
+1: .byte 3 /* DW_OP_addr */
+ .4byte resolvable /* <addr> */
+2: .byte 1 /* DW_AT_external */
+
+ .uleb128 4 /* Abbrev: DW_TAG_variable (extern) */
+ .ascii "extern_resolvable\0" /* DW_AT_name */
+ .4byte .Ltype_int-.Lcu1_begin /* DW_AT_type */
+ .byte 1 /* DW_AT_external */
+
+ /* This variable is optimized-out. */
+ .uleb128 4 /* Abbrev: DW_TAG_variable (extern) */
+ .ascii "extern_unresolvable\0" /* DW_AT_name */
+ .4byte .Ltype_int-.Lcu1_begin /* DW_AT_type */
+ .byte 1 /* DW_AT_external */
+
+ /* main */
+ .uleb128 6 /* Abbrev: DW_TAG_subprogram */
+ .byte 1 /* DW_AT_decl_file */
+ .byte 2 /* DW_AT_decl_line */
+ .ascii "main\0" /* DW_AT_name */
+ .4byte .Ltype_int-.Lcu1_begin /* DW_AT_type */
+ .4byte cu_text_start /* DW_AT_low_pc */
+ .4byte cu_text_end /* DW_AT_high_pc */
+
+ .uleb128 7 /* Abbrev: DW_TAG_variable (location) */
+ .ascii "func_location\0" /* DW_AT_name */
+ .byte 2f - 1f /* DW_AT_location */
+1: .byte 3 /* DW_OP_addr */
+ .4byte resolvable /* <addr> */
+2: .4byte .Ltype_int-.Lcu1_begin /* DW_AT_type */
+
+ .uleb128 5 /* Abbrev: DW_TAG_variable (bare) */
+ .ascii "func_optimized_out\0" /* DW_AT_name */
+ .4byte .Ltype_int-.Lcu1_begin /* DW_AT_type */
+
+ .uleb128 8 /* Abbrev: DW_TAG_variable (location+extern) */
+ .ascii "func_extern_location\0" /* DW_AT_name */
+ .4byte .Ltype_int-.Lcu1_begin /* DW_AT_type */
+ .byte 2f - 1f /* DW_AT_location */
+1: .byte 3 /* DW_OP_addr */
+ .4byte resolvable /* <addr> */
+2: .byte 1 /* DW_AT_external */
+
+ .uleb128 4 /* Abbrev: DW_TAG_variable (extern) */
+ .ascii "func_extern_resolvable\0" /* DW_AT_name */
.4byte .Ltype_int-.Lcu1_begin /* DW_AT_type */
.byte 1 /* DW_AT_external */

+ /* This variable is optimized-out. */
+ .uleb128 4 /* Abbrev: DW_TAG_variable (extern) */
+ .ascii "func_extern_unresolvable\0" /* DW_AT_name */
+ .4byte .Ltype_int-.Lcu1_begin /* DW_AT_type */
+ .byte 1 /* DW_AT_external */
+
+ .byte 0 /* End of children of main */
+
.byte 0 /* End of children of CU */

.Lcu1_end:
@@ -79,8 +129,6 @@ func_cu1:
.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 0x12 /* DW_AT_high_pc */
.uleb128 0x1 /* DW_FORM_addr */
.uleb128 0x11 /* DW_AT_low_pc */
@@ -94,11 +142,43 @@ func_cu1:
.byte 0x0 /* Terminator */
.byte 0x0 /* Terminator */

- .uleb128 2 /* Abbrev code */
- .uleb128 0x2e /* DW_TAG_subprogram */
+ .uleb128 3 /* Abbrev code */
+ .uleb128 0x24 /* DW_TAG_base_type */
.byte 0 /* has_children */
+ .uleb128 0x3 /* DW_AT_name */
+ .uleb128 0x8 /* DW_FORM_string */
+ .uleb128 0xb /* DW_AT_byte_size */
+ .uleb128 0xb /* DW_FORM_data1 */
+ .uleb128 0x3e /* DW_AT_encoding */
+ .uleb128 0xb /* DW_FORM_data1 */
+ .byte 0x0 /* Terminator */
+ .byte 0x0 /* Terminator */
+
+ .uleb128 4 /* Abbrev code (extern) */
+ .uleb128 0x34 /* DW_TAG_variable */
+ .byte 0 /* has_children */
+ .uleb128 0x3 /* DW_AT_name */
+ .uleb128 0x8 /* DW_FORM_string */
+ .uleb128 0x49 /* DW_AT_type */
+ .uleb128 0x13 /* DW_FORM_ref4 */
.uleb128 0x3f /* DW_AT_external */
.uleb128 0xc /* DW_FORM_flag */
+ .byte 0x0 /* Terminator */
+ .byte 0x0 /* Terminator */
+
+ .uleb128 5 /* Abbrev code (bare) */
+ .uleb128 0x34 /* DW_TAG_variable */
+ .byte 0 /* has_children */
+ .uleb128 0x3 /* DW_AT_name */
+ .uleb128 0x8 /* DW_FORM_string */
+ .uleb128 0x49 /* DW_AT_type */
+ .uleb128 0x13 /* DW_FORM_ref4 */
+ .byte 0x0 /* Terminator */
+ .byte 0x0 /* Terminator */
+
+ .uleb128 6 /* Abbrev code */
+ .uleb128 0x2e /* DW_TAG_subprogram */
+ .byte 1 /* has_children */
.uleb128 0x3a /* DW_AT_decl_file */
.uleb128 0xb /* DW_FORM_data1 */
.uleb128 0x3b /* DW_AT_decl_line */
@@ -111,30 +191,30 @@ func_cu1:
.uleb128 0x1 /* DW_FORM_addr */
.uleb128 0x12 /* DW_AT_high_pc */
.uleb128 0x1 /* DW_FORM_addr */
- .uleb128 0x40 /* DW_AT_frame_base */
- .uleb128 0xa /* DW_FORM_block1 */
.byte 0x0 /* Terminator */
.byte 0x0 /* Terminator */

- .uleb128 3 /* Abbrev code */
- .uleb128 0x24 /* DW_TAG_base_type */
+ .uleb128 7 /* Abbrev code (location) */
+ .uleb128 0x34 /* DW_TAG_variable */
.byte 0 /* has_children */
.uleb128 0x3 /* DW_AT_name */
.uleb128 0x8 /* DW_FORM_string */
- .uleb128 0xb /* DW_AT_byte_size */
- .uleb128 0xb /* DW_FORM_data1 */
- .uleb128 0x3e /* DW_AT_encoding */
- .uleb128 0xb /* DW_FORM_data1 */
+ .uleb128 0x2 /* DW_AT_location */
+ .uleb128 0xa /* DW_FORM_block1 */
+ .uleb128 0x49 /* DW_AT_type */
+ .uleb128 0x13 /* DW_FORM_ref4 */
.byte 0x0 /* Terminator */
.byte 0x0 /* Terminator */

- .uleb128 4 /* Abbrev code */
+ .uleb128 8 /* Abbrev code (location+extern) */
.uleb128 0x34 /* DW_TAG_variable */
.byte 0 /* has_children */
.uleb128 0x3 /* DW_AT_name */
.uleb128 0x8 /* DW_FORM_string */
.uleb128 0x49 /* DW_AT_type */
.uleb128 0x13 /* DW_FORM_ref4 */
+ .uleb128 0x2 /* DW_AT_location */
+ .uleb128 0xa /* DW_FORM_block1 */
.uleb128 0x3f /* DW_AT_external */
.uleb128 0xc /* DW_FORM_flag */
.byte 0x0 /* Terminator */
@@ -142,69 +222,3 @@ func_cu1:

.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 */
- .byte 0
-
- /* File names */
- .ascii "file1.txt\0"
- .uleb128 0
- .uleb128 0
- .uleb128 0
-
- .byte 0
-
-.Lline1_lines:
- .byte 0 /* DW_LNE_set_address */
- .uleb128 5
- .byte 2
- .4byte .Lbegin_func_cu1
-
- .byte 3 /* DW_LNS_advance_line */
- .sleb128 3 /* ... to 4 */
-
- .byte 1 /* DW_LNS_copy */
-
- .byte 1 /* DW_LNS_copy (second time as an end-of-prologue marker) */
-
- .byte 0 /* DW_LNE_set_address */
- .uleb128 5
- .byte 2
- .4byte .Lend_func_cu1
-
- .byte 0 /* DW_LNE_end_of_sequence */
- .uleb128 1
- .byte 1
-
-.Lline1_end:
--- gdb/testsuite/gdb.dwarf2/dw2-noloc.exp 3 Jan 2009 05:58:04 -0000 1.4
+++ gdb/testsuite/gdb.dwarf2/dw2-noloc.exp 24 Mar 2009 21:05:16 -0000
@@ -24,25 +24,55 @@ if {![istarget *-*-linux*]
return 0
}

-set testfile "dw2-noloc"
-set srcfile ${testfile}.S
-set binfile ${objdir}/${subdir}/${testfile}.x
-
-if { [gdb_compile "${srcdir}/${subdir}/main.c" "main.o" object {debug}] != "" } {
+if { [prepare_for_testing dw2-noloc.exp "dw2-noloc" {dw2-noloc-main.c dw2-noloc.S} {nodebug}] } {
return -1
}

-if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${testfile}.o" object {nodebug}] != "" } {
- return -1
+proc globals {type} {
+ global pf_prefix
+ set old_prefix $pf_prefix
+ lappend pf_prefix "$type:"
+
+ gdb_test "print file_location" "= 1234567890"
+ gdb_test "ptype file_location" "type = int"
+
+ gdb_test "print file_optimized_out" "= <value optimized out>"
+ gdb_test "ptype file_optimized_out" "type = int"
+
+ gdb_test "print extern_location" "= 1234567890"
+ gdb_test "ptype extern_location" "type = int"
+
+ gdb_test "print extern_resolvable" "= 1234567890"
+ gdb_test "ptype extern_resolvable" "type = int"
+
+ # This variable should be printed as optimized-out.
+ gdb_test "print extern_unresolvable" "Address of symbol \"extern_unresolvable\" is unknown\\."
+ gdb_test "ptype extern_unresolvable" "type = int"
+
+ set pf_prefix $old_prefix
}

-if { [gdb_compile "${testfile}.o main.o" "${binfile}" executable {debug}] != "" } {
+globals no-run
+
+if ![runto_main] {
return -1
}

-gdb_exit
-gdb_start
-gdb_reinitialize_dir $srcdir/$subdir
-gdb_load ${binfile}
+globals in-main
+
+
+gdb_test "print func_location" "= 1234567890"
+gdb_test "ptype func_location" "type = int"
+
+gdb_test "print func_optimized_out" "= <value optimized out>"
+gdb_test "ptype func_optimized_out" "type = int"
+
+gdb_test "print func_extern_location" "= 1234567890"
+gdb_test "ptype func_extern_location" "type = int"
+
+gdb_test "print func_extern_resolvable" "= 1234567890"
+gdb_test "ptype func_extern_resolvable" "type = int"

-gdb_test "print noloc" "Address of symbol \"noloc\" is unknown." "print noloc"
+# This variable should be printed as optimized-out.
+gdb_test "print func_extern_unresolvable" "Address of symbol \"func_extern_unresolvable\" is unknown\\."
+gdb_test "ptype func_extern_unresolvable" "type = int"