[5/5] Move dwarf2_get_dwz_file to dwarf2/dwz.h

Message ID 20210221031647.949270-6-tom@tromey.com
State New
Headers show
Series
  • Some minor dwz-handling improvements & cleanups
Related show

Commit Message

Tom Tromey Feb. 21, 2021, 3:16 a.m.
This moves dwarf2_get_dwz_file and some helper code to dwarf2/dwz.h.
The main benefit of this is just shrinking dwarf2/read.c a little bit.

gdb/ChangeLog
2021-02-20  Tom Tromey  <tom@tromey.com>

	* dwarf2/sect-names.h (dwarf2_elf_names): Declare.
	* dwarf2/read.h (dwarf2_get_dwz_file): Move to dwz.h.
	* dwarf2/read.c (dwarf2_elf_names): No longer static.
	(locate_dwz_sections, dwz_search_other_debugdirs)
	(dwarf2_get_dwz_file): Move to dwz.c.
	* dwarf2/dwz.h (dwarf2_get_dwz_file): Move declaration from
	read.h.
	* dwarf2/dwz.c (locate_dwz_sections, dwz_search_other_debugdirs)
	(dwarf2_get_dwz_file): Move from read.c.
---
 gdb/ChangeLog           |  12 ++
 gdb/dwarf2/dwz.c        | 242 ++++++++++++++++++++++++++++++++++++++++
 gdb/dwarf2/dwz.h        |  11 ++
 gdb/dwarf2/read.c       | 234 +-------------------------------------
 gdb/dwarf2/read.h       |   9 --
 gdb/dwarf2/sect-names.h |   3 +
 6 files changed, 269 insertions(+), 242 deletions(-)

-- 
2.26.2

Patch

diff --git a/gdb/dwarf2/dwz.c b/gdb/dwarf2/dwz.c
index 6be2fa92456..f9d5db6b48a 100644
--- a/gdb/dwarf2/dwz.c
+++ b/gdb/dwarf2/dwz.c
@@ -20,6 +20,16 @@ 
 #include "defs.h"
 #include "dwarf2/dwz.h"
 
+#include "build-id.h"
+#include "debuginfod-support.h"
+#include "dwarf2/read.h"
+#include "dwarf2/sect-names.h"
+#include "filenames.h"
+#include "gdb_bfd.h"
+#include "gdbcore.h"
+#include "gdbsupport/pathstuff.h"
+#include "gdbsupport/scoped_fd.h"
+
 const char *
 dwz_file::read_string (struct objfile *objfile, LONGEST str_offset)
 {
@@ -38,3 +48,235 @@  dwz_file::read_string (struct objfile *objfile, LONGEST str_offset)
     return NULL;
   return (const char *) (str.buffer + str_offset);
 }
