mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-12-19 01:19:41 +08:00
gdb: add an extension language hook for missing debug info
This commit adds a new extension_language_ops hook which allows an extension to handle the case where GDB can't find a separate debug information file for a particular objfile. This commit doesn't actually implement the hook for any of GDB's extension languages, the next commit will do that. This commit just adds support for the hook to extension-priv.h and extension.[ch], and then reworks symfile-debug.c to call the hook. Right now the hook will always return its default value, which means GDB should do nothing different. As such, there should be no user visible changes after this commit. I'll give a brief description of what the hook does here so that we can understand the changes in symfile-debug.c. The next commit adds a Python implementation for this new hook, and gives a fuller description of the new functionality. Currently, when looking for separate debug information GDB tries three things, in this order: 1. Use the build-id to find the required debug information, 2. Check for .gnu_debuglink section and use that to look up the required debug information, 3. Check with debuginfod to see if it can supply the required information. The new extension_language_ops::handle_missing_debuginfo hook is called if all three steps fail to find any debug information. The hook has three possible return values: a. Nothing, no debug information is found, GDB continues without the debug information for this objfile. This matches the current behaviour of GDB, and is the default if nothing is implementing this new hook, b. Install debug information into a location that step #1 or #2 above would normally check, and then request that GDB repeats steps #1 and #2 in the hope that GDB will now find the debug information. If the debug information is still not found then GDB carries on without the debug information. If the debug information is found the GDB loads it and carries on, c. Return a filename for a file containing the required debug information. GDB loads the contents of this file and carries on. The changes in this commit mostly involve placing the core of objfile::find_and_add_separate_symbol_file into a loop which allows for steps #1 and #2 to be repeated. We take care to ensure that debuginfod is only queried once, the first time through. The assumption is that no extension is going to be able to control the replies from debuginfod, so there's no point making a second request -- and as these requests go over the network, they could potentially be slow. The warnings that find_and_add_separate_symbol_file collects are displayed only once assuming that no debug information is found. If debug information is found, even after the extension has operated, then the warnings are not shown; remember, these are warnings from GDB about failure to find any suitable debug information, so it makes sense to hide these if debug information is found. Approved-By: Tom Tromey <tom@tromey.com>
This commit is contained in:
@@ -631,38 +631,88 @@ debuginfod_find_and_open_separate_symbol_file (struct objfile * objfile)
|
||||
bool
|
||||
objfile::find_and_add_separate_symbol_file (symfile_add_flags symfile_flags)
|
||||
{
|
||||
bool has_dwarf = false;
|
||||
bool has_dwarf2 = false;
|
||||
|
||||
deferred_warnings warnings;
|
||||
|
||||
gdb_bfd_ref_ptr debug_bfd;
|
||||
std::string filename;
|
||||
|
||||
std::tie (debug_bfd, filename) = simple_find_and_open_separate_symbol_file
|
||||
(this, find_separate_debug_file_by_buildid, &warnings);
|
||||
|
||||
if (debug_bfd == nullptr)
|
||||
std::tie (debug_bfd, filename)
|
||||
= simple_find_and_open_separate_symbol_file
|
||||
(this, find_separate_debug_file_by_debuglink, &warnings);
|
||||
|
||||
if (debug_bfd == nullptr)
|
||||
std::tie (debug_bfd, filename)
|
||||
= debuginfod_find_and_open_separate_symbol_file (this);
|
||||
|
||||
if (debug_bfd != nullptr)
|
||||
/* Usually we only make a single pass when looking for separate debug
|
||||
information. However, it is possible for an extension language hook
|
||||
to request that GDB make a second pass, in which case max_attempts
|
||||
will be updated, and the loop restarted. */
|
||||
for (unsigned attempt = 0, max_attempts = 1;
|
||||
attempt < max_attempts && !has_dwarf2;
|
||||
++attempt)
|
||||
{
|
||||
symbol_file_add_separate (debug_bfd, filename.c_str (), symfile_flags,
|
||||
this);
|
||||
has_dwarf = true;
|
||||
gdb_assert (max_attempts <= 2);
|
||||
|
||||
deferred_warnings warnings;
|
||||
gdb_bfd_ref_ptr debug_bfd;
|
||||
std::string filename;
|
||||
|
||||
std::tie (debug_bfd, filename)
|
||||
= simple_find_and_open_separate_symbol_file
|
||||
(this, find_separate_debug_file_by_buildid, &warnings);
|
||||
|
||||
if (debug_bfd == nullptr)
|
||||
std::tie (debug_bfd, filename)
|
||||
= simple_find_and_open_separate_symbol_file
|
||||
(this, find_separate_debug_file_by_debuglink, &warnings);
|
||||
|
||||
/* Only try debuginfod on the first attempt. Sure, we could imagine
|
||||
an extension that somehow adds the required debug info to the
|
||||
debuginfod server but, at least for now, we don't support this
|
||||
scenario. Better for the extension to return new debug info
|
||||
directly to GDB. Plus, going to the debuginfod server might be
|
||||
slow, so that's a good argument for only doing this once. */
|
||||
if (debug_bfd == nullptr && attempt == 0)
|
||||
std::tie (debug_bfd, filename)
|
||||
= debuginfod_find_and_open_separate_symbol_file (this);
|
||||
|
||||
if (debug_bfd != nullptr)
|
||||
{
|
||||
/* We found a separate debug info symbol file. If this is our
|
||||
first attempt then setting HAS_DWARF2 will cause us to break
|
||||
from the attempt loop. */
|
||||
symbol_file_add_separate (debug_bfd, filename.c_str (),
|
||||
symfile_flags, this);
|
||||
has_dwarf2 = true;
|
||||
}
|
||||
else if (attempt == 0)
|
||||
{
|
||||
/* Failed to find a separate debug info symbol file. Call out to
|
||||
the extension languages. The user might have registered an
|
||||
extension that can find the debug info for us, or maybe give
|
||||
the user a system specific message that guides them to finding
|
||||
the missing debug info. */
|
||||
|
||||
ext_lang_missing_debuginfo_result ext_result
|
||||
= ext_lang_handle_missing_debuginfo (this);
|
||||
if (!ext_result.filename ().empty ())
|
||||
{
|
||||
/* Extension found a suitable debug file for us. */
|
||||
debug_bfd
|
||||
= symfile_bfd_open_no_error (ext_result.filename ().c_str ());
|
||||
|
||||
if (debug_bfd != nullptr)
|
||||
{
|
||||
symbol_file_add_separate (debug_bfd,
|
||||
ext_result.filename ().c_str (),
|
||||
symfile_flags, this);
|
||||
has_dwarf2 = true;
|
||||
}
|
||||
}
|
||||
else if (ext_result.try_again ())
|
||||
{
|
||||
max_attempts = 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we still have not got a separate debug symbol file, then
|
||||
emit any warnings we've collected so far. */
|
||||
if (!has_dwarf2)
|
||||
warnings.emit ();
|
||||
}
|
||||
|
||||
/* If we still have not got a separate debug symbol file, then
|
||||
emit any warnings we've collected so far. */
|
||||
if (!has_dwarf)
|
||||
warnings.emit ();
|
||||
|
||||
return has_dwarf;
|
||||
return has_dwarf2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user