From: Tom Tromey Date: Sat, 6 Mar 2021 16:26:39 +0000 (-0700) Subject: Move dwarf2_get_dwz_file to dwarf2/dwz.h X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=9938d15a01031e0aded4159adaa77d5b2b2319f6;p=binutils-gdb.git Move dwarf2_get_dwz_file to dwarf2/dwz.h 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-03-06 Tom Tromey * 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. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index e73dec797aa..a3762b353f7 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,15 @@ +2021-03-06 Tom Tromey + + * 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 * debuginfod-support.h: Include scoped_fd.h. 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> debugdir_vec + = dirnames_to_char_ptr_vec (debug_file_directory); + + for (const gdb::unique_xmalloc_ptr &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 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 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 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 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 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 65e2047ef32..f550a4e5008 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> debugdir_vec - = dirnames_to_char_ptr_vec (debug_file_directory); - - for (const gdb::unique_xmalloc_ptr &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 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 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 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 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 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 b974fe46ef4..5728ba68288 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 */