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]

Re: [Patch v9] Debug methods in GDB Python


Siva Chandra writes:
 > Hi,
 > 
 > Attached is the v9 of the patch which adds debug methods feature to
 > the Python API. I have added doc changes in this version (barring a
 > NEWS entry). I request a full review this time.
 > 
 > Changes from v8:
 > 
 > 1. Fixed copyright headers.
 > 2. Added a debug methods interface to the extension language API and
 > implemented the debug methods support in Python using this interface.
 > 3. Added doc changes for debug methods.
 > 
 > Pending items:
 > 
 > 1. NEWS entry
 > 2. A node for debug method commands in gdb.texinfo. I have question
 > here: Should I follow the "Pretty Printing" as an example and add a
 > section "Debug Methods" under "Examining Data"? Then, a node under
 > this section for debug method commands can be added.
 > 
 > 2014-02-10  Siva Chandra Reddy  <sivachandra@google.com>
 > 
 >         * Makefile.in: Add entries for new files.
 >         * data-directory/Makefile.in: Add entries for new Python files.
 >         * eval.c (evaluate_subexp_standard): Lookup and invoke methods
 >         defined in extension languages.
 >         * extension-priv.h (struct extension_language_defn): Add a
 >         pointer to the debug method interface "v-table".
 >         (struct extension_language_debug_method_ops): New struct
 >         defining the debug method interface for extension languages.
 >         * extension.c (new_debug_method_worker): New function.
 >         (clone_debug_method_worker): Likewise.
 >         (get_matching_debug_method_workers): Likewise.
 >         (get_debug_method_argtypes): Likewise.
 >         (invoke_debug_method): Likewise
 >         (free_debug_method_worker_vec): Likewise.
 >         (make_debug_method_worker_vec_cleanup): Likewise.
 >         * extension.h: New function declarations.
 >         (struct debug_method_worker): New struct.
 >         (VEC (debug_method_worker_p)): New type.
 >         (debug_method_worker_p): New typedef.
 >         (debug_method_worker_vec): Likewise.
 >         * guile/guile.c (extension_language_guile): Set the vtable
 >         of the debug methods interface to NULL.
 >         * valarith.c (value_x_binop, value_x_unop): Lookup and invoke
 >         overloaded operator methods defined in extension languages.
 >         * valops.c (find_oload_method_list, find_method_list,
 >         find_overload_match, find_oload_champ): Lookup methods defined
 >         in extension languages.
 >         (value_has_indirect_dynamic_type): New function to determine
 >         the indirect dynamic type of a value.
 >         * value.h (find_overload_match): Update signature.
 >         * python/py-debugmethods.c: New file.
 >         * python/py-objfile.c (objfile_object): New field
 >         'debugmethod_matchers'.
 >         (objfpy_dealloc): XDECREF on the new debugmethod_matcherss field.
 >         (objfpy_new, objfile_to_objfile_object): Initialize
 >         debugmethod_macthers field.
 >         (objfpy_get_debugmethod_matchers): New function.
 >         (objfile_getset): New entry 'debugmethod_matchers'.
 >         * python/py-progspace.c (pspace_object): New field
 >         'debugmethod_matchers'.
 >         (pspy_dealloc): XDECREF on the new debugmethod_matchers field.
 >         (pspy_new, pspace_to_pspace_object): Initialize
 >         debugmethod_matchers field.
 >         (pspy_get_debugmethod_matchers): New function.
 >         (pspace_getset): New entry 'debug_methods'.
 >         * python/python-internal.h: Add declarations for new functions.
 >         * python/python.c (_initialize_python): Invoke
 >         gdbpy_initialize_debugmethods.
 >         * python/python.h: Add declarations of new functions.
 >         * python/lib/gdb/__init__.py (debug_methods): New attribute.
 >         * python/lib/gdb/debugmethods.py: New file.
 >         * python/lib/gdb/command/debugmethods.py: New file.
 > 
 >         testuite/
 >         * gdb.python/py-debugmethods.cc: New testcase to test debug
 >         methods.
 >         * gdb.python/py-debugmethods.exp: New tests to test debug
 >         methods.
 >         * gdb.python/py-debugmethods.py: Python script supporting the
 >         new testcase and tests.
 > 
 >         doc/
 >         * gdb.texinfo (Debug Methods In Python): New node.
 >         (Debug Method API): Likewise.
 >         (Writing a Debug Method): Likewise.
 > diff --git a/gdb/Makefile.in b/gdb/Makefile.in
 > index 6c8db6f..bcefc3d 100644
 > --- a/gdb/Makefile.in
 > +++ b/gdb/Makefile.in
 > @@ -344,6 +344,7 @@ SUBDIR_PYTHON_OBS = \
 >  	py-breakpoint.o \
 >  	py-cmd.o \
 >  	py-continueevent.o \
 > +	py-debugmethods.o \
 >  	py-event.o \
 >  	py-evtregistry.o \
 >  	py-evts.o \
 > @@ -380,6 +381,7 @@ SUBDIR_PYTHON_SRCS = \
 >  	python/py-breakpoint.c \
 >  	python/py-cmd.c \
 >  	python/py-continueevent.c \
 > +	python/py-debugmethods.c \
 >  	python/py-event.c \
 >  	python/py-evtregistry.c \
 >  	python/py-evts.c \
 > @@ -2366,6 +2368,10 @@ py-continueevent.o: $(srcdir)/python/py-continueevent.c
 >  	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-continueevent.c
 >  	$(POSTCOMPILE)
 >  
 > +py-debugmethods.o: $(srcdir)/python/py-debugmethods.c
 > +	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-debugmethods.c
 > +	$(POSTCOMPILE)
 > +
 >  py-event.o: $(srcdir)/python/py-event.c
 >  	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-event.c
 >  	$(POSTCOMPILE)
 > diff --git a/gdb/data-directory/Makefile.in b/gdb/data-directory/Makefile.in
 > index 3288e50..6425d16 100644
 > --- a/gdb/data-directory/Makefile.in
 > +++ b/gdb/data-directory/Makefile.in
 > @@ -63,8 +63,10 @@ PYTHON_FILES = \
 >  	gdb/types.py \
 >  	gdb/printing.py \
 >  	gdb/prompt.py \
 > +	gdb/debugmethods.py \
 >  	gdb/command/bound_registers.py \
 >  	gdb/command/__init__.py \
 > +	gdb/command/debugmethods.py \
 >  	gdb/command/frame_filters.py \
 >  	gdb/command/type_printers.py \
 >  	gdb/command/pretty_printers.py \
 > diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
 > index 035573e..e9ff30c 100644
 > --- a/gdb/doc/gdb.texinfo
 > +++ b/gdb/doc/gdb.texinfo
 > @@ -23662,6 +23662,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.
 > @@ -25694,6 +25697,255 @@ 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 method
 > +@kindex debug method
 > +
 > +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.

I would also add that debugmethods are usable on core files.
*And* when used on live programs they needn't involve running the inferior
and thus don't perturb inferior state.  Thus even if the C++ method
was available to GDB, I'd rather not use it if I don't have to.

 > +
 > +The debug methods feature in Python is available via the concepts of a
 > +@emph{debug method matcher} and a @emph{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_argtypes} method which

I guess I'm less anxious to rename debugmethods to debug_methods,
but what do you think of get_argtypes -> get_arg_types ?

 > +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 winning debug method worker.  A winner is
 > +also selected from among the 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.
 > +
 > +@xref{Debug Method API}, for API to implement debug methods in Python.
 > +@xref{Writing a Debug Method}, for implementing debug methods in Python.

I think(!) the commas should be removed from the previous two sentences.

 > +
 > +@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}.

Two spaces after period.

 > +
 > +A debug method matcher should be an instance of a class derived from
 > +@code{DebugMethodMatcher} defined in the module @code{gdb.debugmethods}.
 > +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.debugmethods}, 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 as represented by the
 > +string value @code{name}.

I think(!) this would read better as:
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)
 > +Creates an enabled debug method matcher with name as represented by the
 > +string value @code{name}.  The @code{methods} attribute is initialized
 > +to @code{None}.

Similarly:
Creates an enabled debug method matcher with name @var{name}.

 > +@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 @code{class_type} and @code{method_name}.
 > +@code{class_type} is a @code{gdb.Type} object, and @code{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 entry 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.debugmethods},
 > +or support the following interface:
 > +
 > +@defun DebugMethodWorker.get_argtypes(self)
 > +This method should return a sequence of 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.
 > +@end defun
 > +
 > +@defun DebugMethodWroker.invoke(self, obj, args)
 > +This is the method which does the @emph{work} of the debug method.
 > +@code{obj} is the object on which the method is being invoked, and
 > +@code{args} is the tuple of arguments to the method.

I would state that obj and args are objects of type gdb.Value.

 > +@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.debugmethods}:
 > +
 > +@defun register_debugmethod_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 a debug method
 > +
 > +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 sum (int b);
 > +
 > + private:
 > +  int a_;
 > +@};
 > +
 > +int
 > +MyClass::sum (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 the method @code{sum} which takes a @code{MyClass} argument.
 > +The debug method matcher can be defined as follows:
 > +
 > +@smallexample
 > +class MyClassMatcher(gdb.debugmethods.DebugMethodMatcher):
 > +    def __init__(self):
 > +        gdb.debugmethods.DebugMethodMatcher.__init__(self, 'MyMatcher')
 > +        # List of methods 'managed' by this matcher
 > +        self.methods = [gdb.debugmethods.DebugMethod('geta'),
 > +                        gdb.debugmethods.DebugMethod('sum')]
 > +
 > +    def match(self, class_type, method_name):
 > +        if class_type.tag != 'MyClass':
 > +            return

return None ?

 > +        if method_name == 'geta' and self.methods[0].enabled:
 > +            return MyClassWorker_geta()
 > +        elif method_name == 'sum' and self.methods[1].enabled:
 > +            return MyClassWorker_sum()
 > +        else:
 > +            return

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_sum} for the
 > +@code{sum} 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.debugmethods.DebugMethodWorker):
 > +    def get_argtypes(self):
 > +        return None
 > +
 > +    def invoke(self, obj, args):
 > +        return obj['a_']
 > +
 > +
 > +class MyClassWorker_sum(gdb.debugmethods.DebugMethodWorker):
 > +    def get_argtypes(self):
 > +        return gdb.lookup_type('MyClass')

Return a list/tuple?

 > +
 > +    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.  Let the matcher defined above be registered with
 > +@value{GDBN} globally as follows:

I think(!) this would read better as:
The matcher defined above is registered with @value{GDBN} globally as follows:

 > +
 > +@smallexample
 > +gdb.debugmethods.register_debugmethod_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 @code{geta} and @code{sum}
 > +methods on @code{obj} will invoke the debug methods defined above:
 > +@noindent
 > +
 > +@smallexample
 > +(gdb) p obj.geta()
 > +$1 = 5
 > +
 > +(gdb) p obj.sum(obj)
 > +$2 = 10
 > +@end smallexample
 > +
 >  @node Inferiors In Python
 >  @subsubsection Inferiors In Python
 >  @cindex inferiors in Python
 > diff --git a/gdb/eval.c b/gdb/eval.c
 > index cd0c20e..e72c77d 100644
 > --- a/gdb/eval.c
 > +++ b/gdb/eval.c
 > @@ -22,6 +22,7 @@
 >  #include "symtab.h"
 >  #include "gdbtypes.h"
 >  #include "value.h"
 > +#include "extension.h"
 >  #include "expression.h"
 >  #include "target.h"
 >  #include "frame.h"
 > @@ -1591,11 +1592,11 @@ evaluate_subexp_standard (struct type *expect_type,
 >            func_name = (char *) alloca (name_len + 1);
 >            strcpy (func_name, &exp->elts[string_pc + 1].string);
 >  
 > -          find_overload_match (&argvec[1], nargs, func_name,
 > -                               NON_METHOD, /* not method */
 > -                               NULL, NULL, /* pass NULL symbol since
 > +	  find_overload_match (&argvec[1], nargs, func_name,
 > +			       NON_METHOD, /* not method */
 > +			       NULL, NULL, /* pass NULL symbol since
 >  					      symbol is unknown */
 > -                               NULL, &symp, NULL, 0);
 > +			       NULL, &symp, NULL, NULL, 0);
 >  
 >            /* Now fix the expression being evaluated.  */
 >            exp->elts[save_pos1 + 2].symbol = symp;
 > @@ -1625,11 +1626,12 @@ evaluate_subexp_standard (struct type *expect_type,
 >  	      /* Language is C++, do some overload resolution before
 >  		 evaluation.  */
 >  	      struct value *valp = NULL;
 > +	      struct debug_method_worker *dm_worker = NULL;
 >  
 >  	      (void) find_overload_match (&argvec[1], nargs, tstr,
 > -	                                  METHOD, /* method */
 > +					  METHOD, /* method */
 >  					  &arg2,  /* the object */
 > -					  NULL, &valp, NULL,
 > +					  NULL, &valp, NULL, &dm_worker,
 >  					  &static_memfuncp, 0);
 >  
 >  	      if (op == OP_SCOPE && !static_memfuncp)
 > @@ -1639,9 +1641,23 @@ evaluate_subexp_standard (struct type *expect_type,
 >  			   "`this' pointer"),
 >  			 function_name);
 >  		}
 > -	      argvec[1] = arg2;	/* the ``this'' pointer */
 > -	      argvec[0] = valp;	/* Use the method found after overload
 > -				   resolution.  */
 > +
 > +	      /* If a method implemented in an extension language is the best
 > +		 match, then invoke it.  */
 > +	      if (dm_worker)
 > +		{
 > +		  struct value *ret_val;
 > +
 > +		  ret_val = invoke_debug_method (dm_worker, arg2, argvec + 2,
 > +						 nargs - 1);
 > +		  xfree (dm_worker);
 > +
 > +		  return ret_val;
 > +		}
 > +
 > +	      argvec[1] = arg2;     /* the ``this'' pointer */
 > +	      argvec[0] = valp;     /* Use the method found after overload
 > +				       resolution.  */

