This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
Fixed documentation and added '_gdb.' prefix to 'objfiles()'. PTAL. On Mon, Mar 30, 2015 at 10:45 AM, Doug Evans <dje@google.com> wrote: > Alexander Smundak writes: > > Addressed eliz@ and dje@ comments. > > > > gdb/ChangeLog > > > > 2015-03-28 Sasha Smundak <asmundak@google.com> > > > > * 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 > > * doc/python.texi (Writing a Frame Unwinder in Python): Add > > section. > > * 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/testsuite/ChangeLog > > > > 2015-03-28 Sasha Smundak <asmundak@google.com> > > > > * 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. > > Hi. Just a few more nits. > > > diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi > > index d725eb0..6b1878e 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 > > + > > +A @code{gdb.UnwindInfo} object can be constructed by one of the > > +methods described above. Use the following method to set the caller > > I'd replace "can be constructed by one of the methods describe above." with > "is constructed with the @code{PendingFrame.create_unwind_info} > method described above." > > > +frame's registers: > > + > > +@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_instance > > s/unwind_instance/unwind_info/ > > > diff --git a/gdb/python/lib/gdb/__init__.py b/gdb/python/lib/gdb/__init__.py > > index 92b06f2..0494959 100644 > > --- a/gdb/python/lib/gdb/__init__.py > > +++ b/gdb/python/lib/gdb/__init__.py > > @@ -71,6 +71,42 @@ type_printers = [] > > xmethods = [] > > # Initial frame filters. > > frame_filters = {} > > +# Initial frame unwinders. > > +frame_unwinders = [] > > + > > +def execute_unwinders(pending_frame): > > + """Internal function called from GDB to execute all unwinders. > > + > > + Runs each currently enabled unwinder until it finds the one that > > + can unwind given frame. > > + > > + Arguments: > > + pending_frame: gdb.PendingFrame instance. > > + Returns: > > + gdb.UnwindInfo instance or None. > > + """ > > + for objfile in objfiles(): > > It's odd to call objfiles() here and _gdb.current_progspace() below. > Either the _gdb. prefix is necessary or it is not. > At the least let's be consistent here. > How about instead of adding _gdb. prefix here ... > > > + for unwinder in objfile.frame_unwinders: > > + if unwinder.enabled: > > + unwind_info = unwinder(pending_frame) > > + if unwind_info is not None: > > + return unwind_info > > + > > + current_progspace = _gdb.current_progspace() > > .... remove it here. > [and rerun the testsuite to verify] > > > + for unwinder in current_progspace.frame_unwinders: > > + if unwinder.enabled: > > + unwind_info = unwinder(pending_frame) > > + if unwind_info is not None: > > + return unwind_info > > + > > + for unwinder in frame_unwinders: > > + if unwinder.enabled: > > + unwind_info = unwinder(pending_frame) > > + if unwind_info is not None: > > + return unwind_info > > + > > + return None > > + > > > > # Convenience variable to GDB's python directory > > PYTHONDIR = os.path.dirname(os.path.dirname(__file__))
Attachment:
patch11.diff
Description: Text document
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |