[RFC][gdb/symtab] Lazy expansion of full symbol table

Tom de Vries tdevries@suse.de
Sun Jun 20 09:41:16 GMT 2021


On 6/19/21 9:36 PM, Tom de Vries wrote:
> On 6/18/21 4:30 AM, Tom Tromey wrote:
>> Tom> I did an overnight build and test with the updated branch (5bc56d745fd)
>> Tom> and ran into some trouble.  The first internal-error I investigated
>> Tom> happens when parsing the libstdc++ .debug package (so, it was not
>> Tom> specific to the test-case).  It seems the branch has some trouble with
>> Tom> the dwz layout where an abbrev entry is shared between different CUs:
>>
>> Thank you for trying this, it uncovered several bugs.
>> As you can see I haven't gotten to the dwz testing yet... one of the
>> issues with DWARF, btw, is that there are just so many modes.
>> I.e., I haven't tried DWO or .debug_types yet either.
>>
> 
> Yeah, very true.
> 
>> I pushed some patches to fix the crashes but the result is so fast that
>> I suspect it is incorrect:
>>
>>     (gdb) file libstdc++.so.6.0.28-10.2.1+git583-lp152.4.1.x86_64.debug 
>>     2021-06-17 20:25:34.361 - command started
>>     Reading symbols from libstdc++.so.6.0.28-10.2.1+git583-lp152.4.1.x86_64.debug...
>>     2021-06-17 20:25:34.406 - command finished
>>     Command execution time: 0.075291 (cpu), 0.045521 (wall)
>>
>> (Though /bin/gdb is also pretty fast here, maybe I'm doing something
>> else wrong.)
>>
>> So, at least it doesn't crash, but more investigation is needed.
>> I'll probably add some code to make it easy to dump the index so it's
>> easier to see what the scanner recorded.
> 
> Tried the updated branch and ran into a race condition, fixed in
> attached patch.

Another thing I ran into is a not 100% reproducible segfault.

It triggered in gdb.base/advance-until-multiple-locations.exp, when
trying to find "test" in the libc debug package.

The segfault happens in cooked_index_entry::matches due to the entry
parameter being invalid, which is set in this loop:
...
  for (const cooked_index_entry *entry
         : per_objfile->per_bfd->cooked_index_table->find (name_vec.back
()))
    {
      if (!entry->matches (search_flags)
          || !entry->matches (domain)
          || !entry->matches (kind))
        continue;
...

I could reproduce the segfault with maint set worker-thread 1.

Using this debugging code:
...
diff --git a/gdb/dwarf2/cooked-index.c b/gdb/dwarf2/cooked-index.c
index 7358352fb0b..c75531ac548 100644
--- a/gdb/dwarf2/cooked-index.c
+++ b/gdb/dwarf2/cooked-index.c
@@ -133,6 +133,43 @@ cooked_index_vector::find (gdb::string_view name)
 {
   range result;

+#if 1
+  auto it = m_entries.begin ();
+  const char *prev_c = nullptr;
+  bool prev = true;
+  for (; it != m_entries.end (); ++it)
+    {
+      auto val = *it;
+      bool res = strncasecmp (val->canonical, name.data (), name.length
()) < 0;
+      if (res && !prev)
+       {
+         fprintf (stderr, "PREV_IT: %s\n", prev_c);
+         fprintf (stderr, "IT: %s\n", (*it)->canonical);
+         fprintf (stderr, "PREV_IT: %d\n",
+                  strncasecmp (prev_c, name.data (), name.length ()));
+         fprintf (stderr, "IT: %d\n",
+                  strncasecmp ((*it)->canonical, name.data (),
name.length ()));
+         gdb_assert_not_reached ("");
+       }
+      prev = res;
+      prev_c = val->canonical;
+    }
+#endif
...
I found out that the precondition for using std::lower_bound of the
vector being sorted in a certain way is not valid:
...
PREV_IT: uint32_t
IT: tcbhead_t
PREV_IT: 1
IT: -2
<gdb_assert>
...
so my hypothesis is that this causes the segfault somehow.

The test passes reliable when sorting at the entry of
cooked_index_vector::find (which is of course inefficient).

Thanks,
- Tom


More information about the Gdb-patches mailing list