+
+/* A helper function to find the sections for a .dwz file.  */
+
+static void
+locate_dwz_sections (bfd *abfd, asection *sectp, dwz_file *dwz_file)
+{
+  /* Note that we only support the standard ELF names, because .dwz
+     is ELF-only (at the time of writing).  */
+  if (dwarf2_elf_names.abbrev.matches (sectp->name))
+    {
+      dwz_file->abbrev.s.section = sectp;
+      dwz_file->abbrev.size = bfd_section_size (sectp);
+    }
+  else if (dwarf2_elf_names.info.matches (sectp->name))
+    {
+      dwz_file->info.s.section = sectp;
+      dwz_file->info.size = bfd_section_size (sectp);
+    }
+  else if (dwarf2_elf_names.str.matches (sectp->name))
+    {
+      dwz_file->str.s.section = sectp;
+      dwz_file->str.size = bfd_section_size (sectp);
+    }
+  else if (dwarf2_elf_names.line.matches (sectp->name))
+    {
+      dwz_file->line.s.section = sectp;
+      dwz_file->line.size = bfd_section_size (sectp);
+    }
+  else if (dwarf2_elf_names.macro.matches (sectp->name))
+    {
+      dwz_file->macro.s.section = sectp;
+      dwz_file->macro.size = bfd_section_size (sectp);
+    }
+  else if (dwarf2_elf_names.gdb_index.matches (sectp->name))
+    {
+      dwz_file->gdb_index.s.section = sectp;
+      dwz_file->gdb_index.size = bfd_section_size (sectp);
+    }
+  else if (dwarf2_elf_names.debug_names.matches (sectp->name))
+    {
+      dwz_file->debug_names.s.section = sectp;
+      dwz_file->debug_names.size = bfd_section_size (sectp);
+    }
+}
+
+/* Attempt to find a .dwz file (whose full path is represented by
+   FILENAME) in all of the specified debug file directories provided.
+
+   Return the equivalent gdb_bfd_ref_ptr of the .dwz file found, or
+   nullptr if it could not find anything.  */
+
+static gdb_bfd_ref_ptr
+dwz_search_other_debugdirs (std::string &filename, bfd_byte *buildid,
+			    size_t buildid_len)
+{
+  /* Let's assume that the path represented by FILENAME has the
+     "/.dwz/" subpath in it.  This is what (most) GNU/Linux
+     distributions do, anyway.  */
+  size_t dwz_pos = filename.find ("/.dwz/");
+
+  if (dwz_pos == std::string::npos)
+    return nullptr;
+
+  /* This is an obvious assertion, but it's here more to educate
+     future readers of this code that FILENAME at DWZ_POS *must*
+     contain a directory separator.  */
+  gdb_assert (IS_DIR_SEPARATOR (filename[dwz_pos]));
+
+  gdb_bfd_ref_ptr dwz_bfd;
+  std::vector<gdb::unique_xmalloc_ptr<char>> debugdir_vec
+    = dirnames_to_char_ptr_vec (debug_file_directory);
+
+  for (const gdb::unique_xmalloc_ptr<char> &debugdir : debugdir_vec)
+    {
+      /* The idea is to iterate over the
+	 debug file directories provided by the user and
+	 replace the hard-coded path in the "filename" by each
+	 debug-file-directory.
+
+	 For example, suppose that filename is:
+
+	   /usr/lib/debug/.dwz/foo.dwz
+
+	 And suppose that we have "$HOME/bar" as the
+	 debug-file-directory.  We would then adjust filename
+	 to look like:
+
+	   $HOME/bar/.dwz/foo.dwz
+
+	 which would hopefully allow us to find the alt debug
+	 file.  */
+      std::string ddir = debugdir.get ();
+
+      if (ddir.empty ())
+	continue;
+
+      /* Make sure the current debug-file-directory ends with a
+	 directory separator.  This is needed because, if FILENAME
+	 contains something like "/usr/lib/abcde/.dwz/foo.dwz" and
+	 DDIR is "/usr/lib/abc", then could wrongfully skip it
+	 below.  */
+      if (!IS_DIR_SEPARATOR (ddir.back ()))
+	ddir += SLASH_STRING;
+
+      /* Check whether the beginning of FILENAME is DDIR.  If it is,
+	 then we are dealing with a file which we already attempted to
+	 open before, so we just skip it and continue processing the
+	 remaining debug file directories.  */
+      if (filename.size () > ddir.size ()
+	  && filename.compare (0, ddir.size (), ddir) == 0)
+	continue;
+
+      /* Replace FILENAME's default debug-file-directory with
+	 DDIR.  */
+      std::string new_filename = ddir + &filename[dwz_pos + 1];
+
+      dwz_bfd = gdb_bfd_open (new_filename.c_str (), gnutarget);
+
+      if (dwz_bfd == nullptr)
+	continue;
+
+      if (!build_id_verify (dwz_bfd.get (), buildid_len, buildid))
+	{
+	  dwz_bfd.reset (nullptr);
+	  continue;
+	}
+
+      /* Found it.  */
+      break;
+    }
+
+  return dwz_bfd;
+}
+
+/* See dwz.h.  */
+
+struct dwz_file *
+dwarf2_get_dwz_file (dwarf2_per_bfd *per_bfd, bool require)
+{
+  bfd_size_type buildid_len_arg;
+  size_t buildid_len;
+  bfd_byte *buildid;
+
+  if (per_bfd->dwz_file != NULL)
+    return per_bfd->dwz_file.get ();
+
+  bfd_set_error (bfd_error_no_error);
+  gdb::unique_xmalloc_ptr<char> data
+    (bfd_get_alt_debug_link_info (per_bfd->obfd,
+				  &buildid_len_arg, &buildid));
+  if (data == NULL)
+    {
+      if (bfd_get_error () == bfd_error_no_error)
+	{
+	  if (!require)
+	    return nullptr;
+	  error (_("could not read '.gnu_debugaltlink' section"));
+	}
+      error (_("could not read '.gnu_debugaltlink' section: %s"),
+	     bfd_errmsg (bfd_get_error ()));
+    }
+
+  gdb::unique_xmalloc_ptr<bfd_byte> buildid_holder (buildid);
+
+  buildid_len = (size_t) buildid_len_arg;
+
+  std::string filename = data.get ();
+
+  if (!IS_ABSOLUTE_PATH (filename.c_str ()))
+    {
+      gdb::unique_xmalloc_ptr<char> abs
+	= gdb_realpath (bfd_get_filename (per_bfd->obfd));
+
+      filename = ldirname (abs.get ()) + SLASH_STRING + filename;
+    }
+
+  /* First try the file name given in the section.  If that doesn't
+     work, try to use the build-id instead.  */
+  gdb_bfd_ref_ptr dwz_bfd (gdb_bfd_open (filename.c_str (), gnutarget));
+  if (dwz_bfd != NULL)
+    {
+      if (!build_id_verify (dwz_bfd.get (), buildid_len, buildid))
+	dwz_bfd.reset (nullptr);
+    }
+
+  if (dwz_bfd == NULL)
+    dwz_bfd = build_id_to_debug_bfd (buildid_len, buildid);
+
+  if (dwz_bfd == nullptr)
+    {
+      /* If the user has provided us with different
+	 debug file directories, we can try them in order.  */
+      dwz_bfd = dwz_search_other_debugdirs (filename, buildid, buildid_len);
+    }
+
+  if (dwz_bfd == nullptr)
+    {
+      gdb::unique_xmalloc_ptr<char> alt_filename;
+      const char *origname = bfd_get_filename (per_bfd->obfd);
+
+      scoped_fd fd (debuginfod_debuginfo_query (buildid,
+						buildid_len,
+						origname,
+						&alt_filename));
+
+      if (fd.get () >= 0)
+	{
+	  /* File successfully retrieved from server.  */
+	  dwz_bfd = gdb_bfd_open (alt_filename.get (), gnutarget);
+
+	  if (dwz_bfd == nullptr)
+	    warning (_("File \"%s\" from debuginfod cannot be opened as bfd"),
+		     alt_filename.get ());
+	  else if (!build_id_verify (dwz_bfd.get (), buildid_len, buildid))
+	    dwz_bfd.reset (nullptr);
+	}
+    }
+
+  if (dwz_bfd == NULL)
+    error (_("could not find '.gnu_debugaltlink' file for %s"),
+	   bfd_get_filename (per_bfd->obfd));
+
+  std::unique_ptr<struct dwz_file> result
+    (new struct dwz_file (std::move (dwz_bfd)));
+
+  for (asection *sec : gdb_bfd_sections (result->dwz_bfd))
+    locate_dwz_sections (result->dwz_bfd.get (), sec, result.get ());
+
+  gdb_bfd_record_inclusion (per_bfd->obfd, result->dwz_bfd.get ());
+  per_bfd->dwz_file = std::move (result);
+  return per_bfd->dwz_file.get ();
+}
diff --git a/gdb/dwarf2/dwz.h b/gdb/dwarf2/dwz.h
index c50aab8676c..634afbbfbcf 100644
--- a/gdb/dwarf2/dwz.h
+++ b/gdb/dwarf2/dwz.h
@@ -24,6 +24,8 @@ 
 #include "dwarf2/index-cache.h"
 #include "dwarf2/section.h"
 
