[1/4,v18] Add xmethod documentation and NEWS entry
Commit Message
This part was approved (I think) previously but sending it out with
version synced to v18. Also, the name changed from "debug method" to
"xmethod". Hence, I think another review is required.
ChangeLog
2014-05-23 Siva Chandra Reddy <sivachandra@google.com>
* NEWS (Python Scripting): Add entry about the new xmethods
feature.
doc/
* python.texi (Xmethods In Python, XMethod API)
(Writing an Xmethod): New nodes.
(Python API): New menu entries "Xmethods In Python",
"Xmethod API", "Writing an Xmethod".
Comments
> Date: Fri, 23 May 2014 14:55:01 -0700
> From: Siva Chandra <sivachandra@google.com>
>
> This part was approved (I think) previously but sending it out with
> version synced to v18. Also, the name changed from "debug method" to
> "xmethod". Hence, I think another review is required.
You've got it.
> +@defun XMethodWorker.invoke(self, obj, args)
> +This is the method which does the @emph{work} of the xmethod.
> +@var{obj} is the object on which the method is being invoked, and
> +@var{args} is the tuple of arguments to the method. @var{obj} and the
> +elements of @var{args} are @code{gdb.Value} objects.
It is best not to begin a sentence with "@var{something}", since in
the printed manual that will produce a sentence starting from a
lower-case letter.
Otherwise, OK. Thanks.
@@ -133,6 +133,11 @@ qXfer:btrace:read's annex
** Valid Python operations on gdb.Value objects representing
structs/classes invoke the corresponding overloaded operators if
available.
+ ** New `Xmethods' feature in the Python API. Xmethods are
+ additional methods or replacements for existing methods of a C++
+ class. This feature is useful for those cases where a method
+ defined in C++ source code could be inlined or optimized out by
+ the compiler, making it unavailable to GDB.
* New targets
PowerPC64 GNU/Linux little-endian powerpc64le-*-linux*
@@ -144,6 +144,9 @@ optional arguments while skipping others. Example:
* Frame Filter API:: Filtering Frames.
* Frame Decorator API:: Decorating Frames.
* Writing a Frame Filter:: Writing a Frame Filter.
+* Xmethods In Python:: Adding and replacing methods of C++ classes.
+* Xmethod API:: Xmethod types.
+* Writing an Xmethod:: Writing an xmethod.
* Inferiors In Python:: Python representation of inferiors (processes)
* Events In Python:: Listening for events from @value{GDBN}.
* Threads In Python:: Accessing inferior threads from Python.
@@ -2175,6 +2178,265 @@ printed hierarchically. Another approach would be to combine the
marker in the inlined frame, and also show the hierarchical
relationship.
+@node Xmethods In Python
+@subsubsection Xmethods In Python
+@cindex xmethods in Python
+
+@dfn{Xmethods} are additional methods or replacements for existing
+methods of a C@t{++} class. This feature is useful for those cases
+where a method defined in C@t{++} source code could be inlined or
+optimized out by the compiler, making it unavailable to @value{GDBN}.
+For such cases, one can define an xmethod to serve as a replacement
+for the method defined in the C@t{++} source code. @value{GDBN} will
+then invoke the xmethod, instead of the C@t{++} method, to
+evaluate expressions. One can also use xmethods when debugging
+with core files. Moreover, when debugging live programs, invoking an
+xmethod need not involve running the inferior (which can potentially
+perturb its state). Hence, even if the C@t{++} method is available, it
+is better to use its replacement xmethod if one is defined.
+
+The xmethods feature in Python is available via the concepts of an
+@dfn{xmethod matcher} and an @dfn{xmethod worker}. To
+implement an xmethod, one has to implement a matcher and a
+corresponding worker for it (more than one worker can be
+implemented, each catering to a different overloaded instance of the
+method). Internally, @value{GDBN} invokes the @code{match} method of a
+matcher to match the class type and method name. On a match, the
+@code{match} method returns a list of matching @emph{worker} objects.
+Each worker object typically corresponds to an overloaded instance of
+the xmethod. They implement a @code{get_arg_types} method which
+returns a sequence of types corresponding to the arguments the xmethod
+requires. @value{GDBN} uses this sequence of types to perform
+overload resolution and picks a winning xmethod worker. A winner
+is also selected from among the methods @value{GDBN} finds in the
+C@t{++} source code. Next, the winning xmethod worker and the
+winning C@t{++} method are compared to select an overall winner. In
+case of a tie between a xmethod worker and a C@t{++} method, the
+xmethod worker is selected as the winner. That is, if a winning
+xmethod worker is found to be equivalent to the winning C@t{++}
+method, then the xmethod worker is treated as a replacement for
+the C@t{++} method. @value{GDBN} uses the overall winner to invoke the
+method. If the winning xmethod worker is the overall winner, then
+the corresponding xmethod is invoked via the @code{invoke} method
+of the worker object.
+
+If one wants to implement an xmethod as a replacement for an
+existing C@t{++} method, then they have to implement an equivalent
+xmethod which has exactly the same name and takes arguments of
+exactly the same type as the C@t{++} method. If the user wants to
+invoke the C@t{++} method even though a replacement xmethod is
+available for that method, then they can disable the xmethod.
+
+@xref{Xmethod API}, for API to implement xmethods in Python.
+@xref{Writing an Xmethod}, for implementing xmethods in Python.
+
+@node Xmethod API
+@subsubsection Xmethod API
+@cindex xmethod API
+
+The @value{GDBN} Python API provides classes, interfaces and functions
+to implement, register and manipulate xmethods.
+@xref{Xmethods In Python}.
+
+A xmethod matcher should be an instance of a class derived from
+@code{XMethodMatcher} defined in the module @code{gdb.xmethod}, or an
+object with similar interface and attributes. An instance of
+@code{XMethodMatcher} has the following attributes:
+
+@defvar name
+The name of the matcher.
+@end defvar
+
+@defvar enabled
+A boolean value indicating whether the matcher is enabled or disabled.
+@end defvar
+
+@defvar methods
+A list of named methods managed by the matcher. Each object in the list
+is an instance of the class @code{XMethod} defined in the module
+@code{gdb.xmethod}, or any object with the following attributes:
+
+@table @code
+
+@item name
+Name of the xmethod which should be unique for each xmethod
+managed by the matcher.
+
+@item enabled
+A boolean value indicating whether the xmethod is enabled or
+disabled.
+
+@end table
+
+The class @code{XMethod} is a convenience class with same
+attributes as above along with the following constructor:
+
+@defun XMethod.__init__(self, name)
+Constructs an enabled xmethod with name @var{name}.
+@end defun
+@end defvar
+
+@noindent
+The @code{XMethodMatcher} class has the following methods:
+
+@defun XMethodMatcher.__init__(self, name)
+Constructs an enabled xmethod matcher with name @var{name}. The
+@code{methods} attribute is initialized to @code{None}.
+@end defun
+
+@defun XMethodMatcher.match(self, class_type, method_name)
+Derived classes should override this method. It should return a
+xmethod worker object (or a sequence of xmethod worker
+objects) matching the @var{class_type} and @var{method_name}.
+@var{class_type} is a @code{gdb.Type} object, and @var{method_name}
+is a string value. If the matcher manages named methods as listed in
+its @code{methods} attribute, then only those worker objects whose
+corresponding entries in the @code{methods} list are enabled should be
+returned.
+@end defun
+
+A xmethod worker should be an instance of a class derived from
+@code{XMethodWorker} defined in the module @code{gdb.xmethod},
+or support the following interface:
+
+@defun XMethodWorker.get_arg_types(self)
+This method returns a sequence of @code{gdb.Type} objects corresponding
+to the arguments that the xmethod takes. It can return an empty
+sequence or @code{None} if the xmethod does not take any arguments.
+If the xmethod takes a single argument, then a single
+@code{gdb.Type} object corresponding to it can be returned.
+@end defun
+
+@defun XMethodWorker.invoke(self, obj, args)
+This is the method which does the @emph{work} of the xmethod.
+@var{obj} is the object on which the method is being invoked, and
+@var{args} is the tuple of arguments to the method. @var{obj} and the
+elements of @var{args} are @code{gdb.Value} objects.
+@end defun
+
+For @value{GDBN} to lookup xmethods, the xmethod matchers
+should be registered using the following function defined in the module
+@code{gdb.xmethod}:
+
+@defun register_xmethod_matcher(locus, matcher, replace=False)
+The @code{matcher} is registered with @code{locus}, replacing an
+existing matcher with the same name as @code{matcher} if
+@code{replace} is @code{True}. @code{locus} can be a
+@code{gdb.Objfile} object (@pxref{Objfiles In Python}), or a
+@code{gdb.Progspace} object (@pxref{Program Spaces In Python}), or
+@code{None}. If it is @code{None}, then @code{matcher} is registered
+globally.
+@end defun
+
+@node Writing a Xmethod
+@subsubsection Writing a Xmethod
+@cindex writing xmethods in Python
+
+Implementing xmethods in Python will require implementing xmethod
+matchers and xmethod workers (@pxref{Xmethods In Python}). Consider
+the following C@t{++} class:
+
+@smallexample
+class MyClass
+@{
+ public:
+ MyClass (int a) : a_(a) {}
+
+ int geta (void) { return a_; }
+ int operator+ (int b);
+
+ private:
+ int a_;
+@};
+
+int
+MyClass::operator+ (int b)
+@{
+ return a_ + b;
+@}
+@end smallexample
+
+@noindent
+Let us define two xmethods for the class @code{MyClass}, one
+replacing the method @code{geta}, and another adding an overloaded
+flavor of @code{operator+} which takes a @code{MyClass} argument. The
+xmethod matcher can be defined as follows:
+
+@smallexample
+class MyClassMatcher(gdb.xmethod.XMethodMatcher):
+ def __init__(self):
+ gdb.xmethod.XMethodMatcher.__init__(self, 'MyMatcher')
+ # List of methods 'managed' by this matcher
+ self.methods = [gdb.xmethod.XMethod('geta'),
+ gdb.xmethod.XMethod('sum')]
+
+ def match(self, class_type, method_name):
+ if class_type.tag != 'MyClass':
+ return None
+ if method_name == 'geta' and self.methods[0].enabled:
+ return MyClassWorker_geta()
+ elif method_name == 'operator+' and self.methods[1].enabled:
+ return MyClassWorker_plus()
+ else:
+ return None
+@end smallexample
+
+@noindent
+Notice that the @code{match} method of @code{MyClassMatcher} returns
+a worker object of type @code{MyClassWorker_geta} for the @code{geta}
+method, and a worker object of type @code{MyClassWorker_plus} for the
+@code{operator+} method. Also, a worker object is returned only if the
+corresponding entry in the @code{methods} attribute is enabled.
+
+The implementation of the worker classes returned by the matcher above
+is as follows:
+
+@smallexample
+class MyClassWorker_geta(gdb.xmethod.XMethodWorker):
+ def get_arg_types(self):
+ return None
+
+ def invoke(self, obj, args):
+ return obj['a_']
+
+
+class MyClassWorker_plus(gdb.xmethod.XMethodWorker):
+ def get_arg_types(self):
+ return gdb.lookup_type('MyClass')
+
+ def invoke(self, obj, args):
+ return obj['a_'] + args[0]['a_']
+@end smallexample
+
+For @value{GDBN} to actually lookup a xmethod, it has to be
+registered with it. The matcher defined above is registered with
+@value{GDBN} globally as follows:
+
+@smallexample
+gdb.xmethod.register_xmethod_matcher(None, MyClassMatcher())
+@end smallexample
+
+If an object @code{obj} of type @code{MyClass} is initialized in C@t{++}
+code as follows:
+
+@smallexample
+MyClass obj(5);
+@end smallexample
+
+@noindent
+then, after loading the Python script defining the xmethod matchers
+and workers into @code{GDBN}, invoking the method @code{geta} or using
+the operator @code{+} on @code{obj} will invoke the xmethods
+defined above:
+
+@smallexample
+(gdb) p obj.geta()
+$1 = 5
+
+(gdb) p obj + obj
+$2 = 10
+@end smallexample
+
@node Inferiors In Python
@subsubsection Inferiors In Python
@cindex inferiors in Python