aboutsummaryrefslogtreecommitdiff
path: root/gdb/doc
diff options
context:
space:
mode:
authorSasha Smundak <asmundak@google.com>2015-04-01 11:49:12 -0700
committerDoug Evans <dje@google.com>2015-04-01 11:49:12 -0700
commitd11916aa89c43071c08c1f9b4550a01f8eec78e3 (patch)
tree7befd0c4b5e47eba48fec1b2b03888dcffbadd7b /gdb/doc
parent79730a3b2683dba745663fa3b907f564bee8a0ef (diff)
downloadgdb-d11916aa89c43071c08c1f9b4550a01f8eec78e3.zip
gdb-d11916aa89c43071c08c1f9b4550a01f8eec78e3.tar.gz
gdb-d11916aa89c43071c08c1f9b4550a01f8eec78e3.tar.bz2
Add support for writing unwinders in Python.
gdb/ChangeLog: * Makefile.in (SUBDIR_PYTHON_OBJS): Add py-unwind.o. (SUBDIR_PYTHON_SRCS): Add py-unwind.c. (py-unwind.o): New recipe. * NEWS: mention Python frame unwinding. * data-directory/Makefile.in (PYTHON_FILE_LIST): Add gdb/unwinder.py and gdb/command/unwinder.py * python/lib/gdb/__init__.py (packages): Add frame_unwinders list. (execute_unwinders): New function. * python/lib/gdb/command/unwinders.py: New file. * python/lib/gdb/unwinder.py: New file. * python/py-objfile.c (objfile_object): Add frame_unwinders field. (objfpy_dealloc): Decrement frame_unwinders reference count. (objfpy_initialize): Create frame_unwinders list. (objfpy_get_frame_unwinders): New function. (objfpy_set_frame_unwinders): Ditto. (objfile_getset): Add frame_unwinders attribute to Objfile. * python/py-progspace.c (pspace_object): Add frame_unwinders field. (pspy_dealloc): Decrement frame_unwinders reference count. (pspy_initialize): Create frame_unwinders list. (pspy_get_frame_unwinders): New function. (pspy_set_frame_unwinders): Ditto. (pspy_getset): Add frame_unwinders attribute to gdb.Progspace. * python/py-unwind.c: New file. * python/python-internal.h (pspy_get_name_unwinders): New prototype. (objpy_get_frame_unwinders): New prototype. (gdbpy_initialize_unwind): New prototype. * python/python.c (gdbpy_apply_type_printers): Call gdbpy_initialize_unwind. gdb/doc/ChangeLog: * doc/python.texi (Writing a Frame Unwinder in Python): Add section. gdb/testsuite/ChangeLog: * gdb.python/py-unwind-maint.c: New file. * gdb.python/py-unwind-maint.exp: New test. * gdb.python/py-unwind-maint.py: New file. * gdb.python/py-unwind.c: New file. * gdb.python/py-unwind.exp: New test. * gdb.python/py-unwind.py: New test.
Diffstat (limited to 'gdb/doc')
-rw-r--r--gdb/doc/ChangeLog5
-rw-r--r--gdb/doc/python.texi143
2 files changed, 148 insertions, 0 deletions
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index 871b626..8376689 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,8 @@
+2015-04-01 Sasha Smundak <asmundak@google.com>
+
+ * doc/python.texi (Writing a Frame Unwinder in Python): Add
+ section.
+
2015-03-31 Sergio Durigan Junior <sergiodj@redhat.com>
PR corefiles/16092
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index d725eb0..098d718 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -144,6 +144,7 @@ optional arguments while skipping others. Example:
* Frame Filter API:: Filtering Frames.
* Frame Decorator API:: Decorating Frames.
* Writing a Frame Filter:: Writing a Frame Filter.
+* Unwinding Frames in Python:: Writing frame unwinder.
* Xmethods In Python:: Adding and replacing methods of C++ classes.
* Xmethod API:: Xmethod types.
* Writing an Xmethod:: Writing an xmethod.
@@ -2178,6 +2179,148 @@ printed hierarchically. Another approach would be to combine the
marker in the inlined frame, and also show the hierarchical
relationship.
+@node Unwinding Frames in Python
+@subsubsection Unwinding Frames in Python
+@cindex unwinding frames in Python
+
+In @value{GDBN} terminology ``unwinding'' is the process of finding
+the previous frame (that is, caller's) from the current one. An
+unwinder has three methods. The first one checks if it can handle
+given frame (``sniff'' it). For the frames it can sniff an unwinder
+provides two additional methods: it can return frame's ID, and it can
+fetch registers from the previous frame. A running @value{GDBN}
+mantains a list of the unwinders and calls each unwinder's sniffer in
+turn until it finds the one that recognizes the current frame. There
+is an API to register an unwinder.
+
+The unwinders that come with @value{GDBN} handle standard frames.
+However, mixed language applications (for example, an application
+running Java Virtual Machine) sometimes use frame layouts that cannot
+be handled by the @value{GDBN} unwinders. You can write Python code
+that can handle such custom frames.
+
+You implement a frame unwinder in Python as a class with which has two
+attributes, @code{name} and @code{enabled}, with obvious meanings, and
+a single method @code{__call__}, which examines a given frame and
+returns an object (an instance of @code{gdb.UnwindInfo class)}
+describing it. If an unwinder does not recognize a frame, it should
+return @code{None}. The code in @value{GDBN} that enables writing
+unwinders in Python uses this object to return frame's ID and previous
+frame registers when @value{GDBN} core asks for them.
+
+@subheading Unwinder Input
+
+An object passed to an unwinder (a @code{gdb.PendingFrame} instance)
+provides a method to read frame's registers:
+
+@defun PendingFrame.read_register (reg)
+This method returns the contents of the register @var{regn} in the
+frame as a @code{gdb.Value} object. @var{reg} can be either a
+register number or a register name; the values are platform-specific.
+They are usually found in the corresponding
+@file{@var{platform}-tdep.h} file in the @value{GDBN} source tree.
+@end defun
+
+It also provides a factory method to create a @code{gdb.UnwindInfo}
+instance to be returned to @value{GDBN}:
+
+@defun PendingFrame.create_unwind_info (frame_id)
+Returns a new @code{gdb.UnwindInfo} instance identified by given
+@var{frame_id}. The argument is used to build @value{GDBN}'s frame ID
+using one of functions provided by @value{GDBN}. @var{frame_id}'s attributes
+determine which function will be used, as follows:
+
+@table @code
+@item sp, pc, special
+@code{frame_id_build_special (@var{frame_id}.sp, @var{frame_id}.pc, @var{frame_id}.special)}
+
+@item sp, pc
+@code{frame_id_build (@var{frame_id}.sp, @var{frame_id}.pc)}
+
+This is the most common case.
+
+@item sp
+@code{frame_id_build_wild (@var{frame_id}.sp)}
+@end table
+The attribute values should be @code{gdb.Value}
+
+@end defun
+
+@subheading Unwinder Output: UnwindInfo
+
+Use @code{PendingFrame.create_unwind_info} method described above to
+create a @code{gdb.UnwindInfo} instance. Use the following method to
+specify caller registers that have been saved in this frame:
+
+@defun gdb.UnwindInfo.add_saved_register (reg, value)
+@var{reg} identifies the register. It can be a number or a name, just
+as for the @code{PendingFrame.read_register} method above.
+@var{value} is a register value (a @code{gdb.Value} object).
+@end defun
+
+@subheading Unwinder Skeleton Code
+
+@value{GDBN} comes with the module containing the base @code{Unwinder}
+class. Derive your unwinder class from it and structure the code as
+follows:
+
+@smallexample
+from gdb.unwinders import Unwinder
+
+class FrameId(object):
+ def __init__(self, sp, pc):
+ self.sp = sp
+ self.pc = pc
+
+
+class MyUnwinder(Unwinder):
+ def __init__(....):
+ supe(MyUnwinder, self).__init___(<expects unwinder name argument>)
+
+ def __call__(pending_frame):
+ if not <we recognize frame>:
+ return None
+ # Create UnwindInfo. Usually the frame is identified by the stack
+ # pointer and the program counter.
+ sp = pending_frame.read_register(<SP number>)
+ pc = pending_frame.read_register(<PC number>)
+ unwind_info = pending_frame.create_unwind_info(FrameId(sp, pc))
+
+ # Find the values of the registers in the caller's frame and
+ # save them in the result:
+ unwind_info.add_saved_register(<register>, <value>)
+ ....
+
+ # Return the result:
+ return unwind_info
+
+@end smallexample
+
+@subheading Registering a Unwinder
+
+An object file, a program space, and the @value{GDBN} proper can have
+unwinders registered with it.
+
+The @code{gdb.unwinders} module provides the function to register a
+unwinder:
+
+@defun gdb.unwinder.register_unwinder (locus, unwinder, replace=False)
+@var{locus} is specifies an object file or a program space to which
+@var{unwinder} is added. Passing @code{None} or @code{gdb} adds
+@var{unwinder} to the @value{GDBN}'s global unwinder list. The newly
+added @var{unwinder} will be called before any other unwinder from the
+same locus. Two unwinders in the same locus cannot have the same
+name. An attempt to add a unwinder with already existing name raises
+an exception unless @var{replace} is @code{True}, in which case the
+old unwinder is deleted.
+@end defun
+
+@subheading Unwinder Precedence
+
+@value{GDBN} first calls the unwinders from all the object files in no
+particular order, then the unwinders from the current program space,
+and finally the unwinders from @value{GDBN}.
+
@node Xmethods In Python
@subsubsection Xmethods In Python
@cindex xmethods in Python