mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-24 18:44:20 +08:00
ba18742c3a
The initial goal of this patch was to remove the usage of VEC(xmethod_worker_ptr) and corresponding cleanups. I ended up having to C++ify the xmethod_worker code, to be able to have xmethod_workers free their data in destructors, and therefore be able to use vectors of xmethod_worker unique_ptr. The operations in extension_language_ops that act on one instance of xmethod_worker (get result type, get args type, invoke) are transformed to methods of xmethod_worker. xmethod_worker becomes an abstract base class with virtual pure methods which python_xmethod_worker implements. The only xmethod-related operation left in extension_language_ops is get_matching_xmethod_workers, which returns a list of xmethod_workers. The changes are relatively straightforward, but here are some notes on things that may raise eyebrows: - I was not really comfortable with the value_of_xmethod function. At first it looks like a simple getter, so I considered making it a method of xmethod_worker. But actually it creates a value and transfers the ownership of the xmethod_worker to it. It would be a bit weird and error-prone if calling a method on an object silently removed the ownership of the object from the caller. To reflect the behavior more accurately, I renamed it to value_from_xmethod and made it accept an rvalue-reference (so the caller knows it gives away the ownership). I noticed the backlink from xmethod_worker to its owning value was not used, so I removed it. - Some code, like get_matching_xmethod_workers, made each callee fill a new vector, which was then merged in the result vector. I think it's safe if we always pass the same vector around, and each implementation just appends to it. - The clone operation does not seem particularly useful, it is removed in the following patch. gdb/ChangeLog: * extension-priv.h (enum ext_lang_rc): Remove, move to extension.h. (struct extension_language_ops) <clone_xmethod_worker_data>: Remove. <free_xmethod_worker_data>: Remove. <get_matching_xmethod_workers>: Chance VEC to std::vector. <get_xmethod_arg_types>: Remove. <get_xmethod_result_type>: Remove. <invoke_xmethod>: Remove. * extension.c (new_xmethod_worker): Remove. (clone_xmethod_worker): Remove. (get_matching_xmethod_workers): Return void, pass std::vector by pointer. (get_xmethod_arg_types): Rename to... (xmethod_worker::get_arg_types): ... this, and adjust. (get_xmethod_result_type): Rename to... (xmethod_worker::get_result_type): ... this, and adjust. (invoke_xmethod): Remove. (free_xmethod_worker): Remove. (free_xmethod_worker_vec): Remove. * extension.h (enum ext_lang_rc): Move here from extension-priv.h. (struct xmethod_worker): Add constructor and destructor. <data>: Remove. <value>: Remove. <invoke, clone, do_get_result_type, do_get_arg_types>: New virtual pure methods. <get_arg_types, get_result_type>: New methods. (xmethod_worker_ptr): Remove typedef. (DEF_VEC_P (xmethod_worker_ptr)): Remove. (xmethod_worker_vec): Remove typedef. (xmethod_worker_up): New typedef. (invoke_xmethod): Remove. (clone_xmethod_worker): Remove. (free_xmethod_worker): Remove. (free_xmethod_worker_vec): Remove. (get_xmethod_arg_types): Remove. (get_xmethod_result_type): Remove. * valops.c (find_method_list): Use std::vector, don't use intermediate vector. (value_find_oload_method_list): Use std::vector. (find_overload_match): Use std::vector. (find_oload_champ): Use std::vector. * value.c (value_free): Use operator delete. (value_of_xmethod): Rename to... (value_from_xmethod): ... this. Don't assign xmethod_worker::value, take rvalue-reference. (result_type_of_xmethod): Adjust. (call_xmethod): Adjust. * value.h: Include extension.h. (struct xmethod_worker): Don't forward-declare. (value_of_xmethod): Rename to... (value_from_xmethod): ... this, take rvalue-reference. * python/py-xmethods.c (struct gdbpy_worker_data): Rename to... (struct python_xmethod_worker): ... this, add constructor and destructor. <invoke, clone, do_get_arg_types, do_get_result_type>: Implement. (gdbpy_free_xmethod_worker_data): Rename to... (python_xmethod_worker::~python_xmethod_worker): ... this and adjust. (gdbpy_clone_xmethod_worker_data): Rename to... (python_xmethod_worker::clone): ... this and adjust. (gdbpy_get_matching_xmethod_workers): Use std::vector, don't use temporary vector. (gdbpy_get_xmethod_arg_types): Rename to... (python_xmethod_worker::do_get_arg_types): ... this and adjust. (gdbpy_get_xmethod_result_type): Rename to... (python_xmethod_worker::do_get_result_type): ... this and adjust. (gdbpy_invoke_xmethod): Rename to... (python_xmethod_worker::invoke): ... this and adjust. (new_python_xmethod_worker): Rename to... (python_xmethod_worker::python_xmethod_worker): ... this and adjust. * python/python-internal.h (gdbpy_clone_xmethod_worker_data): Remove. (gdbpy_free_xmethod_worker_data): Remove. (gdbpy_get_matching_xmethod_workers): Use std::vector. (gdbpy_get_xmethod_arg_types): Remove. (gdbpy_get_xmethod_result_type): Remove. (gdbpy_invoke_xmethod): Remove. * python/python.c (python_extension_ops): Remove obsolete callbacks.
314 lines
10 KiB
C++
314 lines
10 KiB
C++
/* Interface between gdb and its extension languages.
|
|
|
|
Copyright (C) 2014-2018 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/>. */
|
|
|
|
#ifndef EXTENSION_H
|
|
#define EXTENSION_H
|
|
|
|
#include "mi/mi-cmds.h" /* For PRINT_NO_VALUES, etc. */
|
|
#include "common/vec.h"
|
|
|
|
struct breakpoint;
|
|
struct command_line;
|
|
struct frame_info;
|
|
struct language_defn;
|
|
struct objfile;
|
|
struct extension_language_defn;
|
|
struct type;
|
|
struct ui_file;
|
|
struct ui_out;
|
|
struct value;
|
|
struct value_print_options;
|
|
|
|
/* A function to load and process a script file.
|
|
The file has been opened and is ready to be read from the beginning.
|
|
Any exceptions are not caught, and are passed to the caller. */
|
|
typedef void script_sourcer_func (const struct extension_language_defn *,
|
|
FILE *stream, const char *filename);
|
|
|
|
/* A function to load and process a script for an objfile.
|
|
The file has been opened and is ready to be read from the beginning.
|
|
Any exceptions are not caught, and are passed to the caller. */
|
|
typedef void objfile_script_sourcer_func
|
|
(const struct extension_language_defn *,
|
|
struct objfile *, FILE *stream, const char *filename);
|
|
|
|
/* A function to execute a script for an objfile.
|
|
Any exceptions are not caught, and are passed to the caller. */
|
|
typedef void objfile_script_executor_func
|
|
(const struct extension_language_defn *,
|
|
struct objfile *, const char *name, const char *script);
|
|
|
|
/* Enum of each extension(/scripting) language. */
|
|
|
|
enum extension_language
|
|
{
|
|
EXT_LANG_NONE,
|
|
EXT_LANG_GDB,
|
|
EXT_LANG_PYTHON,
|
|
EXT_LANG_GUILE
|
|
};
|
|
|
|
/* Extension language frame-filter status return values. */
|
|
|
|
enum ext_lang_bt_status
|
|
{
|
|
/* Return when an error has occurred in processing frame filters,
|
|
or when printing the stack. */
|
|
EXT_LANG_BT_ERROR = -1,
|
|
|
|
/* Return from internal routines to indicate that the function
|
|
succeeded. */
|
|
EXT_LANG_BT_OK = 1,
|
|
|
|
/* Return when the frame filter process is complete, and all
|
|
operations have succeeded. */
|
|
EXT_LANG_BT_COMPLETED = 2,
|
|
|
|
/* Return when the frame filter process is complete, but there
|
|
were no filter registered and enabled to process. */
|
|
EXT_LANG_BT_NO_FILTERS = 3
|
|
};
|
|
|
|
/* Flags to pass to apply_extlang_frame_filter. */
|
|
|
|
enum frame_filter_flags
|
|
{
|
|
/* Set this flag if frame level is to be printed. */
|
|
PRINT_LEVEL = 1,
|
|
|
|
/* Set this flag if frame information is to be printed. */
|
|
PRINT_FRAME_INFO = 2,
|
|
|
|
/* Set this flag if frame arguments are to be printed. */
|
|
PRINT_ARGS = 4,
|
|
|
|
/* Set this flag if frame locals are to be printed. */
|
|
PRINT_LOCALS = 8,
|
|
};
|
|
|
|
/* A choice of the different frame argument printing strategies that
|
|
can occur in different cases of frame filter instantiation. */
|
|
|
|
enum ext_lang_frame_args
|
|
{
|
|
/* Print no values for arguments when invoked from the MI. */
|
|
NO_VALUES = PRINT_NO_VALUES,
|
|
|
|
MI_PRINT_ALL_VALUES = PRINT_ALL_VALUES,
|
|
|
|
/* Print only simple values (what MI defines as "simple") for
|
|
arguments when invoked from the MI. */
|
|
MI_PRINT_SIMPLE_VALUES = PRINT_SIMPLE_VALUES,
|
|
|
|
/* Print only scalar values for arguments when invoked from the CLI. */
|
|
CLI_SCALAR_VALUES,
|
|
|
|
/* Print all values for arguments when invoked from the CLI. */
|
|
CLI_ALL_VALUES
|
|
};
|
|
|
|
/* The possible results of
|
|
extension_language_ops.breakpoint_cond_says_stop. */
|
|
|
|
enum ext_lang_bp_stop
|
|
{
|
|
/* No "stop" condition is set. */
|
|
EXT_LANG_BP_STOP_UNSET,
|
|
|
|
/* A "stop" condition is set, and it says "don't stop". */
|
|
EXT_LANG_BP_STOP_NO,
|
|
|
|
/* A "stop" condition is set, and it says "stop". */
|
|
EXT_LANG_BP_STOP_YES
|
|
};
|
|
|
|
/* Table of type printers associated with the global typedef table. */
|
|
|
|
struct ext_lang_type_printers
|
|
{
|
|
/* Type-printers from Python. */
|
|
void *py_type_printers;
|
|
};
|
|
|
|
/* The return code for some API calls. */
|
|
|
|
enum ext_lang_rc
|
|
{
|
|
/* The operation completed successfully. */
|
|
EXT_LANG_RC_OK,
|
|
|
|
/* The operation was not performed (e.g., no pretty-printer). */
|
|
EXT_LANG_RC_NOP,
|
|
|
|
/* There was an error (e.g., Python error while printing a value).
|
|
When an error occurs no further extension languages are tried.
|
|
This is to preserve existing behaviour, and because it's convenient
|
|
for Python developers.
|
|
Note: This is different than encountering a memory error trying to read
|
|
a value for pretty-printing. Here we're referring to, e.g., programming
|
|
errors that trigger an exception in the extension language. */
|
|
EXT_LANG_RC_ERROR
|
|
};
|
|
|
|
/* A type which holds its extension language specific xmethod worker data. */
|
|
|
|
struct xmethod_worker
|
|
{
|
|
xmethod_worker (const extension_language_defn *extlang)
|
|
: m_extlang (extlang)
|
|
{}
|
|
|
|
virtual ~xmethod_worker () = default;
|
|
|
|
/* Invoke the xmethod encapsulated in this worker and return the result.
|
|
The method is invoked on OBJ with arguments in the ARGS array. NARGS is
|
|
the length of the this array. */
|
|
|
|
virtual value *invoke (value *obj, value **args, int nargs) = 0;
|
|
|
|
/* Clone this worker, returns a new but identical worker.
|
|
The function get_matching_xmethod_workers 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. */
|
|
|
|
virtual std::unique_ptr<xmethod_worker> clone () = 0;
|
|
|
|
/* Return the arg types of the xmethod encapsulated in this 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. */
|
|
|
|
type **get_arg_types (int *nargs);
|
|
|
|
/* Return the type of the result of the xmethod encapsulated in this worker.
|
|
OBJECT, ARGS, NARGS are the same as for invoke. */
|
|
|
|
type *get_result_type (value *object, value **args, int nargs);
|
|
|
|
private:
|
|
|
|
/* 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. */
|
|
|
|
virtual enum ext_lang_rc do_get_arg_types
|
|
(int *nargs, struct type ***arg_types) = 0;
|
|
|
|
/* Fetch the type of the result of the method implemented by this worker.
|
|
OBJECT, ARGS, NARGS are the same as for the invoked method. The result
|
|
type is stored in *RESULT_TYPE. */
|
|
|
|
virtual enum ext_lang_rc do_get_result_type
|
|
(struct value *obj, struct value **args, int nargs,
|
|
struct type **result_type_ptr) = 0;
|
|
|
|
/* The language the xmethod worker is implemented in. */
|
|
|
|
const extension_language_defn *m_extlang;
|
|
};
|
|
|
|
typedef std::unique_ptr<xmethod_worker> xmethod_worker_up;
|
|
|
|
/* The interface for gdb's own extension(/scripting) language. */
|
|
extern const struct extension_language_defn extension_language_gdb;
|
|
|
|
extern const struct extension_language_defn *get_ext_lang_defn
|
|
(enum extension_language lang);
|
|
|
|
extern const struct extension_language_defn *get_ext_lang_of_file
|
|
(const char *file);
|
|
|
|
extern int ext_lang_present_p (const struct extension_language_defn *);
|
|
|
|
extern int ext_lang_initialized_p (const struct extension_language_defn *);
|
|
|
|
extern void throw_ext_lang_unsupported
|
|
(const struct extension_language_defn *);
|
|
|
|
/* Accessors for "public" attributes of the extension language definition. */
|
|
|
|
extern enum extension_language ext_lang_kind
|
|
(const struct extension_language_defn *);
|
|
|
|
extern const char *ext_lang_name (const struct extension_language_defn *);
|
|
|
|
extern const char *ext_lang_capitalized_name
|
|
(const struct extension_language_defn *);
|
|
|
|
extern const char *ext_lang_suffix (const struct extension_language_defn *);
|
|
|
|
extern const char *ext_lang_auto_load_suffix
|
|
(const struct extension_language_defn *);
|
|
|
|
extern script_sourcer_func *ext_lang_script_sourcer
|
|
(const struct extension_language_defn *);
|
|
|
|
extern objfile_script_sourcer_func *ext_lang_objfile_script_sourcer
|
|
(const struct extension_language_defn *);
|
|
|
|
extern objfile_script_executor_func *ext_lang_objfile_script_executor
|
|
(const struct extension_language_defn *);
|
|
|
|
extern int ext_lang_auto_load_enabled (const struct extension_language_defn *);
|
|
|
|
/* Wrappers for each extension language API function that iterate over all
|
|
extension languages. */
|
|
|
|
extern void finish_ext_lang_initialization (void);
|
|
|
|
extern void eval_ext_lang_from_control_command (struct command_line *cmd);
|
|
|
|
extern void auto_load_ext_lang_scripts_for_objfile (struct objfile *);
|
|
|
|
extern struct ext_lang_type_printers *start_ext_lang_type_printers (void);
|
|
|
|
extern char *apply_ext_lang_type_printers (struct ext_lang_type_printers *,
|
|
struct type *);
|
|
|
|
extern void free_ext_lang_type_printers (struct ext_lang_type_printers *);
|
|
|
|
extern int apply_ext_lang_val_pretty_printer
|
|
(struct type *type,
|
|
LONGEST embedded_offset, CORE_ADDR address,
|
|
struct ui_file *stream, int recurse,
|
|
struct value *val, const struct value_print_options *options,
|
|
const struct language_defn *language);
|
|
|
|
extern enum ext_lang_bt_status apply_ext_lang_frame_filter
|
|
(struct frame_info *frame, int flags, enum ext_lang_frame_args args_type,
|
|
struct ui_out *out, int frame_low, int frame_high);
|
|
|
|
extern void preserve_ext_lang_values (struct objfile *, htab_t copied_types);
|
|
|
|
extern const struct extension_language_defn *get_breakpoint_cond_ext_lang
|
|
(struct breakpoint *b, enum extension_language skip_lang);
|
|
|
|
extern int breakpoint_ext_lang_cond_says_stop (struct breakpoint *);
|
|
|
|
/* If a method with name METHOD_NAME is to be invoked on an object of type
|
|
TYPE, then all extension languages are searched for implementations of
|
|
methods with name METHOD_NAME. All matches found are appended to the WORKERS
|
|
vector. */
|
|
|
|
extern void get_matching_xmethod_workers
|
|
(struct type *type, const char *method_name,
|
|
std::vector<xmethod_worker_up> *workers);
|
|
|
|
#endif /* EXTENSION_H */
|