X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fpython%2Fpython.c;h=c46d68b73ed56f50303fe1162cd384ad5a8e68f2;hb=edeaceda7b2f33b2c3bf78c732e67f3188e7f0b9;hp=03ea5d5286cfb047158fa0eafa5109295d8c9653;hpb=95a6b0a106fac6ea35670421534d461a3663c0ba;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/python/python.c b/gdb/python/python.c index 03ea5d5286..c46d68b73e 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -1,6 +1,6 @@ /* General python/gdb code - Copyright (C) 2008-2017 Free Software Foundation, Inc. + Copyright (C) 2008-2021 Free Software Foundation, Inc. This file is part of GDB. @@ -27,15 +27,14 @@ #include "objfiles.h" #include "value.h" #include "language.h" -#include "event-loop.h" -#include "serial.h" +#include "gdbsupport/event-loop.h" #include "readline/tilde.h" #include "python.h" #include "extension-priv.h" #include "cli/cli-utils.h" #include #include "location.h" -#include "ser-event.h" +#include "run-on-main-thread.h" /* Declared constants and enum for python stack printing. */ static const char python_excp_none[] = "none"; @@ -90,16 +89,14 @@ const struct extension_language_defn extension_language_python = #include "cli/cli-decode.h" #include "charset.h" #include "top.h" -#include "solib.h" #include "python-internal.h" #include "linespec.h" #include "source.h" -#include "version.h" +#include "gdbsupport/version.h" #include "target.h" #include "gdbthread.h" #include "interps.h" #include "event-top.h" -#include "py-ref.h" #include "py-event.h" /* True if Python has been successfully initialized, false @@ -109,10 +106,6 @@ int gdb_python_initialized; extern PyMethodDef python_GdbMethods[]; -#ifdef IS_PY3K -extern struct PyModuleDef python_GdbModuleDef; -#endif - PyObject *gdb_module; PyObject *gdb_python_module; @@ -136,8 +129,7 @@ PyObject *gdbpy_gdb_memory_error; static script_sourcer_func gdbpy_source_script; static objfile_script_sourcer_func gdbpy_source_objfile_script; static objfile_script_executor_func gdbpy_execute_objfile_script; -static void gdbpy_finish_initialization - (const struct extension_language_defn *); +static void gdbpy_initialize (const struct extension_language_defn *); static int gdbpy_initialized (const struct extension_language_defn *); static void gdbpy_eval_from_control_command (const struct extension_language_defn *, struct command_line *cmd); @@ -152,6 +144,8 @@ static void gdbpy_set_quit_flag (const struct extension_language_defn *); static int gdbpy_check_quit_flag (const struct extension_language_defn *); static enum ext_lang_rc gdbpy_before_prompt_hook (const struct extension_language_defn *, const char *current_gdb_prompt); +static gdb::optional gdbpy_colorize + (const std::string &filename, const std::string &contents); /* The interface between gdb proper and loading of python scripts. */ @@ -167,7 +161,7 @@ const struct extension_language_script_ops python_extension_script_ops = const struct extension_language_ops python_extension_ops = { - gdbpy_finish_initialization, + gdbpy_initialize, gdbpy_initialized, gdbpy_eval_from_control_command, @@ -190,12 +184,9 @@ const struct extension_language_ops python_extension_ops = gdbpy_before_prompt_hook, - gdbpy_clone_xmethod_worker_data, - gdbpy_free_xmethod_worker_data, gdbpy_get_matching_xmethod_workers, - gdbpy_get_xmethod_arg_types, - gdbpy_get_xmethod_result_type, - gdbpy_invoke_xmethod + + gdbpy_colorize, }; /* Architecture and language to be used in callbacks from @@ -220,7 +211,7 @@ gdbpy_enter::gdbpy_enter (struct gdbarch *gdbarch, python_language = language; /* Save it and ensure ! PyErr_Occurred () afterwards. */ - PyErr_Fetch (&m_error_type, &m_error_value, &m_error_traceback); + m_error.emplace (); } gdbpy_enter::~gdbpy_enter () @@ -233,15 +224,39 @@ gdbpy_enter::~gdbpy_enter () warning (_("internal error: Unhandled Python exception")); } - PyErr_Restore (m_error_type, m_error_value, m_error_traceback); + m_error->restore (); - PyGILState_Release (m_state); python_gdbarch = m_gdbarch; python_language = m_language; restore_active_ext_lang (m_previous_active); + PyGILState_Release (m_state); } +/* A helper class to save and restore the GIL, but without touching + the other globals that are handled by gdbpy_enter. */ + +class gdbpy_gil +{ +public: + + gdbpy_gil () + : m_state (PyGILState_Ensure ()) + { + } + + ~gdbpy_gil () + { + PyGILState_Release (m_state); + } + + DISABLE_COPY_AND_ASSIGN (gdbpy_gil); + +private: + + PyGILState_STATE m_state; +}; + /* Set the quit flag. */ static void @@ -255,6 +270,10 @@ gdbpy_set_quit_flag (const struct extension_language_defn *extlang) static int gdbpy_check_quit_flag (const struct extension_language_defn *extlang) { + if (!gdb_python_initialized) + return 0; + + gdbpy_gil gil; return PyOS_InterruptOccurred (); } @@ -302,14 +321,8 @@ python_interactive_command (const char *arg, int from_tty) if (arg && *arg) { - int len = strlen (arg); - char *script = (char *) xmalloc (len + 2); - - strcpy (script, arg); - script[len] = '\n'; - script[len + 1] = '\0'; - err = eval_python_command (script); - xfree (script); + std::string script = std::string (arg) + "\n"; + err = eval_python_command (script.c_str ()); } else { @@ -336,9 +349,8 @@ python_interactive_command (const char *arg, int from_tty) A FILE * from one runtime does not necessarily operate correctly in the other runtime. - To work around this potential issue, we create on Windows hosts the - FILE object using Python routines, thus making sure that it is - compatible with the Python library. */ + To work around this potential issue, we run code in Python to load + the script. */ static void python_run_simple_file (FILE *file, const char *filename) @@ -352,15 +364,21 @@ python_run_simple_file (FILE *file, const char *filename) /* Because we have a string for a filename, and are using Python to open the file, we need to expand any tilde in the path first. */ gdb::unique_xmalloc_ptr full_path (tilde_expand (filename)); - gdbpy_ref<> python_file (PyFile_FromString (full_path.get (), (char *) "r")); - if (python_file == NULL) + + if (gdb_python_module == nullptr + || ! PyObject_HasAttrString (gdb_python_module, "_execute_file")) + error (_("Installation error: gdb._execute_file function is missing")); + + gdbpy_ref<> return_value + (PyObject_CallMethod (gdb_python_module, "_execute_file", "s", + full_path.get ())); + if (return_value == nullptr) { - gdbpy_print_stack (); - error (_("Error while opening file: %s"), full_path.get ()); + /* Use PyErr_PrintEx instead of gdbpy_print_stack to better match the + behavior of the non-Windows codepath. */ + PyErr_PrintEx(0); } - PyRun_SimpleFile (PyFile_AsFile (python_file.get ()), filename); - #endif /* _WIN32 */ } @@ -390,12 +408,12 @@ gdbpy_eval_from_control_command (const struct extension_language_defn *extlang, { int ret; - if (cmd->body_count != 1) + if (cmd->body_list_1 != nullptr) error (_("Invalid \"python\" block structure.")); gdbpy_enter enter_py (get_current_arch (), current_language); - std::string script = compute_python_string (cmd->body_list[0]); + std::string script = compute_python_string (cmd->body_list_0.get ()); ret = PyRun_SimpleString (script.c_str ()); if (ret) error (_("Error while executing Python code.")); @@ -418,7 +436,7 @@ python_command (const char *arg, int from_tty) } else { - command_line_up l = get_command_line (python_control, ""); + counted_command_line l = get_command_line (python_control, ""); execute_control_command_untraced (l.get ()); } @@ -444,12 +462,12 @@ gdbpy_parameter_value (enum var_types type, void *var) if (! str) str = ""; - return host_string_to_python_string (str); + return host_string_to_python_string (str).release (); } case var_boolean: { - if (* (int *) var) + if (* (bool *) var) Py_RETURN_TRUE; else Py_RETURN_FALSE; @@ -472,7 +490,8 @@ gdbpy_parameter_value (enum var_types type, void *var) Py_RETURN_NONE; /* Fall through. */ case var_zinteger: - return PyLong_FromLong (* (int *) var); + case var_zuinteger_unlimited: + return gdb_py_object_from_longest (* (int *) var).release (); case var_uinteger: { @@ -480,7 +499,13 @@ gdbpy_parameter_value (enum var_types type, void *var) if (val == UINT_MAX) Py_RETURN_NONE; - return PyLong_FromUnsignedLong (val); + return gdb_py_object_from_ulongest (val).release (); + } + + case var_zuinteger: + { + unsigned int val = * (unsigned int *) var; + return gdb_py_object_from_ulongest (val).release (); } } @@ -494,29 +519,24 @@ gdbpy_parameter_value (enum var_types type, void *var) static PyObject * gdbpy_parameter (PyObject *self, PyObject *args) { - struct gdb_exception except = exception_none; struct cmd_list_element *alias, *prefix, *cmd; const char *arg; - char *newarg; int found = -1; if (! PyArg_ParseTuple (args, "s", &arg)) return NULL; - newarg = concat ("show ", arg, (char *) NULL); + std::string newarg = std::string ("show ") + arg; - TRY + try { - found = lookup_cmd_composition (newarg, &alias, &prefix, &cmd); + found = lookup_cmd_composition (newarg.c_str (), &alias, &prefix, &cmd); } - CATCH (ex, RETURN_MASK_ALL) + catch (const gdb_exception &ex) { - except = ex; + GDB_PY_HANDLE_EXCEPTION (ex); } - END_CATCH - xfree (newarg); - GDB_PY_HANDLE_EXCEPTION (except); if (!found) return PyErr_Format (PyExc_RuntimeError, _("Could not find parameter `%s'."), arg); @@ -582,62 +602,232 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw) std::string to_string_res; - TRY + scoped_restore preventer = prevent_dont_repeat (); + + try { + gdbpy_allow_threads allow_threads; + struct interp *interp; - scoped_restore save_async = make_scoped_restore (¤t_ui->async, 0); + std::string arg_copy = arg; + bool first = true; + char *save_ptr = nullptr; + auto reader + = [&] () + { + const char *result = strtok_r (first ? &arg_copy[0] : nullptr, + "\n", &save_ptr); + first = false; + return result; + }; - scoped_restore save_uiout = make_scoped_restore (¤t_uiout); + counted_command_line lines = read_command_lines_1 (reader, 1, nullptr); - /* Use the console interpreter uiout to have the same print format - for console or MI. */ - interp = interp_lookup (current_ui, "console"); - current_uiout = interp_ui_out (interp); + { + scoped_restore save_async = make_scoped_restore (¤t_ui->async, + 0); - scoped_restore preventer = prevent_dont_repeat (); - if (to_string) - to_string_res = execute_command_to_string (arg, from_tty); - else - execute_command (arg, from_tty); + scoped_restore save_uiout = make_scoped_restore (¤t_uiout); + + /* Use the console interpreter uiout to have the same print format + for console or MI. */ + interp = interp_lookup (current_ui, "console"); + current_uiout = interp->interp_ui_out (); + + if (to_string) + to_string_res = execute_control_commands_to_string (lines.get (), + from_tty); + else + execute_control_commands (lines.get (), from_tty); + } + + /* Do any commands attached to breakpoint we stopped at. */ + bpstat_do_actions (); } - CATCH (except, RETURN_MASK_ALL) + catch (const gdb_exception &except) { + /* If an exception occurred then we won't hit normal_stop (), or have + an exception reach the top level of the event loop, which are the + two usual places in which stdin would be re-enabled. So, before we + convert the exception and continue back in Python, we should + re-enable stdin here. */ + async_enable_stdin (); GDB_PY_HANDLE_EXCEPTION (except); } - END_CATCH - - /* Do any commands attached to breakpoint we stopped at. */ - bpstat_do_actions (); if (to_string) return PyString_FromString (to_string_res.c_str ()); Py_RETURN_NONE; } -/* Implementation of gdb.solib_name (Long) -> String. - Returns the name of the shared library holding a given address, or None. */ +/* Implementation of Python rbreak command. Take a REGEX and + optionally a MINSYMS, THROTTLE and SYMTABS keyword and return a + Python list that contains newly set breakpoints that match that + criteria. REGEX refers to a GDB format standard regex pattern of + symbols names to search; MINSYMS is an optional boolean (default + False) that indicates if the function should search GDB's minimal + symbols; THROTTLE is an optional integer (default unlimited) that + indicates the maximum amount of breakpoints allowable before the + function exits (note, if the throttle bound is passed, no + breakpoints will be set and a runtime error returned); SYMTABS is + an optional Python iterable that contains a set of gdb.Symtabs to + constrain the search within. */ static PyObject * -gdbpy_solib_name (PyObject *self, PyObject *args) +gdbpy_rbreak (PyObject *self, PyObject *args, PyObject *kw) { - char *soname; - PyObject *str_obj; - gdb_py_ulongest pc; - - if (!PyArg_ParseTuple (args, GDB_PY_LLU_ARG, &pc)) + char *regex = NULL; + std::vector symbols; + unsigned long count = 0; + PyObject *symtab_list = NULL; + PyObject *minsyms_p_obj = NULL; + int minsyms_p = 0; + unsigned int throttle = 0; + static const char *keywords[] = {"regex","minsyms", "throttle", + "symtabs", NULL}; + + if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s|O!IO", keywords, + ®ex, &PyBool_Type, + &minsyms_p_obj, &throttle, + &symtab_list)) return NULL; - soname = solib_name_from_address (current_program_space, pc); - if (soname) - str_obj = host_string_to_python_string (soname); - else + /* Parse minsyms keyword. */ + if (minsyms_p_obj != NULL) { - str_obj = Py_None; - Py_INCREF (Py_None); + int cmp = PyObject_IsTrue (minsyms_p_obj); + if (cmp < 0) + return NULL; + minsyms_p = cmp; } - return str_obj; + global_symbol_searcher spec (FUNCTIONS_DOMAIN, regex); + SCOPE_EXIT { + for (const char *elem : spec.filenames) + xfree ((void *) elem); + }; + + /* The "symtabs" keyword is any Python iterable object that returns + a gdb.Symtab on each iteration. If specified, iterate through + the provided gdb.Symtabs and extract their full path. As + python_string_to_target_string returns a + gdb::unique_xmalloc_ptr and a vector containing these types + cannot be coerced to a const char **p[] via the vector.data call, + release the value from the unique_xmalloc_ptr and place it in a + simple type symtab_list_type (which holds the vector and a + destructor that frees the contents of the allocated strings. */ + if (symtab_list != NULL) + { + gdbpy_ref<> iter (PyObject_GetIter (symtab_list)); + + if (iter == NULL) + return NULL; + + while (true) + { + gdbpy_ref<> next (PyIter_Next (iter.get ())); + + if (next == NULL) + { + if (PyErr_Occurred ()) + return NULL; + break; + } + + gdbpy_ref<> obj_name (PyObject_GetAttrString (next.get (), + "filename")); + + if (obj_name == NULL) + return NULL; + + /* Is the object file still valid? */ + if (obj_name == Py_None) + continue; + + gdb::unique_xmalloc_ptr filename = + python_string_to_target_string (obj_name.get ()); + + if (filename == NULL) + return NULL; + + /* Make sure there is a definite place to store the value of + filename before it is released. */ + spec.filenames.push_back (nullptr); + spec.filenames.back () = filename.release (); + } + } + + /* The search spec. */ + symbols = spec.search (); + + /* Count the number of symbols (both symbols and optionally minimal + symbols) so we can correctly check the throttle limit. */ + for (const symbol_search &p : symbols) + { + /* Minimal symbols included? */ + if (minsyms_p) + { + if (p.msymbol.minsym != NULL) + count++; + } + + if (p.symbol != NULL) + count++; + } + + /* Check throttle bounds and exit if in excess. */ + if (throttle != 0 && count > throttle) + { + PyErr_SetString (PyExc_RuntimeError, + _("Number of breakpoints exceeds throttled maximum.")); + return NULL; + } + + gdbpy_ref<> return_list (PyList_New (0)); + + if (return_list == NULL) + return NULL; + + /* Construct full path names for symbols and call the Python + breakpoint constructor on the resulting names. Be tolerant of + individual breakpoint failures. */ + for (const symbol_search &p : symbols) + { + std::string symbol_name; + + /* Skipping minimal symbols? */ + if (minsyms_p == 0) + if (p.msymbol.minsym != NULL) + continue; + + if (p.msymbol.minsym == NULL) + { + struct symtab *symtab = symbol_symtab (p.symbol); + const char *fullname = symtab_to_fullname (symtab); + + symbol_name = fullname; + symbol_name += ":"; + symbol_name += p.symbol->linkage_name (); + } + else + symbol_name = p.msymbol.minsym->linkage_name (); + + gdbpy_ref<> argList (Py_BuildValue("(s)", symbol_name.c_str ())); + gdbpy_ref<> obj (PyObject_CallObject ((PyObject *) + &breakpoint_object_type, + argList.get ())); + + /* Tolerate individual breakpoint failures. */ + if (obj == NULL) + gdbpy_print_stack (); + else + { + if (PyList_Append (return_list.get (), obj.get ()) == -1) + return NULL; + } + } + return return_list.release (); } /* A Python function which is a wrapper for decode_line_1. */ @@ -653,13 +843,23 @@ gdbpy_decode_line (PyObject *self, PyObject *args) if (! PyArg_ParseTuple (args, "|s", &arg)) return NULL; + /* Treat a string consisting of just whitespace the same as + NULL. */ if (arg != NULL) - location = string_to_event_location_basic (&arg, python_language); + { + arg = skip_spaces (arg); + if (*arg == '\0') + arg = NULL; + } + + if (arg != NULL) + location = string_to_event_location_basic (&arg, python_language, + symbol_name_match_type::WILD); std::vector decoded_sals; symtab_and_line def_sal; gdb::array_view sals; - TRY + try { if (location != NULL) { @@ -673,13 +873,12 @@ gdbpy_decode_line (PyObject *self, PyObject *args) sals = def_sal; } } - CATCH (ex, RETURN_MASK_ALL) + catch (const gdb_exception &ex) { /* We know this will always throw. */ gdbpy_convert_exception (ex); return NULL; } - END_CATCH if (!sals.empty ()) { @@ -696,10 +895,7 @@ gdbpy_decode_line (PyObject *self, PyObject *args) } } else - { - result.reset (Py_None); - Py_INCREF (Py_None); - } + result = gdbpy_ref<>::new_reference (Py_None); gdbpy_ref<> return_result (PyTuple_New (2)); if (return_result == NULL) @@ -712,10 +908,7 @@ gdbpy_decode_line (PyObject *self, PyObject *args) return NULL; } else - { - unparsed.reset (Py_None); - Py_INCREF (Py_None); - } + unparsed = gdbpy_ref<>::new_reference (Py_None); PyTuple_SetItem (return_result.get (), 0, unparsed.release ()); PyTuple_SetItem (return_result.get (), 1, result.release ()); @@ -733,49 +926,19 @@ gdbpy_parse_and_eval (PyObject *self, PyObject *args) if (!PyArg_ParseTuple (args, "s", &expr_str)) return NULL; - TRY + try { + gdbpy_allow_threads allow_threads; result = parse_and_eval (expr_str); } - CATCH (except, RETURN_MASK_ALL) + catch (const gdb_exception &except) { GDB_PY_HANDLE_EXCEPTION (except); } - END_CATCH return value_to_value_object (result); } -/* Implementation of gdb.find_pc_line function. - Returns the gdb.Symtab_and_line object corresponding to a PC value. */ - -static PyObject * -gdbpy_find_pc_line (PyObject *self, PyObject *args) -{ - gdb_py_ulongest pc_llu; - PyObject *result = NULL; /* init for gcc -Wall */ - - if (!PyArg_ParseTuple (args, GDB_PY_LLU_ARG, &pc_llu)) - return NULL; - - TRY - { - struct symtab_and_line sal; - CORE_ADDR pc; - - pc = (CORE_ADDR) pc_llu; - sal = find_pc_line (pc, 0); - result = symtab_and_line_to_sal_object (sal); - } - CATCH (except, RETURN_MASK_ALL) - { - GDB_PY_HANDLE_EXCEPTION (except); - } - END_CATCH - - return result; -} - /* Implementation of gdb.invalidate_cached_frames. */ static PyObject * @@ -806,61 +969,54 @@ gdbpy_source_script (const struct extension_language_defn *extlang, /* A single event. */ struct gdbpy_event { - /* The Python event. This is just a callable object. */ - PyObject *event; - /* The next event. */ - struct gdbpy_event *next; -}; + gdbpy_event (gdbpy_ref<> &&func) + : m_func (func.release ()) + { + } -/* All pending events. */ -static struct gdbpy_event *gdbpy_event_list; -/* The final link of the event list. */ -static struct gdbpy_event **gdbpy_event_list_end; + gdbpy_event (gdbpy_event &&other) noexcept + : m_func (other.m_func) + { + other.m_func = nullptr; + } -/* So that we can wake up the main thread even when it is blocked in - poll(). */ -static struct serial_event *gdbpy_serial_event; + gdbpy_event (const gdbpy_event &other) + : m_func (other.m_func) + { + gdbpy_gil gil; + Py_XINCREF (m_func); + } -/* The file handler callback. This reads from the internal pipe, and - then processes the Python event queue. This will always be run in - the main gdb thread. */ + ~gdbpy_event () + { + gdbpy_gil gil; + Py_XDECREF (m_func); + } -static void -gdbpy_run_events (int error, gdb_client_data client_data) -{ - gdbpy_enter enter_py (get_current_arch (), current_language); + gdbpy_event &operator= (const gdbpy_event &other) = delete; - /* Clear the event fd. Do this before flushing the events list, so - that any new event post afterwards is sure to re-awake the event - loop. */ - serial_event_clear (gdbpy_serial_event); + void operator() () + { + gdbpy_enter enter_py (get_current_arch (), current_language); - while (gdbpy_event_list) - { - /* Dispatching the event might push a new element onto the event - loop, so we update here "atomically enough". */ - struct gdbpy_event *item = gdbpy_event_list; - gdbpy_event_list = gdbpy_event_list->next; - if (gdbpy_event_list == NULL) - gdbpy_event_list_end = &gdbpy_event_list; - - /* Ignore errors. */ - gdbpy_ref<> call_result (PyObject_CallObject (item->event, NULL)); - if (call_result == NULL) - PyErr_Clear (); - - Py_DECREF (item->event); - xfree (item); - } -} + gdbpy_ref<> call_result (PyObject_CallObject (m_func, NULL)); + if (call_result == NULL) + gdbpy_print_stack (); + } + +private: + + /* The Python event. This is just a callable object. Note that + this is not a gdbpy_ref<>, because we have to take particular + care to only destroy the reference when holding the GIL. */ + PyObject *m_func; +}; /* Submit an event to the gdb thread. */ static PyObject * gdbpy_post_event (PyObject *self, PyObject *args) { - struct gdbpy_event *event; PyObject *func; - int wakeup; if (!PyArg_ParseTuple (args, "O", &func)) return NULL; @@ -872,38 +1028,13 @@ gdbpy_post_event (PyObject *self, PyObject *args) return NULL; } - Py_INCREF (func); - - /* From here until the end of the function, we have the GIL, so we - can operate on our global data structures without worrying. */ - wakeup = gdbpy_event_list == NULL; - - event = XNEW (struct gdbpy_event); - event->event = func; - event->next = NULL; - *gdbpy_event_list_end = event; - gdbpy_event_list_end = &event->next; - - /* Wake up gdb when needed. */ - if (wakeup) - serial_event_set (gdbpy_serial_event); + gdbpy_ref<> func_ref = gdbpy_ref<>::new_reference (func); + gdbpy_event event (std::move (func_ref)); + run_on_main_thread (event); Py_RETURN_NONE; } -/* Initialize the Python event handler. */ -static int -gdbpy_initialize_events (void) -{ - gdbpy_event_list_end = &gdbpy_event_list; - - gdbpy_serial_event = make_serial_event (); - add_file_handler (serial_event_fd (gdbpy_serial_event), - gdbpy_run_events, NULL); - - return 0; -} - /* This is the extension_language_ops.before_prompt "method". */ @@ -982,6 +1113,74 @@ gdbpy_before_prompt_hook (const struct extension_language_defn *extlang, return EXT_LANG_RC_NOP; } +/* This is the extension_language_ops.colorize "method". */ + +static gdb::optional +gdbpy_colorize (const std::string &filename, const std::string &contents) +{ + if (!gdb_python_initialized) + return {}; + + gdbpy_enter enter_py (get_current_arch (), current_language); + + if (gdb_python_module == nullptr + || !PyObject_HasAttrString (gdb_python_module, "colorize")) + return {}; + + gdbpy_ref<> hook (PyObject_GetAttrString (gdb_python_module, "colorize")); + if (hook == nullptr) + { + gdbpy_print_stack (); + return {}; + } + + if (!PyCallable_Check (hook.get ())) + return {}; + + gdbpy_ref<> fname_arg (PyString_FromString (filename.c_str ())); + if (fname_arg == nullptr) + { + gdbpy_print_stack (); + return {}; + } + gdbpy_ref<> contents_arg (PyString_FromString (contents.c_str ())); + if (contents_arg == nullptr) + { + gdbpy_print_stack (); + return {}; + } + + gdbpy_ref<> result (PyObject_CallFunctionObjArgs (hook.get (), + fname_arg.get (), + contents_arg.get (), + nullptr)); + if (result == nullptr) + { + gdbpy_print_stack (); + return {}; + } + + if (!gdbpy_is_string (result.get ())) + return {}; + + gdbpy_ref<> unic = python_string_to_unicode (result.get ()); + if (unic == nullptr) + { + gdbpy_print_stack (); + return {}; + } + gdbpy_ref<> host_str (PyUnicode_AsEncodedString (unic.get (), + host_charset (), + nullptr)); + if (host_str == nullptr) + { + gdbpy_print_stack (); + return {}; + } + + return std::string (PyBytes_AsString (host_str.get ())); +} + /* Printing. */ @@ -1001,29 +1200,28 @@ gdbpy_write (PyObject *self, PyObject *args, PyObject *kw) &stream_type)) return NULL; - TRY + try { switch (stream_type) - { - case 1: - { + { + case 1: + { fprintf_filtered (gdb_stderr, "%s", arg); break; - } - case 2: - { + } + case 2: + { fprintf_filtered (gdb_stdlog, "%s", arg); break; - } - default: - fprintf_filtered (gdb_stdout, "%s", arg); - } + } + default: + fprintf_filtered (gdb_stdout, "%s", arg); + } } - CATCH (except, RETURN_MASK_ALL) + catch (const gdb_exception &except) { GDB_PY_HANDLE_EXCEPTION (except); } - END_CATCH Py_RETURN_NONE; } @@ -1089,86 +1287,79 @@ gdbpy_print_stack (void) /* PyErr_Print doesn't necessarily end output with a newline. This works because Python's stdout/stderr is fed through printf_filtered. */ - TRY + try { begin_line (); } - CATCH (except, RETURN_MASK_ALL) + catch (const gdb_exception &except) { } - END_CATCH } /* Print "message", just error print message. */ else { - PyObject *ptype, *pvalue, *ptraceback; - - PyErr_Fetch (&ptype, &pvalue, &ptraceback); + gdbpy_err_fetch fetched_error; - /* Fetch the error message contained within ptype, pvalue. */ - gdb::unique_xmalloc_ptr - msg (gdbpy_exception_to_string (ptype, pvalue)); - gdb::unique_xmalloc_ptr type (gdbpy_obj_to_string (ptype)); + gdb::unique_xmalloc_ptr msg = fetched_error.to_string (); + gdb::unique_xmalloc_ptr type; + /* Don't compute TYPE if MSG already indicates that there is an + error. */ + if (msg != NULL) + type = fetched_error.type_to_string (); - TRY + try { - if (msg == NULL) + if (msg == NULL || type == NULL) { /* An error occurred computing the string representation of the error message. */ fprintf_filtered (gdb_stderr, _("Error occurred computing Python error" \ "message.\n")); + PyErr_Clear (); } else - fprintf_filtered (gdb_stderr, "Python Exception %s %s: \n", + fprintf_filtered (gdb_stderr, "Python Exception %s: %s\n", type.get (), msg.get ()); } - CATCH (except, RETURN_MASK_ALL) + catch (const gdb_exception &except) { } - END_CATCH - - Py_XDECREF (ptype); - Py_XDECREF (pvalue); - Py_XDECREF (ptraceback); } } - +/* Like gdbpy_print_stack, but if the exception is a + KeyboardException, throw a gdb "quit" instead. */ -/* Return the current Progspace. - There always is one. */ - -static PyObject * -gdbpy_get_current_progspace (PyObject *unused1, PyObject *unused2) +void +gdbpy_print_stack_or_quit () { - PyObject *result; - - result = pspace_to_pspace_object (current_program_space); - if (result) - Py_INCREF (result); - return result; + if (PyErr_ExceptionMatches (PyExc_KeyboardInterrupt)) + { + PyErr_Clear (); + throw_quit ("Quit"); + } + gdbpy_print_stack (); } + + /* Return a sequence holding all the Progspaces. */ static PyObject * gdbpy_progspaces (PyObject *unused1, PyObject *unused2) { - struct program_space *ps; - gdbpy_ref<> list (PyList_New (0)); if (list == NULL) return NULL; - ALL_PSPACES (ps) - { - PyObject *item = pspace_to_pspace_object (ps); + for (struct program_space *ps : program_spaces) + { + gdbpy_ref<> item = pspace_to_pspace_object (ps); - if (!item || PyList_Append (list.get (), item) == -1) - return NULL; - } + if (item == NULL || PyList_Append (list.get (), item.get ()) == -1) + return NULL; + } return list.release (); } @@ -1195,12 +1386,11 @@ gdbpy_source_objfile_script (const struct extension_language_defn *extlang, if (!gdb_python_initialized) return; - gdbpy_enter enter_py (get_objfile_arch (objfile), current_language); - gdbpy_current_objfile = objfile; + gdbpy_enter enter_py (objfile->arch (), current_language); + scoped_restore restire_current_objfile + = make_scoped_restore (&gdbpy_current_objfile, objfile); python_run_simple_file (file, filename); - - gdbpy_current_objfile = NULL; } /* Set the current objfile to OBJFILE and then execute SCRIPT @@ -1217,12 +1407,11 @@ gdbpy_execute_objfile_script (const struct extension_language_defn *extlang, if (!gdb_python_initialized) return; - gdbpy_enter enter_py (get_objfile_arch (objfile), current_language); - gdbpy_current_objfile = objfile; + gdbpy_enter enter_py (objfile->arch (), current_language); + scoped_restore restire_current_objfile + = make_scoped_restore (&gdbpy_current_objfile, objfile); PyRun_SimpleString (script); - - gdbpy_current_objfile = NULL; } /* Return the current Objfile, or None if there isn't one. */ @@ -1230,37 +1419,10 @@ gdbpy_execute_objfile_script (const struct extension_language_defn *extlang, static PyObject * gdbpy_get_current_objfile (PyObject *unused1, PyObject *unused2) { - PyObject *result; - if (! gdbpy_current_objfile) Py_RETURN_NONE; - result = objfile_to_objfile_object (gdbpy_current_objfile); - if (result) - Py_INCREF (result); - return result; -} - -/* Return a sequence holding all the Objfiles. */ - -static PyObject * -gdbpy_objfiles (PyObject *unused1, PyObject *unused2) -{ - struct objfile *objf; - - gdbpy_ref<> list (PyList_New (0)); - if (list == NULL) - return NULL; - - ALL_OBJFILES (objf) - { - PyObject *item = objfile_to_objfile_object (objf); - - if (!item || PyList_Append (list.get (), item) == -1) - return NULL; - } - - return list.release (); + return objfile_to_objfile_object (gdbpy_current_objfile).release (); } /* Compute the list of active python type printers and store them in @@ -1402,7 +1564,7 @@ python_interactive_command (const char *arg, int from_tty) error (_("Python scripting is not supported in this copy of GDB.")); else { - command_line_up l = get_command_line (python_control, ""); + counted_command_line l = get_command_line (python_control, ""); execute_control_command_untraced (l.get ()); } @@ -1416,30 +1578,87 @@ python_command (const char *arg, int from_tty) #endif /* HAVE_PYTHON */ - +/* When this is turned on before Python is initialised then Python will + ignore any environment variables related to Python. This is equivalent + to passing `-E' to the python program. */ +static bool python_ignore_environment = false; -/* Lists for 'set python' commands. */ +/* Implement 'show python ignore-environment'. */ -static struct cmd_list_element *user_set_python_list; -static struct cmd_list_element *user_show_python_list; +static void +show_python_ignore_environment (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("Python's ignore-environment setting is %s.\n"), + value); +} + +/* Implement 'set python ignore-environment'. This sets Python's internal + flag no matter when the command is issued, however, if this is used + after Py_Initialize has been called then most of the environment will + already have been read. */ + +static void +set_python_ignore_environment (const char *args, int from_tty, + struct cmd_list_element *c) +{ +#ifdef HAVE_PYTHON + Py_IgnoreEnvironmentFlag = python_ignore_environment ? 1 : 0; +#endif +} + +/* When this is turned on before Python is initialised then Python will + not write `.pyc' files on import of a module. */ +static enum auto_boolean python_dont_write_bytecode = AUTO_BOOLEAN_AUTO; -/* Function for use by 'set python' prefix command. */ +/* Implement 'show python dont-write-bytecode'. */ static void -user_set_python (const char *args, int from_tty) +show_python_dont_write_bytecode (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) { - help_list (user_set_python_list, "set python ", all_commands, - gdb_stdout); + if (python_dont_write_bytecode == AUTO_BOOLEAN_AUTO) + { + const char *auto_string + = (python_ignore_environment + || getenv ("PYTHONDONTWRITEBYTECODE") == nullptr) ? "off" : "on"; + + fprintf_filtered (file, + _("Python's dont-write-bytecode setting is %s (currently %s).\n"), + value, auto_string); + } + else + fprintf_filtered (file, _("Python's dont-write-bytecode setting is %s.\n"), + value); } -/* Function for use by 'show python' prefix command. */ +/* Implement 'set python dont-write-bytecode'. This sets Python's internal + flag no matter when the command is issued, however, if this is used + after Py_Initialize has been called then many modules could already + have been imported and their byte code written out. */ static void -user_show_python (const char *args, int from_tty) +set_python_dont_write_bytecode (const char *args, int from_tty, + struct cmd_list_element *c) { - cmd_show_list (user_show_python_list, from_tty, ""); +#ifdef HAVE_PYTHON + if (python_dont_write_bytecode == AUTO_BOOLEAN_AUTO) + Py_DontWriteBytecodeFlag + = (!python_ignore_environment + && getenv ("PYTHONDONTWRITEBYTECODE") != nullptr) ? 1 : 0; + else + Py_DontWriteBytecodeFlag + = python_dont_write_bytecode == AUTO_BOOLEAN_TRUE ? 1 : 0; +#endif /* HAVE_PYTHON */ } + + +/* Lists for 'set python' commands. */ + +static struct cmd_list_element *user_set_python_list; +static struct cmd_list_element *user_show_python_list; + /* Initialize the Python code. */ #ifdef HAVE_PYTHON @@ -1468,19 +1687,38 @@ finalize_python (void *ignore) Py_Finalize (); + gdb_python_initialized = false; restore_active_ext_lang (previous_active); } -static bool -do_start_initialization () -{ - char *progname; #ifdef IS_PY3K - int i; - size_t progsize, count; - wchar_t *progname_copy; +static struct PyModuleDef python_GdbModuleDef = +{ + PyModuleDef_HEAD_INIT, + "_gdb", + NULL, + -1, + python_GdbMethods, + NULL, + NULL, + NULL, + NULL +}; + +/* This is called via the PyImport_AppendInittab mechanism called + during initialization, to make the built-in _gdb module known to + Python. */ +PyMODINIT_FUNC init__gdb_module (void); +PyMODINIT_FUNC +init__gdb_module (void) +{ + return PyModule_Create (&python_GdbModuleDef); +} #endif +static bool +do_start_initialization () +{ #ifdef WITH_PYTHON_PATH /* Work around problem where python gets confused about where it is, and then can't find its libraries, etc. @@ -1488,19 +1726,24 @@ do_start_initialization () /foo/bin/python /foo/lib/pythonX.Y/... This must be done before calling Py_Initialize. */ - progname = concat (ldirname (python_libdir).c_str (), SLASH_STRING, "bin", - SLASH_STRING, "python", (char *) NULL); + gdb::unique_xmalloc_ptr progname + (concat (ldirname (python_libdir.c_str ()).c_str (), SLASH_STRING, "bin", + SLASH_STRING, "python", (char *) NULL)); #ifdef IS_PY3K + /* Python documentation indicates that the memory given + to Py_SetProgramName cannot be freed. However, it seems that + at least Python 3.7.4 Py_SetProgramName takes a copy of the + given program_name. Making progname_copy static and not release + the memory avoids a leak report for Python versions that duplicate + program_name, and respect the requirement of Py_SetProgramName + for Python versions that do not duplicate program_name. */ + static wchar_t *progname_copy; + std::string oldloc = setlocale (LC_ALL, NULL); setlocale (LC_ALL, ""); - progsize = strlen (progname); - progname_copy = (wchar_t *) PyMem_Malloc ((progsize + 1) * sizeof (wchar_t)); - if (!progname_copy) - { - fprintf (stderr, "out of memory\n"); - return false; - } - count = mbstowcs (progname_copy, progname, progsize + 1); + size_t progsize = strlen (progname.get ()); + progname_copy = XNEWVEC (wchar_t, progsize + 1); + size_t count = mbstowcs (progname_copy, progname.get (), progsize + 1); if (count == (size_t) -1) { fprintf (stderr, "Could not convert python path to string\n"); @@ -1512,30 +1755,34 @@ do_start_initialization () remain alive for the duration of the program's execution, so it is not freed after this call. */ Py_SetProgramName (progname_copy); + + /* Define _gdb as a built-in module. */ + PyImport_AppendInittab ("_gdb", init__gdb_module); #else - Py_SetProgramName (progname); + Py_SetProgramName (progname.release ()); #endif #endif Py_Initialize (); +#if PY_VERSION_HEX < 0x03090000 + /* PyEval_InitThreads became deprecated in Python 3.9 and will + be removed in Python 3.11. Prior to Python 3.7, this call was + required to initialize the GIL. */ PyEval_InitThreads (); +#endif #ifdef IS_PY3K - gdb_module = PyModule_Create (&python_GdbModuleDef); - /* Add _gdb module to the list of known built-in modules. */ - _PyImport_FixupBuiltin (gdb_module, "_gdb"); + gdb_module = PyImport_ImportModule ("_gdb"); #else gdb_module = Py_InitModule ("_gdb", python_GdbMethods); #endif if (gdb_module == NULL) return false; - /* The casts to (char*) are for python 2.4. */ - if (PyModule_AddStringConstant (gdb_module, "VERSION", (char*) version) < 0 - || PyModule_AddStringConstant (gdb_module, "HOST_CONFIG", - (char*) host_name) < 0 + if (PyModule_AddStringConstant (gdb_module, "VERSION", version) < 0 + || PyModule_AddStringConstant (gdb_module, "HOST_CONFIG", host_name) < 0 || PyModule_AddStringConstant (gdb_module, "TARGET_CONFIG", - (char*) target_name) < 0) + target_name) < 0) return false; /* Add stream constants. */ @@ -1585,13 +1832,14 @@ do_start_initialization () || gdbpy_initialize_linetable () < 0 || gdbpy_initialize_thread () < 0 || gdbpy_initialize_inferior () < 0 - || gdbpy_initialize_events () < 0 || gdbpy_initialize_eventregistry () < 0 || gdbpy_initialize_py_events () < 0 || gdbpy_initialize_event () < 0 || gdbpy_initialize_arch () < 0 + || gdbpy_initialize_registers () < 0 || gdbpy_initialize_xmethods () < 0 - || gdbpy_initialize_unwind () < 0) + || gdbpy_initialize_unwind () < 0 + || gdbpy_initialize_tui () < 0) return false; #define GDB_PY_DEFINE_EVENT_TYPE(name, py_name, doc, base) \ @@ -1620,8 +1868,7 @@ do_start_initialization () return false; /* Release the GIL while gdb runs. */ - PyThreadState_Swap (NULL); - PyEval_ReleaseLock (); + PyEval_SaveThread (); make_final_cleanup (finalize_python, NULL); @@ -1632,8 +1879,12 @@ do_start_initialization () #endif /* HAVE_PYTHON */ +/* See python.h. */ +cmd_list_element *python_cmd_element = nullptr; + +void _initialize_python (); void -_initialize_python (void) +_initialize_python () { add_com ("python-interactive", class_obscure, python_interactive_command, @@ -1649,8 +1900,7 @@ argument, and if the command is an expression, the result will be\n\ printed. For example:\n\ \n\ (gdb) python-interactive 2 + 3\n\ - 5\n\ -") + 5") #else /* HAVE_PYTHON */ _("\ Start a Python interactive prompt.\n\ @@ -1661,14 +1911,14 @@ This command is only a placeholder.") ); add_com_alias ("pi", "python-interactive", class_obscure, 1); - add_com ("python", class_obscure, python_command, + python_cmd_element = add_com ("python", class_obscure, python_command, #ifdef HAVE_PYTHON _("\ Evaluate a Python command.\n\ \n\ The command can be given as an argument, for instance:\n\ \n\ - python print 23\n\ + python print (23)\n\ \n\ If no argument is given, the following lines are read and used\n\ as the Python commands. Type a line containing \"end\" to indicate\n\ @@ -1684,15 +1934,15 @@ This command is only a placeholder.") add_com_alias ("py", "python", class_obscure, 1); /* Add set/show python print-stack. */ - add_prefix_cmd ("python", no_class, user_show_python, - _("Prefix command for python preference settings."), - &user_show_python_list, "show python ", 0, - &showlist); + add_basic_prefix_cmd ("python", no_class, + _("Prefix command for python preference settings."), + &user_show_python_list, "show python ", 0, + &showlist); - add_prefix_cmd ("python", no_class, user_set_python, - _("Prefix command for python preference settings."), - &user_set_python_list, "set python ", 0, - &setlist); + add_show_prefix_cmd ("python", no_class, + _("Prefix command for python preference settings."), + &user_set_python_list, "set python ", 0, + &setlist); add_setshow_enum_cmd ("print-stack", no_class, python_excp_enums, &gdbpy_should_print_stack, _("\ @@ -1705,20 +1955,39 @@ message == an error message without a stack will be printed."), &user_set_python_list, &user_show_python_list); -#ifdef HAVE_PYTHON - if (!do_start_initialization () && PyErr_Occurred ()) - gdbpy_print_stack (); -#endif /* HAVE_PYTHON */ + add_setshow_boolean_cmd ("ignore-environment", no_class, + &python_ignore_environment, _("\ +Set whether the Python interpreter should ignore environment variables."), _(" \ +Show whether the Python interpreter showlist ignore environment variables."), _(" \ +When enabled GDB's Python interpreter will ignore any Python related\n \ +flags in the environment. This is equivalent to passing `-E' to a\n \ +python executable."), + set_python_ignore_environment, + show_python_ignore_environment, + &user_set_python_list, + &user_show_python_list); + + add_setshow_auto_boolean_cmd ("dont-write-bytecode", no_class, + &python_dont_write_bytecode, _("\ +Set whether the Python interpreter should ignore environment variables."), _(" \ +Show whether the Python interpreter showlist ignore environment variables."), _(" \ +When enabled GDB's Python interpreter will ignore any Python related\n \ +flags in the environment. This is equivalent to passing `-E' to a\n \ +python executable."), + set_python_dont_write_bytecode, + show_python_dont_write_bytecode, + &user_set_python_list, + &user_show_python_list); } #ifdef HAVE_PYTHON -/* Helper function for gdbpy_finish_initialization. This does the - work and then returns false if an error has occurred and must be - displayed, or true on success. */ +/* Helper function for gdbpy_initialize. This does the work and then + returns false if an error has occurred and must be displayed, or true on + success. */ static bool -do_finish_initialization (const struct extension_language_defn *extlang) +do_initialize (const struct extension_language_defn *extlang) { PyObject *m; PyObject *sys_path; @@ -1766,7 +2035,7 @@ do_finish_initialization (const struct extension_language_defn *extlang) warning (_("\n" "Could not load the Python gdb module from `%s'.\n" "Limited Python support is available from the _gdb module.\n" - "Suggest passing --data-directory=/path/to/gdb/data-directory.\n"), + "Suggest passing --data-directory=/path/to/gdb/data-directory."), gdb_pythondir.c_str ()); /* We return "success" here as we've already emitted the warning. */ @@ -1776,18 +2045,19 @@ do_finish_initialization (const struct extension_language_defn *extlang) return gdb_pymodule_addobject (m, "gdb", gdb_python_module) >= 0; } -/* Perform the remaining python initializations. - These must be done after GDB is at least mostly initialized. - E.g., The "info pretty-printer" command needs the "info" prefix - command installed. - This is the extension_language_ops.finish_initialization "method". */ +/* Perform Python initialization. This will be called after GDB has + performed all of its own initialization. This is the + extension_language_ops.initialize "method". */ static void -gdbpy_finish_initialization (const struct extension_language_defn *extlang) +gdbpy_initialize (const struct extension_language_defn *extlang) { + if (!do_start_initialization () && PyErr_Occurred ()) + gdbpy_print_stack (); + gdbpy_enter enter_py (get_current_arch (), current_language); - if (!do_finish_initialization (extlang)) + if (!do_initialize (extlang)) { gdbpy_print_stack (); warning (_("internal error: Unhandled Python exception")); @@ -1803,12 +2073,6 @@ gdbpy_initialized (const struct extension_language_defn *extlang) return gdb_python_initialized; } -#endif /* HAVE_PYTHON */ - - - -#ifdef HAVE_PYTHON - PyMethodDef python_GdbMethods[] = { { "history", gdbpy_history, METH_VARARGS, @@ -1827,15 +2091,11 @@ set to True." }, { "default_visualizer", gdbpy_default_visualizer, METH_VARARGS, "Find the default visualizer for a Value." }, - { "current_progspace", gdbpy_get_current_progspace, METH_NOARGS, - "Return the current Progspace." }, { "progspaces", gdbpy_progspaces, METH_NOARGS, "Return a sequence of all progspaces." }, { "current_objfile", gdbpy_get_current_objfile, METH_NOARGS, "Return the current Objfile being loaded, or None." }, - { "objfiles", gdbpy_objfiles, METH_NOARGS, - "Return a sequence of all loaded objfiles." }, { "newest_frame", gdbpy_newest_frame, METH_NOARGS, "newest_frame () -> gdb.Frame.\n\ @@ -1873,6 +2133,14 @@ a boolean indicating if name is a field of the current implied argument\n\ METH_VARARGS | METH_KEYWORDS, "lookup_global_symbol (name [, domain]) -> symbol\n\ Return the symbol corresponding to the given name (or None)." }, + { "lookup_static_symbol", (PyCFunction) gdbpy_lookup_static_symbol, + METH_VARARGS | METH_KEYWORDS, + "lookup_static_symbol (name [, domain]) -> symbol\n\ +Return the static-linkage symbol corresponding to the given name (or None)." }, + { "lookup_static_symbols", (PyCFunction) gdbpy_lookup_static_symbols, + METH_VARARGS | METH_KEYWORDS, + "lookup_static_symbols (name [, domain]) -> symbol\n\ +Return a list of all static-linkage symbols corresponding to the given name." }, { "lookup_objfile", (PyCFunction) gdbpy_lookup_objfile, METH_VARARGS | METH_KEYWORDS, @@ -1881,11 +2149,6 @@ Look up the specified objfile.\n\ If by_build_id is True, the objfile is looked up by using name\n\ as its build id." }, - { "block_for_pc", gdbpy_block_for_pc, METH_VARARGS, - "Return the block containing the given pc value, or None." }, - { "solib_name", gdbpy_solib_name, METH_VARARGS, - "solib_name (Long) -> String.\n\ -Return the name of the shared library holding a given address, or None." }, { "decode_line", gdbpy_decode_line, METH_VARARGS, "decode_line (String) -> Tuple. Decode a string argument the way\n\ that 'break' or 'edit' does. Return a tuple containing two elements.\n\ @@ -1897,9 +2160,6 @@ gdb.Symtab_and_line objects (or None)."}, "parse_and_eval (String) -> Value.\n\ Parse String as an expression, evaluate it, and return the result as a Value." }, - { "find_pc_line", gdbpy_find_pc_line, METH_VARARGS, - "find_pc_line (pc) -> Symtab_and_line.\n\ -Return the gdb.Symtab_and_line object corresponding to the pc value." }, { "post_event", gdbpy_post_event, METH_VARARGS, "Post an event into gdb's event loop." }, @@ -1910,7 +2170,9 @@ Return the name of the current target charset." }, { "target_wide_charset", gdbpy_target_wide_charset, METH_NOARGS, "target_wide_charset () -> string.\n\ Return the name of the current target wide charset." }, - + { "rbreak", (PyCFunction) gdbpy_rbreak, METH_VARARGS | METH_KEYWORDS, + "rbreak (Regex) -> List.\n\ +Return a Tuple containing gdb.Breakpoint objects that match the given Regex." }, { "string_to_argv", gdbpy_string_to_argv, METH_VARARGS, "string_to_argv (String) -> Array.\n\ Parse String and return an argv-like array.\n\ @@ -1935,28 +2197,28 @@ Return a tuple containing all inferiors." }, Invalidate any cached frame objects in gdb.\n\ Intended for internal use only." }, - {NULL, NULL, 0, NULL} -}; + { "convenience_variable", gdbpy_convenience_variable, METH_VARARGS, + "convenience_variable (NAME) -> value.\n\ +Return the value of the convenience variable $NAME,\n\ +or None if not set." }, + { "set_convenience_variable", gdbpy_set_convenience_variable, METH_VARARGS, + "convenience_variable (NAME, VALUE) -> None.\n\ +Set the value of the convenience variable $NAME." }, -#ifdef IS_PY3K -struct PyModuleDef python_GdbModuleDef = -{ - PyModuleDef_HEAD_INIT, - "_gdb", - NULL, - -1, - python_GdbMethods, - NULL, - NULL, - NULL, - NULL +#ifdef TUI + { "register_window_type", (PyCFunction) gdbpy_register_tui_window, + METH_VARARGS | METH_KEYWORDS, + "register_window_type (NAME, CONSTRUCSTOR) -> None\n\ +Register a TUI window constructor." }, +#endif /* TUI */ + + {NULL, NULL, 0, NULL} }; -#endif /* Define all the event objects. */ #define GDB_PY_DEFINE_EVENT_TYPE(name, py_name, doc, base) \ PyTypeObject name##_event_object_type \ - CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("event_object") \ + CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("event_object") \ = { \ PyVarObject_HEAD_INIT (NULL, 0) \ "gdb." py_name, /* tp_name */ \