gdb: refactor objfile::find_and_add_separate_symbol_file
[binutils-gdb.git] / gdb / symfile-debug.c
index 961ae2327f760c184952af04b6cb4d7f7e8bbc24..0b6dc4752dff785731be9386b6e1ac7dd10a8576 100644 (file)
@@ -560,68 +560,109 @@ objfile::require_partial_symbols (bool verbose)
     }
 }
 
+/* Call LOOKUP_FUNC to find the filename of a file containing the separate
+   debug information matching OBJFILE.  If LOOKUP_FUNC does return a
+   filename then open this file and return a std::pair containing the
+   gdb_bfd_ref_ptr of the open file and the filename returned by
+   LOOKUP_FUNC, otherwise this function returns an empty pair; the first
+   item will be nullptr, and the second will be an empty string.
+
+   Any warnings generated by this function, or by calling LOOKUP_FUNC are
+   placed into WARNINGS, these warnings are only displayed to the user if
+   GDB is unable to find the separate debug information via any route.  */
+static std::pair<gdb_bfd_ref_ptr, std::string>
+simple_find_and_open_separate_symbol_file
+  (struct objfile *objfile,
+   std::string (*lookup_func) (struct objfile *, deferred_warnings *),
+   deferred_warnings *warnings)
+{
+  std::string filename = lookup_func (objfile, warnings);
+
+  if (!filename.empty ())
+    {
+      gdb_bfd_ref_ptr symfile_bfd
+       = symfile_bfd_open_no_error (filename.c_str ());
+      if (symfile_bfd != nullptr)
+       return { symfile_bfd, filename };
+    }
+
+  return {};
+}
+
+/* Lookup separate debug information for OBJFILE via debuginfod.  If
+   successful the debug information will be have been downloaded into the
+   debuginfod cache and this function will return a std::pair containing a
+   gdb_bfd_ref_ptr of the open debug information file and the filename for
+   the file within the debuginfod cache.  If no debug information could be
+   found then this function returns an empty pair; the first item will be
+   nullptr, and the second will be an empty string.  */
+
+static std::pair<gdb_bfd_ref_ptr, std::string>
+debuginfod_find_and_open_separate_symbol_file (struct objfile * objfile)
+{
+  const struct bfd_build_id *build_id
+    = build_id_bfd_get (objfile->obfd.get ());
+  const char *filename = bfd_get_filename (objfile->obfd.get ());
+
+  if (build_id != nullptr)
+    {
+      gdb::unique_xmalloc_ptr<char> symfile_path;
+      scoped_fd fd (debuginfod_debuginfo_query (build_id->data, build_id->size,
+                                               filename, &symfile_path));
+
+      if (fd.get () >= 0)
+       {
+         /* File successfully retrieved from server.  */
+         gdb_bfd_ref_ptr debug_bfd
+           (symfile_bfd_open_no_error (symfile_path.get ()));
+
+         if (debug_bfd != nullptr
+             && build_id_verify (debug_bfd.get (),
+                                 build_id->size, build_id->data))
+           return { debug_bfd, std::string (symfile_path.get ()) };
+       }
+    }
+
+  return {};
+}
+
 /* See objfiles.h.  */
 
 bool
 objfile::find_and_add_separate_symbol_file (symfile_add_flags symfile_flags)
 {
-  bool has_dwarf2 = true;
+  bool has_dwarf = false;
 
   deferred_warnings warnings;
 
-  std::string debugfile
-    = find_separate_debug_file_by_buildid (this, &warnings);
-
-  if (debugfile.empty ())
-    debugfile = find_separate_debug_file_by_debuglink (this, &warnings);
+  gdb_bfd_ref_ptr debug_bfd;
+  std::string filename;
 
-  if (!debugfile.empty ())
-    {
-      gdb_bfd_ref_ptr debug_bfd
-       (symfile_bfd_open_no_error (debugfile.c_str ()));
+  std::tie (debug_bfd, filename) = simple_find_and_open_separate_symbol_file
+    (this, find_separate_debug_file_by_buildid, &warnings);
 
-      if (debug_bfd != nullptr)
-       symbol_file_add_separate (debug_bfd, debugfile.c_str (),
-                                 symfile_flags, this);
-    }
-  else
-    {
-      has_dwarf2 = false;
-      const struct bfd_build_id *build_id
-       = build_id_bfd_get (this->obfd.get ());
-      const char *filename = bfd_get_filename (this->obfd.get ());
-
-      if (build_id != nullptr)
-       {
-         gdb::unique_xmalloc_ptr<char> symfile_path;
-         scoped_fd fd (debuginfod_debuginfo_query (build_id->data,
-                                                   build_id->size,
-                                                   filename,
-                                                   &symfile_path));
+  if (debug_bfd == nullptr)
+    std::tie (debug_bfd, filename)
+      = simple_find_and_open_separate_symbol_file
+         (this, find_separate_debug_file_by_debuglink, &warnings);
 
-         if (fd.get () >= 0)
-           {
-             /* File successfully retrieved from server.  */
-             gdb_bfd_ref_ptr debug_bfd
-               (symfile_bfd_open_no_error (symfile_path.get ()));
+  if (debug_bfd == nullptr)
+    std::tie (debug_bfd, filename)
+      = debuginfod_find_and_open_separate_symbol_file (this);
 
-             if (debug_bfd != nullptr
-                 && build_id_verify (debug_bfd.get (), build_id->size,
-                                     build_id->data))
-               {
-                 symbol_file_add_separate (debug_bfd, symfile_path.get (),
-                                           symfile_flags, this);
-                 has_dwarf2 = true;
-               }
-           }
-       }
+  if (debug_bfd != nullptr)
+    {
+      symbol_file_add_separate (debug_bfd, filename.c_str (), symfile_flags,
+                               this);
+      has_dwarf = true;
     }
-  /* If all the methods to collect the debuginfo failed, print the
-     warnings, this is a no-op if there are no warnings.  */
-  if (debugfile.empty () && !has_dwarf2)
+
+  /* If we still have not got a separate debug symbol file, then
+     emit any warnings we've collected so far.  */
+  if (!has_dwarf)
     warnings.emit ();
 
-  return has_dwarf2;
+  return has_dwarf;
 }
 
 \f