- Patches dropped: * fixup-gdb-6.3-gstack-20050411.patch * fixup-skip-tests.patch * gdb-6.6-buildid-locate-rpm-librpm-workaround.patch * gdb-6.6-buildid-locate-rpm.patch - Patches added: * gdb-add-missing-debug-ext-lang-hook.patch * gdb-add-missing-debug-info-python-hook.patch * gdb-add-rpm-suggestion-script.patch * gdb-do-not-import-py-curses-ascii-module.patch * gdb-handle-no-python-gdb-module.patch * gdb-merge-debug-symbol-lookup.patch * gdb-python-avoid-depending-on-the-curses-library.patch * gdb-refactor-find-and-add-separate-symbol-file.patch * gdb-reformat-missing-debug-py-file.patch * gdb-remove-path-in-test-name.patch * gdb-remove-use-of-py-isascii * gdb-sync-coffread-with-elfread.patch - Patches updated: * fixup-gdb-bz634108-solib_address.patch * gdb-6.3-gstack-20050411.patch * gdb-6.6-buildid-locate-rpm-suse.patch * gdb-6.6-buildid-locate-solib-missing-ids.patch * gdb-6.6-buildid-locate.patch * gdb-archer-next-over-throw-cxx-exec.patch * gdb-bz634108-solib_address.patch * gdb-fedora-libncursesw.patch * gdb-glibc-strstr-workaround.patch * gdb-rhbz1007614-memleak-infpy_read_memory-test.patch OBS-URL: https://build.opensuse.org/package/show/devel:gcc/gdb?expand=0&rev=409
315 lines
12 KiB
Diff
315 lines
12 KiB
Diff
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||
From: Andrew Burgess <aburgess@redhat.com>
|
||
Date: Fri, 13 Oct 2023 16:48:36 +0100
|
||
Subject: gdb-add-missing-debug-ext-lang-hook.patch
|
||
|
||
;; Backport upstream commit 661d98a3331.
|
||
|
||
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>
|
||
|
||
diff --git a/gdb/extension-priv.h b/gdb/extension-priv.h
|
||
--- a/gdb/extension-priv.h
|
||
+++ b/gdb/extension-priv.h
|
||
@@ -279,6 +279,13 @@ struct extension_language_ops
|
||
gdb::optional<int> (*print_insn) (struct gdbarch *gdbarch,
|
||
CORE_ADDR address,
|
||
struct disassemble_info *info);
|
||
+
|
||
+ /* Give extension languages a chance to deal with missing debug
|
||
+ information. OBJFILE is the file for which GDB was unable to find
|
||
+ any debug information. */
|
||
+ ext_lang_missing_debuginfo_result
|
||
+ (*handle_missing_debuginfo) (const struct extension_language_defn *,
|
||
+ struct objfile *objfile);
|
||
};
|
||
|
||
/* State necessary to restore a signal handler to its previous value. */
|
||
diff --git a/gdb/extension.c b/gdb/extension.c
|
||
--- a/gdb/extension.c
|
||
+++ b/gdb/extension.c
|
||
@@ -997,6 +997,25 @@ ext_lang_print_insn (struct gdbarch *gdbarch, CORE_ADDR address,
|
||
return {};
|
||
}
|
||
|
||
+/* See extension.h. */
|
||
+
|
||
+ext_lang_missing_debuginfo_result
|
||
+ext_lang_handle_missing_debuginfo (struct objfile *objfile)
|
||
+{
|
||
+ for (const struct extension_language_defn *extlang : extension_languages)
|
||
+ {
|
||
+ if (extlang->ops == nullptr
|
||
+ || extlang->ops->handle_missing_debuginfo == nullptr)
|
||
+ continue;
|
||
+ ext_lang_missing_debuginfo_result result
|
||
+ = extlang->ops->handle_missing_debuginfo (extlang, objfile);
|
||
+ if (!result.filename ().empty () || result.try_again ())
|
||
+ return result;
|
||
+ }
|
||
+
|
||
+ return {};
|
||
+}
|
||
+
|
||
/* Called via an observer before gdb prints its prompt.
|
||
Iterate over the extension languages giving them a chance to
|
||
change the prompt. The first one to change the prompt wins,
|
||
diff --git a/gdb/extension.h b/gdb/extension.h
|
||
--- a/gdb/extension.h
|
||
+++ b/gdb/extension.h
|
||
@@ -337,6 +337,68 @@ extern gdb::optional<std::string> ext_lang_colorize_disasm
|
||
extern gdb::optional<int> ext_lang_print_insn
|
||
(struct gdbarch *gdbarch, CORE_ADDR address, struct disassemble_info *info);
|
||
|
||
+/* When GDB calls into an extension language because an objfile was
|
||
+ discovered for which GDB couldn't find any debug information, this
|
||
+ structure holds the result that the extension language returns.
|
||
+
|
||
+ There are three possible actions that might be returned by an extension;
|
||
+ first an extension can return a filename, this is the path to the file
|
||
+ containing the required debug information. The second possibility is
|
||
+ to return a flag indicating that GDB should check again for the missing
|
||
+ debug information, this would imply that the extension has installed
|
||
+ the debug information into a location where GDB can be expected to find
|
||
+ it. And the third option is for the extension to just return a null
|
||
+ result, indication there is nothing the extension can do to provide the
|
||
+ missing debug information. */
|
||
+struct ext_lang_missing_debuginfo_result
|
||
+{
|
||
+ /* Default result. The extension was unable to provide the missing debug
|
||
+ info. */
|
||
+ ext_lang_missing_debuginfo_result ()
|
||
+ { /* Nothing. */ }
|
||
+
|
||
+ /* When TRY_AGAIN is true GDB should try searching again, the extension
|
||
+ may have installed the missing debug info into a suitable location.
|
||
+ When TRY_AGAIN is false this is equivalent to the default, no
|
||
+ argument, constructor. */
|
||
+ ext_lang_missing_debuginfo_result (bool try_again)
|
||
+ : m_try_again (try_again)
|
||
+ { /* Nothing. */ }
|
||
+
|
||
+ /* Look in FILENAME for the missing debug info. */
|
||
+ ext_lang_missing_debuginfo_result (std::string &&filename)
|
||
+ : m_filename (std::move (filename))
|
||
+ { /* Nothing. */ }
|
||
+
|
||
+ /* The filename where GDB can find the missing debuginfo. This is empty
|
||
+ if the extension didn't suggest a file that can be used. */
|
||
+ const std::string &
|
||
+ filename () const
|
||
+ {
|
||
+ return m_filename;
|
||
+ }
|
||
+
|
||
+ /* Returns true if GDB should look again for the debug information. */
|
||
+ const bool
|
||
+ try_again () const
|
||
+ {
|
||
+ return m_try_again;
|
||
+ }
|
||
+
|
||
+private:
|
||
+ /* The filename where the missing debuginfo can now be found. */
|
||
+ std::string m_filename;
|
||
+
|
||
+ /* When true GDB will search again for the debuginfo using its standard
|
||
+ techniques. When false GDB will not search again. */
|
||
+ bool m_try_again = false;
|
||
+};
|
||
+
|
||
+/* Called when GDB failed to find any debug information for OBJFILE. */
|
||
+
|
||
+extern ext_lang_missing_debuginfo_result ext_lang_handle_missing_debuginfo
|
||
+ (struct objfile *objfile);
|
||
+
|
||
#if GDB_SELF_TEST
|
||
namespace selftests {
|
||
extern void (*hook_set_active_ext_lang) ();
|
||
diff --git a/gdb/symfile-debug.c b/gdb/symfile-debug.c
|
||
--- a/gdb/symfile-debug.c
|
||
+++ b/gdb/symfile-debug.c
|
||
@@ -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;
|
||
-
|
||
- 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);
|
||
+ bool has_dwarf2 = false;
|
||
+
|
||
+ /* 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)
|
||
+ {
|
||
+ 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)
|
||
- std::tie (debug_bfd, filename)
|
||
- = debuginfod_find_and_open_separate_symbol_file (this);
|
||
+ 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 (debug_bfd != nullptr)
|
||
- {
|
||
- symbol_file_add_separate (debug_bfd, filename.c_str (), symfile_flags,
|
||
- this);
|
||
- has_dwarf = true;
|
||
+ /* 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;
|
||
}
|
||
|
||
|