Change how Python architecture and language are handled
authorTom Tromey <tromey@adacore.com>
Tue, 4 Jan 2022 15:02:24 +0000 (08:02 -0700)
committerTom Tromey <tromey@adacore.com>
Wed, 26 Jan 2022 13:49:51 +0000 (06:49 -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.

20 files changed:
gdb/python/py-breakpoint.c
gdb/python/py-cmd.c
gdb/python/py-connection.c
gdb/python/py-finishbreakpoint.c
gdb/python/py-framefilter.c
gdb/python/py-inferior.c
gdb/python/py-membuf.c
gdb/python/py-objfile.c
gdb/python/py-param.c
gdb/python/py-progspace.c
gdb/python/py-tui.c
gdb/python/py-type.c
gdb/python/py-unwind.c
gdb/python/py-utils.c
gdb/python/py-value.c
gdb/python/py-xmethods.c
gdb/python/python-internal.h
gdb/python/python.c
gdb/testsuite/gdb.python/py-inferior.exp
gdb/testsuite/gdb.python/py-lookup-type.exp

index f00bd6f78e6160349607b59fe117007530aaba0e..2fc20376af86203bac0f942f810e107b0099a74a 100644 (file)
@@ -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);
 
   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);
   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);
 
   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);
 
       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);
 
       PyObject *bp_obj = (PyObject *) bp->py_bp_object;
       if (bp_obj)
index 3a4e6490cf09565a2759cc6bd9dab74a4c39673c..b51b05c95ad24d9862a36302df1bc9ece10c0ff8 100644 (file)
@@ -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.  */
index 7c33a1f93d4312a088f20af60793f1d6d03db6f2..4cdd6abbf3d4304b0df68c503947553b2fe6697a 100644 (file)
@@ -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)
index 8d5eb42efc0d051dcdf4fe55527ca428449b7e13..03bd49345060fa48dec07298af3e4b4d50d775fa 100644 (file)
@@ -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);
index 936354f354c1f0cd681e7b4741ade1fb6f5479be..7870374b3ec06079d1546dd277897cdc4b21a755 100644 (file)
@@ -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
index 45e33f9e28a7d896ef353c6348f7fcd64d3b1e0a..46f0c9ffd04dcd554f94a0bb39dfd93d3227d230 100644 (file)
@@ -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)
@@ -348,7 +347,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)
@@ -792,7 +791,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;
index e789a78e64930ac9457ced4eb402d18bf63b65e5..74cc0fb46bdccfa5b00b628a93db450d93118b8b 100644 (file)
@@ -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));
 }
 
index 38052245bde7e14bd0f8611a957b0e6e74e4893c..6055a42260b8054b3dd24a16167f4b3d3990af73 100644 (file)
@@ -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;
 }
index a25dad315c9bf20602cf9f7222b4ac343125296d..24678bc8a5e7027b88bbfedb823093c3691b1cd3 100644 (file)
@@ -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)
index 8131b66d24b4b6d9b1252149d8359cd405dce0b8..b27ebf4a6665d53190cfbab635d4f84da9988f33 100644 (file)
@@ -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;
 }
index 97fdfe2be9669c29277c4b53054fecc76dbebfd7..6a92251a7056853edc61fd25a5cfdcd5e83afa27 100644 (file)
@@ -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 @@ public:
 
   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 @@ public:
 
   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 @@ private:
 
 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));
index 220b0d46ffb0437fa571180e66ff81d3628559c8..e71e635ecdfdfdefa37db9e608d7d8212d719f7b 100644 (file)
@@ -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);
 
index 4fea9068aad75d2f159e760f691739505268a2b7..36f42cbcac39d5e5fb9cc7c4889f778ceb670e24 100644 (file)
@@ -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),
index 79e1c013261c201199c9372200d2551dabd09a8c..73c860bcc96cad21af6bc83764358dfd596983a4 100644 (file)
@@ -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
index 70b33d5a27bbaa543084c321e5d7fbe6dee8a898..d6ceb54fed8b3adc3e0f3616ec8881b547ea8ef9 100644 (file)
    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;
        }
index fd3673029a0268f124824d9b5946351bb93f5a2f..9d5824962b1b403c0b175b5e47cbdaa9d922cabc 100644 (file)
@@ -69,7 +69,7 @@ private:
 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));
     }
 
index 583989c5a6dae259a9a7c16bbf8dbbb2cbcd39f3..ccea5c4a9cd94d97d67a92291b3fbf9dfb78742f 100644 (file)
@@ -625,14 +625,36 @@ class gdbpy_enter
 {
  public:
 
-  gdbpy_enter (struct gdbarch *gdbarch, const struct language_defn *language);
+  /* Set the ambient Python architecture to GDBARCH and the language
+     to LANGUAGE.  If GDBARCH is nullptr, then the architecture will
+     be computed, when needed, using get_current_arch; see the
+     get_gdbarch method.  If LANGUAGE is not nullptr, then the current
+     language at time of construction will be saved (to be restored on
+     destruction), and the current language will be set to
+     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 +702,6 @@ private:
   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)     \
index 4dcda53d9abd1f2467f793c070fbd5537bd5f01a..7ddc170904cce2baf72fff4c41b78a79b096e128 100644 (file)
@@ -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);
 }
@@ -867,7 +882,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;
@@ -972,7 +987,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);
 }
 
@@ -1011,7 +1026,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)
@@ -1060,7 +1075,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)
@@ -1135,7 +1150,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"))
@@ -1400,7 +1415,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);
 
@@ -1421,7 +1436,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);
 
@@ -1453,7 +1468,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)
@@ -1498,7 +1513,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)
@@ -1561,7 +1576,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);
 }
 
@@ -1696,8 +1711,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 ();
 
@@ -1756,7 +1770,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 ();
@@ -2174,7 +2188,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))
     {
index 5b5f58243e4243855cf6b7701652a64d870ce797..aa78a1540cf8f2d99cbce781d4b3b71b1bb92b34 100644 (file)
@@ -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" \
index 52a1dae20ed880066db7836986fe7fe15c343c22..534a5fd418e7250b8ad24df3b07d5771c1fa33f3 100644 (file)
@@ -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"