[04/28] Ada import functions not in index

Message ID 20250311-search-in-psyms-v1-4-d73d9be20983@tromey.com
State New
Headers
Series Search symbols via quick API |

Commit Message

Tom Tromey March 11, 2025, 2:12 p.m. UTC
  The cooked index does not currently contain entries for Ada import
functions.  This means that whether or not these are visible to
"break" depends on which CUs were previously expanded -- clearly a
bug.

This patch fixes the issue.  I think the comments in the patch explain
the fix reasonably well.

Perhaps one to-do item here is to change GNAT to use
DW_TAG_imported_declaration for these imports.  This may eventually
let us remove some of the current hacks.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32511
---
 gdb/dwarf2/abbrev.c              |  7 ++++++-
 gdb/dwarf2/abbrev.h              |  8 ++++++++
 gdb/dwarf2/cooked-indexer.c      |  6 ++++--
 gdb/dwarf2/read.c                |  9 +++------
 gdb/dwarf2/read.h                |  6 ++++++
 gdb/testsuite/gdb.ada/import.exp | 28 ++++++++++++++--------------
 6 files changed, 41 insertions(+), 23 deletions(-)
  

Patch

diff --git a/gdb/dwarf2/abbrev.c b/gdb/dwarf2/abbrev.c
index 9f7ead88f1fa717985004709e73aa8e916acb1e1..5b7e99abd24ead974595993f72c7452ad0d2ce4c 100644
--- a/gdb/dwarf2/abbrev.c
+++ b/gdb/dwarf2/abbrev.c
@@ -242,7 +242,12 @@  abbrev_table::read (struct dwarf2_section_info *section,
 	}
       else if (has_hardcoded_declaration
 	       && (cur_abbrev->tag != DW_TAG_variable || !has_external))
-	cur_abbrev->interesting = false;
+	{
+	  cur_abbrev->interesting = false;
+	  if (cur_abbrev->tag == DW_TAG_subprogram && has_name
+	      && has_linkage_name)
+	    cur_abbrev->maybe_ada_import = true;
+	}
       else if (!tag_interesting_for_index (cur_abbrev->tag))
 	cur_abbrev->interesting = false;
       else
diff --git a/gdb/dwarf2/abbrev.h b/gdb/dwarf2/abbrev.h
index 29914f9c86dfa46bbab90f5e87a7c248760d942d..41e60adb3aaafb9e70b525cc9fb671f7846a7168 100644
--- a/gdb/dwarf2/abbrev.h
+++ b/gdb/dwarf2/abbrev.h
@@ -51,6 +51,14 @@  struct abbrev_info
   /* True if the DIE has children.  */
   bool has_children;
   bool interesting;
+  /* In Ada, an imported subprogram DIE will be marked as a
+     declaration, but will have both a name and a linkage name.  This
+     declaration may be the only spot where that name is associated
+     with an object, so it has to show up in the index.  But, because
+     abbrevs are CU-independent, we can't check the language when
+     computing them and instead we keep a separate flag to indicate
+     that the scanner should check this DIE.  */
+  bool maybe_ada_import;
   unsigned short size_if_constant;
   unsigned short sibling_offset;
   /* Number of attributes.  */
diff --git a/gdb/dwarf2/cooked-indexer.c b/gdb/dwarf2/cooked-indexer.c
index 18c9c3b2459f2ddf6c849f8f06dbbde18abe1930..98785e9d8ab636249f5f67cb3a408c83b9990633 100644
--- a/gdb/dwarf2/cooked-indexer.c
+++ b/gdb/dwarf2/cooked-indexer.c
@@ -20,6 +20,7 @@ 
 #include "dwarf2/cooked-indexer.h"
 #include "dwarf2/cooked-index-storage.h"
 #include "dwarf2/error.h"
+#include "dwarf2/read.h"
 
 /* See cooked-indexer.h.  */
 
@@ -298,7 +299,7 @@  cooked_indexer::scan_attributes (dwarf2_per_cu *scanning_per_cu,
 	   || abbrev->tag == DW_TAG_namespace)
 	  && abbrev->has_children)
 	*flags |= IS_TYPE_DECLARATION;
