diff options
author | Sasha Smundak <asmundak@google.com> | 2015-04-01 11:49:12 -0700 |
---|---|---|
committer | Doug Evans <dje@google.com> | 2015-04-01 11:49:12 -0700 |
commit | d11916aa89c43071c08c1f9b4550a01f8eec78e3 (patch) | |
tree | 7befd0c4b5e47eba48fec1b2b03888dcffbadd7b /gdb/doc | |
parent | 79730a3b2683dba745663fa3b907f564bee8a0ef (diff) | |
download | gdb-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/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/doc/python.texi | 143 |
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 |