From patchwork Tue Apr 1 22:53:13 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: 380 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 150853600D4 for ; Tue, 1 Apr 2014 15:53:21 -0700 (PDT) Received: by homiemail-mx21.g.dreamhost.com (Postfix, from userid 14314964) id C582AE90454; Tue, 1 Apr 2014 15:53:20 -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 9C64BF7E647 for ; Tue, 1 Apr 2014 15:53:20 -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=HWKakQl9OlPpK5ugaSV5wQ9K/OSPV v+fvZTIJs8e0XvNEuA4JxUzeq/qUX2+FzsEl/W04TxT3uVR993tFnMrVnlW9mteM Mqloqe6moiBH5x1LMxNs5qZCazy2V3Jmc8H2A58aexz+P8oxFVc8EYRa9NTI61LY wUgmq3/oz8looo= 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=6NjmiFMXsUE3yVxRVQTUCXKLbeU=; b=IYa EXCEwk/tF1nGQYKGxORq//kk+EfQAnt84GDJSmxCas0Ik+ThuXDI0NLgoFjN+43j Ub+DQsFQvfDfxE6F11faF8iDU3YNax7Of+SK4GITpWnAUyDMTruaPs2WCZozXppW 4e0wTVQaetBLI1BSQMME6kK6TIXM3e/A9nQkqVX8= Received: (qmail 31249 invoked by alias); 1 Apr 2014 22:53:19 -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 31240 invoked by uid 89); 1 Apr 2014 22:53:18 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.1 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-wi0-f171.google.com Received: from mail-wi0-f171.google.com (HELO mail-wi0-f171.google.com) (209.85.212.171) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Tue, 01 Apr 2014 22:53:17 +0000 Received: by mail-wi0-f171.google.com with SMTP id q5so6084623wiv.4 for ; Tue, 01 Apr 2014 15:53:14 -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=+Qepi/gFhToAk4PXkxyTaKhS+hr54IrbGthvHC9E3Bs=; b=l4PqrRL50XjujtH8eDTwOXbaMeA4+J1B2rDRryN9i59C03e7R65epv5LZEXTEyxqpg 7eDLlsImrfJ/d79yDbi1k62fgesL3qEr4Xh8Y20/mVwDfCLyPF5FOh8pIWVxt88TcwTK hIQ/+c8IMZFlO63BgZgafu2FoUahBU/wCXxtA1s7QKJXp+S0aiJKG+jkkdqe+jwiWufL Mycvg/lPIWnQ4nTP1/JYVmIxPGTuDK3gMvt6pYQxORKO0TMUE8drCUZMq/JB7OVsysAG rTiC8c60J3YTP1mDNqmIGKYsNtLF4EG5NlfWbBmEdfC61WBPR6RvPGIUEabF1sanR91S RJ/w== X-Gm-Message-State: ALoCoQnLGQLNqfQfgvOxp4rdj9zwbYjeRXs4Um0svdZkF/vCVVv40tMD2PjOJzTndnpuMH7tB2qawhF8YD9gfo3Zue75599F8aK4p+fXns6JSiKlZnT7OGX9Krkpx/uyAxv+HKLlXF6LMuLu2WACEjFaxZIlVu850jEgt7MIK8tM7ooDc527fo7mc0o9EEik9nxMeUITfbB0J6/iZoQr/3vBmJlAy9o88Q== MIME-Version: 1.0 X-Received: by 10.194.188.68 with SMTP id fy4mr26008160wjc.30.1396392793900; Tue, 01 Apr 2014 15:53:13 -0700 (PDT) Received: by 10.15.48.194 with HTTP; Tue, 1 Apr 2014 15:53:13 -0700 (PDT) Date: Tue, 1 Apr 2014 15:53:13 -0700 Message-ID: Subject: [Patch v12 2/4] Add 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 adds the debug method interface to the extension language API. 2014-04-01 Siva Chandra Reddy * 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 vector type. (debug_method_worker_ptr): New typedef. (debug_method_worker_vec): Likewise. diff --git a/gdb/extension-priv.h b/gdb/extension-priv.h index 9e63a9c..c4083f1 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..337bfa8 100644 --- a/gdb/extension.c +++ b/gdb/extension.c @@ -834,6 +834,175 @@ 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; + + 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 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 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..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 */