+struct dwarf2_per_bfd;
+
 /* This represents a '.dwz' file.  */
 
 struct dwz_file
@@ -62,4 +64,13 @@  struct dwz_file
   const char *read_string (struct objfile *objfile, LONGEST str_offset);
 };
 
+/* Open the separate '.dwz' debug file, if needed.  If there is no
+   .gnu_debugaltlink section in the file, then the result depends on
+   REQUIRE: if REQUIRE is true, then error; if REQUIRE is false,
+   return NULL.  Always error if there is such a section but the file
+   cannot be found.  */
+
+extern dwz_file *dwarf2_get_dwz_file (dwarf2_per_bfd *per_bfd,
+				      bool require = false);
+
 #endif /* GDB_DWARF2_DWZ_H */
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 6a755f716d1..31f34dc6047 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -87,7 +87,6 @@ 
 #include "rust-lang.h"
 #include "gdbsupport/pathstuff.h"
 #include "count-one-bits.h"
-#include "debuginfod-support.h"
 
 /* When == 1, print basic high level tracing messages.
    When > 1, be more verbose.
@@ -324,7 +323,7 @@  get_dwarf2_per_objfile (struct objfile *objfile)
 /* Note that if the debugging section has been compressed, it might
    have a name like .zdebug_info.  */
 