-      else
+      else if (!is_ada_import_or_export (reader->cu (), *name, *linkage_name))
 	{
 	  *linkage_name = nullptr;
 	  *name = nullptr;
@@ -513,7 +514,8 @@  cooked_indexer::index_dies (cutu_reader *reader,
       /* If a DIE parent is a DW_TAG_subprogram, then the DIE is only
 	 interesting if it's a DW_TAG_subprogram or a DW_TAG_entry_point.  */
       bool die_interesting
-	= (abbrev->interesting
+	= ((abbrev->interesting
+	    || (m_language == language_ada && abbrev->maybe_ada_import))
 	   && (parent_entry == nullptr
 	       || parent_entry->tag != DW_TAG_subprogram
 	       || abbrev->tag == DW_TAG_subprogram
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index a25daa36d38caca8f5651ea7bc0a1b4d94b492a7..eac9c648aef9e6daf9dc6d277f672bb624f24b05 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -1001,9 +1001,6 @@  static void queue_comp_unit (dwarf2_per_cu *per_cu,
 
 static void process_queue (dwarf2_per_objfile *per_objfile);
 
-static bool is_ada_import_or_export (dwarf2_cu *cu, const char *name,
-				     const char *linkagename);
-
 /* Class, the destructor of which frees all allocated queue entries.  This
    will only have work to do if an error was thrown while processing the
    dwarf.  If no error was thrown then the queue entries should have all
@@ -16962,14 +16959,14 @@  add_ada_export_symbol (struct symbol *orig, const char *new_name,
   add_symbol_to_list (copy, list_to_add);
 }
 
-/* A helper function that decides if a given symbol is an Ada Pragma
-   Import or Pragma Export.  */
+/* See read.h.  */
 
-static bool
+bool
 is_ada_import_or_export (dwarf2_cu *cu, const char *name,
 			 const char *linkagename)
 {
   return (cu->lang () == language_ada
+	  && name != nullptr
 	  && linkagename != nullptr
 	  && !streq (name, linkagename)
 	  /* The following exclusions are necessary because symbols
diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h
index e178c60509eaa1ce58bd1da4d6b6845d9d840786..347a6f220561aee2dd4031260cd6df633c1eca01 100644
--- a/gdb/dwarf2/read.h
+++ b/gdb/dwarf2/read.h
@@ -1293,4 +1293,10 @@  extern int dwarf2_ranges_read (unsigned offset, unrelocated_addr *low_return,
 extern file_and_directory &find_file_and_directory (die_info *die,
 						    dwarf2_cu *cu);
 
+/* A helper function that decides if a given symbol is an Ada Pragma
+   Import or Pragma Export.  */
+
+extern bool is_ada_import_or_export (dwarf2_cu *cu, const char *name,
+				     const char *linkagename);
+
 #endif /* GDB_DWARF2_READ_H */
diff --git a/gdb/testsuite/gdb.ada/import.exp b/gdb/testsuite/gdb.ada/import.exp
index 04bb7e1a0d9f18e732855114b008a03348235086..6f1026f545fcfd5bc19d1f6e72321d05ffe12960 100644
--- a/gdb/testsuite/gdb.ada/import.exp
+++ b/gdb/testsuite/gdb.ada/import.exp
@@ -54,6 +54,9 @@  gdb_test "print pkg.imported_var_ada" " = 42"
 gdb_test "print pkg.exported_var_ada" " = 99"
 gdb_test "print exported_var_ada" " = 99"
 
+gdb_breakpoint "local_imported_func" message
+gdb_test "print copy" " = 42"
+
 # This passes with gcc 10 but fails with gcc 9.  With gcc 9, we have:
 #   <1><1659>: Abbrev Number: 4 (DW_TAG_subprogram)
 #      <165a>   DW_AT_external    : 1
@@ -76,19 +79,16 @@  gdb_test "print exported_var_ada" " = 99"
 # The fact that things start to work when adding the DW_AT_declaration is
 # consistent with what is described in commit ff9baa5f1c5, so xfail this
 # (without pinpointing it to a specific gcc PR or commit).
-if { [gcc_major_version] < 10 } {
-    setup_xfail *-*-*
-}
-gdb_breakpoint "pkg.imported_func_ada" message
-gdb_breakpoint "imported_func" message
-if { [gcc_major_version] < 10 } {
-    setup_xfail *-*-*
+foreach func {"pkg.imported_func_ada" "imported_func"} {
+    clean_restart $testfile
+    if { [gcc_major_version] < 10 } {
+	setup_xfail *-*-*
+    }
+    gdb_breakpoint $func message
 }
-gdb_breakpoint "imported_func_ada" message
 
-gdb_breakpoint "local_imported_func" message
-gdb_breakpoint "pkg.exported_func_ada" message
-gdb_breakpoint "exported_func_ada" message
-gdb_breakpoint "exported_func" message
-
-gdb_test "print copy" " = 42"
+foreach func {"imported_func_ada" "pkg.exported_func_ada" \
+		  "exported_func_ada" "exported_func"} {
+    clean_restart $testfile
+    gdb_breakpoint $func message
+}