mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-12-19 01:19:41 +08:00
c96ceed9dce7617f270aa4742645706e535f74b7
879 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
1d45d90934 |
[gdb/symtab] Work around PR gas/29517
When using glibc debuginfo generated with gas 2.39, we run into PR gas/29517:
...
$ gdb -q -batch a.out -ex start -ex "p (char *)strstr (\"haha\", \"ah\")"
Temporary breakpoint 1 at 0x40051b: file hello.c, line 6.
Temporary breakpoint 1, main () at hello.c:6
6 printf ("hello\n");
Invalid cast.
...
while without glibc debuginfo installed we get the expected result:
...
$n = 0x7ffff7daa1b1 "aha"
...
and likewise with glibc debuginfo generated with gas 2.40.
The strstr ifunc resolves to __strstr_sse2_unaligned. The problem is that gas
generates dwarf that states that the return type is void:
...
<1><3e1e58>: Abbrev Number: 2 (DW_TAG_subprogram)
<3e1e59> DW_AT_name : __strstr_sse2_unaligned
<3e1e5d> DW_AT_external : 1
<3e1e5e> DW_AT_low_pc : 0xbbd2e
<3e1e66> DW_AT_high_pc : 0xbc1c3
...
while the return type should be a DW_TAG_unspecified_type, as is the case
with gas 2.40.
We can still use the workaround of casting to another function type for both
__strstr_sse2_unaligned:
...
(gdb) p ((char * (*) (const char *, const char *))__strstr_sse2_unaligned) \
("haha", "ah")
$n = 0x7ffff7daa211 "aha"
...
and strstr (which requires using *strstr to dereference the ifunc before we
cast):
...
gdb) p ((char * (*) (const char *, const char *))*strstr) ("haha", "ah")
$n = 0x7ffff7daa251 "aha"
...
but that's a bit cumbersome to use.
Work around this in the dwarf reader, such that we have instead:
...
(gdb) p (char *)strstr ("haha", "ah")
$n = 0x7ffff7daa1b1 "aha"
...
This also requires fixing producer_is_gcc to stop returning true for
producer "GNU AS 2.39.0".
Tested on x86_64-linux.
Approved-By: Andrew Burgess <aburgess@redhat.com>
PR symtab/30911
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30911
|
||
|
|
8b9c08edda |
[gdb/symtab] Add name_of_main and language_of_main to the DWARF index
This patch adds a new section to the DWARF index containing the name and the language of the main function symbol, gathered from `cooked_index::get_main`, if available. Currently, for lack of a better name, this section is called the "shortcut table". The way this name is both saved and applied upon an index being loaded in mirrors how it is done in `cooked_index_functions`, more specifically, the full name of the main function symbol is saved and `set_objfile_main_name` is used to apply it after it is loaded. The main use case for this patch is in improving startup times when dealing with large binaries. Currently, when an index is used, GDB has to expand symtabs until it finds out what the language of the main function symbol is. For some large executables, this may take a considerable amount of time to complete, slowing down startup. This patch bypasses that operation by having both the name and language of the main function symbol be provided ahead of time by the index. In my testing (a binary with about 1.8GB worth of DWARF data) this change brings startup time down from about 34 seconds to about 1.5 seconds. When testing the patch with target board cc-with-gdb-index, test-case gdb.fortran/nested-funcs-2.exp starts failing, but this is due to a pre-existing issue, filed as PR symtab/30946. Tested on x86_64-linux, with target board unix and cc-with-gdb-index. PR symtab/24549 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=24549 Approved-By: Tom de Vries <tdevries@suse.de> |
||
|
|
ef0f16ccf8 |
Remove explanatory comments from includes
I noticed a comment by an include and remembered that I think these don't really provide much value -- sometimes they are just editorial, and sometimes they are obsolete. I think it's better to just remove them. Tested by rebuilding. Approved-By: Andrew Burgess <aburgess@redhat.com> |
||
|
|
973db6fae3 |
[gdb/symtab] Error out for .debug_types section in dwz file
There are two methods to factor out type information in a dwarf4 executable:
- use -fdebug-info-types to generate type units in a .debug_types section, and
- use dwz to create partial units.
The dwz method has an extra benefit: it also allows to factor out information
between executables into a newly created .dwz file, pointed to by a
.gnu_debugaltlink section.
There is nothing prohibiting a .gnu_debugaltlink file to contain a
.debug_types section.
It's just not generated by dwz or any other tool atm, and consequently gdb has
no support for it. Enhancement PR symtab/30838 is open about the lack of
support.
Make the current situation explicit by emitting a dwarf error:
...
(gdb) file struct-with-sig-2^M
Reading symbols from struct-with-sig-2...^M
Dwarf Error: .debug_types section not supported in dwz file^M
...
and add an assert in write_gdbindex:
...
+ /* See enhancement PR symtab/30838. */
+ gdb_assert (!(per_cu->is_dwz && per_cu->is_debug_types));
...
to clarify why we can use:
...
data_buf &cu_list = (per_cu->is_debug_types
? types_cu_list
: per_cu->is_dwz ? dwz_cu_list : objfile_cu_list);
...
The test-case is a modified copy from gdb.dwarf2/struct-with-sig.exp, so it
keeps the copyright years range.
Tested on x86_64-linux.
Tested-By: Guinevere Larsen <blarsen@redhat.com>
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30838
|
||
|
|
76fc0f6213 |
Give a language to a type
This changes main_type to hold a language, and updates the debug readers to set this field. This is done by adding the language to the type-allocator object. Note that the non-DWARF readers are changed on a "best effort" basis. This patch also reimplements type::is_array_like to use the type's language, and it adds a new type::is_string_like as well. This in turn lets us change the Python implementation of these methods to simply defer to the type. |
||
|
|
d948c67c5d |
Regularize some DWARF type initialization
In one spot, it will be convenient for a subsequent patch if the CU is passed to a type-creation helper function. In another spot, remove the redundant 'objfile' parameter to another such function. |
||
|
|
d559227272 |
Pass a type allocator to init_fixed_point_type
init_fixed_point_type currently takes an objfile and creates its own type allocator. However, for a later patch it is more convenient if this function accepts a type allocator. This patch makes this change. |
||
|
|
93203eebe2 |
[gdb/symtab] Fix overly large gdb-index file check for 32-bit
Add a unit test which checks that write_gdb_index_1 will throw an error when the size of the file would exceed the maximum value capable of being represented by 'offset_type'. The unit test fails on 32-bit systems due to wrapping overflow. Fix this by changing the type of total_len in write_gdbindex_1 from size_t to uint64_t. Tested on x86_64-linux. Co-Authored-By: Kevin Buettner <kevinb@redhat.com> Approved-by: Kevin Buettner <kevinb@redhat.com> |
||
|
|
fe26aa9533 |
Rename split_style::DOT
This renames split_style::DOT, to avoid name clashes when building gdb with an old version of Bison (2.3, the version available on macOS). In particular the error looks like: ./split-name.h:34:3: error: expected identifier DOT, ^ m2-exp.c:163:13: note: expanded from macro 'DOT' Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30286 |
||
|
|
98f6baad7c |
Throw error when creating an overly large gdb-index file
The header in a .gdb_index section uses 32-bit unsigned offsets to refer to other areas of the section. Thus, there is a size limit of 2^32-1 which is currently unaccounted for by GDB's code for outputting these sections. At the moment, when GDB creates an overly large section, it will exit abnormally due to an internal error, which is caused by a failed assert in assert_file_size, which in turn is called from write_gdbindex_1, both of which are in gdb/dwarf2/index-write.c. This is what happens when that assert fails: $ gdb -q -nx -iex 'set auto-load no' -iex 'set debuginfod enabled off' -ex file ./libgraph_tool_inference.so -ex "save gdb-index `pwd`/" Reading symbols from ./libgraph_tool_inference.so... No executable file now. Discard symbol table from `libgraph_tool_inference.so'? (y or n) n Not confirmed. ../../gdb/dwarf2/index-write.c:1069: internal-error: assert_file_size: Assertion `file_size == expected_size' failed. A problem internal to GDB has been detected, further debugging may prove unreliable. ----- Backtrace ----- 0x55fddb4d78b0 gdb_internal_backtrace_1 ../../gdb/bt-utils.c:122 0x55fddb4d78b0 _Z22gdb_internal_backtracev ../../gdb/bt-utils.c:168 0x55fddb98b5d4 internal_vproblem ../../gdb/utils.c:396 0x55fddb98b8de _Z15internal_verrorPKciS0_P13__va_list_tag ../../gdb/utils.c:476 0x55fddbb71654 _Z18internal_error_locPKciS0_z ../../gdbsupport/errors.cc:58 0x55fddb5a0f23 assert_file_size ../../gdb/dwarf2/index-write.c:1069 0x55fddb5a1ee0 assert_file_size /usr/include/c++/13/bits/stl_iterator.h:1158 0x55fddb5a1ee0 write_gdbindex_1 ../../gdb/dwarf2/index-write.c:1119 0x55fddb5a51be write_gdbindex ../../gdb/dwarf2/index-write.c:1273 [...] --------------------- ../../gdb/dwarf2/index-write.c:1069: internal-error: assert_file_size: Assertion `file_size == expected_size' failed. This problem was encountered while building the python-graph-tool package on Fedora. The Fedora bugzilla bug can be found here: https://bugzilla.redhat.com/show_bug.cgi?id=1773651 This commit prevents the internal error from occurring by calling error() when the file size exceeds 2^32-1. Using a gdb built with this commit, I now see this behavior instead: $ gdb -q -nx -iex 'set auto-load no' -iex 'set debuginfod enabled off' -ex file ./libgraph_tool_inference.so -ex "save gdb-index `pwd`/" Reading symbols from ./libgraph_tool_inference.so... No executable file now. Discard symbol table from `/mesquite2/fedora-bugs/1773651/libgraph_tool_inference.so'? (y or n) n Not confirmed. Error while writing index for `/mesquite2/fedora-bugs/1773651/libgraph_tool_inference.so': gdb-index maximum file size of 4294967295 exceeded (gdb) I wish I could provide a test case, but due to the sizes of both the input and output files, I think that testing resources would be strained or exceeded in many environments. My testing on Fedora 38 shows no regressions. Approved-by: Tom Tromey <tom@tromey.com> |
||
|
|
54392c4df6 |
gdb: fix buffer overflow in DWARF reader
In this commit:
commit
|
||
|
|
be7d5d2c41 |
[gdb/symtab] Fix gdb-index writing for .debug_types
With test-case gdb.ada/same_enum.exp and target board dwarf4-gdb-index we run
into:
...
(gdb) print red^M
No definition of "red" in current context.^M
(gdb) FAIL: gdb.ada/same_enum.exp: print red
...
[ This is a regression since commit
|
||
|
|
dec28322cf |
Introduce TYPE_SPECIFIC_RUST_STUFF
This adds a new enum constant, TYPE_SPECIFIC_RUST_STUFF, and changes the DWARF reader to set this on Rust types. This will be used as a flag in a later patch. Note that the size of the type_specific_field bitfield had to be increased. I checked that this did not impact the size of main_type. |
||
|
|
655e4e52ef |
Avoid crash with Ada and -fdata-sections
A user noticed that gdb would crash when showing a backtrace. Investigation showed this to be a crash in the DWARF reader when handling a "pragma export" symbol. The bug here is that earlier code decides to eliminate the symbol, but the export code tries to add it anyway -- but to a NULL list. |
||
|
|
3be8c91910 |
gdb: remove FIELD_BITSIZE
Replace with field::bitsize. Change-Id: I400be235d6a1f446d0a4aafac01df5e850185d3a Approved-By: Tom Tromey <tom@tromey.com> |
||
|
|
886176b865 |
gdb: introduce field::bitsize / field::set_bitsize
Add these two methods, rename the field to m_bitsize to make it pseudo private. Change-Id: Ief95e5cf106e72f2c22ae47b033d0fa47202b413 Approved-By: Tom Tromey <tom@tromey.com> |
||
|
|
454977cdc4 |
gdb: remove TYPE_FIELD_ARTIFICIAL
Replace with type::field + field::is_artificial. Change-Id: Ie3bacae49d9bd02e83e504c1ce01470aba56a081 Approved-By: Tom Tromey <tom@tromey.com> |
||
|
|
321d8b3f28 |
gdb: introduce field::is_artificial / field::set_is_artificial
Add these two methods, rename the field to m_artificial to make it pseudo private. Change-Id: If3a3825473d1d79bb586a8a074b87bba9b43fb1a Approved-By: Tom Tromey <tom@tromey.com> |
||
|
|
8688bb6278 |
Unify DW_TAG_typedef case in new_symbol
This patch merges the DW_TAG_typedef case in new_symbol with some other type-related cases. These all have identical code. Reviewed-By: Guinevere Larsen <blarsen@redhat.com> |
||
|
|
959db21230 |
[gdb/symtab] Replace TYPE_ALLOC with TYPE_ZALLOC where required
Handle the remaining uses of TYPE_ALLOC, either by: - replacing with TYPE_ZALLOC, or - adding a comment explaining why zero-initialization is not necessary. Tested on x86_64-linux. Approved-By: Tom Tromey <tom@tromey.com> |
||
|
|
6d3c2d749b |
[gdb/symtab] Replace TYPE_ALLOC + B_CLRALL with TYPE_ZALLOC
I noticed some cases of TYPE_ALLOC followed by B_CLRALL. Replace these with TYPE_ZALLOC. Tested on x86_64-linux. Approved-By: Tom Tromey <tom@tromey.com> |
||
|
|
2774f2dad5 |
[gdb/symtab] Factor out type::{alloc_fields,copy_fields}
After finding this code in buildsym_compunit::finish_block_internal:
...
ftype->set_fields
((struct field *)
TYPE_ALLOC (ftype, nparams * sizeof (struct field)));
...
and fixing PR30810 by using TYPE_ZALLOC, I wondered if there were more
locations that needed fixing.
I decided to make things easier to spot by factoring out a new function
alloc_fields:
...
/* Allocate the fields array of this type, with NFIELDS elements. If INIT,
zero-initialize the allocated memory. */
void
type::alloc_fields (unsigned int nfields, bool init = true);
...
where:
- a regular use would be "alloc_fields (nfields)", and
- an exceptional use that needed no initialization would be
"alloc_fields (nfields, false)".
Pretty soon I discovered that most of the latter cases are due to
initialization by memcpy, so I added two variants of copy_fields as well.
After this rewrite there are 8 uses of set_fields left:
...
gdb/coffread.c: type->set_fields (nullptr);
gdb/coffread.c: type->set_fields (nullptr);
gdb/coffread.c: type->set_fields (nullptr);
gdb/eval.c: type->set_fields
gdb/gdbtypes.c: type->set_fields (args);
gdb/gdbtypes.c: t->set_fields (XRESIZEVEC (struct field, t->fields (),
gdb/dwarf2/read.c: type->set_fields (new_fields);
gdb/dwarf2/read.c: sub_type->set_fields (sub_type->fields () + 1);
...
These fall into the following categories:
- set to nullptr (coffread.c),
- type not owned by objfile or gdbarch (eval.c), and
- modifying an existing fields array, like adding an element at the end or
dropping an element at the start (the rest).
Tested on x86_64-linux.
|
||
|
|
b8a175b415 |
Use sect_offset_str in cooked_index::dump
Mark Wielaard pointed out that cooked_index::dump uses PRIx64, and Andreas Schwab pointed out that gdb already has sect_offset_str. This patch applies both these observations. |
||
|
|
8d83f51b91 |
[gdb/symtab] Handle self-reference in inherit_abstract_dies
Building gdb with gcc 7.5.0 and -flto -O2 -flto-partition=one generates a
self-referencing DIE:
...
<2><91dace>: Abbrev Number: 405 (DW_TAG_label)
<91dad0> DW_AT_abstract_origin: <0x91dace>
...
When encountering the self-reference DIE in inherit_abstract_dies we loop
following the abstract origin, effectively hanging gdb.
Fix this by handling self-referencing DIEs in the loop in
inherit_abstract_dies.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
PR symtab/30799
https://sourceware.org/bugzilla/show_bug.cgi?id=30799
|
||
|
|
0b72cde372 |
gdb: add gdb::make_unique function
While GDB is still C++11, lets add a gdb::make_unique template function that can be used to create std::unique_ptr objects, just like the C++14 std::make_unique. If GDB is being compiled with a C++14 compiler then the new gdb::make_unique function will delegate to the std::make_unique. I checked with gcc, and at -O1 and above gdb::make_unique will be optimised away completely in this case. If C++14 (or later) becomes our minimum, then it will be easy enough to go through the code and replace gdb::make_unique with std::make_unique later on. I've make use of this function in all the places I think this can easily be used, though I'm sure I've probably missed some. Should be no user visible changes after this commit. Approved-By: Tom Tromey <tom@tromey.com> |
||
|
|
2b9ed6db3f |
[gdb/build, c++20] Fix invalid conversion in test_symbols
When building gdb with -std=c++20, I run into:
...
gdb/dwarf2/read.c:2709:3: error: invalid conversion from ‘const char8_t*’ to \
‘const char*’ [-fpermissive]
2709 | u8"u8função",
| ^~~~~~~~~~~~
| |
| const char8_t*
...
Fix this by making the conversion explicit.
Tested on x86_64-linux.
|
||
|
|
eeee4389cf |
[gdb/symtab] Handle self-reference DIE
While working on a dwarf assembly test-case I accidentally created the
following pathological dwarf:
...
<1><be>: Abbrev Number: 3 (DW_TAG_class_type)
<bf> DW_AT_name : c1
<c2> DW_AT_specification: <0xbe>
...
and noticed gdb segfaulting during cooked index creating due to running out of
stack. This is a regression from gdb-12, where gdb just hung.
Fix this by inhibiting the scan_attributes self-recursion for self-references.
The same test-case with -readnow makes gdb hang, so also fix this in
dwarf2_attr and follow_die_ref.
Note that this doesn't fix the same problems for the more complicated case of:
...
<1><be>: Abbrev Number: 3 (DW_TAG_class_type)
<bf> DW_AT_name : c1
<c2> DW_AT_specification: <0xc6>
<1><c6>: Abbrev Number: 4 (DW_TAG_class_type)
<c7> DW_AT_name : c2
<ca> DW_AT_specification: <0xbe>
...
but the approach for deciding whether to fix pathological dwarf cases is as
per PR27981 comment 3:
...
yes if it is cheap/obvious, and no if it is something complicated or expensive.
...
and at this point I'm not sure whether fixing this will fall in the first
category.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
|
||
|
|
aef36dee93 |
[gdb/symtab] Don't deduplicate variables in gdb-index
When running test-case gdb.python/py-symbol.exp with target board
cc-with-gdb-index, we run into:
...
(gdb) python print (len (gdb.lookup_static_symbols ('rr')))^M
1^M
(gdb) FAIL: gdb.python/py-symbol.exp: print (len (gdb.lookup_static_symbols ('rr')))
...
[ Note that the test-case contains rr in both py-symtab.c:
...
static int __attribute__ ((used)) rr = 42; /* line of rr */
...
and py-symtab-2.c:
...
static int __attribute__ ((used)) rr = 99; /* line of other rr */
... ]
This passes with gdb-12-branch, and fails with gdb-13-branch.
AFAIU the current code in symtab_index_entry::minimize makes the assumption
that it's fine to store only one copy of rr in the gdb-index, because
"print rr" will only ever print one, and always the same.
But that fails to recognize that gdb supports gdb.lookup_static_symbols, which
returns a list of variables rather than the first one.
In other words, the current approach breaks feature parity between cooked
index and gdb-index.
Note btw that also debug-names has both instances:
...
[ 5] #00597969 rr:
<4> DW_TAG_variable DW_IDX_compile_unit=3 DW_IDX_GNU_internal=1
<4> DW_TAG_variable DW_IDX_compile_unit=4 DW_IDX_GNU_internal=1
...
Fix this in symtab_index_entry::minimize, by not deduplicating variables.
Tested on x86_64-linux, with target boards unix and cc-with-gdb-index.
Reviewed-by: Kevin Buettner <kevinb@redhat.com>
PR symtab/30720
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30720
|
||
|
|
aa5b8b8cc3 |
[gdb/symtab] Fix off-by-one error in cooked_indexer::recurse
Test-case gdb.dwarf2/pr13961.exp contains:
...
<1><25>: Abbrev Number: 8 (DW_TAG_class_type)
<26> DW_AT_specification: <0x2a>
<1><2a>: Abbrev Number: 2 (DW_TAG_class_type)
<2b> DW_AT_name : foo
<2f> DW_AT_byte_size : 4
<30> DW_AT_decl_file : 1
<31> DW_AT_decl_line : 1
<32> DW_AT_sibling : <0x44>
...
The DIE at 0x25 contains an intra-CU forward reference, and is deferred during
DIE indexing in the cooked_index, by adding it to m_deferred_entries.
The resulting cooked index entries are:
...
[25] ((cooked_index_entry *) 0x333b5d0)
name: foo
canonical: foo
qualified: foo
DWARF tag: DW_TAG_class_type
flags: 0x0 []
DIE offset: 0x2a
parent: ((cooked_index_entry *) 0)
[26] ((cooked_index_entry *) 0x333b630)
name: foo
canonical: foo
qualified: foo::foo
DWARF tag: DW_TAG_class_type
flags: 0x0 []
DIE offset: 0x25
parent: ((cooked_index_entry *) 0x333b5d0) [foo]
...
Notice that 0x2a is the parent of 0x25, and that this is why the qualified
name of 0x25 is "foo::foo", which is incorrect, it's supposed to be "foo".
The parent is set here in cooked_indexer::make_index:
...
for (const auto &entry : m_deferred_entries)
{
void *obj = m_die_range_map.find (entry.spec_offset);
cooked_index_entry *parent = static_cast<cooked_index_entry *> (obj);
m_index_storage->add (entry.die_offset, entry.tag, entry.flags,
entry.name, parent, m_per_cu);
}
...
and AFAICT, we store in m_die_range_map the parent of the respective
spec_offset DIE (though that's not clear from the comment describing it).
So, the root cause of this is that when we lookup the parent for DIE 0x25, we get
m_die_range_map.find (0x2a) == 0x2a.
This is an off-by-one error, fixed in cooked_indexer::recurse by:
...
- CORE_ADDR start = form_addr (parent_entry->die_offset,
+ CORE_ADDR start = form_addr (parent_entry->die_offset + 1,
...
which gives us:
...
[12] ((cooked_index_entry *) 0x41e21f0)
name: foo
canonical: foo
qualified: foo
DWARF tag: DW_TAG_class_type
flags: 0x0 []
DIE offset: 0x25
parent: ((cooked_index_entry *) 0)
[13] ((cooked_index_entry *) 0x41e2190)
name: foo
canonical: foo
qualified: foo
DWARF tag: DW_TAG_class_type
flags: 0x0 []
DIE offset: 0x2a
parent: ((cooked_index_entry *) 0)
...
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
PR symtab/30739
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30739
|
||
|
|
8f258a6c97 |
[gdb/symtab] Dump qualified name of cooked_index_entry
When doing "maint print objfiles" for the exec of test-case
gdb.dwarf2/pr13961.exp, we get:
...
[25] ((cooked_index_entry *) 0x37b25d0)
name: foo
canonical: foo
DWARF tag: DW_TAG_class_type
flags: 0x0 []
DIE offset: 0x2a
parent: ((cooked_index_entry *) 0)
[26] ((cooked_index_entry *) 0x37b2630)
name: foo
canonical: foo
DWARF tag: DW_TAG_class_type
flags: 0x0 []
DIE offset: 0x25
parent: ((cooked_index_entry *) 0x37b25d0) [foo]
...
By following the parent links in the text, we can conclude that the qualified
name of DIE 0x25 is foo::foo (which is incorrect, that's PR symtab/30739).
But it's not evident, and also hard to verify in a test-case.
Add dumping of the qualified name, such that we have:
...
[25] ((cooked_index_entry *) 0x333b5d0)
name: foo
canonical: foo
qualified: foo
DWARF tag: DW_TAG_class_type
flags: 0x0 []
DIE offset: 0x2a
parent: ((cooked_index_entry *) 0)
[26] ((cooked_index_entry *) 0x333b630)
name: foo
canonical: foo
qualified: foo::foo
DWARF tag: DW_TAG_class_type
flags: 0x0 []
DIE offset: 0x25
parent: ((cooked_index_entry *) 0x333b5d0) [foo]
...
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
|
||
|
|
62a21046a9 |
[gdb/symtab] Fix assertion in write_debug_names
When running test-case gdb.dwarf2/pr13961.exp with target-board
cc-with-debug-names, I run into:
...
Running gdb.dwarf2/pr13961.exp ...
gdb compile failed, gdb/dwarf2/index-write.c:1305: internal-error: \
write_debug_names: Assertion `counter == per_bfd->all_units.size ()' failed.
...
This is a regression since commit
|
||
|
|
226f9f4fad |
Rename bfd_bread and bfd_bwrite
These were renamed from bfd_read and bfd_write back in 2001 when they lost an unnecessary parameter. Rename them back, and get rid of a few casts that are only needed without prototyped functions (K&R C). |
||
|
|
aaa1d4b8f2 |
[gdb/build] Fix build breaker with -std=c++11
When building with -std=c++11 I run into:
...
gdb/dwarf2/cooked-index.c: In member function \
‘void cooked_index::start_writing_index(dwarf2_per_bfd*)’:
gdb/dwarf2/cooked-index.c:469:10: error: lambda capture initializers only \
available with -std=c++14 or -std=gnu++14 [-Werror]
ctx = std::move (ctx)] ()
^~~
...
Fix this by capturing a copy instead when using -std=c++11:
...
= gdb::thread_pool::g_thread_pool->post_task ([this, per_bfd, ctx] ()
...
Tested by building with and without -stdc=++11 on x86_64-linux.
Reported-By: Tom Tromey <tom@tromey.com>
Reviewed-by: John Baldwin <jhb@FreeBSD.org>
|
||
|
|
d06730bc02 |
[gdb/symtab] Find main language without symtab expansion
When loading an executable using "file a.out", the language is set according
to a.out, which can involve looking up the language of symbol "main", which
will cause the symtab expansion for the containing CU.
Expansion of lto debug info can be slow, so in commit
|
||
|
|
0ecf440316 |
Consolidate calls to bfd_set_cacheable
I noticed that some spots in gdb call bfd_set_cacheable after opening a BFD. The BFD file cache is a bit odd. BFDs that are opened locally are unconditionally registered with the cache, and their underlying file descriptor will always be closed when bfd_cache_close_all is called. However, only "cacheable" BFDs will be eligible for reopening when needed -- and by default BFD decides that if a file descriptor is passed in, then it should not be cacheable. If a non-cacheable BFD's file descriptor is closed, there is no offical way to reopen it. gdb needs to call bfd_cache_close_all, because some systems cannot start an executable when it has an open file descriptor referencing it. However, gdb also will sometimes passes an open file descriptor to the various BFD open functions. And, due to lazy DWARF reading, gdb may also need to reopen these BFDs. Rather than having all the callers figure out when exactly to set the cacheable flag, I think it makes sense to consolidate this logic into the gdb_bfd.c wrapper functions. It is ok to do this because gdb always passes a filename to these open functions, so reopening should work ok. Regression tested on x86-64 Fedora 38. Reviewed-by: John Baldwin <jhb@FreeBSD.org> |
||
|
|
0961970dea |
[gdb/symtab] Fix data race on dwarf2_per_cu_data::{files_read,is_debug_types}
With gdb build with -fsanitize=thread, and the exec from test-case
gdb.base/index-cache.exp, I run into:
...
$ rm -f ~/.cache/gdb/*; \
gdb -q -batch -iex "set index-cache enabled on" index-cache \
-ex "print foobar"
...
WARNING: ThreadSanitizer: data race (pid=25018)
Write of size 1 at 0x7b200000410d by main thread:
#0 dw2_get_file_names_reader gdb/dwarf2/read.c:2033 (gdb+0x7ab023)
#1 dw2_get_file_names gdb/dwarf2/read.c:2130 (gdb+0x7ab023)
#2 dw_expand_symtabs_matching_file_matcher(dwarf2_per_objfile*, gdb::function_view<bool (char const*, bool)>) gdb/dwarf2/read.c:3105 (gdb+0x7ac6e9)
#3 cooked_index_functions::expand_symtabs_matching(objfile*, gdb::function_view<bool (char const*, bool)>, lookup_name_info const*, gdb::function_view<bool (char const*)>, gdb::function_view<bool (compunit_symtab*)>, enum_flags<block_search_flag_values>, domain_enum, search_domain) gdb/dwarf2/read.c:16812 (gdb+0x7d040f)
#4 objfile::map_symtabs_matching_filename(char const*, char const*, gdb::function_view<bool (symtab*)>) gdb/symfile-debug.c:219 (gdb+0xda5b6e)
#5 iterate_over_symtabs(char const*, gdb::function_view<bool (symtab*)>) gdb/symtab.c:648 (gdb+0xdc441d)
#6 lookup_symtab(char const*) gdb/symtab.c:662 (gdb+0xdc4522)
#7 classify_name gdb/c-exp.y:3083 (gdb+0x61afec)
#8 c_yylex gdb/c-exp.y:3251 (gdb+0x61dd13)
#9 c_yyparse() build/gdb/c-exp.c.tmp:1988 (gdb+0x61f07e)
#10 c_parse(parser_state*) gdb/c-exp.y:3417 (gdb+0x62d864)
#11 language_defn::parser(parser_state*) const gdb/language.c:598 (gdb+0x977245)
#12 parse_exp_in_context gdb/parse.c:414 (gdb+0xb10b1b)
#13 parse_expression(char const*, innermost_block_tracker*, enum_flags<parser_flag>) gdb/parse.c:462 (gdb+0xb1112e)
#14 process_print_command_args gdb/printcmd.c:1321 (gdb+0xb4bf8c)
#15 print_command_1 gdb/printcmd.c:1335 (gdb+0xb4caaa)
#16 print_command gdb/printcmd.c:1468 (gdb+0xb4cdda)
#17 do_simple_func gdb/cli/cli-decode.c:95 (gdb+0x65b078)
#18 cmd_func(cmd_list_element*, char const*, int) gdb/cli/cli-decode.c:2735 (gdb+0x65ed53)
#19 execute_command(char const*, int) gdb/top.c:575 (gdb+0xe3a7ea)
#20 catch_command_errors gdb/main.c:518 (gdb+0xa183fd)
#21 execute_cmdargs gdb/main.c:617 (gdb+0xa185bf)
#22 captured_main_1 gdb/main.c:1289 (gdb+0xa1aad8)
#23 captured_main gdb/main.c:1310 (gdb+0xa1b9da)
#24 gdb_main(captured_main_args*) gdb/main.c:1339 (gdb+0xa1b9da)
#25 main gdb/gdb.c:39 (gdb+0x42506a)
Previous read of size 1 at 0x7b200000410d by thread T2:
#0 write_gdbindex gdb/dwarf2/index-write.c:1214 (gdb+0x75bb30)
#1 write_dwarf_index(dwarf2_per_bfd*, char const*, char const*, char const*, dw_index_kind) gdb/dwarf2/index-write.c:1469 (gdb+0x75f803)
#2 index_cache::store(dwarf2_per_bfd*, index_cache_store_context const&) gdb/dwarf2/index-cache.c:173 (gdb+0x755a36)
#3 cooked_index::maybe_write_index(dwarf2_per_bfd*, index_cache_store_context const&) gdb/dwarf2/cooked-index.c:642 (gdb+0x71c96d)
#4 operator() gdb/dwarf2/cooked-index.c:471 (gdb+0x71c96d)
#5 _M_invoke /usr/include/c++/7/bits/std_function.h:316 (gdb+0x71c96d)
#6 std::function<void ()>::operator()() const /usr/include/c++/7/bits/std_function.h:706 (gdb+0x72a57c)
#7 void std::__invoke_impl<void, std::function<void ()>&>(std::__invoke_other, std::function<void ()>&) /usr/include/c++/7/bits/invoke.h:60 (gdb+0x72a5db)
#8 std::__invoke_result<std::function<void ()>&>::type std::__invoke<std::function<void ()>&>(std::function<void ()>&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x72a5db)
#9 std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}::operator()() const /usr/include/c++/7/future:1421 (gdb+0x72a5db)
#10 std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}, void>::operator()() const /usr/include/c++/7/future:1362 (gdb+0x72a5db)
#11 std::_Function_handler<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> (), std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}, void> >::_M_invoke(std::_Any_data const&) /usr/include/c++/7/bits/std_function.h:302 (gdb+0x72a5db)
#12 std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>::operator()() const /usr/include/c++/7/bits/std_function.h:706 (gdb+0x724954)
#13 std::__future_base::_State_baseV2::_M_do_set(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*) /usr/include/c++/7/future:561 (gdb+0x724954)
#14 void std::__invoke_impl<void, void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::__invoke_memfun_deref, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/7/bits/invoke.h:73 (gdb+0x72434a)
#15 std::__invoke_result<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>::type std::__invoke<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x72434a)
#16 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#1}::operator()() const /usr/include/c++/7/mutex:672 (gdb+0x72434a)
#17 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#2}::operator()() const /usr/include/c++/7/mutex:677 (gdb+0x72434a)
#18 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#2}::_FUN() /usr/include/c++/7/mutex:677 (gdb+0x72434a)
#19 pthread_once <null> (libtsan.so.0+0x4457c)
#20 __gthread_once /usr/include/c++/7/x86_64-suse-linux/bits/gthr-default.h:699 (gdb+0x72532b)
#21 void std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/7/mutex:684 (gdb+0x72532b)
#22 std::__future_base::_State_baseV2::_M_set_result(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>, bool) /usr/include/c++/7/future:401 (gdb+0x174570d)
#23 std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run() /usr/include/c++/7/future:1423 (gdb+0x174570d)
#24 std::packaged_task<void ()>::operator()() /usr/include/c++/7/future:1556 (gdb+0x174570d)
#25 gdb::thread_pool::thread_function() gdbsupport/thread-pool.cc:242 (gdb+0x174570d)
#26 void std::__invoke_impl<void, void (gdb::thread_pool::*)(), gdb::thread_pool*>(std::__invoke_memfun_deref, void (gdb::thread_pool::*&&)(), gdb::thread_pool*&&) /usr/include/c++/7/bits/invoke.h:73 (gdb+0x17480c0)
#27 std::__invoke_result<void (gdb::thread_pool::*)(), gdb::thread_pool*>::type std::__invoke<void (gdb::thread_pool::*)(), gdb::thread_pool*>(void (gdb::thread_pool::*&&)(), gdb::thread_pool*&&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x17480c0)
#28 decltype (__invoke((_S_declval<0ul>)(), (_S_declval<1ul>)())) std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> >::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>) /usr/include/c++/7/thread:234 (gdb+0x17480c0)
#29 std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> >::operator()() /usr/include/c++/7/thread:243 (gdb+0x17480c0)
#30 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> > >::_M_run() /usr/include/c++/7/thread:186 (gdb+0x17480c0)
#31 <null> <null> (libstdc++.so.6+0xdcac2)
...
SUMMARY: ThreadSanitizer: data race gdb/dwarf2/read.c:2033 in dw2_get_file_names_reader
...
The race happens when issuing the "file $exec" command.
The race is between:
- a worker thread writing the index cache, and in the process reading
dwarf2_per_cu_data::is_debug_type, and
- the main thread writing to dwarf2_per_cu_data::files_read.
The two bitfields dwarf2_per_cu_data::files_read and
dwarf2_per_cu_data::is_debug_type share the same bitfield container.
Fix this by making dwarf2_per_cu_data::files_read a packed<bool, 1>.
Tested on x86_64-linux.
PR symtab/30718
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30718
|
||
|
|
38ef7c3513 |
[gdb/symtab] Fix data race on dwarf2_per_cu_data::{mark,is_debug_types}
With gdb build with -fsanitize=thread, and the exec from test-case
gdb.base/index-cache.exp, I run into:
...
$ rm -f ~/.cache/gdb/*; \
gdb -q -batch -iex "set index-cache enabled on" index-cache \
-ex "print foobar"
...
WARNING: ThreadSanitizer: data race (pid=23970)
Write of size 1 at 0x7b200000410d by main thread:
#0 dw_expand_symtabs_matching_file_matcher(dwarf2_per_objfile*, gdb::function_view<bool (char const*, bool)>) gdb/dwarf2/read.c:3077 (gdb+0x7ac54e)
#1 cooked_index_functions::expand_symtabs_matching(objfile*, gdb::function_view<bool (char const*, bool)>, lookup_name_info const*, gdb::function_view<bool (char const*)>, gdb::function_view<bool (compunit_symtab*)>, enum_flags<block_search_flag_values>, domain_enum, search_domain) gdb/dwarf2/read.c:16812 (gdb+0x7d039f)
#2 objfile::map_symtabs_matching_filename(char const*, char const*, gdb::function_view<bool (symtab*)>) gdb/symfile-debug.c:219 (gdb+0xda5aee)
#3 iterate_over_symtabs(char const*, gdb::function_view<bool (symtab*)>) gdb/symtab.c:648 (gdb+0xdc439d)
#4 lookup_symtab(char const*) gdb/symtab.c:662 (gdb+0xdc44a2)
#5 classify_name gdb/c-exp.y:3083 (gdb+0x61afec)
#6 c_yylex gdb/c-exp.y:3251 (gdb+0x61dd13)
#7 c_yyparse() build/gdb/c-exp.c.tmp:1988 (gdb+0x61f07e)
#8 c_parse(parser_state*) gdb/c-exp.y:3417 (gdb+0x62d864)
#9 language_defn::parser(parser_state*) const gdb/language.c:598 (gdb+0x9771c5)
#10 parse_exp_in_context gdb/parse.c:414 (gdb+0xb10a9b)
#11 parse_expression(char const*, innermost_block_tracker*, enum_flags<parser_flag>) gdb/parse.c:462 (gdb+0xb110ae)
#12 process_print_command_args gdb/printcmd.c:1321 (gdb+0xb4bf0c)
#13 print_command_1 gdb/printcmd.c:1335 (gdb+0xb4ca2a)
#14 print_command gdb/printcmd.c:1468 (gdb+0xb4cd5a)
#15 do_simple_func gdb/cli/cli-decode.c:95 (gdb+0x65b078)
#16 cmd_func(cmd_list_element*, char const*, int) gdb/cli/cli-decode.c:2735 (gdb+0x65ed53)
#17 execute_command(char const*, int) gdb/top.c:575 (gdb+0xe3a76a)
#18 catch_command_errors gdb/main.c:518 (gdb+0xa1837d)
#19 execute_cmdargs gdb/main.c:617 (gdb+0xa1853f)
#20 captured_main_1 gdb/main.c:1289 (gdb+0xa1aa58)
#21 captured_main gdb/main.c:1310 (gdb+0xa1b95a)
#22 gdb_main(captured_main_args*) gdb/main.c:1339 (gdb+0xa1b95a)
#23 main gdb/gdb.c:39 (gdb+0x42506a)
Previous read of size 1 at 0x7b200000410d by thread T1:
#0 write_gdbindex gdb/dwarf2/index-write.c:1214 (gdb+0x75bb30)
#1 write_dwarf_index(dwarf2_per_bfd*, char const*, char const*, char const*, dw_index_kind) gdb/dwarf2/index-write.c:1469 (gdb+0x75f803)
#2 index_cache::store(dwarf2_per_bfd*, index_cache_store_context const&) gdb/dwarf2/index-cache.c:173 (gdb+0x755a36)
#3 cooked_index::maybe_write_index(dwarf2_per_bfd*, index_cache_store_context const&) gdb/dwarf2/cooked-index.c:642 (gdb+0x71c96d)
#4 operator() gdb/dwarf2/cooked-index.c:471 (gdb+0x71c96d)
#5 _M_invoke /usr/include/c++/7/bits/std_function.h:316 (gdb+0x71c96d)
#6 std::function<void ()>::operator()() const /usr/include/c++/7/bits/std_function.h:706 (gdb+0x72a57c)
#7 void std::__invoke_impl<void, std::function<void ()>&>(std::__invoke_other, std::function<void ()>&) /usr/include/c++/7/bits/invoke.h:60 (gdb+0x72a5db)
#8 std::__invoke_result<std::function<void ()>&>::type std::__invoke<std::function<void ()>&>(std::function<void ()>&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x72a5db)
#9 std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}::operator()() const /usr/include/c++/7/future:1421 (gdb+0x72a5db)
#10 std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}, void>::operator()() const /usr/include/c++/7/future:1362 (gdb+0x72a5db)
#11 std::_Function_handler<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> (), std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}, void> >::_M_invoke(std::_Any_data const&) /usr/include/c++/7/bits/std_function.h:302 (gdb+0x72a5db)
#12 std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>::operator()() const /usr/include/c++/7/bits/std_function.h:706 (gdb+0x724954)
#13 std::__future_base::_State_baseV2::_M_do_set(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*) /usr/include/c++/7/future:561 (gdb+0x724954)
#14 void std::__invoke_impl<void, void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::__invoke_memfun_deref, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/7/bits/invoke.h:73 (gdb+0x72434a)
#15 std::__invoke_result<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>::type std::__invoke<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x72434a)
#16 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#1}::operator()() const /usr/include/c++/7/mutex:672 (gdb+0x72434a)
#17 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#2}::operator()() const /usr/include/c++/7/mutex:677 (gdb+0x72434a)
#18 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#2}::_FUN() /usr/include/c++/7/mutex:677 (gdb+0x72434a)
#19 pthread_once <null> (libtsan.so.0+0x4457c)
#20 __gthread_once /usr/include/c++/7/x86_64-suse-linux/bits/gthr-default.h:699 (gdb+0x72532b)
#21 void std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/7/mutex:684 (gdb+0x72532b)
#22 std::__future_base::_State_baseV2::_M_set_result(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>, bool) /usr/include/c++/7/future:401 (gdb+0x174568d)
#23 std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run() /usr/include/c++/7/future:1423 (gdb+0x174568d)
#24 std::packaged_task<void ()>::operator()() /usr/include/c++/7/future:1556 (gdb+0x174568d)
#25 gdb::thread_pool::thread_function() gdbsupport/thread-pool.cc:242 (gdb+0x174568d)
#26 void std::__invoke_impl<void, void (gdb::thread_pool::*)(), gdb::thread_pool*>(std::__invoke_memfun_deref, void (gdb::thread_pool::*&&)(), gdb::thread_pool*&&) /usr/include/c++/7/bits/invoke.h:73 (gdb+0x1748040)
#27 std::__invoke_result<void (gdb::thread_pool::*)(), gdb::thread_pool*>::type std::__invoke<void (gdb::thread_pool::*)(), gdb::thread_pool*>(void (gdb::thread_pool::*&&)(), gdb::thread_pool*&&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x1748040)
#28 decltype (__invoke((_S_declval<0ul>)(), (_S_declval<1ul>)())) std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> >::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>) /usr/include/c++/7/thread:234 (gdb+0x1748040)
#29 std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> >::operator()() /usr/include/c++/7/thread:243 (gdb+0x1748040)
#30 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> > >::_M_run() /usr/include/c++/7/thread:186 (gdb+0x1748040)
#31 <null> <null> (libstdc++.so.6+0xdcac2)
...
SUMMARY: ThreadSanitizer: data race gdb/dwarf2/read.c:3077 in dw_expand_symtabs_matching_file_matcher(dwarf2_per_objfile*, gdb::function_view<bool (char const*, bool)>)
...
The race happens when issuing the "file $exec" command.
The race is between:
- a worker thread writing the index cache, and in the process reading
dwarf2_per_cu_data::is_debug_type, and
- the main thread writing to dwarf2_per_cu_data::mark.
The two bitfields dwarf2_per_cu_data::mark and
dwarf2_per_cu_data::is_debug_type share the same bitfield container.
Fix this by making dwarf2_per_cu_data::mark a packed<unsigned int, 1>.
Tested on x86_64-linux.
PR symtab/30718
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30718
|
||
|
|
edb157dfc6 |
[gdb/symtab] Fix data race on dwarf2_per_cu_data::{m_header_read_in,is_debug_type}
With gdb build with -fsanitize=thread and test-case gdb.base/index-cache.exp
and target board debug-types, I run into:
...
(gdb) file build/gdb/testsuite/outputs/gdb.base/index-cache/index-cache
Reading symbols from build/gdb/testsuite/outputs/gdb.base/index-cache/index-cache...
==================
WARNING: ThreadSanitizer: data race (pid=9654)
Write of size 1 at 0x7b200000420d by main thread:
#0 dwarf2_per_cu_data::get_header() const gdb/dwarf2/read.c:21513 (gdb+0x8d1eee)
#1 dwarf2_per_cu_data::addr_size() const gdb/dwarf2/read.c:21524 (gdb+0x8d1f4e)
#2 dwarf2_cu::addr_type() const gdb/dwarf2/cu.c:112 (gdb+0x806327)
#3 set_die_type gdb/dwarf2/read.c:21932 (gdb+0x8d3870)
#4 read_base_type gdb/dwarf2/read.c:15448 (gdb+0x8bcacb)
#5 read_type_die_1 gdb/dwarf2/read.c:19832 (gdb+0x8cc0a5)
#6 read_type_die gdb/dwarf2/read.c:19767 (gdb+0x8cbe6d)
#7 lookup_die_type gdb/dwarf2/read.c:19739 (gdb+0x8cbdc7)
#8 die_type gdb/dwarf2/read.c:19593 (gdb+0x8cb68a)
#9 read_subroutine_type gdb/dwarf2/read.c:14648 (gdb+0x8b998e)
#10 read_type_die_1 gdb/dwarf2/read.c:19792 (gdb+0x8cbf2f)
#11 read_type_die gdb/dwarf2/read.c:19767 (gdb+0x8cbe6d)
#12 read_func_scope gdb/dwarf2/read.c:10154 (gdb+0x8a4f36)
#13 process_die gdb/dwarf2/read.c:6667 (gdb+0x898daa)
#14 read_file_scope gdb/dwarf2/read.c:7682 (gdb+0x89bad8)
#15 process_die gdb/dwarf2/read.c:6654 (gdb+0x898ced)
#16 process_full_comp_unit gdb/dwarf2/read.c:6418 (gdb+0x8981de)
#17 process_queue gdb/dwarf2/read.c:5690 (gdb+0x894433)
#18 dw2_do_instantiate_symtab gdb/dwarf2/read.c:1770 (gdb+0x88623a)
#19 dw2_instantiate_symtab gdb/dwarf2/read.c:1792 (gdb+0x886300)
#20 dw2_expand_symtabs_matching_one(dwarf2_per_cu_data*, dwarf2_per_objfile*, gdb::function_view<bool (char const*, bool)>, gdb::function_view<bool (compunit_symtab*)>) gdb/dwarf2/read.c:3042 (gdb+0x88b1f1)
#21 cooked_index_functions::expand_symtabs_matching(objfile*, gdb::function_view<bool (char const*, bool)>, lookup_name_info const*, gdb::function_view<bool (char const*)>, gdb::function_view<bool (compunit_symtab*)>, enum_flags<block_search_flag_values>, domain_enum, search_domain) gdb/dwarf2/read.c:16917 (gdb+0x8c228e)
#22 objfile::lookup_symbol(block_enum, char const*, domain_enum) gdb/symfile-debug.c:288 (gdb+0xf39055)
#23 lookup_symbol_via_quick_fns gdb/symtab.c:2385 (gdb+0xf66ab7)
#24 lookup_symbol_in_objfile gdb/symtab.c:2516 (gdb+0xf6711b)
#25 operator() gdb/symtab.c:2562 (gdb+0xf67272)
#26 operator() gdb/../gdbsupport/function-view.h:305 (gdb+0xf776b1)
#27 _FUN gdb/../gdbsupport/function-view.h:299 (gdb+0xf77708)
#28 gdb::function_view<bool (objfile*)>::operator()(objfile*) const gdb/../gdbsupport/function-view.h:289 (gdb+0xc3fc97)
#29 svr4_iterate_over_objfiles_in_search_order gdb/solib-svr4.c:3455 (gdb+0xecae47)
#30 gdbarch_iterate_over_objfiles_in_search_order(gdbarch*, gdb::function_view<bool (objfile*)>, objfile*) gdb/gdbarch.c:5041 (gdb+0x537cad)
#31 lookup_global_or_static_symbol gdb/symtab.c:2559 (gdb+0xf674fb)
#32 lookup_global_symbol(char const*, block const*, domain_enum) gdb/symtab.c:2615 (gdb+0xf67780)
#33 language_defn::lookup_symbol_nonlocal(char const*, block const*, domain_enum) const gdb/symtab.c:2447 (gdb+0xf66d6e)
#34 lookup_symbol_aux gdb/symtab.c:2123 (gdb+0xf65cb3)
#35 lookup_symbol_in_language(char const*, block const*, domain_enum, language, field_of_this_result*) gdb/symtab.c:1931 (gdb+0xf64dab)
#36 set_initial_language() gdb/symfile.c:1708 (gdb+0xf43074)
#37 symbol_file_add_main_1 gdb/symfile.c:1212 (gdb+0xf41608)
#38 symbol_file_command(char const*, int) gdb/symfile.c:1681 (gdb+0xf42faf)
#39 file_command gdb/exec.c:554 (gdb+0x94ff29)
#40 do_simple_func gdb/cli/cli-decode.c:95 (gdb+0x6d9528)
#41 cmd_func(cmd_list_element*, char const*, int) gdb/cli/cli-decode.c:2735 (gdb+0x6e0f69)
#42 execute_command(char const*, int) gdb/top.c:575 (gdb+0xff379c)
#43 command_handler(char const*) gdb/event-top.c:552 (gdb+0x94b5bc)
#44 command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) gdb/event-top.c:788 (gdb+0x94bc79)
#45 tui_command_line_handler gdb/tui/tui-interp.c:104 (gdb+0x1034efc)
#46 gdb_rl_callback_handler gdb/event-top.c:259 (gdb+0x94ab61)
#47 rl_callback_read_char readline/readline/callback.c:290 (gdb+0x11be4ef)
#48 gdb_rl_callback_read_char_wrapper_noexcept gdb/event-top.c:195 (gdb+0x94a960)
#49 gdb_rl_callback_read_char_wrapper gdb/event-top.c:234 (gdb+0x94aa21)
#50 stdin_event_handler gdb/ui.c:155 (gdb+0x10751a0)
#51 handle_file_event gdbsupport/event-loop.cc:573 (gdb+0x1d95bac)
#52 gdb_wait_for_event gdbsupport/event-loop.cc:694 (gdb+0x1d962e4)
#53 gdb_do_one_event(int) gdbsupport/event-loop.cc:264 (gdb+0x1d946d0)
#54 start_event_loop gdb/main.c:412 (gdb+0xb5ab52)
#55 captured_command_loop gdb/main.c:476 (gdb+0xb5ad41)
#56 captured_main gdb/main.c:1320 (gdb+0xb5cec1)
#57 gdb_main(captured_main_args*) gdb/main.c:1339 (gdb+0xb5cf70)
#58 main gdb/gdb.c:32 (gdb+0x416776)
Previous read of size 1 at 0x7b200000420d by thread T11:
#0 write_gdbindex gdb/dwarf2/index-write.c:1229 (gdb+0x831630)
#1 write_dwarf_index(dwarf2_per_bfd*, char const*, char const*, char const*, dw_index_kind) gdb/dwarf2/index-write.c:1484 (gdb+0x832897)
#2 index_cache::store(dwarf2_per_bfd*, index_cache_store_context const&) gdb/dwarf2/index-cache.c:173 (gdb+0x82db8d)
#3 cooked_index::maybe_write_index(dwarf2_per_bfd*, index_cache_store_context const&) gdb/dwarf2/cooked-index.c:645 (gdb+0x7f1d49)
#4 operator() gdb/dwarf2/cooked-index.c:474 (gdb+0x7f0f31)
#5 _M_invoke /usr/include/c++/7/bits/std_function.h:316 (gdb+0x7f2a13)
#6 std::function<void ()>::operator()() const /usr/include/c++/7/bits/std_function.h:706 (gdb+0x700952)
#7 void std::__invoke_impl<void, std::function<void ()>&>(std::__invoke_other, std::function<void ()>&) /usr/include/c++/7/bits/invoke.h:60 (gdb+0x7381a0)
#8 std::__invoke_result<std::function<void ()>&>::type std::__invoke<std::function<void ()>&>(std::function<void ()>&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x737e91)
#9 std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}::operator()() const /usr/include/c++/7/future:1421 (gdb+0x737b59)
#10 std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}, void>::operator()() const /usr/include/c++/7/future:1362 (gdb+0x738660)
#11 std::_Function_handler<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> (), std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}, void> >::_M_invoke(std::_Any_data const&) /usr/include/c++/7/bits/std_function.h:302 (gdb+0x73825c)
#12 std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>::operator()() const /usr/include/c++/7/bits/std_function.h:706 (gdb+0x733623)
#13 std::__future_base::_State_baseV2::_M_do_set(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*) /usr/include/c++/7/future:561 (gdb+0x732bdf)
#14 void std::__invoke_impl<void, void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::__invoke_memfun_deref, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/7/bits/invoke.h:73 (gdb+0x734c4f)
#15 std::__invoke_result<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>::type std::__invoke<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x733bc5)
#16 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#1}::operator()() const /usr/include/c++/7/mutex:672 (gdb+0x73300d)
#17 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#2}::operator()() const /usr/include/c++/7/mutex:677 (gdb+0x7330b2)
#18 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#2}::_FUN() /usr/include/c++/7/mutex:677 (gdb+0x7330f2)
#19 pthread_once <null> (libtsan.so.0+0x4457c)
#20 __gthread_once /usr/include/c++/7/x86_64-suse-linux/bits/gthr-default.h:699 (gdb+0x72f5dd)
#21 void std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/7/mutex:684 (gdb+0x733224)
#22 std::__future_base::_State_baseV2::_M_set_result(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>, bool) /usr/include/c++/7/future:401 (gdb+0x732852)
#23 std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run() /usr/include/c++/7/future:1423 (gdb+0x737bef)
#24 std::packaged_task<void ()>::operator()() /usr/include/c++/7/future:1556 (gdb+0x1dad25a)
#25 gdb::thread_pool::thread_function() gdbsupport/thread-pool.cc:242 (gdb+0x1dacb7c)
#26 void std::__invoke_impl<void, void (gdb::thread_pool::*)(), gdb::thread_pool*>(std::__invoke_memfun_deref, void (gdb::thread_pool::*&&)(), gdb::thread_pool*&&) /usr/include/c++/7/bits/invoke.h:73 (gdb+0x1dadc2b)
#27 std::__invoke_result<void (gdb::thread_pool::*)(), gdb::thread_pool*>::type std::__invoke<void (gdb::thread_pool::*)(), gdb::thread_pool*>(void (gdb::thread_pool::*&&)(), gdb::thread_pool*&&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x1dad05c)
#28 decltype (__invoke((_S_declval<0ul>)(), (_S_declval<1ul>)())) std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> >::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>) /usr/include/c++/7/thread:234 (gdb+0x1db038e)
#29 std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> >::operator()() /usr/include/c++/7/thread:243 (gdb+0x1db0319)
#30 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> > >::_M_run() /usr/include/c++/7/thread:186 (gdb+0x1db02ce)
#31 <null> <null> (libstdc++.so.6+0xdcac2)
...
SUMMARY: ThreadSanitizer: data race gdb/dwarf2/read.c:21513 in dwarf2_per_cu_data::get_header() const
...
The race happens when issuing the "file $exec" command.
The race is between:
- a worker thread writing the index cache, and in the process reading
dwarf2_per_cu_data::is_debug_type, and
- the main thread writing to dwarf2_per_cu_data::m_header_read_in.
The two bitfields dwarf2_per_cu_data::m_header_read_in and
dwarf2_per_cu_data::is_debug_type share the same bitfield container.
Fix this by making dwarf2_per_cu_data::m_header_read_in a packed<bool, 1>.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
PR symtab/30392
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30392
|
||
|
|
12afdeecc9 |
[gdb/symtab] Fix race on dwarf2_per_cu_data::{queued,is_debug_type}
With gdb build with -fsanitize=thread and test-case gdb.base/index-cache.exp I
run into:
...
(gdb) file build/gdb/testsuite/outputs/gdb.base/index-cache/index-cache
Reading symbols from build/gdb/testsuite/outputs/gdb.base/index-cache/index-cache...
==================
WARNING: ThreadSanitizer: data race (pid=24296)
Write of size 1 at 0x7b200000420d by main thread:
#0 queue_comp_unit gdb/dwarf2/read.c:5564 (gdb+0x8939ce)
#1 dw2_do_instantiate_symtab gdb/dwarf2/read.c:1754 (gdb+0x885b96)
#2 dw2_instantiate_symtab gdb/dwarf2/read.c:1792 (gdb+0x885d86)
#3 dw2_expand_symtabs_matching_one(dwarf2_per_cu_data*, dwarf2_per_objfile*, gdb::function_view<bool (char const*, bool)>, gdb::function_view<bool (compunit_symtab*)>) gdb/dwarf2/read.c:3042 (gdb+0x88ac77)
#4 cooked_index_functions::expand_symtabs_matching(objfile*, gdb::function_view<bool (char const*, bool)>, lookup_name_info const*, gdb::function_view<bool (char const*)>, gdb::function_view<bool (compunit_symtab*)>, enum_flags<block_search_flag_values>, domain_enum, search_domain) gdb/dwarf2/read.c:16915 (gdb+0x8c1c8a)
#5 objfile::lookup_symbol(block_enum, char const*, domain_enum) gdb/symfile-debug.c:288 (gdb+0xf389a1)
#6 lookup_symbol_via_quick_fns gdb/symtab.c:2385 (gdb+0xf66403)
#7 lookup_symbol_in_objfile gdb/symtab.c:2516 (gdb+0xf66a67)
#8 operator() gdb/symtab.c:2562 (gdb+0xf66bbe)
#9 operator() gdb/../gdbsupport/function-view.h:305 (gdb+0xf76ffd)
#10 _FUN gdb/../gdbsupport/function-view.h:299 (gdb+0xf77054)
#11 gdb::function_view<bool (objfile*)>::operator()(objfile*) const gdb/../gdbsupport/function-view.h:289 (gdb+0xc3f5e3)
#12 svr4_iterate_over_objfiles_in_search_order gdb/solib-svr4.c:3455 (gdb+0xeca793)
#13 gdbarch_iterate_over_objfiles_in_search_order(gdbarch*, gdb::function_view<bool (objfile*)>, objfile*) gdb/gdbarch.c:5041 (gdb+0x537cad)
#14 lookup_global_or_static_symbol gdb/symtab.c:2559 (gdb+0xf66e47)
#15 lookup_global_symbol(char const*, block const*, domain_enum) gdb/symtab.c:2615 (gdb+0xf670cc)
#16 language_defn::lookup_symbol_nonlocal(char const*, block const*, domain_enum) const gdb/symtab.c:2447 (gdb+0xf666ba)
#17 lookup_symbol_aux gdb/symtab.c:2123 (gdb+0xf655ff)
#18 lookup_symbol_in_language(char const*, block const*, domain_enum, language, field_of_this_result*) gdb/symtab.c:1931 (gdb+0xf646f7)
#19 set_initial_language() gdb/symfile.c:1708 (gdb+0xf429c0)
#20 symbol_file_add_main_1 gdb/symfile.c:1212 (gdb+0xf40f54)
#21 symbol_file_command(char const*, int) gdb/symfile.c:1681 (gdb+0xf428fb)
#22 file_command gdb/exec.c:554 (gdb+0x94f875)
#23 do_simple_func gdb/cli/cli-decode.c:95 (gdb+0x6d9528)
#24 cmd_func(cmd_list_element*, char const*, int) gdb/cli/cli-decode.c:2735 (gdb+0x6e0f69)
#25 execute_command(char const*, int) gdb/top.c:575 (gdb+0xff3166)
#26 command_handler(char const*) gdb/event-top.c:552 (gdb+0x94af08)
#27 command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) gdb/event-top.c:788 (gdb+0x94b5c5)
#28 tui_command_line_handler gdb/tui/tui-interp.c:104 (gdb+0x10348c6)
#29 gdb_rl_callback_handler gdb/event-top.c:259 (gdb+0x94a4ad)
#30 rl_callback_read_char readline/readline/callback.c:290 (gdb+0x11bdf87)
#31 gdb_rl_callback_read_char_wrapper_noexcept gdb/event-top.c:195 (gdb+0x94a2ac)
#32 gdb_rl_callback_read_char_wrapper gdb/event-top.c:234 (gdb+0x94a36d)
#33 stdin_event_handler gdb/ui.c:155 (gdb+0x1074b6a)
#34 handle_file_event gdbsupport/event-loop.cc:573 (gdb+0x1d9502c)
#35 gdb_wait_for_event gdbsupport/event-loop.cc:694 (gdb+0x1d95764)
#36 gdb_do_one_event(int) gdbsupport/event-loop.cc:264 (gdb+0x1d93b50)
#37 start_event_loop gdb/main.c:412 (gdb+0xb5a49e)
#38 captured_command_loop gdb/main.c:476 (gdb+0xb5a68d)
#39 captured_main gdb/main.c:1320 (gdb+0xb5c80d)
#40 gdb_main(captured_main_args*) gdb/main.c:1339 (gdb+0xb5c8bc)
#41 main gdb/gdb.c:32 (gdb+0x416776)
Previous read of size 1 at 0x7b200000420d by thread T12:
#0 write_gdbindex gdb/dwarf2/index-write.c:1229 (gdb+0x8310c8)
#1 write_dwarf_index(dwarf2_per_bfd*, char const*, char const*, char const*, dw_index_kind) gdb/dwarf2/index-write.c:1484 (gdb+0x83232f)
#2 index_cache::store(dwarf2_per_bfd*, index_cache_store_context*) gdb/dwarf2/index-cache.c:177 (gdb+0x82d62b)
#3 cooked_index::maybe_write_index(dwarf2_per_bfd*) gdb/dwarf2/cooked-index.c:640 (gdb+0x7f1bf7)
#4 operator() gdb/dwarf2/cooked-index.c:470 (gdb+0x7f0f40)
#5 _M_invoke /usr/include/c++/7/bits/std_function.h:316 (gdb+0x7f2909)
#6 std::function<void ()>::operator()() const /usr/include/c++/7/bits/std_function.h:706 (gdb+0x700952)
#7 void std::__invoke_impl<void, std::function<void ()>&>(std::__invoke_other, std::function<void ()>&) /usr/include/c++/7/bits/invoke.h:60 (gdb+0x7381a0)
#8 std::__invoke_result<std::function<void ()>&>::type std::__invoke<std::function<void ()>&>(std::function<void ()>&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x737e91)
#9 std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}::operator()() const /usr/include/c++/7/future:1421 (gdb+0x737b59)
#10 std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}, void>::operator()() const /usr/include/c++/7/future:1362 (gdb+0x738660)
#11 std::_Function_handler<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> (), std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}, void> >::_M_invoke(std::_Any_data const&) /usr/include/c++/7/bits/std_function.h:302 (gdb+0x73825c)
#12 std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>::operator()() const /usr/include/c++/7/bits/std_function.h:706 (gdb+0x733623)
#13 std::__future_base::_State_baseV2::_M_do_set(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*) /usr/include/c++/7/future:561 (gdb+0x732bdf)
#14 void std::__invoke_impl<void, void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::__invoke_memfun_deref, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/7/bits/invoke.h:73 (gdb+0x734c4f)
#15 std::__invoke_result<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>::type std::__invoke<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x733bc5)
#16 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#1}::operator()() const /usr/include/c++/7/mutex:672 (gdb+0x73300d)
#17 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#2}::operator()() const /usr/include/c++/7/mutex:677 (gdb+0x7330b2)
#18 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#2}::_FUN() /usr/include/c++/7/mutex:677 (gdb+0x7330f2)
#19 pthread_once <null> (libtsan.so.0+0x4457c)
#20 __gthread_once /usr/include/c++/7/x86_64-suse-linux/bits/gthr-default.h:699 (gdb+0x72f5dd)
#21 void std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/7/mutex:684 (gdb+0x733224)
#22 std::__future_base::_State_baseV2::_M_set_result(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>, bool) /usr/include/c++/7/future:401 (gdb+0x732852)
#23 std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run() /usr/include/c++/7/future:1423 (gdb+0x737bef)
#24 std::packaged_task<void ()>::operator()() /usr/include/c++/7/future:1556 (gdb+0x1dac6da)
#25 gdb::thread_pool::thread_function() gdbsupport/thread-pool.cc:242 (gdb+0x1dabffc)
#26 void std::__invoke_impl<void, void (gdb::thread_pool::*)(), gdb::thread_pool*>(std::__invoke_memfun_deref, void (gdb::thread_pool::*&&)(), gdb::thread_pool*&&) /usr/include/c++/7/bits/invoke.h:73 (gdb+0x1dad0ab)
#27 std::__invoke_result<void (gdb::thread_pool::*)(), gdb::thread_pool*>::type std::__invoke<void (gdb::thread_pool::*)(), gdb::thread_pool*>(void (gdb::thread_pool::*&&)(), gdb::thread_pool*&&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x1dac4dc)
#28 decltype (__invoke((_S_declval<0ul>)(), (_S_declval<1ul>)())) std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> >::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>) /usr/include/c++/7/thread:234 (gdb+0x1daf80e)
#29 std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> >::operator()() /usr/include/c++/7/thread:243 (gdb+0x1daf799)
#30 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> > >::_M_run() /usr/include/c++/7/thread:186 (gdb+0x1daf74e)
#31 <null> <null> (libstdc++.so.6+0xdcac2)
...
SUMMARY: ThreadSanitizer: data race gdb/dwarf2/read.c:5564 in queue_comp_unit
...
The race happens when issuing the "file $exec" command.
The race is between:
- a worker thread writing the index cache, and in the process reading
dwarf2_per_cu_data::is_debug_type, and
- the main thread expanding the CU containing main, and in the process setting
dwarf2_per_cu_data::queued.
The two bitfields dwarf2_per_cu_data::queue and
dwarf2_per_cu_data::is_debug_type share the same bitfield container.
Fix this by making dwarf2_per_cu_data::queued a packed<bool, 1>.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
PR symtab/30392
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30392
|
||
|
|
488b3ff1fc |
[gdb/symtab] Fix data race on bfd::{cacheable,format}
With gdb build with -fsanitize=thread and test-case gdb.base/index-cache.exp I
run into:
...
(gdb) file build/gdb/testsuite/outputs/gdb.base/index-cache/index-cache
Reading symbols from build/gdb/testsuite/outputs/gdb.base/index-cache/index-cache...
==================
WARNING: ThreadSanitizer: data race (pid=12261)
Write of size 4 at 0x7b4400097d08 by main thread:
#0 bfd_open_file bfd/cache.c:584 (gdb+0x148bb92)
#1 bfd_cache_lookup_worker bfd/cache.c:261 (gdb+0x148b12a)
#2 cache_bseek bfd/cache.c:289 (gdb+0x148b324)
#3 bfd_seek bfd/bfdio.c:459 (gdb+0x1489c31)
#4 _bfd_generic_get_section_contents bfd/libbfd.c:1069 (gdb+0x14977a4)
#5 bfd_get_section_contents bfd/section.c:1606 (gdb+0x149cc7c)
#6 gdb_bfd_scan_elf_dyntag(int, bfd*, unsigned long*, unsigned long*) gdb/solib.c:1601 (gdb+0xed8eca)
#7 elf_locate_base gdb/solib-svr4.c:705 (gdb+0xec28ac)
#8 svr4_iterate_over_objfiles_in_search_order gdb/solib-svr4.c:3430 (gdb+0xeca55d)
#9 gdbarch_iterate_over_objfiles_in_search_order(gdbarch*, gdb::function_view<bool (objfile*)>, objfile*) gdb/gdbarch.c:5041 (gdb+0x537cad)
#10 find_main_name gdb/symtab.c:6270 (gdb+0xf743a5)
#11 main_language() gdb/symtab.c:6313 (gdb+0xf74499)
#12 set_initial_language() gdb/symfile.c:1700 (gdb+0xf4285c)
#13 symbol_file_add_main_1 gdb/symfile.c:1212 (gdb+0xf40e2a)
#14 symbol_file_command(char const*, int) gdb/symfile.c:1681 (gdb+0xf427d1)
#15 file_command gdb/exec.c:554 (gdb+0x94f74b)
#16 do_simple_func gdb/cli/cli-decode.c:95 (gdb+0x6d9528)
#17 cmd_func(cmd_list_element*, char const*, int) gdb/cli/cli-decode.c:2735 (gdb+0x6e0f69)
#18 execute_command(char const*, int) gdb/top.c:575 (gdb+0xff303c)
#19 command_handler(char const*) gdb/event-top.c:552 (gdb+0x94adde)
#20 command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) gdb/event-top.c:788 (gdb+0x94b49b)
#21 tui_command_line_handler gdb/tui/tui-interp.c:104 (gdb+0x103479c)
#22 gdb_rl_callback_handler gdb/event-top.c:259 (gdb+0x94a383)
#23 rl_callback_read_char readline/readline/callback.c:290 (gdb+0x11bde5d)
#24 gdb_rl_callback_read_char_wrapper_noexcept gdb/event-top.c:195 (gdb+0x94a182)
#25 gdb_rl_callback_read_char_wrapper gdb/event-top.c:234 (gdb+0x94a243)
#26 stdin_event_handler gdb/ui.c:155 (gdb+0x1074a40)
#27 handle_file_event gdbsupport/event-loop.cc:573 (gdb+0x1d94f02)
#28 gdb_wait_for_event gdbsupport/event-loop.cc:694 (gdb+0x1d9563a)
#29 gdb_do_one_event(int) gdbsupport/event-loop.cc:264 (gdb+0x1d93a26)
#30 start_event_loop gdb/main.c:412 (gdb+0xb5a374)
#31 captured_command_loop gdb/main.c:476 (gdb+0xb5a563)
#32 captured_main gdb/main.c:1320 (gdb+0xb5c6e3)
#33 gdb_main(captured_main_args*) gdb/main.c:1339 (gdb+0xb5c792)
#34 main gdb/gdb.c:32 (gdb+0x416776)
Previous read of size 1 at 0x7b4400097d08 by thread T12:
#0 bfd_check_format_matches bfd/format.c:323 (gdb+0x1492db4)
#1 bfd_check_format bfd/format.c:94 (gdb+0x1492104)
#2 build_id_bfd_get(bfd*) gdb/build-id.c:42 (gdb+0x6648f7)
#3 index_cache::store(dwarf2_per_bfd*, index_cache_store_context*) gdb/dwarf2/index-cache.c:110 (gdb+0x82d205)
#4 cooked_index::maybe_write_index(dwarf2_per_bfd*) gdb/dwarf2/cooked-index.c:640 (gdb+0x7f1bf1)
#5 operator() gdb/dwarf2/cooked-index.c:470 (gdb+0x7f0f40)
#6 _M_invoke /usr/include/c++/7/bits/std_function.h:316 (gdb+0x7f28f7)
#7 std::function<void ()>::operator()() const /usr/include/c++/7/bits/std_function.h:706 (gdb+0x700952)
#8 void std::__invoke_impl<void, std::function<void ()>&>(std::__invoke_other, std::function<void ()>&) /usr/include/c++/7/bits/invoke.h:60 (gdb+0x7381a0)
#9 std::__invoke_result<std::function<void ()>&>::type std::__invoke<std::function<void ()>&>(std::function<void ()>&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x737e91)
#10 std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}::operator()() const /usr/include/c++/7/future:1421 (gdb+0x737b59)
#11 std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}, void>::operator()() const /usr/include/c++/7/future:1362 (gdb+0x738660)
#12 std::_Function_handler<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> (), std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}, void> >::_M_invoke(std::_Any_data const&) /usr/include/c++/7/bits/std_function.h:302 (gdb+0x73825c)
#13 std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>::operator()() const /usr/include/c++/7/bits/std_function.h:706 (gdb+0x733623)
#14 std::__future_base::_State_baseV2::_M_do_set(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*) /usr/include/c++/7/future:561 (gdb+0x732bdf)
#15 void std::__invoke_impl<void, void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::__invoke_memfun_deref, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/7/bits/invoke.h:73 (gdb+0x734c4f)
#16 std::__invoke_result<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>::type std::__invoke<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x733bc5)
#17 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#1}::operator()() const /usr/include/c++/7/mutex:672 (gdb+0x73300d)
#18 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#2}::operator()() const /usr/include/c++/7/mutex:677 (gdb+0x7330b2)
#19 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#2}::_FUN() /usr/include/c++/7/mutex:677 (gdb+0x7330f2)
#20 pthread_once <null> (libtsan.so.0+0x4457c)
#21 __gthread_once /usr/include/c++/7/x86_64-suse-linux/bits/gthr-default.h:699 (gdb+0x72f5dd)
#22 void std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/7/mutex:684 (gdb+0x733224)
#23 std::__future_base::_State_baseV2::_M_set_result(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>, bool) /usr/include/c++/7/future:401 (gdb+0x732852)
#24 std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run() /usr/include/c++/7/future:1423 (gdb+0x737bef)
#25 std::packaged_task<void ()>::operator()() /usr/include/c++/7/future:1556 (gdb+0x1dac5b0)
#26 gdb::thread_pool::thread_function() gdbsupport/thread-pool.cc:242 (gdb+0x1dabed2)
#27 void std::__invoke_impl<void, void (gdb::thread_pool::*)(), gdb::thread_pool*>(std::__invoke_memfun_deref, void (gdb::thread_pool::*&&)(), gdb::thread_pool*&&) /usr/include/c++/7/bits/invoke.h:73 (gdb+0x1dacf81)
#28 std::__invoke_result<void (gdb::thread_pool::*)(), gdb::thread_pool*>::type std::__invoke<void (gdb::thread_pool::*)(), gdb::thread_pool*>(void (gdb::thread_pool::*&&)(), gdb::thread_pool*&&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x1dac3b2)
#29 decltype (__invoke((_S_declval<0ul>)(), (_S_declval<1ul>)())) std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> >::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>) /usr/include/c++/7/thread:234 (gdb+0x1daf6e4)
#30 std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> >::operator()() /usr/include/c++/7/thread:243 (gdb+0x1daf66f)
#31 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> > >::_M_run() /usr/include/c++/7/thread:186 (gdb+0x1daf624)
#32 <null> <null> (libstdc++.so.6+0xdcac2)
...
SUMMARY: ThreadSanitizer: data race bfd/cache.c:584 in bfd_open_file
...
The race happens when issuing the "file $exec" command.
The race is between:
- a worker thread getting the build id while writing the index cache, and in
the process reading bfd::format, and
- the main thread calling find_main_name, and in the process setting
bfd::cacheable.
The two bitfields bfd::cacheable and bfd::format share the same bitfield
container.
Fix this by capturing the build id in the main thread, and using the captured
value in the worker thread.
Likewise for the dwz build id, which likely suffers from the same issue.
While we're at it, also move the creation of the cache directory to
the index_cache_store_context constructor, to:
- make sure there's no race between subsequent file commands, and
- issue any related warning or error messages during the file command.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
PR symtab/30392
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30392
|
||
|
|
8adc552228 |
[gdb/symtab] Fix data race on index_cache::m_enabled
With gdb build with -fsanitize=thread and test-case gdb.base/index-cache.exp I
run into:
...
(gdb) file build/gdb/testsuite/outputs/gdb.base/index-cache/index-cache
Reading symbols from build/gdb/testsuite/outputs/gdb.base/index-cache/index-cache...
(gdb) show index-cache enabled
The index cache is off.
(gdb) PASS: gdb.base/index-cache.exp: test_basic_stuff: index-cache is disabled by default
set index-cache enabled on
==================
WARNING: ThreadSanitizer: data race (pid=32248)
Write of size 1 at 0x00000321f540 by main thread:
#0 index_cache::enable() gdb/dwarf2/index-cache.c:76 (gdb+0x82cfdd)
#1 set_index_cache_enabled_command gdb/dwarf2/index-cache.c:270 (gdb+0x82d9af)
#2 bool setting::set<bool>(bool const&) gdb/command.h:353 (gdb+0x6fe5f2)
#3 do_set_command(char const*, int, cmd_list_element*) gdb/cli/cli-setshow.c:414 (gdb+0x6fcd21)
#4 execute_command(char const*, int) gdb/top.c:567 (gdb+0xff2e64)
#5 command_handler(char const*) gdb/event-top.c:552 (gdb+0x94acc0)
#6 command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) gdb/event-top.c:788 (gdb+0x94b37d)
#7 tui_command_line_handler gdb/tui/tui-interp.c:104 (gdb+0x103467e)
#8 gdb_rl_callback_handler gdb/event-top.c:259 (gdb+0x94a265)
#9 rl_callback_read_char readline/readline/callback.c:290 (gdb+0x11bdd3f)
#10 gdb_rl_callback_read_char_wrapper_noexcept gdb/event-top.c:195 (gdb+0x94a064)
#11 gdb_rl_callback_read_char_wrapper gdb/event-top.c:234 (gdb+0x94a125)
#12 stdin_event_handler gdb/ui.c:155 (gdb+0x1074922)
#13 handle_file_event gdbsupport/event-loop.cc:573 (gdb+0x1d94de4)
#14 gdb_wait_for_event gdbsupport/event-loop.cc:694 (gdb+0x1d9551c)
#15 gdb_do_one_event(int) gdbsupport/event-loop.cc:264 (gdb+0x1d93908)
#16 start_event_loop gdb/main.c:412 (gdb+0xb5a256)
#17 captured_command_loop gdb/main.c:476 (gdb+0xb5a445)
#18 captured_main gdb/main.c:1320 (gdb+0xb5c5c5)
#19 gdb_main(captured_main_args*) gdb/main.c:1339 (gdb+0xb5c674)
#20 main gdb/gdb.c:32 (gdb+0x416776)
Previous read of size 1 at 0x00000321f540 by thread T12:
#0 index_cache::enabled() const gdb/dwarf2/index-cache.h:48 (gdb+0x82e1a6)
#1 index_cache::store(dwarf2_per_bfd*) gdb/dwarf2/index-cache.c:94 (gdb+0x82d0bc)
#2 cooked_index::maybe_write_index(dwarf2_per_bfd*) gdb/dwarf2/cooked-index.c:638 (gdb+0x7f1b97)
#3 operator() gdb/dwarf2/cooked-index.c:468 (gdb+0x7f0f24)
#4 _M_invoke /usr/include/c++/7/bits/std_function.h:316 (gdb+0x7f285b)
#5 std::function<void ()>::operator()() const /usr/include/c++/7/bits/std_function.h:706 (gdb+0x700952)
#6 void std::__invoke_impl<void, std::function<void ()>&>(std::__invoke_other, std::function<void ()>&) /usr/include/c++/7/bits/invoke.h:60 (gdb+0x7381a0)
#7 std::__invoke_result<std::function<void ()>&>::type std::__invoke<std::function<void ()>&>(std::function<void ()>&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x737e91)
#8 std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}::operator()() const /usr/include/c++/7/future:1421 (gdb+0x737b59)
#9 std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}, void>::operator()() const /usr/include/c++/7/future:1362 (gdb+0x738660)
#10 std::_Function_handler<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> (), std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}, void> >::_M_invoke(std::_Any_data const&) /usr/include/c++/7/bits/std_function.h:302 (gdb+0x73825c)
#11 std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>::operator()() const /usr/include/c++/7/bits/std_function.h:706 (gdb+0x733623)
#12 std::__future_base::_State_baseV2::_M_do_set(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*) /usr/include/c++/7/future:561 (gdb+0x732bdf)
#13 void std::__invoke_impl<void, void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::__invoke_memfun_deref, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/7/bits/invoke.h:73 (gdb+0x734c4f)
#14 std::__invoke_result<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>::type std::__invoke<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x733bc5)
#15 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#1}::operator()() const /usr/include/c++/7/mutex:672 (gdb+0x73300d)
#16 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#2}::operator()() const /usr/include/c++/7/mutex:677 (gdb+0x7330b2)
#17 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#2}::_FUN() /usr/include/c++/7/mutex:677 (gdb+0x7330f2)
#18 pthread_once <null> (libtsan.so.0+0x4457c)
#19 __gthread_once /usr/include/c++/7/x86_64-suse-linux/bits/gthr-default.h:699 (gdb+0x72f5dd)
#20 void std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/7/mutex:684 (gdb+0x733224)
#21 std::__future_base::_State_baseV2::_M_set_result(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>, bool) /usr/include/c++/7/future:401 (gdb+0x732852)
#22 std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run() /usr/include/c++/7/future:1423 (gdb+0x737bef)
#23 std::packaged_task<void ()>::operator()() /usr/include/c++/7/future:1556 (gdb+0x1dac492)
#24 gdb::thread_pool::thread_function() gdbsupport/thread-pool.cc:242 (gdb+0x1dabdb4)
#25 void std::__invoke_impl<void, void (gdb::thread_pool::*)(), gdb::thread_pool*>(std::__invoke_memfun_deref, void (gdb::thread_pool::*&&)(), gdb::thread_pool*&&) /usr/include/c++/7/bits/invoke.h:73 (gdb+0x1dace63)
#26 std::__invoke_result<void (gdb::thread_pool::*)(), gdb::thread_pool*>::type std::__invoke<void (gdb::thread_pool::*)(), gdb::thread_pool*>(void (gdb::thread_pool::*&&)(), gdb::thread_pool*&&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x1dac294)
#27 decltype (__invoke((_S_declval<0ul>)(), (_S_declval<1ul>)())) std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> >::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>) /usr/include/c++/7/thread:234 (gdb+0x1daf5c6)
#28 std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> >::operator()() /usr/include/c++/7/thread:243 (gdb+0x1daf551)
#29 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> > >::_M_run() /usr/include/c++/7/thread:186 (gdb+0x1daf506)
#30 <null> <null> (libstdc++.so.6+0xdcac2)
Location is global 'global_index_cache' of size 48 at 0x00000321f520 (gdb+0x00000321f540)
...
SUMMARY: ThreadSanitizer: data race gdb/dwarf2/index-cache.c:76 in index_cache::enable()
...
The race happens when issuing a "file $exec" command followed by a
"set index-cache enabled on" command.
The race is between:
- a worker thread reading index_cache::m_enabled to determine whether an
index-cache entry for $exec needs to be written
(due to command "file $exec"), and
- the main thread setting index_cache::m_enabled
(due to command "set index-cache enabled on").
Fix this by capturing the value of index_cache::m_enabled in the main thread,
and using the captured value in the worker thread.
Tested on x86_64-linux.
PR symtab/30392
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30392
|
||
|
|
8d76ceb7f1 |
[gdb/symtab] Remove superfluous handling of Ada main in write_cooked_index
I filed PR29179 about the following FAIL in test-case gdb.ada/O2_float_param.exp with target board cc-with-gdb-index: ... (gdb) break increment^M Function "increment" not defined.^M Make breakpoint pending on future shared library load? (y or [n]) n^M (gdb) FAIL: gdb.ada/O2_float_param.exp: scenario=all: gdb_breakpoint: \ set breakpoint at increment ... The FAIL was a regression since commit |
||
|
|
fe34aba060 |
Fix bug in fixed-point handling
Alexandre Oliva found a bug in gdb's handling of fixed-point -- a
certain Ada fixed-point type would be misintepreted. The bug was that
the DW_AT_small looked like:
<1><13cd>: Abbrev Number: 16 (DW_TAG_constant)
<13ce> DW_AT_GNU_numerator: 1
<13cf> DW_AT_GNU_denominator: 0x8000000000000000
... but gdb interpreted the denominator as a negative value.
|
||
|
|
4d051f3a4e |
Fix crash with DW_FORM_implicit_const
Jakub pointed out that using DW_FORM_implicit_const with DW_AT_bit_size would cause gdb to crash. This happened because DW_FORM_implicit_const is not an "unsigned" form, causing as_unsigned to assert. This patch fixes the problem. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30651 Approved-By: Andrew Burgess <aburgess@redhat.com> |
||
|
|
f4c4456eb4 |
[gdb/symtab] Add optimized out static var to cooked index
Consider the test-case:
...
$ cat main.c
int main (void) { return 0; }
$ cat static-optimized-out.c
static int aaa;
...
compiled like this:
...
$ gcc-12 static-optimized-out.c main.c -g -O2 -flto
...
There's a difference in behaviour depending on symtab expansion state:
...
$ gdb -q -batch a.out -ex "print aaa"
No symbol "aaa" in current context.
$ gdb -q -batch a.out -ex "maint expand-symtab" -ex "print aaa"
$1 = <optimized out>
...
The reason for the difference is that the optimized out variable aaa:
...
<1><104>: Abbrev Number: 2 (DW_TAG_variable)
<105> DW_AT_name : aaa
<109> DW_AT_decl_file : 1
<10a> DW_AT_decl_line : 18
<10b> DW_AT_decl_column : 12
<10c> DW_AT_type : <0x110>
...
is not added to the cooked index because of this clause in abbrev_table::read:
...
else if (!has_location && !has_specification_or_origin && !has_external
&& cur_abbrev->tag == DW_TAG_variable)
cur_abbrev->interesting = false;
...
Fix this inconsistency by making sure that the optimized out variable is added
to the cooked index.
Regression tested on x86_64-linux.
Add two test-cases, a C test-case gdb.opt/static-optimized-out.exp and a dwarf
assembly test-case gdb.dwarf2/static-optimized-out.exp.
Tested gdb.opt/static-optimized-out.exp with gcc-8 to gcc-12, for which we now
consistently get:
...
(gdb) print aaa^M
$1 = <optimized out>^M
...
and with gcc 7.5.0 and clang 13.0.1, for which we still consistently get:
...
(gdb) print aaa^M
No symbol "aaa" in current context.^M
...
due to missing debug info for the variable.
PR symtab/30656
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30656
Approved-By: Tom Tromey <tom@tromey.com>
|
||
|
|
6e27b5eb00 |
Fix handling of DW_TAG_unspecified_type for Ada
Commit
|
||
|
|
6f96f4854f |
Use gdb::byte_vector in agent_expr
This changes agent_expr to use gdb::byte_vector rather than manually reimplementing a vector. Reviewed-by: John Baldwin <jhb@FreeBSD.org> |
||
|
|
f3741bbd18 |
Simplify case DW_OP_GNU_uninit in dwarf_expr_context::execute_stack_op
Tom Tromey pointed out that the test and call to error() for the
DW_OP_GNU_uninit case in dwarf_expr_context::execute_stack_op (in
gdb/dwarf2/expr.c)...
if (op_ptr != op_end && *op_ptr != DW_OP_piece
&& *op_ptr != DW_OP_bit_piece)
error (_("DWARF-2 expression error: DW_OP_GNU_uninit must always "
"be the very last op in a DWARF expression or "
"DW_OP_piece/DW_OP_bit_piece piece."));
...could be replaced by a call to dwarf_expr_require_composition which
performs a similar check and outputs a suitable error message.
|
||
|
|
d65befc152 |
Permit DW_OP_GNU_uninit to be used with DW_OP_piece
This commit implements a fix for a bug reported against GDB on Fedora bugzilla... https://bugzilla.redhat.com/show_bug.cgi?id=2166796 The test case in that bug report involved running gdb against the 'jq' program (which is a command-line JSON processor) on Fedora 37. Since the debug info is compiler (and compile-time option) dependent, it won't necessarily show up in other distributions or even past or future versions of Fedora. (E.g. when trying the example shown below on Fedora 38, GDB says that the value of 'value' has been optimized out. I.e. it does not demonstrate the same DWARF error that can be see when using Fedora 37.) That said, on Fedora 37, the bug could be reproduced as follows: [kev@f37-1 ~]$ gdb jq -q -ex 'b src/util.c:415' -ex 'r </dev/null' Reading symbols from jq... This GDB supports auto-downloading debuginfo from the following URLs: <https://debuginfod.fedoraproject.org/> Enable debuginfod for this session? (y or [n]) y Debuginfod has been enabled. To make this setting permanent, add 'set debuginfod enabled on' to .gdbinit. Reading symbols from /home/kev/.cache/debuginfod_client/9d3c8b4197350a190a74972d481de32abf641aa4/debuginfo... No source file named src/util.c. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (src/util.c:415) pending. Starting program: /usr/bin/jq </dev/null [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib64/libthread_db.so.1". Breakpoint 1, jq_util_input_next_input (state=0x55555555d7f0) at src/util.c:416 416 if (state->parser == NULL) { (gdb) p value DWARF-2 expression error: DW_OP_GNU_uninit must always be the very last op. This is undesirable - rather than output an error about the DWARF info, we'd prefer to see a value, even if it is uninitialized. Examination of the debuginfo showed the following: <1><468f1>: Abbrev Number: 112 (DW_TAG_subprogram) <468f2> DW_AT_external : 1 <468f2> DW_AT_name : (indirect string, offset: 0x4781): jq_util_input_next_input <468f6> DW_AT_decl_file : 10 <468f6> DW_AT_decl_line : 411 <468f8> DW_AT_decl_column : 4 <468f9> DW_AT_prototyped : 1 <468f9> DW_AT_type : <0x3f2> <468fd> DW_AT_sibling : <0x4692e> ... <2><46921>: Abbrev Number: 102 (DW_TAG_variable) <46922> DW_AT_name : (indirect string, offset: 0x8cb): value <46926> DW_AT_decl_file : 10 <46926> DW_AT_decl_line : 414 <46928> DW_AT_decl_column : 6 <46929> DW_AT_type : <0x3f2> Note that there's no DW_AT_location, so I looked for an abstract origin entry: <2><2dfa0>: Abbrev Number: 90 (DW_TAG_variable) <2dfa1> DW_AT_abstract_origin: <0x46921> <2dfa5> DW_AT_location : 0x27cf1 (location list) <2dfa9> DW_AT_GNU_locviews: 0x27ce1 (Note that the DW_AT_abstract_origin attribute's value is 0x46921 which is the DIE for the local variable "value".) Looking at the location list, I see: 00027cf1 v000000000000000 v000000000000000 views at 00027ce1 for: 000000000002f8fe 000000000002f92e (DW_OP_reg13 (r13); DW_OP_GNU_uninit; DW_OP_piece: 8; DW_OP_reg12 (r12); DW_OP_GNU_uninit; DW_OP_piece: 8) While DW_OP_GNU_uninit is not the very last op, it is the last op prior to DW_OP_piece. The fix involved changing the DW_OP_GNU_uninit case in dwarf_expr_context::execute_stack_op in gdb/dwarf2/expr.c so that DW_OP_GNU_uninit may appear just before DW_OP_piece. With the fix in place, attempting to print 'value' now looks like this: (gdb) p value $1 = [uninitialized] {kind_flags = 0 '\000', pad_ = 0 '\000', offset = 0, size = 0, u = {ptr = 0x0, number = 0}} Note that "[uninitialized]" is part of the output. (But also note that there's an extra space character.) I've made a new test case, gdb.dwarf2/DW_OP_piece_with_DW_OP_GNU_uninit.exp, by adapting an existing one, gdb.dwarf2/opt-out-not-implptr.exp. Since it uses the DWARF assembler, the test case does not depend on a specific compiler version or compiler options. Tested on Fedora 37 and Fedora 38. |
||
|
|
d0516c8e66 |
Use unrelocated_addr in dwarf2_fde
This changes dwarf2_fde to use the unrelocated_addr type. This pointed out a latent bug in dwarf2_frame_cache, where a relocated address is compared to an unrelocated address. |