public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/3] Improvements to Python parameters
@ 2022-01-05 17:13 Tom Tromey
  2022-01-05 17:13 ` [PATCH 1/3] Change how Python architecture and language are handled Tom Tromey
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Tom Tromey @ 2022-01-05 17:13 UTC (permalink / raw)
  To: gdb-patches

This series fixes a few problems with gdb parameters when used from
Python.

Currently, gdb captures the current language on entry to Python.
However, this means that Python scripts can't affect this setting in a
meaningful way.  However, that is bad because such scripts are often
dependent on the current language -- for example, for symbol lookup or
expression evaluation.

I also found some crashes involving parameters.  The second patch in
particular tries to make such crashes harder to introduce.

Finally, this adds a convenience API to make it easy to temporarily
modify a gdb parameter for a block of Python code.

Let me know what you think.  I'm particularly interested in whether
the API is reasonable.

Regression tested on x86-64 Fedora 34.

Tom



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/3] Change how Python architecture and language are handled
  2022-01-05 17:13 [PATCH 0/3] Improvements to Python parameters Tom Tromey
@ 2022-01-05 17:13 ` Tom Tromey
  2022-01-10 15:35   ` Andrew Burgess
  2022-01-05 17:13 ` [PATCH 2/3] Fix another crash with gdb parameters in Python Tom Tromey
  2022-01-05 17:13 ` [PATCH 3/3] Add a way to temporarily set a gdb parameter from Python Tom Tromey
  2 siblings, 1 reply; 10+ messages in thread
From: Tom Tromey @ 2022-01-05 17:13 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

Currently, gdb's Python layer captures the current architecture and
language when "entering" Python code.  This has some undesirable
effects, and so this series changes how this is handled.

First, there is code like this:

  gdbpy_enter enter_py (python_gdbarch, python_language);

This is incorrect, because both of these are NULL when not otherwise
assigned.  This can cause crashes in some cases -- I've added one to
the test suite.  (Note that this crasher is just an example, other
ones along the same lines are possible.)

Second, when the language is captured in this way, it means that
Python code cannot affect the current language for its own purposes.
It's reasonable to want to write code like this:

    gdb.execute('set language mumble')
    ... stuff using the current language
    gdb.execute('set language previous-value')

However, this won't actually work, because the language is captured on
entry.  I've added a test to show this as well.

This patch changes gdb to try to avoid capturing the current values.
The Python concept of the current gdbarch is only set in those few
cases where a non-default value is computed or needed; and the
language is not captured at all -- instead, in the cases where it's
required, the current language is temporarily changed.
---
 gdb/python/py-breakpoint.c                  | 19 ++-----
 gdb/python/py-cmd.c                         |  8 +--
 gdb/python/py-connection.c                  |  2 +-
 gdb/python/py-finishbreakpoint.c            |  6 +-
 gdb/python/py-framefilter.c                 | 12 ++--
 gdb/python/py-inferior.c                    | 27 +++++----
 gdb/python/py-membuf.c                      |  3 +-
 gdb/python/py-objfile.c                     |  2 +-
 gdb/python/py-param.c                       |  4 +-
 gdb/python/py-progspace.c                   |  2 +-
 gdb/python/py-tui.c                         | 18 +++---
 gdb/python/py-type.c                        |  4 +-
 gdb/python/py-unwind.c                      |  2 +-
 gdb/python/py-utils.c                       | 10 ++--
 gdb/python/py-value.c                       | 21 ++++---
 gdb/python/py-xmethods.c                    | 12 ++--
 gdb/python/python-internal.h                | 20 +++++--
 gdb/python/python.c                         | 62 +++++++++++++--------
 gdb/testsuite/gdb.python/py-inferior.exp    |  2 +
 gdb/testsuite/gdb.python/py-lookup-type.exp |  8 +++
 20 files changed, 139 insertions(+), 105 deletions(-)

diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
index f00bd6f78e6..c1cb34879bd 100644
--- a/gdb/python/py-breakpoint.c
+++ b/gdb/python/py-breakpoint.c
@@ -858,7 +858,7 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
 	    const struct breakpoint_ops *ops =
 	      breakpoint_ops_for_event_location (location.get (), false);
 
-	    create_breakpoint (python_gdbarch,
+	    create_breakpoint (gdbpy_enter::get_gdbarch (),
 			       location.get (), NULL, -1, NULL, false,
 			       0,
 			       temporary_bp, type,
@@ -954,15 +954,13 @@ gdbpy_breakpoint_cond_says_stop (const struct extension_language_defn *extlang,
   int stop;
   struct gdbpy_breakpoint_object *bp_obj = b->py_bp_object;
   PyObject *py_bp = (PyObject *) bp_obj;
-  struct gdbarch *garch;
 
   if (bp_obj == NULL)
     return EXT_LANG_BP_STOP_UNSET;
 
   stop = -1;
-  garch = b->gdbarch ? b->gdbarch : get_current_arch ();
 
-  gdbpy_enter enter_py (garch, current_language);
+  gdbpy_enter enter_py (b->gdbarch ? b->gdbarch : nullptr);
 
   if (bp_obj->is_finish_bp)
     bpfinishpy_pre_stop_hook (bp_obj);
@@ -1005,15 +1003,13 @@ gdbpy_breakpoint_has_cond (const struct extension_language_defn *extlang,
 			   struct breakpoint *b)
 {
   PyObject *py_bp;
-  struct gdbarch *garch;
 
   if (b->py_bp_object == NULL)
     return 0;
 
   py_bp = (PyObject *) b->py_bp_object;
-  garch = b->gdbarch ? b->gdbarch : get_current_arch ();
 
-  gdbpy_enter enter_py (garch, current_language);
+  gdbpy_enter enter_py (b->gdbarch ? b->gdbarch : nullptr);
   return PyObject_HasAttrString (py_bp, stop_func);
 }
 
@@ -1048,8 +1044,7 @@ gdbpy_breakpoint_created (struct breakpoint *bp)
       return;
     }
 
-  struct gdbarch *garch = bp->gdbarch ? bp->gdbarch : get_current_arch ();
-  gdbpy_enter enter_py (garch, current_language);
+  gdbpy_enter enter_py (bp->gdbarch ? bp->gdbarch : nullptr);
 
   if (bppy_pending_object)
     {
@@ -1099,8 +1094,7 @@ gdbpy_breakpoint_deleted (struct breakpoint *b)
   bp = get_breakpoint (num);
   if (bp)
     {
-      struct gdbarch *garch = bp->gdbarch ? bp->gdbarch : get_current_arch ();
-      gdbpy_enter enter_py (garch, current_language);
+      gdbpy_enter enter_py (b->gdbarch ? b->gdbarch : nullptr);
 
       gdbpy_ref<gdbpy_breakpoint_object> bp_obj (bp->py_bp_object);
       if (bp_obj != NULL)
@@ -1131,8 +1125,7 @@ gdbpy_breakpoint_modified (struct breakpoint *b)
   bp = get_breakpoint (num);
   if (bp)
     {
-      struct gdbarch *garch = bp->gdbarch ? bp->gdbarch : get_current_arch ();
-      gdbpy_enter enter_py (garch, current_language);
+      gdbpy_enter enter_py (b->gdbarch ? b->gdbarch : nullptr);
 
       PyObject *bp_obj = (PyObject *) bp->py_bp_object;
       if (bp_obj)
diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c
index 3a4e6490cf0..b51b05c95ad 100644
--- a/gdb/python/py-cmd.c
+++ b/gdb/python/py-cmd.c
@@ -90,7 +90,7 @@ cmdpy_dont_repeat (PyObject *self, PyObject *args)
 static void
 cmdpy_destroyer (struct cmd_list_element *self, void *context)
 {
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
 
   /* Release our hold on the command object.  */
   gdbpy_ref<cmdpy_object> cmd ((cmdpy_object *) context);
@@ -104,7 +104,7 @@ cmdpy_function (const char *args, int from_tty, cmd_list_element *command)
 {
   cmdpy_object *obj = (cmdpy_object *) command->context ();
 
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
 
   if (! obj)
     error (_("Invalid invocation of Python command object."));
@@ -223,7 +223,7 @@ cmdpy_completer_handle_brkchars (struct cmd_list_element *command,
 				 completion_tracker &tracker,
 				 const char *text, const char *word)
 {
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
 
   /* Calling our helper to obtain a reference to the PyObject of the Python
      function.  */
@@ -266,7 +266,7 @@ cmdpy_completer (struct cmd_list_element *command,
 		 completion_tracker &tracker,
 		 const char *text, const char *word)
 {
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
 
   /* Calling our helper to obtain a reference to the PyObject of the Python
      function.  */
diff --git a/gdb/python/py-connection.c b/gdb/python/py-connection.c
index 7c33a1f93d4..4cdd6abbf3d 100644
--- a/gdb/python/py-connection.c
+++ b/gdb/python/py-connection.c
@@ -161,7 +161,7 @@ connpy_connection_removed (process_stratum_target *target)
   if (!gdb_python_initialized)
     return;
 
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
 
   if (!evregpy_no_listeners_p (gdb_py_events.connection_removed))
     if (emit_connection_event (target, gdb_py_events.connection_removed) < 0)
diff --git a/gdb/python/py-finishbreakpoint.c b/gdb/python/py-finishbreakpoint.c
index 8d5eb42efc0..03bd4934506 100644
--- a/gdb/python/py-finishbreakpoint.c
+++ b/gdb/python/py-finishbreakpoint.c
@@ -293,7 +293,7 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
       /* Set a breakpoint on the return address.  */
       event_location_up location
 	= new_address_location (get_frame_pc (prev_frame), NULL, 0);
-      create_breakpoint (python_gdbarch,
+      create_breakpoint (gdbpy_enter::get_gdbarch (),
 			 location.get (), NULL, thread, NULL, false,
 			 0,
 			 1 /*temp_flag*/,
@@ -380,7 +380,7 @@ bpfinishpy_detect_out_scope_cb (struct breakpoint *b,
 static void
 bpfinishpy_handle_stop (struct bpstat *bs, int print_frame)
 {
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
 
   for (breakpoint *bp : all_breakpoints_safe ())
     bpfinishpy_detect_out_scope_cb (bp, bs == NULL ? NULL : bs->breakpoint_at);
@@ -392,7 +392,7 @@ bpfinishpy_handle_stop (struct bpstat *bs, int print_frame)
 static void
 bpfinishpy_handle_exit (struct inferior *inf)
 {
-  gdbpy_enter enter_py (target_gdbarch (), current_language);
+  gdbpy_enter enter_py (target_gdbarch ());
 
   for (breakpoint *bp : all_breakpoints_safe ())
     bpfinishpy_detect_out_scope_cb (bp, nullptr);
diff --git a/gdb/python/py-framefilter.c b/gdb/python/py-framefilter.c
index 936354f354c..7870374b3ec 100644
--- a/gdb/python/py-framefilter.c
+++ b/gdb/python/py-framefilter.c
@@ -74,11 +74,11 @@ extract_sym (PyObject *obj, gdb::unique_xmalloc_ptr<char> *name,
       if (*name == NULL)
 	return EXT_LANG_BT_ERROR;
       /* If the API returns a string (and not a symbol), then there is
-	no symbol derived language available and the frame filter has
-	either overridden the symbol with a string, or supplied a
-	entirely synthetic symbol/value pairing.  In that case, use
-	python_language.  */
-      *language = python_language;
+	 no symbol derived language available and the frame filter has
+	 either overridden the symbol with a string, or supplied a
+	 entirely synthetic symbol/value pairing.  In that case, use
+	 the current language.  */
+      *language = current_language;
       *sym = NULL;
       *sym_block = NULL;
     }
@@ -1157,7 +1157,7 @@ gdbpy_apply_frame_filter (const struct extension_language_defn *extlang,
       return EXT_LANG_BT_NO_FILTERS;
     }
 
-  gdbpy_enter enter_py (gdbarch, current_language);
+  gdbpy_enter enter_py (gdbarch);
 
   /* When we're limiting the number of frames, be careful to request
      one extra frame, so that we can print a message if there are more
diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c
index 6b1443db2a8..0e5895da918 100644
--- a/gdb/python/py-inferior.c
+++ b/gdb/python/py-inferior.c
@@ -86,7 +86,7 @@ python_on_normal_stop (struct bpstat *bs, int print_frame)
 
   stop_signal = inferior_thread ()->stop_signal ();
 
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
 
   if (emit_stop_event (bs, stop_signal) < 0)
     gdbpy_print_stack ();
@@ -98,7 +98,7 @@ python_on_resume (ptid_t ptid)
   if (!gdb_python_initialized)
     return;
 
-  gdbpy_enter enter_py (target_gdbarch (), current_language);
+  gdbpy_enter enter_py (target_gdbarch ());
 
   if (emit_continue_event (ptid) < 0)
     gdbpy_print_stack ();
@@ -110,7 +110,7 @@ python_on_resume (ptid_t ptid)
 static void
 python_on_inferior_call_pre (ptid_t thread, CORE_ADDR address)
 {
-  gdbpy_enter enter_py (target_gdbarch (), current_language);
+  gdbpy_enter enter_py (target_gdbarch ());
 
   if (emit_inferior_call_event (INFERIOR_CALL_PRE, thread, address) < 0)
     gdbpy_print_stack ();
@@ -122,7 +122,7 @@ python_on_inferior_call_pre (ptid_t thread, CORE_ADDR address)
 static void
 python_on_inferior_call_post (ptid_t thread, CORE_ADDR address)
 {
-  gdbpy_enter enter_py (target_gdbarch (), current_language);
+  gdbpy_enter enter_py (target_gdbarch ());
 
   if (emit_inferior_call_event (INFERIOR_CALL_POST, thread, address) < 0)
     gdbpy_print_stack ();
@@ -135,7 +135,7 @@ python_on_inferior_call_post (ptid_t thread, CORE_ADDR address)
 static void
 python_on_memory_change (struct inferior *inferior, CORE_ADDR addr, ssize_t len, const bfd_byte *data)
 {
-  gdbpy_enter enter_py (target_gdbarch (), current_language);
+  gdbpy_enter enter_py (target_gdbarch ());
 
   if (emit_memory_changed_event (addr, len) < 0)
     gdbpy_print_stack ();
@@ -148,7 +148,7 @@ python_on_memory_change (struct inferior *inferior, CORE_ADDR addr, ssize_t len,
 static void
 python_on_register_change (struct frame_info *frame, int regnum)
 {
-  gdbpy_enter enter_py (target_gdbarch (), current_language);
+  gdbpy_enter enter_py (target_gdbarch ());
 
   if (emit_register_changed_event (frame, regnum) < 0)
     gdbpy_print_stack ();
@@ -162,7 +162,7 @@ python_inferior_exit (struct inferior *inf)
   if (!gdb_python_initialized)
     return;
 
-  gdbpy_enter enter_py (target_gdbarch (), current_language);
+  gdbpy_enter enter_py (target_gdbarch ());
 
   if (inf->has_exit_code)
     exit_code = &inf->exit_code;
@@ -183,8 +183,7 @@ python_new_objfile (struct objfile *objfile)
 
   gdbpy_enter enter_py (objfile != NULL
 			? objfile->arch ()
-			: target_gdbarch (),
-			current_language);
+			: target_gdbarch ());
 
   if (objfile == NULL)
     {
@@ -237,7 +236,7 @@ python_new_inferior (struct inferior *inf)
   if (!gdb_python_initialized)
     return;
 
-  gdbpy_enter enter_py (python_gdbarch, python_language);
+  gdbpy_enter enter_py;
 
   if (evregpy_no_listeners_p (gdb_py_events.new_inferior))
     return;
@@ -265,7 +264,7 @@ python_inferior_deleted (struct inferior *inf)
   if (!gdb_python_initialized)
     return;
 
-  gdbpy_enter enter_py (python_gdbarch, python_language);
+  gdbpy_enter enter_py;
 
   if (evregpy_no_listeners_p (gdb_py_events.inferior_deleted))
     return;
@@ -312,7 +311,7 @@ add_thread_object (struct thread_info *tp)
   if (!gdb_python_initialized)
     return;
 
-  gdbpy_enter enter_py (python_gdbarch, python_language);
+  gdbpy_enter enter_py;
 
   gdbpy_ref<thread_object> thread_obj = create_thread_object (tp);
   if (thread_obj == NULL)
@@ -347,7 +346,7 @@ delete_thread_object (struct thread_info *tp, int ignore)
   if (!gdb_python_initialized)
     return;
 
-  gdbpy_enter enter_py (python_gdbarch, python_language);
+  gdbpy_enter enter_py;
 
   gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (tp->inf);
   if (inf_obj == NULL)
@@ -791,7 +790,7 @@ py_free_inferior (struct inferior *inf, void *datum)
   if (!gdb_python_initialized)
     return;
 
-  gdbpy_enter enter_py (python_gdbarch, python_language);
+  gdbpy_enter enter_py;
   gdbpy_ref<inferior_object> inf_obj ((inferior_object *) datum);
 
   inf_obj->inferior = NULL;
diff --git a/gdb/python/py-membuf.c b/gdb/python/py-membuf.c
index e789a78e649..74cc0fb46bd 100644
--- a/gdb/python/py-membuf.c
+++ b/gdb/python/py-membuf.c
@@ -83,7 +83,8 @@ mbpy_str (PyObject *self)
 
   return PyString_FromFormat (_("Memory buffer for address %s, \
 which is %s bytes long."),
-			      paddress (python_gdbarch, membuf_obj->addr),
+			      paddress (gdbpy_enter::get_gdbarch (),
+					membuf_obj->addr),
 			      pulongest (membuf_obj->length));
 }
 
diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
index 38052245bde..6055a42260b 100644
--- a/gdb/python/py-objfile.c
+++ b/gdb/python/py-objfile.c
@@ -661,7 +661,7 @@ gdbpy_lookup_objfile (PyObject *self, PyObject *args, PyObject *kw)
 static void
 py_free_objfile (struct objfile *objfile, void *datum)
 {
-  gdbpy_enter enter_py (objfile->arch (), current_language);
+  gdbpy_enter enter_py (objfile->arch ());
   gdbpy_ref<objfile_object> object ((objfile_object *) datum);
   object->objfile = NULL;
 }
diff --git a/gdb/python/py-param.c b/gdb/python/py-param.c
index 592ecbb41f9..8559bc997ea 100644
--- a/gdb/python/py-param.c
+++ b/gdb/python/py-param.c
@@ -396,7 +396,7 @@ get_set_value (const char *args, int from_tty,
   PyObject *obj = (PyObject *) c->context ();
   gdb::unique_xmalloc_ptr<char> set_doc_string;
 
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
   gdbpy_ref<> set_doc_func (PyString_FromString ("get_set_string"));
 
   if (set_doc_func == NULL)
@@ -431,7 +431,7 @@ get_show_value (struct ui_file *file, int from_tty,
   PyObject *obj = (PyObject *) c->context ();
   gdb::unique_xmalloc_ptr<char> show_doc_string;
 
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
   gdbpy_ref<> show_doc_func (PyString_FromString ("get_show_string"));
 
   if (show_doc_func == NULL)
diff --git a/gdb/python/py-progspace.c b/gdb/python/py-progspace.c
index 8131b66d24b..b27ebf4a666 100644
--- a/gdb/python/py-progspace.c
+++ b/gdb/python/py-progspace.c
@@ -472,7 +472,7 @@ py_free_pspace (struct program_space *pspace, void *datum)
      being deleted.  */
   struct gdbarch *arch = target_gdbarch ();
 
-  gdbpy_enter enter_py (arch, current_language);
+  gdbpy_enter enter_py (arch);
   gdbpy_ref<pspace_object> object ((pspace_object *) datum);
   object->pspace = NULL;
 }
diff --git a/gdb/python/py-tui.c b/gdb/python/py-tui.c
index 97fdfe2be96..6a92251a705 100644
--- a/gdb/python/py-tui.c
+++ b/gdb/python/py-tui.c
@@ -155,7 +155,7 @@ gdbpy_tui_window::is_valid () const
 
 tui_py_window::~tui_py_window ()
 {
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
 
   /* This can be null if the user-provided Python construction
      function failed.  */
@@ -181,7 +181,7 @@ tui_py_window::rerender ()
 {
   tui_win_info::rerender ();
 
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
 
   int h = viewport_height ();
   int w = viewport_width ();
@@ -206,7 +206,7 @@ tui_py_window::rerender ()
 void
 tui_py_window::do_scroll_horizontal (int num_to_scroll)
 {
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
 
   if (PyObject_HasAttrString (m_window.get (), "hscroll"))
     {
@@ -220,7 +220,7 @@ tui_py_window::do_scroll_horizontal (int num_to_scroll)
 void
 tui_py_window::do_scroll_vertical (int num_to_scroll)
 {
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
 
   if (PyObject_HasAttrString (m_window.get (), "vscroll"))
     {
@@ -234,7 +234,7 @@ tui_py_window::do_scroll_vertical (int num_to_scroll)
 void
 tui_py_window::click (int mouse_x, int mouse_y, int mouse_button)
 {
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
 
   if (PyObject_HasAttrString (m_window.get (), "click"))
     {
@@ -285,7 +285,7 @@ class gdbpy_tui_window_maker
 
   gdbpy_tui_window_maker (const gdbpy_tui_window_maker &other)
   {
-    gdbpy_enter enter_py (get_current_arch (), current_language);
+    gdbpy_enter enter_py;
     m_constr = other.m_constr;
   }
 
@@ -297,7 +297,7 @@ class gdbpy_tui_window_maker
 
   gdbpy_tui_window_maker &operator= (const gdbpy_tui_window_maker &other)
   {
-    gdbpy_enter enter_py (get_current_arch (), current_language);
+    gdbpy_enter enter_py;
     m_constr = other.m_constr;
     return *this;
   }
@@ -312,14 +312,14 @@ class gdbpy_tui_window_maker
 
 gdbpy_tui_window_maker::~gdbpy_tui_window_maker ()
 {
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
   m_constr.reset (nullptr);
 }
 
 tui_win_info *
 gdbpy_tui_window_maker::operator() (const char *win_name)
 {
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
 
   gdbpy_ref<gdbpy_tui_window> wrapper
     (PyObject_New (gdbpy_tui_window, &gdbpy_tui_window_object_type));
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index 220b0d46ffb..e71e635ecdf 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -799,7 +799,7 @@ typy_lookup_typename (const char *type_name, const struct block *block)
       else if (startswith (type_name, "enum "))
 	type = lookup_enum (type_name + 5, NULL);
       else
-	type = lookup_typename (python_language,
+	type = lookup_typename (current_language,
 				type_name, block, 0);
     }
   catch (const gdb_exception &except)
@@ -1089,7 +1089,7 @@ save_objfile_types (struct objfile *objfile, void *datum)
 
   /* This prevents another thread from freeing the objects we're
      operating on.  */
-  gdbpy_enter enter_py (objfile->arch (), current_language);
+  gdbpy_enter enter_py (objfile->arch ());
 
   htab_up copied_types = create_copied_types_hash (objfile);
 
diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c
index a884c83ec26..3f10122860e 100644
--- a/gdb/python/py-unwind.c
+++ b/gdb/python/py-unwind.c
@@ -524,7 +524,7 @@ pyuw_sniffer (const struct frame_unwind *self, struct frame_info *this_frame,
   struct gdbarch *gdbarch = (struct gdbarch *) (self->unwind_data);
   cached_frame_info *cached_frame;
 
-  gdbpy_enter enter_py (gdbarch, current_language);
+  gdbpy_enter enter_py (gdbarch);
 
   pyuw_debug_printf ("frame=%d, sp=%s, pc=%s",
 		     frame_relative_level (this_frame),
diff --git a/gdb/python/py-utils.c b/gdb/python/py-utils.c
index 79e1c013261..73c860bcc96 100644
--- a/gdb/python/py-utils.c
+++ b/gdb/python/py-utils.c
@@ -93,8 +93,9 @@ unicode_to_encoded_python_string (PyObject *unicode_str, const char *charset)
 gdb::unique_xmalloc_ptr<char>
 unicode_to_target_string (PyObject *unicode_str)
 {
-  return unicode_to_encoded_string (unicode_str,
-				    target_charset (python_gdbarch));
+  return (unicode_to_encoded_string
+	  (unicode_str,
+	   target_charset (gdbpy_enter::get_gdbarch ())));
 }
 
 /* Returns a PyObject with the contents of the given unicode string
@@ -104,8 +105,9 @@ unicode_to_target_string (PyObject *unicode_str)
 static gdbpy_ref<>
 unicode_to_target_python_string (PyObject *unicode_str)
 {
-  return unicode_to_encoded_python_string (unicode_str,
-					   target_charset (python_gdbarch));
+  return (unicode_to_encoded_python_string
+	  (unicode_str,
+	   target_charset (gdbpy_enter::get_gdbarch ())));
 }
 
 /* Converts a python string (8-bit or unicode) to a target string in
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index 70b33d5a27b..d6ceb54fed8 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -35,23 +35,26 @@
    GDB (which uses target arithmetic).  */
 
 /* Python's integer type corresponds to C's long type.  */
-#define builtin_type_pyint builtin_type (python_gdbarch)->builtin_long
+#define builtin_type_pyint \
+  builtin_type (gdbpy_enter::get_gdbarch ())->builtin_long
 
 /* Python's float type corresponds to C's double type.  */
-#define builtin_type_pyfloat builtin_type (python_gdbarch)->builtin_double
+#define builtin_type_pyfloat \
+  builtin_type (gdbpy_enter::get_gdbarch ())->builtin_double
 
 /* Python's long type corresponds to C's long long type.  */
-#define builtin_type_pylong builtin_type (python_gdbarch)->builtin_long_long
+#define builtin_type_pylong \
+  builtin_type (gdbpy_enter::get_gdbarch ())->builtin_long_long
 
 /* Python's long type corresponds to C's long long type.  Unsigned version.  */
 #define builtin_type_upylong builtin_type \
-  (python_gdbarch)->builtin_unsigned_long_long
+  (gdbpy_enter::get_gdbarch ())->builtin_unsigned_long_long
 
 #define builtin_type_pybool \
-  language_bool_type (python_language, python_gdbarch)
+  language_bool_type (current_language, gdbpy_enter::get_gdbarch ())
 
 #define builtin_type_pychar \
-  language_string_char_type (python_language, python_gdbarch)
+  language_string_char_type (current_language, gdbpy_enter::get_gdbarch ())
 
 struct value_object {
   PyObject_HEAD
@@ -754,7 +757,7 @@ valpy_format_string (PyObject *self, PyObject *args, PyObject *kw)
   try
     {
       common_val_print (((value_object *) self)->value, &stb, 0,
-			&opts, python_language);
+			&opts, current_language);
     }
   catch (const gdb_exception &except)
     {
@@ -1160,7 +1163,7 @@ valpy_str (PyObject *self)
   try
     {
       common_val_print (((value_object *) self)->value, &stb, 0,
-			&opts, python_language);
+			&opts, current_language);
     }
   catch (const gdb_exception &except)
     {
@@ -2025,7 +2028,7 @@ gdbpy_convenience_variable (PyObject *self, PyObject *args)
 
       if (var != NULL)
 	{
-	  res_val = value_of_internalvar (python_gdbarch, var);
+	  res_val = value_of_internalvar (gdbpy_enter::get_gdbarch (), var);
 	  if (value_type (res_val)->code () == TYPE_CODE_VOID)
 	    res_val = NULL;
 	}
diff --git a/gdb/python/py-xmethods.c b/gdb/python/py-xmethods.c
index fd3673029a0..9d5824962b1 100644
--- a/gdb/python/py-xmethods.c
+++ b/gdb/python/py-xmethods.c
@@ -69,7 +69,7 @@ struct python_xmethod_worker : xmethod_worker
 python_xmethod_worker::~python_xmethod_worker ()
 {
   /* We don't do much here, but we still need the GIL.  */
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
 
   Py_DECREF (m_py_worker);
   Py_DECREF (m_this_type);
@@ -122,7 +122,7 @@ gdbpy_get_matching_xmethod_workers
 {
   gdb_assert (obj_type != NULL && method_name != NULL);
 
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
 
   gdbpy_ref<> py_type (type_to_type_object (obj_type));
   if (py_type == NULL)
@@ -294,7 +294,7 @@ python_xmethod_worker::do_get_arg_types (std::vector<type *> *arg_types)
 {
   /* The gdbpy_enter object needs to be placed first, so that it's the last to
      be destroyed.  */
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
   struct type *obj_type;
   int i = 1, arg_count;
   gdbpy_ref<> list_iter;
@@ -410,7 +410,7 @@ python_xmethod_worker::do_get_result_type (value *obj,
   struct type *obj_type, *this_type;
   int i;
 
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
 
   /* First see if there is a get_result_type method.
      If not this could be an old xmethod (pre 7.9.1).  */
@@ -502,7 +502,7 @@ struct value *
 python_xmethod_worker::invoke (struct value *obj,
 			       gdb::array_view<value *> args)
 {
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
 
   int i;
   struct type *obj_type, *this_type;
@@ -580,7 +580,7 @@ python_xmethod_worker::invoke (struct value *obj,
     }
   else
     {
-      res = allocate_value (lookup_typename (python_language,
+      res = allocate_value (lookup_typename (current_language,
 					     "void", NULL, 0));
     }
 
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 583989c5a6d..b6550343ad4 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -625,14 +625,29 @@ class gdbpy_enter
 {
  public:
 
-  gdbpy_enter (struct gdbarch *gdbarch, const struct language_defn *language);
+  explicit gdbpy_enter (struct gdbarch *gdbarch = nullptr,
+			const struct language_defn *language = nullptr);
 
   ~gdbpy_enter ();
 
   DISABLE_COPY_AND_ASSIGN (gdbpy_enter);
 
+  /* Return the current gdbarch, as known to the Python layer.  This
+     is either python_gdbarch (which comes from the most recent call
+     to the gdbpy_enter constructor), or, if that is nullptr, the
+     result of get_current_arch.  */
+  static struct gdbarch *get_gdbarch ();
+
+  /* Called only during gdb shutdown.  This sets python_gdbarch to an
+     acceptable value.  */
+  static void finalize ();
+
  private:
 
+  /* The current gdbarch, according to Python.  This can be
+     nullptr.  */
+  static struct gdbarch *python_gdbarch;
+
   struct active_ext_lang_state *m_previous_active;
   PyGILState_STATE m_state;
   struct gdbarch *m_gdbarch;
@@ -680,9 +695,6 @@ class gdbpy_allow_threads
   PyThreadState *m_save;
 };
 
-extern struct gdbarch *python_gdbarch;
-extern const struct language_defn *python_language;
-
 /* Use this after a TRY_EXCEPT to throw the appropriate Python
    exception.  */
 #define GDB_PY_HANDLE_EXCEPTION(Exception)	\
diff --git a/gdb/python/python.c b/gdb/python/python.c
index e05b99c0bec..d1b03aec328 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -192,13 +192,12 @@ const struct extension_language_defn extension_language_python =
 
 /* Architecture and language to be used in callbacks from
    the Python interpreter.  */
-struct gdbarch *python_gdbarch;
-const struct language_defn *python_language;
+struct gdbarch *gdbpy_enter::python_gdbarch;
 
 gdbpy_enter::gdbpy_enter  (struct gdbarch *gdbarch,
 			   const struct language_defn *language)
 : m_gdbarch (python_gdbarch),
-  m_language (python_language)
+  m_language (language == nullptr ? nullptr : current_language)
 {
   /* We should not ever enter Python unless initialized.  */
   if (!gdb_python_initialized)
@@ -209,7 +208,8 @@ gdbpy_enter::gdbpy_enter  (struct gdbarch *gdbarch,
   m_state = PyGILState_Ensure ();
 
   python_gdbarch = gdbarch;
-  python_language = language;
+  if (language != nullptr)
+    set_language (language->la_language);
 
   /* Save it and ensure ! PyErr_Occurred () afterwards.  */
   m_error.emplace ();
@@ -228,12 +228,27 @@ gdbpy_enter::~gdbpy_enter ()
   m_error->restore ();
 
   python_gdbarch = m_gdbarch;
-  python_language = m_language;
+  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 = target_gdbarch ();
+}
+
 /* A helper class to save and restore the GIL, but without touching
    the other globals that are handled by gdbpy_enter.  */
 
@@ -318,7 +333,7 @@ python_interactive_command (const char *arg, int from_tty)
 
   arg = skip_spaces (arg);
 
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
 
   if (arg && *arg)
     {
@@ -412,7 +427,7 @@ gdbpy_eval_from_control_command (const struct extension_language_defn *extlang,
   if (cmd->body_list_1 != nullptr)
     error (_("Invalid \"python\" block structure."));
 
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
 
   std::string script = compute_python_string (cmd->body_list_0.get ());
   ret = PyRun_SimpleString (script.c_str ());
@@ -425,7 +440,7 @@ gdbpy_eval_from_control_command (const struct extension_language_defn *extlang,
 static void
 python_command (const char *arg, int from_tty)
 {
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
 
   scoped_restore save_async = make_scoped_restore (&current_ui->async, 0);
 
@@ -556,7 +571,7 @@ gdbpy_parameter (PyObject *self, PyObject *args)
 static PyObject *
 gdbpy_target_charset (PyObject *self, PyObject *args)
 {
-  const char *cset = target_charset (python_gdbarch);
+  const char *cset = target_charset (gdbpy_enter::get_gdbarch ());
 
   return PyUnicode_Decode (cset, strlen (cset), host_charset (), NULL);
 }
@@ -566,7 +581,7 @@ gdbpy_target_charset (PyObject *self, PyObject *args)
 static PyObject *
 gdbpy_target_wide_charset (PyObject *self, PyObject *args)
 {
-  const char *cset = target_wide_charset (python_gdbarch);
+  const char *cset = target_wide_charset (gdbpy_enter::get_gdbarch ());
 
   return PyUnicode_Decode (cset, strlen (cset), host_charset (), NULL);
 }
@@ -857,7 +872,7 @@ gdbpy_decode_line (PyObject *self, PyObject *args)
     }
 
   if (arg != NULL)
-    location = string_to_event_location_basic (&arg, python_language,
+    location = string_to_event_location_basic (&arg, current_language,
 					       symbol_name_match_type::WILD);
 
   std::vector<symtab_and_line> decoded_sals;
@@ -962,7 +977,7 @@ static void
 gdbpy_source_script (const struct extension_language_defn *extlang,
 		     FILE *file, const char *filename)
 {
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
   python_run_simple_file (file, filename);
 }
 
@@ -1001,7 +1016,7 @@ struct gdbpy_event
 
   void operator() ()
   {
-    gdbpy_enter enter_py (get_current_arch (), current_language);
+    gdbpy_enter enter_py;
 
     gdbpy_ref<> call_result (PyObject_CallObject (m_func, NULL));
     if (call_result == NULL)
@@ -1050,7 +1065,7 @@ gdbpy_before_prompt_hook (const struct extension_language_defn *extlang,
   if (!gdb_python_initialized)
     return EXT_LANG_RC_NOP;
 
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
 
   if (!evregpy_no_listeners_p (gdb_py_events.before_prompt)
       && evpy_emit_event (NULL, gdb_py_events.before_prompt) < 0)
@@ -1125,7 +1140,7 @@ gdbpy_colorize (const std::string &filename, const std::string &contents)
   if (!gdb_python_initialized)
     return {};
 
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
 
   if (gdb_python_module == nullptr
       || !PyObject_HasAttrString (gdb_python_module, "colorize"))
@@ -1390,7 +1405,7 @@ gdbpy_source_objfile_script (const struct extension_language_defn *extlang,
   if (!gdb_python_initialized)
     return;
 
-  gdbpy_enter enter_py (objfile->arch (), current_language);
+  gdbpy_enter enter_py (objfile->arch ());
   scoped_restore restire_current_objfile
     = make_scoped_restore (&gdbpy_current_objfile, objfile);
 
@@ -1411,7 +1426,7 @@ gdbpy_execute_objfile_script (const struct extension_language_defn *extlang,
   if (!gdb_python_initialized)
     return;
 
-  gdbpy_enter enter_py (objfile->arch (), current_language);
+  gdbpy_enter enter_py (objfile->arch ());
   scoped_restore restire_current_objfile
     = make_scoped_restore (&gdbpy_current_objfile, objfile);
 
@@ -1443,7 +1458,7 @@ gdbpy_start_type_printers (const struct extension_language_defn *extlang,
   if (!gdb_python_initialized)
     return;
 
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
 
   gdbpy_ref<> type_module (PyImport_ImportModule ("gdb.types"));
   if (type_module == NULL)
@@ -1488,7 +1503,7 @@ gdbpy_apply_type_printers (const struct extension_language_defn *extlang,
   if (!gdb_python_initialized)
     return EXT_LANG_RC_NOP;
 
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
 
   gdbpy_ref<> type_obj (type_to_type_object (type));
   if (type_obj == NULL)
@@ -1551,7 +1566,7 @@ gdbpy_free_type_printers (const struct extension_language_defn *extlang,
   if (!gdb_python_initialized)
     return;
 
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
   Py_DECREF (printers);
 }
 
@@ -1686,8 +1701,7 @@ finalize_python (void *ignore)
   previous_active = set_active_ext_lang (&extension_language_python);
 
   (void) PyGILState_Ensure ();
-  python_gdbarch = target_gdbarch ();
-  python_language = current_language;
+  gdbpy_enter::finalize ();
 
   Py_Finalize ();
 
@@ -1746,7 +1760,7 @@ gdbpy_gdb_exiting (int exit_code)
   if (!gdb_python_initialized)
     return;
 
-  gdbpy_enter enter_py (python_gdbarch, python_language);
+  gdbpy_enter enter_py;
 
   if (emit_exiting_event (exit_code) < 0)
     gdbpy_print_stack ();
@@ -2164,7 +2178,7 @@ gdbpy_initialize (const struct extension_language_defn *extlang)
   if (!do_start_initialization () && PyErr_Occurred ())
     gdbpy_print_stack ();
 
-  gdbpy_enter enter_py (get_current_arch (), current_language);
+  gdbpy_enter enter_py;
 
   if (!do_initialize (extlang))
     {
diff --git a/gdb/testsuite/gdb.python/py-inferior.exp b/gdb/testsuite/gdb.python/py-inferior.exp
index 5b5f58243e4..aa78a1540cf 100644
--- a/gdb/testsuite/gdb.python/py-inferior.exp
+++ b/gdb/testsuite/gdb.python/py-inferior.exp
@@ -220,6 +220,7 @@ with_test_prefix "is_valid" {
     gdb_test "python print (inf_list\[0\].is_valid())" "True" \
 	"check inferior validity 1"
 
+    # The "dummy" line below used to cause a gdb crash.
     gdb_test_multiline "install new inferior event handler" \
 	"python" "" \
 	"my_inferior_count = 1" "" \
@@ -227,6 +228,7 @@ with_test_prefix "is_valid" {
 	"  global my_inferior_count" "" \
 	"  if evt.inferior is not None:" "" \
 	"    my_inferior_count = my_inferior_count + 1" "" \
+	"    dummy = gdb.Value(True)" "" \
 	"gdb.events.new_inferior.connect(new_inf_handler)" "" \
 	"end" ""
     gdb_test_multiline "install inferior deleted event handler" \
diff --git a/gdb/testsuite/gdb.python/py-lookup-type.exp b/gdb/testsuite/gdb.python/py-lookup-type.exp
index 52a1dae20ed..534a5fd418e 100644
--- a/gdb/testsuite/gdb.python/py-lookup-type.exp
+++ b/gdb/testsuite/gdb.python/py-lookup-type.exp
@@ -54,3 +54,11 @@ test_lookup_type "opencl" "ushort"
 test_lookup_type "objective-c" "char"
 
 test_lookup_type "pascal" "char"
+
+# Ensure that the language can be changed from within Python and still
+# affect the results.
+gdb_test_multiline "look up ada type from another language" \
+    "python" "" \
+    "gdb.execute('set language ada')" "" \
+    "print(gdb.lookup_type('character'))" "" \
+    "end" "character"
-- 
2.31.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 2/3] Fix another crash with gdb parameters in Python
  2022-01-05 17:13 [PATCH 0/3] Improvements to Python parameters Tom Tromey
  2022-01-05 17:13 ` [PATCH 1/3] Change how Python architecture and language are handled Tom Tromey