I often don't mind a little bit of whitespace cleanup in a patch.
But this one I'd like left alone, mostly because it crosses a threshold
(to me) of detracting from this particular change (which is to insert
the "if (dm_worker)" clause.

 >  	    }
 >  	  else
 >  	    /* Non-C++ case -- or no overload resolution.  */
 > @@ -1698,9 +1714,9 @@ evaluate_subexp_standard (struct type *expect_type,
 >  
 >  	      (void) find_overload_match (&argvec[1], nargs,
 >  					  NULL,        /* no need for name */
 > -	                                  NON_METHOD,  /* not method */
 > -	                                  NULL, function, /* the function */
 > -					  NULL, &symp, NULL, no_adl);
 > +					  NON_METHOD,  /* not method */
 > +					  NULL, function, /* the function */
 > +					  NULL, &symp, NULL, NULL, no_adl);
 >  
 >  	      if (op == OP_VAR_VALUE)
 >  		{
 > diff --git a/gdb/extension-priv.h b/gdb/extension-priv.h
 > index 9e63a9c..f3c8781 100644
 > --- a/gdb/extension-priv.h
 > +++ b/gdb/extension-priv.h
 > @@ -77,6 +77,10 @@ struct extension_language_defn
 >       or NULL if the support is not compiled into GDB.  */
 >    const struct extension_language_script_ops *script_ops;
 >  
 > +  /* A pointer to the "methods" to manipulate debug methods defined in this
 > +     language, or NULL if this language does not support debug methods.  */
 > +  const struct extension_language_debug_method_ops *dm_ops;
 > +

I'm not comfortable with having a separate dm_ops field here.
"Consistency Is Good" would then make me want to require separate ops vectors
for type-pretty-printers, etc. and that feels like too much at this point.

I recognize that maybe at some point extension_language_ops would become
too much of a kitchen sink, so the question is "Are we there yet?"
To me it feels early.

Thus can you move all of the extension_language_debug_method_ops members
into extension_language_ops?

 >    /* Either a pointer to the "methods" of the extension language interface
 >       or NULL if the support is not compiled into GDB.
 >       This is also NULL for GDB's own scripting language which is relatively
 > @@ -108,6 +112,53 @@ struct extension_language_script_ops
 >    int (*auto_load_enabled) (const struct extension_language_defn *);
 >  };
 >  
 > +/* Interface for manipulating debug methods defined in an extension langauge.
 > +   All the listed methods have to be implemented.  */
 > +
 > +struct extension_language_debug_method_ops
 > +{
 > +  /* Clone DATA and return a new but identical data object for this
 > +     extension language.  */
 > +  void * (*clone_debug_method_worker_data) (
 > +     const struct extension_language_defn *extlang, void *data);
 > +
 > +  /* Free the DATA object of this extension language.  */
 > +  void (*free_debug_method_worker_data) (
 > +     const struct extension_language_defn *extlang, void *data);
 > +
 > +  /* Return a vector of matching debug method workers defined in this
 > +     extension language.  The workers service methods with  name
 > +     METHOD_NAME on objects of type OBJ_TYPE.  The vector is returned
 > +     in DM_VEC.  */
 > +  enum ext_lang_rc (*get_matching_debug_method_workers) (
 > +     const struct extension_language_defn *extlang,
 > +     struct type *obj_type,
 > +     const char *method_name,
 > +     debug_method_worker_vec **dm_vec);
 > +
 > +  /* Given a WORKER servicing a particular method, return the types
 > +     of the arguments the method takes.  The number of arguments is
 > +     returned in NARGS, and their types are returned in the array
 > +     ARGTYPES.  */
 > +  enum ext_lang_rc (*get_debug_method_argtypes) (
 > +     const struct extension_language_defn *extlang,
 > +     struct debug_method_worker *worker,
 > +     int *nargs,
 > +     struct type ***argtypes);
 > +
 > +  /* Invoke the debug method serviced by WORKER.  The method is invoked
 > +     on OBJECT with arguments in the array ARGS.  NARGS is the length of
 > +     this array.  The value returned by the method is returned in
 > +     RESULT.  */
 > +  enum ext_lang_rc (*invoke_debug_method) (
 > +     const struct extension_language_defn *extlang,
 > +     struct debug_method_worker *worker,
 > +     struct value *object,
 > +     struct value **args,
 > +     int nargs,
 > +     struct value **result);
 > +};
 > +
 >  /* The interface for making calls from GDB to an external extension
 >     language.  This is for non-script-loading related functionality, like
 >     pretty-printing, etc.  The reason these are separated out is GDB's own
 > diff --git a/gdb/extension.c b/gdb/extension.c
 > index c2f502b..ddc9a6e 100644
 > --- a/gdb/extension.c
 > +++ b/gdb/extension.c
 > @@ -833,6 +833,153 @@ check_quit_flag (void)
 >    return result;
 >  }
 >  
 > +/* Debug method support
 > + */

Style issue.  "*/" never appears on a line by itself.

/* Debug method support.  */

 > +
 > +/* Returns a new debug_method_worker with EXTLANG and DATA.  */
 > +
 > +struct debug_method_worker *
 > +new_debug_method_worker (const struct extension_language_defn *extlang,
 > +			 void *data)

There is a convention that all ext lang API routines have "ext_lang" in the name.
It's not a hard and fast rule as there's, e.g., check_quit_flag (though
in this case check_quit_flag is more than just an ext lang API routine).
"debug_method" has a sufficient connotation to implicitly say
"I am implemented by an extension language" so I think the name is ok as is.
I'm just writing this down to point out that I did consider the issue.
However, I think for future readers it would be good to document
why things are the way they are.  Thus, at the start of this section,
right after "Debug method support.", can you add something like:

Debug method API routines do not have "ext_lang" in the name because
"debug_method" implicitly says "I am implemented by an extension language."
Plus some of the methods take a debug_method_foo * "self/this" arg,
not an extension_language_defn * arg.

 > +{
 > +  struct debug_method_worker *worker = XCNEW (struct debug_method_worker);
 > +
 > +  worker->extlang = extlang;
 > +  worker->data = data;
 > +
 > +  return worker;
 > +}
 > +
 > +/* Clones WORKER and returns a new but identical worker.  */

I think it would be useful to say where when this function is used.
I.e., why does this API routine exist?

 > +
 > +struct debug_method_worker *
 > +clone_debug_method_worker (struct debug_method_worker *worker)
 > +{
 > +  struct debug_method_worker *new_worker;
 > +  const struct extension_language_defn *extlang = worker->extlang;
 > +
 > +  new_worker = new_debug_method_worker (
 > +     extlang,
 > +     extlang->dm_ops->clone_debug_method_worker_data(extlang, worker->data));

I'm assuming you can only get here if the feature is implemented as
I see checks for a NULL method below.
It would be good to specify in the header that if the feature is implemented
then which (or all) methods must be implemented.
I would also add a call to gdb_assert here to make this explicit
to the reader (since I was expecting to see a check for NULL here,
and had to read ahead to see what's up).

Plus space after open paren.

 > +
 > +  return new_worker;
 > +}
 > +
 > +/* If a method with name METHOD_NAME is to be invoked on an object of type
 > +   TYPE, then all entension languages are searched for implementations of
 > +   methods with name METHOD in the extension languages.  All matches found are returned as

line too long
I think you can just delete "in the extension languages".

 > +   a vector 'struct ent_fn_descriptor' objects.  If no matching methods are

a vector of

 > +   found, NULL is returned.  */
 > +
 > +VEC (debug_method_worker_p) *
 > +get_matching_debug_method_workers (struct type *type, const char *method_name)
 > +{
 > +  VEC (debug_method_worker_p) *workers = NULL;
 > +  int i;
 > +  const struct extension_language_defn *extlang;
 > +
 > +  ALL_EXTENSION_LANGUAGES (i, extlang)
 > +    {
 > +      VEC (debug_method_worker_p) *lang_workers, *new_vec;
 > +      enum ext_lang_rc rc;
 > +
 > +      if (extlang->dm_ops == NULL)
 > +	continue;
 > +      gdb_assert (extlang->dm_ops->get_matching_debug_method_workers);
 > +
 > +      rc = extlang->dm_ops->get_matching_debug_method_workers (
 > +         extlang, type, method_name, &lang_workers);
 > +      if (rc == EXT_LANG_RC_ERROR)
 > +	{
 > +	  xfree (workers);

VEC_free?

 > +	  error (_("Error while looking for matching debug method workers "
 > +		   "defined in %s."), extlang->name);
 > +	}
 > +
 > +      new_vec = VEC_merge (debug_method_worker_p, workers, lang_workers);
 > +      /* Free only the vectors and not the elements as NEW_VEC still
 > +	 contains them.  */
 > +      VEC_free (debug_method_worker_p, workers);
 > +      VEC_free (debug_method_worker_p, lang_workers);
 > +      workers = new_vec;
 > +    }
 > +
 > +  return workers;
 > +}
 > +
 > +/* Return the arg types of the debug method encapsulated in WORKER.
 > +   An array of arg types is returned.  The length of the array is returned in
 > +   NARGS.  The type of the 'this' object is returned as the first element of
 > +   array.  */
 > +
 > +struct type **
 > +get_debug_method_argtypes (struct debug_method_worker *worker, int *nargs)

Repeating in case it was missed,
How about get_debug_method_arg_types ?
[btw, for brevity I won't always point out argtypes -> arg_types below]

 > +{
 > +  enum ext_lang_rc rc;
 > +  struct type **type_array = NULL;
 > +  const struct extension_language_defn *extlang = worker->extlang;
 > +
 > +  gdb_assert (worker->extlang->dm_ops->get_debug_method_argtypes);

Add != NULL.

 > +
 > +  rc = extlang->dm_ops->get_debug_method_argtypes (worker->extlang, worker,
 > +						   nargs, &type_array);
 > +  if (rc == EXT_LANG_RC_ERROR)
 > +    error (_("Error while looking for arg types of a debug method worker "
 > +	     "defined in %s."), extlang->name);

{ } around the call to error since it takes more than one line.

 > +
 > +  return type_array;
 > +}
 > +
 > +/* Invokes the debug method encapsulated in WORKER and returns the result.
 > +   The method is invoked on OBJ with arguments in the ARGS array.  NARGS is
 > +   the length of the this array.  */
 > +
 > +struct value *
 > +invoke_debug_method (struct debug_method_worker *worker, struct value *obj,
 > +		     struct value **args, int nargs)
 > +{
 > +  struct value *result = NULL;
 > +  enum ext_lang_rc rc;
 > +
 > +  gdb_assert (worker->extlang->dm_ops->invoke_debug_method);

Add != NULL.

 > +
 > +  rc = worker->extlang->dm_ops->invoke_debug_method (worker->extlang, worker,
 > +						     obj, args, nargs, &result);
 > +  if (rc == EXT_LANG_RC_ERROR)
 > +    error (_("Error while invoking a debug method defined in %s"),
 > +	   worker->extlang->name);

{ } around call to error.

 > +
 > +  return result;
 > +}
 > +
 > +/* Frees a vector of debug_method_workers VEC.  */
 > +
 > +static void
 > +free_debug_method_worker_vec (void *vec)
 > +{
 > +  int i;
 > +  struct debug_method_worker *worker;
 > +  VEC (debug_method_worker_p) *v = (VEC (debug_method_worker_p) *) vec;
 > +
 > +  for (i = 0; VEC_iterate (debug_method_worker_p, v, i, worker); i++)
 > +    {

Add assert that free_debug_method_worker_data != NULL.

 > +      worker->extlang->dm_ops->free_debug_method_worker_data (worker->extlang,
 > +							      worker->data);
 > +      xfree (worker);
 > +    }
 > +
 > +  VEC_free (debug_method_worker_p, v);
 > +}
 > +
 > +/* Return a cleanup object to free a vector VEC of extension function
 > +   descriptors.  */
 > +
 > +struct cleanup *
 > +make_debug_method_worker_vec_cleanup (VEC (debug_method_worker_p) *vec)
 > +{
 > +  return make_cleanup (free_debug_method_worker_vec, (void *) vec);
 > +}
 > +
 >  /* Called via an observer before gdb prints its prompt.
 >     Iterate over the extension languages giving them a chance to
 >     change the prompt.  The first one to change the prompt wins,
 > diff --git a/gdb/extension.h b/gdb/extension.h
 > index 61dc81b..589e653 100644
 > --- a/gdb/extension.h
 > +++ b/gdb/extension.h
 > @@ -21,6 +21,7 @@
 >  #define EXTENSION_H
 >  
 >  #include "mi/mi-cmds.h" /* For PRINT_NO_VALUES, etc.  */
 > +#include "common/vec.h"
 >  
 >  struct breakpoint;
 >  struct command_line;
 > @@ -33,6 +34,7 @@ struct ui_file;
 >  struct ui_out;
 >  struct value;
 >  struct value_print_options;
 > +struct debug_method_worker;
 >  
 >  /* A function to load and process a script file.
 >     The file has been opened and is ready to be read from the beginning.
 > @@ -138,6 +140,23 @@ struct ext_lang_type_printers
 >    /* Type-printers from Python.  */
 >    void *py_type_printers;
 >  };
 > +
 > +/* A type which holds its extension language specific debug method worker
 > +   data.  */
 > +
 > +struct debug_method_worker
 > +{
 > +  /* The language the debug method worker is implemented in.  */
 > +  const struct extension_language_defn *extlang;
 > +
 > +  /* The extension language specific data for this debug method worker.  */
 > +  void *data;
 > +};
 > +
 > +typedef struct debug_method_worker *debug_method_worker_p;

I realize DEF_VEC_P is spelled with "_P", but can you change
debug_method_worker_p to debug_method_worker_ptr?
"_p" is a common convention for denoting predicates (functions that return boolean values).

 > +DEF_VEC_P (debug_method_worker_p);
 > +typedef VEC (debug_method_worker_p) debug_method_worker_vec;
 > +
 >  
 >  /* The interface for gdb's own extension(/scripting) language.  */
 >  extern const struct extension_language_defn extension_language_gdb;
 > @@ -212,4 +231,23 @@ extern const struct extension_language_defn *get_breakpoint_cond_ext_lang
 >  
 >  extern int breakpoint_ext_lang_cond_says_stop (struct breakpoint *);
 >  
 > +extern struct value *invoke_debug_method (struct debug_method_worker *,
 > +					  struct value *,
 > +					  struct value **, int nargs);
 > +
 > +extern struct debug_method_worker *clone_debug_method_worker (
 > +   struct debug_method_worker *);
 > +
 > +extern struct debug_method_worker *new_debug_method_worker (
 > +   const struct extension_language_defn *extlang, void *data);
 > +
 > +extern debug_method_worker_vec *get_matching_debug_method_workers (
 > +   struct type *, const char *);
 > +
 > +extern struct type **get_debug_method_argtypes (
 > +   struct debug_method_worker *, int *);
 > +
 > +extern struct cleanup *make_debug_method_worker_vec_cleanup (
 > +   debug_method_worker_vec *vec);
 > +
 >  #endif /* EXTENSION_H */
 > diff --git a/gdb/guile/guile.c b/gdb/guile/guile.c
 > index b7134f7..dd2f434 100644
 > --- a/gdb/guile/guile.c
 > +++ b/gdb/guile/guile.c
 > @@ -78,6 +78,7 @@ const struct extension_language_defn extension_language_guile =
 >  
 >  #ifdef HAVE_GUILE
 >    &guile_extension_script_ops,
 > +  NULL,
 >    &guile_extension_ops
 >  #else
 >    NULL,
 > diff --git a/gdb/python/lib/gdb/__init__.py b/gdb/python/lib/gdb/__init__.py
 > index 95a76c2..76e35dc 100644
 > --- a/gdb/python/lib/gdb/__init__.py
 > +++ b/gdb/python/lib/gdb/__init__.py
 > @@ -67,6 +67,8 @@ pretty_printers = []
 >  
 >  # Initial type printers.
 >  type_printers = []
 > +# Initial debug_methods.
 > +debugmethod_matchers = []

Every now and then, e.g., when I read this, I *really* want it spelled debug_method.
Thoughts?

 >  # Initial frame filters.
 >  frame_filters = {}
 >  
 > diff --git a/gdb/python/lib/gdb/command/debugmethods.py b/gdb/python/lib/gdb/command/debugmethods.py
 > new file mode 100644
 > index 0000000..dafb79d
 > --- /dev/null
 > +++ b/gdb/python/lib/gdb/command/debugmethods.py
 > @@ -0,0 +1,256 @@
 > +# Debug method commands.
 > +# Copyright 2013-2014 Free Software Foundation, Inc.
 > +
 > +# This program is free software; you can redistribute it and/or modify
 > +# it under the terms of the GNU General Public License as published by
 > +# the Free Software Foundation; either version 3 of the License, or
 > +# (at your option) any later version.
 > +#
 > +# This program is distributed in the hope that it will be useful,
 > +# but WITHOUT ANY WARRANTY; without even the implied warranty of
 > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 > +# GNU General Public License for more details.
 > +#
 > +# You should have received a copy of the GNU General Public License
 > +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 > +
 > +import gdb
 > +import re
 > +
 > +"""GDB commands for working with debug-methods."""
 > +
 > +
 > +def validate_dm_regexp(part_name, regexp):
 > +  try:
 > +    return re.compile(regexp)
 > +  except SyntaxError:
 > +    raise SyntaxError("Invalid %s regexp: %s", part_name, regexp)

Indentation level should be 4.

 > +
 > +
 > +def parse_dm_command_args(arg):
 > +    """Parses the arguments passed to a debug method command.
 > +
 > +    Arguments:
 > +        arg: The argument string passed to a debug method command.
 > +
 > +    Returns:
 > +        A 2-tuple: (<locus matching regular expression>,
 > +                    <name matching regular expression>)

The code returns a 3-tuple.

 > +    """
 > +    argv = gdb.string_to_argv(arg)
 > +    argc = len(argv)
 > +    if argc > 2:
 > +        raise SyntaxError("Too many arguments to command.")
 > +    locus_regexp = ""
 > +    matcher_name_regexp = ""
 > +    dm_name_regexp = None
 > +    if argc >= 1:
 > +        locus_regexp = argv[0]
 > +    if argc == 2:
 > +        parts = argv[1].split(";", 1)
 > +        matcher_name_regexp = parts[0]
 > +        if len(parts) > 1:
 > +            dm_name_regexp = parts[1]
 > +    if dm_name_regexp:
 > +        name_re = validate_dm_regexp("debugmethod name", dm_name_regexp)

Here too.  "debug method name" ?

 > +    else:
 > +        name_re = None
 > +    return (validate_dm_regexp("locus", locus_regexp),
 > +            validate_dm_regexp("matcher name", matcher_name_regexp),
 > +            name_re)
 > +
 > +
 > +def get_global_method_matchers(locus_re, matcher_re):
 > +    """Returns a dict of matching globally registered debug methods.
 > +
 > +    Arguments:
 > +        locus_re: Even though only globally registered debug methods are
 > +                  looked up, they will be looked up only if 'global' matches
 > +                  LOCUS_RE.
 > +        name_re: The regular expression matching the names of debug methods.
 > +    Returns:
 > +        A dict of matching globally registered debug methods.  The only key in
 > +        the dict will be 'global'.
 > +    """
 > +    locus_str = "registered globally"
 > +    dm_dict = { locus_str: [] }
 > +    if locus_re.match("global"):
 > +        dm_dict[locus_str].extend(
 > +            [m for m in gdb.debugmethod_matchers if matcher_re.match(m.name)]
 > +        )
 > +    return dm_dict
 > +
 > +
 > +def get_method_matchers_in_loci(loci, locus_re, matcher_re):
 > +    """Returns a dict of macthing registered debug methods in the LOCI.
 > +
 > +    Arguments:
 > +        loci: The list of loci to lookup matching debug methods in.
 > +        locus_re: Debug methods will be looked up in a particular locus only
 > +                  if its filename matches the regular expression LOCUS_RE.
 > +        name_re: The regular expression to match the names of debug methods.
 > +
 > +    Returns:
 > +        A dict of matching debug methods.  The keys of the dict are the
 > +        filenames of the loci the debug methods belong to.
 > +    """
 > +    dm_dict = {}
 > +    for locus in loci:
 > +        if not locus_re.match(locus.filename):
 > +            continue
 > +        locus_type = "objfile"
 > +        if isinstance(locus, gdb.Progspace):
 > +            locus_type = "progspace"
 > +        locus_str = "registered with %s %s" % (locus_type, locus.filename)
 > +        dm_dict[locus_str] = [
 > +            m for m in locus.debugmethod_matchers if matcher_re.match(m.name)
 > +        ]
 > +    return dm_dict
 > +
 > +
 > +def print_dm_info(dm_dict, name_re):
 > +    """Print a dictionary of debug methods."""
 > +    if not dm_dict:
 > +        return
 > +    for locus_str in dm_dict:
 > +        if not dm_dict[locus_str]:
 > +            continue
 > +        print ("Debug methods %s:" % locus_str)

"Debug methods in %s:" ?

OTOH, it might be better to just print "Debug Methods" once at the top, before the for loop, and then just print each loci name.

 > +        for matcher in dm_dict[locus_str]:
 > +            print ("  %s" % matcher.name)
 > +            if not matcher.methods:
 > +                continue
 > +            for m in matcher.methods:
 > +                if name_re is None or name_re.match(m.name):
 > +                    print ("    %s" % m.name)
 > +            
 > +
 > +def set_dm_status1(dm_dict, name_re, status):
 > +    """Set the status (enabled/disabled) of a dictionary of debug methods."""
 > +    for locus_str, matchers in dm_dict.iteritems():
 > +        if not matchers:
 > +            continue
 > +        for matcher in matchers:
 > +            if not name_re:
 > +                matcher.enabled = status
 > +                continue
 > +            if not matcher.methods:
 > +                continue
 > +            for m in matcher.methods:
 > +                if name_re.match(m.name):
 > +                    m.enabled = status

btw, I'm not auditing everything for correctness in this pass.
E.g., the above function looks ok, but I'm not 100% positive.

 > +
 > +
 > +def set_dm_status(arg, status):
 > +    """Set the status (enabled/disabled) of debug methods matching ARG.
 > +    This is a helper function for enable/disable commands.  ARG is the
 > +    argument string passed to the commands.
 > +    """
 > +    locus_re, matcher_re, name_re = parse_dm_command_args(arg)
 > +    set_dm_status1(get_global_method_matchers(locus_re, matcher_re), name_re,
 > +                   status)
 > +    set_dm_status1(
 > +        get_method_matchers_in_loci(gdb.progspaces(), locus_re, matcher_re),
 > +        name_re,
 > +        status
 > +    )

These trailing parens on a line by themself doesn't feel right, style wise.
I couldn't find anything in pep008 that allows this.

 > +    set_dm_status1(
 > +        get_method_matchers_in_loci(gdb.objfiles(), locus_re, matcher_re),
 > +        name_re,
 > +        status
 > +    )
 > +
 > +
 > +class InfoDebugMethod(gdb.Command):
 > +    """GDB command to list registered debug method matchers.
 > +
 > +    Usage: info debugmethod [locus-regexp [name-regexp]]

Presenting "debugmethod" to the user instead of "debug-method" doesn't feel right.
[I feel more strongly about this than how it looks in the code.]

 > +
 > +    LOCUS-REGEXP is a regular expression matching the location of the debug
 > +    method matcherss.  If it is ommitted, all registered debug methods from all

matchers
omitted

 > +    loci are listed.  A locus could be 'global', a regular expression matching
 > +    filenames of program spaces, or a regular expression matching filenames of
 > +    objfiles.
 > +
 > +    NAME-REGEXP is a regular expression matching the names of debug method
 > +    matchers.  If this omitted for a specified locus, then all registered debug
 > +    methods in the locus are listed.  To list only a certain debug methods
 > +    managed by a single matcher, the name regexp can be specified as
 > +    matcher-name-regexp;debug-method-name-regexp.
 > +    """
 > +
 > +    def __init__(self):
 > +        super(InfoDebugMethod, self).__init__("info debugmethod",
 > +                                               gdb.COMMAND_DATA)
 > +
 > +    def invoke(self, arg, from_tty):
 > +        locus_re, matcher_re, name_re = parse_dm_command_args(arg)
 > +        print_dm_info(get_global_method_matchers(locus_re, matcher_re),
 > +                      name_re)
 > +        print_dm_info(
 > +            get_method_matchers_in_loci(
 > +                gdb.progspaces(), locus_re, matcher_re),
 > +            name_re
 > +        )

move parens on line by themself to preceding line

 > +        print_dm_info(
 > +            get_method_matchers_in_loci(gdb.objfiles(), locus_re, matcher_re),
 > +            name_re
 > +        )
 > +
 > +
 > +class EnableDebugMethod(gdb.Command):
 > +    """GDB command to enable a specified (group of) debug method(s).
 > +
 > +    Usage: enable debugmethod [locus-regexp [name-regexp]]

enable debug-method

 > +
 > +    LOCUS-REGEXP is a regular expression matching the location of the debug
 > +    methods.  If it is ommitted, all registered debug methods from all loci

omitted

 > +    are enabled.  A locus could be 'global', a regular expression matching
 > +    filenames of program spaces or a regular expression matching filenames of
 > +    objfiles.
 > +
 > +    NAME-REGEXP is a regular expression matching the names of debug methods
 > +    within a given locus.  If this omitted for a specified locus, then all
 > +    registered debug methods in the locus are enabled.
 > +    """
 > +
 > +    def __init__(self):
 > +        super(EnableDebugMethod, self).__init__("enable debugmethod",
 > +                                                gdb.COMMAND_DATA)
 > +
 > +    def invoke(self, arg, from_tty):
 > +        set_dm_status(arg, True)
 > +        
 > +
 > +class DisableDebugMethod(gdb.Command):
 > +    """GDB command to disable a specified (group of) debug method(s).
 > +
 > +    Usage: disable debugmethod [locus-regexp [name-regexp]]

disable debug-method

 > +
 > +    LOCUS-REGEXP is a regular expression matching the location of the debug
 > +    methods.  If it is ommitted, all registered debug methods from all loci

omitted

 > +    are disabled.  A locus could be 'global', a regular expression matching
 > +    filenames of program spaces or a regular expression matching filenames of
 > +    objfiles.
 > +
 > +    NAME-REGEXP is a regular expression matching the names of debug methods
 > +    within a given locus.  If this omitted for a specified locus, then all
 > +    registered debug methods in the locus are disabled.
 > +    """
 > +
 > +    def __init__(self):
 > +        super(DisableDebugMethod, self).__init__("disable debugmethod",
 > +                                                gdb.COMMAND_DATA)
 > +
 > +    def invoke(self, arg, from_tty):
 > +        set_dm_status(arg, False)
 > +        
 > +
 > +def register_debug_method_commands():
 > +    """Installs the debug method commands."""
 > +    InfoDebugMethod()
 > +    EnableDebugMethod()
 > +    DisableDebugMethod()
 > +
 > +
 > +register_debug_method_commands()
 > diff --git a/gdb/python/lib/gdb/debugmethods.py b/gdb/python/lib/gdb/debugmethods.py
 > new file mode 100644
 > index 0000000..a8b07e1
 > --- /dev/null
 > +++ b/gdb/python/lib/gdb/debugmethods.py
 > @@ -0,0 +1,236 @@
 > +# Python side of the support for debug methods.
 > +# Copyright (C) 2013-2014 Free Software Foundation, Inc.
 > +
 > +# This program is free software; you can redistribute it and/or modify
 > +# it under the terms of the GNU General Public License as published by
 > +# the Free Software Foundation; either version 3 of the License, or
 > +# (at your option) any later version.
 > +#
 > +# This program is distributed in the hope that it will be useful,
 > +# but WITHOUT ANY WARRANTY; without even the implied warranty of
 > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 > +# GNU General Public License for more details.
 > +#
 > +# You should have received a copy of the GNU General Public License
 > +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 > +
 > +"""Utilities for defining debug methods"""
 > +
 > +import gdb
 > +import re
 > +import sys

two blank lines after import list (I think)

 > +
 > +if sys.version_info[0] > 2:
 > +    # Python 3 removed basestring and long
 > +    basestring = str
 > +    long = int

two blank lines here
[and between all top level objects.  ref: pep008]

 > +
 > +class DebugMethod(object):
 > +    """Base class (or a prototype) for debug method description.
 > +
 > +    Currently, the description only requires only 'name' and 'enabled'
 > +    attributes.  Description objects are managed by 'DebugMethodMatcher'
 > +    objects (see below).
 > +
 > +    Attributes:
 > +        name: The name of the debug method.
 > +        enabled: A boolean indicating if the debug method is enabled.
 > +    """
 > +
 > +    def __init__(self, name):
 > +        self.name = name
 > +        self.enabled = True
 > +
 > +
 > +class DebugMethodMatcher(object):
 > +    """Abstract base class for matching a debug method.
 > +
 > +    When looking for debug methods, GDB invokes the `match' method of a
 > +    registered debug method matcher to match the object type and method name.
 > +    The `match' method in concrete classes derived from this class should
 > +    return a `DebugMethodWorker' object, or a list of `DebugMethodWorker'
 > +    objects if there is a match (see below for 'DebugMethodWorker' class).
 > +
 > +    Attributes:
 > +        name: The name of the matcher.
 > +        enabled: A boolean indicating if the matcher is enabled.
 > +        debug_methods: A sequence of objects of type 'DebugMethod', or objects
 > +            which have atleast the attribute of a 'DebugMethod' object.

at least the attributes

 > +            This list is used by the 'enable'/'disable'/'info' commands to
 > +            enable/disable/list the debug methods registered with GDB.  See
 > +            the 'match' method below to know how this sequence is to be used.

is used

 > +    """
 > +
 > +    def __init__(self, name):
 > +        """
 > +        Args:
 > +            name: An identifying name for the debug method or the group of
 > +                  debug methods returned by the `match' method.
 > +        """
 > +        self.name = name
 > +        self.enabled = True
 > +        self.methods = None
 > +
 > +    def match(self, class_type, method_name):
 > +        """Match class type and method name.
 > +
 > +        In derived classes, it should return a DebugMethodWorker object, or a
 > +        sequence of 'DebugMethodWorker' objects.  Only those debug method
 > +        workers whose corresponding 'DebugMethod' descriptor object is enabled
 > +        should be returned.
 > +
 > +        Args:
 > +            class_type: The class type (gdb.Type object) to match.
 > +            method_name: The name (string) of the method to match.
 > +        """
 > +        raise NotImplementedError("DebugMethodMatcher match")
 > +
 > +
 > +class DebugMethodWorker(object):
 > +    """Base class for all debug method workers defined in Python.
 > +
 > +    A debug method worker is an object which matches the method arguments, and
 > +    invokes the method when GDB wants it to.  Internally, GDB first invokes the
 > +    'get_argtypes' method to perform overload resolution.  If GDB selects to 
 > +    invoke this Python debug method, then it invokes it via the overridden
 > +    'invoke' method.
 > +
 > +    Derived classes should override the 'get_argtypes' and 'invoke' methods.
 > +    """
 > +
 > +    def get_argtypes(self):
 > +        """Return a sequence of gdb.Type objects corresponding to the arguments
 > +           of the debug method.
 > +        """
 > +        raise NotImplementedError("DebugMethod get_argtypes")
 > +
 > +    def invoke(self, obj, args):
 > +        """Invoke the debug method.
 > +
 > +        Args:
 > +            obj: The gdb.Value of the object on which the method is to be
 > +                 invoked.
 > +            args: The tuple of arguments to the method.

This should specify what the result is.

 > +        """
 > +        raise NotImplementedError("DebugMethod invoke")
 > +
 > +
 > +class SimpleDebugMethodMatcher(DebugMethodMatcher):

Multiline docstrings should have a one sentence summary followed
by a blank line.  ref: pep257

 > +    """This is a utility class which does name match by class name of the
 > +    objects on which the debug methods are defined.  For simple classes and
 > +    methods, one can choose to use this class.  For complex debug methods,
 > +    which need to replace/implement template source methods on possibly
 > +    template classes, one should implement their own debug method classes
 > +    deriving from the base class 'DebugMethod'.  See the py-debugmethods.py
 > +    in the testsuite/gdb.python directory of the GDB source tree for
 > +    examples.
 > +    """
 > +
 > +    class SimpleDebugMethodWorker(DebugMethodWorker):
 > +        def __init__(self, method_function, argtypes):
 > +            self._argtypes = argtypes
 > +            self._method_function = method_function
 > +
 > +        def get_argtypes(self):
 > +            return self._argtypes
 > +
 > +        def invoke(self, obj, args):
 > +            return self._method_function(obj, *args)
 > +
 > +
 > +    def __init__(self, name, class_matcher, method_matcher, method_function,
 > +                 *argtypes):
 > +        """
 > +        Args:
 > +            name: Name of the debug method matcher.
 > +            class_matcher: A regular expression used to match the name of the
 > +                class whose method this debug method is implementing/replacing.
 > +            method_matcher: A regular expression used to match the name of the
 > +                method this debug method is implementing/replacing.
 > +            method_function: A Python callable which would be called via the
 > +                invoke them of this class to actually invoke the debug method.
 > +                This callable should accept the object (*this) as the first
 > +                argument followed by the rest of the arguments to the method.
 > +            argtypes: The gdb.Type objects corresponding to the arguments that
 > +                this debug method takes.
 > +        """
 > +        DebugMethodMatcher.__init__(self, name)
 > +        assert callable(method_function), (
 > +            "The 'method_function' argument to 'SimpleDebugMethodMatcher' "
 > +            "__init__ method should be a callable.")
 > +        self._method_function = method_function
 > +        self._class_matcher = class_matcher
 > +        self._method_matcher = method_matcher
 > +        self._argtypes = argtypes
 > +
 > +    def match(self, class_type, method_name):
 > +        cm = re.match(self._class_matcher, str(class_type.unqualified().tag))
 > +        mm = re.match(self._method_matcher, method_name)
 > +        if cm and mm:
 > +            return SimpleDebugMethodMatcher.SimpleDebugMethodWorker(
 > +                self._method_function, self._argtypes)
 > +
 > +
 > +# A helper function for register_debugmethod_matcher which returns an error
 > +# object if MATCHER is not having the requisite attributes in the proper
 > +# format.
 > +def validate_debugmethod_matcher(matcher):
 > +    if not isinstance(matcher, DebugMethodMatcher):
 > +        return TypeError("Debug method matcher is not an instance of "
 > +                         "'DebugMethodMatcher'")
 > +    if not hasattr(matcher, "name"):
 > +        return TypeError("Debug method matcher is missing attribute: name")
 > +    if not hasattr(matcher, "enabled"):
 > +        return TypeError("Debug method matcher is missing attribute: enabled")
 > +    if not isinstance(matcher.name, basestring):
 > +        return TypeError("Attribute 'name' of debug method matcher is not a "
 > +                         "string")
 > +    if matcher.name.find(";") >= 0:
 > +        return ValueError("Debug method matcher name cannot contain ';' in it")
 > +
 > +
 > +# A helper function for register_debugmethod_matcher which looks up a debug
 > +# method matcher with NAME in LOCUS.  Returns the index of the debug method
 > +# matcher in 'debug_method_matchers' sequence attribute of the LOCUS.
 > +def lookup_debugmethod_matcher(locus, name):
 > +    i = 0
 > +    for m in locus.debugmethod_matchers:
 > +        if m.name == name:
 > +            return i
 > +        i = i + 1
 > +
 > +
 > +def register_debugmethod_matcher(locus, matcher, replace=False):
 > +    """Registers a debug method matcher MATCHER with a LOCUS.
 > +
 > +    Arguments:
 > +        locus: The locus in which the debug methods should be registered.  It
 > +               can be 'None' to indicate that the debug methods should be
 > +               registered globally. Or, it could be a gdb.Objfile or a
 > +               gdb.Progspace object in which the debug methods should be
 > +               registered.
 > +        matcher: The debug method matcher to register with the LOCUS.  It
 > +            should be an instance of 'DebugMethodMatcher' class.
 > +        replace: If True, replace any existing debug method matcher with the
 > +            same name in the locus.  Otherwise, if a matcher with the same name
 > +            exists in the locus, raise an exception.
 > +    """
 > +    err = validate_debugmethod_matcher(matcher)
 > +    if err:
 > +        raise err
 > +    if not locus:
 > +        locus = gdb
 > +    if locus == gdb:
 > +        locus_name = 'GDB globally'
 > +    else:
 > +        locus_name = locus.filename
 > +    index = lookup_debugmethod_matcher(locus, matcher.name)
 > +    if index:
 > +        if replace:
 > +            del locus.debugmethod_matchers[index]
 > +        else:
 > +            raise RuntimeError('Debug method matcher already registered with '
 > +                               '%s: %s' % (locus_name, new_method.name))
 > +    if gdb.parameter("verbose"):
 > +        gdb.write("Registering debug method matcher '%s' with %s' ...\n") 
 > +    locus.debugmethod_matchers.insert(0, matcher)
 > diff --git a/gdb/python/py-debugmethods.c b/gdb/python/py-debugmethods.c
 > new file mode 100644
 > index 0000000..e267564
 > --- /dev/null
 > +++ b/gdb/python/py-debugmethods.c
 > @@ -0,0 +1,695 @@
 > +/* Support for debug methods in Python.
 > +
 > +   Copyright (C) 2013-2014 Free Software Foundation, Inc.
 > +
 > +   This file is part of GDB.
 > +
 > +   This program is free software; you can redistribute it and/or modify
 > +   it under the terms of the GNU General Public License as published by
 > +   the Free Software Foundation; either version 3 of the License, or
 > +   (at your option) any later version.
 > +
 > +   This program is distributed in the hope that it will be useful,
 > +   but WITHOUT ANY WARRANTY; without even the implied warranty of
 > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 > +   GNU General Public License for more details.
 > +
 > +   You should have received a copy of the GNU General Public License
 > +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 > +
 > +#include "defs.h"
 > +#include "arch-utils.h"
 > +#include "extension.h"

Delete extension.h. extension-priv.h includes it.

 > +#include "extension-priv.h"
 > +#include "objfiles.h"
 > +#include "value.h"
 > +#include "language.h"
 > +
 > +#include "python.h"
 > +
 > +#ifdef HAVE_PYTHON

There's no longer a need for #ifdef HAVE_PYTHON.
At least there shouldn't be.

Well, it's the end of the day.
I better get this sent off.
I'll continue reviewing the rest tomorrow.

Thanks!

 > +#include "python-internal.h"
 > +
 > +static const char enabled_field_name[] = "enabled";
 > +static const char match_method_name[] = "match";
 > +static const char get_argtypes_method_name[] = "get_argtypes";
 > +static const char invoke_method_name[] = "invoke";
 > +static const char matchers_attr_str[] = "debugmethod_matchers";
 > +
 > +static PyObject *py_match_method_name = NULL;
 > +static PyObject *py_get_argtypes_method_name = NULL;
 > +static PyObject *py_invoke_method_name = NULL;
 > +
 > +struct gdbpy_worker_data
 > +{
 > +  PyObject *worker;
 > +  PyObject *this_type;
 > +};
 > +
 > +static struct debug_method_worker *new_python_debug_method_worker (
 > +   PyObject *item, PyObject *py_obj_type);
 > +
 > +/* Implementation of free_debug_method_worker_data for Python.  */
 > +
 > +static void
 > +gdbpy_free_debug_method_worker_data (
 > +   const struct extension_language_defn *extlang, void *data)
 > +{
 > +  struct gdbpy_worker_data *worker_data = data;
 > +
 > +  Py_XDECREF (worker_data->worker);
 > +  Py_XDECREF (worker_data->this_type);
 > +  xfree (worker_data);
 > +}
 > +
 > +/* Implementation of clone_debug_method_worker_data for Python.  */
 > +
 > +static void *
 > +gdbpy_clone_debug_method_worker_data (
 > +   const struct extension_language_defn *extlang, void *data)
 > +{
 > +  struct gdbpy_worker_data *worker_data = data, *new_data;
 > +
 > +  new_data = XCNEW (struct gdbpy_worker_data); 
 > +  new_data->worker = worker_data->worker;
 > +  new_data->this_type = worker_data->this_type;
 > +  Py_XINCREF (new_data->worker);
 > +  Py_XINCREF (new_data->this_type);
 > +
 > +  return new_data;
 > +}
 > +
 > +/* Invoke the "match" method of the MATCHER and return a new reference
 > +   to the result.  Returns NULL on error.  */
 > +
 > +static PyObject *
 > +invoke_match_method (PyObject *matcher, PyObject *py_obj_type,
 > +		     const char *debugmethod_name)
 > +{
 > +  PyObject *py_debugmethod_name;
 > +  PyObject *match_method, *enabled_field, *match_result;
 > +  struct cleanup *cleanups;
 > +  int enabled;
 > +
 > +  if (debugmethod_name == NULL)
 > +    return NULL;
 > +
 > +  cleanups = make_cleanup (null_cleanup, NULL);
 > +
 > +  enabled_field = PyObject_GetAttrString (matcher, enabled_field_name);
 > +  if (enabled_field == NULL)
 > +    {
 > +      do_cleanups (cleanups);
 > +
 > +      return NULL;
 > +    }
 > +  make_cleanup_py_decref (enabled_field);
 > +
 > +  enabled = PyObject_IsTrue (enabled_field);
 > +  if (enabled == -1)
 > +    {
 > +      do_cleanups (cleanups);
 > +
 > +      return NULL;
 > +    }
 > +  if (enabled == 0)
 > +    {
 > +      /* Return 'None' if the matcher is not enabled.  */
 > +      do_cleanups (cleanups);
 > +      Py_INCREF (Py_None);
 > +
 > +      return Py_None;
 > +    }
 > +
 > +  match_method = PyObject_GetAttrString (matcher, match_method_name);
 > +  if (match_method == NULL)
 > +    {
 > +      do_cleanups (cleanups);
 > +
 > +      return NULL;
 > +    }
 > +  make_cleanup_py_decref (match_method);
 > +  if (!PyCallable_Check (match_method))
 > +    {
 > +      warning (_("Attribute '%s' of a registered Python debug method matcher "
 > +		 "is not a callable."), match_method_name);
 > +      do_cleanups (cleanups);
 > +
 > +      return NULL;
 > +    }
 > +
 > +  py_debugmethod_name = PyString_FromString (debugmethod_name);
 > +  if (py_debugmethod_name == NULL)
 > +    {
 > +      do_cleanups (cleanups);
 > +
 > +      return NULL;
 > +    }
 > +  make_cleanup_py_decref (py_debugmethod_name);
 > +
 > +  match_result = PyObject_CallMethodObjArgs (matcher,
 > +					     py_match_method_name,
 > +					     py_obj_type,
 > +					     py_debugmethod_name,
 > +					     NULL);
 > +  if (match_result == NULL)
 > +    gdbpy_print_stack ();
 > +  do_cleanups (cleanups);
 > +
 > +  return match_result;
 > +}
 > +
 > +/* Implementation of get_matching_debug_method_workers for Python.  */
 > +
 > +static enum ext_lang_rc
 > +gdbpy_get_matching_debug_method_workers (
 > +   const struct extension_language_defn *extlang,
 > +   struct type *obj_type, const char *method_name,
 > +   debug_method_worker_vec **dm_vec)
 > +{
 > +  struct cleanup *cleanups;
 > +  struct objfile *objfile;
 > +  VEC (debug_method_worker_p) *worker_vec = NULL;
 > +  PyObject *py_type, *py_progspace;
 > +  PyObject *py_debugmethod_matcher_list = NULL, *list_iter, *matcher;
 > +
 > +  if (obj_type == NULL || method_name == NULL)
 > +    return EXT_LANG_RC_ERROR;
 > +
 > +  cleanups = ensure_python_env (get_current_arch (), current_language);
 > +
 > +  py_type = type_to_type_object (obj_type);
 > +  if (py_type == NULL)
 > +    {
 > +      gdbpy_print_stack ();
 > +      do_cleanups (cleanups);
 > +
 > +      return EXT_LANG_RC_ERROR;
 > +    }
 > +  make_cleanup_py_decref (py_type);
 > +
 > +  /* Create an empty list of debug methods.  */
 > +  py_debugmethod_matcher_list = PyList_New (0);
 > +  if (py_debugmethod_matcher_list == NULL)
 > +    {
 > +      gdbpy_print_stack ();
 > +      do_cleanups (cleanups);
 > +
 > +      return EXT_LANG_RC_ERROR;
 > +    }
 > +
 > +  /* Gather debug method matchers registered with the object files.  */
 > +  ALL_OBJFILES (objfile)
 > +    {
 > +      PyObject *py_objfile = objfile_to_objfile_object (objfile);
 > +      PyObject *objfile_matchers, *temp = py_debugmethod_matcher_list;
 > +
 > +      if (py_objfile == NULL)
 > +	{
 > +	  gdbpy_print_stack ();
 > +	  Py_DECREF (py_debugmethod_matcher_list);
 > +	  do_cleanups (cleanups);
 > +
 > +	  return EXT_LANG_RC_ERROR;
 > +	}
 > +
 > +      objfile_matchers = objfpy_get_debugmethod_matchers (py_objfile, NULL);
 > +      py_debugmethod_matcher_list = PySequence_Concat (temp,
 > +						       objfile_matchers);
 > +      Py_DECREF (temp);
 > +      Py_XDECREF (objfile_matchers);
 > +      if (py_debugmethod_matcher_list == NULL)
 > +	{
 > +	  gdbpy_print_stack ();
 > +	  do_cleanups (cleanups);
 > +
 > +	  return EXT_LANG_RC_ERROR;
 > +	}
 > +    }
 > +
 > +  /* Gather debug methods matchers registered with the current program
 > +     space.  */
 > +  py_progspace = pspace_to_pspace_object (current_program_space);
 > +  if (py_progspace != NULL)
 > +    {
 > +      PyObject *temp = py_debugmethod_matcher_list;
 > +      PyObject *pspace_matchers = pspy_get_debugmethod_matchers (py_progspace,
 > +								 NULL);
 > +
 > +      py_debugmethod_matcher_list = PySequence_Concat (temp, pspace_matchers);
 > +      Py_DECREF (temp);
 > +      Py_XDECREF (pspace_matchers);
 > +      if (py_debugmethod_matcher_list == NULL)
 > +	{
 > +	  gdbpy_print_stack ();
 > +	  do_cleanups (cleanups);
 > +
 > +	  return EXT_LANG_RC_ERROR;
 > +	}
 > +    }
 > +  else
 > +    {
 > +      gdbpy_print_stack ();
 > +      Py_DECREF (py_debugmethod_matcher_list);
 > +      do_cleanups (cleanups);
 > +
 > +      return EXT_LANG_RC_ERROR;
 > +    }
 > +
 > +  /* Gather debug method matchers registered globally.  */
 > +  if (gdb_python_module != NULL
 > +      && PyObject_HasAttrString (gdb_python_module, matchers_attr_str))
 > +    {
 > +      PyObject *gdb_matchers;
 > +      PyObject *temp = py_debugmethod_matcher_list;
 > +
 > +      gdb_matchers = PyObject_GetAttrString (gdb_python_module,
 > +					     matchers_attr_str);
 > +      if (gdb_matchers != NULL)
 > +	{
 > +	  py_debugmethod_matcher_list = PySequence_Concat (temp,
 > +							   gdb_matchers);
 > +	  Py_DECREF (temp);
 > +	  Py_DECREF (gdb_matchers);
 > +	  if (py_debugmethod_matcher_list == NULL)
 > +	    {
 > +	      gdbpy_print_stack ();
 > +	      do_cleanups (cleanups);
 > +
 > +	      return EXT_LANG_RC_ERROR;
 > +	    }
 > +	}
 > +      else
 > +	{
 > +	  gdbpy_print_stack ();
 > +	  Py_DECREF (py_debugmethod_matcher_list);
 > +	  do_cleanups (cleanups);
 > +
 > +	  return EXT_LANG_RC_ERROR;
 > +	}
 > +    }
 > +
 > +  /* Safe to make a cleanup for py_debugmethod_matcher_list now as it
 > +     will not change any more.  */
 > +  make_cleanup_py_decref (py_debugmethod_matcher_list);
 > +
 > +  list_iter = PyObject_GetIter (py_debugmethod_matcher_list);
 > +  if (list_iter == NULL)
 > +    {
 > +      gdbpy_print_stack ();
 > +      do_cleanups (cleanups);
 > +
 > +      return EXT_LANG_RC_ERROR;
 > +    }
 > +  while ((matcher = PyIter_Next (list_iter)))
 > +    {
 > +      PyObject *match_result = invoke_match_method (matcher, py_type,
 > +						    method_name);
 > +
 > +      if (match_result == NULL)
 > +	{
 > +	  gdbpy_print_stack ();
 > +	  Py_DECREF (matcher);
 > +	  do_cleanups (cleanups);
 > +
 > +	  return EXT_LANG_RC_ERROR;
 > +	}
 > +      if (match_result == Py_None)
 > +	; /* This means there was no match.  */
 > +      else if (PySequence_Check (match_result))
 > +	{
 > +	  PyObject *iter = PyObject_GetIter (match_result);
 > +	  PyObject *py_worker;
 > +
 > +	  if (iter == NULL)
 > +	    {
 > +	      gdbpy_print_stack ();
 > +	      Py_DECREF (matcher);
 > +	      Py_DECREF (match_result);
 > +	      do_cleanups (cleanups);
 > +
 > +	      return EXT_LANG_RC_ERROR;
 > +	    }
 > +	  while ((py_worker = PyIter_Next (iter)))
 > +	    {
 > +	      struct debug_method_worker *worker;
 > +
 > +	      worker = new_python_debug_method_worker (py_worker, py_type);
 > +	      VEC_safe_push (debug_method_worker_p, worker_vec, worker);
 > +	      Py_DECREF (worker);
 > +	    }
 > +	  Py_DECREF (iter);
 > +	  /* Report any error that could have occurred while iterating.  */
 > +	  if (PyErr_Occurred ())
 > +	    {
 > +	      gdbpy_print_stack ();
 > +	      Py_DECREF (matcher);
 > +	      Py_DECREF (match_result);
 > +	      do_cleanups (cleanups);
 > +
 > +	      return EXT_LANG_RC_ERROR;
 > +	    }
 > +	}
 > +      else
 > +	{
 > +	  struct debug_method_worker *worker;
 > +
 > +	  worker = new_python_debug_method_worker (match_result, py_type);
 > +	  VEC_safe_push (debug_method_worker_p, worker_vec, worker);
 > +	}
 > +
 > +      Py_XDECREF (match_result);
 > +      Py_DECREF (matcher);
 > +    }
 > +  Py_DECREF (list_iter);
 > +  /* Report any error that could have occurred while iterating.  */
 > +  if (PyErr_Occurred ())
 > +    {
 > +      gdbpy_print_stack ();
 > +      do_cleanups (cleanups);
 > +
 > +      return EXT_LANG_RC_ERROR;
 > +    }
 > +
 > +  do_cleanups (cleanups);
 > +  *dm_vec = worker_vec;
 > +
 > +  return EXT_LANG_RC_OK;
 > +}
 > +
 > +/* Implementation of get_debug_method_argtypes for Python.  */
 > +
 > +static enum ext_lang_rc
 > +gdbpy_get_debug_method_argtypes (
 > +   const struct extension_language_defn *extlang,
 > +   struct debug_method_worker *worker,
 > +   int *nargs,
 > +   struct type ***argtypes)
 > +{
 > +  struct gdbpy_worker_data *worker_data = worker->data;
 > +  PyObject *py_worker = worker_data->worker;
 > +  PyObject *get_argtypes_method;
 > +  PyObject *py_argtype_list, *list_iter = NULL, *item;
 > +  struct cleanup *cleanups;
 > +  struct type **type_array, *obj_type;
 > +  int i = 1, arg_count;
 > +
 > +  /* Set nargs to 0 so that any premature return from this function returns
 > +     0 arg types.  */
 > +  *nargs = 0;
 > +
 > +  cleanups = ensure_python_env (get_current_arch (), current_language);
 > +
 > +  get_argtypes_method =  PyObject_GetAttrString (py_worker,
 > +						 get_argtypes_method_name);
 > +  if (get_argtypes_method == NULL)
 > +    {
 > +      gdbpy_print_stack ();
 > +      do_cleanups (cleanups);
 > +
 > +      return EXT_LANG_RC_ERROR;
 > +    }
 > +  make_cleanup_py_decref (get_argtypes_method);
 > +
 > +  if (!PyCallable_Check (get_argtypes_method))
 > +    {
 > +      warning (_("Attribute '%s' of a registered Python debug method is not "
 > +		 "callable."), get_argtypes_method_name);
 > +      do_cleanups (cleanups);
 > +
 > +      return EXT_LANG_RC_ERROR;
 > +    }
 > +
 > +  py_argtype_list = PyObject_CallMethodObjArgs (py_worker,
 > +						py_get_argtypes_method_name,
 > +						NULL);
 > +  if (py_argtype_list == NULL)
 > +    {
 > +      gdbpy_print_stack ();
 > +      do_cleanups (cleanups);
 > +
 > +      return EXT_LANG_RC_ERROR;
 > +    }
 > +  make_cleanup_py_decref (py_argtype_list);
 > +  if (py_argtype_list == Py_None)
 > +    arg_count = 0;
 > +  else if (PySequence_Check (py_argtype_list))
 > +    {
 > +      arg_count = PySequence_Size (py_argtype_list);
 > +      if (arg_count == -1)
 > +	{
 > +	  gdbpy_print_stack ();
 > +	  do_cleanups (cleanups);
 > +
 > +	  return EXT_LANG_RC_ERROR;
 > +	}
 > +
 > +      list_iter = PyObject_GetIter (py_argtype_list);
 > +      if (list_iter == NULL)
 > +	{
 > +	  gdbpy_print_stack ();
 > +	  do_cleanups (cleanups);
 > +
 > +	  return EXT_LANG_RC_ERROR;
 > +	}
 > +      make_cleanup_py_decref (list_iter);
 > +    }
 > +  else
 > +    arg_count = 1;
 > +
 > +  /* Include the 'this' argument in the size.  */
 > +  type_array = XCNEWVEC (struct type *, arg_count + 1);
 > +  i = 1;
 > +  if (list_iter != NULL)
 > +    {
 > +      while ((item = PyIter_Next (list_iter)))
 > +	{
 > +	  struct type *arg_type = type_object_to_type (item);
 > +
 > +	  Py_DECREF (item);
 > +	  if (arg_type == NULL)
 > +	    {
 > +	      PyErr_SetString (PyExc_TypeError,
 > +			       _("Arg type returned by the get_argtypes method "
 > +				 "of a debug method worker object is not a "
 > +				 "gdb.Type object."));
 > +	      break;
 > +	    }
 > +
 > +	  type_array[i] = arg_type;
 > +	  i++;
 > +	}
 > +    }
 > +  else if (arg_count == 1)
 > +    {
 > +      /* py_argtype_list is not actually a list but a single gdb.Type
 > +	 object.  */
 > +      struct type *arg_type = type_object_to_type (py_argtype_list);
 > +
 > +      if (arg_type == NULL)
 > +	PyErr_SetString (PyExc_TypeError,
 > +			 _("Arg type returned by the get_argtypes method "
 > +			   "of a debug method worker object is not a gdb.Type "
 > +			   "object."));
 > +      else
 > +	{
 > +	  type_array[1] = arg_type;
 > +	  i++;
 > +	}
 > +    }
 > +  if (PyErr_Occurred ())
 > +    {
 > +      gdbpy_print_stack ();
 > +      do_cleanups (cleanups);
 > +      xfree (type_array);
 > +
 > +      return EXT_LANG_RC_ERROR;
 > +    }
 > +
 > +  /* Add the type of 'this' as the first argument.  */
 > +  obj_type = type_object_to_type (worker_data->this_type);
 > +  type_array[0] = make_cv_type (1, 0, lookup_pointer_type (obj_type), NULL);
 > +  *nargs = i;
 > +  *argtypes = type_array;
 > +  do_cleanups (cleanups);
 > +
 > +  return EXT_LANG_RC_OK;
 > +}
 > +
 > +/* Implementation of invoke_debug_method for Python.  */
 > +
 > +static enum ext_lang_rc
 > +gdbpy_invoke_debug_method (
 > +   const struct extension_language_defn *extlang,
 > +   struct debug_method_worker *worker,
 > +   struct value *obj, struct value **args, int nargs,
 > +   struct value **result)
 > +{
 > +  int i;
 > +  struct cleanup *cleanups;
 > +  PyObject *py_value_obj, *py_arg_tuple, *py_result;
 > +  PyObject *invoke_method;
 > +  struct type *obj_type, *this_type;
 > +  struct value *res = NULL;
 > +  struct gdbpy_worker_data *worker_data = worker->data;
 > +  PyObject *debugmethod_worker = worker_data->worker;
 > +
 > +  cleanups = ensure_python_env (get_current_arch (), current_language);
 > +
 > +  invoke_method =  PyObject_GetAttrString (debugmethod_worker,
 > +					   invoke_method_name);
 > +  if (invoke_method == NULL)
 > +    {
 > +      gdbpy_print_stack ();
 > +      do_cleanups (cleanups);
 > +
 > +      return EXT_LANG_RC_ERROR;
 > +    }
 > +  make_cleanup_py_decref (invoke_method);
 > +
 > +  if (!PyCallable_Check (invoke_method))
 > +    {
 > +      warning (_("Attribute '%s' of a registered Python debug method is not "
 > +		 "callable."), invoke_method_name);
 > +      do_cleanups (cleanups);
 > +
 > +      return EXT_LANG_RC_ERROR;
 > +    }
 > +
 > +  obj_type = check_typedef (value_type (obj));
 > +  this_type = check_typedef (type_object_to_type (worker_data->this_type));
 > +  if (TYPE_CODE (obj_type) == TYPE_CODE_PTR)
 > +    {
 > +      struct type *this_ptr = lookup_pointer_type (this_type);
 > +
 > +      if (!types_equal (obj_type, this_ptr))
 > +	obj = value_cast (this_ptr, obj);
 > +    }
 > +  else if (TYPE_CODE (obj_type) == TYPE_CODE_REF)
 > +    {
 > +      struct type *this_ref = lookup_reference_type (this_type);
 > +
 > +      if (!types_equal (obj_type, this_ref))
 > +	obj = value_cast (this_ref, obj);
 > +    }
 > +  else
 > +    {
 > +      if (!types_equal (obj_type, this_type))
 > +	obj = value_cast (this_type, obj);
 > +    }
 > +  py_value_obj = value_to_value_object (obj);
 > +  if (py_value_obj == NULL)
 > +    {
 > +      gdbpy_print_stack ();
 > +      do_cleanups (cleanups);
 > +
 > +      return EXT_LANG_RC_ERROR;
 > +    }
 > +  make_cleanup_py_decref (py_value_obj);
 > +
 > +  py_arg_tuple = PyTuple_New (nargs);
 > +  if (py_arg_tuple == NULL)
 > +    {
 > +      gdbpy_print_stack ();
 > +      do_cleanups (cleanups);
 > +
 > +      return EXT_LANG_RC_ERROR;
 > +    }
 > +  make_cleanup_py_decref (py_arg_tuple);
 > +
 > +  for (i = 0; i < nargs; i++)
 > +    {
 > +      PyObject *py_value_arg = value_to_value_object (args[i]);
 > +
 > +      if (py_value_arg == NULL)
 > +	{
 > +	  gdbpy_print_stack ();
 > +	  do_cleanups (cleanups);
 > +
 > +	  return EXT_LANG_RC_ERROR;
 > +	}
 > +
 > +      PyTuple_SET_ITEM (py_arg_tuple, i, py_value_arg);
 > +    }
 > +
 > +  py_result = PyObject_CallMethodObjArgs (debugmethod_worker,
 > +					  py_invoke_method_name,
 > +					  py_value_obj,
 > +					  py_arg_tuple, NULL);
 > +  if (py_result == NULL)
 > +    {
 > +      gdbpy_print_stack ();
 > +      do_cleanups (cleanups);
 > +
 > +      return EXT_LANG_RC_ERROR;
 > +    }
 > +  make_cleanup_py_decref (py_result);
 > +
 > +  /* Check that a debug method did not return None.  */
 > +  if (py_result != Py_None)
 > +    {
 > +      res = convert_value_from_python (py_result);
 > +      if (res == NULL)
 > +	{
 > +	  gdbpy_print_stack ();
 > +	  do_cleanups (cleanups);
 > +
 > +	  return EXT_LANG_RC_ERROR;
 > +	}
 > +    }
 > +  else
 > +    res = allocate_value (lookup_typename (python_language, python_gdbarch,
 > +					   "void", NULL, 0));
 > +
 > +  *result = res;
 > +  do_cleanups (cleanups);
 > +
 > +  return EXT_LANG_RC_OK;
 > +}
 > +
 > +/* v-table of extension_language_debug_method_ops for Python.  */
 > +
 > +struct extension_language_debug_method_ops python_debug_method_ops = {
 > +  gdbpy_clone_debug_method_worker_data,
 > +  gdbpy_free_debug_method_worker_data,
 > +  gdbpy_get_matching_debug_method_workers,
 > +  gdbpy_get_debug_method_argtypes,
 > +  gdbpy_invoke_debug_method
 > +};
 > +
 > +/* Creates a new Python debug_method_worker object.
 > +   The new object has data of type 'struct gdbpy_worker_data' composed
 > +   with the components PY_WORKER and THIS_TYPE.  */
 > +
 > +static struct debug_method_worker *
 > +new_python_debug_method_worker (PyObject *py_worker, PyObject *this_type)
 > +{
 > +  struct gdbpy_worker_data *data = XCNEW (struct gdbpy_worker_data);
 > +
 > +  data->worker = py_worker;
 > +  data->this_type = this_type;
 > +  Py_XINCREF (py_worker);
 > +  Py_XINCREF (this_type);
 > +
 > +  return new_debug_method_worker (&extension_language_python, data);
 > +}
 > +
 > +int
 > +gdbpy_initialize_debugmethods (void)
 > +{
 > +  py_match_method_name = PyString_FromString (match_method_name);
 > +  if (py_match_method_name == NULL)
 > +    return -1;
 > +
 > +  py_invoke_method_name = PyString_FromString (invoke_method_name);
 > +  if (py_invoke_method_name == NULL)
 > +    return -1;
 > +
 > +  py_get_argtypes_method_name = PyString_FromString (get_argtypes_method_name);
 > +  if (py_get_argtypes_method_name == NULL)
 > +    return -1;
 > +
 > +  return 1;
 > +}
 > +
 > +#endif /* HAVE_PYTHON */
 > diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
 > index 97fb0be..fd4254a 100644
 > --- a/gdb/python/py-objfile.c
 > +++ b/gdb/python/py-objfile.c
 > @@ -37,6 +37,9 @@ typedef struct
 >    PyObject *frame_filters;
 >    /* The type-printer list.  */
 >    PyObject *type_printers;
 > +
 > +  /* The debug method matcher list.  */
 > +  PyObject *debugmethod_matchers;
 >  } objfile_object;
 >  
 >  static PyTypeObject objfile_object_type
 > @@ -67,6 +70,7 @@ objfpy_dealloc (PyObject *o)
 >    Py_XDECREF (self->printers);
 >    Py_XDECREF (self->frame_filters);
 >    Py_XDECREF (self->type_printers);
 > +  Py_XDECREF (self->debugmethod_matchers);
 >    Py_TYPE (self)->tp_free (self);
 >  }
 >  
 > @@ -99,6 +103,13 @@ objfpy_new (PyTypeObject *type, PyObject *args, PyObject *keywords)
 >  	  Py_DECREF (self);
 >  	  return NULL;
 >  	}
 > +
 > +      self->debugmethod_matchers = PyList_New (0);
 > +      if (self->debugmethod_matchers == NULL)
 > +	{
 > +	  Py_DECREF (self);
 > +	  return NULL;
 > +	}
 >      }
 >    return (PyObject *) self;
 >  }
 > @@ -193,6 +204,17 @@ objfpy_get_type_printers (PyObject *o, void *ignore)
 >    return self->type_printers;
 >  }
 >  
 > +/* Get the 'debugmethod_matchers' attribute.  */
 > +
 > +PyObject *
 > +objfpy_get_debugmethod_matchers (PyObject *o, void *ignore)
 > +{
 > +  objfile_object *self = (objfile_object *) o;
 > +
 > +  Py_INCREF (self->debugmethod_matchers);
 > +  return self->debugmethod_matchers;
 > +}
 > +
 >  /* Set the 'type_printers' attribute.  */
 >  
 >  static int
 > @@ -292,6 +314,13 @@ objfile_to_objfile_object (struct objfile *objfile)
 >  	      return NULL;
 >  	    }
 >  
 > +	  object->debugmethod_matchers = PyList_New (0);
 > +	  if (object->debugmethod_matchers == NULL)
 > +	    {
 > +	      Py_DECREF (object);
 > +	      return NULL;
 > +	    }
 > +
 >  	  set_objfile_data (objfile, objfpy_objfile_data_key, object);
 >  	}
 >      }
 > @@ -333,6 +362,8 @@ static PyGetSetDef objfile_getset[] =
 >      objfpy_set_frame_filters, "Frame Filters.", NULL },
 >    { "type_printers", objfpy_get_type_printers, objfpy_set_type_printers,
 >      "Type printers.", NULL },
 > +  { "debugmethod_matchers", objfpy_get_debugmethod_matchers, NULL,
 > +    "Debug methods.", NULL },
 >    { NULL }
 >  };
 >  
 > diff --git a/gdb/python/py-progspace.c b/gdb/python/py-progspace.c
 > index cda5a86..c65d863 100644
 > --- a/gdb/python/py-progspace.c
 > +++ b/gdb/python/py-progspace.c
 > @@ -39,6 +39,9 @@ typedef struct
 >    PyObject *frame_filters;
 >    /* The type-printer list.  */
 >    PyObject *type_printers;
 > +
 > +  /* The debug method list.  */
 > +  PyObject *debugmethod_matchers;
 >  } pspace_object;
 >  
 >  static PyTypeObject pspace_object_type
 > @@ -75,6 +78,7 @@ pspy_dealloc (PyObject *self)
 >    Py_XDECREF (ps_self->printers);
 >    Py_XDECREF (ps_self->frame_filters);
 >    Py_XDECREF (ps_self->type_printers);
 > +  Py_XDECREF (ps_self->debugmethod_matchers);
 >    Py_TYPE (self)->tp_free (self);
 >  }
 >  
 > @@ -107,6 +111,13 @@ pspy_new (PyTypeObject *type, PyObject *args, PyObject *keywords)
 >  	  Py_DECREF (self);
 >  	  return NULL;
 >  	}
 > +
 > +      self->debugmethod_matchers = PyList_New (0);
 > +      if (self->debugmethod_matchers == NULL)
 > +	{
 > +	  Py_DECREF (self);
 > +	  return NULL;
 > +	}
 >      }
 >    return (PyObject *) self;
 >  }
 > @@ -201,6 +212,17 @@ pspy_get_type_printers (PyObject *o, void *ignore)
 >    return self->type_printers;
 >  }
 >  
 > +/* Get the 'debugmethod_matchers' attribute.  */
 > +
 > +PyObject *
 > +pspy_get_debugmethod_matchers (PyObject *o, void *ignore)
 > +{
 > +  pspace_object *self = (pspace_object *) o;
 > +
 > +  Py_INCREF (self->debugmethod_matchers);
 > +  return self->debugmethod_matchers;
 > +}
 > +
 >  /* Set the 'type_printers' attribute.  */
 >  
 >  static int
 > @@ -288,6 +310,13 @@ pspace_to_pspace_object (struct program_space *pspace)
 >  	      return NULL;
 >  	    }
 >  
 > +	  object->debugmethod_matchers = PyList_New (0);
 > +	  if (object->debugmethod_matchers == NULL)
 > +	    {
 > +	      Py_DECREF (object);
 > +	      return NULL;
 > +	    }
 > +
 >  	  set_program_space_data (pspace, pspy_pspace_data_key, object);
 >  	}
 >      }
 > @@ -320,6 +349,8 @@ static PyGetSetDef pspace_getset[] =
 >      "Frame filters.", NULL },
 >    { "type_printers", pspy_get_type_printers, pspy_set_type_printers,
 >      "Type printers.", NULL },
 > +  { "debugmethod_matchers", pspy_get_debugmethod_matchers, NULL,
 > +    "Debug methods.", NULL },
 >    { NULL }
 >  };
 >  
 > diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
 > index 07650f7..fe1f479 100644
 > --- a/gdb/python/python-internal.h
 > +++ b/gdb/python/python-internal.h
 > @@ -345,11 +345,13 @@ PyObject *pspace_to_pspace_object (struct program_space *)
 >      CPYCHECKER_RETURNS_BORROWED_REF;
 >  PyObject *pspy_get_printers (PyObject *, void *);
 >  PyObject *pspy_get_frame_filters (PyObject *, void *);
 > +PyObject *pspy_get_debugmethod_matchers (PyObject *, void *);
 >  
 >  PyObject *objfile_to_objfile_object (struct objfile *)
 >      CPYCHECKER_RETURNS_BORROWED_REF;
 >  PyObject *objfpy_get_printers (PyObject *, void *);
 >  PyObject *objfpy_get_frame_filters (PyObject *, void *);
 > +PyObject *objfpy_get_debugmethod_matchers (PyObject *, void *);
 >  
 >  PyObject *gdbarch_to_arch_object (struct gdbarch *gdbarch);
 >  
 > @@ -430,6 +432,8 @@ int gdbpy_initialize_new_objfile_event (void)
 >    CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
 >  int gdbpy_initialize_arch (void)
 >    CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
 > +int gdbpy_initialize_debugmethods (void)
 > +  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
 >  
 >  struct cleanup *make_cleanup_py_decref (PyObject *py);
 >  struct cleanup *make_cleanup_py_xdecref (PyObject *py);
 > diff --git a/gdb/python/python.c b/gdb/python/python.c
 > index cbfa73a..50e3020 100644
 > --- a/gdb/python/python.c
 > +++ b/gdb/python/python.c
 > @@ -60,6 +60,8 @@ static const char *gdbpy_should_print_stack = python_excp_message;
 >  /* Forward decls, these are defined later.  */
 >  static const struct extension_language_script_ops python_extension_script_ops;
 >  static const struct extension_language_ops python_extension_ops;
 > +/* This is defined in py-debugmethods.c.  */
 > +extern const struct extension_language_debug_method_ops python_debug_method_ops;
 >  #endif
 >  
 >  /* The main struct describing GDB's interface to the Python
 > @@ -77,6 +79,7 @@ const struct extension_language_defn extension_language_python =
 >  
 >  #ifdef HAVE_PYTHON
 >    &python_extension_script_ops,
 > +  &python_debug_method_ops,
 >    &python_extension_ops
 >  #else
 >    NULL,
 > @@ -1752,7 +1755,8 @@ message == an error message without a stack will be printed."),
 >        || gdbpy_initialize_exited_event () < 0
 >        || gdbpy_initialize_thread_event () < 0
 >        || gdbpy_initialize_new_objfile_event ()  < 0
 > -      || gdbpy_initialize_arch () < 0)
 > +      || gdbpy_initialize_arch () < 0
 > +      || gdbpy_initialize_debugmethods () < 0)
 >      goto fail;
 >  
 >    gdbpy_to_string_cst = PyString_FromString ("to_string");
 > diff --git a/gdb/testsuite/gdb.python/py-debugmethods.cc b/gdb/testsuite/gdb.python/py-debugmethods.cc
 > new file mode 100644
 > index 0000000..e71d5bc
 > --- /dev/null
 > +++ b/gdb/testsuite/gdb.python/py-debugmethods.cc
 > @@ -0,0 +1,192 @@
 > +/* This testcase is part of GDB, the GNU debugger.
 > +
 > +   Copyright 2014 Free Software Foundation, Inc.
 > +
 > +   This program is free software; you can redistribute it and/or modify
 > +   it under the terms of the GNU General Public License as published by
 > +   the Free Software Foundation; either version 3 of the License, or
 > +   (at your option) any later version.
 > +
 > +   This program is distributed in the hope that it will be useful,
 > +   but WITHOUT ANY WARRANTY; without even the implied warranty of
 > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 > +   GNU General Public License for more details.
 > +
 > +   You should have received a copy of the GNU General Public License
 > +   along with this program.  If not, see  <http://www.gnu.org/licenses/>.  */
 > +
 > +#include <iostream>
 > +
 > +using namespace std;
 > +
 > +namespace dop
 > +{
 > +
 > +class A
 > +{
 > + public:
 > +  int a;
 > +  int array [10];
 > +  virtual ~A ();
 > +  int operator+ (const A &obj);
 > +  virtual int operator- (const A &obj);
 > +  virtual int geta ();
 > +};
 > +
 > +A::~A () { }
 > +
 > +int
 > +A::operator+ (const A &obj)
 > +{
 > +  cout << "From CC <A_plus_A>:" << endl;
 > +  return a + obj.a;
 > +}
 > +
 > +int A::operator- (const A &obj)
 > +{
 > +  cout << "From CC <A_minus_A>:" << endl;
 > +  return a - obj.a;
 > +}
 > +
 > +int A::geta (void)
 > +{
 > +  cout << "From CC geta:" << endl;
 > +  return a;
 > +}
 > +
 > +class B : public A
 > +{
 > + public:
 > +  virtual int operator* (const B &obj);
 > +};
 > +
 > +int
 > +B::operator* (const B &obj)
 > +{
 > +  cout << "From CC <B_star_B>:" << endl;
 > +  return a * obj.a;
 > +}
 > +
 > +typedef B Bt;
 > +
 > +typedef Bt Btt;
 > +
 > +class C : public Bt
 > +{
 > + public:
 > +  virtual ~C();
 > +};
 > +
 > +C::~C () { }
 > +
 > +class D : public B
 > +{
 > + public:
 > +  /* This class overrides the virtual operator* defined in B.  The
 > +     associated Python script replaces B::operator* but not D::operator*.
 > +     Hence, if we have a reference pointing to an instance of D, the C++
 > +     version of D::operator* should be invoked and not the Python version
 > +     B::operator* even after loading the python script.  */
 > +  virtual int operator* (const B &obj);
 > +};
 > +
 > +int
 > +D::operator* (const B &obj)
 > +{
 > +  cout << "From CC <D_star_D>:" << endl;
 > +  return a * obj.a;
 > +}
 > +
 > +class E : public A
 > +{
 > + public:
 > +  /* This class has a member named 'a', while the base class also has a
 > +     member named 'a'.  When one invokes A::geta(), A::a should be
 > +     returned and not E::a as the 'geta' method is defined on class 'A'.
 > +     This class tests this aspect of debug methods.  */
 > +  int a;
 > +};
 > +
 > +template <typename T>
 > +class G
 > +{
 > + public:
 > +  template <typename T1>
 > +  int size_diff ();
 > +
 > +  template <int M>
 > +  int size_mul ();
 > +
 > +  template <typename T1>
 > +  T mul(const T1 t1);
 > +
 > + public:
 > +  T t;
 > +};
 > +
 > +template <typename T>
 > +template <typename T1>
 > +int
 > +G<T>::size_diff ()
 > +{
 > +  cout << "From CC G<>::size_diff:" << endl;
 > +  return sizeof (T1) - sizeof (T);
 > +}
 > +
 > +template <typename T>
 > +template <int M>
 > +int
 > +G<T>::size_mul ()
 > +{
 > +  cout << "From CC G<>::size_mul:" << endl;
 > +  return M * sizeof (T);
 > +}
 > +
 > +template <typename T>
 > +template <typename T1>
 > +T
 > +G<T>::mul (const T1 t1)
 > +{
 > +  cout << "From CC G<>::mul:" << endl;
 > +  return t1 * t;
 > +}
 > +
 > +}
 > +
 > +using namespace dop;
 > +
 > +int main(void)
 > +{
 > +  A a1, a2;
 > +  a1.a = 5;
 > +  a2.a = 10;
 > +  C c1;
 > +  c1.a = 20;
 > +  B b1;
 > +  b1.a = 30;
 > +  D d1;
 > +  d1.a = 50;
 > +  Bt bt;
 > +  bt.a = 40;
 > +  A &ref_c = c1;
 > +  B &ref_d = d1;
 > +  Btt btt;
 > +  btt.a = -5;
 > +  G<int> g, *g_ptr;
 > +  g.t = 5;
 > +  g_ptr = &g;
 > +  E e;
 > +  e.a = 1000;
 > +  e.A::a = 100;
 > +
 > +  int diff = g.size_diff<float> ();
 > +  int smul = g.size_mul<2> ();
 > +  int mul = g.mul (1.0);
 > +
 > +  for (int i = 0; i < 10; i++)
 > +    {
 > +      a1.array[i] = a2.array[i] = i;
 > +    }
 > +
 > +  return 0; /* Break here.  */ 
 > +}
 > diff --git a/gdb/testsuite/gdb.python/py-debugmethods.exp b/gdb/testsuite/gdb.python/py-debugmethods.exp
 > new file mode 100644
 > index 0000000..d54af6e
 > --- /dev/null
 > +++ b/gdb/testsuite/gdb.python/py-debugmethods.exp
 > @@ -0,0 +1,125 @@
 > +# Copyright 2014 Free Software Foundation, Inc.
 > +
 > +# This program is free software; you can redistribute it and/or modify
 > +# it under the terms of the GNU General Public License as published by
 > +# the Free Software Foundation; either version 3 of the License, or
 > +# (at your option) any later version.
 > +#
 > +# This program is distributed in the hope that it will be useful,
 > +# but WITHOUT ANY WARRANTY; without even the implied warranty of
 > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 > +# GNU General Public License for more details.
 > +#
 > +# You should have received a copy of the GNU General Public License
 > +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 > +
 > +# This file is part of the GDB testsuite.  It tests the debug methods
 > +# feature in the Python extension language.
 > +
 > +load_lib gdb-python.exp
 > +
 > +if { [skip_cplus_tests] } { continue }
 > +
 > +standard_testfile py-debugmethods.cc
 > +
 > +if {[prepare_for_testing $testfile.exp $testfile $srcfile {debug c++}]} {
 > +    return -1
 > +}
 > +
 > +# Skip all tests if Python scripting is not enabled.
 > +if { [skip_python_tests] } { continue }
 > +
 > +if ![runto_main] {
 > +   return -1
 > +}
 > +
 > +set debug_methods_script "${srcdir}/${subdir}/${testfile}.py"
 > +
 > +gdb_breakpoint [gdb_get_line_number "Break here."]
 > +gdb_continue_to_breakpoint "Break here" ".*Break here.*"
 > +
 > +# Tests before loading the debug methods.
 > +gdb_test "p a1 + a2" "From CC <A_plus_A>.*15" "Before: a1 + a2"
 > +gdb_test "p a2 - a1" "From CC <A_minus_A>.*5" "Before: a1 - a2"
 > +gdb_test "p b1 - a1" "From CC <A_minus_A>.*25" "Before: b1 - a1"
 > +gdb_test "p c1 - a1" "From CC <A_minus_A>.*15" "Before: c1 - a1"
 > +gdb_test "p c1 - c1" "From CC <A_minus_A>.*0" "Before: c1 - c1"
 > +gdb_test "p a1.geta()" "From CC geta.*5" "Before: a1.geta()"
 > +gdb_test "p ref_c - a1" "From CC <A_minus_A>.*15" "Before: ref_c - a1"
 > +gdb_test "p ref_c - c1" "From CC <A_minus_A>.*0" "Before: ref_c - c1"
 > +gdb_test "p b1 * b1" "From CC <B_star_B>.*900" "Before: b1 * b1"
 > +gdb_test "p ref_c * b1" "No symbol.*" "Before: ref_c * b1"
 > +gdb_test "p ref_d * b1" "From CC <D_star_D>.*1500" "Before: ref_d * b1"
 > +gdb_test "p bt * c1" "From CC <B_star_B>.*800" "Before: bt * c1"
 > +gdb_test "p ++a1" "No symbol.*" "Before: ++a1"
 > +gdb_test "p a1.getarrayind(5)" "Couldn't find method.*" \
 > +  "Before: a1.getarrayind(5)"
 > +gdb_test "p e.geta()" "From CC geta.*100" "Before: e.geta()"
 > +gdb_test "p g.size_diff<float>()" "From CC G<>::size_diff.*" \
 > +  "Before: g.size_diff<float>()"
 > +gdb_test "p g.size_diff<unsigned long>()" "Couldn't find method.*" \
 > +  "Before: g.size_diff<unsigned long>()"
 > +gdb_test "p g.size_mul<2>()" "From CC G<>::size_mul.*" \
 > +  "Before: g.size_mul<2>()"
 > +gdb_test "p g.size_mul<5>()" "Couldn't find method.*" \
 > +  "Before: g.size_mul<5>()"
 > +gdb_test "p g.mul<double>(2.0)" "From CC G<>::mul.*" \
 > +  "Before: g.mul<double>(2.0)"
 > +gdb_test "p g.mul<char>('a')" "Couldn't find method.*" \
 > +  "Before: g.mul<char>('a')"
 > +
 > +# Load the script which adds the debug methods.
 > +gdb_test_no_output "source ${debug_methods_script}" "load the script file"
 > +
 > +# Tests after loading debug methods.
 > +gdb_test "p a1 + a2" "From Python <A_plus_A>.*15" "After: a1 + a2"
 > +gdb_test "p a2 - a1" "From CC <A_minus_A>.*5" "After: a1 - a2"
 > +gdb_test "p b1 - a1" "From CC <A_minus_A>.*25" "After: b1 - a2"
 > +gdb_test "p c1 - a1" "From CC <A_minus_A>.*15" "After: c1 - a1"
 > +gdb_test "p c1 - c1" "From Python <C_minus_C>.*0" "After: c1 - c1"
 > +gdb_test "p a1.geta()" "From Python <A_geta>.*5" "After: a1.geta()"
 > +gdb_test "p ref_c - a1" "From CC <A_minus_A>.*15" "After: ref_c - a1"
 > +gdb_test "p ref_c - c1" "From Python <C_minus_C>.*0" "After: ref_c - c1"
 > +gdb_test "p b1 * b1" "From Python <B_star_B>.*900" "After: b1 * b1"
 > +gdb_test "p ref_c * b1" "No symbol.*" "After: ref_c * b1 failure"
 > +gdb_test "p ref_d * b1" "From CC <D_star_D>.*1500" "After: ref_d * b1"
 > +gdb_test "p bt * c1" "From Python <B_star_B>.*800" "After: bt * c1"
 > +gdb_test "p ++a1" "From Python <plus_plus_A>.*6" "After: ++a1"
 > +gdb_test "p a1.getarrayind(5)" "From Python <A_getarrayind>.*5" \
 > +  "After: a1.getarrayind(5)"
 > +gdb_test "p e.geta()" "From Python <A_geta>.*100" "After: e.geta()"
 > +gdb_test "p g.size_diff<float>  ()" "From Python G<>::size_diff.*" \
 > +  "After: g.size_diff<float>()"
 > +gdb_test "p g.size_diff<  unsigned long  >()" "From Python G<>::size_diff.*" \
 > +  "After: g.size_diff<unsigned long>()"
 > +gdb_test "p g.size_mul<2>()" "From Python G<>::size_mul.*" \
 > +  "After: g.size_mul<2>()"
 > +gdb_test "p g.size_mul<  5  >()" "From Python G<>::size_mul.*" \
 > +  "After: g.size_mul<  5  >()"
 > +gdb_test "p g.mul<double>(2.0)" "From Python G<>::mul.*" \
 > +  "After: g.mul<double>(2.0)"
 > +gdb_test "p g.mul<char>('a')" "From Python G<>::mul.*" \
 > +gdb_test "p g_ptr->mul<char>('a')" "From Python G<>::mul.*" \
 > +  "After: g->mul<char>('a')"
 > +
 > +# Tests for 'disable/enable debugmethod' command.
 > +gdb_test_no_output "disable debugmethod .*debugmethods G_methods" \
 > +  "Disable G_methods"
 > +gdb_test "p g.mul<char>('a')" "Couldn't find method.*" \
 > +  "g.mul<char>('a') after disabling G_methods"
 > +gdb_test_no_output "enable debugmethod .*debugmethods G_methods" \
 > +  "Enable G_methods"
 > +gdb_test "p g.mul<char>('a')" "From Python G<>::mul.*" \
 > +  "After enabling G_methods"
 > +gdb_test_no_output "disable debugmethod .*debugmethods G_methods;mul" \
 > +  "Disable G_methods;mul"
 > +gdb_test "p g.mul<char>('a')" "Couldn't find method.*" \
 > +  "g.mul<char>('a') after disabling G_methods;mul"
 > +gdb_test_no_output "enable debugmethod .*debugmethods G_methods;mul" \
 > +  "Enable G_methods;mul"
 > +gdb_test "p g.mul<char>('a')" "From Python G<>::mul.*" \
 > +  "After enabling G_methods;mul"
 > +
 > +# Test for 'info debug-methods' command
 > +gdb_test "info debugmethod global plus" "global.*plus_plus_A" \
 > +  "info debug-method global plus"
 > diff --git a/gdb/testsuite/gdb.python/py-debugmethods.py b/gdb/testsuite/gdb.python/py-debugmethods.py
 > new file mode 100644
 > index 0000000..2494914
 > --- /dev/null
 > +++ b/gdb/testsuite/gdb.python/py-debugmethods.py
 > @@ -0,0 +1,185 @@
 > +# Copyright 2014 Free Software Foundation, Inc.
 > +
 > +# This program is free software; you can redistribute it and/or modify
 > +# it under the terms of the GNU General Public License as published by
 > +# the Free Software Foundation; either version 3 of the License, or
 > +# (at your option) any later version.
 > +#
 > +# This program is distributed in the hope that it will be useful,
 > +# but WITHOUT ANY WARRANTY; without even the implied warranty of
 > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 > +# GNU General Public License for more details.
 > +#
 > +# You should have received a copy of the GNU General Public License
 > +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 > +
 > +# This file is part of the GDB testsuite.  It implements debug methods
 > +# in the Python extension language.
 > +
 > +import gdb
 > +import re
 > +
 > +from gdb.debugmethods import DebugMethod, DebugMethodMatcher, DebugMethodWorker
 > +from gdb.debugmethods import SimpleDebugMethodMatcher
 > +
 > +def A_plus_A(obj, opr):
 > +  print ('From Python <A_plus_A>:')
 > +  return obj['a'] + opr['a']
 > +
 > +def plus_plus_A(obj):
 > +  print ('From Python <plus_plus_A>:')
 > +  return obj['a'] + 1
 > +
 > +def C_minus_C(obj, opr):
 > +  # This function is not defined for objects of class C in the associated C++
 > +  # file.  However, C is derived from A which has a virtual operator- method.
 > +  # Hence, if an operator '-' is used on a reference pointing to 'C' after
 > +  # loading this script, then this Python version should be invoked.
 > +  print ('From Python <C_minus_C>:')
 > +  return obj['a'] - opr['a']
 > +
 > +def B_star_B(obj, opr):
 > +  print ('From Python <B_star_B>:')
 > +  return obj['a'] * opr['a']
 > +
 > +def A_geta(obj):
 > +  print ('From Python <A_geta>:')
 > +  return obj['a']
 > +
 > +def A_getarrayind(obj, index):
 > +  print 'From Python <A_getarrayind>:'
 > +  return obj['array'][index]
 > +
 > +
 > +type_A = gdb.parse_and_eval('(dop::A *) 0').type.target()
 > +type_B = gdb.parse_and_eval('(dop::B *) 0').type.target()
 > +type_C = gdb.parse_and_eval('(dop::C *) 0').type.target()
 > +type_int = gdb.parse_and_eval('(int *) 0').type.target()
 > +
 > +
 > +class G_size_diff_worker(DebugMethodWorker):
 > +    def __init__(self, class_template_type, method_template_type):
 > +        self._class_template_type = class_template_type
 > +        self._method_template_type = method_template_type
 > +
 > +    def get_argtypes(self):
 > +        pass
 > +
 > +    def invoke(self, obj, args):
 > +        print ('From Python G<>::size_diff()')
 > +        return (self._method_template_type.sizeof -
 > +                self._class_template_type.sizeof)
 > +
 > +
 > +class G_size_mul_worker(DebugMethodWorker):
 > +    def __init__(self, class_template_type, method_template_val):
 > +        self._class_template_type = class_template_type
 > +        self._method_template_val = method_template_val
 > +
 > +    def get_argtypes(self):
 > +        pass
 > +
 > +    def invoke(self, obj, args):
 > +        print ('From Python G<>::size_mul()')
 > +        return self._class_template_type.sizeof * self._method_template_val
 > +
 > +
 > +class G_mul_worker(DebugMethodWorker):
 > +    def __init__(self, class_template_type, method_template_type):
 > +        self._class_template_type = class_template_type
 > +        self._method_template_type = method_template_type
 > +
 > +    def get_argtypes(self):
 > +        return self._method_template_type
 > +
 > +    def invoke(self, obj, args):
 > +        print ('From Python G<>::mul()')
 > +        return obj['t'] * args[0]
 > +
 > +
 > +class G_methods_matcher(DebugMethodMatcher):
 > +    def __init__(self):
 > +        DebugMethodMatcher.__init__(self, 'G_methods')
 > +        self.methods = [DebugMethod('size_diff'),
 > +                        DebugMethod('size_mul'),
 > +                        DebugMethod('mul')]
 > +
 > +    def _is_enabled(self, name):
 > +        for method in self.methods:
 > +            if method.name == name and method.enabled:
 > +                return True
 > +
 > +    def match(self, class_type, method_name):
 > +        class_tag = class_type.unqualified().tag
 > +        if not re.match('^dop::G<[ ]*[_a-zA-Z][ _a-zA-Z0-9]*>$',
 > +                        class_tag):
 > +            return None
 > +        t_name = class_tag[7:-1]
 > +        try:
 > +            t_type = gdb.lookup_type(t_name)
 > +        except Exception:
 > +            return None
 > +        if re.match('^size_diff<[ ]*[_a-zA-Z][ _a-zA-Z0-9]*>$', method_name):
 > +            if not self._is_enabled('size_diff'):
 > +                return None
 > +            t1_name = method_name[10:-1]
 > +            try:
 > +                t1_type = gdb.lookup_type(t1_name)
 > +                return G_size_diff_worker(t_type, t1_type)
 > +            except Exception:
 > +                return None
 > +        if re.match('^size_mul<[ ]*[0-9]+[ ]*>$', method_name):
 > +            if not self._is_enabled('size_mul'):
 > +                return None
 > +            m_val = int(method_name[9:-1])
 > +            return G_size_mul_worker(t_type, m_val)
 > +        if re.match('^mul<[ ]*[_a-zA-Z][ _a-zA-Z0-9]*>$', method_name):
 > +            if not self._is_enabled('mul'):
 > +                return None
 > +            t1_name = method_name[4:-1]
 > +            try:
 > +                t1_type = gdb.lookup_type(t1_name)
 > +                return G_mul_worker(t_type, t1_type)
 > +            except Exception:
 > +                return None
 > +
 > +
 > +global_dm_list = [
 > +    SimpleDebugMethodMatcher('A_plus_A',
 > +                             '^dop::A$',
 > +                             'operator\+',
 > +                             A_plus_A,
 > +                             # This is a replacement, hence match the arg type
 > +                             # exactly!
 > +                             type_A.const().reference()),
 > +    SimpleDebugMethodMatcher('plus_plus_A',
 > +                             '^dop::A$',
 > +                             'operator\+\+',
 > +                             plus_plus_A),
 > +    SimpleDebugMethodMatcher('C_minus_C',
 > +                             '^dop::C$',
 > +                             'operator\-',
 > +                             C_minus_C,
 > +                             type_C),
 > +    SimpleDebugMethodMatcher('B_star_B',
 > +                             '^dop::B$',
 > +                             'operator\*',
 > +                             B_star_B,
 > +                             # This is a replacement, hence match the arg type
 > +                             # exactly!
 > +                             type_B.const().reference()),
 > +    SimpleDebugMethodMatcher('A_geta',
 > +                             '^dop::A$',
 > +                             '^geta$',
 > +                             A_geta),
 > +    SimpleDebugMethodMatcher('A_getarrayind',
 > +                             '^dop::A$',
 > +                             '^getarrayind$',
 > +                             A_getarrayind,
 > +                             type_int),
 > +]
 > +
 > +for matcher in global_dm_list:
 > +    gdb.debugmethods.register_debugmethod_matcher(gdb, matcher)
 > +gdb.debugmethods.register_debugmethod_matcher(gdb.current_progspace(),
 > +                                              G_methods_matcher())
 > diff --git a/gdb/valarith.c b/gdb/valarith.c
 > index 8e863e3..c39d88c 100644
 > --- a/gdb/valarith.c
 > +++ b/gdb/valarith.c
 > @@ -30,6 +30,7 @@
 >  #include <math.h>
 >  #include "infcall.h"
 >  #include "exceptions.h"
 > +#include "extension.h"
 >  
 >  /* Define whether or not the C operator '/' truncates towards zero for
 >     differently signed operands (truncation direction is undefined in C).  */
 > @@ -285,21 +286,27 @@ unop_user_defined_p (enum exp_opcode op, struct value *arg1)
 >     explicitly, and perform correct overload resolution in all of the above
 >     situations or combinations thereof.  */
 >  
 > -static struct value *
 > +static void
 >  value_user_defined_cpp_op (struct value **args, int nargs, char *operator,
 > -                           int *static_memfuncp)
 > +			   struct value **src_fn,
 > +			   struct debug_method_worker **dm_worker,
 > +			   int *static_memfuncp)
 >  {
 >  
 >    struct symbol *symp = NULL;
 >    struct value *valp = NULL;
 > +  struct debug_method_worker *worker = NULL;
 >  
 >    find_overload_match (args, nargs, operator, BOTH /* could be method */,
 > -                       &args[0] /* objp */,
 > -                       NULL /* pass NULL symbol since symbol is unknown */,
 > -                       &valp, &symp, static_memfuncp, 0);
 > +		       &args[0] /* objp */,
 > +		       NULL /* pass NULL symbol since symbol is unknown */,
 > +		       &valp, &symp, &worker, static_memfuncp, 0);
 >  
 >    if (valp)
 > -    return valp;
 > +    {
 > +      *src_fn = valp;
 > +      return;
 > +    }
 >  
 >    if (symp)
 >      {
 > @@ -307,7 +314,14 @@ value_user_defined_cpp_op (struct value **args, int nargs, char *operator,
 >           expect a reference as its first argument
 >           rather the explicit structure.  */
 >        args[0] = value_ind (args[0]);
 > -      return value_of_variable (symp, 0);
 > +      *src_fn = value_of_variable (symp, 0);
 > +      return;
 > +    }
 > +
 > +  if (worker)
 > +    {
 > +      *dm_worker = worker;
 > +      return;
 >      }
 >  
 >    error (_("Could not find %s."), operator);
 > @@ -316,19 +330,23 @@ value_user_defined_cpp_op (struct value **args, int nargs, char *operator,
 >  /* Lookup user defined operator NAME.  Return a value representing the
 >     function, otherwise return NULL.  */
 >  
 > -static struct value *
 > +static void
 >  value_user_defined_op (struct value **argp, struct value **args, char *name,
 > -                       int *static_memfuncp, int nargs)
 > +		       int *static_memfuncp, int nargs,
 > +		       struct value **src_fn,
 > +		       struct debug_method_worker **dm_worker)
 >  {
 >    struct value *result = NULL;
 >  
 >    if (current_language->la_language == language_cplus)
 > -    result = value_user_defined_cpp_op (args, nargs, name, static_memfuncp);
 > +    value_user_defined_cpp_op (args, nargs, name, src_fn, dm_worker,
 > +			       static_memfuncp);
 >    else
 > -    result = value_struct_elt (argp, args, name, static_memfuncp,
 > -                               "structure");
 > -
 > -  return result;
 > +    {
 > +      result = value_struct_elt (argp, args, name, static_memfuncp,
 > +				 "structure");
 > +      *src_fn = result;
 > +    }
 >  }
 >  
 >  /* We know either arg1 or arg2 is a structure, so try to find the right
 > @@ -345,6 +363,7 @@ value_x_binop (struct value *arg1, struct value *arg2, enum exp_opcode op,
 >  	       enum exp_opcode otherop, enum noside noside)
 >  {
 >    struct value **argvec;
 > +  struct debug_method_worker *dm_worker = NULL;
 >    char *ptr;
 >    char tstr[13];
 >    int static_memfuncp;
 > @@ -359,6 +378,7 @@ value_x_binop (struct value *arg1, struct value *arg2, enum exp_opcode op,
 >      error (_("Can't do that binary op on that type"));	/* FIXME be explicit */
 >  
 >    argvec = (struct value **) alloca (sizeof (struct value *) * 4);
 > +  argvec[0] = NULL;
 >    argvec[1] = value_addr (arg1);
 >    argvec[2] = arg2;
 >    argvec[3] = 0;
 > @@ -471,8 +491,8 @@ value_x_binop (struct value *arg1, struct value *arg2, enum exp_opcode op,
 >        error (_("Invalid binary operation specified."));
 >      }
 >  
 > -  argvec[0] = value_user_defined_op (&arg1, argvec + 1, tstr,
 > -                                     &static_memfuncp, 2);
 > +  value_user_defined_op (&arg1, argvec + 1, tstr, &static_memfuncp, 2,
 > +			 &argvec[0], &dm_worker);
 >  
 >    if (argvec[0])
 >      {
 > @@ -492,6 +512,14 @@ value_x_binop (struct value *arg1, struct value *arg2, enum exp_opcode op,
 >        return call_function_by_hand (argvec[0], 2 - static_memfuncp,
 >  				    argvec + 1);
 >      }
 > +  if (dm_worker)
 > +    {
 > +      struct value *ret_val = invoke_debug_method (dm_worker, arg1, &arg2, 1);
 > +
 > +      xfree (dm_worker);
 > +
 > +      return ret_val;
 > +    }
 >    throw_error (NOT_FOUND_ERROR,
 >                 _("member function %s not found"), tstr);
 >  #ifdef lint
 > @@ -510,6 +538,7 @@ value_x_unop (struct value *arg1, enum exp_opcode op, enum noside noside)
 >  {
 >    struct gdbarch *gdbarch = get_type_arch (value_type (arg1));
 >    struct value **argvec;
 > +  struct debug_method_worker *dm_worker;
 >    char *ptr;
 >    char tstr[13], mangle_tstr[13];
 >    int static_memfuncp, nargs;
 > @@ -523,6 +552,7 @@ value_x_unop (struct value *arg1, enum exp_opcode op, enum noside noside)
 >      error (_("Can't do that unary op on that type"));	/* FIXME be explicit */
 >  
 >    argvec = (struct value **) alloca (sizeof (struct value *) * 4);
 > +  argvec[0] = NULL;
 >    argvec[1] = value_addr (arg1);
 >    argvec[2] = 0;
 >  
 > @@ -574,8 +604,8 @@ value_x_unop (struct value *arg1, enum exp_opcode op, enum noside noside)
 >        error (_("Invalid unary operation specified."));
 >      }
 >  
 > -  argvec[0] = value_user_defined_op (&arg1, argvec + 1, tstr,
 > -                                     &static_memfuncp, nargs);
 > +  value_user_defined_op (&arg1, argvec + 1, tstr, &static_memfuncp, nargs,
 > +			 &argvec[0], &dm_worker);
 >  
 >    if (argvec[0])
 >      {
 > @@ -594,6 +624,14 @@ value_x_unop (struct value *arg1, enum exp_opcode op, enum noside noside)
 >  	  return value_zero (return_type, VALUE_LVAL (arg1));
 >  	}
 >        return call_function_by_hand (argvec[0], nargs, argvec + 1);
 > +    } 
 > +  if (dm_worker)
 > +    {
 > +      struct value *ret_val = invoke_debug_method (dm_worker, arg1, NULL, 0);
 > +
 > +      xfree (dm_worker);
 > +
 > +      return ret_val;
 >      }
 >    throw_error (NOT_FOUND_ERROR,
 >                 _("member function %s not found"), tstr);
 > diff --git a/gdb/valops.c b/gdb/valops.c
 > index 898401d..4feebd4 100644
 > --- a/gdb/valops.c
 > +++ b/gdb/valops.c
 > @@ -42,6 +42,7 @@
 >  #include "observer.h"
 >  #include "objfiles.h"
 >  #include "exceptions.h"
 > +#include "extension.h"
 >  
 >  extern unsigned int overload_debug;
 >  /* Local functions.  */
 > @@ -70,8 +71,8 @@ int find_oload_champ_namespace_loop (struct value **, int,
 >  				     const int no_adl);
 >  
 >  static int find_oload_champ (struct value **, int, int, int,
 > -			     struct fn_field *, struct symbol **,
 > -			     struct badness_vector **);
 > +			     struct fn_field *, VEC (debug_method_worker_p) *,
 > +			     struct symbol **, struct badness_vector **);
 >  
 >  static int oload_method_static (int, struct fn_field *, int);
 >  
 > @@ -98,9 +99,10 @@ static CORE_ADDR allocate_space_in_inferior (int);
 >  
 >  static struct value *cast_into_complex (struct type *, struct value *);
 >  
 > -static struct fn_field *find_method_list (struct value **, const char *,
 > -					  int, struct type *, int *,
 > -					  struct type **, int *);
 > +static void find_method_list (struct value **, const char *,
 > +			      int, struct type *, struct fn_field **, int *,
 > +			      VEC (debug_method_worker_p) **,
 > +			      struct type **, int *);
 >  
 >  void _initialize_valops (void);
 >  
 > @@ -2293,52 +2295,76 @@ value_struct_elt_bitpos (struct value **argp, int bitpos, struct type *ftype,
 >  
 >  /* Search through the methods of an object (and its bases) to find a
 >     specified method.  Return the pointer to the fn_field list of
 > -   overloaded instances.
 > +   overloaded instances defined in the source language.  If available
 > +   and matching, a vector matching/overloaded debug methods defined in
 > +   extension languages are also returned.
 >  
 >     Helper function for value_find_oload_list.
 >     ARGP is a pointer to a pointer to a value (the object).
 >     METHOD is a string containing the method name.
 >     OFFSET is the offset within the value.
 >     TYPE is the assumed type of the object.
 > +   FN_LIST The pointer to matching overloaded instances defined in
 > +      source language.
 >     NUM_FNS is the number of overloaded instances.
 > +   EXT_FN_VEC The vector matching debug methods defined in extension
 > +      languages.
 >     BASETYPE is set to the actual type of the subobject where the
 >        method is found.
 >     BOFFSET is the offset of the base subobject where the method is found.  */
 >  
 > -static struct fn_field *
 > +static void
 >  find_method_list (struct value **argp, const char *method,
 > -		  int offset, struct type *type, int *num_fns,
 > +		  int offset, struct type *type,
 > +		  struct fn_field **fn_list, int *num_fns,
 > +		  VEC (debug_method_worker_p) **dm_worker_vec,
 >  		  struct type **basetype, int *boffset)
 >  {
 >    int i;
 > -  struct fn_field *f;
 > -  CHECK_TYPEDEF (type);
 > +  struct fn_field *f = NULL;
 >  
 > -  *num_fns = 0;
 > +  CHECK_TYPEDEF (type);
 >  
 >    /* First check in object itself.  */
 > -  for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; i--)
 > -    {
 > -      /* pai: FIXME What about operators and type conversions?  */
 > -      const char *fn_field_name = TYPE_FN_FIELDLIST_NAME (type, i);
 >  
 > -      if (fn_field_name && (strcmp_iw (fn_field_name, method) == 0))
 > -	{
 > -	  int len = TYPE_FN_FIELDLIST_LENGTH (type, i);
 > -	  struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
 > +  if (fn_list && !(*fn_list))
 > +    for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; i--)
 > +      {
 > +	/* pai: FIXME What about operators and type conversions?  */
 > +	const char *fn_field_name = TYPE_FN_FIELDLIST_NAME (type, i);
 > +  
 > +	if (fn_field_name && (strcmp_iw (fn_field_name, method) == 0))
 > +  	{
 > +  	  int len = TYPE_FN_FIELDLIST_LENGTH (type, i);
 > +  	  f = TYPE_FN_FIELDLIST1 (type, i);
 > +	  *fn_list = f;
 > +  
 > +  	  *num_fns = len;
 > +  	  *basetype = type;
 > +  	  *boffset = offset;
 > +  
 > +  	  /* Resolve any stub methods.  */
 > +  	  check_stub_method_group (type, i);
 > +  
 > +	  break;
 > +  	}
 > +      }
 >  
 > -	  *num_fns = len;
 > -	  *basetype = type;
 > -	  *boffset = offset;
 > +  if (dm_worker_vec)
 > +    {
 > +      VEC (debug_method_worker_p) *worker_vec = NULL, *new_vec = NULL;
 >  
 > -	  /* Resolve any stub methods.  */
 > -	  check_stub_method_group (type, i);
 > +      worker_vec = get_matching_debug_method_workers (type, method);
 > +      new_vec = VEC_merge (debug_method_worker_p, *dm_worker_vec, worker_vec);
 >  
 > -	  return f;
 > -	}
 > +      VEC_free (debug_method_worker_p, *dm_worker_vec);
 > +      VEC_free (debug_method_worker_p, worker_vec);
 > +      *dm_worker_vec = new_vec;
 >      }
 >  
 > -  /* Not found in object, check in base subobjects.  */
 > +  /* If source methods are not found in current class, look for them in the
 > +     base classes.  We have to go through the base classes to gather extension
 > +     methods anyway.  */
 >    for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)
 >      {
 >        int base_offset;
 > @@ -2355,13 +2381,11 @@ find_method_list (struct value **argp, const char *method,
 >  	{
 >  	  base_offset = TYPE_BASECLASS_BITPOS (type, i) / 8;
 >  	}
 > -      f = find_method_list (argp, method, base_offset + offset,
 > -			    TYPE_BASECLASS (type, i), num_fns, 
 > -			    basetype, boffset);
 > -      if (f)
 > -	return f;
 > +      
 > +      find_method_list (argp, method, base_offset + offset,
 > +			TYPE_BASECLASS (type, i), fn_list, num_fns,
 > +			dm_worker_vec, basetype, boffset);
 >      }
 > -  return NULL;
 >  }
 >  
 >  /* Return the list of overloaded methods of a specified name.
 > @@ -2369,14 +2393,20 @@ find_method_list (struct value **argp, const char *method,
 >     ARGP is a pointer to a pointer to a value (the object).
 >     METHOD is the method name.
 >     OFFSET is the offset within the value contents.
 > +   FN_LIST The pointer to matching overloaded instances defined in
 > +      source language.
 >     NUM_FNS is the number of overloaded instances.
 > +   DM_WORKER_VEC The vector of matching debug method workers defined in
 > +      extension languages.
 >     BASETYPE is set to the type of the base subobject that defines the
 >        method.
 >     BOFFSET is the offset of the base subobject which defines the method.  */
 >  
 > -static struct fn_field *
 > +static void
 >  value_find_oload_method_list (struct value **argp, const char *method,
 > -			      int offset, int *num_fns, 
 > +                              int offset, struct fn_field **fn_list,
 > +                              int *num_fns,
 > +                              VEC (debug_method_worker_p) **dm_worker_vec,
 >  			      struct type **basetype, int *boffset)
 >  {
 >    struct type *t;
 > @@ -2398,8 +2428,34 @@ value_find_oload_method_list (struct value **argp, const char *method,
 >      error (_("Attempt to extract a component of a "
 >  	     "value that is not a struct or union"));
 >  
 > -  return find_method_list (argp, method, 0, t, num_fns, 
 > -			   basetype, boffset);
 > +  /* Clear the lists.  */
 > +  if (fn_list)
 > +    {
 > +      *fn_list = NULL;
 > +      *num_fns = 0;
 > +    }
 > +  if (dm_worker_vec)
 > +    *dm_worker_vec = VEC_alloc (debug_method_worker_p, 1);
 > +
 > +  find_method_list (argp, method, 0, t, fn_list, num_fns, dm_worker_vec,
 > +		    basetype, boffset);
 > +}
 > +
 > +/* Return the dynamic type of OBJ.  */
 > +
 > +static struct type *
 > +value_has_indirect_dynamic_type (struct value *obj)
 > +{
 > +  struct type *stype, *dtype, *dtype_ind;
 > +
 > +  stype = check_typedef (TYPE_TARGET_TYPE (value_type (obj)));
 > +  dtype_ind = value_rtti_indirect_type (obj, NULL, NULL, NULL);
 > +  dtype = dtype_ind ? check_typedef (TYPE_TARGET_TYPE (dtype_ind)) : stype;
 > +
 > +  if (class_types_same_p (stype, dtype))
 > +    return NULL;
 > +  else
 > +    return dtype_ind;
 >  }
 >  
 >  /* Given an array of arguments (ARGS) (which includes an
 > @@ -2427,9 +2483,11 @@ value_find_oload_method_list (struct value **argp, const char *method,
 >     Return value is an integer: 0 -> good match, 10 -> debugger applied
 >     non-standard coercions, 100 -> incompatible.
 >  
 > -   If a method is being searched for, VALP will hold the value.
 > -   If a non-method is being searched for, SYMP will hold the symbol 
 > -   for it.
 > +   If the best match is a debug function/method implemented in an extension
 > +   language, then EXT_FN will hold the matching function/method.  Otherwise,
 > +   VALP will hold the value if a method is being searched for, or SYMP will
 > +   hold the symbol for the matching function if a non-method is being
 > +   searched for.
 >  
 >     If a method is being searched for, and it is a static method,
 >     then STATICP will point to a non-zero value.
 > @@ -2447,6 +2505,7 @@ find_overload_match (struct value **args, int nargs,
 >  		     const char *name, enum oload_search_type method,
 >  		     struct value **objp, struct symbol *fsym,
 >  		     struct value **valp, struct symbol **symp, 
 > +		     struct debug_method_worker **dm_worker,
 >  		     int *staticp, const int no_adl)
 >  {
 >    struct value *obj = (objp ? *objp : NULL);
 > @@ -2454,16 +2513,24 @@ find_overload_match (struct value **args, int nargs,
 >    /* Index of best overloaded function.  */
 >    int func_oload_champ = -1;
 >    int method_oload_champ = -1;
 > +  int src_method_oload_champ = -1;
 > +  int src_method_oload_champ_bkp = -1;
 > +  int ext_method_oload_champ = -1;
 > +  int src_and_ext_equal = 0;
 >  
 >    /* The measure for the current best match.  */
 >    struct badness_vector *method_badness = NULL;
 >    struct badness_vector *func_badness = NULL;
 > +  struct badness_vector *ext_method_badness = NULL;
 > +  struct badness_vector *src_method_badness = NULL;
 >  
 >    struct value *temp = obj;
 >    /* For methods, the list of overloaded methods.  */
 >    struct fn_field *fns_ptr = NULL;
 >    /* For non-methods, the list of overloaded function symbols.  */
 >    struct symbol **oload_syms = NULL;
 > +  /* For extension functions, the VEC of extension function descriptors.  */
 > +  VEC (debug_method_worker_p) *dm_worker_vec = NULL;
 >    /* Number of overloaded instances being considered.  */
 >    int num_fns = 0;
 >    struct type *basetype = NULL;
 > @@ -2475,6 +2542,8 @@ find_overload_match (struct value **args, int nargs,
 >    const char *func_name = NULL;
 >    enum oload_classification match_quality;
 >    enum oload_classification method_match_quality = INCOMPATIBLE;
 > +  enum oload_classification src_method_match_quality = INCOMPATIBLE;
 > +  enum oload_classification ext_method_match_quality = INCOMPATIBLE;
 >    enum oload_classification func_match_quality = INCOMPATIBLE;
 >  
 >    /* Get the list of overloaded methods or functions.  */
 > @@ -2503,12 +2572,12 @@ find_overload_match (struct value **args, int nargs,
 >  	}
 >  
 >        /* Retrieve the list of methods with the name NAME.  */
 > -      fns_ptr = value_find_oload_method_list (&temp, name, 
 > -					      0, &num_fns, 
 > -					      &basetype, &boffset);
 > +      value_find_oload_method_list (&temp, name, 0, &fns_ptr, &num_fns,
 > +				    dm_worker ? &dm_worker_vec : NULL,
 > +				    &basetype, &boffset);
 >        /* If this is a method only search, and no methods were found
 >           the search has faild.  */
 > -      if (method == METHOD && (!fns_ptr || !num_fns))
 > +      if (method == METHOD && (!fns_ptr || !num_fns) && !dm_worker_vec)
 >  	error (_("Couldn't find method %s%s%s"),
 >  	       obj_type_name,
 >  	       (obj_type_name && *obj_type_name) ? "::" : "",
 > @@ -2519,18 +2588,82 @@ find_overload_match (struct value **args, int nargs,
 >        if (fns_ptr)
 >  	{
 >  	  gdb_assert (TYPE_DOMAIN_TYPE (fns_ptr[0].type) != NULL);
 > -	  method_oload_champ = find_oload_champ (args, nargs, method,
 > -	                                         num_fns, fns_ptr,
 > -	                                         oload_syms, &method_badness);
 > -
 > -	  method_match_quality =
 > -	      classify_oload_match (method_badness, nargs,
 > -	                            oload_method_static (method, fns_ptr,
 > -	                                                 method_oload_champ));
 > +	  src_method_oload_champ = find_oload_champ (args, nargs, method,
 > +						     num_fns, fns_ptr, NULL,
 > +						     oload_syms,
 > +						     &src_method_badness);
 > +
 > +	  src_method_match_quality =
 > +	      classify_oload_match (
 > +		  src_method_badness, nargs,
 > +		  oload_method_static (method, fns_ptr,
 > +				       src_method_oload_champ));
 > +
 > +	  make_cleanup (xfree, src_method_badness);
 > +	}
 >  
 > -	  make_cleanup (xfree, method_badness);
 > +      if (dm_worker && VEC_length (debug_method_worker_p, dm_worker_vec))
 > +	{
 > +	  ext_method_oload_champ = find_oload_champ (args, nargs, method,
 > +						     0, NULL, dm_worker_vec,
 > +						     NULL, &ext_method_badness);
 > +	  ext_method_match_quality = classify_oload_match (ext_method_badness,
 > +							   nargs, 0);
 > +	  make_cleanup (xfree, ext_method_badness);
 > +	  make_debug_method_worker_vec_cleanup (dm_worker_vec);
 >  	}
 >  
 > +      if (src_method_oload_champ >= 0 && ext_method_oload_champ >= 0)
 > +	{
 > +	  switch (compare_badness (ext_method_badness, src_method_badness))
 > +	    {
 > +	      case 0: /* Src method and ext method are equally good.  */
 > +		src_and_ext_equal = 1;
 > +	      case 1: /* Src method and ext method are incompatible  */
 > +		/* if ext method match is not standard, then let source method
 > +		   win.  */
 > +		if (ext_method_match_quality != STANDARD)
 > +		  {
 > +		    method_oload_champ = src_method_oload_champ;
 > +		    method_badness = src_method_badness;
 > +		    ext_method_oload_champ = -1;
 > +		    method_match_quality = src_method_match_quality;
 > +		    break;
 > +		  }
 > +	      case 2: /* Ext method is champion.  */
 > +		method_oload_champ = ext_method_oload_champ;
 > +		method_badness = ext_method_badness;
 > +		src_method_oload_champ_bkp = src_method_oload_champ;
 > +		src_method_oload_champ = -1;
 > +		method_match_quality = ext_method_match_quality;
 > +		break;
 > +	      case 3: /* Src method is champion.  */
 > +		method_oload_champ = src_method_oload_champ;
 > +		method_badness = src_method_badness;
 > +		ext_method_oload_champ = -1;
 > +		method_match_quality = src_method_match_quality;
 > +		break;
 > +	      default:
 > +		error (_("Internal error: unexpected overload comparison "
 > +			 "result"));
 > +		break;
 > +	    }
 > +	}
 > +      else
 > +	{
 > +	  if (src_method_oload_champ >= 0)
 > +	    {
 > +	      method_oload_champ = src_method_oload_champ;
 > +	      method_badness = src_method_badness;
 > +	      method_match_quality = src_method_match_quality;
 > +	    }
 > +	  if (ext_method_oload_champ >= 0)
 > +	    {
 > +	      method_oload_champ = ext_method_oload_champ;
 > +	      method_badness = ext_method_badness;
 > +	      method_match_quality = ext_method_match_quality;
 > +	    }
 > +	}
 >      }
 >  
 >    if (method == NON_METHOD || method == BOTH)
 > @@ -2673,21 +2806,6 @@ find_overload_match (struct value **args, int nargs,
 >  		 func_name);
 >      }
 >  
 > -  if (staticp != NULL)
 > -    *staticp = oload_method_static (method, fns_ptr, method_oload_champ);
 > -
 > -  if (method_oload_champ >= 0)
 > -    {
 > -      if (TYPE_FN_FIELD_VIRTUAL_P (fns_ptr, method_oload_champ))
 > -	*valp = value_virtual_fn_field (&temp, fns_ptr, method_oload_champ,
 > -					basetype, boffset);
 > -      else
 > -	*valp = value_fn_field (&temp, fns_ptr, method_oload_champ,
 > -				basetype, boffset);
 > -    }
 > -  else
 > -    *symp = oload_syms[func_oload_champ];
 > -
 >    if (objp)
 >      {
 >        struct type *temp_type = check_typedef (value_type (temp));
 > @@ -2697,10 +2815,66 @@ find_overload_match (struct value **args, int nargs,
 >  	  && (TYPE_CODE (objtype) == TYPE_CODE_PTR
 >  	      || TYPE_CODE (objtype) == TYPE_CODE_REF))
 >  	{
 > -	  temp = value_addr (temp);
 > +	  *objp = value_addr (temp);
 > +	}
 > +      else
 > +	*objp = temp;
 > +    }
 > +
 > +  if (staticp != NULL)
 > +    *staticp = oload_method_static (method, fns_ptr, method_oload_champ);
 > +
 > +  if (method_oload_champ >= 0)
 > +    {
 > +      if (src_method_oload_champ >= 0)
 > +	{
 > +	  if (TYPE_FN_FIELD_VIRTUAL_P (fns_ptr, method_oload_champ))
 > +	    {
 > +	      struct type *dtype;
 > +      
 > +	      dtype = value_has_indirect_dynamic_type (args[0]);
 > +	      if (dtype)
 > +		{
 > +		  args[0] = value_cast (dtype, args[0]);
 > +		  do_cleanups (all_cleanups);
 > +		  return find_overload_match (args, nargs, name, method,
 > +					      objp, fsym, valp, symp, dm_worker,
 > +					      staticp, no_adl);
 > +		}
 > +	      else
 > +		*valp = value_virtual_fn_field (&temp, fns_ptr,
 > +						method_oload_champ,
 > +						basetype, boffset);
 > +	    }
 > +	  else
 > +	    *valp = value_fn_field (&temp, fns_ptr, method_oload_champ,
 > +				    basetype, boffset);
 > +	}
 > +      else
 > +	{
 > +	  if (src_and_ext_equal 
 > +	      && TYPE_FN_FIELD_VIRTUAL_P (fns_ptr, src_method_oload_champ_bkp))
 > +	    {
 > +	      struct type *dtype;
 > +      
 > +	      dtype = value_has_indirect_dynamic_type (args[0]);
 > +	      if (dtype)
 > +		{
 > +		  args[0] = value_cast (dtype, args[0]);
 > +		  do_cleanups (all_cleanups);
 > +		  return find_overload_match (args, nargs, name, method,
 > +					      objp, fsym, valp, symp, dm_worker,
 > +					      staticp, no_adl);
 > +		}
 > +	    }
 > +
 > +	  *dm_worker = clone_debug_method_worker (
 > +	     VEC_index (debug_method_worker_p, dm_worker_vec,
 > +			ext_method_oload_champ));
 >  	}
 > -      *objp = temp;
 >      }
 > +  else
 > +    *symp = oload_syms[func_oload_champ];
 >  
 >    do_cleanups (all_cleanups);
 >  
 > @@ -2835,7 +3009,7 @@ find_oload_champ_namespace_loop (struct value **args, int nargs,
 >      ++num_fns;
 >  
 >    new_oload_champ = find_oload_champ (args, nargs, 0, num_fns,
 > -				      NULL, new_oload_syms,
 > +				      NULL, NULL, new_oload_syms,
 >  				      &new_oload_champ_bv);
 >  
 >    /* Case 1: We found a good match.  Free earlier matches (if any),
 > @@ -2873,7 +3047,9 @@ find_oload_champ_namespace_loop (struct value **args, int nargs,
 >  
 >  /* Look for a function to take NARGS args of ARGS.  Find
 >     the best match from among the overloaded methods or functions
 > -   (depending on METHOD) given by FNS_PTR or OLOAD_SYMS, respectively.
 > +   given by FNS_PTR or OLOAD_SYMS or DM_WORKER_VEC, respectively.  If
 > +   DM_WORKER_VEC is NULL, then METHOD indicates whether to use FNS_PTR
 > +   or OLOAD_SYMS to find the best match.
 >     The number of methods/functions in the list is given by NUM_FNS.
 >     Return the index of the best match; store an indication of the
 >     quality of the match in OLOAD_CHAMP_BV.
 > @@ -2883,10 +3059,12 @@ find_oload_champ_namespace_loop (struct value **args, int nargs,
 >  static int
 >  find_oload_champ (struct value **args, int nargs, int method,
 >  		  int num_fns, struct fn_field *fns_ptr,
 > +		  VEC (debug_method_worker_p) *dm_worker_vec,
 >  		  struct symbol **oload_syms,
 >  		  struct badness_vector **oload_champ_bv)
 >  {
 >    int ix;
 > +  int dm_worker_vec_n = 0;
 >    /* A measure of how good an overloaded instance is.  */
 >    struct badness_vector *bv;
 >    /* Index of best overloaded function.  */
 > @@ -2896,18 +3074,30 @@ find_oload_champ (struct value **args, int nargs, int method,
 >    /* 0 => no ambiguity, 1 => two good funcs, 2 => incomparable funcs.  */
 >  
 >    *oload_champ_bv = NULL;
 > +  if (dm_worker_vec != NULL)
 > +    dm_worker_vec_n = VEC_length (debug_method_worker_p, dm_worker_vec);
 > +  else
 > +    dm_worker_vec_n = 0;
 >  
 >    /* Consider each candidate in turn.  */
 > -  for (ix = 0; ix < num_fns; ix++)
 > +  for (ix = 0; (ix < num_fns) || (ix < dm_worker_vec_n); ix++)
 >      {
 >        int jj;
 > -      int static_offset = oload_method_static (method, fns_ptr, ix);
 > +      int static_offset = 0;
 >        int nparms;
 >        struct type **parm_types;
 > +      struct debug_method_worker *worker = NULL;
 > +
 > +      if (dm_worker_vec)
 > +	worker = VEC_index (debug_method_worker_p, dm_worker_vec, ix);
 >  
 >        if (method)
 >  	{
 > -	  nparms = TYPE_NFIELDS (TYPE_FN_FIELD_TYPE (fns_ptr, ix));
 > +	  if (fns_ptr)
 > +	    {
 > +	      static_offset = oload_method_static (method, fns_ptr, ix);
 > +	      nparms = TYPE_NFIELDS (TYPE_FN_FIELD_TYPE (fns_ptr, ix));
 > +	    }
 >  	}
 >        else
 >  	{
 > @@ -2916,13 +3106,18 @@ find_oload_champ (struct value **args, int nargs, int method,
 >  	}
 >  
 >        /* Prepare array of parameter types.  */
 > -      parm_types = (struct type **) 
 > -	xmalloc (nparms * (sizeof (struct type *)));
 > -      for (jj = 0; jj < nparms; jj++)
 > -	parm_types[jj] = (method
 > -			  ? (TYPE_FN_FIELD_ARGS (fns_ptr, ix)[jj].type)
 > -			  : TYPE_FIELD_TYPE (SYMBOL_TYPE (oload_syms[ix]), 
 > -					     jj));
 > +      if (fns_ptr || oload_syms)
 > +	{
 > +	  parm_types = (struct type **) 
 > +	    xmalloc (nparms * (sizeof (struct type *)));
 > +	  for (jj = 0; jj < nparms; jj++)
 > +	    parm_types[jj] = (method
 > +			      ? (TYPE_FN_FIELD_ARGS (fns_ptr, ix)[jj].type)
 > +			      : TYPE_FIELD_TYPE (SYMBOL_TYPE (oload_syms[ix]), 
 > +			      jj));
 > +	}
 > +      else
 > +	parm_types = get_debug_method_argtypes (worker, &nparms);
 >  
 >        /* Compare parameter types to supplied argument types.  Skip
 >           THIS for static methods.  */
 > diff --git a/gdb/value.h b/gdb/value.h
 > index f846669..87bd109 100644
 > --- a/gdb/value.h
 > +++ b/gdb/value.h
 > @@ -31,6 +31,7 @@ struct type;
 >  struct ui_file;
 >  struct language_defn;
 >  struct value_print_options;
 > +struct debug_method_worker;
 >  
 >  /* The structure which defines the type of a value.  It should never
 >     be possible for a program lval value to survive over a call to the
 > @@ -690,6 +691,7 @@ extern int find_overload_match (struct value **args, int nargs,
 >  				enum oload_search_type method,
 >  				struct value **objp, struct symbol *fsym,
 >  				struct value **valp, struct symbol **symp,
 > +				struct debug_method_worker **dm_worker,
 >  				int *staticp, const int no_adl);
 >  
 >  extern struct value *value_field (struct value *arg1, int fieldno);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]