-static const struct dwarf2_debug_sections dwarf2_elf_names =
+const struct dwarf2_debug_sections dwarf2_elf_names =
 {
   { ".debug_info", ".zdebug_info" },
   { ".debug_abbrev", ".zdebug_abbrev" },
@@ -2143,237 +2142,6 @@  dwarf2_get_section_info (struct objfile *objfile,
   *sizep = info->size;
 }
 
-/* A helper function to find the sections for a .dwz file.  */
-
-static void
-locate_dwz_sections (bfd *abfd, asection *sectp, dwz_file *dwz_file)
-{
-  /* Note that we only support the standard ELF names, because .dwz
-     is ELF-only (at the time of writing).  */
-  if (dwarf2_elf_names.abbrev.matches (sectp->name))
-    {
-      dwz_file->abbrev.s.section = sectp;
-      dwz_file->abbrev.size = bfd_section_size (sectp);
-    }
-  else if (dwarf2_elf_names.info.matches (sectp->name))
-    {
-      dwz_file->info.s.section = sectp;
-      dwz_file->info.size = bfd_section_size (sectp);
-    }
-  else if (dwarf2_elf_names.str.matches (sectp->name))
-    {
-      dwz_file->str.s.section = sectp;
-      dwz_file->str.size = bfd_section_size (sectp);
-    }
-  else if (dwarf2_elf_names.line.matches (sectp->name))
-    {
-      dwz_file->line.s.section = sectp;
-      dwz_file->line.size = bfd_section_size (sectp);
-    }
-  else if (dwarf2_elf_names.macro.matches (sectp->name))
-    {
-      dwz_file->macro.s.section = sectp;
-      dwz_file->macro.size = bfd_section_size (sectp);
-    }
-  else if (dwarf2_elf_names.gdb_index.matches (sectp->name))
-    {
-      dwz_file->gdb_index.s.section = sectp;
-      dwz_file->gdb_index.size = bfd_section_size (sectp);
-    }
-  else if (dwarf2_elf_names.debug_names.matches (sectp->name))
-    {
-      dwz_file->debug_names.s.section = sectp;
-      dwz_file->debug_names.size = bfd_section_size (sectp);
-    }
-}
-
-/* Attempt to find a .dwz file (whose full path is represented by
-   FILENAME) in all of the specified debug file directories provided.
-
-   Return the equivalent gdb_bfd_ref_ptr of the .dwz file found, or
-   nullptr if it could not find anything.  */
-
-static gdb_bfd_ref_ptr
-dwz_search_other_debugdirs (std::string &filename, bfd_byte *buildid,
-			    size_t buildid_len)
-{
-  /* Let's assume that the path represented by FILENAME has the
-     "/.dwz/" subpath in it.  This is what (most) GNU/Linux
-     distributions do, anyway.  */
-  size_t dwz_pos = filename.find ("/.dwz/");
-
-  if (dwz_pos == std::string::npos)
-    return nullptr;
-
-  /* This is an obvious assertion, but it's here more to educate
-     future readers of this code that FILENAME at DWZ_POS *must*
-     contain a directory separator.  */
-  gdb_assert (IS_DIR_SEPARATOR (filename[dwz_pos]));
-
-  gdb_bfd_ref_ptr dwz_bfd;
-  std::vector<gdb::unique_xmalloc_ptr<char>> debugdir_vec
-    = dirnames_to_char_ptr_vec (debug_file_directory);
-
-  for (const gdb::unique_xmalloc_ptr<char> &debugdir : debugdir_vec)
-    {
-      /* The idea is to iterate over the
-	 debug file directories provided by the user and
-	 replace the hard-coded path in the "filename" by each
-	 debug-file-directory.
-
-	 For example, suppose that filename is:
-
-	   /usr/lib/debug/.dwz/foo.dwz
-
-	 And suppose that we have "$HOME/bar" as the
-	 debug-file-directory.  We would then adjust filename
-	 to look like:
-
-	   $HOME/bar/.dwz/foo.dwz
-
-	 which would hopefully allow us to find the alt debug
-	 file.  */
-      std::string ddir = debugdir.get ();
-
-      if (ddir.empty ())
-	continue;
-
-      /* Make sure the current debug-file-directory ends with a
-	 directory separator.  This is needed because, if FILENAME
-	 contains something like "/usr/lib/abcde/.dwz/foo.dwz" and
-	 DDIR is "/usr/lib/abc", then could wrongfully skip it
-	 below.  */
-      if (!IS_DIR_SEPARATOR (ddir.back ()))
-	ddir += SLASH_STRING;
-
-      /* Check whether the beginning of FILENAME is DDIR.  If it is,
-	 then we are dealing with a file which we already attempted to
-	 open before, so we just skip it and continue processing the
-	 remaining debug file directories.  */
-      if (filename.size () > ddir.size ()
-	  && filename.compare (0, ddir.size (), ddir) == 0)
-	continue;
-
-      /* Replace FILENAME's default debug-file-directory with
-	 DDIR.  */
-      std::string new_filename = ddir + &filename[dwz_pos + 1];
-
-      dwz_bfd = gdb_bfd_open (new_filename.c_str (), gnutarget);
-
-      if (dwz_bfd == nullptr)
-	continue;
-
-      if (!build_id_verify (dwz_bfd.get (), buildid_len, buildid))
-	{
-	  dwz_bfd.reset (nullptr);
-	  continue;
-	}
-
-      /* Found it.  */
-      break;
-    }
-
-  return dwz_bfd;
-}
-
-/* See dwarf2read.h.  */
-
-struct dwz_file *
-dwarf2_get_dwz_file (dwarf2_per_bfd *per_bfd, bool require)
-{
-  bfd_size_type buildid_len_arg;
-  size_t buildid_len;
-  bfd_byte *buildid;
-
-  if (per_bfd->dwz_file != NULL)
-    return per_bfd->dwz_file.get ();
-
-  bfd_set_error (bfd_error_no_error);
-  gdb::unique_xmalloc_ptr<char> data
-    (bfd_get_alt_debug_link_info (per_bfd->obfd,
-				  &buildid_len_arg, &buildid));
-  if (data == NULL)
-    {
-      if (bfd_get_error () == bfd_error_no_error)
-	{
-	  if (!require)
-	    return nullptr;
-	  error (_("could not read '.gnu_debugaltlink' section"));
-	}
-      error (_("could not read '.gnu_debugaltlink' section: %s"),
-	     bfd_errmsg (bfd_get_error ()));
-    }
-
-  gdb::unique_xmalloc_ptr<bfd_byte> buildid_holder (buildid);
-
-  buildid_len = (size_t) buildid_len_arg;
-
-  std::string filename = data.get ();
-
-  if (!IS_ABSOLUTE_PATH (filename.c_str ()))
-    {
-      gdb::unique_xmalloc_ptr<char> abs
-	= gdb_realpath (bfd_get_filename (per_bfd->obfd));
-
-      filename = ldirname (abs.get ()) + SLASH_STRING + filename;
-    }
-
-  /* First try the file name given in the section.  If that doesn't
-     work, try to use the build-id instead.  */
-  gdb_bfd_ref_ptr dwz_bfd (gdb_bfd_open (filename.c_str (), gnutarget));
-  if (dwz_bfd != NULL)
-    {
-      if (!build_id_verify (dwz_bfd.get (), buildid_len, buildid))
-	dwz_bfd.reset (nullptr);
-    }
-
-  if (dwz_bfd == NULL)
-    dwz_bfd = build_id_to_debug_bfd (buildid_len, buildid);
-
-  if (dwz_bfd == nullptr)
-    {
-      /* If the user has provided us with different
-	 debug file directories, we can try them in order.  */
-      dwz_bfd = dwz_search_other_debugdirs (filename, buildid, buildid_len);
-    }
-
-  if (dwz_bfd == nullptr)
-    {
-      gdb::unique_xmalloc_ptr<char> alt_filename;
-      const char *origname = bfd_get_filename (per_bfd->obfd);
-
-      scoped_fd fd (debuginfod_debuginfo_query (buildid,
-						buildid_len,
-						origname,
-						&alt_filename));
-
-      if (fd.get () >= 0)
-	{
-	  /* File successfully retrieved from server.  */
-	  dwz_bfd = gdb_bfd_open (alt_filename.get (), gnutarget);
-
-	  if (dwz_bfd == nullptr)
-	    warning (_("File \"%s\" from debuginfod cannot be opened as bfd"),
-		     alt_filename.get ());
-	  else if (!build_id_verify (dwz_bfd.get (), buildid_len, buildid))
-	    dwz_bfd.reset (nullptr);
-	}
-    }
-
-  if (dwz_bfd == NULL)
-    error (_("could not find '.gnu_debugaltlink' file for %s"),
-	   bfd_get_filename (per_bfd->obfd));
-
-  std::unique_ptr<struct dwz_file> result
-    (new struct dwz_file (std::move (dwz_bfd)));
-
-  for (asection *sec : gdb_bfd_sections (result->dwz_bfd))
-    locate_dwz_sections (result->dwz_bfd.get (), sec, result.get ());
-
-  gdb_bfd_record_inclusion (per_bfd->obfd, result->dwz_bfd.get ());
-  per_bfd->dwz_file = std::move (result);
-  return per_bfd->dwz_file.get ();
-}
 
 /* DWARF quick_symbols_functions support.  */
 
diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h
index 86ac6b50cc0..1d0f0a4995b 100644
--- a/gdb/dwarf2/read.h
+++ b/gdb/dwarf2/read.h
@@ -633,15 +633,6 @@  struct signatured_type
   struct dwo_unit *dwo_unit;
 };
 
-/* Open the separate '.dwz' debug file, if needed.  If there is no
-   .gnu_debugaltlink section in the file, then the result depends on
-   REQUIRE: if REQUIRE is true, then error; if REQUIRE is false,
-   return NULL.  Always error if there is such a section but the file
-   cannot be found.  */
-
-extern dwz_file *dwarf2_get_dwz_file (dwarf2_per_bfd *per_bfd,
-				      bool require = false);
-
 /* Return the type of the DIE at DIE_OFFSET in the CU named by
    PER_CU.  */
 
diff --git a/gdb/dwarf2/sect-names.h b/gdb/dwarf2/sect-names.h
index b75328358c2..bf7ea2cd4b2 100644
--- a/gdb/dwarf2/sect-names.h
+++ b/gdb/dwarf2/sect-names.h
@@ -72,4 +72,7 @@  struct dwarf2_debug_sections {
   int sentinel;
 };
 
+/* Section names for ELF.  */
+extern const struct dwarf2_debug_sections dwarf2_elf_names;
+
 #endif /* GDB_DWARF2_SECT_NAMES_H */