mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-05 15:15:42 +00:00
On openSUSE Leap 15.6 x86_64, with gcc 7 and test-case
gdb.base/condbreak-multi-context.exp I run into:
...
(gdb) print aaa^M
$3 = <optimized out>^M
(gdb) FAIL: $exp: start_before=true: scenario_1: print aaa
...
This is a regression since commit 86ac8c5462 ("Convert
lookup_symbol_in_objfile").
Likewise in test-cases gdb.cp/m-static.exp and gdb.cp/namespace.exp.
The failure is specific to using Dwarf v4:
- using target board unix/gdb:debug_flags=-gdwarf-5 fixes it
- using target board unix/gdb:debug_flags=-gdwarf-4 on Tumbleweed (with gcc 15
and Dwarf v5 default) triggers it
The variable we're trying to print, A::aaa is a static const int member:
...
class A : public Base
{
public:
static const int aaa = 10;
...
};
...
With Dwarf v5, we have this DIE:
...
<2><356>: Abbrev Number: 2 (DW_TAG_variable)
<357> DW_AT_name : aaa
<35c> DW_AT_linkage_name: _ZN1A3aaaE
<364> DW_AT_external : 1
<364> DW_AT_accessibility: 1 (public)
<364> DW_AT_declaration : 1
<364> DW_AT_const_value : 10
...
and the cooked index contains these corresponding entries:
...
[45] ((cooked_index_entry *) 0x7facf0004730)
name: _ZN1A3aaaE
canonical: _ZN1A3aaaE
qualified: _ZN1A3aaaE
DWARF tag: DW_TAG_variable
flags: 0x4 [IS_LINKAGE]
DIE offset: 0x356
parent: ((cooked_index_entry *) 0)
[52] ((cooked_index_entry *) 0x7facf0004700)
name: aaa
canonical: aaa
qualified: A::aaa
DWARF tag: DW_TAG_variable
flags: 0x0 []
DIE offset: 0x356
parent: ((cooked_index_entry *) 0x7facf00046d0) [A]
...
With Dwarf v4, we have instead the following DIE:
...
<2><350>: Abbrev Number: 3 (DW_TAG_member)
<351> DW_AT_name : aaa
<35b> DW_AT_external : 1
<35b> DW_AT_accessibility: 1 (public)
<35c> DW_AT_declaration : 1
<35c> DW_AT_const_value : 4 byte block: a 0 0 0
...
and there are no corresponding entries.
Fix this by adding an entry:
...
[47] ((cooked_index_entry *) 0x7f5a24004660)
name: aaa
canonical: aaa
qualified: A::aaa
DWARF tag: DW_TAG_member
flags: 0x0 []
DIE offset: 0x350
parent: ((cooked_index_entry *) 0x7f5a24004630) [A]
...
Add a regression test in the form of a dwarf assembly test-case printing the
value of variable A::aaa.
In the test-case, for A::aaa, DW_FORM_flag is used to encode
DW_AT_declaration. In v1 of this patch that mattered (because of using
has_hardcoded_declaration in abbrev_table::read), but that's no longer the
case. Nevertheless, also add an A::bbb using FORM_flag_present for
DW_AT_declaration (and while we're at it, DW_AT_external as well).
Also add two variants, for which <optimized out> is printed:
- A::ccc: a variant with DW_AT_location instead of DW_AT_const_value, and
- A::ddd: a variant without external.
This behavior is not part of the regression. I've reproduced it using a
system gdb based on 14.2. It's also not specific to using the cooked index,
it reproduces with -readnow as well.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
PR symtab/33415
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33415
162 lines
4.3 KiB
C
162 lines
4.3 KiB
C
/* Tag attributes
|
|
|
|
Copyright (C) 2022-2025 Free Software Foundation, Inc.
|
|
|
|
This file is part of GDB.
|
|
|
|
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/>. */
|
|
|
|
#ifndef GDB_DWARF2_TAG_H
|
|
#define GDB_DWARF2_TAG_H
|
|
|
|
#include "dwarf2.h"
|
|
#include "symtab.h"
|
|
#include "read-gdb-index.h"
|
|
|
|
/* Return true if TAG represents a type, false otherwise. */
|
|
|
|
static inline bool
|
|
tag_is_type (dwarf_tag tag)
|
|
{
|
|
switch (tag)
|
|
{
|
|
case DW_TAG_array_type:
|
|
case DW_TAG_class_type:
|
|
case DW_TAG_enumeration_type:
|
|
case DW_TAG_pointer_type:
|
|
case DW_TAG_reference_type:
|
|
case DW_TAG_string_type:
|
|
case DW_TAG_structure_type:
|
|
case DW_TAG_subroutine_type:
|
|
case DW_TAG_typedef:
|
|
case DW_TAG_union_type:
|
|
case DW_TAG_ptr_to_member_type:
|
|
case DW_TAG_set_type:
|
|
case DW_TAG_subrange_type:
|
|
case DW_TAG_base_type:
|
|
case DW_TAG_const_type:
|
|
case DW_TAG_packed_type:
|
|
case DW_TAG_template_type_param:
|
|
case DW_TAG_volatile_type:
|
|
case DW_TAG_restrict_type:
|
|
case DW_TAG_interface_type:
|
|
case DW_TAG_namespace:
|
|
case DW_TAG_unspecified_type:
|
|
case DW_TAG_shared_type:
|
|
case DW_TAG_rvalue_reference_type:
|
|
case DW_TAG_coarray_type:
|
|
case DW_TAG_dynamic_type:
|
|
case DW_TAG_atomic_type:
|
|
case DW_TAG_immutable_type:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/* Return true if the given DWARF tag matches the specified search
|
|
domain flags. LANG may affect the result, due to the "C++ tag
|
|
hack". */
|
|
|
|
static inline bool
|
|
tag_matches_domain (dwarf_tag tag, domain_search_flags search, language lang)
|
|
{
|
|
domain_search_flags flags = 0;
|
|
switch (tag)
|
|
{
|
|
case DW_TAG_variable:
|
|
case DW_TAG_member:
|
|
case DW_TAG_enumerator:
|
|
case DW_TAG_constant:
|
|
flags = SEARCH_VAR_DOMAIN;
|
|
break;
|
|
|
|
case DW_TAG_subprogram:
|
|
case DW_TAG_entry_point:
|
|
flags = SEARCH_FUNCTION_DOMAIN;
|
|
break;
|
|
|
|
case DW_TAG_structure_type:
|
|
case DW_TAG_class_type:
|
|
case DW_TAG_union_type:
|
|
case DW_TAG_enumeration_type:
|
|
{
|
|
if (lang == language_c
|
|
|| lang == language_objc
|
|
|| lang == language_opencl
|
|
|| lang == language_minimal)
|
|
flags = SEARCH_STRUCT_DOMAIN;
|
|
else if (lang == language_cplus)
|
|
flags = SEARCH_STRUCT_DOMAIN | SEARCH_TYPE_DOMAIN;
|
|
else
|
|
flags = SEARCH_TYPE_DOMAIN;
|
|
}
|
|
break;
|
|
|
|
case DW_TAG_imported_declaration:
|
|
/* DW_TAG_imported_declaration isn't necessarily a type, but the
|
|
scanner doesn't track the referent, and the full reader
|
|
also currently puts it in TYPE_DOMAIN. */
|
|
case DW_TAG_padding:
|
|
case DW_TAG_array_type:
|
|
case DW_TAG_pointer_type:
|
|
case DW_TAG_reference_type:
|
|
case DW_TAG_string_type:
|
|
case DW_TAG_subroutine_type:
|
|
case DW_TAG_ptr_to_member_type:
|
|
case DW_TAG_set_type:
|
|
case DW_TAG_subrange_type:
|
|
case DW_TAG_base_type:
|
|
case DW_TAG_const_type:
|
|
case DW_TAG_packed_type:
|
|
case DW_TAG_template_type_param:
|
|
case DW_TAG_volatile_type:
|
|
case DW_TAG_restrict_type:
|
|
case DW_TAG_interface_type:
|
|
case DW_TAG_namespace:
|
|
case DW_TAG_unspecified_type:
|
|
case DW_TAG_shared_type:
|
|
case DW_TAG_rvalue_reference_type:
|
|
case DW_TAG_coarray_type:
|
|
case DW_TAG_dynamic_type:
|
|
case DW_TAG_atomic_type:
|
|
case DW_TAG_immutable_type:
|
|
case DW_TAG_typedef:
|
|
flags = SEARCH_TYPE_DOMAIN;
|
|
break;
|
|
|
|
case DW_TAG_label:
|
|
flags = SEARCH_LABEL_DOMAIN;
|
|
break;
|
|
|
|
case DW_TAG_module:
|
|
if (lang == language_ada)
|
|
flags = SEARCH_TYPE_DOMAIN;
|
|
else
|
|
flags = SEARCH_MODULE_DOMAIN;
|
|
break;
|
|
|
|
case DW_TAG_GDB_INDEX_OTHER:
|
|
flags = SEARCH_MODULE_DOMAIN | SEARCH_TYPE_DOMAIN;
|
|
break;
|
|
case DW_TAG_GDB_INDEX_TYPE:
|
|
flags = SEARCH_STRUCT_DOMAIN | SEARCH_TYPE_DOMAIN;
|
|
break;
|
|
}
|
|
|
|
return (flags & search) != 0;
|
|
}
|
|
|
|
#endif /* GDB_DWARF2_TAG_H */
|