@ 2022-01-05 17:13 ` Tom Tromey
  2022-01-10 15:46   ` Andrew Burgess
  2022-01-05 17:13 ` [PATCH 3/3] Add a way to temporarily set a gdb parameter from Python Tom Tromey
  2 siblings, 1 reply; 10+ messages in thread
From: Tom Tromey @ 2022-01-05 17:13 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

While looking into the language-capturing issue, I found another way
to crash gdb using parameters from Python:

(gdb) python print(gdb.parameter('endian'))

(This is related to PR python/12188, though this patch isn't going to
fix what that bug is really about.)

The problem here is that the global variable that underlies the
"endian" parameter is initialized to NULL.  However, that's not a
valid value for an "enum" set/show parameter.

My understanding is that, in gdb, an "enum" parameter's underlying
variable must have a value that is "==" (not just strcmp-equal) to one
of the values coming from the enum array.  This invariant is relied on
in various places.

I started this patch by fixing the problem with "endian".  Then I
added some assertions to add_setshow_enum_cmd to try to catch other
problems of the same type.

This patch fixes all the problems that I found.  I also looked at all
the calls to add_setshow_enum_cmd to ensure that they were all
included in the gdb I tested.  I think they are: there are no calls in
nat-* files, or in remote-sim.c; and I was trying a build with all
targets, Python, and Guile enabled.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=12188
---
 gdb/arch-utils.c                          |  5 +++--
 gdb/arm-tdep.c                            |  2 ++
 gdb/charset.c                             |  9 +++++++++
 gdb/cli/cli-decode.c                      | 10 ++++++++++
 gdb/guile/scm-param.c                     |  4 ++--
 gdb/language.c                            | 11 ++++++-----
 gdb/osabi.c                               |  4 +++-
 gdb/python/py-param.c                     |  4 ++--
 gdb/testsuite/gdb.python/py-parameter.exp |  4 ++++
 9 files changed, 41 insertions(+), 12 deletions(-)

diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c
index 38e3132668d..3ee978a0249 100644
--- a/gdb/arch-utils.c
+++ b/gdb/arch-utils.c
@@ -359,7 +359,7 @@ static const char *const endian_enum[] =
   endian_auto,
   NULL,
 };
-static const char *set_endian_string;
+static const char *set_endian_string = endian_auto;
 
 enum bfd_endian
 selected_byte_order (void)
@@ -757,7 +757,8 @@ initialize_current_architecture (void)
      list of architectures.  */
   {
     /* Append ``auto''.  */
-    arches.push_back ("auto");
+    set_architecture_string = "auto";
+    arches.push_back (set_architecture_string);
     arches.push_back (nullptr);
     set_show_commands architecture_cmds
       = add_setshow_enum_cmd ("architecture", class_support,
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index d631f53f703..72d2c890bc2 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -9802,6 +9802,8 @@ _initialize_arm_tdep ()
 	size_t offset = strlen ("reg-names-");
 	const char *style = disasm_options->name[i];
 	valid_disassembly_styles[j++] = &style[offset];
+	if (strcmp (&style[offset], "std") == 0)
+	  disassembly_style = &style[offset];
 	length = snprintf (rdptr, rest, "%s - %s\n", &style[offset],
 			   disasm_options->description[i]);
 	rdptr += length;
diff --git a/gdb/charset.c b/gdb/charset.c
index 0b3ef26f1d6..e011793f746 100644
--- a/gdb/charset.c
+++ b/gdb/charset.c
@@ -1029,6 +1029,9 @@ _initialize_charset ()
 #endif
 #endif
 
+  /* Recall that the first element is always "auto".  */
+  host_charset_name = charset_enum[0];
+  gdb_assert (strcmp (host_charset_name, "auto") == 0);
   add_setshow_enum_cmd ("charset", class_support,
 			charset_enum, &host_charset_name, _("\
 Set the host and target character sets."), _("\
@@ -1057,6 +1060,9 @@ To see a list of the character sets GDB supports, type `set host-charset <TAB>'.
 			show_host_charset_name,
 			&setlist, &showlist);
 
