From patchwork Tue Apr 1 22:52:46 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Siva Chandra Reddy X-Patchwork-Id: 379 Return-Path: X-Original-To: siddhesh@wilcox.dreamhost.com Delivered-To: siddhesh@wilcox.dreamhost.com Received: from homiemail-mx22.g.dreamhost.com (mx2.sub5.homie.mail.dreamhost.com [208.113.200.128]) by wilcox.dreamhost.com (Postfix) with ESMTP id 7C8493600D4 for ; Tue, 1 Apr 2014 15:52:54 -0700 (PDT) Received: by homiemail-mx22.g.dreamhost.com (Postfix, from userid 14314964) id 2EF9E455AA3A; Tue, 1 Apr 2014 15:52:54 -0700 (PDT) X-Original-To: gdb@patchwork.siddhesh.in Delivered-To: x14314964@homiemail-mx22.g.dreamhost.com Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by homiemail-mx22.g.dreamhost.com (Postfix) with ESMTPS id F0170455AA5D for ; Tue, 1 Apr 2014 15:52:53 -0700 (PDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:mime-version:date:message-id:subject:from:to :content-type; q=dns; s=default; b=UJap8QWxmqMR8PEnZO+0hNHBja/Gh q/GwXon9jF3/eO5b25y32Cp506oWP9awFl9ubwSZ1b+2RiyWTMBMjqeDoyJxQ7qZ s0psqtMyt+4Funn84IwUVGWl5O7xg2GaESqKZHIhu5w6OKB07P7zg1DiIyzLxutO IwBWW9WqIlMUJU= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:mime-version:date:message-id:subject:from:to :content-type; s=default; bh=atwwjyeRuGcvKdfiTf5Jz+gq0cA=; b=G+o WEjGUmJfczwnHiHrcdu3xhsRWDU8JsPg16FPLOEyJ6iJ0P8J1d5fR+qGrWFJqKhB 8Yy/cRTqAtv3QrzLFgpJWetTQl/NA1uHNu7u9cgc0tn1dzHdFPnjNK0afi705c/l xVcP5vpwzkf6jMQn1IQp0iFDR09cEFZyEBqNp9bM= Received: (qmail 30394 invoked by alias); 1 Apr 2014 22:52:52 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 30381 invoked by uid 89); 1 Apr 2014 22:52:51 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.8 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-wg0-f52.google.com Received: from mail-wg0-f52.google.com (HELO mail-wg0-f52.google.com) (74.125.82.52) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Tue, 01 Apr 2014 22:52:49 +0000 Received: by mail-wg0-f52.google.com with SMTP id k14so8019103wgh.23 for ; Tue, 01 Apr 2014 15:52:46 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:date:message-id:subject:from:to :content-type; bh=7kVz26Uqqv7tkqjlVWQgWjXXwduJXus7DX32P8HYJVo=; b=TD1dZZ0WieGnn4BMJqeH2ArrJ1ef36qGzcewk9LLv1iEUSlULj/c9OPfU9e9xmY/jf mSc2TxJr99XUYykRgU7VGN6HBa90Hn3EzX8YpF/NaqHzFU8Ecv6xJQQJxTDgoPl1fn71 64xehmK8SNhDe97vB+SVQf7K9oTHHVKY9AdXiwqaWa86SbIh8ZXaM8SeCrJC4glYshYu 7x5d1zuuDYLcjXEdg4vZPRqtyzuXtGw1T6wigtVRwov0uoGuTQpbY1RLLTw/jhW22GOE EtEqri767oSr13/twVBXLYSO4C6g+R2nESw1lS2N4lJoVOa7qWPW3f/li+wf72j3dZ/x AHNg== X-Gm-Message-State: ALoCoQlaG0gLizZ3d4kM+A1J+UYOx7n4QEuQOZ0j4iYiZhPnWgIozxG6QShHx8UbLUrrBGfOe+Z0wmM88obvsq+dW08DOYXTruzgQul92C05qKIVekhzGc2acBM9e9/uVXk4pKwvxAFAgCymJDcnK+EallB0qnDpRGw0TUgm1cfufyf374XA3bQpJxLfjz/NSdeVUb/PSkSm/uR0wpV7XZinbDo0DvVg4g== MIME-Version: 1.0 X-Received: by 10.180.189.139 with SMTP id gi11mr23471162wic.53.1396392766703; Tue, 01 Apr 2014 15:52:46 -0700 (PDT) Received: by 10.15.48.194 with HTTP; Tue, 1 Apr 2014 15:52:46 -0700 (PDT) Date: Tue, 1 Apr 2014 15:52:46 -0700 Message-ID: Subject: [Patch v12 1/4] Documentation of the debug method support in GDB Python API From: Siva Chandra To: gdb-patches X-IsSubscribed: yes X-DH-Original-To: gdb@patchwork.siddhesh.in This part adds the docs and NEWS entries. I addressed all of Eli's and Doug's comments barring the following: Siva> +The @value{GDBN} Python API provides classes, interfaces and functions Siva> +to implement, register and manipulate debug methods. The core concepts Siva> +involved in implementing debug methods are @emph{debug method matchers} Siva> +and @emph{debug method workers}. Eli> The last sentence is a repetition of what the previous section said. Eli> Do we really need this here? I can remove the repetitive sentence. However, for the HTML version of the manual with each node on its own page, the repetition makes the page self contained (I think). Siva> +An instance of @code{DebugMethodMatcher} has the following attributes: Siva> + Siva> +@defvar DebugMethodMatcher.name Siva> +The name of the matcher. Siva> +@end defvar Eli> I think we use only the attribute name, without the class name. Are you referring to 'DebugMethodMatcher.name'? I find that other Python types are also documented in this fashion. 2014-04-01 Siva Chandra Reddy * NEWS (Python Scripting): Add entry about this new feature. doc/ * python.texi (Debug Methods In Python): New node. (Debug Method API): Likewise. (Writing a Debug Method): Likewise. diff --git a/gdb/NEWS b/gdb/NEWS index df233fc..133d02a 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -94,6 +94,11 @@ qXfer:btrace:read's annex ** Valid Python operations on gdb.Value objects representing structs/classes invoke the corresponding overloaded operators if available. + ** New `Debug Methods' feature in the Python API. Debug methods 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* diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index 90b7074..f149ea0 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -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. +* Debug Methods In Python:: Adding and replacing methods of C++ classes. +* Debug Method API:: Debug method types. +* Writing a Debug Method:: Writing a debug method. * 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. @@ -2195,6 +2198,267 @@ printed hierarchically. Another approach would be to combine the marker in the inlined frame, and also show the hierarchical relationship. +@node Debug Methods In Python +@subsubsection Debug Methods In Python +@cindex debug methods in Python + +@dfn{Debug methods} 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 a debug method to serve as a replacement +for the method defined in the C@t{++} source code. @value{GDBN} will +then invoke the debug method, instead of the C@t{++} method, to +evaluate expressions. One can also use debug methods when debugging +with core files. Moreover, when debugging live programs, invoking a +debug method 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 debug method if one is defined. + +The debug methods feature in Python is available via the concepts of a +@dfn{debug method matcher} and a @dfn{debug method worker}. To +implement a debug method, 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 debug method. They implement a @code{get_arg_types} method which +returns a sequence of types corresponding to the arguments the debug +method requires. @value{GDBN} uses this sequence of types to perform +overload resolution and picks a winning debug method worker. A winner +is also selected from among the methods @value{GDBN} finds in the +C@t{++} source code. Next, the winning debug method worker and the +winning C@t{++} method are compared to select an overall winner. In +case of a tie between a debug method worker and a C@t{++} method, the +debug method worker is selected as the winner. That is, if a winning +debug method worker is found to be equivalent to the winning C@t{++} +method, then the debug method worker is treated as a replacement for +the C@t{++} method. @value{GDBN} uses the overall winner to invoke the +method. If the winning debug method worker is the overall winner, then +the corresponding debug method is invoked via the @code{invoke} method +of the worker object. + +If one wants to implement a debug method as a replacement for an +existing C@t{++} method, then they have to implement an equivalent +debug method 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 debug method is +available for that method, then they can disable the debug method. + +@xref{Debug Method API}, for API to implement debug methods in Python. +@xref{Writing a Debug Method}, for implementing debug methods in Python. + +@node Debug Method API +@subsubsection Debug Method API +@cindex debug method API + +The @value{GDBN} Python API provides classes, interfaces and functions +to implement, register and manipulate debug methods. The core concepts +involved in implementing debug methods are @emph{debug method matchers} +and @emph{debug method workers}. @xref{Debug Methods In Python}. + +A debug method matcher should be an instance of a class derived from +@code{DebugMethodMatcher} defined in the module +@code{gdb.debug_method}. An instance of @code{DebugMethodMatcher} has +the following attributes: + +@defvar DebugMethodMatcher.name +The name of the matcher. +@end defvar + +@defvar DebugMethodMatcher.enabled +A boolean value indicating whether the matcher is enabled or disabled. +@end defvar + +@defvar DebugMethodMatcher.methods +A list of named methods managed by the matcher. Each object in the list +is an instance of the class @code{DebugMethod} defined in the module +@code{gdb.debug_method}, or any object with the following attributes: + +@table @code + +@item name +Name of the debug method which should be unique for each debug method +managed by the matcher. + +@item enabled +A boolean value indicating whether the debug method is enabled or +disabled. + +@end table + +The class @code{DebugMethod} is a convenience class with same +attributes as above along with the following constructor: + +@defun DebugMethod.__init__(self, name) +Constructs an enabled debug method with name @var{name}. +@end defun +@end defvar + +@noindent +The @code{DebugMethodMatcher} class has the following methods: + +@defun DebugMethodMatcher.__init__(self, name) +Constructs an enabled debug method matcher with name @var{name}. The +@code{methods} attribute is initialized to @code{None}. +@end defun + +@defun DebugMethodMatcher.match(self, class_type, method_name) +Derived classes should override this method. It should return a +debug method worker object (or a sequence of debug method 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 debug method worker should be an instance of a class derived from +@code{DebugMethodWorker} defined in the module @code{gdb.debug_method}, +or support the following interface: + +@defun DebugMethodWorker.get_arg_types(self) +This method returns a sequence of @code{gdb.Type} objects corresponding +to the arguments that the debug method takes. It can return an empty +sequence or @code{None} if the debug method does not take any arguments. +If the debug method takes a single argument, then a single +@code{gdb.Type} object corresponding to it can be returned. +@end defun + +@defun DebugMethodWorker.invoke(self, obj, args) +This is the method which does the @emph{work} of the debug method. +@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 debug methods, the debug method matchers +should be registered using the following function defined in the module +@code{gdb.debug_method}: + +@defun register_debug_method_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 Debug Method +@subsubsection Writing a Debug Method +@cindex writing debug methods in Python + +Implementing debug methods in Python will require implementing debug +method matchers and debug method workers +(@pxref{Debug Methods 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 debug methods 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 +debug method matcher can be defined as follows: + +@smallexample +class MyClassMatcher(gdb.debug_method.DebugMethodMatcher): + def __init__(self): + gdb.debug_method.DebugMethodMatcher.__init__(self, 'MyMatcher') + # List of methods 'managed' by this matcher + self.methods = [gdb.debug_method.DebugMethod('geta'), + gdb.debug_method.DebugMethod('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.debug_method.DebugMethodWorker): + def get_arg_types(self): + return None + + def invoke(self, obj, args): + return obj['a_'] + + +class MyClassWorker_plus(gdb.debug_method.DebugMethodWorker): + 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 debug method, it has to be +registered with it. The matcher defined above is registered with +@value{GDBN} globally as follows: + +@smallexample +gdb.debug_method.register_debug_method_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 debug method matchers +and workers into @code{GDBN}, invoking the method @code{geta} or using +the operator @code{+} on @code{obj} will invoke the debug methods +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