-/* 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 (section_is_p (sectp->name, &dwarf2_elf_names.abbrev))
- {
- dwz_file->abbrev.s.section = sectp;
- dwz_file->abbrev.size = bfd_section_size (sectp);
- }
- else if (section_is_p (sectp->name, &dwarf2_elf_names.info))
- {
- dwz_file->info.s.section = sectp;
- dwz_file->info.size = bfd_section_size (sectp);
- }
- else if (section_is_p (sectp->name, &dwarf2_elf_names.str))
- {
- dwz_file->str.s.section = sectp;
- dwz_file->str.size = bfd_section_size (sectp);
- }
- else if (section_is_p (sectp->name, &dwarf2_elf_names.line))
- {
- dwz_file->line.s.section = sectp;
- dwz_file->line.size = bfd_section_size (sectp);
- }
- else if (section_is_p (sectp->name, &dwarf2_elf_names.macro))
- {
- dwz_file->macro.s.section = sectp;
- dwz_file->macro.size = bfd_section_size (sectp);
- }
- else if (section_is_p (sectp->name, &dwarf2_elf_names.gdb_index))
- {
- dwz_file->gdb_index.s.section = sectp;
- dwz_file->gdb_index.size = bfd_section_size (sectp);
- }
- else if (section_is_p (sectp->name, &dwarf2_elf_names.debug_names))
- {
- 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)
-{
- 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)
- return NULL;
- 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 ();
-}