From patchwork Mon Apr 28 14:00:24 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Siva Chandra Reddy X-Patchwork-Id: 723 Return-Path: X-Original-To: siddhesh@wilcox.dreamhost.com Delivered-To: siddhesh@wilcox.dreamhost.com Received: from homiemail-mx21.g.dreamhost.com (peon2454.g.dreamhost.com [208.113.200.127]) by wilcox.dreamhost.com (Postfix) with ESMTP id 9FC4F360075 for ; Mon, 28 Apr 2014 07:00:35 -0700 (PDT) Received: by homiemail-mx21.g.dreamhost.com (Postfix, from userid 14314964) id 14BC214C848B; Mon, 28 Apr 2014 07:00:34 -0700 (PDT) X-Original-To: gdb@patchwork.siddhesh.in Delivered-To: x14314964@homiemail-mx21.g.dreamhost.com Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by homiemail-mx21.g.dreamhost.com (Postfix) with ESMTPS id B01A313F891B for ; Mon, 28 Apr 2014 07:00:34 -0700 (PDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:mime-version:date:message-id:subject:from:to :content-type; q=dns; s=default; b=lzsrE44wtPq+QMfektrk0fUixmkdR r0RaWgg/lzRL+zc8zbHHCevKW9aE98p3+E0vhtp7wHOv6+506GJB38Ee3BnhpOAU bDpCVRwLT3WCjIxMQy5xHyocklBGEuLEWiL4L/d4AN/PoxBsvN7tOaKMOmNS6G3A mDAGPGj6b9aiP0= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:mime-version:date:message-id:subject:from:to :content-type; s=default; bh=uuvvDuoRnkdqoUQFcESv+gxY2Nc=; b=vyJ 3XOsHKBbeqJIp5L9VST7jVRP8xRPLmGc/seBh65+VGe9yTHAe7e874/mB9S2wFBj 4f/NVPeC+ce6qC55aZInv4WKeHkc/zN5LTR1nuwDHBz5+queJxoN2Ka4NDbiliq8 wx+8y2ZXWLSZSq6cZ7QKZxLNrVIm6Bdu9WAp33WE= Received: (qmail 31104 invoked by alias); 28 Apr 2014 14:00:32 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 31084 invoked by uid 89); 28 Apr 2014 14:00:31 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.8 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-we0-f175.google.com Received: from mail-we0-f175.google.com (HELO mail-we0-f175.google.com) (74.125.82.175) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Mon, 28 Apr 2014 14:00:28 +0000 Received: by mail-we0-f175.google.com with SMTP id q58so6441338wes.34 for ; Mon, 28 Apr 2014 07:00:25 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:date:message-id:subject:from:to :content-type; bh=qcRL7IdEMPUwmTtZ1yGUKz3V6KBEttdcbexNd9WXZ+w=; b=Kzjir/zEi6yyMqZxtlkIoDf2/UhlpadWzA4VakcDvHpMBq+dZSzB0AX2n/MwMVFrsh lYEC8wjjpso6DsWIpF8Djpzwss82fPfcn43fu2wBUUQadlbHJuFjO5brKJBKpeGWJYX9 uOIqjMmuFP0sss7Dtw4r1myYkTBMgl+vBGp8aPHrsDPX9teLf8m7wkW7dqnyf6MKauv/ cfJ35thfqDxDtCa9IDbOtetSC/pcffN8H349u8ERaAP40T4P7c+Mgm3Fafm+YEboiVl9 9BfU7AiHXWhzzMAFf8hMhi/HvwgyJPVRDbz92IVtm29bH7usd55E5cBpY0sFgSoe/d57 qm+w== X-Gm-Message-State: ALoCoQkNDvytvzoPkGF6OdtMtzQWZmBCCW2WflXmjEpa6PuSwEhC2eMAYV8EsNMBRDqNlpv/fUl+bWTBVObuq8z7PN63u3UjCbJ4R9qO6oVwkMN6XhZ8URC9OtjQshalRXzAfmGFw7PlZwJTuNd3dtxe6bU2LXdj4aZ9S5yKCmKsrnNCsfzruhZiYU3bXhWHst1fEiG2fxNKK/bP9xR6IxoezURXO1UYzw== MIME-Version: 1.0 X-Received: by 10.180.9.202 with SMTP id c10mr2810920wib.7.1398693625160; Mon, 28 Apr 2014 07:00:25 -0700 (PDT) Received: by 10.217.51.7 with HTTP; Mon, 28 Apr 2014 07:00:24 -0700 (PDT) Date: Mon, 28 Apr 2014 07:00:24 -0700 Message-ID: Subject: [PATCH 2/4 v14] Add xmethod (was debug method) interface to the extension language API From: Siva Chandra To: gdb-patches X-IsSubscribed: yes X-DH-Original-To: gdb@patchwork.siddhesh.in This part of the patch series was previously approved but sending out for review again because of the following changes: 1. The name "debug methods" has been changed to "xmethods". The attached patch does not change the name at every instance, but only with the new changes made after v13. The reason is that I am not sure if we are going to stick with the name "xmethod". I thought leaving in both the names for now would help is deciding which seems better, but if it makes reading difficult, I can change it all places. 2. "xmethods" now have an associated type, TYPE_CODE_XMETHOD. The function find_overload_match returns a value of type TYPE_CODE_XMETHOD if the best matching method is an xmethod. This change is in part 3/4 of this series, but the required infrastructure is added in this part. ChangeLog 2014-04-28 Siva Chandra Reddy * defs.h (enum lval_type): New enumerator "lval_xmethod". * extension-priv.h (struct extension_language_ops): Add the debug method interface. * extension.c (new_debug_method_worker, clone_debug_method_worker, get_matching_debug_method_workers, get_debug_method_argtypes, invoke_debug_method, free_xmethod_worker, free_debug_method_worker_vec, make_debug_method_worker_vec_cleanup): New functions. * extension.h: #include "common/vec.h". New function declarations. (struct debug_method_worker): New struct. (VEC (debug_method_worker_ptr)): New vector type. (debug_method_worker_ptr): New typedef. (debug_method_worker_vec): Likewise. * gdbtypes.h (enum type_code): New enumerator TYPE_CODE_XMETHOD. (struct builtin_type): New field "xmethod". * gdbtypes.c (gdbtypes_post_init): Initialize "xmethod" field of builtin_type. * value.c: #include "extension.h". (struct value): New field XM_WORKER in the field LOCATION. (value_of_xmethod, call_xmethod, free_xmethod_value): New functions. * value.h: Declare new functions value_of_xmethod, call_xmethod and free_xmethod_value. diff --git a/gdb/defs.h b/gdb/defs.h index 47da43a..6750585 100644 --- a/gdb/defs.h +++ b/gdb/defs.h @@ -388,6 +388,8 @@ enum lval_type lval_register, /* * In a gdb internal variable. */ lval_internalvar, + /* * Value is an xmethod. */ + lval_xmethod, /* * Part of a gdb internal variable (structure field). */ lval_internalvar_component, /* * Value's bits are fetched and stored using functions provided diff --git a/gdb/extension-priv.h b/gdb/extension-priv.h index 9e63a9c..b862dd3 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 + 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 1146cc7..2cb1cbe 100644 --- a/gdb/extension.c +++ b/gdb/extension.c @@ -834,6 +834,182 @@ 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. Space for the + result is allocated using 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; + worker->value = NULL; + + 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). + + Space for the result is allocated using 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 'debug_method_worker_ptr' objects. If no matching methods are + 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_ENABLED_EXTENSION_LANGUAGES (i, extlang) + { + 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->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->capitalized_name); + } + + 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->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->capitalized_name); + } + + return result; +} + +/* Frees the xmethod worker WORKER. */ + +void +free_xmethod_worker (struct debug_method_worker *worker) +{ + 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); +} + +/* 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++) + free_xmethod_worker (worker); + + VEC_free (debug_method_worker_ptr, v); +} + +/* Return a cleanup object to free the vector VEC of debug method workers. */ + +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..7bc6b42 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; @@ -138,6 +139,27 @@ 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; + + /* The TYPE_CODE_XMETHOD value corresponding to this worker. + Always Use value_of_xmethod to access it. */ + struct value *value; +}; + +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 +234,25 @@ 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 void free_xmethod_worker (struct debug_method_worker *); + +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/gdbtypes.c b/gdb/gdbtypes.c index 8b528b8..fdfc311 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -4366,6 +4366,10 @@ gdbtypes_post_init (struct gdbarch *gdbarch) = arch_type (gdbarch, TYPE_CODE_INTERNAL_FUNCTION, 0, ""); + /* This type represents an xmethod. */ + builtin_type->xmethod + = arch_type (gdbarch, TYPE_CODE_XMETHOD, 0, ""); + return builtin_type; } diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 86b1d62..26133d6 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -179,7 +179,10 @@ enum type_code TYPE_CODE_MODULE, /**< Fortran module. */ /* * Internal function type. */ - TYPE_CODE_INTERNAL_FUNCTION + TYPE_CODE_INTERNAL_FUNCTION, + + /* * Methods implmented in extension languages. */ + TYPE_CODE_XMETHOD }; /* * For now allow source to use TYPE_CODE_CLASS for C++ classes, as @@ -1468,6 +1471,9 @@ struct builtin_type /* * This type is used to represent a GDB internal function. */ struct type *internal_fn; + + /* * This type is used to represent an xmethod. */ + struct type *xmethod; }; /* * Return the type table for the specified architecture. */ diff --git a/gdb/value.c b/gdb/value.c index d125a09..85c2a88 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -230,6 +230,9 @@ struct value /* Pointer to internal variable. */ struct internalvar *internalvar; + /* Pointer to xmethod worker. */ + struct debug_method_worker *xm_worker; + /* If lval == lval_computed, this is a set of function pointers to use to access and describe the value, and a closure pointer for them to use. */ @@ -1433,6 +1436,8 @@ value_free (struct value *val) if (funcs->free_closure) funcs->free_closure (val); } + else if (VALUE_LVAL (val) == lval_xmethod) + free_xmethod_worker (val->location.xm_worker); xfree (val->contents); VEC_free (range_s, val->unavailable); @@ -2456,6 +2461,56 @@ show_convenience (char *ignore, int from_tty) } } +/* Return the TYPE_CODE_XMETHOD value corresponding to WORKER. When done with + the value and the WORKER, free it using free_xmethod_value. Free-ing the + value frees the WORKER as well. */ + +struct value * +value_of_xmethod (struct debug_method_worker *worker) +{ + struct value *v; + + if (worker->value != NULL) + v = worker->value; + else + { + v = allocate_value (builtin_type (target_gdbarch ())->xmethod); + v->lval = lval_xmethod; + v->location.xm_worker = worker; + worker->value = v; + } + + return v; +} + +/* Call the xmethod corresponding to the TYPE_CODE_XMETHOD value METHOD. */ + +struct value * +call_xmethod (struct value *method, int argc, struct value **argv) +{ + gdb_assert (TYPE_CODE (value_type (method)) == TYPE_CODE_XMETHOD + && method->lval == lval_xmethod && argc > 0); + + return invoke_debug_method (method->location.xm_worker, + argv[0], argv + 1, argc - 1); +} + +/* Free the TYPE_CODE_XMETHOD value XM_VALUE. Releases the value from the + value chain and frees it. The xmethod worker object corresponding to + this value is also freed. */ + +void +free_xmethod_value (void *xm_value) +{ + struct value *v = xm_value; + + gdb_assert (TYPE_CODE (value_type (v)) == TYPE_CODE_XMETHOD + && v->lval == lval_xmethod); + + release_value (v); + value_free (v); +} + /* Extract a value as a C number (either long or double). Knows how to convert fixed values to double, or floating values to long. diff --git a/gdb/value.h b/gdb/value.h index 144e182..55cdb53 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 @@ -857,6 +858,8 @@ extern int compile_internalvar_to_ax (struct internalvar *var, extern struct internalvar *lookup_internalvar (const char *name); +extern struct value *value_of_xmethod (struct debug_method_worker *); + extern int value_equal (struct value *arg1, struct value *arg2); extern int value_equal_contents (struct value *arg1, struct value *arg2); @@ -1011,4 +1014,9 @@ struct value *call_internal_function (struct gdbarch *gdbarch, char *value_internal_function_name (struct value *); +struct value *call_xmethod (struct value *function, + int argc, struct value **argv); + +extern void free_xmethod_value (void *); + #endif /* !defined (VALUE_H) */