c26c6b70cb
Backport upstream commits 1f0fab7ff86, aa19bc1d259, acc117b57f7, aff250145af, and 3644f41dc80. These commits reduce the size of the generated gdb-index file, and also ensure that the gdb-index and dwarf-5 index are generated consistently even as the number of worker threads that GDB uses changes (RHBZ 2232086). The first and third of these patches are refactoring, but are required by the other patches in this series. The second patch fixes a bug that causes the gdb-index files to be (sometimes) bigger than needed. The fourth and fifth patches ensure that the gdb-index and dwarf-5 index (respectively) are generated the same (for the same input binary), regardless of how many worker threads that GDB uses.
102 lines
3.7 KiB
Diff
102 lines
3.7 KiB
Diff
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
|
From: Andrew Burgess <aburgess@redhat.com>
|
|
Date: Mon, 27 Nov 2023 13:19:39 +0000
|
|
Subject: gdb-rhbz-2232086-generate-dwarf-5-index-consistently.patch
|
|
|
|
;; Back-port upstream commit 3644f41dc80 as part of a fix for
|
|
;; non-deterministic gdb-index generation (RH BZ 2232086).
|
|
|
|
gdb: generate dwarf-5 index identically as worker-thread count changes
|
|
|
|
Similar to the previous commit, this commit ensures that the dwarf-5
|
|
index files are generated identically as the number of worker-threads
|
|
changes.
|
|
|
|
Building the dwarf-5 index makes use of a closed hash table, the
|
|
bucket_hash local within debug_names::build(). Entries are added to
|
|
bucket_hash from m_name_to_value_set, which, in turn, is populated
|
|
by calls to debug_names::insert() in write_debug_names. The insert
|
|
calls are ordered based on the entries within the cooked_index, and
|
|
the ordering within cooked_index depends on the number of worker
|
|
threads that GDB is using.
|
|
|
|
My proposal is to sort each chain within the bucket_hash closed hash
|
|
table prior to using this to build the dwarf-5 index.
|
|
|
|
The buckets within bucket_hash will always have the same ordering (for
|
|
a given GDB build with a given executable), and by sorting the chains
|
|
within each bucket, we can be sure that GDB will see each entry in a
|
|
deterministic order.
|
|
|
|
I've extended the index creation test to cover this case.
|
|
|
|
Approved-By: Tom Tromey <tom@tromey.com>
|
|
|
|
diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c
|
|
--- a/gdb/dwarf2/index-write.c
|
|
+++ b/gdb/dwarf2/index-write.c
|
|
@@ -453,6 +453,11 @@ class c_str_view
|
|
return strcmp (m_cstr, other.m_cstr) == 0;
|
|
}
|
|
|
|
+ bool operator< (const c_str_view &other) const
|
|
+ {
|
|
+ return strcmp (m_cstr, other.m_cstr) < 0;
|
|
+ }
|
|
+
|
|
/* Return the underlying C string. Note, the returned string is
|
|
only a reference with lifetime of this object. */
|
|
const char *c_str () const
|
|
@@ -770,10 +775,18 @@ class debug_names
|
|
}
|
|
for (size_t bucket_ix = 0; bucket_ix < bucket_hash.size (); ++bucket_ix)
|
|
{
|
|
- const std::forward_list<hash_it_pair> &hashitlist
|
|
- = bucket_hash[bucket_ix];
|
|
+ std::forward_list<hash_it_pair> &hashitlist = bucket_hash[bucket_ix];
|
|
if (hashitlist.empty ())
|
|
continue;
|
|
+
|
|
+ /* Sort the items within each bucket. This ensures that the
|
|
+ generated index files will be the same no matter the order in
|
|
+ which symbols were added into the index. */
|
|
+ hashitlist.sort ([] (const hash_it_pair &a, const hash_it_pair &b)
|
|
+ {
|
|
+ return a.it->first < b.it->first;
|
|
+ });
|
|
+
|
|
uint32_t &bucket_slot = m_bucket_table[bucket_ix];
|
|
/* The hashes array is indexed starting at 1. */
|
|
store_unsigned_integer (reinterpret_cast<gdb_byte *> (&bucket_slot),
|
|
diff --git a/gdb/testsuite/gdb.gdb/index-file.exp b/gdb/testsuite/gdb.gdb/index-file.exp
|
|
--- a/gdb/testsuite/gdb.gdb/index-file.exp
|
|
+++ b/gdb/testsuite/gdb.gdb/index-file.exp
|
|
@@ -47,6 +47,9 @@ remote_exec host "mkdir -p ${dir1}"
|
|
with_timeout_factor $timeout_factor {
|
|
gdb_test_no_output "save gdb-index $dir1" \
|
|
"create gdb-index file"
|
|
+
|
|
+ gdb_test_no_output "save gdb-index -dwarf-5 $dir1" \
|
|
+ "create dwarf-index files"
|
|
}
|
|
|
|
# Close GDB.
|
|
@@ -143,13 +146,16 @@ if { $worker_threads > 1 } {
|
|
with_timeout_factor $timeout_factor {
|
|
gdb_test_no_output "save gdb-index $dir2" \
|
|
"create second gdb-index file"
|
|
+
|
|
+ gdb_test_no_output "save gdb-index -dwarf-5 $dir2" \
|
|
+ "create second dwarf-index files"
|
|
}
|
|
|
|
# Close GDB.
|
|
gdb_exit
|
|
|
|
# Now check that the index files are identical.
|
|
- foreach suffix { gdb-index } {
|
|
+ foreach suffix { gdb-index debug_names debug_str } {
|
|
set result \
|
|
[remote_exec host \
|
|
"cmp -s \"$dir1/${index_filename_base}.${suffix}\" \"$dir2/${index_filename_base}.${suffix}\""]
|