aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog12
-rw-r--r--gdb/dwarf2/dwz.c242
-rw-r--r--gdb/dwarf2/dwz.h11
-rw-r--r--gdb/dwarf2/read.c234
-rw-r--r--gdb/dwarf2/read.h9
-rw-r--r--gdb/dwarf2/sect-names.h3
6 files changed, 269 insertions, 242 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index e73dec7..a3762b3 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,17 @@
2021-03-06 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.
+
+2021-03-06 Tom Tromey <tom@tromey.com>
+
* debuginfod-support.h: Include scoped_fd.h.
2021-03-06 Tom Tromey <tom@tromey.com>
diff --git a/gdb/dwarf2/dwz.c b/gdb/dwarf2/dwz.c
index 6be2fa9..f9d5db6 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 c50aab8..634afbb 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 65e2047..f550a4e 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" },
@@ -2149,237 +2148,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 b974fe4..5728ba6 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 b753283..bf7ea2c 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 */