]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Emit some type declarations in .gdb_index
authorTom Tromey <tom@tromey.com>
Tue, 11 Feb 2025 18:48:09 +0000 (11:48 -0700)
committerTom Tromey <tom@tromey.com>
Wed, 10 Sep 2025 22:05:27 +0000 (16:05 -0600)
If you run struct-decl.exp with the .gdb_index board, you will see
that "the_type" is not emitted in the index.  This would cause a
failure in this series.  The fix is to ensure that certain necessary
type declarations are emitted.

However, a naive fix here will regress stub-array-size.exp, where a
type declaration and a type definition are both seen -- but the
declaration is seen first and causes a failure.  This is handled by
adding some code (including a mild hack) to filter out type
declarations when a corresponding type definition is seen.

Acked-By: Simon Marchi <simon.marchi@efficios.com>
gdb/dwarf2/index-write.c

index d5b198ba34734480573e3cb29a613764576c4baa..bd14cb9eace0bdca8f9fe635aef0979a661ffd79 100644 (file)
@@ -55,7 +55,7 @@
 #define DW2_GDB_INDEX_SYMBOL_KIND_SET_VALUE(cu_index, value) \
   do { \
     gdb_assert ((value) >= GDB_INDEX_SYMBOL_KIND_TYPE \
-               && (value) <= GDB_INDEX_SYMBOL_KIND_OTHER); \
+               && (value) <= GDB_INDEX_SYMBOL_KIND_UNUSED5); \
     GDB_INDEX_SYMBOL_KIND_SET_VALUE((cu_index), (value)); \
   } while (0)
 
@@ -422,10 +422,47 @@ symtab_index_entry::minimize ()
   if (name == nullptr || cu_indices.empty ())
     return;
 
-  std::sort (cu_indices.begin (), cu_indices.end ());
+  /* We sort the indexes in a funny way: GDB_INDEX_SYMBOL_KIND_UNUSED5
+     is always sorted last; then otherwise we sort by numeric value.
+     This ensures that we prefer the definition when both a definition
+     and a declaration (stub type) are seen.  */
+  std::sort (cu_indices.begin (), cu_indices.end (),
+            [] (offset_type vala, offset_type valb)
+              {
+                auto kinda = GDB_INDEX_SYMBOL_KIND_VALUE (vala);
+                auto kindb = GDB_INDEX_SYMBOL_KIND_VALUE (valb);
+                if (kinda != kindb)
+                  {
+                    /* Declaration sorts last.  */
+                    if (kinda == GDB_INDEX_SYMBOL_KIND_UNUSED5)
+                      return false;
+                    if (kindb == GDB_INDEX_SYMBOL_KIND_UNUSED5)
+                      return true;
+                  }
+                return vala < valb;
+              });
   auto from = std::unique (cu_indices.begin (), cu_indices.end ());
   cu_indices.erase (from, cu_indices.end ());
 
+  /* Rewrite GDB_INDEX_SYMBOL_KIND_UNUSED5.  This ensures that a type
+     declaration will be deleted by the subsequent squashing step, if
+     warranted.  */
+  for (auto &val : cu_indices)
+    {
+      gdb_index_symbol_kind kind = GDB_INDEX_SYMBOL_KIND_VALUE (val);
+      if (kind != GDB_INDEX_SYMBOL_KIND_UNUSED5)
+       continue;
+
+      offset_type newval = 0;
+      DW2_GDB_INDEX_CU_SET_VALUE (newval, GDB_INDEX_CU_VALUE (val));
+      DW2_GDB_INDEX_SYMBOL_STATIC_SET_VALUE
+       (newval, GDB_INDEX_SYMBOL_STATIC_VALUE (val));
+      DW2_GDB_INDEX_SYMBOL_KIND_SET_VALUE (newval,
+                                          GDB_INDEX_SYMBOL_KIND_TYPE);
+
+      val = newval;
+    }
+
   /* We don't want to enter a type more than once, so
      remove any such duplicates from the list as well.  When doing
      this, we want to keep the entry from the first CU -- but this is
@@ -1212,6 +1249,21 @@ write_cooked_index (cooked_index *table,
                    const cu_index_map &cu_index_htab,
                    struct mapped_symtab *symtab)
 {
+  gdb::unordered_set<const cooked_index_entry *> required_decl_entries;
+  for (const cooked_index_entry *entry : table->all_entries ())
+    {
+      /* Any type declaration that is used as a (non-trivial) parent
+        entry must be written out.  */
+      if ((entry->flags & IS_TYPE_DECLARATION) == 0)
+       {
+         for (const cooked_index_entry *parent = entry->get_parent ();
+              parent != nullptr;
+              parent = parent->get_parent ())
+           if ((parent->flags & IS_TYPE_DECLARATION) != 0)
+             required_decl_entries.insert (parent);
+       }
+    }
+
   for (const cooked_index_entry *entry : table->all_entries ())
     {
       const auto it = cu_index_htab.find (entry->per_cu);
@@ -1237,11 +1289,10 @@ write_cooked_index (cooked_index *table,
             be redundant are rare and not worth supporting.  */
          continue;
        }
-      else if ((entry->flags & IS_TYPE_DECLARATION) != 0)
-       {
-         /* Don't add type declarations to the index.  */
-         continue;
-       }
+      /* Don't add most type declarations to the index.  */
+      else if ((entry->flags & IS_TYPE_DECLARATION) != 0
+              && !required_decl_entries.contains (entry))
+       continue;
 
       gdb_index_symbol_kind kind;
       if (entry->tag == DW_TAG_subprogram
@@ -1252,7 +1303,16 @@ write_cooked_index (cooked_index *table,
               || entry->tag == DW_TAG_enumerator)
        kind = GDB_INDEX_SYMBOL_KIND_VARIABLE;
       else if (tag_is_type (entry->tag))
-       kind = GDB_INDEX_SYMBOL_KIND_TYPE;
+       {
+         /* If we added a type declaration, we want to note this
+            fact for later, because we don't want a type declaration
+            to cause the real definition to be omitted from the
+            index.  GDB_INDEX_SYMBOL_KIND_UNUSED5 is used here, but
+            rewritten later before the index is written.  */
+         kind = ((entry->flags & IS_TYPE_DECLARATION) == 0
+                 ? GDB_INDEX_SYMBOL_KIND_TYPE
+                 : GDB_INDEX_SYMBOL_KIND_UNUSED5);
+       }
       else
        kind = GDB_INDEX_SYMBOL_KIND_OTHER;