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  <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.
This commit is contained in:
Tom Tromey 2021-03-06 09:26:39 -07:00
parent 1803565556
commit 9938d15a01
6 changed files with 269 additions and 242 deletions

View file

@ -1,3 +1,15 @@
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.

View file

@ -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 ();
}

View file

@ -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 */

View file

@ -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. */

View file

@ -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. */

View file

@ -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 */