|  | /* General python/gdb code | 
|  |  | 
|  | Copyright (C) 2008-2024 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/>.  */ | 
|  |  | 
|  | #include "arch-utils.h" | 
|  | #include "command.h" | 
|  | #include "ui-out.h" | 
|  | #include "cli/cli-script.h" | 
|  | #include "cli/cli-cmds.h" | 
|  | #include "progspace.h" | 
|  | #include "objfiles.h" | 
|  | #include "value.h" | 
|  | #include "language.h" | 
|  | #include "gdbsupport/event-loop.h" | 
|  | #include "readline/tilde.h" | 
|  | #include "python.h" | 
|  | #include "extension-priv.h" | 
|  | #include "cli/cli-utils.h" | 
|  | #include <ctype.h> | 
|  | #include "location.h" | 
|  | #include "run-on-main-thread.h" | 
|  | #include "observable.h" | 
|  |  | 
|  | #if GDB_SELF_TEST | 
|  | #include "gdbsupport/selftest.h" | 
|  | #endif | 
|  |  | 
|  | /* Declared constants and enum for python stack printing.  */ | 
|  | static const char python_excp_none[] = "none"; | 
|  | static const char python_excp_full[] = "full"; | 
|  | static const char python_excp_message[] = "message"; | 
|  |  | 
|  | /* "set python print-stack" choices.  */ | 
|  | static const char *const python_excp_enums[] = | 
|  | { | 
|  | python_excp_none, | 
|  | python_excp_full, | 
|  | python_excp_message, | 
|  | NULL | 
|  | }; | 
|  |  | 
|  | /* The exception printing variable.  'full' if we want to print the | 
|  | error message and stack, 'none' if we want to print nothing, and | 
|  | 'message' if we only want to print the error message.  'message' is | 
|  | the default.  */ | 
|  | static const char *gdbpy_should_print_stack = python_excp_message; | 
|  |  | 
|  |  | 
|  | #ifdef HAVE_PYTHON | 
|  |  | 
|  | #include "cli/cli-decode.h" | 
|  | #include "charset.h" | 
|  | #include "top.h" | 
|  | #include "ui.h" | 
|  | #include "python-internal.h" | 
|  | #include "linespec.h" | 
|  | #include "source.h" | 
|  | #include "gdbsupport/version.h" | 
|  | #include "target.h" | 
|  | #include "gdbthread.h" | 
|  | #include "interps.h" | 
|  | #include "event-top.h" | 
|  | #include "py-event.h" | 
|  |  | 
|  | /* True if Python has been successfully initialized, false | 
|  | otherwise.  */ | 
|  |  | 
|  | int gdb_python_initialized; | 
|  |  | 
|  | extern PyMethodDef python_GdbMethods[]; | 
|  |  | 
|  | PyObject *gdb_module; | 
|  | PyObject *gdb_python_module; | 
|  |  | 
|  | /* Some string constants we may wish to use.  */ | 
|  | PyObject *gdbpy_to_string_cst; | 
|  | PyObject *gdbpy_children_cst; | 
|  | PyObject *gdbpy_display_hint_cst; | 
|  | PyObject *gdbpy_doc_cst; | 
|  | PyObject *gdbpy_enabled_cst; | 
|  | PyObject *gdbpy_value_cst; | 
|  |  | 
|  | /* The GdbError exception.  */ | 
|  | PyObject *gdbpy_gdberror_exc; | 
|  |  | 
|  | /* The `gdb.error' base class.  */ | 
|  | PyObject *gdbpy_gdb_error; | 
|  |  | 
|  | /* The `gdb.MemoryError' exception.  */ | 
|  | 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_initialize (const struct extension_language_defn *); | 
|  | static int gdbpy_initialized (const struct extension_language_defn *); | 
|  | static void finalize_python (const struct extension_language_defn *); | 
|  | static void gdbpy_eval_from_control_command | 
|  | (const struct extension_language_defn *, struct command_line *cmd); | 
|  | static void gdbpy_start_type_printers (const struct extension_language_defn *, | 
|  | struct ext_lang_type_printers *); | 
|  | static enum ext_lang_rc gdbpy_apply_type_printers | 
|  | (const struct extension_language_defn *, | 
|  | const struct ext_lang_type_printers *, struct type *, | 
|  | gdb::unique_xmalloc_ptr<char> *); | 
|  | static void gdbpy_free_type_printers (const struct extension_language_defn *, | 
|  | struct ext_lang_type_printers *); | 
|  | static void gdbpy_set_quit_flag (const struct extension_language_defn *); | 
|  | static bool 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 std::optional<std::string> gdbpy_colorize | 
|  | (const std::string &filename, const std::string &contents); | 
|  | static std::optional<std::string> gdbpy_colorize_disasm | 
|  | (const std::string &content, gdbarch *gdbarch); | 
|  | static ext_lang_missing_debuginfo_result gdbpy_handle_missing_debuginfo | 
|  | (const struct extension_language_defn *extlang, struct objfile *objfile); | 
|  |  | 
|  | /* The interface between gdb proper and loading of python scripts.  */ | 
|  |  | 
|  | static const struct extension_language_script_ops python_extension_script_ops = | 
|  | { | 
|  | gdbpy_source_script, | 
|  | gdbpy_source_objfile_script, | 
|  | gdbpy_execute_objfile_script, | 
|  | gdbpy_auto_load_enabled | 
|  | }; | 
|  |  | 
|  | /* The interface between gdb proper and python extensions.  */ | 
|  |  | 
|  | static const struct extension_language_ops python_extension_ops = | 
|  | { | 
|  | gdbpy_initialize, | 
|  | gdbpy_initialized, | 
|  | finalize_python, | 
|  |  | 
|  | gdbpy_eval_from_control_command, | 
|  |  | 
|  | gdbpy_start_type_printers, | 
|  | gdbpy_apply_type_printers, | 
|  | gdbpy_free_type_printers, | 
|  |  | 
|  | gdbpy_apply_val_pretty_printer, | 
|  |  | 
|  | gdbpy_apply_frame_filter, | 
|  |  | 
|  | gdbpy_preserve_values, | 
|  |  | 
|  | gdbpy_breakpoint_has_cond, | 
|  | gdbpy_breakpoint_cond_says_stop, | 
|  |  | 
|  | gdbpy_set_quit_flag, | 
|  | gdbpy_check_quit_flag, | 
|  |  | 
|  | gdbpy_before_prompt_hook, | 
|  |  | 
|  | gdbpy_get_matching_xmethod_workers, | 
|  |  | 
|  | gdbpy_colorize, | 
|  |  | 
|  | gdbpy_colorize_disasm, | 
|  |  | 
|  | gdbpy_print_insn, | 
|  |  | 
|  | gdbpy_handle_missing_debuginfo | 
|  | }; | 
|  |  | 
|  | #endif /* HAVE_PYTHON */ | 
|  |  | 
|  | /* The main struct describing GDB's interface to the Python | 
|  | extension language.  */ | 
|  | const struct extension_language_defn extension_language_python = | 
|  | { | 
|  | EXT_LANG_PYTHON, | 
|  | "python", | 
|  | "Python", | 
|  |  | 
|  | ".py", | 
|  | "-gdb.py", | 
|  |  | 
|  | python_control, | 
|  |  | 
|  | #ifdef HAVE_PYTHON | 
|  | &python_extension_script_ops, | 
|  | &python_extension_ops | 
|  | #else | 
|  | NULL, | 
|  | NULL | 
|  | #endif | 
|  | }; | 
|  |  | 
|  | #ifdef HAVE_PYTHON | 
|  |  | 
|  | /* Architecture and language to be used in callbacks from | 
|  | the Python interpreter.  */ | 
|  | struct gdbarch *gdbpy_enter::python_gdbarch; | 
|  |  | 
|  | gdbpy_enter::gdbpy_enter  (struct gdbarch *gdbarch, | 
|  | const struct language_defn *language) | 
|  | : m_gdbarch (python_gdbarch), | 
|  | m_language (language == nullptr ? nullptr : current_language) | 
|  | { | 
|  | /* We should not ever enter Python unless initialized.  */ | 
|  | if (!gdb_python_initialized) | 
|  | error (_("Python not initialized")); | 
|  |  | 
|  | m_previous_active = set_active_ext_lang (&extension_language_python); | 
|  |  | 
|  | m_state = PyGILState_Ensure (); | 
|  |  | 
|  | python_gdbarch = gdbarch; | 
|  | if (language != nullptr) | 
|  | set_language (language->la_language); | 
|  |  | 
|  | /* Save it and ensure ! PyErr_Occurred () afterwards.  */ | 
|  | m_error.emplace (); | 
|  | } | 
|  |  | 
|  | gdbpy_enter::~gdbpy_enter () | 
|  | { | 
|  | /* Leftover Python error is forbidden by Python Exception Handling.  */ | 
|  | if (PyErr_Occurred ()) | 
|  | { | 
|  | /* This order is similar to the one calling error afterwards. */ | 
|  | gdbpy_print_stack (); | 
|  | warning (_("internal error: Unhandled Python exception")); | 
|  | } | 
|  |  | 
|  | m_error->restore (); | 
|  |  | 
|  | python_gdbarch = m_gdbarch; | 
|  | if (m_language != nullptr) | 
|  | set_language (m_language->la_language); | 
|  |  | 
|  | restore_active_ext_lang (m_previous_active); | 
|  | PyGILState_Release (m_state); | 
|  | } | 
|  |  | 
|  | struct gdbarch * | 
|  | gdbpy_enter::get_gdbarch () | 
|  | { | 
|  | if (python_gdbarch != nullptr) | 
|  | return python_gdbarch; | 
|  | return get_current_arch (); | 
|  | } | 
|  |  | 
|  | void | 
|  | gdbpy_enter::finalize () | 
|  | { | 
|  | python_gdbarch = current_inferior ()->arch (); | 
|  | } | 
|  |  | 
|  | /* Set the quit flag.  */ | 
|  |  | 
|  | static void | 
|  | gdbpy_set_quit_flag (const struct extension_language_defn *extlang) | 
|  | { | 
|  | PyErr_SetInterrupt (); | 
|  | } | 
|  |  | 
|  | /* Return true if the quit flag has been set, false otherwise.  */ | 
|  |  | 
|  | static bool | 
|  | gdbpy_check_quit_flag (const struct extension_language_defn *extlang) | 
|  | { | 
|  | if (!gdb_python_initialized) | 
|  | return false; | 
|  |  | 
|  | gdbpy_gil gil; | 
|  | return PyOS_InterruptOccurred (); | 
|  | } | 
|  |  | 
|  | /* Evaluate a Python command like PyRun_SimpleString, but takes a | 
|  | Python start symbol, and does not automatically print the stack on | 
|  | errors.  FILENAME is used to set the file name in error messages; | 
|  | NULL means that this is evaluating a string, not the contents of a | 
|  | file.  */ | 
|  |  | 
|  | static int | 
|  | eval_python_command (const char *command, int start_symbol, | 
|  | const char *filename = nullptr) | 
|  | { | 
|  | PyObject *m, *d; | 
|  |  | 
|  | m = PyImport_AddModule ("__main__"); | 
|  | if (m == NULL) | 
|  | return -1; | 
|  |  | 
|  | d = PyModule_GetDict (m); | 
|  | if (d == NULL) | 
|  | return -1; | 
|  |  | 
|  | bool file_set = false; | 
|  | if (filename != nullptr) | 
|  | { | 
|  | gdbpy_ref<> file = host_string_to_python_string ("__file__"); | 
|  | if (file == nullptr) | 
|  | return -1; | 
|  |  | 
|  | /* PyDict_GetItemWithError returns a borrowed reference.  */ | 
|  | PyObject *found = PyDict_GetItemWithError (d, file.get ()); | 
|  | if (found == nullptr) | 
|  | { | 
|  | if (PyErr_Occurred ()) | 
|  | return -1; | 
|  |  | 
|  | gdbpy_ref<> filename_obj = host_string_to_python_string (filename); | 
|  | if (filename_obj == nullptr) | 
|  | return -1; | 
|  |  | 
|  | if (PyDict_SetItem (d, file.get (), filename_obj.get ()) < 0) | 
|  | return -1; | 
|  | if (PyDict_SetItemString (d, "__cached__", Py_None) < 0) | 
|  | return -1; | 
|  |  | 
|  | file_set = true; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Use this API because it is in Python 3.2.  */ | 
|  | gdbpy_ref<> code (Py_CompileStringExFlags (command, | 
|  | filename == nullptr | 
|  | ? "<string>" | 
|  | : filename, | 
|  | start_symbol, | 
|  | nullptr, -1)); | 
|  |  | 
|  | int result = -1; | 
|  | if (code != nullptr) | 
|  | { | 
|  | gdbpy_ref<> eval_result (PyEval_EvalCode (code.get (), d, d)); | 
|  | if (eval_result != nullptr) | 
|  | result = 0; | 
|  | } | 
|  |  | 
|  | if (file_set) | 
|  | { | 
|  | /* If there's already an exception occurring, preserve it and | 
|  | restore it before returning from this function.  */ | 
|  | std::optional<gdbpy_err_fetch> save_error; | 
|  | if (result < 0) | 
|  | save_error.emplace (); | 
|  |  | 
|  | /* CPython also just ignores errors here.  These should be | 
|  | expected to be exceedingly rare anyway.  */ | 
|  | if (PyDict_DelItemString (d, "__file__") < 0) | 
|  | PyErr_Clear (); | 
|  | if (PyDict_DelItemString (d, "__cached__") < 0) | 
|  | PyErr_Clear (); | 
|  |  | 
|  | if (save_error.has_value ()) | 
|  | save_error->restore (); | 
|  | } | 
|  |  | 
|  | return result; | 
|  | } | 
|  |  | 
|  | /* Implementation of the gdb "python-interactive" command.  */ | 
|  |  | 
|  | static void | 
|  | python_interactive_command (const char *arg, int from_tty) | 
|  | { | 
|  | struct ui *ui = current_ui; | 
|  | int err; | 
|  |  | 
|  | scoped_restore save_async = make_scoped_restore (¤t_ui->async, 0); | 
|  |  | 
|  | arg = skip_spaces (arg); | 
|  |  | 
|  | gdbpy_enter enter_py; | 
|  |  | 
|  | if (arg && *arg) | 
|  | { | 
|  | std::string script = std::string (arg) + "\n"; | 
|  | /* Py_single_input causes the result to be displayed.  */ | 
|  | err = eval_python_command (script.c_str (), Py_single_input); | 
|  | } | 
|  | else | 
|  | { | 
|  | err = PyRun_InteractiveLoop (ui->instream, "<stdin>"); | 
|  | dont_repeat (); | 
|  | } | 
|  |  | 
|  | if (err) | 
|  | gdbpy_handle_exception (); | 
|  | } | 
|  |  | 
|  | /* Like PyRun_SimpleFile, but if there is an exception, it is not | 
|  | automatically displayed.  FILE is the Python script to run named | 
|  | FILENAME. | 
|  |  | 
|  | On Windows hosts few users would build Python themselves (this is no | 
|  | trivial task on this platform), and thus use binaries built by | 
|  | someone else instead.  There may happen situation where the Python | 
|  | library and GDB are using two different versions of the C runtime | 
|  | library.  Python, being built with VC, would use one version of the | 
|  | msvcr DLL (Eg. msvcr100.dll), while MinGW uses msvcrt.dll. | 
|  | A FILE * from one runtime does not necessarily operate correctly in | 
|  | the other runtime.  */ | 
|  |  | 
|  | static int | 
|  | python_run_simple_file (FILE *file, const char *filename) | 
|  | { | 
|  | std::string contents = read_remainder_of_file (file); | 
|  | return eval_python_command (contents.c_str (), Py_file_input, filename); | 
|  | } | 
|  |  | 
|  | /* Given a command_line, return a command string suitable for passing | 
|  | to Python.  Lines in the string are separated by newlines.  */ | 
|  |  | 
|  | static std::string | 
|  | compute_python_string (struct command_line *l) | 
|  | { | 
|  | struct command_line *iter; | 
|  | std::string script; | 
|  |  | 
|  | for (iter = l; iter; iter = iter->next) | 
|  | { | 
|  | script += iter->line; | 
|  | script += '\n'; | 
|  | } | 
|  | return script; | 
|  | } | 
|  |  | 
|  | /* Take a command line structure representing a 'python' command, and | 
|  | evaluate its body using the Python interpreter.  */ | 
|  |  | 
|  | static void | 
|  | gdbpy_eval_from_control_command (const struct extension_language_defn *extlang, | 
|  | struct command_line *cmd) | 
|  | { | 
|  | if (cmd->body_list_1 != nullptr) | 
|  | error (_("Invalid \"python\" block structure.")); | 
|  |  | 
|  | gdbpy_enter enter_py; | 
|  |  | 
|  | std::string script = compute_python_string (cmd->body_list_0.get ()); | 
|  | int ret = eval_python_command (script.c_str (), Py_file_input); | 
|  | if (ret != 0) | 
|  | gdbpy_handle_exception (); | 
|  | } | 
|  |  | 
|  | /* Implementation of the gdb "python" command.  */ | 
|  |  | 
|  | static void | 
|  | python_command (const char *arg, int from_tty) | 
|  | { | 
|  | gdbpy_enter enter_py; | 
|  |  | 
|  | scoped_restore save_async = make_scoped_restore (¤t_ui->async, 0); | 
|  |  | 
|  | arg = skip_spaces (arg); | 
|  | if (arg && *arg) | 
|  | { | 
|  | int ret = eval_python_command (arg, Py_file_input); | 
|  | if (ret != 0) | 
|  | gdbpy_handle_exception (); | 
|  | } | 
|  | else | 
|  | { | 
|  | counted_command_line l = get_command_line (python_control, ""); | 
|  |  | 
|  | execute_control_command_untraced (l.get ()); | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  |  | 
|  | /* Transform a gdb parameters's value into a Python value.  May return | 
|  | NULL (and set a Python exception) on error.  Helper function for | 
|  | get_parameter.  */ | 
|  | PyObject * | 
|  | gdbpy_parameter_value (const setting &var) | 
|  | { | 
|  | switch (var.type ()) | 
|  | { | 
|  | case var_string: | 
|  | case var_string_noescape: | 
|  | case var_optional_filename: | 
|  | case var_filename: | 
|  | case var_enum: | 
|  | { | 
|  | const char *str; | 
|  | if (var.type () == var_enum) | 
|  | str = var.get<const char *> (); | 
|  | else | 
|  | str = var.get<std::string> ().c_str (); | 
|  |  | 
|  | return host_string_to_python_string (str).release (); | 
|  | } | 
|  |  | 
|  | case var_boolean: | 
|  | { | 
|  | if (var.get<bool> ()) | 
|  | Py_RETURN_TRUE; | 
|  | else | 
|  | Py_RETURN_FALSE; | 
|  | } | 
|  |  | 
|  | case var_auto_boolean: | 
|  | { | 
|  | enum auto_boolean ab = var.get<enum auto_boolean> (); | 
|  |  | 
|  | if (ab == AUTO_BOOLEAN_TRUE) | 
|  | Py_RETURN_TRUE; | 
|  | else if (ab == AUTO_BOOLEAN_FALSE) | 
|  | Py_RETURN_FALSE; | 
|  | else | 
|  | Py_RETURN_NONE; | 
|  | } | 
|  |  | 
|  | case var_uinteger: | 
|  | case var_integer: | 
|  | case var_pinteger: | 
|  | { | 
|  | LONGEST value | 
|  | = (var.type () == var_uinteger | 
|  | ? static_cast<LONGEST> (var.get<unsigned int> ()) | 
|  | : static_cast<LONGEST> (var.get<int> ())); | 
|  |  | 
|  | if (var.extra_literals () != nullptr) | 
|  | for (const literal_def *l = var.extra_literals (); | 
|  | l->literal != nullptr; | 
|  | l++) | 
|  | if (value == l->use) | 
|  | { | 
|  | if (strcmp (l->literal, "unlimited") == 0) | 
|  | { | 
|  | /* Compatibility hack for API brokenness.  */ | 
|  | if (var.type () == var_pinteger | 
|  | && l->val.has_value () | 
|  | && *l->val == -1) | 
|  | value = -1; | 
|  | else | 
|  | Py_RETURN_NONE; | 
|  | } | 
|  | else if (l->val.has_value ()) | 
|  | value = *l->val; | 
|  | else | 
|  | return host_string_to_python_string (l->literal).release (); | 
|  | } | 
|  |  | 
|  | if (var.type () == var_uinteger) | 
|  | return | 
|  | gdb_py_object_from_ulongest | 
|  | (static_cast<unsigned int> (value)).release (); | 
|  | else | 
|  | return | 
|  | gdb_py_object_from_longest | 
|  | (static_cast<int> (value)).release (); | 
|  | } | 
|  | } | 
|  |  | 
|  | return PyErr_Format (PyExc_RuntimeError, | 
|  | _("Programmer error: unhandled type.")); | 
|  | } | 
|  |  | 
|  | /* A Python function which returns a gdb parameter's value as a Python | 
|  | value.  */ | 
|  |  | 
|  | static PyObject * | 
|  | gdbpy_parameter (PyObject *self, PyObject *args) | 
|  | { | 
|  | struct cmd_list_element *alias, *prefix, *cmd; | 
|  | const char *arg; | 
|  | int found = -1; | 
|  |  | 
|  | if (! PyArg_ParseTuple (args, "s", &arg)) | 
|  | return NULL; | 
|  |  | 
|  | std::string newarg = std::string ("show ") + arg; | 
|  |  | 
|  | try | 
|  | { | 
|  | found = lookup_cmd_composition (newarg.c_str (), &alias, &prefix, &cmd); | 
|  | } | 
|  | catch (const gdb_exception &ex) | 
|  | { | 
|  | GDB_PY_HANDLE_EXCEPTION (ex); | 
|  | } | 
|  |  | 
|  | if (cmd == CMD_LIST_AMBIGUOUS) | 
|  | return PyErr_Format (PyExc_RuntimeError, | 
|  | _("Parameter `%s' is ambiguous."), arg); | 
|  | else if (!found) | 
|  | return PyErr_Format (PyExc_RuntimeError, | 
|  | _("Could not find parameter `%s'."), arg); | 
|  |  | 
|  | if (!cmd->var.has_value ()) | 
|  | return PyErr_Format (PyExc_RuntimeError, | 
|  | _("`%s' is not a parameter."), arg); | 
|  |  | 
|  | return gdbpy_parameter_value (*cmd->var); | 
|  | } | 
|  |  | 
|  | /* Wrapper for target_charset.  */ | 
|  |  | 
|  | static PyObject * | 
|  | gdbpy_target_charset (PyObject *self, PyObject *args) | 
|  | { | 
|  | const char *cset = target_charset (gdbpy_enter::get_gdbarch ()); | 
|  |  | 
|  | return PyUnicode_Decode (cset, strlen (cset), host_charset (), NULL); | 
|  | } | 
|  |  | 
|  | /* Wrapper for target_wide_charset.  */ | 
|  |  | 
|  | static PyObject * | 
|  | gdbpy_target_wide_charset (PyObject *self, PyObject *args) | 
|  | { | 
|  | const char *cset = target_wide_charset (gdbpy_enter::get_gdbarch ()); | 
|  |  | 
|  | return PyUnicode_Decode (cset, strlen (cset), host_charset (), NULL); | 
|  | } | 
|  |  | 
|  | /* Implement gdb.host_charset().  */ | 
|  |  | 
|  | static PyObject * | 
|  | gdbpy_host_charset (PyObject *self, PyObject *args) | 
|  | { | 
|  | const char *cset = host_charset (); | 
|  |  | 
|  | return PyUnicode_Decode (cset, strlen (cset), host_charset (), NULL); | 
|  | } | 
|  |  | 
|  | /* A Python function which evaluates a string using the gdb CLI.  */ | 
|  |  | 
|  | static PyObject * | 
|  | execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw) | 
|  | { | 
|  | const char *arg; | 
|  | PyObject *from_tty_obj = nullptr; | 
|  | PyObject *to_string_obj = nullptr; | 
|  | static const char *keywords[] = { "command", "from_tty", "to_string", | 
|  | nullptr }; | 
|  |  | 
|  | if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s|O!O!", keywords, &arg, | 
|  | &PyBool_Type, &from_tty_obj, | 
|  | &PyBool_Type, &to_string_obj)) | 
|  | return nullptr; | 
|  |  | 
|  | bool from_tty = false; | 
|  | if (from_tty_obj != nullptr) | 
|  | { | 
|  | int cmp = PyObject_IsTrue (from_tty_obj); | 
|  | if (cmp < 0) | 
|  | return nullptr; | 
|  | from_tty = (cmp != 0); | 
|  | } | 
|  |  | 
|  | bool to_string = false; | 
|  | if (to_string_obj != nullptr) | 
|  | { | 
|  | int cmp = PyObject_IsTrue (to_string_obj); | 
|  | if (cmp < 0) | 
|  | return nullptr; | 
|  | to_string = (cmp != 0); | 
|  | } | 
|  |  | 
|  | std::string to_string_res; | 
|  |  | 
|  | scoped_restore preventer = prevent_dont_repeat (); | 
|  |  | 
|  | /* If the executed command raises an exception, we may have to | 
|  | enable stdin and recover the GDB prompt. | 
|  |  | 
|  | Stdin should not be re-enabled if it is already blocked because, | 
|  | for example, we are running a command in the context of a | 
|  | synchronous execution command ("run", "continue", etc.).  Like | 
|  | this: | 
|  |  | 
|  | User runs "continue" | 
|  | --> command blocks the prompt | 
|  | --> Python API is invoked, e.g.  via events | 
|  | --> gdb.execute(C) invoked inside Python | 
|  | --> command C raises an exception | 
|  |  | 
|  | In this case case, GDB would go back to the top "continue" command | 
|  | and move on with its normal course of execution.  That is, it | 
|  | would enable stdin in the way it normally does. | 
|  |  | 
|  | Similarly, if the command we are about to execute enables the | 
|  | stdin while we are still in the context of a synchronous | 
|  | execution command, we would be displaying the prompt too early, | 
|  | before the surrounding command completes. | 
|  |  | 
|  | For these reasons, we keep the prompt blocked, if it already is.  */ | 
|  | bool prompt_was_blocked = (current_ui->prompt_state == PROMPT_BLOCKED); | 
|  | scoped_restore save_prompt_state | 
|  | = make_scoped_restore (¤t_ui->keep_prompt_blocked, | 
|  | prompt_was_blocked); | 
|  |  | 
|  | try | 
|  | { | 
|  | gdbpy_allow_threads allow_threads; | 
|  |  | 
|  | struct interp *interp; | 
|  |  | 
|  | std::string arg_copy = arg; | 
|  | bool first = true; | 
|  | char *save_ptr = nullptr; | 
|  | auto reader | 
|  | = [&] (std::string &buffer) | 
|  | { | 
|  | const char *result = strtok_r (first ? &arg_copy[0] : nullptr, | 
|  | "\n", &save_ptr); | 
|  | first = false; | 
|  | return result; | 
|  | }; | 
|  |  | 
|  | counted_command_line lines = read_command_lines_1 (reader, 1, nullptr); | 
|  |  | 
|  | { | 
|  | scoped_restore save_async = make_scoped_restore (¤t_ui->async, | 
|  | 0); | 
|  |  | 
|  | 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 (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); | 
|  | } | 
|  |  | 
|  | if (to_string) | 
|  | return PyUnicode_FromString (to_string_res.c_str ()); | 
|  | Py_RETURN_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_rbreak (PyObject *self, PyObject *args, PyObject *kw) | 
|  | { | 
|  | char *regex = NULL; | 
|  | std::vector<symbol_search> 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; | 
|  |  | 
|  | /* Parse minsyms keyword.  */ | 
|  | if (minsyms_p_obj != NULL) | 
|  | { | 
|  | int cmp = PyObject_IsTrue (minsyms_p_obj); | 
|  | if (cmp < 0) | 
|  | return NULL; | 
|  | minsyms_p = cmp; | 
|  | } | 
|  |  | 
|  | global_symbol_searcher spec (SEARCH_FUNCTION_DOMAIN, regex); | 
|  |  | 
|  | /* 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<char> 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<char> filename = | 
|  | python_string_to_target_string (obj_name.get ()); | 
|  |  | 
|  | if (filename == NULL) | 
|  | return NULL; | 
|  |  | 
|  | spec.add_filename (std::move (filename)); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* 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 = p.symbol->symtab (); | 
|  | 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.  */ | 
|  |  | 
|  | static PyObject * | 
|  | gdbpy_decode_line (PyObject *self, PyObject *args) | 
|  | { | 
|  | const char *arg = NULL; | 
|  | gdbpy_ref<> result; | 
|  | gdbpy_ref<> unparsed; | 
|  | location_spec_up locspec; | 
|  |  | 
|  | if (! PyArg_ParseTuple (args, "|s", &arg)) | 
|  | return NULL; | 
|  |  | 
|  | /* Treat a string consisting of just whitespace the same as | 
|  | NULL.  */ | 
|  | if (arg != NULL) | 
|  | { | 
|  | arg = skip_spaces (arg); | 
|  | if (*arg == '\0') | 
|  | arg = NULL; | 
|  | } | 
|  |  | 
|  | if (arg != NULL) | 
|  | locspec = string_to_location_spec_basic (&arg, current_language, | 
|  | symbol_name_match_type::WILD); | 
|  |  | 
|  | std::vector<symtab_and_line> decoded_sals; | 
|  | symtab_and_line def_sal; | 
|  | gdb::array_view<symtab_and_line> sals; | 
|  | try | 
|  | { | 
|  | if (locspec != NULL) | 
|  | { | 
|  | decoded_sals = decode_line_1 (locspec.get (), 0, NULL, NULL, 0); | 
|  | sals = decoded_sals; | 
|  | } | 
|  | else | 
|  | { | 
|  | set_default_source_symtab_and_line (); | 
|  | def_sal = get_current_source_symtab_and_line (current_program_space); | 
|  | sals = def_sal; | 
|  | } | 
|  | } | 
|  | catch (const gdb_exception &ex) | 
|  | { | 
|  | /* We know this will always throw.  */ | 
|  | gdbpy_convert_exception (ex); | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | if (!sals.empty ()) | 
|  | { | 
|  | result.reset (PyTuple_New (sals.size ())); | 
|  | if (result == NULL) | 
|  | return NULL; | 
|  | for (size_t i = 0; i < sals.size (); ++i) | 
|  | { | 
|  | PyObject *obj = symtab_and_line_to_sal_object (sals[i]); | 
|  | if (obj == NULL) | 
|  | return NULL; | 
|  |  | 
|  | PyTuple_SetItem (result.get (), i, obj); | 
|  | } | 
|  | } | 
|  | else | 
|  | result = gdbpy_ref<>::new_reference (Py_None); | 
|  |  | 
|  | gdbpy_ref<> return_result (PyTuple_New (2)); | 
|  | if (return_result == NULL) | 
|  | return NULL; | 
|  |  | 
|  | if (arg != NULL && strlen (arg) > 0) | 
|  | { | 
|  | unparsed.reset (PyUnicode_FromString (arg)); | 
|  | if (unparsed == NULL) | 
|  | return NULL; | 
|  | } | 
|  | else | 
|  | unparsed = gdbpy_ref<>::new_reference (Py_None); | 
|  |  | 
|  | PyTuple_SetItem (return_result.get (), 0, unparsed.release ()); | 
|  | PyTuple_SetItem (return_result.get (), 1, result.release ()); | 
|  |  | 
|  | return return_result.release (); | 
|  | } | 
|  |  | 
|  | /* Parse a string and evaluate it as an expression.  */ | 
|  | static PyObject * | 
|  | gdbpy_parse_and_eval (PyObject *self, PyObject *args, PyObject *kw) | 
|  | { | 
|  | static const char *keywords[] = { "expression", "global_context", nullptr }; | 
|  |  | 
|  | const char *expr_str; | 
|  | PyObject *global_context_obj = nullptr; | 
|  |  | 
|  | if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s|O!", keywords, | 
|  | &expr_str, | 
|  | &PyBool_Type, &global_context_obj)) | 
|  | return nullptr; | 
|  |  | 
|  | parser_flags flags = 0; | 
|  | if (global_context_obj != NULL) | 
|  | { | 
|  | int cmp = PyObject_IsTrue (global_context_obj); | 
|  | if (cmp < 0) | 
|  | return nullptr; | 
|  | if (cmp) | 
|  | flags |= PARSER_LEAVE_BLOCK_ALONE; | 
|  | } | 
|  |  | 
|  | PyObject *result = nullptr; | 
|  | try | 
|  | { | 
|  | scoped_value_mark free_values; | 
|  | struct value *val; | 
|  | { | 
|  | /* Allow other Python threads to run while we're evaluating | 
|  | the expression.  This is important because the expression | 
|  | could involve inferior calls or otherwise be a lengthy | 
|  | calculation.  We take care here to re-acquire the GIL here | 
|  | before continuing with Python work.  */ | 
|  | gdbpy_allow_threads allow_threads; | 
|  | val = parse_and_eval (expr_str, flags); | 
|  | } | 
|  | result = value_to_value_object (val); | 
|  | } | 
|  | catch (const gdb_exception &except) | 
|  | { | 
|  | GDB_PY_HANDLE_EXCEPTION (except); | 
|  | } | 
|  |  | 
|  | return result; | 
|  | } | 
|  |  | 
|  | /* Implementation of gdb.invalidate_cached_frames.  */ | 
|  |  | 
|  | static PyObject * | 
|  | gdbpy_invalidate_cached_frames (PyObject *self, PyObject *args) | 
|  | { | 
|  | reinit_frame_cache (); | 
|  | Py_RETURN_NONE; | 
|  | } | 
|  |  | 
|  | /* Read a file as Python code. | 
|  | This is the extension_language_script_ops.script_sourcer "method". | 
|  | FILE is the file to load.  FILENAME is name of the file FILE. | 
|  | This does not throw any errors.  If an exception occurs python will print | 
|  | the traceback and clear the error indicator.  */ | 
|  |  | 
|  | static void | 
|  | gdbpy_source_script (const struct extension_language_defn *extlang, | 
|  | FILE *file, const char *filename) | 
|  | { | 
|  | gdbpy_enter enter_py; | 
|  | int result = python_run_simple_file (file, filename); | 
|  | if (result != 0) | 
|  | gdbpy_handle_exception (); | 
|  | } | 
|  |  | 
|  |  | 
|  |  | 
|  | /* Posting and handling events.  */ | 
|  |  | 
|  | /* A single event.  */ | 
|  | struct gdbpy_event | 
|  | { | 
|  | gdbpy_event (gdbpy_ref<> &&func) | 
|  | : m_func (func.release ()) | 
|  | { | 
|  | } | 
|  |  | 
|  | gdbpy_event (gdbpy_event &&other) noexcept | 
|  | : m_func (other.m_func) | 
|  | { | 
|  | other.m_func = nullptr; | 
|  | } | 
|  |  | 
|  | gdbpy_event (const gdbpy_event &other) | 
|  | : m_func (other.m_func) | 
|  | { | 
|  | gdbpy_gil gil; | 
|  | Py_XINCREF (m_func); | 
|  | } | 
|  |  | 
|  | ~gdbpy_event () | 
|  | { | 
|  | gdbpy_gil gil; | 
|  | Py_XDECREF (m_func); | 
|  | } | 
|  |  | 
|  | gdbpy_event &operator= (const gdbpy_event &other) = delete; | 
|  |  | 
|  | void operator() () | 
|  | { | 
|  | gdbpy_enter enter_py; | 
|  |  | 
|  | 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) | 
|  | { | 
|  | PyObject *func; | 
|  |  | 
|  | if (!PyArg_ParseTuple (args, "O", &func)) | 
|  | return NULL; | 
|  |  | 
|  | if (!PyCallable_Check (func)) | 
|  | { | 
|  | PyErr_SetString (PyExc_RuntimeError, | 
|  | _("Posted event is not callable")); | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | gdbpy_ref<> func_ref = gdbpy_ref<>::new_reference (func); | 
|  | gdbpy_event event (std::move (func_ref)); | 
|  | run_on_main_thread (event); | 
|  |  | 
|  | Py_RETURN_NONE; | 
|  | } | 
|  |  | 
|  | /* Interrupt the current operation on the main thread.  */ | 
|  | static PyObject * | 
|  | gdbpy_interrupt (PyObject *self, PyObject *args) | 
|  | { | 
|  | { | 
|  | /* Make sure the interrupt isn't delivered immediately somehow. | 
|  | This probably is not truly needed, but at the same time it | 
|  | seems more clear to be explicit about the intent.  */ | 
|  | gdbpy_allow_threads temporarily_exit_python; | 
|  | scoped_disable_cooperative_sigint_handling no_python_sigint; | 
|  |  | 
|  | set_quit_flag (); | 
|  | } | 
|  |  | 
|  | Py_RETURN_NONE; | 
|  | } | 
|  |  | 
|  |  | 
|  |  | 
|  | /* This is the extension_language_ops.before_prompt "method".  */ | 
|  |  | 
|  | static enum ext_lang_rc | 
|  | gdbpy_before_prompt_hook (const struct extension_language_defn *extlang, | 
|  | const char *current_gdb_prompt) | 
|  | { | 
|  | if (!gdb_python_initialized) | 
|  | return EXT_LANG_RC_NOP; | 
|  |  | 
|  | gdbpy_enter enter_py; | 
|  |  | 
|  | if (!evregpy_no_listeners_p (gdb_py_events.before_prompt) | 
|  | && evpy_emit_event (NULL, gdb_py_events.before_prompt) < 0) | 
|  | return EXT_LANG_RC_ERROR; | 
|  |  | 
|  | if (gdb_python_module | 
|  | && PyObject_HasAttrString (gdb_python_module, "prompt_hook")) | 
|  | { | 
|  | gdbpy_ref<> hook (PyObject_GetAttrString (gdb_python_module, | 
|  | "prompt_hook")); | 
|  | if (hook == NULL) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | return EXT_LANG_RC_ERROR; | 
|  | } | 
|  |  | 
|  | if (PyCallable_Check (hook.get ())) | 
|  | { | 
|  | gdbpy_ref<> current_prompt (PyUnicode_FromString (current_gdb_prompt)); | 
|  | if (current_prompt == NULL) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | return EXT_LANG_RC_ERROR; | 
|  | } | 
|  |  | 
|  | gdbpy_ref<> result | 
|  | (PyObject_CallFunctionObjArgs (hook.get (), current_prompt.get (), | 
|  | NULL)); | 
|  | if (result == NULL) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | return EXT_LANG_RC_ERROR; | 
|  | } | 
|  |  | 
|  | /* Return type should be None, or a String.  If it is None, | 
|  | fall through, we will not set a prompt.  If it is a | 
|  | string, set  PROMPT.  Anything else, set an exception.  */ | 
|  | if (result != Py_None && !PyUnicode_Check (result.get ())) | 
|  | { | 
|  | PyErr_Format (PyExc_RuntimeError, | 
|  | _("Return from prompt_hook must " \ | 
|  | "be either a Python string, or None")); | 
|  | gdbpy_print_stack (); | 
|  | return EXT_LANG_RC_ERROR; | 
|  | } | 
|  |  | 
|  | if (result != Py_None) | 
|  | { | 
|  | gdb::unique_xmalloc_ptr<char> | 
|  | prompt (python_string_to_host_string (result.get ())); | 
|  |  | 
|  | if (prompt == NULL) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | return EXT_LANG_RC_ERROR; | 
|  | } | 
|  |  | 
|  | set_prompt (prompt.get ()); | 
|  | return EXT_LANG_RC_OK; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | return EXT_LANG_RC_NOP; | 
|  | } | 
|  |  | 
|  | /* This is the extension_language_ops.colorize "method".  */ | 
|  |  | 
|  | static std::optional<std::string> | 
|  | gdbpy_colorize (const std::string &filename, const std::string &contents) | 
|  | { | 
|  | if (!gdb_python_initialized) | 
|  | return {}; | 
|  |  | 
|  | gdbpy_enter enter_py; | 
|  |  | 
|  | gdbpy_ref<> module (PyImport_ImportModule ("gdb.styling")); | 
|  | if (module == nullptr) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | return {}; | 
|  | } | 
|  |  | 
|  | if (!PyObject_HasAttrString (module.get (), "colorize")) | 
|  | return {}; | 
|  |  | 
|  | gdbpy_ref<> hook (PyObject_GetAttrString (module.get (), "colorize")); | 
|  | if (hook == nullptr) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | return {}; | 
|  | } | 
|  |  | 
|  | if (!PyCallable_Check (hook.get ())) | 
|  | return {}; | 
|  |  | 
|  | gdbpy_ref<> fname_arg (PyUnicode_FromString (filename.c_str ())); | 
|  | if (fname_arg == nullptr) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | return {}; | 
|  | } | 
|  |  | 
|  | /* The pygments library, which is what we currently use for applying | 
|  | styling, is happy to take input as a bytes object, and to figure out | 
|  | the encoding for itself.  This removes the need for us to figure out | 
|  | (guess?) at how the content is encoded, which is probably a good | 
|  | thing.  */ | 
|  | gdbpy_ref<> contents_arg (PyBytes_FromStringAndSize (contents.c_str (), | 
|  | contents.size ())); | 
|  | if (contents_arg == nullptr) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | return {}; | 
|  | } | 
|  |  | 
|  | /* Calling gdb.colorize passing in the filename (a string), and the file | 
|  | contents (a bytes object).  This function should return either a bytes | 
|  | object, the same contents with styling applied, or None to indicate | 
|  | that no styling should be performed.  */ | 
|  | gdbpy_ref<> result (PyObject_CallFunctionObjArgs (hook.get (), | 
|  | fname_arg.get (), | 
|  | contents_arg.get (), | 
|  | nullptr)); | 
|  | if (result == nullptr) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | return {}; | 
|  | } | 
|  |  | 
|  | if (result == Py_None) | 
|  | return {}; | 
|  | else if (!PyBytes_Check (result.get ())) | 
|  | { | 
|  | PyErr_SetString (PyExc_TypeError, | 
|  | _("Return value from gdb.colorize should be a bytes object or None.")); | 
|  | gdbpy_print_stack (); | 
|  | return {}; | 
|  | } | 
|  |  | 
|  | return std::string (PyBytes_AsString (result.get ())); | 
|  | } | 
|  |  | 
|  | /* This is the extension_language_ops.colorize_disasm "method".  */ | 
|  |  | 
|  | static std::optional<std::string> | 
|  | gdbpy_colorize_disasm (const std::string &content, gdbarch *gdbarch) | 
|  | { | 
|  | if (!gdb_python_initialized) | 
|  | return {}; | 
|  |  | 
|  | gdbpy_enter enter_py; | 
|  |  | 
|  | gdbpy_ref<> module (PyImport_ImportModule ("gdb.styling")); | 
|  | if (module == nullptr) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | return {}; | 
|  | } | 
|  |  | 
|  | if (!PyObject_HasAttrString (module.get (), "colorize_disasm")) | 
|  | return {}; | 
|  |  | 
|  | gdbpy_ref<> hook (PyObject_GetAttrString (module.get (), | 
|  | "colorize_disasm")); | 
|  | if (hook == nullptr) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | return {}; | 
|  | } | 
|  |  | 
|  | if (!PyCallable_Check (hook.get ())) | 
|  | return {}; | 
|  |  | 
|  | gdbpy_ref<> content_arg (PyBytes_FromString (content.c_str ())); | 
|  | if (content_arg == nullptr) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | return {}; | 
|  | } | 
|  |  | 
|  | gdbpy_ref<> gdbarch_arg (gdbarch_to_arch_object (gdbarch)); | 
|  | if (gdbarch_arg == nullptr) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | return {}; | 
|  | } | 
|  |  | 
|  | gdbpy_ref<> result (PyObject_CallFunctionObjArgs (hook.get (), | 
|  | content_arg.get (), | 
|  | gdbarch_arg.get (), | 
|  | nullptr)); | 
|  | if (result == nullptr) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | return {}; | 
|  | } | 
|  |  | 
|  | if (result == Py_None) | 
|  | return {}; | 
|  |  | 
|  | if (!PyBytes_Check (result.get ())) | 
|  | { | 
|  | PyErr_SetString (PyExc_TypeError, | 
|  | _("Return value from gdb.colorize_disasm should be a bytes object or None.")); | 
|  | gdbpy_print_stack (); | 
|  | return {}; | 
|  | } | 
|  |  | 
|  | return std::string (PyBytes_AsString (result.get ())); | 
|  | } | 
|  |  | 
|  |  | 
|  |  | 
|  | /* Implement gdb.format_address(ADDR,P_SPACE,ARCH).  Provide access to | 
|  | GDB's print_address function from Python.  The returned address will | 
|  | have the format '0x..... <symbol+offset>'.  */ | 
|  |  | 
|  | static PyObject * | 
|  | gdbpy_format_address (PyObject *self, PyObject *args, PyObject *kw) | 
|  | { | 
|  | static const char *keywords[] = | 
|  | { | 
|  | "address", "progspace", "architecture", nullptr | 
|  | }; | 
|  | PyObject *addr_obj = nullptr, *pspace_obj = nullptr, *arch_obj = nullptr; | 
|  | CORE_ADDR addr; | 
|  | struct gdbarch *gdbarch = nullptr; | 
|  | struct program_space *pspace = nullptr; | 
|  |  | 
|  | if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "O|OO", keywords, | 
|  | &addr_obj, &pspace_obj, &arch_obj)) | 
|  | return nullptr; | 
|  |  | 
|  | if (get_addr_from_python (addr_obj, &addr) < 0) | 
|  | return nullptr; | 
|  |  | 
|  | /* If the user passed None for progspace or architecture, then we | 
|  | consider this to mean "the default".  Here we replace references to | 
|  | None with nullptr, this means that in the following code we only have | 
|  | to handle the nullptr case.  These are only borrowed references, so | 
|  | no decref is required here.  */ | 
|  | if (pspace_obj == Py_None) | 
|  | pspace_obj = nullptr; | 
|  | if (arch_obj == Py_None) | 
|  | arch_obj = nullptr; | 
|  |  | 
|  | if (pspace_obj == nullptr && arch_obj == nullptr) | 
|  | { | 
|  | /* Grab both of these from the current inferior, and its associated | 
|  | default architecture.  */ | 
|  | pspace = current_inferior ()->pspace; | 
|  | gdbarch = current_inferior ()->arch (); | 
|  | } | 
|  | else if (arch_obj == nullptr || pspace_obj == nullptr) | 
|  | { | 
|  | /* If the user has only given one of program space or architecture, | 
|  | then don't use the default for the other.  Sure we could use the | 
|  | default, but it feels like there's too much scope of mistakes in | 
|  | this case, so better to require the user to provide both | 
|  | arguments.  */ | 
|  | PyErr_SetString (PyExc_ValueError, | 
|  | _("The architecture and progspace arguments must both be supplied")); | 
|  | return nullptr; | 
|  | } | 
|  | else | 
|  | { | 
|  | /* The user provided an address, program space, and architecture. | 
|  | Just check that these objects are valid.  */ | 
|  | if (!gdbpy_is_progspace (pspace_obj)) | 
|  | { | 
|  | PyErr_SetString (PyExc_TypeError, | 
|  | _("The progspace argument is not a gdb.Progspace object")); | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | pspace = progspace_object_to_program_space (pspace_obj); | 
|  | if (pspace == nullptr) | 
|  | { | 
|  | PyErr_SetString (PyExc_ValueError, | 
|  | _("The progspace argument is not valid")); | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | if (!gdbpy_is_architecture (arch_obj)) | 
|  | { | 
|  | PyErr_SetString (PyExc_TypeError, | 
|  | _("The architecture argument is not a gdb.Architecture object")); | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | /* Architectures are never deleted once created, so gdbarch should | 
|  | never come back as nullptr.  */ | 
|  | gdbarch = arch_object_to_gdbarch (arch_obj); | 
|  | gdb_assert (gdbarch != nullptr); | 
|  | } | 
|  |  | 
|  | /* By this point we should know the program space and architecture we are | 
|  | going to use.  */ | 
|  | gdb_assert (pspace != nullptr); | 
|  | gdb_assert (gdbarch != nullptr); | 
|  |  | 
|  | /* Unfortunately print_address relies on the current program space for | 
|  | its symbol lookup.  Temporarily switch now.  */ | 
|  | scoped_restore_current_program_space restore_progspace; | 
|  | set_current_program_space (pspace); | 
|  |  | 
|  | /* Format the address, and return it as a string.  */ | 
|  | string_file buf; | 
|  | print_address (gdbarch, addr, &buf); | 
|  | return PyUnicode_FromString (buf.c_str ()); | 
|  | } | 
|  |  | 
|  |  | 
|  |  | 
|  | /* Printing.  */ | 
|  |  | 
|  | /* A python function to write a single string using gdb's filtered | 
|  | output stream .  The optional keyword STREAM can be used to write | 
|  | to a particular stream.  The default stream is to gdb_stdout.  */ | 
|  |  | 
|  | static PyObject * | 
|  | gdbpy_write (PyObject *self, PyObject *args, PyObject *kw) | 
|  | { | 
|  | const char *arg; | 
|  | static const char *keywords[] = { "text", "stream", NULL }; | 
|  | int stream_type = 0; | 
|  |  | 
|  | if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s|i", keywords, &arg, | 
|  | &stream_type)) | 
|  | return NULL; | 
|  |  | 
|  | try | 
|  | { | 
|  | switch (stream_type) | 
|  | { | 
|  | case 1: | 
|  | { | 
|  | gdb_printf (gdb_stderr, "%s", arg); | 
|  | break; | 
|  | } | 
|  | case 2: | 
|  | { | 
|  | gdb_printf (gdb_stdlog, "%s", arg); | 
|  | break; | 
|  | } | 
|  | default: | 
|  | gdb_printf (gdb_stdout, "%s", arg); | 
|  | } | 
|  | } | 
|  | catch (const gdb_exception &except) | 
|  | { | 
|  | GDB_PY_HANDLE_EXCEPTION (except); | 
|  | } | 
|  |  | 
|  | Py_RETURN_NONE; | 
|  | } | 
|  |  | 
|  | /* A python function to flush a gdb stream.  The optional keyword | 
|  | STREAM can be used to flush a particular stream.  The default stream | 
|  | is gdb_stdout.  */ | 
|  |  | 
|  | static PyObject * | 
|  | gdbpy_flush (PyObject *self, PyObject *args, PyObject *kw) | 
|  | { | 
|  | static const char *keywords[] = { "stream", NULL }; | 
|  | int stream_type = 0; | 
|  |  | 
|  | if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "|i", keywords, | 
|  | &stream_type)) | 
|  | return NULL; | 
|  |  | 
|  | switch (stream_type) | 
|  | { | 
|  | case 1: | 
|  | { | 
|  | gdb_flush (gdb_stderr); | 
|  | break; | 
|  | } | 
|  | case 2: | 
|  | { | 
|  | gdb_flush (gdb_stdlog); | 
|  | break; | 
|  | } | 
|  | default: | 
|  | gdb_flush (gdb_stdout); | 
|  | } | 
|  |  | 
|  | Py_RETURN_NONE; | 
|  | } | 
|  |  | 
|  | /* Return non-zero if print-stack is not "none".  */ | 
|  |  | 
|  | int | 
|  | gdbpy_print_python_errors_p (void) | 
|  | { | 
|  | return gdbpy_should_print_stack != python_excp_none; | 
|  | } | 
|  |  | 
|  | /* Print a python exception trace, print just a message, or print | 
|  | nothing and clear the python exception, depending on | 
|  | gdbpy_should_print_stack.  Only call this if a python exception is | 
|  | set.  */ | 
|  | void | 
|  | gdbpy_print_stack (void) | 
|  | { | 
|  |  | 
|  | /* Print "none", just clear exception.  */ | 
|  | if (gdbpy_should_print_stack == python_excp_none) | 
|  | { | 
|  | PyErr_Clear (); | 
|  | } | 
|  | /* Print "full" message and backtrace.  */ | 
|  | else if (gdbpy_should_print_stack == python_excp_full) | 
|  | { | 
|  | PyErr_Print (); | 
|  | /* PyErr_Print doesn't necessarily end output with a newline. | 
|  | This works because Python's stdout/stderr is fed through | 
|  | gdb_printf.  */ | 
|  | try | 
|  | { | 
|  | begin_line (); | 
|  | } | 
|  | catch (const gdb_exception &except) | 
|  | { | 
|  | } | 
|  | } | 
|  | /* Print "message", just error print message.  */ | 
|  | else | 
|  | { | 
|  | gdbpy_err_fetch fetched_error; | 
|  |  | 
|  | gdb::unique_xmalloc_ptr<char> msg = fetched_error.to_string (); | 
|  | gdb::unique_xmalloc_ptr<char> type; | 
|  | /* Don't compute TYPE if MSG already indicates that there is an | 
|  | error.  */ | 
|  | if (msg != NULL) | 
|  | type = fetched_error.type_to_string (); | 
|  |  | 
|  | try | 
|  | { | 
|  | if (msg == NULL || type == NULL) | 
|  | { | 
|  | /* An error occurred computing the string representation of the | 
|  | error message.  */ | 
|  | gdb_printf (gdb_stderr, | 
|  | _("Error occurred computing Python error " | 
|  | "message.\n")); | 
|  | PyErr_Clear (); | 
|  | } | 
|  | else | 
|  | gdb_printf (gdb_stderr, "Python Exception %s: %s\n", | 
|  | type.get (), msg.get ()); | 
|  | } | 
|  | catch (const gdb_exception &except) | 
|  | { | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Like gdbpy_print_stack, but if the exception is a | 
|  | KeyboardException, throw a gdb "quit" instead.  */ | 
|  |  | 
|  | void | 
|  | gdbpy_print_stack_or_quit () | 
|  | { | 
|  | 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) | 
|  | { | 
|  | gdbpy_ref<> list (PyList_New (0)); | 
|  | if (list == NULL) | 
|  | return NULL; | 
|  |  | 
|  | for (struct program_space *ps : program_spaces) | 
|  | { | 
|  | gdbpy_ref<> item = pspace_to_pspace_object (ps); | 
|  |  | 
|  | if (item == NULL || PyList_Append (list.get (), item.get ()) == -1) | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | return list.release (); | 
|  | } | 
|  |  | 
|  | /* Return the name of the current language.  */ | 
|  |  | 
|  | static PyObject * | 
|  | gdbpy_current_language (PyObject *unused1, PyObject *unused2) | 
|  | { | 
|  | return host_string_to_python_string (current_language->name ()).release (); | 
|  | } | 
|  |  | 
|  |  | 
|  |  | 
|  | /* See python.h.  */ | 
|  | struct objfile *gdbpy_current_objfile; | 
|  |  | 
|  | /* Set the current objfile to OBJFILE and then read FILE named FILENAME | 
|  | as Python code.  This does not throw any errors.  If an exception | 
|  | occurs python will print the traceback and clear the error indicator. | 
|  | This is the extension_language_script_ops.objfile_script_sourcer | 
|  | "method".  */ | 
|  |  | 
|  | static void | 
|  | gdbpy_source_objfile_script (const struct extension_language_defn *extlang, | 
|  | struct objfile *objfile, FILE *file, | 
|  | const char *filename) | 
|  | { | 
|  | if (!gdb_python_initialized) | 
|  | return; | 
|  |  | 
|  | gdbpy_enter enter_py (objfile->arch ()); | 
|  | scoped_restore restire_current_objfile | 
|  | = make_scoped_restore (&gdbpy_current_objfile, objfile); | 
|  |  | 
|  | int result = python_run_simple_file (file, filename); | 
|  | if (result != 0) | 
|  | gdbpy_print_stack (); | 
|  | } | 
|  |  | 
|  | /* Set the current objfile to OBJFILE and then execute SCRIPT | 
|  | as Python code.  This does not throw any errors.  If an exception | 
|  | occurs python will print the traceback and clear the error indicator. | 
|  | This is the extension_language_script_ops.objfile_script_executor | 
|  | "method".  */ | 
|  |  | 
|  | static void | 
|  | gdbpy_execute_objfile_script (const struct extension_language_defn *extlang, | 
|  | struct objfile *objfile, const char *name, | 
|  | const char *script) | 
|  | { | 
|  | if (!gdb_python_initialized) | 
|  | return; | 
|  |  | 
|  | gdbpy_enter enter_py (objfile->arch ()); | 
|  | scoped_restore restire_current_objfile | 
|  | = make_scoped_restore (&gdbpy_current_objfile, objfile); | 
|  |  | 
|  | int ret = eval_python_command (script, Py_file_input); | 
|  | if (ret != 0) | 
|  | gdbpy_print_stack (); | 
|  | } | 
|  |  | 
|  | /* Return the current Objfile, or None if there isn't one.  */ | 
|  |  | 
|  | static PyObject * | 
|  | gdbpy_get_current_objfile (PyObject *unused1, PyObject *unused2) | 
|  | { | 
|  | if (! gdbpy_current_objfile) | 
|  | Py_RETURN_NONE; | 
|  |  | 
|  | return objfile_to_objfile_object (gdbpy_current_objfile).release (); | 
|  | } | 
|  |  | 
|  | /* Implement the 'handle_missing_debuginfo' hook for Python.  GDB has | 
|  | failed to find any debug information for OBJFILE.  The extension has a | 
|  | chance to record this, or even install the required debug information. | 
|  | See the description of ext_lang_missing_debuginfo_result in | 
|  | extension-priv.h for details of the return value.  */ | 
|  |  | 
|  | static ext_lang_missing_debuginfo_result | 
|  | gdbpy_handle_missing_debuginfo (const struct extension_language_defn *extlang, | 
|  | struct objfile *objfile) | 
|  | { | 
|  | /* Early exit if Python is not initialised.  */ | 
|  | if (!gdb_python_initialized || gdb_python_module == nullptr) | 
|  | return {}; | 
|  |  | 
|  | struct gdbarch *gdbarch = objfile->arch (); | 
|  |  | 
|  | gdbpy_enter enter_py (gdbarch); | 
|  |  | 
|  | /* Convert OBJFILE into the corresponding Python object.  */ | 
|  | gdbpy_ref<> pyo_objfile = objfile_to_objfile_object (objfile); | 
|  | if (pyo_objfile == nullptr) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | return {}; | 
|  | } | 
|  |  | 
|  | /* Lookup the helper function within the GDB module.  */ | 
|  | gdbpy_ref<> pyo_handler | 
|  | (PyObject_GetAttrString (gdb_python_module, "_handle_missing_debuginfo")); | 
|  | if (pyo_handler == nullptr) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | return {}; | 
|  | } | 
|  |  | 
|  | /* Call the function, passing in the Python objfile object.  */ | 
|  | gdbpy_ref<> pyo_execute_ret | 
|  | (PyObject_CallFunctionObjArgs (pyo_handler.get (), pyo_objfile.get (), | 
|  | nullptr)); | 
|  | if (pyo_execute_ret == nullptr) | 
|  | { | 
|  | /* If the handler is cancelled due to a Ctrl-C, then propagate | 
|  | the Ctrl-C as a GDB exception instead of swallowing it.  */ | 
|  | gdbpy_print_stack_or_quit (); | 
|  | return {}; | 
|  | } | 
|  |  | 
|  | /* Parse the result, and convert it back to the C++ object.  */ | 
|  | if (pyo_execute_ret == Py_None) | 
|  | return {}; | 
|  |  | 
|  | if (PyBool_Check (pyo_execute_ret.get ())) | 
|  | { | 
|  | bool try_again = PyObject_IsTrue (pyo_execute_ret.get ()); | 
|  | return ext_lang_missing_debuginfo_result (try_again); | 
|  | } | 
|  |  | 
|  | if (!gdbpy_is_string (pyo_execute_ret.get ())) | 
|  | { | 
|  | PyErr_SetString (PyExc_ValueError, | 
|  | "return value from _handle_missing_debuginfo should " | 
|  | "be None, a Bool, or a String"); | 
|  | gdbpy_print_stack (); | 
|  | return {}; | 
|  | } | 
|  |  | 
|  | gdb::unique_xmalloc_ptr<char> filename | 
|  | = python_string_to_host_string (pyo_execute_ret.get ()); | 
|  | if (filename == nullptr) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | return {}; | 
|  | } | 
|  |  | 
|  | return ext_lang_missing_debuginfo_result (std::string (filename.get ())); | 
|  | } | 
|  |  | 
|  | /* Compute the list of active python type printers and store them in | 
|  | EXT_PRINTERS->py_type_printers.  The product of this function is used by | 
|  | gdbpy_apply_type_printers, and freed by gdbpy_free_type_printers. | 
|  | This is the extension_language_ops.start_type_printers "method".  */ | 
|  |  | 
|  | static void | 
|  | gdbpy_start_type_printers (const struct extension_language_defn *extlang, | 
|  | struct ext_lang_type_printers *ext_printers) | 
|  | { | 
|  | PyObject *printers_obj = NULL; | 
|  |  | 
|  | if (!gdb_python_initialized) | 
|  | return; | 
|  |  | 
|  | gdbpy_enter enter_py; | 
|  |  | 
|  | gdbpy_ref<> type_module (PyImport_ImportModule ("gdb.types")); | 
|  | if (type_module == NULL) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | return; | 
|  | } | 
|  |  | 
|  | gdbpy_ref<> func (PyObject_GetAttrString (type_module.get (), | 
|  | "get_type_recognizers")); | 
|  | if (func == NULL) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | return; | 
|  | } | 
|  |  | 
|  | printers_obj = PyObject_CallFunctionObjArgs (func.get (), (char *) NULL); | 
|  | if (printers_obj == NULL) | 
|  | gdbpy_print_stack (); | 
|  | else | 
|  | ext_printers->py_type_printers = printers_obj; | 
|  | } | 
|  |  | 
|  | /* If TYPE is recognized by some type printer, store in *PRETTIED_TYPE | 
|  | a newly allocated string holding the type's replacement name, and return | 
|  | EXT_LANG_RC_OK. | 
|  | If there's a Python error return EXT_LANG_RC_ERROR. | 
|  | Otherwise, return EXT_LANG_RC_NOP. | 
|  | This is the extension_language_ops.apply_type_printers "method".  */ | 
|  |  | 
|  | static enum ext_lang_rc | 
|  | gdbpy_apply_type_printers (const struct extension_language_defn *extlang, | 
|  | const struct ext_lang_type_printers *ext_printers, | 
|  | struct type *type, | 
|  | gdb::unique_xmalloc_ptr<char> *prettied_type) | 
|  | { | 
|  | PyObject *printers_obj = (PyObject *) ext_printers->py_type_printers; | 
|  | gdb::unique_xmalloc_ptr<char> result; | 
|  |  | 
|  | if (printers_obj == NULL) | 
|  | return EXT_LANG_RC_NOP; | 
|  |  | 
|  | if (!gdb_python_initialized) | 
|  | return EXT_LANG_RC_NOP; | 
|  |  | 
|  | gdbpy_enter enter_py; | 
|  |  | 
|  | gdbpy_ref<> type_obj (type_to_type_object (type)); | 
|  | if (type_obj == NULL) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | return EXT_LANG_RC_ERROR; | 
|  | } | 
|  |  | 
|  | gdbpy_ref<> type_module (PyImport_ImportModule ("gdb.types")); | 
|  | if (type_module == NULL) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | return EXT_LANG_RC_ERROR; | 
|  | } | 
|  |  | 
|  | gdbpy_ref<> func (PyObject_GetAttrString (type_module.get (), | 
|  | "apply_type_recognizers")); | 
|  | if (func == NULL) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | return EXT_LANG_RC_ERROR; | 
|  | } | 
|  |  | 
|  | gdbpy_ref<> result_obj (PyObject_CallFunctionObjArgs (func.get (), | 
|  | printers_obj, | 
|  | type_obj.get (), | 
|  | (char *) NULL)); | 
|  | if (result_obj == NULL) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | return EXT_LANG_RC_ERROR; | 
|  | } | 
|  |  | 
|  | if (result_obj == Py_None) | 
|  | return EXT_LANG_RC_NOP; | 
|  |  | 
|  | result = python_string_to_host_string (result_obj.get ()); | 
|  | if (result == NULL) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | return EXT_LANG_RC_ERROR; | 
|  | } | 
|  |  | 
|  | *prettied_type = std::move (result); | 
|  | return EXT_LANG_RC_OK; | 
|  | } | 
|  |  | 
|  | /* Free the result of start_type_printers. | 
|  | This is the extension_language_ops.free_type_printers "method".  */ | 
|  |  | 
|  | static void | 
|  | gdbpy_free_type_printers (const struct extension_language_defn *extlang, | 
|  | struct ext_lang_type_printers *ext_printers) | 
|  | { | 
|  | PyObject *printers = (PyObject *) ext_printers->py_type_printers; | 
|  |  | 
|  | if (printers == NULL) | 
|  | return; | 
|  |  | 
|  | if (!gdb_python_initialized) | 
|  | return; | 
|  |  | 
|  | gdbpy_enter enter_py; | 
|  | Py_DECREF (printers); | 
|  | } | 
|  |  | 
|  | #else /* HAVE_PYTHON */ | 
|  |  | 
|  | /* Dummy implementation of the gdb "python-interactive" and "python" | 
|  | command. */ | 
|  |  | 
|  | static void | 
|  | python_interactive_command (const char *arg, int from_tty) | 
|  | { | 
|  | arg = skip_spaces (arg); | 
|  | if (arg && *arg) | 
|  | error (_("Python scripting is not supported in this copy of GDB.")); | 
|  | else | 
|  | { | 
|  | counted_command_line l = get_command_line (python_control, ""); | 
|  |  | 
|  | execute_control_command_untraced (l.get ()); | 
|  | } | 
|  | } | 
|  |  | 
|  | static void | 
|  | python_command (const char *arg, int from_tty) | 
|  | { | 
|  | python_interactive_command (arg, 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; | 
|  |  | 
|  | /* Implement 'show python ignore-environment'.  */ | 
|  |  | 
|  | static void | 
|  | show_python_ignore_environment (struct ui_file *file, int from_tty, | 
|  | struct cmd_list_element *c, const char *value) | 
|  | { | 
|  | gdb_printf (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 is deprecated in Python 3.12.  Disable | 
|  | its usage in Python 3.10 and above since the PyConfig mechanism | 
|  | is now (also) used in 3.10 and higher.  See do_start_initialization() | 
|  | in this file.  */ | 
|  | #if PY_VERSION_HEX < 0x030a0000 | 
|  | Py_IgnoreEnvironmentFlag = python_ignore_environment ? 1 : 0; | 
|  | #endif | 
|  | #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; | 
|  |  | 
|  | /* Implement 'show python dont-write-bytecode'.  */ | 
|  |  | 
|  | static void | 
|  | show_python_dont_write_bytecode (struct ui_file *file, int from_tty, | 
|  | struct cmd_list_element *c, const char *value) | 
|  | { | 
|  | if (python_dont_write_bytecode == AUTO_BOOLEAN_AUTO) | 
|  | { | 
|  | const char *auto_string | 
|  | = (python_ignore_environment | 
|  | || getenv ("PYTHONDONTWRITEBYTECODE") == nullptr) ? "off" : "on"; | 
|  |  | 
|  | gdb_printf (file, | 
|  | _("Python's dont-write-bytecode setting is %s (currently %s).\n"), | 
|  | value, auto_string); | 
|  | } | 
|  | else | 
|  | gdb_printf (file, _("Python's dont-write-bytecode setting is %s.\n"), | 
|  | value); | 
|  | } | 
|  |  | 
|  | #ifdef HAVE_PYTHON | 
|  | /* Return value to assign to PyConfig.write_bytecode or, when | 
|  | negated (via !), Py_DontWriteBytecodeFlag.  Py_DontWriteBytecodeFlag | 
|  | is deprecated in Python 3.12.  */ | 
|  |  | 
|  | static int | 
|  | python_write_bytecode () | 
|  | { | 
|  | int wbc = 0; | 
|  |  | 
|  | if (python_dont_write_bytecode == AUTO_BOOLEAN_AUTO) | 
|  | { | 
|  | if (python_ignore_environment) | 
|  | wbc = 1; | 
|  | else | 
|  | { | 
|  | const char *pdwbc = getenv ("PYTHONDONTWRITEBYTECODE"); | 
|  | wbc = (pdwbc == nullptr || pdwbc[0] == '\0') ? 1 : 0; | 
|  | } | 
|  | } | 
|  | else | 
|  | wbc = python_dont_write_bytecode == AUTO_BOOLEAN_TRUE ? 0 : 1; | 
|  |  | 
|  | return wbc; | 
|  | } | 
|  | #endif /* HAVE_PYTHON */ | 
|  |  | 
|  | /* 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 | 
|  | set_python_dont_write_bytecode (const char *args, int from_tty, | 
|  | struct cmd_list_element *c) | 
|  | { | 
|  | #ifdef HAVE_PYTHON | 
|  | /* Py_DontWriteBytecodeFlag is deprecated in Python 3.12.  Disable | 
|  | its usage in Python 3.10 and above since the PyConfig mechanism | 
|  | is now (also) used in 3.10 and higher.  See do_start_initialization() | 
|  | in this file.  */ | 
|  | #if PY_VERSION_HEX < 0x030a0000 | 
|  | Py_DontWriteBytecodeFlag = !python_write_bytecode (); | 
|  | #endif | 
|  | #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 | 
|  |  | 
|  | /* This is installed as a final cleanup and cleans up the | 
|  | interpreter.  This lets Python's 'atexit' work.  */ | 
|  |  | 
|  | static void | 
|  | finalize_python (const struct extension_language_defn *ignore) | 
|  | { | 
|  | struct active_ext_lang_state *previous_active; | 
|  |  | 
|  | /* We don't use ensure_python_env here because if we ever ran the | 
|  | cleanup, gdb would crash -- because the cleanup calls into the | 
|  | Python interpreter, which we are about to destroy.  It seems | 
|  | clearer to make the needed calls explicitly here than to create a | 
|  | cleanup and then mysteriously discard it.  */ | 
|  |  | 
|  | /* This is only called as a final cleanup so we can assume the active | 
|  | SIGINT handler is gdb's.  We still need to tell it to notify Python.  */ | 
|  | previous_active = set_active_ext_lang (&extension_language_python); | 
|  |  | 
|  | (void) PyGILState_Ensure (); | 
|  | gdbpy_enter::finalize (); | 
|  |  | 
|  | /* Call the gdbpy_finalize_* functions from every *.c file.  */ | 
|  | gdbpy_initialize_file::finalize_all (); | 
|  |  | 
|  | Py_Finalize (); | 
|  |  | 
|  | gdb_python_initialized = false; | 
|  | restore_active_ext_lang (previous_active); | 
|  | } | 
|  |  | 
|  | 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); | 
|  | } | 
|  |  | 
|  | /* Emit a gdb.GdbExitingEvent, return a negative value if there are any | 
|  | errors, otherwise, return 0.  */ | 
|  |  | 
|  | static int | 
|  | emit_exiting_event (int exit_code) | 
|  | { | 
|  | if (evregpy_no_listeners_p (gdb_py_events.gdb_exiting)) | 
|  | return 0; | 
|  |  | 
|  | gdbpy_ref<> event_obj = create_event_object (&gdb_exiting_event_object_type); | 
|  | if (event_obj == nullptr) | 
|  | return -1; | 
|  |  | 
|  | gdbpy_ref<> code = gdb_py_object_from_longest (exit_code); | 
|  | if (evpy_add_attribute (event_obj.get (), "exit_code", code.get ()) < 0) | 
|  | return -1; | 
|  |  | 
|  | return evpy_emit_event (event_obj.get (), gdb_py_events.gdb_exiting); | 
|  | } | 
|  |  | 
|  | /* Callback for the gdb_exiting observable.  EXIT_CODE is the value GDB | 
|  | will exit with.  */ | 
|  |  | 
|  | static void | 
|  | gdbpy_gdb_exiting (int exit_code) | 
|  | { | 
|  | if (!gdb_python_initialized) | 
|  | return; | 
|  |  | 
|  | gdbpy_enter enter_py; | 
|  |  | 
|  | if (emit_exiting_event (exit_code) < 0) | 
|  | gdbpy_print_stack (); | 
|  | } | 
|  |  | 
|  | static bool | 
|  | do_start_initialization () | 
|  | { | 
|  | /* Define all internal modules.  These are all imported (and thus | 
|  | created) during initialization.  */ | 
|  | struct _inittab mods[] = | 
|  | { | 
|  | { "_gdb", init__gdb_module }, | 
|  | { "_gdbevents", gdbpy_events_mod_func }, | 
|  | { nullptr, nullptr } | 
|  | }; | 
|  |  | 
|  | if (PyImport_ExtendInittab (mods) < 0) | 
|  | return false; | 
|  |  | 
|  | #ifdef WITH_PYTHON_PATH | 
|  | /* Work around problem where python gets confused about where it is, | 
|  | and then can't find its libraries, etc. | 
|  | NOTE: Python assumes the following layout: | 
|  | /foo/bin/python | 
|  | /foo/lib/pythonX.Y/... | 
|  | This must be done before calling Py_Initialize.  */ | 
|  | gdb::unique_xmalloc_ptr<char> progname | 
|  | (concat (ldirname (python_libdir.c_str ()).c_str (), SLASH_STRING, "bin", | 
|  | SLASH_STRING, "python", (char *) NULL)); | 
|  | /* 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, ""); | 
|  | 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"); | 
|  | return false; | 
|  | } | 
|  | setlocale (LC_ALL, oldloc.c_str ()); | 
|  |  | 
|  | /* Py_SetProgramName was deprecated in Python 3.11.  Use PyConfig | 
|  | mechanisms for Python 3.10 and newer.  */ | 
|  | #if PY_VERSION_HEX < 0x030a0000 | 
|  | /* Note that Py_SetProgramName expects the string it is passed to | 
|  | remain alive for the duration of the program's execution, so | 
|  | it is not freed after this call.  */ | 
|  | Py_SetProgramName (progname_copy); | 
|  | Py_Initialize (); | 
|  | #else | 
|  | PyConfig config; | 
|  |  | 
|  | PyConfig_InitPythonConfig (&config); | 
|  | PyStatus status = PyConfig_SetString (&config, &config.program_name, | 
|  | progname_copy); | 
|  | if (PyStatus_Exception (status)) | 
|  | goto init_done; | 
|  |  | 
|  | config.write_bytecode = python_write_bytecode (); | 
|  | config.use_environment = !python_ignore_environment; | 
|  |  | 
|  | status = PyConfig_Read (&config); | 
|  | if (PyStatus_Exception (status)) | 
|  | goto init_done; | 
|  |  | 
|  | status = Py_InitializeFromConfig (&config); | 
|  |  | 
|  | init_done: | 
|  | PyConfig_Clear (&config); | 
|  | if (PyStatus_Exception (status)) | 
|  | return false; | 
|  | #endif | 
|  | #else | 
|  | Py_Initialize (); | 
|  | #endif | 
|  |  | 
|  | #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 | 
|  |  | 
|  | gdb_module = PyImport_ImportModule ("_gdb"); | 
|  | if (gdb_module == NULL) | 
|  | return false; | 
|  |  | 
|  | if (PyModule_AddStringConstant (gdb_module, "VERSION", version) < 0 | 
|  | || PyModule_AddStringConstant (gdb_module, "HOST_CONFIG", host_name) < 0 | 
|  | || PyModule_AddStringConstant (gdb_module, "TARGET_CONFIG", | 
|  | target_name) < 0) | 
|  | return false; | 
|  |  | 
|  | /* Add stream constants.  */ | 
|  | if (PyModule_AddIntConstant (gdb_module, "STDOUT", 0) < 0 | 
|  | || PyModule_AddIntConstant (gdb_module, "STDERR", 1) < 0 | 
|  | || PyModule_AddIntConstant (gdb_module, "STDLOG", 2) < 0) | 
|  | return false; | 
|  |  | 
|  | gdbpy_gdb_error = PyErr_NewException ("gdb.error", PyExc_RuntimeError, NULL); | 
|  | if (gdbpy_gdb_error == NULL | 
|  | || gdb_pymodule_addobject (gdb_module, "error", gdbpy_gdb_error) < 0) | 
|  | return false; | 
|  |  | 
|  | gdbpy_gdb_memory_error = PyErr_NewException ("gdb.MemoryError", | 
|  | gdbpy_gdb_error, NULL); | 
|  | if (gdbpy_gdb_memory_error == NULL | 
|  | || gdb_pymodule_addobject (gdb_module, "MemoryError", | 
|  | gdbpy_gdb_memory_error) < 0) | 
|  | return false; | 
|  |  | 
|  | gdbpy_gdberror_exc = PyErr_NewException ("gdb.GdbError", NULL, NULL); | 
|  | if (gdbpy_gdberror_exc == NULL | 
|  | || gdb_pymodule_addobject (gdb_module, "GdbError", | 
|  | gdbpy_gdberror_exc) < 0) | 
|  | return false; | 
|  |  | 
|  | /* Call the gdbpy_initialize_* functions from every *.c file.  */ | 
|  | if (!gdbpy_initialize_file::initialize_all ()) | 
|  | return false; | 
|  |  | 
|  | #define GDB_PY_DEFINE_EVENT_TYPE(name, py_name, doc, base)	\ | 
|  | if (gdbpy_initialize_event_generic (&name##_event_object_type, py_name) < 0) \ | 
|  | return false; | 
|  | #include "py-event-types.def" | 
|  | #undef GDB_PY_DEFINE_EVENT_TYPE | 
|  |  | 
|  | gdbpy_to_string_cst = PyUnicode_FromString ("to_string"); | 
|  | if (gdbpy_to_string_cst == NULL) | 
|  | return false; | 
|  | gdbpy_children_cst = PyUnicode_FromString ("children"); | 
|  | if (gdbpy_children_cst == NULL) | 
|  | return false; | 
|  | gdbpy_display_hint_cst = PyUnicode_FromString ("display_hint"); | 
|  | if (gdbpy_display_hint_cst == NULL) | 
|  | return false; | 
|  | gdbpy_doc_cst = PyUnicode_FromString ("__doc__"); | 
|  | if (gdbpy_doc_cst == NULL) | 
|  | return false; | 
|  | gdbpy_enabled_cst = PyUnicode_FromString ("enabled"); | 
|  | if (gdbpy_enabled_cst == NULL) | 
|  | return false; | 
|  | gdbpy_value_cst = PyUnicode_FromString ("value"); | 
|  | if (gdbpy_value_cst == NULL) | 
|  | return false; | 
|  |  | 
|  | gdb::observers::gdb_exiting.attach (gdbpy_gdb_exiting, "python"); | 
|  |  | 
|  | /* Release the GIL while gdb runs.  */ | 
|  | PyEval_SaveThread (); | 
|  |  | 
|  | /* Only set this when initialization has succeeded.  */ | 
|  | gdb_python_initialized = 1; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | #if GDB_SELF_TEST | 
|  | namespace selftests { | 
|  |  | 
|  | /* Entry point for python unit tests.  */ | 
|  |  | 
|  | static void | 
|  | test_python () | 
|  | { | 
|  | #define CMD(S) execute_command_to_string (S, "python print(5)", 0, true) | 
|  |  | 
|  | std::string output; | 
|  |  | 
|  | CMD (output); | 
|  | SELF_CHECK (output == "5\n"); | 
|  | output.clear (); | 
|  |  | 
|  | bool saw_exception = false; | 
|  | { | 
|  | scoped_restore reset_gdb_python_initialized | 
|  | = make_scoped_restore (&gdb_python_initialized, 0); | 
|  | try | 
|  | { | 
|  | CMD (output); | 
|  | } | 
|  | catch (const gdb_exception &e) | 
|  | { | 
|  | saw_exception = true; | 
|  | SELF_CHECK (e.reason == RETURN_ERROR); | 
|  | SELF_CHECK (e.error == GENERIC_ERROR); | 
|  | SELF_CHECK (*e.message == "Python not initialized"); | 
|  | } | 
|  | SELF_CHECK (saw_exception); | 
|  | SELF_CHECK (output.empty ()); | 
|  | } | 
|  |  | 
|  | saw_exception = false; | 
|  | { | 
|  | scoped_restore save_hook | 
|  | = make_scoped_restore (&hook_set_active_ext_lang, | 
|  | []() { raise (SIGINT); }); | 
|  | try | 
|  | { | 
|  | CMD (output); | 
|  | } | 
|  | catch (const gdb_exception_quit &e) | 
|  | { | 
|  | saw_exception = true; | 
|  | SELF_CHECK (e.reason == RETURN_QUIT); | 
|  | SELF_CHECK (e.error == GDB_NO_ERROR); | 
|  | SELF_CHECK (*e.message == "Quit"); | 
|  | } | 
|  | SELF_CHECK (saw_exception); | 
|  | SELF_CHECK (output.empty ()); | 
|  | } | 
|  |  | 
|  | #undef CMD | 
|  | } | 
|  |  | 
|  | #undef CHECK_OUTPUT | 
|  |  | 
|  | } // namespace selftests | 
|  | #endif /* GDB_SELF_TEST */ | 
|  |  | 
|  | #endif /* HAVE_PYTHON */ | 
|  |  | 
|  | /* See python.h.  */ | 
|  | cmd_list_element *python_cmd_element = nullptr; | 
|  |  | 
|  | void _initialize_python (); | 
|  | void | 
|  | _initialize_python () | 
|  | { | 
|  | cmd_list_element *python_interactive_cmd | 
|  | =	add_com ("python-interactive", class_obscure, | 
|  | python_interactive_command, | 
|  | #ifdef HAVE_PYTHON | 
|  | _("\ | 
|  | Start an interactive Python prompt.\n\ | 
|  | \n\ | 
|  | To return to GDB, type the EOF character (e.g., Ctrl-D on an empty\n\ | 
|  | prompt).\n\ | 
|  | \n\ | 
|  | Alternatively, a single-line Python command can be given as an\n\ | 
|  | 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") | 
|  | #else /* HAVE_PYTHON */ | 
|  | _("\ | 
|  | Start a Python interactive prompt.\n\ | 
|  | \n\ | 
|  | Python scripting is not supported in this copy of GDB.\n\ | 
|  | This command is only a placeholder.") | 
|  | #endif /* HAVE_PYTHON */ | 
|  | ); | 
|  | add_com_alias ("pi", python_interactive_cmd, class_obscure, 1); | 
|  |  | 
|  | 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\ | 
|  | \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\ | 
|  | the end of the command.") | 
|  | #else /* HAVE_PYTHON */ | 
|  | _("\ | 
|  | Evaluate a Python command.\n\ | 
|  | \n\ | 
|  | Python scripting is not supported in this copy of GDB.\n\ | 
|  | This command is only a placeholder.") | 
|  | #endif /* HAVE_PYTHON */ | 
|  | ); | 
|  | add_com_alias ("py", python_cmd_element, class_obscure, 1); | 
|  |  | 
|  | /* Add set/show python print-stack.  */ | 
|  | add_setshow_prefix_cmd ("python", no_class, | 
|  | _("Prefix command for python preference settings."), | 
|  | _("Prefix command for python preference settings."), | 
|  | &user_set_python_list, &user_show_python_list, | 
|  | &setlist, &showlist); | 
|  |  | 
|  | add_setshow_enum_cmd ("print-stack", no_class, python_excp_enums, | 
|  | &gdbpy_should_print_stack, _("\ | 
|  | Set mode for Python stack dump on error."), _("\ | 
|  | Show the mode of Python stack printing on error."), _("\ | 
|  | none  == no stack or message will be printed.\n\ | 
|  | full == a message and a stack will be printed.\n\ | 
|  | message == an error message without a stack will be printed."), | 
|  | NULL, NULL, | 
|  | &user_set_python_list, | 
|  | &user_show_python_list); | 
|  |  | 
|  | 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 avoid byte-compiling python modules."), _("\ | 
|  | Show whether the Python interpreter should avoid byte-compiling python modules."), _("\ | 
|  | When enabled, GDB's embedded Python interpreter won't byte-compile python\n\ | 
|  | modules.  In order to take effect, this setting must be enabled in an early\n\ | 
|  | initialization file, i.e. those run via the --early-init-eval-command or\n\ | 
|  | -eix command line options.  A 'set python dont-write-bytecode on' command\n\ | 
|  | can also be issued directly from the GDB command line via the\n\ | 
|  | --early-init-eval-command or -eiex command line options.\n\ | 
|  | \n\ | 
|  | This setting defaults to 'auto'.  In this mode, provided the 'python\n\ | 
|  | ignore-environment' setting is 'off', the environment variable\n\ | 
|  | PYTHONDONTWRITEBYTECODE is examined to determine whether or not to\n\ | 
|  | byte-compile python modules.  PYTHONDONTWRITEBYTECODE is considered to be\n\ | 
|  | off/disabled either when set to the empty string or when the\n\ | 
|  | environment variable doesn't exist.  All other settings, including those\n\ | 
|  | which don't seem to make sense, indicate that it's on/enabled."), | 
|  | set_python_dont_write_bytecode, | 
|  | show_python_dont_write_bytecode, | 
|  | &user_set_python_list, | 
|  | &user_show_python_list); | 
|  |  | 
|  | #ifdef HAVE_PYTHON | 
|  | #if GDB_SELF_TEST | 
|  | selftests::register_test ("python", selftests::test_python); | 
|  | #endif /* GDB_SELF_TEST */ | 
|  | #endif /* HAVE_PYTHON */ | 
|  | } | 
|  |  | 
|  | #ifdef HAVE_PYTHON | 
|  |  | 
|  | /* 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_initialize (const struct extension_language_defn *extlang) | 
|  | { | 
|  | PyObject *m; | 
|  | PyObject *sys_path; | 
|  |  | 
|  | /* Add the initial data-directory to sys.path.  */ | 
|  |  | 
|  | std::string gdb_pythondir = (std::string (gdb_datadir) + SLASH_STRING | 
|  | + "python"); | 
|  |  | 
|  | sys_path = PySys_GetObject ("path"); | 
|  |  | 
|  | /* PySys_SetPath was deprecated in Python 3.11.  Disable this | 
|  | deprecated code for Python 3.10 and newer.  Also note that this | 
|  | ifdef eliminates potential initialization of sys.path via | 
|  | PySys_SetPath.  My (kevinb's) understanding of PEP 587 suggests | 
|  | that it's not necessary due to module_search_paths being | 
|  | initialized to an empty list following any of the PyConfig | 
|  | initialization functions.  If it does turn out that some kind of | 
|  | initialization is still needed, it should be added to the | 
|  | PyConfig-based initialization in do_start_initialize().  */ | 
|  | #if PY_VERSION_HEX < 0x030a0000 | 
|  | /* If sys.path is not defined yet, define it first.  */ | 
|  | if (!(sys_path && PyList_Check (sys_path))) | 
|  | { | 
|  | PySys_SetPath (L""); | 
|  | sys_path = PySys_GetObject ("path"); | 
|  | } | 
|  | #endif | 
|  | if (sys_path && PyList_Check (sys_path)) | 
|  | { | 
|  | gdbpy_ref<> pythondir (PyUnicode_FromString (gdb_pythondir.c_str ())); | 
|  | if (pythondir == NULL || PyList_Insert (sys_path, 0, pythondir.get ())) | 
|  | return false; | 
|  | } | 
|  | else | 
|  | return false; | 
|  |  | 
|  | /* Import the gdb module to finish the initialization, and | 
|  | add it to __main__ for convenience.  */ | 
|  | m = PyImport_AddModule ("__main__"); | 
|  | if (m == NULL) | 
|  | return false; | 
|  |  | 
|  | /* Keep the reference to gdb_python_module since it is in a global | 
|  | variable.  */ | 
|  | gdb_python_module = PyImport_ImportModule ("gdb"); | 
|  | if (gdb_python_module == NULL) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | /* This is passed in one call to warning so that blank lines aren't | 
|  | inserted between each line of text.  */ | 
|  | 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."), | 
|  | gdb_pythondir.c_str ()); | 
|  | /* We return "success" here as we've already emitted the | 
|  | warning.  */ | 
|  | return true; | 
|  | } | 
|  |  | 
|  | return gdb_pymodule_addobject (m, "gdb", gdb_python_module) >= 0; | 
|  | } | 
|  |  | 
|  | /* 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_initialize (const struct extension_language_defn *extlang) | 
|  | { | 
|  | if (!do_start_initialization () && PyErr_Occurred ()) | 
|  | gdbpy_print_stack (); | 
|  |  | 
|  | gdbpy_enter enter_py; | 
|  |  | 
|  | if (!do_initialize (extlang)) | 
|  | { | 
|  | gdbpy_print_stack (); | 
|  | warning (_("internal error: Unhandled Python exception")); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Return non-zero if Python has successfully initialized. | 
|  | This is the extension_languages_ops.initialized "method".  */ | 
|  |  | 
|  | static int | 
|  | gdbpy_initialized (const struct extension_language_defn *extlang) | 
|  | { | 
|  | return gdb_python_initialized; | 
|  | } | 
|  |  | 
|  | PyMethodDef python_GdbMethods[] = | 
|  | { | 
|  | { "history", gdbpy_history, METH_VARARGS, | 
|  | "Get a value from history" }, | 
|  | { "add_history", gdbpy_add_history, METH_VARARGS, | 
|  | "Add a value to the value history list" }, | 
|  | { "history_count", gdbpy_history_count, METH_NOARGS, | 
|  | "Return an integer, the number of values in GDB's value history" }, | 
|  | { "execute", (PyCFunction) execute_gdb_command, METH_VARARGS | METH_KEYWORDS, | 
|  | "execute (command [, from_tty] [, to_string]) -> [String]\n\ | 
|  | Evaluate command, a string, as a gdb CLI command.  Optionally returns\n\ | 
|  | a Python String containing the output of the command if to_string is\n\ | 
|  | set to True." }, | 
|  | { "execute_mi", (PyCFunction) gdbpy_execute_mi_command, | 
|  | METH_VARARGS | METH_KEYWORDS, | 
|  | "execute_mi (command, arg...) -> dictionary\n\ | 
|  | Evaluate command, a string, as a gdb MI command.\n\ | 
|  | Arguments (also strings) are passed to the command." }, | 
|  | { "parameter", gdbpy_parameter, METH_VARARGS, | 
|  | "Return a gdb parameter's value" }, | 
|  |  | 
|  | { "breakpoints", gdbpy_breakpoints, METH_NOARGS, | 
|  | "Return a tuple of all breakpoint objects" }, | 
|  |  | 
|  | { "default_visualizer", gdbpy_default_visualizer, METH_VARARGS, | 
|  | "Find the default visualizer for a Value." }, | 
|  |  | 
|  | { "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." }, | 
|  |  | 
|  | { "newest_frame", gdbpy_newest_frame, METH_NOARGS, | 
|  | "newest_frame () -> gdb.Frame.\n\ | 
|  | Return the newest frame object." }, | 
|  | { "selected_frame", gdbpy_selected_frame, METH_NOARGS, | 
|  | "selected_frame () -> gdb.Frame.\n\ | 
|  | Return the selected frame object." }, | 
|  | { "frame_stop_reason_string", gdbpy_frame_stop_reason_string, METH_VARARGS, | 
|  | "stop_reason_string (Integer) -> String.\n\ | 
|  | Return a string explaining unwind stop reason." }, | 
|  |  | 
|  | { "start_recording", gdbpy_start_recording, METH_VARARGS, | 
|  | "start_recording ([method] [, format]) -> gdb.Record.\n\ | 
|  | Start recording with the given method.  If no method is given, will fall back\n\ | 
|  | to the system default method.  If no format is given, will fall back to the\n\ | 
|  | default format for the given method."}, | 
|  | { "current_recording", gdbpy_current_recording, METH_NOARGS, | 
|  | "current_recording () -> gdb.Record.\n\ | 
|  | Return current recording object." }, | 
|  | { "stop_recording", gdbpy_stop_recording, METH_NOARGS, | 
|  | "stop_recording () -> None.\n\ | 
|  | Stop current recording." }, | 
|  |  | 
|  | { "lookup_type", (PyCFunction) gdbpy_lookup_type, | 
|  | METH_VARARGS | METH_KEYWORDS, | 
|  | "lookup_type (name [, block]) -> type\n\ | 
|  | Return a Type corresponding to the given name." }, | 
|  | { "lookup_symbol", (PyCFunction) gdbpy_lookup_symbol, | 
|  | METH_VARARGS | METH_KEYWORDS, | 
|  | "lookup_symbol (name [, block] [, domain]) -> (symbol, is_field_of_this)\n\ | 
|  | Return a tuple with the symbol corresponding to the given name (or None) and\n\ | 
|  | a boolean indicating if name is a field of the current implied argument\n\ | 
|  | `this' (when the current language is object-oriented)." }, | 
|  | { "lookup_global_symbol", (PyCFunction) gdbpy_lookup_global_symbol, | 
|  | 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, | 
|  | "lookup_objfile (name, [by_build_id]) -> objfile\n\ | 
|  | 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." }, | 
|  |  | 
|  | { "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\ | 
|  | The first element contains any unparsed portion of the String parameter\n\ | 
|  | (or None if the string was fully parsed).  The second element contains\n\ | 
|  | a tuple that contains all the locations that match, represented as\n\ | 
|  | gdb.Symtab_and_line objects (or None)."}, | 
|  | { "parse_and_eval", (PyCFunction) gdbpy_parse_and_eval, | 
|  | METH_VARARGS | METH_KEYWORDS, | 
|  | "parse_and_eval (String, [Boolean]) -> Value.\n\ | 
|  | Parse String as an expression, evaluate it, and return the result as a Value." | 
|  | }, | 
|  |  | 
|  | { "post_event", gdbpy_post_event, METH_VARARGS, | 
|  | "Post an event into gdb's event loop." }, | 
|  | { "interrupt", gdbpy_interrupt, METH_NOARGS, | 
|  | "Interrupt gdb's current operation." }, | 
|  |  | 
|  | { "target_charset", gdbpy_target_charset, METH_NOARGS, | 
|  | "target_charset () -> string.\n\ | 
|  | 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." }, | 
|  | { "host_charset", gdbpy_host_charset, METH_NOARGS, | 
|  | "host_charset () -> string.\n\ | 
|  | Return the name of the current host 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\ | 
|  | Arguments are separate by spaces and may be quoted." | 
|  | }, | 
|  | { "write", (PyCFunction)gdbpy_write, METH_VARARGS | METH_KEYWORDS, | 
|  | "Write a string using gdb's filtered stream." }, | 
|  | { "flush", (PyCFunction)gdbpy_flush, METH_VARARGS | METH_KEYWORDS, | 
|  | "Flush gdb's filtered stdout stream." }, | 
|  | { "selected_thread", gdbpy_selected_thread, METH_NOARGS, | 
|  | "selected_thread () -> gdb.InferiorThread.\n\ | 
|  | Return the selected thread object." }, | 
|  | { "selected_inferior", gdbpy_selected_inferior, METH_NOARGS, | 
|  | "selected_inferior () -> gdb.Inferior.\n\ | 
|  | Return the selected inferior object." }, | 
|  | { "inferiors", gdbpy_inferiors, METH_NOARGS, | 
|  | "inferiors () -> (gdb.Inferior, ...).\n\ | 
|  | Return a tuple containing all inferiors." }, | 
|  |  | 
|  | { "invalidate_cached_frames", gdbpy_invalidate_cached_frames, METH_NOARGS, | 
|  | "invalidate_cached_frames () -> None.\n\ | 
|  | Invalidate any cached frame objects in gdb.\n\ | 
|  | Intended for internal use only." }, | 
|  |  | 
|  | { "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 TUI | 
|  | { "register_window_type", (PyCFunction) gdbpy_register_tui_window, | 
|  | METH_VARARGS | METH_KEYWORDS, | 
|  | "register_window_type (NAME, CONSTRUCTOR) -> None\n\ | 
|  | Register a TUI window constructor." }, | 
|  | #endif	/* TUI */ | 
|  |  | 
|  | { "architecture_names", gdbpy_all_architecture_names, METH_NOARGS, | 
|  | "architecture_names () -> List.\n\ | 
|  | Return a list of all the architecture names GDB understands." }, | 
|  |  | 
|  | { "connections", gdbpy_connections, METH_NOARGS, | 
|  | "connections () -> List.\n\ | 
|  | Return a list of gdb.TargetConnection objects." }, | 
|  |  | 
|  | { "format_address", (PyCFunction) gdbpy_format_address, | 
|  | METH_VARARGS | METH_KEYWORDS, | 
|  | "format_address (ADDRESS, PROG_SPACE, ARCH) -> String.\n\ | 
|  | Format ADDRESS, an address within PROG_SPACE, a gdb.Progspace, using\n\ | 
|  | ARCH, a gdb.Architecture to determine the address size.  The format of\n\ | 
|  | the returned string is 'ADDRESS <SYMBOL+OFFSET>' without the quotes." }, | 
|  |  | 
|  | { "current_language", gdbpy_current_language, METH_NOARGS, | 
|  | "current_language () -> string\n\ | 
|  | Return the name of the currently selected language." }, | 
|  |  | 
|  | { "print_options", gdbpy_print_options, METH_NOARGS, | 
|  | "print_options () -> dict\n\ | 
|  | Return the current print options." }, | 
|  |  | 
|  | { "notify_mi", (PyCFunction) gdbpy_notify_mi, | 
|  | METH_VARARGS | METH_KEYWORDS, | 
|  | "notify_mi (name, data) -> None\n\ | 
|  | Output async record to MI channels if any." }, | 
|  | {NULL, NULL, 0, NULL} | 
|  | }; | 
|  |  | 
|  | /* 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") \ | 
|  | = { \ | 
|  | PyVarObject_HEAD_INIT (NULL, 0)				\ | 
|  | "gdb." py_name,                             /* tp_name */ \ | 
|  | sizeof (event_object),                      /* tp_basicsize */ \ | 
|  | 0,                                          /* tp_itemsize */ \ | 
|  | evpy_dealloc,                               /* tp_dealloc */ \ | 
|  | 0,                                          /* tp_print */ \ | 
|  | 0,                                          /* tp_getattr */ \ | 
|  | 0,                                          /* tp_setattr */ \ | 
|  | 0,                                          /* tp_compare */ \ | 
|  | 0,                                          /* tp_repr */ \ | 
|  | 0,                                          /* tp_as_number */ \ | 
|  | 0,                                          /* tp_as_sequence */ \ | 
|  | 0,                                          /* tp_as_mapping */ \ | 
|  | 0,                                          /* tp_hash  */ \ | 
|  | 0,                                          /* tp_call */ \ | 
|  | 0,                                          /* tp_str */ \ | 
|  | 0,                                          /* tp_getattro */ \ | 
|  | 0,                                          /* tp_setattro */ \ | 
|  | 0,                                          /* tp_as_buffer */ \ | 
|  | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,   /* tp_flags */ \ | 
|  | doc,                                        /* tp_doc */ \ | 
|  | 0,                                          /* tp_traverse */ \ | 
|  | 0,                                          /* tp_clear */ \ | 
|  | 0,                                          /* tp_richcompare */ \ | 
|  | 0,                                          /* tp_weaklistoffset */ \ | 
|  | 0,                                          /* tp_iter */ \ | 
|  | 0,                                          /* tp_iternext */ \ | 
|  | 0,                                          /* tp_methods */ \ | 
|  | 0,                                          /* tp_members */ \ | 
|  | 0,                                          /* tp_getset */ \ | 
|  | &base,                                      /* tp_base */ \ | 
|  | 0,                                          /* tp_dict */ \ | 
|  | 0,                                          /* tp_descr_get */ \ | 
|  | 0,                                          /* tp_descr_set */ \ | 
|  | 0,                                          /* tp_dictoffset */ \ | 
|  | 0,                                          /* tp_init */ \ | 
|  | 0                                           /* tp_alloc */ \ | 
|  | }; | 
|  | #include "py-event-types.def" | 
|  | #undef GDB_PY_DEFINE_EVENT_TYPE | 
|  |  | 
|  | #endif /* HAVE_PYTHON */ |