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: [PING^2] [Patch v11] Debug methods in GDB Python


Hi.
For subsequent patches, can you split this into four separate patches in four separate emails?

1) docs, NEWS
2) extension* changes
3) python support
4) eval.c, valarith.c, valops.c changes

Thanks.

Rest of the comments are inline.

Siva Chandra writes:
 > Link to earlier posting of the latest version (v11) of the patch:
 > https://sourceware.org/ml/gdb-patches/2014-03/msg00037.html
 > 
 > Summary:
 > 
 > 1. v11 addresses Doug's extensive comments from his review.
 > 
 > 2. Eli had comments on the doc changes. I will address them with the
 > next round of code changes.
 > 
 > 3. The patch currently targets debug methods for C++ only.
 > 
 > 4. The overall idea: a user will have to define a method matcher which
 > returns a list of matching workers (also defined by the user) if any.
 > GDB will first call into the matchers registered with it and collects
 > matching workers if any. It then iterates over the matching workers to
 > perform overload resolution.
 > 
 > ChangeLog
 > 2014-03-27  Siva Chandra Reddy  <sivachandra@google.com>
 > 
 >         * Makefile.in: Add entries for new files.
 >         * NEWS (Python Scripting): Add entry about this feature.
 >         * 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_ops): Add the
 >         debug method interface.
 >         * 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_ptr)): New type.
 >         (debug_method_worker_ptr): New typedef.
 >         (debug_method_worker_vec): Likewise.
 >         * 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-debug_methods.c: New file.
 >         * python/py-objfile.c (objfile_object): New field
 >         'debug_method_matchers'.
 >         (objfpy_dealloc): XDECREF on the new debug_method_matchers field.
 >         (objfpy_new, objfile_to_objfile_object): Initialize
 >         debug_method_macthers field.
 >         (objfpy_get_debug_method_matchers): New function.
 >             (objfile_getset): New entry 'debug_method_matchers'.
 >         * python/py-progspace.c (pspace_object): New field
 >         'debug_method_matchers'.
 >         (pspy_dealloc): XDECREF on the new debug_method_matchers field.
 >         (pspy_new, pspace_to_pspace_object): Initialize
 >         debug_method_matchers field.
 >         (pspy_get_debug_method_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_debug_methods.
 >         * python/lib/gdb/__init__.py (debug_method_matcherss): 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/
 >         * python.texi (Debug Methods In Python): New node.
 >         (Debug Method API): Likewise.
 >         (Writing a Debug Method): Likewise.

fyi,
I didn't audit the ChangeLog for correctness in this pass.

 > diff --git a/gdb/Makefile.in b/gdb/Makefile.in
 > index 2558da5..ec52d82 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 \
 > @@ -2377,6 +2379,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/NEWS b/gdb/NEWS
 > index 2a384ba..d4fd167 100644
 > --- a/gdb/NEWS
 > +++ b/gdb/NEWS
 > @@ -87,6 +87,7 @@ qXfer:btrace:read's annex
 >    ** Valid Python operations on gdb.Value objects representing
 >       structs/classes invoke the corresponding overloaded operators if
 >       available.
 > +  ** New `Debug Methods' feature to the Python API.
 >  
 >  * New targets
 >  PowerPC64 GNU/Linux little-endian	powerpc64le-*-linux*
 > 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 \

Perhaps I push "Consistency Is Good" too much, but I don't think so. :-)
Can you rename these files to debug_methods.py.

 >  	gdb/command/frame_filters.py \
 >  	gdb/command/type_printers.py \
 >  	gdb/command/pretty_printers.py \
 > diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
 > index 90b7074..8a31446 100644
 > --- a/gdb/doc/python.texi
 > +++ b/gdb/doc/python.texi
 > @@ -144,6 +144,9 @@ optional arguments while skipping others.  Example:
 >  * Frame Filter API::            Filtering Frames.
 >  * Frame Decorator API::         Decorating Frames.
 >  * Writing a Frame Filter::      Writing a Frame Filter.
 > +* Debug Methods In Python::     Adding and replacing methods of C++ classes.
 > +* Debug Method API::            Debug method types.
 > +* Writing a Debug Method::      Writing a debug method.
 >  * Inferiors In Python::         Python representation of inferiors (processes)
 >  * Events In Python::            Listening for events from @value{GDBN}.
 >  * Threads In Python::           Accessing inferior threads from Python.
 > @@ -2195,6 +2198,260 @@ 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.  One can also use debug methods when debugging
 > +with core files.  Moreover, when debugging live programs, invoking a
 > +debug method need not involve running the inferior (which can potentially
 > +perturb its state).  Hence, even if the C@t{++} method is available, it
 > +is better to use its replacement debug method if one is defined.
 > +
 > +The debug methods feature in Python is available via the concepts of a
 > +@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_arg_types} method which
 > +returns a sequence of types corresponding to the arguments the debug
 > +method requires.  @value{GDBN} uses this sequence of types to perform
 > +overload resolution and picks a winning debug method worker.  A winner
 > +is also selected from among the 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.

It would be good to mention that if one wants the C++ method to "win", then one can by disabling the debug method.

 > +
 > +@xref{Debug Method API}, for API to implement debug methods in Python.
 > +@xref{Writing a Debug Method}, for implementing debug methods in Python.
 > +
 > +@node Debug Method API
 > +@subsubsection Debug Method API
 > +@cindex debug method API
 > +
 > +The @value{GDBN} Python API provides classes, interfaces and functions
 > +to implement, register and manipulate debug methods.  The core concepts
 > +involved in implementing debug methods are @emph{debug method matchers}
 > +and @emph{debug method workers}.  @xref{Debug Methods In Python}.
 > +
 > +A debug method matcher should be an instance of a class derived from
 > +@code{DebugMethodMatcher} defined in the module @code{gdb.debugmethods}.

gdb.debug_methods
[here and elsewhere]

 > +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 @var{name}.
 > +@end defun
 > +@end defvar
 > +
 > +@noindent
 > +The @code{DebugMethodMatcher} class has the following methods:
 > +
 > +@defun DebugMethodMatcher.__init__(self, name)
 > +Constructs an enabled debug method matcher with name @var{name}.  The
 > +@code{methods} attribute is initialized to @code{None}.
 > +@end defun
 > +
 > +@defun DebugMethodMatcher.match(self, class_type, method_name)
 > +Derived classes should override this method.  It should return a
 > +debug method worker object (or a sequence of debug method worker
 > +objects) matching the @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_arg_types(self)
 > +This method should return a sequence of @code{gdb.Type} objects

Remove "should".
"This methods returns a ..."

 > +corresponding to the arguments that the debug method takes.  It can
 > +return an empty sequence or @code{None} if the debug method does not
 > +take any arguments.  If the debug method takes a single argument, then
 > +a single @code{gdb.Type} object corresponding to it can be returned.
 > +@end defun
 > +
 > +@defun DebugMethodWroker.invoke(self, obj, args)

typo: Worker

 > +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.  @code{obj} and the
 > +elements of @code{args} are @code{gdb.Value} objects.
 > +@end defun
 > +
 > +For @value{GDBN} to lookup debug methods, the debug method matchers
 > +should be registered using the following function defined in the module
 > +@code{gdb.debugmethods}:
 > +
 > +@defun register_debug_method_matcher(locus, matcher, replace=False)
 > +The @code{matcher} is registered with @code{locus}, replacing an
 > +existing matcher with the same name as @code{matcher} if
 > +@code{replace} is @code{True}.  @code{locus} can be a
 > +@code{gdb.Objfile} object (@pxref{Objfiles In Python}), or a
 > +@code{gdb.Progspace} object (@pxref{Program Spaces In Python}), or
 > +@code{None}.  If it is @code{None}, then @code{matcher} is registered
 > +globally.
 > +@end defun
 > +
 > +@node Writing a Debug Method
 > +@subsubsection Writing a Debug Method
 > +@cindex writing 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.

I was thinking it would be good if the example included overloading an operator.
That will be the most common use.
It should be easy enough to replace sum with some operator, even +.

 > +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 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 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_arg_types(self):
 > +        return None
 > +
 > +    def invoke(self, obj, args):
 > +        return obj['a_']
 > +
 > +
 > +class MyClassWorker_sum(gdb.debugmethods.DebugMethodWorker):
 > +    def get_arg_types(self):
 > +        return gdb.lookup_type('MyClass')
 > +
 > +    def invoke(self, obj, args):
 > +        return obj['a_'] + args[0]['a_']
 > +@end smallexample
 > +
 > +For @value{GDBN} to actually lookup a debug method, it has to be
 > +registered with it.  The matcher defined above is registered with
 > +@value{GDBN} globally as follows:
 > +
 > +@smallexample
 > +gdb.debugmethods.register_debug_method_matcher(None, MyClassMatcher())
 > +@end smallexample
 > +
 > +If an object @code{obj} of type @code{MyClass} is initialized in C@t{++}
 > +code as follows:
 > +
 > +@smallexample
 > +MyClass obj(5);
 > +@end smallexample
 > +
 > +@noindent
 > +Then, after loading the Python script defining the debug method matchers
 > +and workers into @code{GDBN}, invoking @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 36615e1..0d26585 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,8 +1641,22 @@ 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
 > +
 > +	      /* 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);

Can invoke_debug_method throw an error?
[One could use a cleanup to free dm_worker, regardless.]

 > +		  xfree (dm_worker);
 > +
 > +		  return ret_val;
 > +		}
 > +
 > +	      argvec[1] = arg2; /* the ``this'' pointer */
 > +	      argvec[0] = valp; /* Use the method found after overload
 >  				   resolution.  */
 >  	    }
 >  	  else
 > @@ -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..a862b72 100644
 > --- a/gdb/extension-priv.h
 > +++ b/gdb/extension-priv.h
 > @@ -256,6 +256,54 @@ struct extension_language_ops
 >       changed or an error occurs no further languages are called.  */
 >    enum ext_lang_rc (*before_prompt) (const struct extension_language_defn *,
 >  				     const char *current_gdb_prompt);
 > +
 > +  /* Debug method support:
 > +     clone_debug_method_worker_data, free_debug_method_worker_data,
 > +     get_matching_debug_method_workers, get_debug_method_arg_types,
 > +     invoke_debug_method.
 > +     These methods are optional and may be NULL, but if one of them is
 > +     implemented then they all must be.  */
 > +
 > +  /* Clone DATA and return a new but identical debug method worker 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

extra space before 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_arg_types) (
 > +     const struct extension_language_defn *extlang,
 > +     struct debug_method_worker *worker,
 > +     int *nargs,
 > +     struct type ***arg_types);
 > +
 > +  /* 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);
 >  };
 >  
 >  /* State necessary to restore a signal handler to its previous value.  */
 > diff --git a/gdb/extension.c b/gdb/extension.c
 > index c2f502b..64c892f 100644
 > --- a/gdb/extension.c
 > +++ b/gdb/extension.c
 > @@ -833,6 +833,174 @@ check_quit_flag (void)
 >    return result;
 >  }
 >  
 > +/* Debug method support.  */
 > +
 > +/* Debug method API routines do not have "ext_lang" in the name because
 > +the name "debug_method" implies that this routine deals with extension
 > +languages.  Plus some of the methods take a debug_method_foo * "self/this"
 > +arg, not an extension_language_defn * arg.  */
 > +
 > +static void free_debug_method_worker_vec (void *vec);
 > +
 > +/* Returns a new debug_method_worker with EXTLANG and DATA.  */

Add something like "Space for the result is allocated with malloc,
caller must free."

 > +
 > +struct debug_method_worker *
 > +new_debug_method_worker (const struct extension_language_defn *extlang,
 > +			 void *data)
 > +{
 > +  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.
 > +   The function get_matching_debug_method_workers (see below), returns a
 > +   vector of matching workers.  If a particular worker is selected by GDB
 > +   to invoke a method, then this function can help in cloning the
 > +   selected worker and freeing up the vector via a cleanup (see
 > +   make_debug_method_worker_vec_cleanup below).  */

Ditto.
Add something like "Space for the result is allocated with malloc,
caller must free."

 > +
 > +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;
 > +
 > +  gdb_assert (extlang->ops->clone_debug_method_worker_data != NULL);
 > +
 > +  new_worker = new_debug_method_worker (
 > +     extlang,
 > +     extlang->ops->clone_debug_method_worker_data (extlang, worker->data));
 > +
 > +  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.  All matches found are returned as a vector
 > +   of 'struct ent_fn_descriptor' objects.  If no matching methods are

ent_fn_descriptor?

 > +   found, NULL is returned.  */
 > +
 > +VEC (debug_method_worker_ptr) *
 > +get_matching_debug_method_workers (struct type *type, const char *method_name)
 > +{
 > +  VEC (debug_method_worker_ptr) *workers = NULL;
 > +  int i;
 > +  const struct extension_language_defn *extlang;
 > +
 > +  ALL_EXTENSION_LANGUAGES (i, extlang)

I think it would be more consistent to use
ALL_ENABLED_EXTENSION_LANGUAGES.
With that, remove the ops == NULL check below.

 > +    {
 > +      VEC (debug_method_worker_ptr) *lang_workers, *new_vec;
 > +      enum ext_lang_rc rc;
 > +
 > +      /* If an extension language does not support debug methods, ignore
 > +	 it.  */
 > +      if (extlang->ops == NULL
 > +	  || extlang->ops->get_matching_debug_method_workers == NULL)
 > +	continue;
 > +
 > +      rc = extlang->ops->get_matching_debug_method_workers (extlang,
 > +							    type, method_name,
 > +							    &lang_workers);
 > +      if (rc == EXT_LANG_RC_ERROR)
 > +	{
 > +	  free_debug_method_worker_vec (workers);
 > +	  error (_("Error while looking for matching debug method workers "
 > +		   "defined in %s."), extlang->name);

I think it would be better to use extlang->capitalized_name here.

 > +	}
 > +
 > +      new_vec = VEC_merge (debug_method_worker_ptr, workers, lang_workers);
 > +      /* Free only the vectors and not the elements as NEW_VEC still
 > +	 contains them.  */
 > +      VEC_free (debug_method_worker_ptr, workers);
 > +      VEC_free (debug_method_worker_ptr, 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_arg_types (struct debug_method_worker *worker, int *nargs)
 > +{
 > +  enum ext_lang_rc rc;
 > +  struct type **type_array = NULL;
 > +  const struct extension_language_defn *extlang = worker->extlang;
 > +
 > +  gdb_assert (extlang->ops->get_debug_method_arg_types != NULL);
 > +
 > +  rc = extlang->ops->get_debug_method_arg_types (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);

extlang->capitalized_name

 > +    }
 > +
 > +  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->ops->invoke_debug_method != NULL);
 > +
 > +  rc = worker->extlang->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);

extlang->capitalized_name.

 > +    }
 > +
 > +  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_ptr) *v = (VEC (debug_method_worker_ptr) *) vec;
 > +
 > +  for (i = 0; VEC_iterate (debug_method_worker_ptr, v, i, worker); i++)
 > +    {
 > +      gdb_assert (worker->extlang->ops->free_debug_method_worker_data != NULL);
 > +      worker->extlang->ops->free_debug_method_worker_data (worker->extlang,
 > +							   worker->data);
 > +      xfree (worker);
 > +    }
 > +
 > +  VEC_free (debug_method_worker_ptr, v);
 > +}
 > +
 > +/* Return a cleanup object to free a vector VEC of extension function
 > +   descriptors.  */

s/extension function/debug method worker/ (or some such)

 > +
 > +struct cleanup *
 > +make_debug_method_worker_vec_cleanup (VEC (debug_method_worker_ptr) *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..049ce57 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_ptr;
 > +DEF_VEC_P (debug_method_worker_ptr);
 > +typedef VEC (debug_method_worker_ptr) 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_arg_types (
 > +   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/python/lib/gdb/__init__.py b/gdb/python/lib/gdb/__init__.py
 > index 95a76c2..b818258 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 method matchers.
 > +debug_method_matchers = []
 >  # 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..9540565
 > --- /dev/null
 > +++ b/gdb/python/lib/gdb/command/debugmethods.py
 > @@ -0,0 +1,260 @@
 > +# Debug method commands.
 > +# Copyright 2013-2014 Free Software Foundation, Inc.

2013 can be deleted here and throughout.

 > +
 > +# 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)
 > +
 > +
 > +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 3-tuple: (<locus matching regular expression>,
 > +                    <matcher matching regular expression>,
 > +                    <name matching regular experssion>)
 > +    """
 > +    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("debug method name", dm_name_regexp)
 > +    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.
 > +        matcher_re: The regular expression matching the names of debug methods.
 > +
 > +    Returns:
 > +        A dict of matching globally registered debug method matchers.  The only
 > +        key in the dict will be 'global'.

The code uses "registered globally" for the key.

 > +    """
 > +    locus_str = "registered globally"
 > +    dm_dict = { locus_str: [] }
 > +    if locus_re.match("global"):
 > +        dm_dict[locus_str].extend(
 > +            [m for m in gdb.debug_method_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.

Typo: matching

 > +
 > +    Arguments:
 > +        loci: The list of loci to lookup matching debug methods in.
 > +        locus_re: Debug method matchers will be looked up in a particular locus
 > +                  only if its filename matches the regular expression LOCUS_RE.
 > +        matcher_re: The regular expression to match the debug method matcher
 > +                    names.
 > +
 > +    Returns:
 > +        A dict of matching debug method matchers.  The keys of the dict are the
 > +        filenames of the loci the debug method matchers 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.debug_method_matchers if matcher_re.match(m.name)]
 > +    return dm_dict
 > +
 > +
 > +def print_dm_info(dm_dict, name_re):
 > +    """Print a dictionary of debug methods."""

This should print enabled/disabled status.
The output should be consistent with "info pretty-printer".

 > +    if not dm_dict:
 > +        return
 > +    for locus_str in dm_dict:
 > +        if not dm_dict[locus_str]:
 > +            continue
 > +        print ("Debug methods in %s:" % locus_str)
 > +        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

How come this "if" is needed?
If it's because the empty case uses "None", how about have it use [] instead?

 > +        for matcher in matchers:
 > +            if not name_re:
 > +                # If the name regex is missing, then set the status of the
 > +                # matcher and its methods.
 > +                matcher.enabled = status

I think the pretty-printers just set the status of the matcher in this case, not each individual printer.
This should do the same.

 > +            if not matcher.methods:
 > +                continue
 > +            for m in matcher.methods:
 > +                if not name_re:
 > +                    m.enabled = status
 > +                elif name_re.match(m.name):
 > +                    m.enabled = status
 > +
 > +
 > +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)
 > +    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 debug-method [locus-regexp [name-regexp]]
 > +
 > +    LOCUS-REGEXP is a regular expression matching the location of the debug
 > +    method matchers.  If it is omitted, all registered debug method matchers
 > +    from all 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 debug-method",
 > +                                               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)
 > +        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 debug-method [locus-regexp [name-regexp]]
 > +
 > +    LOCUS-REGEXP is a regular expression matching the location of the debug
 > +    methods.  If it is omitted, all registered debug methods from all loci
 > +    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 method matchers in the locus are enabled.  To enable 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(EnableDebugMethod, self).__init__("enable debug-method",
 > +                                                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 debug-method [locus-regexp [name-regexp]]
 > +
 > +    LOCUS-REGEXP is a regular expression matching the location of the debug
 > +    methods.  If it is omitted, all registered debug methods from all loci
 > +    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 method matchers in the locus are disabled.  To disable
 > +    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(DisableDebugMethod, self).__init__("disable debug-method",
 > +                                                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..93134af
 > --- /dev/null
 > +++ b/gdb/python/lib/gdb/debugmethods.py
 > @@ -0,0 +1,253 @@
 > +# 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
 > +
 > +
 > +if sys.version_info[0] > 2:
 > +    # Python 3 removed basestring and long
 > +    basestring = str
 > +    long = int
 > +
 > +
 > +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 at least the attributes of a 'DebugMethod' object.
 > +            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 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_arg_types' 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_arg_types' and 'invoke' methods.
 > +    """
 > +
 > +    def get_arg_types(self):
 > +        """Return arguments types of a debug method.
 > +
 > +        A sequence of gdb.Type objects corresponding to the arguments of the
 > +        debug method are returned.  If the debug method takes no arguments,
 > +        then returns 'None' or an empty sequence.  If the debug method takes
 > +        only a single argument, then a gdb.Type object or a sequence with a
 > +        single gdb.Type element is returned.
 > +        """
 > +        raise NotImplementedError("DebugMethod get_arg_types")
 > +
 > +    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.  Each element of the
 > +                  tuple is a gdb.Value object.
 > +
 > +        Returns:
 > +            A gdb.Value corresponding to the value returned by the debug
 > +            method.  Returns 'None' if the method does not return anything.
 > +        """
 > +        raise NotImplementedError("DebugMethod invoke")
 > +
 > +
 > +class SimpleDebugMethodMatcher(DebugMethodMatcher):
 > +    """A utility class to implement simple debug method mathers and workers.
 > +
 > +    See the __init__ method below for information on how instances of this
 > +    class can be used.
 > +
 > +    For simple classes and methods, one can choose to use this class.  For
 > +    complex debug methods, which need to replace/implement template methods on
 > +    possibly template classes, one should implement their own debug method
 > +    matchers and workers.  See py-debugmethods.py in testsuite/gdb.python
 > +    directory of the GDB source tree for examples.
 > +    """
 > +
 > +    class SimpleDebugMethodWorker(DebugMethodWorker):
 > +        def __init__(self, method_function, arg_types):
 > +            self._arg_types = arg_types
 > +            self._method_function = method_function
 > +
 > +        def get_arg_types(self):
 > +            return self._arg_types
 > +
 > +        def invoke(self, obj, args):
 > +            return self._method_function(obj, *args)
 > +
 > +
 > +    def __init__(self, name, class_matcher, method_matcher, method_function,
 > +                 *arg_types):
 > +        """
 > +        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' method of the worker returned by the objects of this
 > +                class.  This callable should accept the object (*this) as the
 > +                first argument followed by the rest of the arguments to the
 > +                method. All arguments to this function should be gdb.Value
 > +                objects.
 > +            arg_types: The gdb.Type objects corresponding to the arguments that
 > +                this debug method takes. It can be None, or an empty sequence,
 > +                or a single gdb.Type object, or a sequence of gdb.Type objects.
 > +        """
 > +        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._arg_types = arg_types
 > +
 > +    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._arg_types)
 > +
 > +
 > +# A helper function for register_debug_method_matcher which returns an error
 > +# object if MATCHER is not having the requisite attributes in the proper
 > +# format.

blank line

 > +def validate_debug_method_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_debug_method_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.

blank line

 > +def lookup_debug_method_matcher(locus, name):
 > +    i = 0
 > +    for m in locus.debug_method_matchers:
 > +        if m.name == name:
 > +            return i
 > +        i = i + 1
 > +
 > +
 > +def register_debug_method_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_debug_method_matcher(matcher)
 > +    if err:
 > +        raise err
 > +    if not locus:
 > +        locus = gdb
 > +    if locus == gdb:
 > +        locus_name = 'GDB globally'

This is a different global locus name than that used above.
How about just "global"?

 > +    else:
 > +        locus_name = locus.filename
 > +    index = lookup_debug_method_matcher(locus, matcher.name)
 > +    if index:
 > +        if replace:
 > +            del locus.debug_method_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.debug_method_matchers.insert(0, matcher)
 > diff --git a/gdb/python/py-debugmethods.c b/gdb/python/py-debugmethods.c
 > new file mode 100644
 > index 0000000..710f6aa
 > --- /dev/null
 > +++ b/gdb/python/py-debugmethods.c
 > @@ -0,0 +1,644 @@
 > +/* 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-priv.h"
 > +#include "objfiles.h"
 > +#include "value.h"
 > +#include "language.h"
 > +
 > +#include "python.h"
 > +#include "python-internal.h"
 > +
 > +static const char enabled_field_name[] = "enabled";
 > +static const char match_method_name[] = "match";
 > +static const char get_arg_types_method_name[] = "get_arg_types";
 > +static const char invoke_method_name[] = "invoke";
 > +static const char matchers_attr_str[] = "debug_method_matchers";
 > +
 > +static PyObject *py_match_method_name = NULL;
 > +static PyObject *py_get_arg_types_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.  */
 > +
 > +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);

Is XDECREF needed here, instead of just DECREF?
As a reader, it adds the complexity of having to think about when these values could be NULL.
Can they ever be NULL?

 > +  xfree (worker_data);
 > +}
 > +
 > +/* Implementation of clone_debug_method_worker_data for Python.  */
 > +
 > +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);

Is XINCREF needed here?
Can we assert that the values are non-NULL instead?
[haven't read the rest of the code yet]

 > +
 > +  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 *debug_method_name)
 > +{
 > +  PyObject *py_debug_method_name;
 > +  PyObject *match_method, *enabled_field, *match_result;
 > +  struct cleanup *cleanups;
 > +  int enabled;
 > +
 > +  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_RETURN_NONE;
 > +    }
 > +
 > +  match_method = PyObject_GetAttrString (matcher, match_method_name);
 > +  if (match_method == NULL)
 > +    {
 > +      do_cleanups (cleanups);
 > +      return NULL;
 > +    }
 > +  make_cleanup_py_decref (match_method);
 > +
 > +  py_debug_method_name = PyString_FromString (debug_method_name);
 > +  if (py_debug_method_name == NULL)
 > +    {
 > +      do_cleanups (cleanups);
 > +      return NULL;
 > +    }
 > +  make_cleanup_py_decref (py_debug_method_name);
 > +
 > +  match_result = PyObject_CallMethodObjArgs (matcher,
 > +					     py_match_method_name,
 > +					     py_obj_type,
 > +					     py_debug_method_name,
 > +					     NULL);
 > +
 > +  do_cleanups (cleanups);
 > +
 > +  return match_result;
 > +}
 > +
 > +/* Implementation of get_matching_debug_method_workers for Python.  */
 > +
 > +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_ptr) *worker_vec = NULL;
 > +  PyObject *py_type, *py_progspace;
 > +  PyObject *py_debug_method_matcher_list = NULL, *list_iter, *matcher;
 > +
 > +  gdb_assert (obj_type != NULL && method_name != NULL);
 > +
 > +  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_debug_method_matcher_list = PyList_New (0);
 > +  if (py_debug_method_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_debug_method_matcher_list;
 > +
 > +      if (py_objfile == NULL)
 > +	{
 > +	  gdbpy_print_stack ();
 > +	  Py_DECREF (py_debug_method_matcher_list);
 > +	  do_cleanups (cleanups);
 > +
 > +	  return EXT_LANG_RC_ERROR;
 > +	}
 > +
 > +      objfile_matchers = objfpy_get_debug_method_matchers (py_objfile, NULL);
 > +      py_debug_method_matcher_list = PySequence_Concat (temp,
 > +						       objfile_matchers);
 > +      Py_DECREF (temp);
 > +      Py_DECREF (objfile_matchers);
 > +      if (py_debug_method_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_debug_method_matcher_list;
 > +      PyObject *pspace_matchers = pspy_get_debug_method_matchers (py_progspace,
 > +								 NULL);
 > +
 > +      py_debug_method_matcher_list = PySequence_Concat (temp, pspace_matchers);
 > +      Py_DECREF (temp);
 > +      Py_DECREF (pspace_matchers);
 > +      if (py_debug_method_matcher_list == NULL)
 > +	{
 > +	  gdbpy_print_stack ();
 > +	  do_cleanups (cleanups);
 > +
 > +	  return EXT_LANG_RC_ERROR;
 > +	}
 > +    }
 > +  else
 > +    {
 > +      gdbpy_print_stack ();
 > +      Py_DECREF (py_debug_method_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_debug_method_matcher_list;
 > +
 > +      gdb_matchers = PyObject_GetAttrString (gdb_python_module,
 > +					     matchers_attr_str);
 > +      if (gdb_matchers != NULL)
 > +	{
 > +	  py_debug_method_matcher_list = PySequence_Concat (temp,
 > +							   gdb_matchers);
 > +	  Py_DECREF (temp);
 > +	  Py_DECREF (gdb_matchers);
 > +	  if (py_debug_method_matcher_list == NULL)
 > +	    {
 > +	      gdbpy_print_stack ();
 > +	      do_cleanups (cleanups);
 > +
 > +	      return EXT_LANG_RC_ERROR;
 > +	    }
 > +	}
 > +      else
 > +	{
 > +	  gdbpy_print_stack ();
 > +	  Py_DECREF (py_debug_method_matcher_list);
 > +	  do_cleanups (cleanups);
 > +
 > +	  return EXT_LANG_RC_ERROR;
 > +	}
 > +    }
 > +
 > +  /* Safe to make a cleanup for py_debug_method_matcher_list now as it
 > +     will not change any more.  */
 > +  make_cleanup_py_decref (py_debug_method_matcher_list);
 > +
 > +  list_iter = PyObject_GetIter (py_debug_method_matcher_list);
 > +  if (list_iter == NULL)
 > +    {
 > +      gdbpy_print_stack ();
 > +      do_cleanups (cleanups);
 > +
 > +      return EXT_LANG_RC_ERROR;
 > +    }
 > +  while ((matcher = PyIter_Next (list_iter)) != NULL)
 > +    {
 > +      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)) != NULL)
 > +	    {
 > +	      struct debug_method_worker *worker;
 > +
 > +	      worker = new_python_debug_method_worker (py_worker, py_type);
 > +	      VEC_safe_push (debug_method_worker_ptr, worker_vec, worker);
 > +	      Py_DECREF (py_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_ptr, 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_arg_types for Python.  */
 > +
 > +enum ext_lang_rc
 > +gdbpy_get_debug_method_arg_types (const struct extension_language_defn *extlang,
 > +				  struct debug_method_worker *worker,
 > +				  int *nargs, struct type ***arg_types)
 > +{
 > +  struct gdbpy_worker_data *worker_data = worker->data;
 > +  PyObject *py_worker = worker_data->worker;
 > +  PyObject *get_arg_types_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_arg_types_method =  PyObject_GetAttrString (py_worker,
 > +						  get_arg_types_method_name);
 > +  if (get_arg_types_method == NULL)
 > +    {
 > +      gdbpy_print_stack ();
 > +      do_cleanups (cleanups);
 > +
 > +      return EXT_LANG_RC_ERROR;
 > +    }
 > +  make_cleanup_py_decref (get_arg_types_method);
 > +
 > +  py_argtype_list = PyObject_CallMethodObjArgs (py_worker,
 > +						py_get_arg_types_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)) != NULL)
 > +	{
 > +	  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_arg_types "
 > +				 "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_arg_types 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;
 > +  *arg_types = type_array;
 > +  do_cleanups (cleanups);
 > +
 > +  return EXT_LANG_RC_OK;
 > +}
 > +
 > +/* Implementation of invoke_debug_method for Python.  */
 > +
 > +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 *debug_method_worker = worker_data->worker;
 > +
 > +  cleanups = ensure_python_env (get_current_arch (), current_language);
 > +
 > +  invoke_method =  PyObject_GetAttrString (debug_method_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);
 > +
 > +  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 (debug_method_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.  */

This comment doesn't add anything of value.
I'd just delete it.

 > +  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));

I realize this else clause is just one statement,
but since it occupies multiple lines wrap it in {}.

 > +
 > +  *result = res;
 > +  do_cleanups (cleanups);
 > +
 > +  return EXT_LANG_RC_OK;
 > +}
 > +
 > +/* 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;
 > +
 > +  gdb_assert (py_worker != NULL && this_type != NULL);
 > +
 > +  data = XCNEW (struct gdbpy_worker_data);
 > +  data->worker = py_worker;
 > +  data->this_type = this_type;
 > +  Py_INCREF (py_worker);
 > +  Py_INCREF (this_type);
 > +
 > +  return new_debug_method_worker (&extension_language_python, data);
 > +}
 > +
 > +int
 > +gdbpy_initialize_debug_methods (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_arg_types_method_name
 > +    = PyString_FromString (get_arg_types_method_name);
 > +  if (py_get_arg_types_method_name == NULL)
 > +    return -1;
 > +
 > +  return 1;
 > +}
 > diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
 > index 97fb0be..027d3ed 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 *debug_method_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->debug_method_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->debug_method_matchers = PyList_New (0);
 > +      if (self->debug_method_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 'debug_method_matchers' attribute.  */
 > +
 > +PyObject *
 > +objfpy_get_debug_method_matchers (PyObject *o, void *ignore)
 > +{
 > +  objfile_object *self = (objfile_object *) o;
 > +
 > +  Py_INCREF (self->debug_method_matchers);
 > +  return self->debug_method_matchers;
 > +}
 > +
 >  /* Set the 'type_printers' attribute.  */
 >  
 >  static int
 > @@ -292,6 +314,13 @@ objfile_to_objfile_object (struct objfile *objfile)
 >  	      return NULL;
 >  	    }
 >  
 > +	  object->debug_method_matchers = PyList_New (0);
 > +	  if (object->debug_method_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 },
 > +  { "debug_method_matchers", objfpy_get_debug_method_matchers, NULL,
 > +    "Debug methods.", NULL },

I realize why you want to add _matchers to the attribute name here, but it violates consistency with the other attributes here.
Please name the attribute "debug_methods".
[with requisite changes to accessors, etc.]

 >    { NULL }
 >  };
 >  
 > diff --git a/gdb/python/py-progspace.c b/gdb/python/py-progspace.c
 > index cda5a86..3592beb 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 *debug_method_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->debug_method_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->debug_method_matchers = PyList_New (0);
 > +      if (self->debug_method_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 'debug_method_matchers' attribute.  */
 > +
 > +PyObject *
 > +pspy_get_debug_method_matchers (PyObject *o, void *ignore)
 > +{
 > +  pspace_object *self = (pspace_object *) o;
 > +
 > +  Py_INCREF (self->debug_method_matchers);
 > +  return self->debug_method_matchers;
 > +}
 > +
 >  /* Set the 'type_printers' attribute.  */
 >  
 >  static int
 > @@ -288,6 +310,13 @@ pspace_to_pspace_object (struct program_space *pspace)
 >  	      return NULL;
 >  	    }
 >  
 > +	  object->debug_method_matchers = PyList_New (0);
 > +	  if (object->debug_method_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 },
 > +  { "debug_method_matchers", pspy_get_debug_method_matchers, NULL,
 > +    "Debug methods.", NULL },

Name the attribute "debug_methods".
[with requisite changes to accessors, etc.]

 >    { NULL }
 >  };
 >  
 > diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
 > index 07650f7..e905e68 100644
 > --- a/gdb/python/python-internal.h
 > +++ b/gdb/python/python-internal.h
 > @@ -307,6 +307,25 @@ extern enum ext_lang_bp_stop gdbpy_breakpoint_cond_says_stop
 >    (const struct extension_language_defn *, struct breakpoint *);
 >  extern int gdbpy_breakpoint_has_cond (const struct extension_language_defn *,
 >  				      struct breakpoint *b);
 > +
 > +extern void *gdbpy_clone_debug_method_worker_data
 > +  (const struct extension_language_defn *extlang, void *data);
 > +extern void gdbpy_free_debug_method_worker_data
 > +  (const struct extension_language_defn *extlang, void *data);
 > +extern 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);
 > +extern enum ext_lang_rc gdbpy_get_debug_method_arg_types
 > +  (const struct extension_language_defn *extlang,
 > +   struct debug_method_worker *worker,
 > +   int *nargs,
 > +   struct type ***arg_types);
 > +extern 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);
 >  
 >  PyObject *gdbpy_history (PyObject *self, PyObject *args);
 >  PyObject *gdbpy_breakpoints (PyObject *, PyObject *);
 > @@ -345,11 +364,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_debug_method_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_debug_method_matchers (PyObject *, void *);
 >  
 >  PyObject *gdbarch_to_arch_object (struct gdbarch *gdbarch);
 >  
 > @@ -430,6 +451,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_debug_methods (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..e6ae41a 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;

Delete this, from an older version of the patch.

 >  #endif
 >  
 >  /* The main struct describing GDB's interface to the Python
 > @@ -186,7 +188,13 @@ static const struct extension_language_ops python_extension_ops =
 >    gdbpy_set_quit_flag,
 >    gdbpy_check_quit_flag,
 >  
 > -  gdbpy_before_prompt_hook
 > +  gdbpy_before_prompt_hook,
 > +
 > +  gdbpy_clone_debug_method_worker_data,
 > +  gdbpy_free_debug_method_worker_data,
 > +  gdbpy_get_matching_debug_method_workers,
 > +  gdbpy_get_debug_method_arg_types,
 > +  gdbpy_invoke_debug_method
 >  };
 >  
 >  /* Architecture and language to be used in callbacks from
 > @@ -1752,7 +1760,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_debug_methods () < 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..fa6ea7a
 > --- /dev/null
 > +++ b/gdb/testsuite/gdb.python/py-debugmethods.cc
 > @@ -0,0 +1,194 @@
 > +/* 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;
 > +  E *e_ptr = &e;
 > +  E &e_ref = e;
 > +
 > +  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..27f63d9
 > --- /dev/null
 > +++ b/gdb/testsuite/gdb.python/py-debugmethods.exp
 > @@ -0,0 +1,133 @@
 > +# 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 [gdb_remote_download host \
 > +			      ${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 e_ptr->geta()" "From Python <A_geta>.*100" "After: e_ptr->geta()"
 > +gdb_test "p e_ref.geta()" "From Python <A_geta>.*100" "After: e_ref.geta()"
 > +gdb_test "p e.method(10)" "From Python <E_method_int>.*" "After: e.method(10)"
 > +gdb_test "p e.method('a')" "From Python <E_method_char>.*" \
 > +  "After: e.method('a')"
 > +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_ptr->mul<char>('a')"
 > +
 > +# Tests for 'disable/enable debug-method' command.
 > +gdb_test_no_output "disable debug-method .*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 debug-method .*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 debug-method .*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 debug-method .*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 debug-method global plus" "global.*plus_plus_A" \
 > +  "info debug-method global plus"
 > +
 > +remote_file host delete ${debug_methods_script}
 > diff --git a/gdb/testsuite/gdb.python/py-debugmethods.py b/gdb/testsuite/gdb.python/py-debugmethods.py
 > new file mode 100644
 > index 0000000..23dd3de
 > --- /dev/null
 > +++ b/gdb/testsuite/gdb.python/py-debugmethods.py
 > @@ -0,0 +1,232 @@
 > +# 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()
 > +
 > +
 > +# The E class matcher and worker test two things:
 > +#   1. debug method returning None.
 > +#   2. Matcher returning a list of workers.
 > +
 > +class E_method_worker1(DebugMethodWorker):
 > +    def __init__(self):
 > +        pass
 > +
 > +    def get_arg_types(self):
 > +        return gdb.lookup_type('char')
 > +
 > +    def invoke(self, obj, args):
 > +        print 'From Python <E_method_char>'
 > +        return None
 > +
 > +
 > +class E_method_worker2(DebugMethodWorker):
 > +    def __init__(self):
 > +        pass
 > +
 > +    def get_arg_types(self):
 > +        return gdb.lookup_type('int')
 > +
 > +    def invoke(self, obj, args):
 > +        print 'From Python <E_method_int>'
 > +        return None
 > +
 > +
 > +class E_method_matcher(DebugMethodMatcher):
 > +    def __init__(self):
 > +        DebugMethodMatcher.__init__(self, 'E_methods')
 > +
 > +    def match(self, class_type, method_name):
 > +        class_tag = class_type.unqualified().tag
 > +        if not re.match('^dop::E$', class_tag):
 > +            return None
 > +	if not re.match('^method$', method_name):
 > +            return None
 > +        return [E_method_worker1(), E_method_worker2()]
 > +
 > +
 > +# The G class method matcher and worker illustrate how to write
 > +# debug method matchers and workers for template classes and template
 > +# methods.
 > +
 > +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_arg_types(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_arg_types(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_arg_types(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 gdb.error:
 > +            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 gdb.error:
 > +                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 gdb.error:
 > +                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_debug_method_matcher(gdb, matcher)
 > +gdb.debugmethods.register_debug_method_matcher(gdb.current_progspace(),
 > +                                               G_methods_matcher())
 > +gdb.debugmethods.register_debug_method_matcher(gdb.current_objfile(),
 > +                                               E_method_matcher())
 > diff --git a/gdb/valarith.c b/gdb/valarith.c
 > index 8e863e3..9e79412 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).  */
 > @@ -282,24 +283,34 @@ unop_user_defined_p (enum exp_opcode op, struct value *arg1)
 >     *STATIC_MEMFUNP will be set to 1, and otherwise 0.
 >     The search if performed through find_overload_match which will handle
 >     member operators, non member operators, operators imported implicitly or
 > -   explicitly, and perform correct overload resolution in all of the above
 > -   situations or combinations thereof.  */
 > +   explicitly, operators implemented as debug methods, and perform correct
 > +   overload resolution in all of the above situations or combinations
 > +   thereof.  If a matching method/function is found in the binary, its
 > +   corresponding value is returned in SRC_FN.  If a debug method is the best
 > +   match, then the corresponding debug method worker is returned in
 > +   DM_WORKER.  */
 >  
 > -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,28 +318,41 @@ 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);
 >  }
 >  
 > -/* Lookup user defined operator NAME.  Return a value representing the
 > -   function, otherwise return NULL.  */
 > +/* Lookup user defined operator NAME.  If a matching operator is found in the
 > +   binary, its corresponding value is returned in SRC_FN.  If a debug method
 > +   is the best matching operator, then the corresponding debug method worker
 > +   is returned in DM_WORKER.  */
 >  
 > -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 +369,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 +384,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 +497,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 +518,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 != NULL)
 > +    {
 > +      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 +544,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 +558,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 +610,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])
 >      {
 > @@ -595,6 +631,14 @@ value_x_unop (struct value *arg1, enum exp_opcode op, enum noside noside)
 >  	}
 >        return call_function_by_hand (argvec[0], nargs, argvec + 1);
 >      }
 > +  if (dm_worker != NULL)
 > +    {
 > +      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 cf195a3..f63de63 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,
 > -			     struct fn_field *, struct symbol **,
 > -			     struct badness_vector **);
 > +			     struct fn_field *, VEC (debug_method_worker_ptr) *,
 > +			     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_ptr) **,
 > +			      struct type **, int *);
 >  
 >  void _initialize_valops (void);
 >  
 > @@ -2242,53 +2244,83 @@ 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.
 > +   specified method.  Return the pointer to the fn_field list FN_LIST of
 > +   overloaded instances defined in the source language.  If available
 > +   and matching, a vector of matching debug methods defined in
 > +   extension languages are also returned in DM_WORKER_VEC
 >  
 >     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.
 > +   DM_WORKER_VEC The vector of matching debug method workers.
 >     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_ptr) **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--)
 > +  /* First check in object itself.
 > +     This function is called recurssively to search through base classes.
 > +     If there is a source method match found at some stage, then we need not
 > +     look for source methods in consequent recursive calls.  */
 > +  if (fn_list && !(*fn_list))
 >      {
 > -      /* 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))
 > +      for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; i--)
 >  	{
 > -	  int len = TYPE_FN_FIELDLIST_LENGTH (type, i);
 > -	  struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
 > +	  /* pai: FIXME What about operators and type conversions?  */
 > +	  const char *fn_field_name = TYPE_FN_FIELDLIST_NAME (type, i);
 >  
 > -	  *num_fns = len;
 > -	  *basetype = type;
 > -	  *boffset = offset;
 > +	  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;
 >  
 > -	  /* Resolve any stub methods.  */
 > -	  check_stub_method_group (type, i);
 > +	      *num_fns = len;
 > +	      *basetype = type;
 > +	      *boffset = offset;
 > +
 > +	      /* Resolve any stub methods.  */
 > +	      check_stub_method_group (type, i);
 >  
 > -	  return f;
 > +	      break;
 > +	    }
 >  	}
 >      }
 >  
 > -  /* Not found in object, check in base subobjects.  */
 > +  /* Unlike source methods, debug methods can be accumulated over successive
 > +     recursive calls.  In other words, a debug method named 'm' in a class
 > +     will not hide a debug method named 'm' in its base class(es).  */
 > +  if (dm_worker_vec)
 > +    {
 > +      VEC (debug_method_worker_ptr) *worker_vec = NULL, *new_vec = NULL;
 > +
 > +      worker_vec = get_matching_debug_method_workers (type, method);
 > +      new_vec = VEC_merge (debug_method_worker_ptr, *dm_worker_vec, worker_vec);
 > +
 > +      VEC_free (debug_method_worker_ptr, *dm_worker_vec);
 > +      VEC_free (debug_method_worker_ptr, worker_vec);
 > +      *dm_worker_vec = new_vec;
 > +    }
 > +
 > +  /* 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;
 > @@ -2305,28 +2337,35 @@ 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.
 > +/* Return the list of overloaded methods of a specified name.  The methods
 > +   could be those GDB finds in the binary, or debug methods.  Methods found
 > +   in the binary are returned in FN_LIST, and debug methods are returned in
 > +   DM_WORKER_VEC.
 >  
 >     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_ptr) **dm_worker_vec,
 >  			      struct type **basetype, int *boffset)
 >  {
 >    struct type *t;
 > @@ -2348,8 +2387,35 @@ 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_ptr, 1);
 > +
 > +  find_method_list (argp, method, 0, t, fn_list, num_fns, dm_worker_vec,
 > +		    basetype, boffset);
 > +}
 > +
 > +/* Return the dynamic type of OBJ.  NULL is returned if OBJ does not have any
 > +   dynamic type.  */
 > +
 > +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
 > @@ -2377,9 +2443,10 @@ 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 method then DM_WORKER will hold the matching
 > +   debug method worker.  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.
 > @@ -2397,6 +2464,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);
 > @@ -2404,16 +2472,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_orig = -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_ptr) *dm_worker_vec = NULL;
 >    /* Number of overloaded instances being considered.  */
 >    int num_fns = 0;
 >    struct type *basetype = NULL;
 > @@ -2425,6 +2501,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.  */
 > @@ -2453,12 +2531,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) ? "::" : "",
 > @@ -2469,18 +2547,90 @@ 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,
 > -	                                         num_fns, fns_ptr,
 > -	                                         NULL, &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,
 > +						     num_fns, fns_ptr, NULL,
 > +						     NULL, &src_method_badness);
 >  
 > -	  make_cleanup (xfree, 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);
 > +	}
 > +
 > +      if (dm_worker && VEC_length (debug_method_worker_ptr, dm_worker_vec))
 > +	{
 > +	  ext_method_oload_champ = find_oload_champ (args, nargs,
 > +						     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 debug method are equally good.  */
 > +		src_and_ext_equal = 1;
 > +		/* If src method and debug method are equally good, then debug
 > +		   method should be the winner.  Hence, fall through to the
 > +		   case where a debug method is better than the source
 > +		   method, except when the debug method match quality is
 > +		   non-standard.  */
 > +		/* FALLTHROUGH */
 > +	      case 1: /* Src method and ext method are incompatible.  */
 > +		/* If ext method match is not standard, then let source method
 > +		   win.  Otherwise, fallthrough to let debug 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;
 > +		  }
 > +		/* FALLTHROUGH */
 > +	      case 2: /* Ext method is champion.  */
 > +		method_oload_champ = ext_method_oload_champ;
 > +		method_badness = ext_method_badness;
 > +		/* We save the source overload champ index so that it can be
 > +		   used to determine whether the source method is virtual
 > +		   later in this function.  */
 > +		src_method_oload_champ_orig = 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:
 > +		gdb_assert_not_reached (_("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)
 > @@ -2623,21 +2773,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));
 > @@ -2647,10 +2782,75 @@ 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)
 > +	{
 > +	  /* Even if the source method was the winner, it could be a virtual
 > +	     function.  In such a case, we should look for the possibility of
 > +	     debug methods defined on the object's dynamic type.  */
 > +	  if (TYPE_FN_FIELD_VIRTUAL_P (fns_ptr, method_oload_champ))
 > +	    {
 > +	      struct type *dtype;
 > +
 > +	      dtype = value_has_indirect_dynamic_type (args[0]);
 > +	      if (dtype)
 > +		{
 > +		  /* If the object has a dynamic type, then look for matching
 > +		     methods for its dynamic type.  */
 > +		  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
 > +	{
 > +	  /* Debug methods cannot be virtual.  However, if a debug method is as
 > +	     good as the source method, and if the source method is virtual, we
 > +	     should look for the possibility of better matching methods defined
 > +	     for the dynamic type of the object.  */
 > +	  if (src_and_ext_equal
 > +	      && TYPE_FN_FIELD_VIRTUAL_P (fns_ptr, src_method_oload_champ_orig))
 > +	    {
 > +	      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_ptr, dm_worker_vec,
 > +			ext_method_oload_champ));
 >  	}
 > -      *objp = temp;
 >      }
 > +  else
 > +    *symp = oload_syms[func_oload_champ];
 >  
 >    do_cleanups (all_cleanups);
 >  
 > @@ -2785,7 +2985,7 @@ find_oload_champ_namespace_loop (struct value **args, int nargs,
 >      ++num_fns;
 >  
 >    new_oload_champ = find_oload_champ (args, nargs, 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),
 > @@ -2823,9 +3023,13 @@ 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
 > -   given by FNS_PTR or OLOAD_SYMS, respectively.  One, and only one of
 > -   FNS_PTR and OLOAD_SYMS can be non-NULL.  The number of
 > -   methods/functions in the non-NULL list is given by NUM_FNS.
 > +   given by FNS_PTR or OLOAD_SYMS or DM_WORKER_VEC, respectively.
 > +   One, and only one of FNS_PTR, OLOAD_SYMS and DM_WORKER_VEC can be
 > +   non-NULL.
 > +
 > +   If DM_WORKER_VEC is NULL, then the length of the arrays FNS_PTR
 > +   or OLOAD_SYMS (whichever is non-NULL) is specified in NUM_FNS.
 > +
 >     Return the index of the best match; store an indication of the
 >     quality of the match in OLOAD_CHAMP_BV.
 >  
 > @@ -2834,10 +3038,13 @@ find_oload_champ_namespace_loop (struct value **args, int nargs,
 >  static int
 >  find_oload_champ (struct value **args, int nargs,
 >  		  int num_fns, struct fn_field *fns_ptr,
 > +		  VEC (debug_method_worker_ptr) *dm_worker_vec,
 >  		  struct symbol **oload_syms,
 >  		  struct badness_vector **oload_champ_bv)
 >  {
 >    int ix;
 > +  int fn_count;
 > +  int dm_worker_vec_n = VEC_length (debug_method_worker_ptr, dm_worker_vec);
 >    /* A measure of how good an overloaded instance is.  */
 >    struct badness_vector *bv;
 >    /* Index of best overloaded function.  */
 > @@ -2847,40 +3054,49 @@ find_oload_champ (struct value **args, int nargs,
 >    /* 0 => no ambiguity, 1 => two good funcs, 2 => incomparable funcs.  */
 >  
 >    /* A champion can be found among methods alone, or among functions
 > -     alone, but not both.  */
 > -  gdb_assert ((fns_ptr != NULL) + (oload_syms != NULL) == 1);
 > +     alone, or in debug methods alone, but not in more than one of these
 > +     groups.  */
 > +  gdb_assert ((fns_ptr != NULL) + (oload_syms != NULL) + (dm_worker_vec != NULL)
 > +	      == 1);
 >  
 >    *oload_champ_bv = NULL;
 >  
 > +  fn_count = (dm_worker_vec != NULL
 > +	      ? VEC_length (debug_method_worker_ptr, dm_worker_vec)
 > +	      : num_fns);
 >    /* Consider each candidate in turn.  */
 > -  for (ix = 0; ix < num_fns; ix++)
 > +  for (ix = 0; ix < fn_count; ix++)
 >      {
 >        int jj;
 > -      int static_offset;
 > +      int static_offset = 0;
 >        int nparms;
 >        struct type **parm_types;
 > +      struct debug_method_worker *worker = NULL;
 >  
 > -      if (fns_ptr != NULL)
 > +      if (dm_worker_vec != NULL)
 >  	{
 > -	  nparms = TYPE_NFIELDS (TYPE_FN_FIELD_TYPE (fns_ptr, ix));
 > -	  static_offset = oload_method_static (1, fns_ptr, ix);
 > +	  worker = VEC_index (debug_method_worker_ptr, dm_worker_vec, ix);
 > +	  parm_types = get_debug_method_arg_types (worker, &nparms);
 >  	}
 >        else
 >  	{
 > -	  /* If it's not a method, this is the proper place.  */
 > -	  nparms = TYPE_NFIELDS (SYMBOL_TYPE (oload_syms[ix]));
 > -	  static_offset = 0;
 > +	  if (fns_ptr != NULL)
 > +	    {
 > +	      nparms = TYPE_NFIELDS (TYPE_FN_FIELD_TYPE (fns_ptr, ix));
 > +	      static_offset = oload_method_static (1, fns_ptr, ix);
 > +	    }
 > +          else
 > +	    nparms = TYPE_NFIELDS (SYMBOL_TYPE (oload_syms[ix]));
 > +
 > +	  parm_types = (struct type **)
 > +	    xmalloc (nparms * (sizeof (struct type *)));
 > +	  for (jj = 0; jj < nparms; jj++)
 > +	    parm_types[jj] = (fns_ptr != NULL
 > +			      ? (TYPE_FN_FIELD_ARGS (fns_ptr, ix)[jj].type)
 > +			      : TYPE_FIELD_TYPE (SYMBOL_TYPE (oload_syms[ix]),
 > +			      jj));
 >  	}
 >  
 > -      /* Prepare array of parameter types.  */
 > -      parm_types = (struct type **) 
 > -	xmalloc (nparms * (sizeof (struct type *)));
 > -      for (jj = 0; jj < nparms; jj++)
 > -	parm_types[jj] = (fns_ptr != NULL
 > -			  ? (TYPE_FN_FIELD_ARGS (fns_ptr, ix)[jj].type)
 > -			  : TYPE_FIELD_TYPE (SYMBOL_TYPE (oload_syms[ix]), 
 > -					     jj));
 > -
 >        /* Compare parameter types to supplied argument types.  Skip
 >           THIS for static methods.  */
 >        bv = rank_function (parm_types, nparms, 
 > @@ -2914,10 +3130,14 @@ find_oload_champ (struct value **args, int nargs,
 >        xfree (parm_types);
 >        if (overload_debug)
 >  	{
 > -	  if (fns_ptr)
 > +	  if (fns_ptr != NULL)
 >  	    fprintf_filtered (gdb_stderr,
 >  			      "Overloaded method instance %s, # of parms %d\n",
 >  			      fns_ptr[ix].physname, nparms);
 > +	  else if (dm_worker_vec != NULL)
 > +	    fprintf_filtered (gdb_stderr,
 > +			      "Debug method worker, # of parms %d\n",
 > +			      nparms);
 >  	  else
 >  	    fprintf_filtered (gdb_stderr,
 >  			      "Overloaded function instance "
 > 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);

-- 
/dje


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