aboutsummaryrefslogtreecommitdiff
path: root/gdb/doc
diff options
context:
space:
mode:
authorAndrew Burgess <aburgess@redhat.com>2023-10-15 22:48:42 +0100
committerAndrew Burgess <aburgess@redhat.com>2023-11-14 12:02:47 +0000
commit8f6c452b5a4e50fbb55ff1d13328b392ad1fd416 (patch)
tree18a5900e6c34450d6c941c210f7540183693d110 /gdb/doc
parent661d98a33318e06e0a6715eec5e6d0e140d8f337 (diff)
downloadbinutils-8f6c452b5a4e50fbb55ff1d13328b392ad1fd416.zip
binutils-8f6c452b5a4e50fbb55ff1d13328b392ad1fd416.tar.gz
binutils-8f6c452b5a4e50fbb55ff1d13328b392ad1fd416.tar.bz2
gdb: implement missing debug handler hook for Python
This commit builds on the previous commit, and implements the extension_language_ops::handle_missing_debuginfo function for Python. This hook will give user supplied Python code a chance to help find missing debug information. The implementation of the new hook is pretty minimal within GDB's C++ code; most of the work is out-sourced to a Python implementation which is modelled heavily on how GDB's Python frame unwinders are implemented. The following new commands are added as commands implemented in Python, this is similar to how the Python unwinder commands are implemented: info missing-debug-handlers enable missing-debug-handler LOCUS HANDLER disable missing-debug-handler LOCUS HANDLER To make use of this extension hook a user will create missing debug information handler objects, and registers these handlers with GDB. When GDB encounters an objfile that is missing debug information, each handler is called in turn until one is able to help. Here is a minimal handler that does nothing useful: import gdb import gdb.missing_debug class MyFirstHandler(gdb.missing_debug.MissingDebugHandler): def __init__(self): super().__init__("my_first_handler") def __call__(self, objfile): # This handler does nothing useful. return None gdb.missing_debug.register_handler(None, MyFirstHandler()) Returning None from the __call__ method tells GDB that this handler was unable to find the missing debug information, and GDB should ask any other registered handlers. By extending the __call__ method it is possible for the Python extension to locate the debug information for objfile and return a value that tells GDB how to use the information that has been located. Possible return values from a handler: - None: This means the handler couldn't help. GDB will call other registered handlers to see if they can help instead. - False: The handler has done all it can, but the debug information for the objfile still couldn't be found. GDB will not call any other handlers, and will continue without the debug information for objfile. - True: The handler has installed the debug information into a location where GDB would normally expect to find it. GDB should look again for the debug information. - A string: The handler can return a filename, which is the file containing the missing debug information. GDB will load this file. When a handler returns True, GDB will look again for the debug information, but only using the standard built-in build-id and .gnu_debuglink based lookup strategies. It is not possible for an extension to trigger another debuginfod lookup; the assumption is that the debuginfod server is remote, and out of the control of extensions running within GDB. Handlers can be registered globally, or per program space. GDB checks the handlers for the current program space first, and then all of the global handles. The first handler that returns a value that is not None, has "handled" the objfile, at which point GDB continues. Reviewed-By: Eli Zaretskii <eliz@gnu.org> Approved-By: Tom Tromey <tom@tromey.com>
Diffstat (limited to 'gdb/doc')
-rw-r--r--gdb/doc/python.texi140
1 files changed, 140 insertions, 0 deletions
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index 8cc3f92..c26949e 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -230,6 +230,7 @@ optional arguments while skipping others. Example:
* Connections In Python:: Python representation of connections.
* TUI Windows In Python:: Implementing new TUI windows.
* Disassembly In Python:: Instruction Disassembly In Python
+* Missing Debug Info In Python:: Handle missing debug info from Python.
@end menu
@node Basic Python
@@ -5252,6 +5253,12 @@ The @code{frame_filters} attribute is a dictionary of frame filter
objects. @xref{Frame Filter API}, for more information.
@end defvar
+@defvar Progspace.missing_debug_handlers
+The @code{missing_debug_handlers} attribute is a list of the missing
+debug handler objects for this program space. @xref{Missing Debug
+Info In Python}, for more information.
+@end defvar
+
A program space has the following methods:
@defun Progspace.block_for_pc (pc)
@@ -7819,6 +7826,139 @@ class NibbleSwapDisassembler(gdb.disassembler.Disassembler):
gdb.disassembler.register_disassembler(NibbleSwapDisassembler())
@end smallexample
+@node Missing Debug Info In Python
+@subsubsection Missing Debug Info In Python
+@cindex python, handle missing debug information
+
+When @value{GDBN} encounters a new objfile (@pxref{Objfiles In
+Python}), e.g.@: the primary executable, or any shared libraries used
+by the inferior, @value{GDBN} will attempt to load the corresponding
+debug information for that objfile. The debug information might be
+found within the objfile itself, or within a separate objfile which
+@value{GDBN} will automatically locate and load.
+
+Sometimes though, @value{GDBN} might not find any debug information
+for an objfile, in this case the debugging experience will be
+restricted.
+
+If @value{GDBN} fails to locate any debug information for a particular
+objfile, there is an opportunity for a Python extension to step in. A
+Python extension can potentially locate the missing debug information
+using some platform- or project-specific steps, and inform
+@value{GDBN} of its location. Or a Python extension might provide
+some platform- or project-specific advice to the user about how to
+obtain the missing debug information.
+
+A missing debug information Python extension consists of a handler
+object which has the @code{name} and @code{enabled} attributes, and
+implements the @code{__call__} method. When @value{GDBN} encounters
+an objfile for which it is unable to find any debug information, it
+invokes the @code{__call__} method. Full details of how handlers are
+written can be found below.
+
+@subheading The @code{gdb.missing_debug} Module
+
+@value{GDBN} comes with a @code{gdb.missing_debug} module which
+contains the following class and global function:
+
+@deftp{class} gdb.missing_debug.MissingDebugHandler
+
+@code{MissingDebugHandler} is a base class from which user-created
+handlers can derive, though it is not required that handlers derive
+from this class, so long as any user created handler has the
+@code{name} and @code{enabled} attributes, and implements the
+@code{__call__} method.
+
+@defun MissingDebugHandler.__init__ (name)
+The @var{name} is a string used to reference this missing debug
+handler within some @value{GDBN} commands. Valid names consist of the
+characters @code{[-_a-zA-Z0-9]}, creating a handler with an invalid
+name raises a @code{ValueError} exception.
+@end defun
+
+@defun MissingDebugHandler.__call__ (objfile)
+Sub-classes must override the @code{__call__} method. The
+@var{objfile} argument will be a @code{gdb.Objfile}, this is the
+objfile for which @value{GDBN} was unable to find any debug
+information.
+
+The return value from the @code{__call__} method indicates what
+@value{GDBN} should do next. The possible return values are:
+
+@itemize @bullet
+@item @code{None}
+
+This indicates that this handler could not help with @var{objfile},
+@value{GDBN} should call any other registered handlers.
+
+@item @code{True}
+
+This indicates that this handler has installed the debug information
+into a location where @value{GDBN} would normally expect to find it
+when looking for separate debug information files (@pxref{Separate
+Debug Files}). @value{GDBN} will repeat the normal lookup process,
+which should now find the separate debug file.
+
+If @value{GDBN} still doesn't find the separate debug information file
+after this second attempt, then the Python missing debug information
+handlers are not invoked a second time, this prevents a badly behaved
+handler causing @value{GDBN} to get stuck in a loop. @value{GDBN}
+will continue without any debug information for @var{objfile}.
+
+@item @code{False}
+
+This indicates that this handler has done everything that it intends
+to do with @var{objfile}, but no separate debug information can be
+found. @value{GDBN} will not call any other registered handlers for
+@var{objfile}. @value{GDBN} will continue without debugging
+information for @var{objfile}.
+
+@item A string
+
+The returned string should contain a filename. @value{GDBN} will not
+call any further registered handlers, and will instead load the debug
+information from the file identified by the returned filename.
+@end itemize
+
+Invoking the @code{__call__} method from this base class will raise a
+@code{NotImplementedError} exception.
+@end defun
+
+@defvar MissingDebugHandler.name
+A read-only attribute which is a string, the name of this handler
+passed to the @code{__init__} method.
+@end defvar
+
+@defvar MissingDebugHandler.enabled
+A modifiable attribute containing a boolean; when @code{True}, the
+handler is enabled, and will be used by @value{GDBN}. When
+@code{False}, the handler has been disabled, and will not be used.
+@end defvar
+@end deftp
+
+@defun gdb.missing_debug.register_handler (locus, handler, replace=@code{False})
+Register a new missing debug handler with @value{GDBN}.
+
+@var{handler} is an instance of a sub-class of
+@code{MissingDebugHandler}, or at least an instance of an object that
+has the same attributes and methods as @code{MissingDebugHandler}.
+
+@var{locus} specifies to which handler list to prepend @var{handler}.
+It can be either a @code{gdb.Progspace} (@pxref{Progspaces In Python})
+or @code{None}, in which case the handler is registered globally. The
+newly registered @var{handler} will be called before any other handler
+from the same locus. Two handlers in the same locus cannot have the
+same name, an attempt to add a handler with an already existing name
+raises an exception unless @var{replace} is @code{True}, in which case
+the old handler is deleted and the new handler is prepended to the
+selected handler list.
+
+@value{GDBN} first calls the handlers for the current program space,
+and then the globally registered handlers. As soon as a handler
+returns a value other than @code{None}, no further handlers are called
+for this objfile.
+@end defun
+
@node Python Auto-loading
@subsection Python Auto-loading
@cindex Python auto-loading