From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 25711 invoked by alias); 6 Dec 2013 05:52:55 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 25702 invoked by uid 89); 6 Dec 2013 05:52:54 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.7 required=5.0 tests=AWL,BAYES_00,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,MSGID_FROM_MTA_HEADER,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=no version=3.3.2 X-HELO: mail-pd0-f172.google.com Received: from Unknown (HELO mail-pd0-f172.google.com) (209.85.192.172) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Fri, 06 Dec 2013 05:52:50 +0000 Received: by mail-pd0-f172.google.com with SMTP id g10so415075pdj.31 for ; Thu, 05 Dec 2013 21:52:42 -0800 (PST) X-Received: by 10.66.141.165 with SMTP id rp5mr1998789pab.90.1386309162799; Thu, 05 Dec 2013 21:52:42 -0800 (PST) Received: from sspiff.org (173-13-178-50-sfba.hfc.comcastbusiness.net. [173.13.178.50]) by mx.google.com with ESMTPSA id vh3sm115762299pbc.8.2013.12.05.21.52.40 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 05 Dec 2013 21:52:41 -0800 (PST) Message-ID: <52a16629.23ee440a.55aa.31c4@mx.google.com> Received: by sspiff.org (sSMTP sendmail emulation); Thu, 05 Dec 2013 21:52:14 -0800 Date: Fri, 06 Dec 2013 05:52:00 -0000 From: xdje42@gmail.com To: gdb-patches@sourceware.org Subject: [PATCH v1 02/13] script language API for GDB: scripting.[ch] X-IsSubscribed: yes X-SW-Source: 2013-12/txt/msg00223.txt.bz2 This patch adds scripting.h, scripting.c and scripting-priv.h. scripting.h provides the public API. The enums that were in python.h have been moved here and any py_,PY_ part of the name has been replaced to be non-python-specific. scripting-priv.h provides the "private" API. This is what Python exports to GDB. scripting.c defines script_language_gdb for GDB's own scripting language, and provides the functions GDB calls to call into a scripting language. 2013-12-05 Doug Evans * Makefile.in (SFILES): Add scripting.c. (HFILES_NO_SRCDIR): Add scripting.h. (COMMON_OBS): Add scripting.o. * scripting.h: New file. * scripting-priv.h: New file. * scripting.c: New file. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index be30dfd..a859ffc 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -757,7 +757,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ proc-service.list progspace.c \ prologue-value.c psymtab.c \ regcache.c reggroups.c remote.c remote-fileio.c remote-notif.c reverse.c \ - sentinel-frame.c \ + scripting.c sentinel-frame.c \ serial.c ser-base.c ser-unix.c skip.c \ solib.c solib-target.c source.c \ stabsread.c stack.c probe.c stap-probe.c std-regs.c \ @@ -842,6 +842,7 @@ config/nm-nto.h config/sparc/nm-sol2.h config/nm-linux.h \ top.h bsd-kvm.h gdb-stabs.h reggroups.h \ annotate.h sim-regno.h dictionary.h dfp.h main.h frame-unwind.h \ remote-fileio.h i386-linux-tdep.h vax-tdep.h objc-lang.h \ +scripting.h scripting-priv.h \ sentinel-frame.h bcache.h symfile.h windows-tdep.h linux-tdep.h \ gdb_usleep.h jit.h xml-syscall.h microblaze-tdep.h \ psymtab.h psympriv.h progspace.h bfin-tdep.h ia64-hpux-tdep.h \ @@ -934,6 +935,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ go-lang.o go-valprint.o go-typeprint.o \ jv-lang.o jv-valprint.o jv-typeprint.o jv-varobj.o \ m2-lang.o opencl-lang.o p-lang.o p-typeprint.o p-valprint.o \ + scripting.o \ sentinel-frame.o \ complaints.o typeprint.o \ ada-typeprint.o c-typeprint.o f-typeprint.o m2-typeprint.o \ diff --git a/gdb/scripting-priv.h b/gdb/scripting-priv.h new file mode 100644 index 0000000..f839d8c --- /dev/null +++ b/gdb/scripting-priv.h @@ -0,0 +1,191 @@ +/* Private implementation details of interface between gdb and its + scripting languages. + + Copyright (C) 2013 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 . */ + +#ifndef SCRIPTING_PRIV_H +#define SCRIPTING_PRIV_H + +#include "scripting.h" + +/* High level description of a scripting language. + An entry for each is compiled into GDB regardless of whether the support + is present. This is done so that we can issue meaningful errors if the + support is not compiled in. */ + +struct script_language_defn +{ + /* Enum of the scripting language. */ + enum script_language language; + + /* The name of the scripting language, lowercase. E.g., python. */ + const char *name; + + /* The capitalized name of the scripting language. E.g., Python. */ + const char *capitalized_name; + + /* The file suffix for this scripting language. E.g., ".py". */ + const char *suffix; + + /* The suffix of per-objfile scripts to auto-load scripts. + E.g., When the program loads libfoo.so, look for libfoo.so-gdb.py. */ + const char *auto_load_suffix; + + /* We support embedding external scripting language code in GDB's own + scripting language. We do this by having a special command that begins + the external language snippet, and terminate it with "end". + This specifies the control type used to implement this. */ + enum command_control_type cli_control_type; + + /* A pointer to the "methods" to load scripts in this language, + or NULL if the support is not compiled into GDB. */ + const struct script_language_script_ops *script_ops; + + /* Either a pointer to the "methods" of the scripting language interface + or NULL if the support is not compiled into GDB. + This is also NULL for GDB's own scripting language which is relatively + primitive, and doesn't provide these features. */ + const struct script_language_ops *ops; +}; + +/* The interface for loading scripts from external scripting languages, + as well as GDB's own scripting language. */ + +struct script_language_script_ops +{ + /* Load a script. This is called, e.g., via the "source" command. */ + script_sourcer_func *script_sourcer; + + /* Load a script attached to an objfile. */ + objfile_script_sourcer_func *objfile_script_sourcer; + + /* Return non-zero if auto-loading scripts in this scripting language + is enabled. */ + int (*auto_load_enabled) (const struct script_language_defn *); +}; + +/* The interface for making calls from GDB to an external scripting + language. This is for non-script-loading related functionality, + like pretty-printing, etc. The reason these are separated out as + GDB's own scripting language makes use of script_language_script_opts, + but it makes no use of these. There is no (current) intention to split + script_language_ops up any further. */ + +struct script_language_ops +{ + /* Called at the end of gdb initialization to give the scripting language + an opportunity to finish up. This is useful for things like adding + new commands where one has to wait until gdb itself is initialized. */ + void (*finish_initialization) (const struct script_language_defn *); + + /* Return non-zero if the scripting language successfully initialized. */ + int (*initialized) (const struct script_language_defn *); + + /* Process a sequence of commands embedded in gdb's own scripting language. + E.g., + python + print 42 + end */ + void (*eval_from_control_command) (const struct script_language_defn *, + struct command_line *); + + /* Called before printing a type. */ + void (*start_type_printers) (const struct script_language_defn *, + struct script_type_printers *); + + /* Try to pretty-print TYPE. If successful the pretty-printed type is + returned. Otherwise NULL is returned. + This function has a bit of a funny name, since it actually applies + recognizers, but this seemed clearer given the start_type_printers + and free_type_printers functions. */ + char *(*apply_type_printers) (const struct script_language_defn *, + const struct script_type_printers *, + struct type *); + + /* Called after a type has been printed to give the type pretty-printer + mechanism an opportunity to clean up. */ + void (*free_type_printers) (const struct script_language_defn *, + struct script_type_printers *); + + /* Try to pretty-print a value of type TYPE located at VALADDR + + EMBEDDED_OFFSET, which came from the inferior at address ADDRESS + + EMBEDDED_OFFSET, onto stdio stream STREAM according to OPTIONS. + VAL is the whole object that came from ADDRESS. VALADDR must point to + the head of VAL's contents buffer. + Returns non-zero if the value was successfully pretty-printed. */ + int (*apply_val_pretty_printer) + (const struct script_language_defn *, + struct type *type, const gdb_byte *valaddr, + int embedded_offset, CORE_ADDR address, + struct ui_file *stream, int recurse, + const struct value *val, const struct value_print_options *options, + const struct language_defn *language); + + /* GDB access to the "frame filter" feature. + FRAME is the source frame to start frame-filter invocation. FLAGS is an + integer holding the flags for printing. The following elements of + the FRAME_FILTER_FLAGS enum denotes the make-up of FLAGS: + PRINT_LEVEL is a flag indicating whether to print the frame's + relative level in the output. PRINT_FRAME_INFO is a flag that + indicates whether this function should print the frame + information, PRINT_ARGS is a flag that indicates whether to print + frame arguments, and PRINT_LOCALS, likewise, with frame local + variables. ARGS_TYPE is an enumerator describing the argument + format, OUT is the output stream to print. FRAME_LOW is the + beginning of the slice of frames to print, and FRAME_HIGH is the + upper limit of the frames to count. Returns SCR_BT_ERROR on error, + or SCR_BT_COMPLETED on success. */ + enum script_bt_status (*apply_frame_filter) + (const struct script_language_defn *, + struct frame_info *frame, int flags, enum script_frame_args args_type, + struct ui_out *out, int frame_low, int frame_high); + + /* Update values held by the scripting language when OBJFILE is discarded. + New global types must be created for every such value, which must then be + updated to use the new types. + The function typically just iterates over all appropriate values and + calls preserve_one_value for each one. + COPIED_TYPES is used to prevent cycles / duplicates and is passed to + preserve_one_value. */ + void (*preserve_values) (const struct script_language_defn *, + struct objfile *objfile, htab_t copied_types); + + /* Return non-zero if there is a stop condition for the breakpoint. */ + int (*breakpoint_has_cond) (const struct script_language_defn *, + struct breakpoint *); + + /* Return non-zero if there is a stop condition for the breakpoint, + and it indicates the program should stop. */ + enum scr_bp_stop (*breakpoint_cond_says_stop) + (const struct script_language_defn *, struct breakpoint *); + + /* The next three are used to connect gdb's SIGINT handling with the + scripting language's. */ + + /* Clear the SIGINT indicator. */ + void (*clear_quit_flag) (const struct script_language_defn *); + + /* Set the SIGINT indicator. */ + void (*set_quit_flag) (const struct script_language_defn *); + + /* Return non-zero if a SIGINT has occurred. + This is expected to also clear the indicator. */ + int (*check_quit_flag) (const struct script_language_defn *); +}; + +#endif /* SCRIPTING_PRIV_H */ diff --git a/gdb/scripting.c b/gdb/scripting.c new file mode 100644 index 0000000..f63edf8 --- /dev/null +++ b/gdb/scripting.c @@ -0,0 +1,621 @@ +/* Interface between gdb and its scripting languages. + + Copyright (C) 2013 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 . */ + +/* Note: With few exceptions, external functions and variables in this file + have "script" in the name, and no other symbol in gdb does. */ + +#include "defs.h" +#include "auto-load.h" +#include "breakpoint.h" +#include "scripting.h" +#include "scripting-priv.h" +#include "cli/cli-script.h" +#include "python/python.h" + +/* Iterate over all external scripting languages, regardless of whether the + support has been compiled in or not. */ +#define ALL_EXT_SCRIPTING_LANGUAGES(i, slang) \ + for (/*int*/ i = 0, slang = external_scripting_languages[0]; \ + slang != NULL; \ + slang = external_scripting_languages[++i]) + +/* Iterate over all external scripting languages that are supported. */ +#define ALL_ENABLED_EXT_SCRIPTING_LANGUAGES(i, slang) \ + for (/*int*/ i = 0, slang = external_scripting_languages[0]; \ + slang != NULL; \ + slang = external_scripting_languages[++i]) \ + if (slang->ops != NULL) + +static script_sourcer_func source_gdb_script; +static objfile_script_sourcer_func source_gdb_objfile_script; + +/* GDB's own scripting language. + This exists, in part, to support auto-loading ${prog}-gdb.gdb scripts. */ + +static const struct script_language_script_ops script_lang_gdb_script_ops = +{ + source_gdb_script, + source_gdb_objfile_script, + auto_load_gdb_scripts_enabled +}; + +const struct script_language_defn script_language_gdb = +{ + SCRIPT_LANG_GDB, + "gdb", + "GDB", + + /* We fall back to interpreting a script as a GDB script if it doesn't + match the other scripting languages, but for consistency's sake + give it a formal suffix. */ + ".gdb", + "-gdb.gdb", + + /* cli_control_type: This is never used: GDB's own scripting language + has a variety of control types (if, while, etc.). */ + commands_control, + + &script_lang_gdb_script_ops, + + /* The rest of the scripting interface isn't supported by GDB's own + scripting language. */ + NULL +}; + +/* Table of all external (non-native) scripting languages. */ + +static const struct script_language_defn * const + external_scripting_languages[] = +{ + &script_language_python, + NULL +}; + +/* Methods for GDB's own scripting language. */ + +/* The script_language_script_ops.script_sourcer "method". */ + +static void +source_gdb_script (const struct script_language_defn *slang, + FILE *stream, const char *file) +{ + script_from_file (stream, file); +} + +/* The script_language_script_ops.objfile_script_sourcer "method". */ + +static void +source_gdb_objfile_script (const struct script_language_defn *slang, + struct objfile *objfile, + FILE *stream, const char *file) +{ + script_from_file (stream, file); +} + +/* Accessors for "public" attributes of struct script_language. + + IWBN if we could use slang_foo here and elsewhere, but we can't for fear of + confusing someone into thinking we might be referring to the Slang + programming language. */ + +/* Return the "name" field of SLANG. */ + +const char * +script_lang_name (const struct script_language_defn *slang) +{ + return slang->name; +} + +/* Return the "capitalized_name" field of SLANG. */ + +const char * +script_lang_capitalized_name (const struct script_language_defn *slang) +{ + return slang->capitalized_name; +} + +/* Return the "suffix" field of SLANG. */ + +const char * +script_lang_suffix (const struct script_language_defn *slang) +{ + return slang->suffix; +} + +/* Return the "auto_load_suffix" field of SLANG. */ + +const char * +script_lang_auto_load_suffix (const struct script_language_defn *slang) +{ + return slang->auto_load_suffix; +} + +/* script_language_script_ops wrappers. */ + +static void +throw_unsupported (const struct script_language_defn *slang) +{ + throw_error (UNSUPPORTED_ERROR, + _("Scripting in the \"%s\" language is not supported" + " in this copy of GDB."), + slang->capitalized_name); +} + +/* Throw UNSUPPORTED_ERROR if called. + This is used to implement script_ext_{soft,hard}. */ + +static void +source_script_unsupported (const struct script_language_defn *slang, + FILE *stream, const char *file) +{ + throw_unsupported (slang); +} + +/* Return TRUE if FILE has extension EXTENSION. */ + +static int +has_extension (const char *file, const char *extension) +{ + int file_len = strlen (file); + int extension_len = strlen (extension); + + return (file_len > extension_len + && strcmp (&file[file_len - extension_len], extension) == 0); +} + +/* Return a function to load FILE. + If FILE specifies a scripting language we support then the script language + definition is stored in *SLANG_PTR. + If FILE specifies a scripting language we support but which is not + enabled then return a function that throws UNSUPPORTED_ERROR. + Otherwise return NULL. + + Note: This could be a lot cleaner if not for script_ext_soft. */ + +script_sourcer_func * +get_script_sourcer (const char *file, + const struct script_language_defn **slang_ptr) +{ + int i; + const struct script_language_defn *slang; + + *slang_ptr = NULL; + + ALL_EXT_SCRIPTING_LANGUAGES (i, slang) + { + if (has_extension (file, slang->suffix)) + { + script_sourcer_func *func = script_lang_sourcer (slang); + + *slang_ptr = slang; + if (func != NULL) + return func; + return source_script_unsupported; + } + } + + return NULL; +} + +/* Return the script "sourcer" function for SLANG. + This is the function that loads and processes a script. */ + +script_sourcer_func * +script_lang_sourcer (const struct script_language_defn *slang) +{ + if (slang->script_ops == NULL) + return NULL; + return slang->script_ops->script_sourcer; +} + +/* Return the objfile script "sourcer" function for SLANG. + This is the function that loads and processes a script for a particular + objfile. */ + +objfile_script_sourcer_func * +script_lang_objfile_sourcer (const struct script_language_defn *slang) +{ + if (slang->script_ops == NULL) + return NULL; + return slang->script_ops->objfile_script_sourcer; +} + +/* Return non-zero if auto-loading of SLANG scripts is enabled. */ + +int +script_lang_auto_load_enabled (const struct script_language_defn *slang) +{ + if (slang->script_ops == NULL) + return 0; + return slang->script_ops->auto_load_enabled (slang); +} + +/* Functions that iterate over all (external) scripting languages. */ + +/* Wrapper to call the script_language_ops.finish_initialization "method" + for each compiled-in scripting language. */ + +void +finish_script_initialization (void) +{ + int i; + const struct script_language_defn *slang; + + ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang) + { + if (slang->ops->finish_initialization != NULL) + slang->ops->finish_initialization (slang); + } +} + +/* Return the scripting language specified by CMD. + Note the difference between this function and + eval_script_from_control_command is that we loop on + ALL_EXT_SCRIPTING_LANGUAGES whereas the latter loops on + ALL_ENABLED_EXT_SCRIPTING_LANGUAGES. */ + +static const struct script_language_defn * +script_lang_from_control_command (struct command_line *cmd) +{ + int i; + const struct script_language_defn *slang; + + ALL_EXT_SCRIPTING_LANGUAGES (i, slang) + { + if (slang->cli_control_type == cmd->control_type) + return slang; + } + + gdb_assert_not_reached ("invalid scripting language in cli command"); +} + +/* Evaluate the commands in CMD, which specifies a sequence of commands + in an external scripting language. */ + +void +eval_script_from_control_command (struct command_line *cmd) +{ + int i; + const struct script_language_defn *slang; + const char *script_lang_name; + + ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang) + { + if (slang->cli_control_type == cmd->control_type + && slang->ops->eval_from_control_command != NULL) + { + slang->ops->eval_from_control_command (slang, cmd); + return; + } + } + + /* The requested scripting language is not supported in this GDB. */ + throw_unsupported (script_lang_from_control_command (cmd)); +} + +/* Load scripts for OBJFILE written in external languages. */ + +void +auto_load_scripts_for_objfile (struct objfile *objfile) +{ + int i; + const struct script_language_defn *slang; + + slang = &script_language_gdb; + if (script_lang_auto_load_enabled (slang)) + auto_load_objfile_script (objfile, slang); + + ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang) + { + if (script_lang_auto_load_enabled (slang)) + auto_load_objfile_script (objfile, slang); + } +} + +/* Interface to type pretty-printers implemented in an external + scripting language. */ + +/* Call this at the start when preparing to pretty-print a type. + The result is a pointer to an opaque object (to the caller) to be passed + to apply_script_type_printers and free_script_type_printers. */ + +struct script_type_printers * +start_script_type_printers (void) +{ + struct script_type_printers *printers + = XZALLOC (struct script_type_printers); + int i; + const struct script_language_defn *slang; + + ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang) + { + if (slang->ops->start_type_printers != NULL) + slang->ops->start_type_printers (slang, printers); + } + + return printers; +} + +/* Iteratively try the type pretty-printers specified by PRINTERS, + returning the result of the first one that succeeds. If no printer + succeeds then NULL is returned. */ + +char * +apply_script_type_printers (struct script_type_printers *printers, + struct type *type) +{ + int i; + const struct script_language_defn *slang; + + ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang) + { + char *result = NULL; + + if (slang->ops->apply_type_printers != NULL) + result = slang->ops->apply_type_printers (slang, printers, type); + + if (result != NULL) + return result; + } + + return NULL; +} + +/* Call this after pretty-printing a type to release all memory held + by PRINTERS. */ + +void +free_script_type_printers (struct script_type_printers *printers) +{ + int i; + const struct script_language_defn *slang; + + ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang) + { + if (slang->ops->free_type_printers != NULL) + slang->ops->free_type_printers (slang, printers); + } + + xfree (printers); +} + +/* Try to pretty-print a value of type TYPE located at VALADDR + + EMBEDDED_OFFSET, which came from the inferior at address ADDRESS + + EMBEDDED_OFFSET, onto stdio stream STREAM according to OPTIONS. + VAL is the whole object that came from ADDRESS. VALADDR must point to + the head of VAL's contents buffer. + Returns non-zero if the value was successfully pretty-printed. */ + +int +apply_val_script_pretty_printer (struct type *type, const gdb_byte *valaddr, + int embedded_offset, CORE_ADDR address, + struct ui_file *stream, int recurse, + const struct value *val, + const struct value_print_options *options, + const struct language_defn *language) +{ + int i; + const struct script_language_defn *slang; + + ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang) + { + if (slang->ops->apply_val_pretty_printer (slang, type, valaddr, + embedded_offset, address, + stream, recurse, val, + options, language)) + return 1; + } + + return 0; +} + +/* GDB access to the "frame filter" feature. + FRAME is the source frame to start frame-filter invocation. FLAGS is an + integer holding the flags for printing. The following elements of + the FRAME_FILTER_FLAGS enum denotes the make-up of FLAGS: + PRINT_LEVEL is a flag indicating whether to print the frame's + relative level in the output. PRINT_FRAME_INFO is a flag that + indicates whether this function should print the frame + information, PRINT_ARGS is a flag that indicates whether to print + frame arguments, and PRINT_LOCALS, likewise, with frame local + variables. ARGS_TYPE is an enumerator describing the argument + format, OUT is the output stream to print. FRAME_LOW is the + beginning of the slice of frames to print, and FRAME_HIGH is the + upper limit of the frames to count. Returns SCR_BT_ERROR on error, + or SCR_BT_COMPLETED on success. */ + +enum script_bt_status +apply_script_frame_filter (struct frame_info *frame, int flags, + enum script_frame_args args_type, + struct ui_out *out, + int frame_low, int frame_high) +{ + int i; + const struct script_language_defn *slang; + + ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang) + { + enum script_bt_status status; + + if (slang->ops->apply_frame_filter == NULL) + continue; + status = slang->ops->apply_frame_filter (slang, frame, flags, + args_type, out, + frame_low, frame_high); + /* We use the filters from the first scripting language that has + applicable filters. */ + if (status != SCR_BT_NO_FILTERS) + return status; + } + + return SCR_BT_NO_FILTERS; +} + +/* Update values held by the scripting language when OBJFILE is discarded. + New global types must be created for every such value, which must then be + updated to use the new types. + The function typically just iterates over all appropriate values and + calls preserve_one_value for each one. + COPIED_TYPES is used to prevent cycles / duplicates and is passed to + preserve_one_value. */ + +void +preserve_script_values (struct objfile *objfile, htab_t copied_types) +{ + int i; + const struct script_language_defn *slang; + + ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang) + { + if (slang->ops->preserve_values != NULL) + slang->ops->preserve_values (slang, objfile, copied_types); + } +} + +/* Return non-zero if there is a stop condition for the breakpoint. + If SKIP_LANG is not SCRIPT_LANG_NONE, skip checking this language. + This is for the case where we're setting a new condition: Only one + condition is allowed, so when setting a condition for any particular + scripting language, we need to check if any other already has a + condition set. */ + +int +breakpoint_has_script_cond (struct breakpoint *b, + enum script_language skip_lang) +{ + int i; + const struct script_language_defn *slang; + + ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang) + { + if (slang->language != skip_lang + && slang->ops->breakpoint_has_cond != NULL + && slang->ops->breakpoint_has_cond (slang, b)) + return 1; + } + + return 0; +} + +/* Return whether a stop condition for breakpoint B says to stop. + True is also returned if there is no stop condition for B. */ + +int +breakpoint_script_cond_says_stop (struct breakpoint *b) +{ + int i; + const struct script_language_defn *slang; + enum scr_bp_stop stop = SCR_BP_STOP_UNSET; + + ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang) + { + /* There is a rule that a breakpoint can have at most one of any of a + CLI or script language condition. However, Python hacks in "finish + breakpoints" on top of the "stop" check, so we have to call this for + every language, even if we could first determine whether a "stop" + method exists. */ + if (slang->ops->breakpoint_cond_says_stop != NULL) + { + enum scr_bp_stop this_stop + = slang->ops->breakpoint_cond_says_stop (slang, b); + + if (this_stop != SCR_BP_STOP_UNSET) + { + /* Even though we have to check every scripting language, only + one of them can return yes/no (because only one of them + can have a "stop" condition. */ + gdb_assert (stop == SCR_BP_STOP_UNSET); + stop = this_stop; + } + } + } + + return stop == SCR_BP_STOP_NO ? 0 : 1; +} + +/* ^C/SIGINT support. + This requires cooperation with the scripting languages so the support + is defined here. + The prototypes for these are in defs.h. */ + +/* Nonzero means a quit has been requested. + This flag tracks quit requests but it's only used if the scripting language + doesn't provide the necessary support. */ +static int quit_flag; + +/* Clear the quit flag. */ + +void +clear_quit_flag (void) +{ + int i; + const struct script_language_defn *slang; + + ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang) + { + if (slang->ops->clear_quit_flag != NULL) + slang->ops->clear_quit_flag (slang); + } + + quit_flag = 0; +} + +/* Set the quit flag. */ + +void +set_quit_flag (void) +{ + int i; + const struct script_language_defn *slang; + + ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang) + { + if (slang->ops->set_quit_flag != NULL) + slang->ops->set_quit_flag (slang); + } + + quit_flag = 1; +} + +/* Return true if the quit flag has been set, false otherwise. + Scripting languages may need their own control over whether SIGINT has + been seen. */ + +int +check_quit_flag (void) +{ + int i, result = 0; + const struct script_language_defn *slang; + + ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang) + { + if (slang->ops->check_quit_flag != NULL) + if (slang->ops->check_quit_flag (slang) != 0) + result = 1; + } + + /* This is written in a particular way to avoid races. */ + if (quit_flag) + { + quit_flag = 0; + result = 1; + } + + return result; +} diff --git a/gdb/scripting.h b/gdb/scripting.h new file mode 100644 index 0000000..4307bb0 --- /dev/null +++ b/gdb/scripting.h @@ -0,0 +1,204 @@ +/* Interface between gdb and its scripting languages. + + Copyright (C) 2013 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 . */ + +#ifndef SCRIPTING_H +#define SCRIPTING_H + +#include "mi/mi-cmds.h" /* For PRINT_NO_VALUES, etc. */ + +struct breakpoint; +struct command_line; +struct frame_info; +struct language_defn; +struct objfile; +struct script_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 script_language_defn *, + FILE *, const char *); + +/* 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 script_language_defn *, + struct objfile *, + FILE *, const char *); + +/* Enum of each scripting language. */ + +enum script_language + { + SCRIPT_LANG_NONE, + SCRIPT_LANG_GDB, + SCRIPT_LANG_PYTHON + }; + +/* Script frame-filter status return values. */ + +enum script_bt_status + { + /* Return when an error has occurred in processing frame filters, + or when printing the stack. */ + SCR_BT_ERROR = -1, + + /* Return from internal routines to indicate that the function + succeeded. */ + SCR_BT_OK = 1, + + /* Return when the frame filter process is complete, and all + operations have succeeded. */ + SCR_BT_COMPLETED = 2, + + /* Return when the frame filter process is complete, but there + were no filter registered and enabled to process. */ + SCR_BT_NO_FILTERS = 3 + }; + +/* Flags to pass to apply_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 script_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 script_language_ops.breakpoint_cond_says_stop. */ + +enum scr_bp_stop + { + /* No "stop" condition is set. */ + SCR_BP_STOP_UNSET, + + /* A "stop" condition is set, and it says "don't stop". */ + SCR_BP_STOP_NO, + + /* A "stop" condition is set, and it says "stop". */ + SCR_BP_STOP_YES + }; + +/* Table of type printers associated with the global typedef table. */ + +struct script_type_printers +{ + /* Type-printers from Python. */ + void *py_type_printers; +}; + +/* The interface for gdb's own scripting language. */ +extern const struct script_language_defn script_language_gdb; + +/* Accessors for "public" attributes of the scripting language definition. */ + +extern enum script_language script_lang_kind + (const struct script_language_defn *); + +extern const char *script_lang_name (const struct script_language_defn *); + +extern const char *script_lang_capitalized_name + (const struct script_language_defn *); + +extern const char *script_lang_suffix (const struct script_language_defn *); + +extern const char *script_lang_auto_load_suffix + (const struct script_language_defn *); + +extern script_sourcer_func *script_lang_sourcer + (const struct script_language_defn *); + +extern objfile_script_sourcer_func *script_lang_objfile_sourcer + (const struct script_language_defn *); + +extern int script_lang_auto_load_enabled (const struct script_language_defn *); + +/* Return the function that can load(source) FILE. */ +extern script_sourcer_func *get_script_sourcer + (const char *file, const struct script_language_defn **slang_ptr); + +/* Wrappers for each scripting API function that iterate over all + (external) scripting languages. */ + +extern void finish_script_initialization (void); + +extern void eval_script_from_control_command (struct command_line *cmd); + +extern void auto_load_scripts_for_objfile (struct objfile *); + +extern struct script_type_printers *start_script_type_printers (void); + +extern char *apply_script_type_printers (struct script_type_printers *, + struct type *); + +extern void free_script_type_printers (struct script_type_printers *); + +extern int apply_val_script_pretty_printer + (struct type *type, const gdb_byte *valaddr, + int embedded_offset, CORE_ADDR address, + struct ui_file *stream, int recurse, + const struct value *val, const struct value_print_options *options, + const struct language_defn *language); + +extern enum script_bt_status apply_script_frame_filter + (struct frame_info *frame, int flags, enum script_frame_args args_type, + struct ui_out *out, int frame_low, int frame_high); + +extern void preserve_script_values (struct objfile *, htab_t copied_types); + +extern int breakpoint_has_script_cond (struct breakpoint *b, + enum script_language skip_lang); + +extern int breakpoint_script_cond_says_stop (struct breakpoint *); + +#endif /* SCRIPTING_H */