+  /* Recall that the first element is always "auto".  */
+  target_charset_name = charset_enum[0];
+  gdb_assert (strcmp (target_charset_name, "auto") == 0);
   add_setshow_enum_cmd ("target-charset", class_support,
 			charset_enum, &target_charset_name, _("\
 Set the target character set."), _("\
@@ -1069,6 +1075,9 @@ To see a list of the character sets GDB supports, type `set target-charset'<TAB>
 			show_target_charset_name,
 			&setlist, &showlist);
 
+  /* Recall that the first element is always "auto".  */
+  target_wide_charset_name = charset_enum[0];
+  gdb_assert (strcmp (target_wide_charset_name, "auto") == 0);
   add_setshow_enum_cmd ("target-wide-charset", class_support,
 			charset_enum, &target_wide_charset_name,
 			_("\
diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
index 7266fb36d0d..bf6404a5755 100644
--- a/gdb/cli/cli-decode.c
+++ b/gdb/cli/cli-decode.c
@@ -613,6 +613,16 @@ add_setshow_enum_cmd (const char *name,
 		      struct cmd_list_element **set_list,
 		      struct cmd_list_element **show_list)
 {
+  /* We require *VAR to be initialized before this call, and
+     furthermore it must be == to one of the values in ENUMLIST.  */
+  gdb_assert (var != nullptr && *var != nullptr);
+  for (int i = 0; ; ++i)
+    {
+      gdb_assert (enumlist[i] != nullptr);
+      if (*var == enumlist[i])
+	break;
+    }
+
   set_show_commands commands
     =  add_setshow_cmd_full<const char *> (name, theclass, var_enum, var,
 					   set_doc, show_doc, help_doc,
diff --git a/gdb/guile/scm-param.c b/gdb/guile/scm-param.c
index 125b0e4766b..a3af3c2251e 100644
--- a/gdb/guile/scm-param.c
+++ b/gdb/guile/scm-param.c
@@ -458,12 +458,12 @@ add_setshow_generic (enum var_types param_type, enum command_class cmd_class,
       break;
 
     case var_enum:
+      /* Initialize the value, just in case.  */
+      make_setting (self).set<const char *> (self->enumeration[0]);
       commands = add_setshow_enum_cmd (cmd_name, cmd_class, self->enumeration,
 				       &self->value.cstringval, set_doc,
 				       show_doc, help_doc, set_func, show_func,
 				       set_list, show_list);
-      /* Initialize the value, just in case.  */
-      make_setting (self).set<const char *> (self->enumeration[0]);
       break;
 
     default:
diff --git a/gdb/language.c b/gdb/language.c
index 132ff769817..64a0a9e0fbf 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -476,7 +476,8 @@ add_set_language_command ()
   /* Display "auto", "local" and "unknown" first, and then the rest,
      alpha sorted.  */
   const char **language_names_p = language_names;
-  *language_names_p++ = language_def (language_auto)->name ();
+  language = language_def (language_auto)->name ();
+  *language_names_p++ = language;
   *language_names_p++ = "local";
   *language_names_p++ = language_def (language_unknown)->name ();
   const char **sort_begin = language_names_p;
@@ -1150,6 +1151,8 @@ _initialize_language ()
   add_alias_cmd ("c", setshow_check_cmds.show, no_class, 1, &showlist);
   add_alias_cmd ("ch", setshow_check_cmds.show, no_class, 1, &showlist);
 
+  range = type_or_range_names[3];
+  gdb_assert (strcmp (range, "auto") == 0);
   add_setshow_enum_cmd ("range", class_support, type_or_range_names,
 			&range,
 			_("Set range checking (on/warn/off/auto)."),
@@ -1158,6 +1161,8 @@ _initialize_language ()
 			show_range_command,
 			&setchecklist, &showchecklist);
 
+  case_sensitive = case_sensitive_names[2];
+  gdb_assert (strcmp (case_sensitive, "auto") == 0);
   add_setshow_enum_cmd ("case-sensitive", class_support, case_sensitive_names,
 			&case_sensitive, _("\
 Set case sensitivity in name search (on/off/auto)."), _("\
@@ -1174,10 +1179,6 @@ For Fortran the default is off; for other languages the default is on."),
 
   add_set_language_command ();
 
-  language = "auto";
-  range = "auto";
-  case_sensitive = "auto";
-
   /* Have the above take effect.  */
   set_language (language_auto);
 }
diff --git a/gdb/osabi.c b/gdb/osabi.c
index 40c86e782e7..d4a98061dbd 100644
--- a/gdb/osabi.c
+++ b/gdb/osabi.c
@@ -666,11 +666,13 @@ _initialize_gdb_osabi ()
 				  generic_elf_osabi_sniffer);
 
   /* Register the "set osabi" command.  */
+  user_osabi_state = osabi_auto;
+  set_osabi_string = gdb_osabi_available_names[0];
+  gdb_assert (strcmp (set_osabi_string, "auto") == 0);
   add_setshow_enum_cmd ("osabi", class_support, gdb_osabi_available_names,
 			&set_osabi_string,
 			_("Set OS ABI of target."),
 			_("Show OS ABI of target."),
 			NULL, set_osabi, show_osabi,
 			&setlist, &showlist);
-  user_osabi_state = osabi_auto;
 }
diff --git a/gdb/python/py-param.c b/gdb/python/py-param.c
index 8559bc997ea..6ee14d42ab8 100644
--- a/gdb/python/py-param.c
+++ b/gdb/python/py-param.c
@@ -572,13 +572,13 @@ add_setshow_generic (int parmclass, enum command_class cmdclass,
       break;
 
     case var_enum:
+      /* Initialize the value, just in case.  */
+      self->value.cstringval = self->enumeration[0];
       commands = add_setshow_enum_cmd (cmd_name.get (), cmdclass,
 				       self->enumeration,
 				       &self->value.cstringval, set_doc,
 				       show_doc, help_doc, get_set_value,
 				       get_show_value, set_list, show_list);
-      /* Initialize the value, just in case.  */
-      self->value.cstringval = self->enumeration[0];
       break;
 
     default:
diff --git a/gdb/testsuite/gdb.python/py-parameter.exp b/gdb/testsuite/gdb.python/py-parameter.exp
index b025c2562f0..2de148c1b27 100644
--- a/gdb/testsuite/gdb.python/py-parameter.exp
+++ b/gdb/testsuite/gdb.python/py-parameter.exp
@@ -364,3 +364,7 @@ test_really_undocumented_parameter
 test_deprecated_api_parameter
 test_integer_parameter
 test_throwing_parameter
+
+# This caused a gdb crash.
+gdb_test "python print(gdb.parameter('endian'))" "auto" \
+    "print endian parameter"
-- 
2.31.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 3/3] Add a way to temporarily set a gdb parameter from Python
  2022-01-05 17:13 [PATCH 0/3] Improvements to Python parameters Tom Tromey
  2022-01-05 17:13 ` [PATCH 1/3] Change how Python architecture and language are handled Tom Tromey
  2022-01-05 17:13 ` [PATCH 2/3] Fix another crash with gdb parameters in Python Tom Tromey
@ 2022-01-05 17:13 ` Tom Tromey
  2022-01-10 15:59   ` Andrew Burgess
  2 siblings, 1 reply; 10+ messages in thread
From: Tom Tromey @ 2022-01-05 17:13 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

It's sometimes useful to temporarily set some gdb parameter from
Python.  Now that the 'endian' crash is fixed, and now that the
current language is no longer captured by the Python layer, it seems
reasonable to add a helper function for this situation.

This adds a new gdb.set_parameter function.  This creates a context
manager which temporarily sets some parameter to a specified value.
The old value is restored when the context is exited.  This is most
useful with the Python "with" statement:

   with gdb.set_parameter('language', 'ada'):
      ... do Ada stuff

This is PR python/10790.  I think for permanent changes to parameters,
it's fine (IMO anyway) to just rely on gdb.execute, so I plan to close
the PR if this lands.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=10790
---
 gdb/NEWS                                    |  4 ++++
 gdb/doc/python.texi                         | 19 +++++++++++++++++++
 gdb/python/lib/gdb/__init__.py              | 12 ++++++++++++
 gdb/testsuite/gdb.python/py-lookup-type.exp | 12 ++++++++++++
 4 files changed, 47 insertions(+)

diff --git a/gdb/NEWS b/gdb/NEWS
index c26e15b530a..e3b4e4da609 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -120,6 +120,10 @@ clone-inferior
      is equivalent to the existing 'maint packet' CLI command; it
      allows a user specified packet to be sent to the remote target.
 
+  ** New gdb.set_parameter(NAME, VALUE).  This returns a context
+     manager that temporarily sets the gdb parameter NAME to VALUE,
+     then resets it when the context is exited.
+
 * New features in the GDB remote stub, GDBserver
 
   ** GDBserver is now supported on OpenRISC GNU/Linux.
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index 6bd5f6b90ac..a97d8c2015c 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -332,6 +332,25 @@ parameter's value is converted to a Python value of the appropriate
 type, and returned.
 @end defun
 
+@findex gdb.set_parameter
+@defun gdb.set_parameter (name, value)
+Create a Python context manager (for use with the Python
+@command{with} statement) that temporarily sets the gdb parameter
+@var{name} to @var{value}.  On exit from the context, the previous
+value will be restored.
+
+This uses @code{gdb.parameter} in its implementation, so it can throw
+the same exceptions as that function.
+
+For example, it's sometimes useful to evaluate some Python code with a
+particular gdb language:
+
+@smallexample
+with gdb.set_parameter('language', 'pascal'):
+  ... language-specific operations
+@end smallexample
+@end defun
+
 @findex gdb.history
 @defun gdb.history (number)
 Return a value from @value{GDBN}'s value history (@pxref{Value
diff --git a/gdb/python/lib/gdb/__init__.py b/gdb/python/lib/gdb/__init__.py
index 11a1b444bfd..ea41f405157 100644
--- a/gdb/python/lib/gdb/__init__.py
+++ b/gdb/python/lib/gdb/__init__.py
@@ -17,6 +17,7 @@ import traceback
 import os
 import sys
 import _gdb
+from contextlib import contextmanager
 
 # Python 3 moved "reload"
 if sys.version_info >= (3, 4):
@@ -231,6 +232,17 @@ def find_pc_line(pc):
     return current_progspace().find_pc_line(pc)
 
 
+@contextmanager
+def set_parameter(name, value):
+    """Temporarily set the GDB parameter NAME to VALUE.
+    Note that this is a context manager."""
+    old_value = parameter(name)
+    execute('set ' + name + ' ' + str(value))
+    # Nothing that useful to return.
+    yield None
+    execute('set ' + name + ' ' + old_value)
+
+
 try:
     from pygments import formatters, lexers, highlight
 
diff --git a/gdb/testsuite/gdb.python/py-lookup-type.exp b/gdb/testsuite/gdb.python/py-lookup-type.exp
index 534a5fd418e..8cdbeaeb2a5 100644
--- a/gdb/testsuite/gdb.python/py-lookup-type.exp
+++ b/gdb/testsuite/gdb.python/py-lookup-type.exp
@@ -55,6 +55,18 @@ test_lookup_type "objective-c" "char"
 
 test_lookup_type "pascal" "char"
 
+gdb_test "show language" \
+    "The current source language is .pascal.." \
+    "show language before 'with'"
+gdb_test_multiline "look up type using set_parameter" \
+    "python" "" \
+    "with gdb.set_parameter('language', 'ada'):" "" \
+    "  print(gdb.lookup_type('character'))" "" \
+    "end" "character"
+gdb_test "show language" \
+    "The current source language is .pascal.." \
+    "show language after 'with'"
+
 # Ensure that the language can be changed from within Python and still
 # affect the results.
 gdb_test_multiline "look up ada type from another language" \
-- 
2.31.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/3] Change how Python architecture and language are handled
  2022-01-05 17:13 ` [PATCH 1/3] Change how Python architecture and language are handled Tom Tromey
@ 2022-01-10 15:35   ` Andrew Burgess
  2022-01-10 21:15     ` Tom Tromey
  0 siblings, 1 reply; 10+ messages in thread
From: Andrew Burgess @ 2022-01-10 15:35 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

* Tom Tromey via Gdb-patches <gdb-patches@sourceware.org> [2022-01-05 10:13:45 -0700]:

> Currently, gdb's Python layer captures the current architecture and
> language when "entering" Python code.  This has some undesirable
> effects, and so this series changes how this is handled.
> 
> First, there is code like this:
> 
>   gdbpy_enter enter_py (python_gdbarch, python_language);
> 
> This is incorrect, because both of these are NULL when not otherwise
> assigned.  This can cause crashes in some cases -- I've added one to
> the test suite.  (Note that this crasher is just an example, other
> ones along the same lines are possible.)
> 
> Second, when the language is captured in this way, it means that
> Python code cannot affect the current language for its own purposes.
> It's reasonable to want to write code like this:
> 
>     gdb.execute('set language mumble')
>     ... stuff using the current language
>     gdb.execute('set language previous-value')
> 
> However, this won't actually work, because the language is captured on
> entry.  I've added a test to show this as well.
> 
> This patch changes gdb to try to avoid capturing the current values.
> The Python concept of the current gdbarch is only set in those few
> cases where a non-default value is computed or needed; and the
> language is not captured at all -- instead, in the cases where it's
> required, the current language is temporarily changed.

Thanks Tom, this looks good to me.  I did have a couple of minor
points, see below.


> ---
>  gdb/python/py-breakpoint.c                  | 19 ++-----
>  gdb/python/py-cmd.c                         |  8 +--
>  gdb/python/py-connection.c                  |  2 +-
>  gdb/python/py-finishbreakpoint.c            |  6 +-
>  gdb/python/py-framefilter.c                 | 12 ++--
>  gdb/python/py-inferior.c                    | 27 +++++----
>  gdb/python/py-membuf.c                      |  3 +-
>  gdb/python/py-objfile.c                     |  2 +-
>  gdb/python/py-param.c                       |  4 +-
>  gdb/python/py-progspace.c                   |  2 +-
>  gdb/python/py-tui.c                         | 18 +++---
>  gdb/python/py-type.c                        |  4 +-
>  gdb/python/py-unwind.c                      |  2 +-
>  gdb/python/py-utils.c                       | 10 ++--
>  gdb/python/py-value.c                       | 21 ++++---
>  gdb/python/py-xmethods.c                    | 12 ++--
>  gdb/python/python-internal.h                | 20 +++++--
>  gdb/python/python.c                         | 62 +++++++++++++--------
>  gdb/testsuite/gdb.python/py-inferior.exp    |  2 +
>  gdb/testsuite/gdb.python/py-lookup-type.exp |  8 +++
>  20 files changed, 139 insertions(+), 105 deletions(-)
> 
> diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
> index f00bd6f78e6..c1cb34879bd 100644
> --- a/gdb/python/py-breakpoint.c
> +++ b/gdb/python/py-breakpoint.c
> @@ -858,7 +858,7 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
>  	    const struct breakpoint_ops *ops =
>  	      breakpoint_ops_for_event_location (location.get (), false);
>  
> -	    create_breakpoint (python_gdbarch,
> +	    create_breakpoint (gdbpy_enter::get_gdbarch (),
>  			       location.get (), NULL, -1, NULL, false,
>  			       0,
>  			       temporary_bp, type,
> @@ -954,15 +954,13 @@ gdbpy_breakpoint_cond_says_stop (const struct extension_language_defn *extlang,
>    int stop;
>    struct gdbpy_breakpoint_object *bp_obj = b->py_bp_object;
>    PyObject *py_bp = (PyObject *) bp_obj;
> -  struct gdbarch *garch;
>  
>    if (bp_obj == NULL)
>      return EXT_LANG_BP_STOP_UNSET;
>  
>    stop = -1;
> -  garch = b->gdbarch ? b->gdbarch : get_current_arch ();
>  
> -  gdbpy_enter enter_py (garch, current_language);
> +  gdbpy_enter enter_py (b->gdbarch ? b->gdbarch : nullptr);

This pattern is repeated through out this patch, and feels really
odd.

Isn't this code equivalent to:

  gdbpy_enter enter_py (b->gdbarch);

>  
>    if (bp_obj->is_finish_bp)
>      bpfinishpy_pre_stop_hook (bp_obj);
> @@ -1005,15 +1003,13 @@ gdbpy_breakpoint_has_cond (const struct extension_language_defn *extlang,
>  			   struct breakpoint *b)
>  {
>    PyObject *py_bp;
> -  struct gdbarch *garch;
>  
>    if (b->py_bp_object == NULL)
>      return 0;
>  
>    py_bp = (PyObject *) b->py_bp_object;
> -  garch = b->gdbarch ? b->gdbarch : get_current_arch ();
>  
> -  gdbpy_enter enter_py (garch, current_language);
> +  gdbpy_enter enter_py (b->gdbarch ? b->gdbarch : nullptr);
>    return PyObject_HasAttrString (py_bp, stop_func);
>  }
>  
> @@ -1048,8 +1044,7 @@ gdbpy_breakpoint_created (struct breakpoint *bp)
>        return;
>      }
>  
> -  struct gdbarch *garch = bp->gdbarch ? bp->gdbarch : get_current_arch ();
> -  gdbpy_enter enter_py (garch, current_language);
> +  gdbpy_enter enter_py (bp->gdbarch ? bp->gdbarch : nullptr);
>  
>    if (bppy_pending_object)
>      {
> @@ -1099,8 +1094,7 @@ gdbpy_breakpoint_deleted (struct breakpoint *b)
>    bp = get_breakpoint (num);
>    if (bp)
>      {
> -      struct gdbarch *garch = bp->gdbarch ? bp->gdbarch : get_current_arch ();
> -      gdbpy_enter enter_py (garch, current_language);
> +      gdbpy_enter enter_py (b->gdbarch ? b->gdbarch : nullptr);
>  
>        gdbpy_ref<gdbpy_breakpoint_object> bp_obj (bp->py_bp_object);
>        if (bp_obj != NULL)
> @@ -1131,8 +1125,7 @@ gdbpy_breakpoint_modified (struct breakpoint *b)
>    bp = get_breakpoint (num);
>    if (bp)
>      {
> -      struct gdbarch *garch = bp->gdbarch ? bp->gdbarch : get_current_arch ();
> -      gdbpy_enter enter_py (garch, current_language);
> +      gdbpy_enter enter_py (b->gdbarch ? b->gdbarch : nullptr);
>  
>        PyObject *bp_obj = (PyObject *) bp->py_bp_object;
>        if (bp_obj)
> diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c
> index 3a4e6490cf0..b51b05c95ad 100644
> --- a/gdb/python/py-cmd.c
> +++ b/gdb/python/py-cmd.c
> @@ -90,7 +90,7 @@ cmdpy_dont_repeat (PyObject *self, PyObject *args)
>  static void
>  cmdpy_destroyer (struct cmd_list_element *self, void *context)
>  {
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>  
>    /* Release our hold on the command object.  */
>    gdbpy_ref<cmdpy_object> cmd ((cmdpy_object *) context);
> @@ -104,7 +104,7 @@ cmdpy_function (const char *args, int from_tty, cmd_list_element *command)
>  {
>    cmdpy_object *obj = (cmdpy_object *) command->context ();
>  
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>  
>    if (! obj)
>      error (_("Invalid invocation of Python command object."));
> @@ -223,7 +223,7 @@ cmdpy_completer_handle_brkchars (struct cmd_list_element *command,
>  				 completion_tracker &tracker,
>  				 const char *text, const char *word)
>  {
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>  
>    /* Calling our helper to obtain a reference to the PyObject of the Python
>       function.  */
> @@ -266,7 +266,7 @@ cmdpy_completer (struct cmd_list_element *command,
>  		 completion_tracker &tracker,
>  		 const char *text, const char *word)
>  {
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>  
>    /* Calling our helper to obtain a reference to the PyObject of the Python
>       function.  */
> diff --git a/gdb/python/py-connection.c b/gdb/python/py-connection.c
> index 7c33a1f93d4..4cdd6abbf3d 100644
> --- a/gdb/python/py-connection.c
> +++ b/gdb/python/py-connection.c
> @@ -161,7 +161,7 @@ connpy_connection_removed (process_stratum_target *target)
>    if (!gdb_python_initialized)
>      return;
>  
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>  
>    if (!evregpy_no_listeners_p (gdb_py_events.connection_removed))
>      if (emit_connection_event (target, gdb_py_events.connection_removed) < 0)
> diff --git a/gdb/python/py-finishbreakpoint.c b/gdb/python/py-finishbreakpoint.c
> index 8d5eb42efc0..03bd4934506 100644
> --- a/gdb/python/py-finishbreakpoint.c
> +++ b/gdb/python/py-finishbreakpoint.c
> @@ -293,7 +293,7 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
>        /* Set a breakpoint on the return address.  */
>        event_location_up location
>  	= new_address_location (get_frame_pc (prev_frame), NULL, 0);
> -      create_breakpoint (python_gdbarch,
> +      create_breakpoint (gdbpy_enter::get_gdbarch (),
>  			 location.get (), NULL, thread, NULL, false,
>  			 0,
>  			 1 /*temp_flag*/,
> @@ -380,7 +380,7 @@ bpfinishpy_detect_out_scope_cb (struct breakpoint *b,
>  static void
>  bpfinishpy_handle_stop (struct bpstat *bs, int print_frame)
>  {
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>  
>    for (breakpoint *bp : all_breakpoints_safe ())
>      bpfinishpy_detect_out_scope_cb (bp, bs == NULL ? NULL : bs->breakpoint_at);
> @@ -392,7 +392,7 @@ bpfinishpy_handle_stop (struct bpstat *bs, int print_frame)
>  static void
>  bpfinishpy_handle_exit (struct inferior *inf)
>  {
> -  gdbpy_enter enter_py (target_gdbarch (), current_language);
> +  gdbpy_enter enter_py (target_gdbarch ());
>  
>    for (breakpoint *bp : all_breakpoints_safe ())
>      bpfinishpy_detect_out_scope_cb (bp, nullptr);
> diff --git a/gdb/python/py-framefilter.c b/gdb/python/py-framefilter.c
> index 936354f354c..7870374b3ec 100644
> --- a/gdb/python/py-framefilter.c
> +++ b/gdb/python/py-framefilter.c
> @@ -74,11 +74,11 @@ extract_sym (PyObject *obj, gdb::unique_xmalloc_ptr<char> *name,
>        if (*name == NULL)
>  	return EXT_LANG_BT_ERROR;
>        /* If the API returns a string (and not a symbol), then there is
> -	no symbol derived language available and the frame filter has
> -	either overridden the symbol with a string, or supplied a
> -	entirely synthetic symbol/value pairing.  In that case, use
> -	python_language.  */
> -      *language = python_language;
> +	 no symbol derived language available and the frame filter has
> +	 either overridden the symbol with a string, or supplied a
> +	 entirely synthetic symbol/value pairing.  In that case, use
> +	 the current language.  */
> +      *language = current_language;
>        *sym = NULL;
>        *sym_block = NULL;
>      }
> @@ -1157,7 +1157,7 @@ gdbpy_apply_frame_filter (const struct extension_language_defn *extlang,
>        return EXT_LANG_BT_NO_FILTERS;
>      }
>  
> -  gdbpy_enter enter_py (gdbarch, current_language);
> +  gdbpy_enter enter_py (gdbarch);
>  
>    /* When we're limiting the number of frames, be careful to request
>       one extra frame, so that we can print a message if there are more
> diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c
> index 6b1443db2a8..0e5895da918 100644
> --- a/gdb/python/py-inferior.c
> +++ b/gdb/python/py-inferior.c
> @@ -86,7 +86,7 @@ python_on_normal_stop (struct bpstat *bs, int print_frame)
>  
>    stop_signal = inferior_thread ()->stop_signal ();
>  
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>  
>    if (emit_stop_event (bs, stop_signal) < 0)
>      gdbpy_print_stack ();
> @@ -98,7 +98,7 @@ python_on_resume (ptid_t ptid)
>    if (!gdb_python_initialized)
>      return;
>  
> -  gdbpy_enter enter_py (target_gdbarch (), current_language);
> +  gdbpy_enter enter_py (target_gdbarch ());
>  
>    if (emit_continue_event (ptid) < 0)
>      gdbpy_print_stack ();
> @@ -110,7 +110,7 @@ python_on_resume (ptid_t ptid)
>  static void
>  python_on_inferior_call_pre (ptid_t thread, CORE_ADDR address)
>  {
> -  gdbpy_enter enter_py (target_gdbarch (), current_language);
> +  gdbpy_enter enter_py (target_gdbarch ());
>  
>    if (emit_inferior_call_event (INFERIOR_CALL_PRE, thread, address) < 0)
>      gdbpy_print_stack ();
> @@ -122,7 +122,7 @@ python_on_inferior_call_pre (ptid_t thread, CORE_ADDR address)
>  static void
>  python_on_inferior_call_post (ptid_t thread, CORE_ADDR address)
>  {
> -  gdbpy_enter enter_py (target_gdbarch (), current_language);
> +  gdbpy_enter enter_py (target_gdbarch ());
>  
>    if (emit_inferior_call_event (INFERIOR_CALL_POST, thread, address) < 0)
>      gdbpy_print_stack ();
> @@ -135,7 +135,7 @@ python_on_inferior_call_post (ptid_t thread, CORE_ADDR address)
>  static void
>  python_on_memory_change (struct inferior *inferior, CORE_ADDR addr, ssize_t len, const bfd_byte *data)
>  {
> -  gdbpy_enter enter_py (target_gdbarch (), current_language);
> +  gdbpy_enter enter_py (target_gdbarch ());
>  
>    if (emit_memory_changed_event (addr, len) < 0)
>      gdbpy_print_stack ();
> @@ -148,7 +148,7 @@ python_on_memory_change (struct inferior *inferior, CORE_ADDR addr, ssize_t len,
>  static void
>  python_on_register_change (struct frame_info *frame, int regnum)
>  {
> -  gdbpy_enter enter_py (target_gdbarch (), current_language);
> +  gdbpy_enter enter_py (target_gdbarch ());
>  
>    if (emit_register_changed_event (frame, regnum) < 0)
>      gdbpy_print_stack ();
> @@ -162,7 +162,7 @@ python_inferior_exit (struct inferior *inf)
>    if (!gdb_python_initialized)
>      return;
>  
> -  gdbpy_enter enter_py (target_gdbarch (), current_language);
> +  gdbpy_enter enter_py (target_gdbarch ());
>  
>    if (inf->has_exit_code)
>      exit_code = &inf->exit_code;
> @@ -183,8 +183,7 @@ python_new_objfile (struct objfile *objfile)
>  
>    gdbpy_enter enter_py (objfile != NULL
>  			? objfile->arch ()
> -			: target_gdbarch (),
> -			current_language);
> +			: target_gdbarch ());
>  
>    if (objfile == NULL)
>      {
> @@ -237,7 +236,7 @@ python_new_inferior (struct inferior *inf)
>    if (!gdb_python_initialized)
>      return;
>  
> -  gdbpy_enter enter_py (python_gdbarch, python_language);
> +  gdbpy_enter enter_py;
>  
>    if (evregpy_no_listeners_p (gdb_py_events.new_inferior))
>      return;
> @@ -265,7 +264,7 @@ python_inferior_deleted (struct inferior *inf)
>    if (!gdb_python_initialized)
>      return;
>  
> -  gdbpy_enter enter_py (python_gdbarch, python_language);
> +  gdbpy_enter enter_py;
>  
>    if (evregpy_no_listeners_p (gdb_py_events.inferior_deleted))
>      return;
> @@ -312,7 +311,7 @@ add_thread_object (struct thread_info *tp)
>    if (!gdb_python_initialized)
>      return;
>  
> -  gdbpy_enter enter_py (python_gdbarch, python_language);
> +  gdbpy_enter enter_py;
>  
>    gdbpy_ref<thread_object> thread_obj = create_thread_object (tp);
>    if (thread_obj == NULL)
> @@ -347,7 +346,7 @@ delete_thread_object (struct thread_info *tp, int ignore)
>    if (!gdb_python_initialized)
>      return;
>  
> -  gdbpy_enter enter_py (python_gdbarch, python_language);
> +  gdbpy_enter enter_py;
>  
>    gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (tp->inf);
>    if (inf_obj == NULL)
> @@ -791,7 +790,7 @@ py_free_inferior (struct inferior *inf, void *datum)
>    if (!gdb_python_initialized)
>      return;
>  
> -  gdbpy_enter enter_py (python_gdbarch, python_language);
> +  gdbpy_enter enter_py;
>    gdbpy_ref<inferior_object> inf_obj ((inferior_object *) datum);
>  
>    inf_obj->inferior = NULL;
> diff --git a/gdb/python/py-membuf.c b/gdb/python/py-membuf.c
> index e789a78e649..74cc0fb46bd 100644
> --- a/gdb/python/py-membuf.c
> +++ b/gdb/python/py-membuf.c
> @@ -83,7 +83,8 @@ mbpy_str (PyObject *self)
>  
>    return PyString_FromFormat (_("Memory buffer for address %s, \
>  which is %s bytes long."),
> -			      paddress (python_gdbarch, membuf_obj->addr),
> +			      paddress (gdbpy_enter::get_gdbarch (),
> +					membuf_obj->addr),
>  			      pulongest (membuf_obj->length));
>  }
>  
> diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
> index 38052245bde..6055a42260b 100644
> --- a/gdb/python/py-objfile.c
> +++ b/gdb/python/py-objfile.c
> @@ -661,7 +661,7 @@ gdbpy_lookup_objfile (PyObject *self, PyObject *args, PyObject *kw)
>  static void
>  py_free_objfile (struct objfile *objfile, void *datum)
>  {
> -  gdbpy_enter enter_py (objfile->arch (), current_language);
> +  gdbpy_enter enter_py (objfile->arch ());
>    gdbpy_ref<objfile_object> object ((objfile_object *) datum);
>    object->objfile = NULL;
>  }
> diff --git a/gdb/python/py-param.c b/gdb/python/py-param.c
> index 592ecbb41f9..8559bc997ea 100644
> --- a/gdb/python/py-param.c
> +++ b/gdb/python/py-param.c
> @@ -396,7 +396,7 @@ get_set_value (const char *args, int from_tty,
>    PyObject *obj = (PyObject *) c->context ();
>    gdb::unique_xmalloc_ptr<char> set_doc_string;
>  
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>    gdbpy_ref<> set_doc_func (PyString_FromString ("get_set_string"));
>  
>    if (set_doc_func == NULL)
> @@ -431,7 +431,7 @@ get_show_value (struct ui_file *file, int from_tty,
>    PyObject *obj = (PyObject *) c->context ();
>    gdb::unique_xmalloc_ptr<char> show_doc_string;
>  
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>    gdbpy_ref<> show_doc_func (PyString_FromString ("get_show_string"));
>  
>    if (show_doc_func == NULL)
> diff --git a/gdb/python/py-progspace.c b/gdb/python/py-progspace.c
> index 8131b66d24b..b27ebf4a666 100644
> --- a/gdb/python/py-progspace.c
> +++ b/gdb/python/py-progspace.c
> @@ -472,7 +472,7 @@ py_free_pspace (struct program_space *pspace, void *datum)
>       being deleted.  */
>    struct gdbarch *arch = target_gdbarch ();
>  
> -  gdbpy_enter enter_py (arch, current_language);
> +  gdbpy_enter enter_py (arch);
>    gdbpy_ref<pspace_object> object ((pspace_object *) datum);
>    object->pspace = NULL;
>  }
> diff --git a/gdb/python/py-tui.c b/gdb/python/py-tui.c
> index 97fdfe2be96..6a92251a705 100644
> --- a/gdb/python/py-tui.c
> +++ b/gdb/python/py-tui.c
> @@ -155,7 +155,7 @@ gdbpy_tui_window::is_valid () const
>  
>  tui_py_window::~tui_py_window ()
>  {
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>  
>    /* This can be null if the user-provided Python construction
>       function failed.  */
> @@ -181,7 +181,7 @@ tui_py_window::rerender ()
>  {
>    tui_win_info::rerender ();
>  
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>  
>    int h = viewport_height ();
>    int w = viewport_width ();
> @@ -206,7 +206,7 @@ tui_py_window::rerender ()
>  void
>  tui_py_window::do_scroll_horizontal (int num_to_scroll)
>  {
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>  
>    if (PyObject_HasAttrString (m_window.get (), "hscroll"))
>      {
> @@ -220,7 +220,7 @@ tui_py_window::do_scroll_horizontal (int num_to_scroll)
>  void
>  tui_py_window::do_scroll_vertical (int num_to_scroll)
>  {
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>  
>    if (PyObject_HasAttrString (m_window.get (), "vscroll"))
>      {
> @@ -234,7 +234,7 @@ tui_py_window::do_scroll_vertical (int num_to_scroll)
>  void
>  tui_py_window::click (int mouse_x, int mouse_y, int mouse_button)
>  {
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>  
>    if (PyObject_HasAttrString (m_window.get (), "click"))
>      {
> @@ -285,7 +285,7 @@ class gdbpy_tui_window_maker
>  
>    gdbpy_tui_window_maker (const gdbpy_tui_window_maker &other)
>    {
> -    gdbpy_enter enter_py (get_current_arch (), current_language);
> +    gdbpy_enter enter_py;
>      m_constr = other.m_constr;
>    }
>  
> @@ -297,7 +297,7 @@ class gdbpy_tui_window_maker
>  
>    gdbpy_tui_window_maker &operator= (const gdbpy_tui_window_maker &other)
>    {
> -    gdbpy_enter enter_py (get_current_arch (), current_language);
> +    gdbpy_enter enter_py;
>      m_constr = other.m_constr;
>      return *this;
>    }
> @@ -312,14 +312,14 @@ class gdbpy_tui_window_maker
>  
>  gdbpy_tui_window_maker::~gdbpy_tui_window_maker ()
>  {
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>    m_constr.reset (nullptr);
>  }
>  
>  tui_win_info *
>  gdbpy_tui_window_maker::operator() (const char *win_name)
>  {
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>  
>    gdbpy_ref<gdbpy_tui_window> wrapper
>      (PyObject_New (gdbpy_tui_window, &gdbpy_tui_window_object_type));
> diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
> index 220b0d46ffb..e71e635ecdf 100644
> --- a/gdb/python/py-type.c
> +++ b/gdb/python/py-type.c
> @@ -799,7 +799,7 @@ typy_lookup_typename (const char *type_name, const struct block *block)
>        else if (startswith (type_name, "enum "))
>  	type = lookup_enum (type_name + 5, NULL);
>        else
> -	type = lookup_typename (python_language,
> +	type = lookup_typename (current_language,
>  				type_name, block, 0);
>      }
>    catch (const gdb_exception &except)
> @@ -1089,7 +1089,7 @@ save_objfile_types (struct objfile *objfile, void *datum)
>  
>    /* This prevents another thread from freeing the objects we're
>       operating on.  */
> -  gdbpy_enter enter_py (objfile->arch (), current_language);
> +  gdbpy_enter enter_py (objfile->arch ());
>  
>    htab_up copied_types = create_copied_types_hash (objfile);
>  
> diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c
> index a884c83ec26..3f10122860e 100644
> --- a/gdb/python/py-unwind.c
> +++ b/gdb/python/py-unwind.c
> @@ -524,7 +524,7 @@ pyuw_sniffer (const struct frame_unwind *self, struct frame_info *this_frame,
>    struct gdbarch *gdbarch = (struct gdbarch *) (self->unwind_data);
>    cached_frame_info *cached_frame;
>  
> -  gdbpy_enter enter_py (gdbarch, current_language);
> +  gdbpy_enter enter_py (gdbarch);
>  
>    pyuw_debug_printf ("frame=%d, sp=%s, pc=%s",
>  		     frame_relative_level (this_frame),
> diff --git a/gdb/python/py-utils.c b/gdb/python/py-utils.c
> index 79e1c013261..73c860bcc96 100644
> --- a/gdb/python/py-utils.c
> +++ b/gdb/python/py-utils.c
> @@ -93,8 +93,9 @@ unicode_to_encoded_python_string (PyObject *unicode_str, const char *charset)
>  gdb::unique_xmalloc_ptr<char>
>  unicode_to_target_string (PyObject *unicode_str)
>  {
> -  return unicode_to_encoded_string (unicode_str,
> -				    target_charset (python_gdbarch));
> +  return (unicode_to_encoded_string
> +	  (unicode_str,
> +	   target_charset (gdbpy_enter::get_gdbarch ())));
>  }
>  
>  /* Returns a PyObject with the contents of the given unicode string
> @@ -104,8 +105,9 @@ unicode_to_target_string (PyObject *unicode_str)
>  static gdbpy_ref<>
>  unicode_to_target_python_string (PyObject *unicode_str)
>  {
> -  return unicode_to_encoded_python_string (unicode_str,
> -					   target_charset (python_gdbarch));
> +  return (unicode_to_encoded_python_string
> +	  (unicode_str,
> +	   target_charset (gdbpy_enter::get_gdbarch ())));
>  }
>  
>  /* Converts a python string (8-bit or unicode) to a target string in
> diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
> index 70b33d5a27b..d6ceb54fed8 100644
> --- a/gdb/python/py-value.c
> +++ b/gdb/python/py-value.c
> @@ -35,23 +35,26 @@
>     GDB (which uses target arithmetic).  */
>  
>  /* Python's integer type corresponds to C's long type.  */
> -#define builtin_type_pyint builtin_type (python_gdbarch)->builtin_long
> +#define builtin_type_pyint \
> +  builtin_type (gdbpy_enter::get_gdbarch ())->builtin_long
>  
>  /* Python's float type corresponds to C's double type.  */
> -#define builtin_type_pyfloat builtin_type (python_gdbarch)->builtin_double
> +#define builtin_type_pyfloat \
> +  builtin_type (gdbpy_enter::get_gdbarch ())->builtin_double
>  
>  /* Python's long type corresponds to C's long long type.  */
> -#define builtin_type_pylong builtin_type (python_gdbarch)->builtin_long_long
> +#define builtin_type_pylong \
> +  builtin_type (gdbpy_enter::get_gdbarch ())->builtin_long_long
>  
>  /* Python's long type corresponds to C's long long type.  Unsigned version.  */
>  #define builtin_type_upylong builtin_type \
> -  (python_gdbarch)->builtin_unsigned_long_long
> +  (gdbpy_enter::get_gdbarch ())->builtin_unsigned_long_long
>  
>  #define builtin_type_pybool \
> -  language_bool_type (python_language, python_gdbarch)
> +  language_bool_type (current_language, gdbpy_enter::get_gdbarch ())
>  
>  #define builtin_type_pychar \
> -  language_string_char_type (python_language, python_gdbarch)
> +  language_string_char_type (current_language, gdbpy_enter::get_gdbarch ())
>  
>  struct value_object {
>    PyObject_HEAD
> @@ -754,7 +757,7 @@ valpy_format_string (PyObject *self, PyObject *args, PyObject *kw)
>    try
>      {
>        common_val_print (((value_object *) self)->value, &stb, 0,
> -			&opts, python_language);
> +			&opts, current_language);
>      }
>    catch (const gdb_exception &except)
>      {
> @@ -1160,7 +1163,7 @@ valpy_str (PyObject *self)
>    try
>      {
>        common_val_print (((value_object *) self)->value, &stb, 0,
> -			&opts, python_language);
> +			&opts, current_language);
>      }
>    catch (const gdb_exception &except)
>      {
> @@ -2025,7 +2028,7 @@ gdbpy_convenience_variable (PyObject *self, PyObject *args)
>  
>        if (var != NULL)
>  	{
> -	  res_val = value_of_internalvar (python_gdbarch, var);
> +	  res_val = value_of_internalvar (gdbpy_enter::get_gdbarch (), var);
>  	  if (value_type (res_val)->code () == TYPE_CODE_VOID)
>  	    res_val = NULL;
>  	}
> diff --git a/gdb/python/py-xmethods.c b/gdb/python/py-xmethods.c
> index fd3673029a0..9d5824962b1 100644
> --- a/gdb/python/py-xmethods.c
> +++ b/gdb/python/py-xmethods.c
> @@ -69,7 +69,7 @@ struct python_xmethod_worker : xmethod_worker
>  python_xmethod_worker::~python_xmethod_worker ()
>  {
>    /* We don't do much here, but we still need the GIL.  */
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>  
>    Py_DECREF (m_py_worker);
>    Py_DECREF (m_this_type);
> @@ -122,7 +122,7 @@ gdbpy_get_matching_xmethod_workers
>  {
>    gdb_assert (obj_type != NULL && method_name != NULL);
>  
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>  
>    gdbpy_ref<> py_type (type_to_type_object (obj_type));
>    if (py_type == NULL)
> @@ -294,7 +294,7 @@ python_xmethod_worker::do_get_arg_types (std::vector<type *> *arg_types)
>  {
>    /* The gdbpy_enter object needs to be placed first, so that it's the last to
>       be destroyed.  */
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>    struct type *obj_type;
>    int i = 1, arg_count;
>    gdbpy_ref<> list_iter;
> @@ -410,7 +410,7 @@ python_xmethod_worker::do_get_result_type (value *obj,
>    struct type *obj_type, *this_type;
>    int i;
>  
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>  
>    /* First see if there is a get_result_type method.
>       If not this could be an old xmethod (pre 7.9.1).  */
> @@ -502,7 +502,7 @@ struct value *
>  python_xmethod_worker::invoke (struct value *obj,
>  			       gdb::array_view<value *> args)
>  {
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>  
>    int i;
>    struct type *obj_type, *this_type;
> @@ -580,7 +580,7 @@ python_xmethod_worker::invoke (struct value *obj,
>      }
>    else
>      {
> -      res = allocate_value (lookup_typename (python_language,
> +      res = allocate_value (lookup_typename (current_language,
>  					     "void", NULL, 0));
>      }
>  
> diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
> index 583989c5a6d..b6550343ad4 100644
> --- a/gdb/python/python-internal.h
> +++ b/gdb/python/python-internal.h
> @@ -625,14 +625,29 @@ class gdbpy_enter
>  {
>   public:
>  
> -  gdbpy_enter (struct gdbarch *gdbarch, const struct language_defn *language);
> +  explicit gdbpy_enter (struct gdbarch *gdbarch = nullptr,
> +			const struct language_defn *language = nullptr);

I know the old code was not commented, but it would be awesome if we
could take this opportunity to add a description of what the function
does, and what the parameters are used for.

Thanks,
Andrew

>  
>    ~gdbpy_enter ();
>  
>    DISABLE_COPY_AND_ASSIGN (gdbpy_enter);
>  
> +  /* Return the current gdbarch, as known to the Python layer.  This
> +     is either python_gdbarch (which comes from the most recent call
> +     to the gdbpy_enter constructor), or, if that is nullptr, the
> +     result of get_current_arch.  */
> +  static struct gdbarch *get_gdbarch ();
> +
> +  /* Called only during gdb shutdown.  This sets python_gdbarch to an
> +     acceptable value.  */
> +  static void finalize ();
> +
>   private:
>  
> +  /* The current gdbarch, according to Python.  This can be
> +     nullptr.  */
> +  static struct gdbarch *python_gdbarch;
> +
>    struct active_ext_lang_state *m_previous_active;
>    PyGILState_STATE m_state;
>    struct gdbarch *m_gdbarch;
> @@ -680,9 +695,6 @@ class gdbpy_allow_threads
>    PyThreadState *m_save;
>  };
>  
> -extern struct gdbarch *python_gdbarch;
> -extern const struct language_defn *python_language;
> -
>  /* Use this after a TRY_EXCEPT to throw the appropriate Python
>     exception.  */
>  #define GDB_PY_HANDLE_EXCEPTION(Exception)	\
> diff --git a/gdb/python/python.c b/gdb/python/python.c
> index e05b99c0bec..d1b03aec328 100644
> --- a/gdb/python/python.c
> +++ b/gdb/python/python.c
> @@ -192,13 +192,12 @@ const struct extension_language_defn extension_language_python =
>  
>  /* Architecture and language to be used in callbacks from
>     the Python interpreter.  */
> -struct gdbarch *python_gdbarch;
> -const struct language_defn *python_language;
> +struct gdbarch *gdbpy_enter::python_gdbarch;
>  
>  gdbpy_enter::gdbpy_enter  (struct gdbarch *gdbarch,
>  			   const struct language_defn *language)
>  : m_gdbarch (python_gdbarch),
> -  m_language (python_language)
> +  m_language (language == nullptr ? nullptr : current_language)
>  {
>    /* We should not ever enter Python unless initialized.  */
>    if (!gdb_python_initialized)
> @@ -209,7 +208,8 @@ gdbpy_enter::gdbpy_enter  (struct gdbarch *gdbarch,
>    m_state = PyGILState_Ensure ();
>  
>    python_gdbarch = gdbarch;
> -  python_language = language;
> +  if (language != nullptr)
> +    set_language (language->la_language);
>  
>    /* Save it and ensure ! PyErr_Occurred () afterwards.  */
>    m_error.emplace ();
> @@ -228,12 +228,27 @@ gdbpy_enter::~gdbpy_enter ()
>    m_error->restore ();
>  
>    python_gdbarch = m_gdbarch;
> -  python_language = m_language;
> +  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 = target_gdbarch ();
> +}
> +
>  /* A helper class to save and restore the GIL, but without touching
>     the other globals that are handled by gdbpy_enter.  */
>  
> @@ -318,7 +333,7 @@ python_interactive_command (const char *arg, int from_tty)
>  
>    arg = skip_spaces (arg);
>  
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>  
>    if (arg && *arg)
>      {
> @@ -412,7 +427,7 @@ gdbpy_eval_from_control_command (const struct extension_language_defn *extlang,
>    if (cmd->body_list_1 != nullptr)
>      error (_("Invalid \"python\" block structure."));
>  
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>  
>    std::string script = compute_python_string (cmd->body_list_0.get ());
>    ret = PyRun_SimpleString (script.c_str ());
> @@ -425,7 +440,7 @@ gdbpy_eval_from_control_command (const struct extension_language_defn *extlang,
>  static void
>  python_command (const char *arg, int from_tty)
>  {
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>  
>    scoped_restore save_async = make_scoped_restore (&current_ui->async, 0);
>  
> @@ -556,7 +571,7 @@ gdbpy_parameter (PyObject *self, PyObject *args)
>  static PyObject *
>  gdbpy_target_charset (PyObject *self, PyObject *args)
>  {
> -  const char *cset = target_charset (python_gdbarch);
> +  const char *cset = target_charset (gdbpy_enter::get_gdbarch ());
>  
>    return PyUnicode_Decode (cset, strlen (cset), host_charset (), NULL);
>  }
> @@ -566,7 +581,7 @@ gdbpy_target_charset (PyObject *self, PyObject *args)
>  static PyObject *
>  gdbpy_target_wide_charset (PyObject *self, PyObject *args)
>  {
> -  const char *cset = target_wide_charset (python_gdbarch);
> +  const char *cset = target_wide_charset (gdbpy_enter::get_gdbarch ());
>  
>    return PyUnicode_Decode (cset, strlen (cset), host_charset (), NULL);
>  }
> @@ -857,7 +872,7 @@ gdbpy_decode_line (PyObject *self, PyObject *args)
>      }
>  
>    if (arg != NULL)
> -    location = string_to_event_location_basic (&arg, python_language,
> +    location = string_to_event_location_basic (&arg, current_language,
>  					       symbol_name_match_type::WILD);
>  
>    std::vector<symtab_and_line> decoded_sals;
> @@ -962,7 +977,7 @@ static void
>  gdbpy_source_script (const struct extension_language_defn *extlang,
>  		     FILE *file, const char *filename)
>  {
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>    python_run_simple_file (file, filename);
>  }
>  
> @@ -1001,7 +1016,7 @@ struct gdbpy_event
>  
>    void operator() ()
>    {
> -    gdbpy_enter enter_py (get_current_arch (), current_language);
> +    gdbpy_enter enter_py;
>  
>      gdbpy_ref<> call_result (PyObject_CallObject (m_func, NULL));
>      if (call_result == NULL)
> @@ -1050,7 +1065,7 @@ gdbpy_before_prompt_hook (const struct extension_language_defn *extlang,
>    if (!gdb_python_initialized)
>      return EXT_LANG_RC_NOP;
>  
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>  
>    if (!evregpy_no_listeners_p (gdb_py_events.before_prompt)
>        && evpy_emit_event (NULL, gdb_py_events.before_prompt) < 0)
> @@ -1125,7 +1140,7 @@ gdbpy_colorize (const std::string &filename, const std::string &contents)
>    if (!gdb_python_initialized)
>      return {};
>  
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>  
>    if (gdb_python_module == nullptr
>        || !PyObject_HasAttrString (gdb_python_module, "colorize"))
> @@ -1390,7 +1405,7 @@ gdbpy_source_objfile_script (const struct extension_language_defn *extlang,
>    if (!gdb_python_initialized)
>      return;
>  
> -  gdbpy_enter enter_py (objfile->arch (), current_language);
> +  gdbpy_enter enter_py (objfile->arch ());
>    scoped_restore restire_current_objfile
>      = make_scoped_restore (&gdbpy_current_objfile, objfile);
>  
> @@ -1411,7 +1426,7 @@ gdbpy_execute_objfile_script (const struct extension_language_defn *extlang,
>    if (!gdb_python_initialized)
>      return;
>  
> -  gdbpy_enter enter_py (objfile->arch (), current_language);
> +  gdbpy_enter enter_py (objfile->arch ());
>    scoped_restore restire_current_objfile
>      = make_scoped_restore (&gdbpy_current_objfile, objfile);
>  
> @@ -1443,7 +1458,7 @@ gdbpy_start_type_printers (const struct extension_language_defn *extlang,
>    if (!gdb_python_initialized)
>      return;
>  
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>  
>    gdbpy_ref<> type_module (PyImport_ImportModule ("gdb.types"));
>    if (type_module == NULL)
> @@ -1488,7 +1503,7 @@ gdbpy_apply_type_printers (const struct extension_language_defn *extlang,
>    if (!gdb_python_initialized)
>      return EXT_LANG_RC_NOP;
>  
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>  
>    gdbpy_ref<> type_obj (type_to_type_object (type));
>    if (type_obj == NULL)
> @@ -1551,7 +1566,7 @@ gdbpy_free_type_printers (const struct extension_language_defn *extlang,
>    if (!gdb_python_initialized)
>      return;
>  
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>    Py_DECREF (printers);
>  }
>  
> @@ -1686,8 +1701,7 @@ finalize_python (void *ignore)
>    previous_active = set_active_ext_lang (&extension_language_python);
>  
>    (void) PyGILState_Ensure ();
> -  python_gdbarch = target_gdbarch ();
> -  python_language = current_language;
> +  gdbpy_enter::finalize ();
>  
>    Py_Finalize ();
>  
> @@ -1746,7 +1760,7 @@ gdbpy_gdb_exiting (int exit_code)
>    if (!gdb_python_initialized)
>      return;
>  
> -  gdbpy_enter enter_py (python_gdbarch, python_language);
> +  gdbpy_enter enter_py;
>  
>    if (emit_exiting_event (exit_code) < 0)
>      gdbpy_print_stack ();
> @@ -2164,7 +2178,7 @@ gdbpy_initialize (const struct extension_language_defn *extlang)
>    if (!do_start_initialization () && PyErr_Occurred ())
>      gdbpy_print_stack ();
>  
> -  gdbpy_enter enter_py (get_current_arch (), current_language);
> +  gdbpy_enter enter_py;
>  
>    if (!do_initialize (extlang))
>      {
> diff --git a/gdb/testsuite/gdb.python/py-inferior.exp b/gdb/testsuite/gdb.python/py-inferior.exp
> index 5b5f58243e4..aa78a1540cf 100644
> --- a/gdb/testsuite/gdb.python/py-inferior.exp
> +++ b/gdb/testsuite/gdb.python/py-inferior.exp
> @@ -220,6 +220,7 @@ with_test_prefix "is_valid" {
>      gdb_test "python print (inf_list\[0\].is_valid())" "True" \
>  	"check inferior validity 1"
>  
> +    # The "dummy" line below used to cause a gdb crash.
>      gdb_test_multiline "install new inferior event handler" \
>  	"python" "" \
>  	"my_inferior_count = 1" "" \
> @@ -227,6 +228,7 @@ with_test_prefix "is_valid" {
>  	"  global my_inferior_count" "" \
>  	"  if evt.inferior is not None:" "" \
>  	"    my_inferior_count = my_inferior_count + 1" "" \
> +	"    dummy = gdb.Value(True)" "" \
>  	"gdb.events.new_inferior.connect(new_inf_handler)" "" \
>  	"end" ""
>      gdb_test_multiline "install inferior deleted event handler" \
> diff --git a/gdb/testsuite/gdb.python/py-lookup-type.exp b/gdb/testsuite/gdb.python/py-lookup-type.exp
> index 52a1dae20ed..534a5fd418e 100644
> --- a/gdb/testsuite/gdb.python/py-lookup-type.exp
> +++ b/gdb/testsuite/gdb.python/py-lookup-type.exp
> @@ -54,3 +54,11 @@ test_lookup_type "opencl" "ushort"
>  test_lookup_type "objective-c" "char"
>  
>  test_lookup_type "pascal" "char"
> +
> +# Ensure that the language can be changed from within Python and still
> +# affect the results.
> +gdb_test_multiline "look up ada type from another language" \
> +    "python" "" \
> +    "gdb.execute('set language ada')" "" \
> +    "print(gdb.lookup_type('character'))" "" \
> +    "end" "character"
> -- 
> 2.31.1
> 


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] Fix another crash with gdb parameters in Python
  2022-01-05 17:13 ` [PATCH 2/3] Fix another crash with gdb parameters in Python Tom Tromey
@ 2022-01-10 15:46   ` Andrew Burgess
  0 siblings, 0 replies; 10+ messages in thread
From: Andrew Burgess @ 2022-01-10 15:46 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

* Tom Tromey via Gdb-patches <gdb-patches@sourceware.org> [2022-01-05 10:13:46 -0700]:

> While looking into the language-capturing issue, I found another way
> to crash gdb using parameters from Python:
> 
> (gdb) python print(gdb.parameter('endian'))
> 
> (This is related to PR python/12188, though this patch isn't going to
> fix what that bug is really about.)
> 
> The problem here is that the global variable that underlies the
> "endian" parameter is initialized to NULL.  However, that's not a
> valid value for an "enum" set/show parameter.
> 
> My understanding is that, in gdb, an "enum" parameter's underlying
> variable must have a value that is "==" (not just strcmp-equal) to one
> of the values coming from the enum array.  This invariant is relied on
> in various places.
> 
> I started this patch by fixing the problem with "endian".  Then I
> added some assertions to add_setshow_enum_cmd to try to catch other
> problems of the same type.
> 
> This patch fixes all the problems that I found.  I also looked at all
> the calls to add_setshow_enum_cmd to ensure that they were all
> included in the gdb I tested.  I think they are: there are no calls in
> nat-* files, or in remote-sim.c; and I was trying a build with all
> targets, Python, and Guile enabled.
> 
> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=12188

LGTM.

Thanks,
Andrew

> ---
>  gdb/arch-utils.c                          |  5 +++--
>  gdb/arm-tdep.c                            |  2 ++
>  gdb/charset.c                             |  9 +++++++++
>  gdb/cli/cli-decode.c                      | 10 ++++++++++
>  gdb/guile/scm-param.c                     |  4 ++--
>  gdb/language.c                            | 11 ++++++-----
>  gdb/osabi.c                               |  4 +++-
>  gdb/python/py-param.c                     |  4 ++--
>  gdb/testsuite/gdb.python/py-parameter.exp |  4 ++++
>  9 files changed, 41 insertions(+), 12 deletions(-)
> 
> diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c
> index 38e3132668d..3ee978a0249 100644
> --- a/gdb/arch-utils.c
> +++ b/gdb/arch-utils.c
> @@ -359,7 +359,7 @@ static const char *const endian_enum[] =
>    endian_auto,
>    NULL,
>  };
> -static const char *set_endian_string;
> +static const char *set_endian_string = endian_auto;
>  
>  enum bfd_endian
>  selected_byte_order (void)
> @@ -757,7 +757,8 @@ initialize_current_architecture (void)
>       list of architectures.  */
>    {
>      /* Append ``auto''.  */
> -    arches.push_back ("auto");
> +    set_architecture_string = "auto";
> +    arches.push_back (set_architecture_string);
>      arches.push_back (nullptr);
>      set_show_commands architecture_cmds
>        = add_setshow_enum_cmd ("architecture", class_support,
> diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
> index d631f53f703..72d2c890bc2 100644
> --- a/gdb/arm-tdep.c
> +++ b/gdb/arm-tdep.c
> @@ -9802,6 +9802,8 @@ _initialize_arm_tdep ()
>  	size_t offset = strlen ("reg-names-");
>  	const char *style = disasm_options->name[i];
>  	valid_disassembly_styles[j++] = &style[offset];
> +	if (strcmp (&style[offset], "std") == 0)
> +	  disassembly_style = &style[offset];
>  	length = snprintf (rdptr, rest, "%s - %s\n", &style[offset],
>  			   disasm_options->description[i]);
>  	rdptr += length;
> diff --git a/gdb/charset.c b/gdb/charset.c
> index 0b3ef26f1d6..e011793f746 100644
> --- a/gdb/charset.c
> +++ b/gdb/charset.c
> @@ -1029,6 +1029,9 @@ _initialize_charset ()
>  #endif
>  #endif
>  
> +  /* Recall that the first element is always "auto".  */
> +  host_charset_name = charset_enum[0];
> +  gdb_assert (strcmp (host_charset_name, "auto") == 0);
>    add_setshow_enum_cmd ("charset", class_support,
>  			charset_enum, &host_charset_name, _("\
>  Set the host and target character sets."), _("\
> @@ -1057,6 +1060,9 @@ To see a list of the character sets GDB supports, type `set host-charset <TAB>'.
>  			show_host_charset_name,
>  			&setlist, &showlist);
>  
> +  /* Recall that the first element is always "auto".  */
> +  target_charset_name = charset_enum[0];
> +  gdb_assert (strcmp (target_charset_name, "auto") == 0);
>    add_setshow_enum_cmd ("target-charset", class_support,
>  			charset_enum, &target_charset_name, _("\
>  Set the target character set."), _("\
> @@ -1069,6 +1075,9 @@ To see a list of the character sets GDB supports, type `set target-charset'<TAB>
>  			show_target_charset_name,
>  			&setlist, &showlist);
>  
> +  /* Recall that the first element is always "auto".  */
> +  target_wide_charset_name = charset_enum[0];
> +  gdb_assert (strcmp (target_wide_charset_name, "auto") == 0);
>    add_setshow_enum_cmd ("target-wide-charset", class_support,
>  			charset_enum, &target_wide_charset_name,
>  			_("\
> diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
> index 7266fb36d0d..bf6404a5755 100644
> --- a/gdb/cli/cli-decode.c
> +++ b/gdb/cli/cli-decode.c
> @@ -613,6 +613,16 @@ add_setshow_enum_cmd (const char *name,
>  		      struct cmd_list_element **set_list,
>  		      struct cmd_list_element **show_list)
>  {
> +  /* We require *VAR to be initialized before this call, and
> +     furthermore it must be == to one of the values in ENUMLIST.  */
> +  gdb_assert (var != nullptr && *var != nullptr);
> +  for (int i = 0; ; ++i)
> +    {
> +      gdb_assert (enumlist[i] != nullptr);
> +      if (*var == enumlist[i])
> +	break;
> +    }
> +
>    set_show_commands commands
>      =  add_setshow_cmd_full<const char *> (name, theclass, var_enum, var,
>  					   set_doc, show_doc, help_doc,
> diff --git a/gdb/guile/scm-param.c b/gdb/guile/scm-param.c
> index 125b0e4766b..a3af3c2251e 100644
> --- a/gdb/guile/scm-param.c
> +++ b/gdb/guile/scm-param.c
> @@ -458,12 +458,12 @@ add_setshow_generic (enum var_types param_type, enum command_class cmd_class,
>        break;
>  
>      case var_enum:
> +      /* Initialize the value, just in case.  */
> +      make_setting (self).set<const char *> (self->enumeration[0]);
>        commands = add_setshow_enum_cmd (cmd_name, cmd_class, self->enumeration,
>  				       &self->value.cstringval, set_doc,
>  				       show_doc, help_doc, set_func, show_func,
>  				       set_list, show_list);
> -      /* Initialize the value, just in case.  */
> -      make_setting (self).set<const char *> (self->enumeration[0]);
>        break;
>  
>      default:
> diff --git a/gdb/language.c b/gdb/language.c
> index 132ff769817..64a0a9e0fbf 100644
> --- a/gdb/language.c
> +++ b/gdb/language.c
> @@ -476,7 +476,8 @@ add_set_language_command ()
>    /* Display "auto", "local" and "unknown" first, and then the rest,
>       alpha sorted.  */
>    const char **language_names_p = language_names;
> -  *language_names_p++ = language_def (language_auto)->name ();
> +  language = language_def (language_auto)->name ();
> +  *language_names_p++ = language;
>    *language_names_p++ = "local";
>    *language_names_p++ = language_def (language_unknown)->name ();
>    const char **sort_begin = language_names_p;
> @@ -1150,6 +1151,8 @@ _initialize_language ()
>    add_alias_cmd ("c", setshow_check_cmds.show, no_class, 1, &showlist);
>    add_alias_cmd ("ch", setshow_check_cmds.show, no_class, 1, &showlist);
>  
> +  range = type_or_range_names[3];
> +  gdb_assert (strcmp (range, "auto") == 0);
>    add_setshow_enum_cmd ("range", class_support, type_or_range_names,
>  			&range,
>  			_("Set range checking (on/warn/off/auto)."),
> @@ -1158,6 +1161,8 @@ _initialize_language ()
>  			show_range_command,
>  			&setchecklist, &showchecklist);
>  
> +  case_sensitive = case_sensitive_names[2];
> +  gdb_assert (strcmp (case_sensitive, "auto") == 0);
>    add_setshow_enum_cmd ("case-sensitive", class_support, case_sensitive_names,
>  			&case_sensitive, _("\
>  Set case sensitivity in name search (on/off/auto)."), _("\
> @@ -1174,10 +1179,6 @@ For Fortran the default is off; for other languages the default is on."),
>  
>    add_set_language_command ();
>  
> -  language = "auto";
> -  range = "auto";
> -  case_sensitive = "auto";
> -
>    /* Have the above take effect.  */
>    set_language (language_auto);
>  }
> diff --git a/gdb/osabi.c b/gdb/osabi.c
> index 40c86e782e7..d4a98061dbd 100644
> --- a/gdb/osabi.c
> +++ b/gdb/osabi.c
> @@ -666,11 +666,13 @@ _initialize_gdb_osabi ()
>  				  generic_elf_osabi_sniffer);
>  
>    /* Register the "set osabi" command.  */
> +  user_osabi_state = osabi_auto;
> +  set_osabi_string = gdb_osabi_available_names[0];
> +  gdb_assert (strcmp (set_osabi_string, "auto") == 0);
>    add_setshow_enum_cmd ("osabi", class_support, gdb_osabi_available_names,
>  			&set_osabi_string,
>  			_("Set OS ABI of target."),
>  			_("Show OS ABI of target."),
>  			NULL, set_osabi, show_osabi,
>  			&setlist, &showlist);
> -  user_osabi_state = osabi_auto;
>  }
> diff --git a/gdb/python/py-param.c b/gdb/python/py-param.c
> index 8559bc997ea..6ee14d42ab8 100644
> --- a/gdb/python/py-param.c
> +++ b/gdb/python/py-param.c
> @@ -572,13 +572,13 @@ add_setshow_generic (int parmclass, enum command_class cmdclass,
>        break;
>  
>      case var_enum:
> +      /* Initialize the value, just in case.  */
> +      self->value.cstringval = self->enumeration[0];
>        commands = add_setshow_enum_cmd (cmd_name.get (), cmdclass,
>  				       self->enumeration,
>  				       &self->value.cstringval, set_doc,
>  				       show_doc, help_doc, get_set_value,
>  				       get_show_value, set_list, show_list);
> -      /* Initialize the value, just in case.  */
> -      self->value.cstringval = self->enumeration[0];
>        break;
>  
>      default:
> diff --git a/gdb/testsuite/gdb.python/py-parameter.exp b/gdb/testsuite/gdb.python/py-parameter.exp
> index b025c2562f0..2de148c1b27 100644
> --- a/gdb/testsuite/gdb.python/py-parameter.exp
> +++ b/gdb/testsuite/gdb.python/py-parameter.exp
> @@ -364,3 +364,7 @@ test_really_undocumented_parameter
>  test_deprecated_api_parameter
>  test_integer_parameter
>  test_throwing_parameter
> +
> +# This caused a gdb crash.
> +gdb_test "python print(gdb.parameter('endian'))" "auto" \
> +    "print endian parameter"
> -- 
> 2.31.1
> 


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/3] Add a way to temporarily set a gdb parameter from Python
  2022-01-05 17:13 ` [PATCH 3/3] Add a way to temporarily set a gdb parameter from Python Tom Tromey
@ 2022-01-10 15:59   ` Andrew Burgess
  2022-01-10 21:16     ` Tom Tromey
  0 siblings, 1 reply; 10+ messages in thread
From: Andrew Burgess @ 2022-01-10 15:59 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

* Tom Tromey via Gdb-patches <gdb-patches@sourceware.org> [2022-01-05 10:13:47 -0700]:

> It's sometimes useful to temporarily set some gdb parameter from
> Python.  Now that the 'endian' crash is fixed, and now that the
> current language is no longer captured by the Python layer, it seems
> reasonable to add a helper function for this situation.
> 
> This adds a new gdb.set_parameter function.  This creates a context
> manager which temporarily sets some parameter to a specified value.
> The old value is restored when the context is exited.  This is most
> useful with the Python "with" statement:
> 
>    with gdb.set_parameter('language', 'ada'):
>       ... do Ada stuff

I don't have time to look through this patch right now, but I did have
one question/thought.

Maybe I'm missing something, but, if I wanted to make a permanent
change to a parameter (i.e. one that persists outside the scope of a
call to gdb.set_parameter) do I need to use gdb.execute ("set ....")?

If that's the case, I wonder how you'd feel about having two
functions,

  gdb.set_parameter(PARAM, VALUE)
  gdb.with_parameter(PARAM, VALUE)

The second of these is what you propose adding (but with a new name),
the first make a persistent change to the parameter value?

Thanks,
Andrew


  



> 
> This is PR python/10790.  I think for permanent changes to parameters,
> it's fine (IMO anyway) to just rely on gdb.execute, so I plan to close
> the PR if this lands.
> 
> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=10790
> ---
>  gdb/NEWS                                    |  4 ++++
>  gdb/doc/python.texi                         | 19 +++++++++++++++++++
>  gdb/python/lib/gdb/__init__.py              | 12 ++++++++++++
>  gdb/testsuite/gdb.python/py-lookup-type.exp | 12 ++++++++++++
>  4 files changed, 47 insertions(+)
> 
> diff --git a/gdb/NEWS b/gdb/NEWS
> index c26e15b530a..e3b4e4da609 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -120,6 +120,10 @@ clone-inferior
>       is equivalent to the existing 'maint packet' CLI command; it
>       allows a user specified packet to be sent to the remote target.
>  
> +  ** New gdb.set_parameter(NAME, VALUE).  This returns a context
> +     manager that temporarily sets the gdb parameter NAME to VALUE,
> +     then resets it when the context is exited.
> +
>  * New features in the GDB remote stub, GDBserver
>  
>    ** GDBserver is now supported on OpenRISC GNU/Linux.
> diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
> index 6bd5f6b90ac..a97d8c2015c 100644
> --- a/gdb/doc/python.texi
> +++ b/gdb/doc/python.texi
> @@ -332,6 +332,25 @@ parameter's value is converted to a Python value of the appropriate
>  type, and returned.
>  @end defun
>  
> +@findex gdb.set_parameter
> +@defun gdb.set_parameter (name, value)
> +Create a Python context manager (for use with the Python
> +@command{with} statement) that temporarily sets the gdb parameter
> +@var{name} to @var{value}.  On exit from the context, the previous
> +value will be restored.
> +
> +This uses @code{gdb.parameter} in its implementation, so it can throw
> +the same exceptions as that function.
> +
> +For example, it's sometimes useful to evaluate some Python code with a
> +particular gdb language:
> +
> +@smallexample
> +with gdb.set_parameter('language', 'pascal'):
> +  ... language-specific operations
> +@end smallexample
> +@end defun
> +
>  @findex gdb.history
>  @defun gdb.history (number)
>  Return a value from @value{GDBN}'s value history (@pxref{Value
> diff --git a/gdb/python/lib/gdb/__init__.py b/gdb/python/lib/gdb/__init__.py
> index 11a1b444bfd..ea41f405157 100644
> --- a/gdb/python/lib/gdb/__init__.py
> +++ b/gdb/python/lib/gdb/__init__.py
> @@ -17,6 +17,7 @@ import traceback
>  import os
>  import sys
>  import _gdb
> +from contextlib import contextmanager
>  
>  # Python 3 moved "reload"
>  if sys.version_info >= (3, 4):
> @@ -231,6 +232,17 @@ def find_pc_line(pc):
>      return current_progspace().find_pc_line(pc)
>  
>  
> +@contextmanager
> +def set_parameter(name, value):
> +    """Temporarily set the GDB parameter NAME to VALUE.
> +    Note that this is a context manager."""
> +    old_value = parameter(name)
> +    execute('set ' + name + ' ' + str(value))
> +    # Nothing that useful to return.
> +    yield None
> +    execute('set ' + name + ' ' + old_value)
> +
> +
>  try:
>      from pygments import formatters, lexers, highlight
>  
> diff --git a/gdb/testsuite/gdb.python/py-lookup-type.exp b/gdb/testsuite/gdb.python/py-lookup-type.exp
> index 534a5fd418e..8cdbeaeb2a5 100644
> --- a/gdb/testsuite/gdb.python/py-lookup-type.exp
> +++ b/gdb/testsuite/gdb.python/py-lookup-type.exp
> @@ -55,6 +55,18 @@ test_lookup_type "objective-c" "char"
>  
>  test_lookup_type "pascal" "char"
>  
> +gdb_test "show language" \
> +    "The current source language is .pascal.." \
> +    "show language before 'with'"
> +gdb_test_multiline "look up type using set_parameter" \
> +    "python" "" \
> +    "with gdb.set_parameter('language', 'ada'):" "" \
> +    "  print(gdb.lookup_type('character'))" "" \
> +    "end" "character"
> +gdb_test "show language" \
> +    "The current source language is .pascal.." \
> +    "show language after 'with'"
> +
>  # Ensure that the language can be changed from within Python and still
>  # affect the results.
>  gdb_test_multiline "look up ada type from another language" \
> -- 
> 2.31.1
> 


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/3] Change how Python architecture and language are handled
  2022-01-10 15:35   ` Andrew Burgess
@ 2022-01-10 21:15     ` Tom Tromey
  2022-01-10 21:22       ` Tom Tromey
  0 siblings, 1 reply; 10+ messages in thread
From: Tom Tromey @ 2022-01-10 21:15 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: Tom Tromey, gdb-patches

>>>>> "Andrew" == Andrew Burgess <aburgess@redhat.com> writes:

>> -  gdbpy_enter enter_py (garch, current_language);
>> +  gdbpy_enter enter_py (b->gdbarch ? b->gdbarch : nullptr);

Andrew> This pattern is repeated through out this patch, and feels really
Andrew> odd.
Andrew> Isn't this code equivalent to:
Andrew>   gdbpy_enter enter_py (b->gdbarch);

Yeah, I don't know why I didn't realize that.
I'll simplify this.

>> -  gdbpy_enter (struct gdbarch *gdbarch, const struct language_defn *language);
>> +  explicit gdbpy_enter (struct gdbarch *gdbarch = nullptr,
>> +			const struct language_defn *language = nullptr);

Andrew> I know the old code was not commented, but it would be awesome if we
Andrew> could take this opportunity to add a description of what the function
Andrew> does, and what the parameters are used for.

Will do.

Tom

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/3] Add a way to temporarily set a gdb parameter from Python
  2022-01-10 15:59   ` Andrew Burgess
@ 2022-01-10 21:16     ` Tom Tromey
  0 siblings, 0 replies; 10+ messages in thread
From: Tom Tromey @ 2022-01-10 21:16 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: Tom Tromey, gdb-patches

Andrew> Maybe I'm missing something, but, if I wanted to make a permanent
Andrew> change to a parameter (i.e. one that persists outside the scope of a
Andrew> call to gdb.set_parameter) do I need to use gdb.execute ("set ....")?

Yes.

Andrew> If that's the case, I wonder how you'd feel about having two
Andrew> functions,

Andrew>   gdb.set_parameter(PARAM, VALUE)
Andrew>   gdb.with_parameter(PARAM, VALUE)

Andrew> The second of these is what you propose adding (but with a new name),
Andrew> the first make a persistent change to the parameter value?

Sounds good, I'll make this change.

Tom

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/3] Change how Python architecture and language are handled
  2022-01-10 21:15     ` Tom Tromey
@ 2022-01-10 21:22       ` Tom Tromey
  0 siblings, 0 replies; 10+ messages in thread
From: Tom Tromey @ 2022-01-10 21:22 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Andrew Burgess, gdb-patches

>>> -  gdbpy_enter (struct gdbarch *gdbarch, const struct language_defn *language);
>>> +  explicit gdbpy_enter (struct gdbarch *gdbarch = nullptr,
>>> +			const struct language_defn *language = nullptr);

Andrew> I know the old code was not commented, but it would be awesome if we
Andrew> could take this opportunity to add a description of what the function
Andrew> does, and what the parameters are used for.

Tom> Will do.

Some of it is documented at the 'class' level:

/* Called before entering the Python interpreter to install the
   current language and architecture to be used for Python values.
   Also set the active extension language for GDB so that SIGINT's
   are directed our way, and if necessary install the right SIGINT
   handler.  */
class gdbpy_enter

However I've added some text to the constructor as well.

Tom

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2022-01-10 21:22 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-05 17:13 [PATCH 0/3] Improvements to Python parameters Tom Tromey
2022-01-05 17:13 ` [PATCH 1/3] Change how Python architecture and language are handled Tom Tromey
2022-01-10 15:35   ` Andrew Burgess
2022-01-10 21:15     ` Tom Tromey
2022-01-10 21:22       ` Tom Tromey
2022-01-05 17:13 ` [PATCH 2/3] Fix another crash with gdb parameters in Python Tom Tromey
2022-01-10 15:46   ` Andrew Burgess
2022-01-05 17:13 ` [PATCH 3/3] Add a way to temporarily set a gdb parameter from Python Tom Tromey
2022-01-10 15:59   ` Andrew Burgess
2022-01-10 21:16     ` Tom Tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).