gdb: Try searching for auto-load script using .gnu_debuglink
authorAaron Merey <amerey@redhat.com>
Tue, 8 Mar 2022 22:32:35 +0000 (17:32 -0500)
committerAaron Merey <amerey@redhat.com>
Wed, 9 Mar 2022 01:39:05 +0000 (20:39 -0500)
If an auto-load script cannot be found and objfile is a separate
debuginfo whose filename does not match the name found in the parent
file's .gnu_debuglink section, then repeat the search using the
parent's filename where the last component is replaced with the
.gnu_debuglink name.

For example if the parent's filename is "/usr/lib/libxyz.so" and the
name in its .gnu_debuglink section is "libxyz.so.debug", then
if no auto-load script is otherwise found the search will be
repeated with the filename "/usr/lib/libxyz.so.debug".

This helps gdb locate auto-load scripts when debuginfo files do not have
the expected filename, such as when they are aquired from debuginfod.

gdb/auto-load.c

index 9a1ccec87ce5e1ddd9614da53a687fcdc1818ec0..5253b320543573d15680c97c140e98b76d6e5295 100644 (file)
@@ -51,6 +51,9 @@
    followed by the path of a python script to load.  */
 #define AUTO_SECTION_NAME ".debug_gdb_scripts"
 
+/* The section to look in for the name of a separate debug file.  */
+#define DEBUGLINK_SECTION_NAME ".gnu_debuglink"
+
 static void maybe_print_unsupported_script_warning
   (struct auto_load_pspace_info *, struct objfile *objfile,
    const struct extension_language_defn *language,
@@ -823,24 +826,61 @@ auto_load_objfile_script (struct objfile *objfile,
   gdb::unique_xmalloc_ptr<char> realname
     = gdb_realpath (objfile_name (objfile));
 
-  if (!auto_load_objfile_script_1 (objfile, realname.get (), language))
+  if (auto_load_objfile_script_1 (objfile, realname.get (), language))
+    return;
+
+  /* For Windows/DOS .exe executables, strip the .exe suffix, so that
+     FOO-gdb.gdb could be used for FOO.exe, and try again.  */
+
+  size_t len = strlen (realname.get ());
+  const size_t lexe = sizeof (".exe") - 1;
+
+  if (len > lexe && strcasecmp (realname.get () + len - lexe, ".exe") == 0)
     {
-      /* For Windows/DOS .exe executables, strip the .exe suffix, so that
-        FOO-gdb.gdb could be used for FOO.exe, and try again.  */
+      len -= lexe;
+      realname.get ()[len] = '\0';
+
+      auto_load_debug_printf
+       ("auto-load: Stripped .exe suffix, retrying with \"%s\".",
+        realname.get ());
+
+      auto_load_objfile_script_1 (objfile, realname.get (), language);
+      return;
+    }
 
-      size_t len = strlen (realname.get ());
-      const size_t lexe = sizeof (".exe") - 1;
+  /* If OBJFILE is a separate debug file and its name does not match
+     the name given in the parent's .gnu_debuglink section, try to
+     find the auto-load script using the parent's path and the
+     debuglink name.  */
+
+  struct objfile *parent = objfile->separate_debug_objfile_backlink;
+  if (parent != nullptr)
+    {
+      unsigned long crc32;
+      gdb::unique_xmalloc_ptr<char> debuglink
+       (bfd_get_debug_link_info (parent->obfd, &crc32));
 
-      if (len > lexe && strcasecmp (realname.get () + len - lexe, ".exe") == 0)
+      if (debuglink.get () != nullptr
+         && strcmp (debuglink.get (), lbasename (realname.get ())) != 0)
        {
-         len -= lexe;
-         realname.get ()[len] = '\0';
+         /* Replace the last component of the parent's path with the
+            debuglink name.  */
 
-         auto_load_debug_printf
-           ("auto-load: Stripped .exe suffix, retrying with \"%s\".",
-            realname.get ());
+         std::string p_realname = gdb_realpath (objfile_name (parent)).get ();
+         size_t last = p_realname.find_last_of ('/');
 
-         auto_load_objfile_script_1 (objfile, realname.get (), language);
+         if (last != std::string::npos)
+           {
+             p_realname.replace (last + 1, std::string::npos,
+                                 debuglink.get ());
+
+             auto_load_debug_printf
+               ("Debug filename mismatch, retrying with \"%s\".",
+                p_realname.c_str ());
+
+             auto_load_objfile_script_1 (objfile,
+                                         p_realname.c_str (), language);
+           }
        }
     }
 }