gdb: use caller objfile in dwarf_evaluate_loc_desc::push_dwarf_reg_entry_value
[deliverable/binutils-gdb.git] / gdb / python / py-inferior.c
index dbc197e05be9104e6620e46fd841c08de741fb5b..b9268c11d4385b6eeef25aa0e92222c796ed30eb 100644 (file)
@@ -1,6 +1,6 @@
 /* Python interface to inferiors.
 
-   Copyright (C) 2009-2015 Free Software Foundation, Inc.
+   Copyright (C) 2009-2020 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "gdbthread.h"
 #include "inferior.h"
 #include "objfiles.h"
-#include "observer.h"
+#include "observable.h"
 #include "python-internal.h"
 #include "arch-utils.h"
 #include "language.h"
-#include "gdb_signals.h"
+#include "gdbsupport/gdb_signals.h"
 #include "py-event.h"
 #include "py-stopevent.h"
 
-struct threadlist_entry {
-  thread_object *thread_obj;
+struct threadlist_entry
+{
+  threadlist_entry (gdbpy_ref<thread_object> &&ref)
+    : thread_obj (std::move (ref))
+  {
+  }
+
+  gdbpy_ref<thread_object> thread_obj;
   struct threadlist_entry *next;
 };
 
-typedef struct
+struct inferior_object
 {
   PyObject_HEAD
 
@@ -48,7 +54,7 @@ typedef struct
 
   /* Number of threads in the list.  */
   int nthreads;
-} inferior_object;
+};
 
 extern PyTypeObject inferior_object_type
     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("inferior_object");
@@ -81,39 +87,32 @@ extern PyTypeObject membuf_object_type
 static void
 python_on_normal_stop (struct bpstats *bs, int print_frame)
 {
-  struct cleanup *cleanup;
   enum gdb_signal stop_signal;
 
   if (!gdb_python_initialized)
     return;
 
-  if (!find_thread_ptid (inferior_ptid))
-      return;
+  if (inferior_ptid == null_ptid)
+    return;
 
   stop_signal = inferior_thread ()->suspend.stop_signal;
 
-  cleanup = ensure_python_env (get_current_arch (), current_language);
+  gdbpy_enter enter_py (get_current_arch (), current_language);
 
   if (emit_stop_event (bs, stop_signal) < 0)
     gdbpy_print_stack ();
-
-  do_cleanups (cleanup);
 }
 
 static void
 python_on_resume (ptid_t ptid)
 {
-  struct cleanup *cleanup;
-
   if (!gdb_python_initialized)
     return;
 
-  cleanup = ensure_python_env (target_gdbarch (), current_language);
+  gdbpy_enter enter_py (target_gdbarch (), current_language);
 
   if (emit_continue_event (ptid) < 0)
     gdbpy_print_stack ();
-
-  do_cleanups (cleanup);
 }
 
 /* Callback, registered as an observer, that notifies Python listeners
@@ -122,14 +121,10 @@ python_on_resume (ptid_t ptid)
 static void
 python_on_inferior_call_pre (ptid_t thread, CORE_ADDR address)
 {
-  struct cleanup *cleanup;
-
-  cleanup = ensure_python_env (target_gdbarch (), current_language);
+  gdbpy_enter enter_py (target_gdbarch (), current_language);
 
   if (emit_inferior_call_event (INFERIOR_CALL_PRE, thread, address) < 0)
     gdbpy_print_stack ();
-
-  do_cleanups (cleanup);
 }
 
 /* Callback, registered as an observer, that notifies Python listeners
@@ -138,14 +133,10 @@ python_on_inferior_call_pre (ptid_t thread, CORE_ADDR address)
 static void
 python_on_inferior_call_post (ptid_t thread, CORE_ADDR address)
 {
-  struct cleanup *cleanup;
-
-  cleanup = ensure_python_env (target_gdbarch (), current_language);
+  gdbpy_enter enter_py (target_gdbarch (), current_language);
 
   if (emit_inferior_call_event (INFERIOR_CALL_POST, thread, address) < 0)
     gdbpy_print_stack ();
-
-  do_cleanups (cleanup);
 }
 
 /* Callback, registered as an observer, that notifies Python listeners
@@ -155,14 +146,10 @@ 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)
 {
-  struct cleanup *cleanup;
-
-  cleanup = ensure_python_env (target_gdbarch (), current_language);
+  gdbpy_enter enter_py (target_gdbarch (), current_language);
 
   if (emit_memory_changed_event (addr, len) < 0)
     gdbpy_print_stack ();
-
-  do_cleanups (cleanup);
 }
 
 /* Callback, registered as an observer, that notifies Python listeners
@@ -172,34 +159,27 @@ 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)
 {
-  struct cleanup *cleanup;
-
-  cleanup = ensure_python_env (target_gdbarch (), current_language);
+  gdbpy_enter enter_py (target_gdbarch (), current_language);
 
   if (emit_register_changed_event (frame, regnum) < 0)
     gdbpy_print_stack ();
-
-  do_cleanups (cleanup);
 }
 
 static void
 python_inferior_exit (struct inferior *inf)
 {
-  struct cleanup *cleanup;
   const LONGEST *exit_code = NULL;
 
   if (!gdb_python_initialized)
     return;
 
-  cleanup = ensure_python_env (target_gdbarch (), current_language);
+  gdbpy_enter enter_py (target_gdbarch (), current_language);
 
   if (inf->has_exit_code)
     exit_code = &inf->exit_code;
 
   if (emit_exited_event (exit_code, inf) < 0)
     gdbpy_print_stack ();
-
-  do_cleanups (cleanup);
 }
 
 /* Callback used to notify Python listeners about new objfiles loaded in the
@@ -209,15 +189,13 @@ python_inferior_exit (struct inferior *inf)
 static void
 python_new_objfile (struct objfile *objfile)
 {
-  struct cleanup *cleanup;
-
   if (!gdb_python_initialized)
     return;
 
-  cleanup = ensure_python_env (objfile != NULL
-                              ? get_objfile_arch (objfile)
-                              : target_gdbarch (),
-                              current_language);
+  gdbpy_enter enter_py (objfile != NULL
+                       ? objfile->arch ()
+                       : target_gdbarch (),
+                       current_language);
 
   if (objfile == NULL)
     {
@@ -229,15 +207,14 @@ python_new_objfile (struct objfile *objfile)
       if (emit_new_objfile_event (objfile) < 0)
        gdbpy_print_stack ();
     }
-
-  do_cleanups (cleanup);
 }
 
 /* Return a reference to the Python object of type Inferior
    representing INFERIOR.  If the object has already been created,
    return it and increment the reference count,  otherwise, create it.
    Return NULL on failure.  */
-PyObject *
+
+gdbpy_ref<inferior_object>
 inferior_to_inferior_object (struct inferior *inferior)
 {
   inferior_object *inf_obj;
@@ -247,120 +224,145 @@ inferior_to_inferior_object (struct inferior *inferior)
     {
       inf_obj = PyObject_New (inferior_object, &inferior_object_type);
       if (!inf_obj)
-         return NULL;
+       return NULL;
 
       inf_obj->inferior = inferior;
       inf_obj->threads = NULL;
       inf_obj->nthreads = 0;
 
+      /* PyObject_New initializes the new object with a refcount of 1.  This
+        counts for the reference we are keeping in the inferior data.  */
       set_inferior_data (inferior, infpy_inf_data_key, inf_obj);
-
     }
-  else
-    Py_INCREF ((PyObject *)inf_obj);
 
-  return (PyObject *) inf_obj;
+  /* We are returning a new reference.  */
+  gdb_assert (inf_obj != nullptr);
+  return gdbpy_ref<inferior_object>::new_reference (inf_obj);
 }
 
-/* Finds the Python Inferior object for the given PID.  Returns a
-   reference, or NULL if PID does not match any inferior object. */
-
-PyObject *
-find_inferior_object (int pid)
+/* Called when a new inferior is created.  Notifies any Python event
+   listeners.  */
+static void
+python_new_inferior (struct inferior *inf)
 {
-  struct inferior *inf = find_inferior_pid (pid);
+  if (!gdb_python_initialized)
+    return;
 
-  if (inf)
-    return inferior_to_inferior_object (inf);
+  gdbpy_enter enter_py (python_gdbarch, python_language);
 
-  return NULL;
+  if (evregpy_no_listeners_p (gdb_py_events.new_inferior))
+    return;
+
+  gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (inf);
+  if (inf_obj == NULL)
+    {
+      gdbpy_print_stack ();
+      return;
+    }
+
+  gdbpy_ref<> event = create_event_object (&new_inferior_event_object_type);
+  if (event == NULL
+      || evpy_add_attribute (event.get (), "inferior",
+                            (PyObject *) inf_obj.get ()) < 0
+      || evpy_emit_event (event.get (), gdb_py_events.new_inferior) < 0)
+    gdbpy_print_stack ();
 }
 
-thread_object *
-find_thread_object (ptid_t ptid)
+/* Called when an inferior is removed.  Notifies any Python event
+   listeners.  */
+static void
+python_inferior_deleted (struct inferior *inf)
 {
-  int pid;
-  struct threadlist_entry *thread;
-  PyObject *inf_obj;
-  thread_object *found = NULL;
+  if (!gdb_python_initialized)
+    return;
 
-  pid = ptid_get_pid (ptid);
-  if (pid == 0)
-    return NULL;
+  gdbpy_enter enter_py (python_gdbarch, python_language);
+
+  if (evregpy_no_listeners_p (gdb_py_events.inferior_deleted))
+    return;
 
-  inf_obj = find_inferior_object (pid);
+  gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (inf);
+  if (inf_obj == NULL)
+    {
+      gdbpy_print_stack ();
+      return;
+    }
 
-  if (! inf_obj)
+  gdbpy_ref<> event = create_event_object (&inferior_deleted_event_object_type);
+  if (event == NULL
+      || evpy_add_attribute (event.get (), "inferior",
+                            (PyObject *) inf_obj.get ()) < 0
+      || evpy_emit_event (event.get (), gdb_py_events.inferior_deleted) < 0)
+    gdbpy_print_stack ();
+}
+
+gdbpy_ref<>
+thread_to_thread_object (thread_info *thr)
+{
+  gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (thr->inf);
+  if (inf_obj == NULL)
     return NULL;
 
-  for (thread = ((inferior_object *)inf_obj)->threads; thread;
+  for (threadlist_entry *thread = inf_obj->threads;
+       thread != NULL;
        thread = thread->next)
-    if (ptid_equal (thread->thread_obj->thread->ptid, ptid))
-      {
-       found = thread->thread_obj;
-       break;
-      }
-
-  Py_DECREF (inf_obj);
-
-  if (found)
-    return found;
+    if (thread->thread_obj->thread == thr)
+      return gdbpy_ref<>::new_reference ((PyObject *) thread->thread_obj.get ());
 
+  PyErr_SetString (PyExc_SystemError,
+                  _("could not find gdb thread object"));
   return NULL;
 }
 
 static void
 add_thread_object (struct thread_info *tp)
 {
-  struct cleanup *cleanup;
-  thread_object *thread_obj;
   inferior_object *inf_obj;
   struct threadlist_entry *entry;
 
   if (!gdb_python_initialized)
     return;
 
-  cleanup = ensure_python_env (python_gdbarch, python_language);
+  gdbpy_enter enter_py (python_gdbarch, python_language);
 
-  thread_obj = create_thread_object (tp);
-  if (!thread_obj)
+  gdbpy_ref<thread_object> thread_obj = create_thread_object (tp);
+  if (thread_obj == NULL)
     {
       gdbpy_print_stack ();
-      do_cleanups (cleanup);
       return;
     }
 
   inf_obj = (inferior_object *) thread_obj->inf_obj;
 
-  entry = XNEW (struct threadlist_entry);
-  entry->thread_obj = thread_obj;
+  entry = new threadlist_entry (std::move (thread_obj));
   entry->next = inf_obj->threads;
 
   inf_obj->threads = entry;
   inf_obj->nthreads++;
 
-  do_cleanups (cleanup);
+  if (evregpy_no_listeners_p (gdb_py_events.new_thread))
+    return;
+
+  gdbpy_ref<> event = create_thread_event_object (&new_thread_event_object_type,
+                                                 (PyObject *) inf_obj);
+  if (event == NULL
+      || evpy_emit_event (event.get (), gdb_py_events.new_thread) < 0)
+    gdbpy_print_stack ();
 }
 
 static void
 delete_thread_object (struct thread_info *tp, int ignore)
 {
-  struct cleanup *cleanup;
-  inferior_object *inf_obj;
   struct threadlist_entry **entry, *tmp;
 
   if (!gdb_python_initialized)
     return;
 
-  cleanup = ensure_python_env (python_gdbarch, python_language);
+  gdbpy_enter enter_py (python_gdbarch, python_language);
 
-  inf_obj
-    = (inferior_object *) find_inferior_object (ptid_get_pid (tp->ptid));
-  if (!inf_obj)
-    {
-      do_cleanups (cleanup);
-      return;
-    }
+  gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (tp->inf);
+  if (inf_obj == NULL)
+    return;
 
   /* Find thread entry in its inferior's thread_list.  */
   for (entry = &inf_obj->threads; *entry != NULL; entry =
@@ -369,11 +371,7 @@ delete_thread_object (struct thread_info *tp, int ignore)
       break;
 
   if (!*entry)
-    {
-      Py_DECREF (inf_obj);
-      do_cleanups (cleanup);
-      return;
-    }
+    return;
 
   tmp = *entry;
   tmp->thread_obj->thread = NULL;
@@ -381,11 +379,7 @@ delete_thread_object (struct thread_info *tp, int ignore)
   *entry = (*entry)->next;
   inf_obj->nthreads--;
 
-  Py_DECREF (tmp->thread_obj);
-  Py_DECREF (inf_obj);
-  xfree (tmp);
-
-  do_cleanups (cleanup);
+  delete tmp;
 }
 
 static PyObject *
@@ -398,15 +392,14 @@ infpy_threads (PyObject *self, PyObject *args)
 
   INFPY_REQUIRE_VALID (inf_obj);
 
-  TRY
+  try
     {
       update_thread_list ();
     }
-  CATCH (except, RETURN_MASK_ALL)
+  catch (const gdb_exception &except)
     {
       GDB_PY_HANDLE_EXCEPTION (except);
     }
-  END_CATCH
 
   tuple = PyTuple_New (inf_obj->nthreads);
   if (!tuple)
@@ -415,8 +408,9 @@ infpy_threads (PyObject *self, PyObject *args)
   for (i = 0, entry = inf_obj->threads; i < inf_obj->nthreads;
        i++, entry = entry->next)
     {
-      Py_INCREF (entry->thread_obj);
-      PyTuple_SET_ITEM (tuple, i, (PyObject *) entry->thread_obj);
+      PyObject *thr = (PyObject *) entry->thread_obj.get ();
+      Py_INCREF (thr);
+      PyTuple_SET_ITEM (tuple, i, thr);
     }
 
   return tuple;
@@ -453,23 +447,19 @@ infpy_get_was_attached (PyObject *self, void *closure)
   Py_RETURN_FALSE;
 }
 
-static int
-build_inferior_list (struct inferior *inf, void *arg)
-{
-  PyObject *list = (PyObject *) arg;
-  PyObject *inferior = inferior_to_inferior_object (inf);
-  int success = 0;
+/* Getter of gdb.Inferior.progspace.  */
 
-  if (! inferior)
-    return 0;
+static PyObject *
+infpy_get_progspace (PyObject *self, void *closure)
+{
+  inferior_object *inf = (inferior_object *) self;
 
-  success = PyList_Append (list, inferior);
-  Py_DECREF (inferior);
+  INFPY_REQUIRE_VALID (inf);
 
-  if (success)
-    return 1;
+  program_space *pspace = inf->inferior->pspace;
+  gdb_assert (pspace != nullptr);
 
-  return 0;
+  return pspace_to_pspace_object (pspace).release ();
 }
 
 /* Implementation of gdb.inferiors () -> (gdb.Inferior, ...).
@@ -477,22 +467,22 @@ build_inferior_list (struct inferior *inf, void *arg)
 PyObject *
 gdbpy_inferiors (PyObject *unused, PyObject *unused2)
 {
-  PyObject *list, *tuple;
-
-  list = PyList_New (0);
-  if (!list)
+  gdbpy_ref<> list (PyList_New (0));
+  if (list == NULL)
     return NULL;
 
-  if (iterate_over_inferiors (build_inferior_list, list))
+  for (inferior *inf : all_inferiors ())
     {
-      Py_DECREF (list);
-      return NULL;
-    }
+      gdbpy_ref<inferior_object> inferior = inferior_to_inferior_object (inf);
 
-  tuple = PyList_AsTuple (list);
-  Py_DECREF (list);
+      if (inferior == NULL)
+       continue;
 
-  return tuple;
+      if (PyList_Append (list.get (), (PyObject *) inferior.get ()) != 0)
+       return NULL;
+    }
+
+  return PyList_AsTuple (list.get ());
 }
 
 /* Membuf and memory manipulation.  */
@@ -505,50 +495,44 @@ static PyObject *
 infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw)
 {
   CORE_ADDR addr, length;
-  void *buffer = NULL;
-  membuf_object *membuf_obj;
+  gdb::unique_xmalloc_ptr<gdb_byte> buffer;
   PyObject *addr_obj, *length_obj, *result;
-  static char *keywords[] = { "address", "length", NULL };
+  static const char *keywords[] = { "address", "length", NULL };
 
-  if (! PyArg_ParseTupleAndKeywords (args, kw, "OO", keywords,
-                                    &addr_obj, &length_obj))
+  if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "OO", keywords,
+                                       &addr_obj, &length_obj))
     return NULL;
 
   if (get_addr_from_python (addr_obj, &addr) < 0
       || get_addr_from_python (length_obj, &length) < 0)
     return NULL;
 
-  TRY
+  try
     {
-      buffer = xmalloc (length);
+      buffer.reset ((gdb_byte *) xmalloc (length));
 
-      read_memory (addr, buffer, length);
+      read_memory (addr, buffer.get (), length);
     }
-  CATCH (except, RETURN_MASK_ALL)
+  catch (const gdb_exception &except)
     {
-      xfree (buffer);
       GDB_PY_HANDLE_EXCEPTION (except);
     }
-  END_CATCH
 
-  membuf_obj = PyObject_New (membuf_object, &membuf_object_type);
+  gdbpy_ref<membuf_object> membuf_obj (PyObject_New (membuf_object,
+                                                    &membuf_object_type));
   if (membuf_obj == NULL)
-    {
-      xfree (buffer);
-      return NULL;
-    }
+    return NULL;
 
-  membuf_obj->buffer = buffer;
+  membuf_obj->buffer = buffer.release ();
   membuf_obj->addr = addr;
   membuf_obj->length = length;
 
 #ifdef IS_PY3K
-  result = PyMemoryView_FromObject ((PyObject *) membuf_obj);
+  result = PyMemoryView_FromObject ((PyObject *) membuf_obj.get ());
 #else
-  result = PyBuffer_FromReadWriteObject ((PyObject *) membuf_obj, 0,
+  result = PyBuffer_FromReadWriteObject ((PyObject *) membuf_obj.get (), 0,
                                         Py_END_OF_BUFFER);
 #endif
-  Py_DECREF (membuf_obj);
 
   return result;
 }
@@ -562,59 +546,42 @@ infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw)
 static PyObject *
 infpy_write_memory (PyObject *self, PyObject *args, PyObject *kw)
 {
-  struct gdb_exception except = exception_none;
+  struct gdb_exception except;
   Py_ssize_t buf_len;
-  const char *buffer;
+  const gdb_byte *buffer;
   CORE_ADDR addr, length;
   PyObject *addr_obj, *length_obj = NULL;
-  static char *keywords[] = { "address", "buffer", "length", NULL };
-#ifdef IS_PY3K
+  static const char *keywords[] = { "address", "buffer", "length", NULL };
   Py_buffer pybuf;
 
-  if (! PyArg_ParseTupleAndKeywords (args, kw, "Os*|O", keywords,
-                                    &addr_obj, &pybuf,
-                                    &length_obj))
+  if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "Os*|O", keywords,
+                                       &addr_obj, &pybuf, &length_obj))
     return NULL;
 
-  buffer = pybuf.buf;
+  Py_buffer_up buffer_up (&pybuf);
+  buffer = (const gdb_byte *) pybuf.buf;
   buf_len = pybuf.len;
-#else
-  if (! PyArg_ParseTupleAndKeywords (args, kw, "Os#|O", keywords,
-                                    &addr_obj, &buffer, &buf_len,
-                                    &length_obj))
-    return NULL;
-#endif
 
   if (get_addr_from_python (addr_obj, &addr) < 0)
-    goto fail;
+    return nullptr;
 
   if (!length_obj)
     length = buf_len;
   else if (get_addr_from_python (length_obj, &length) < 0)
-    goto fail;
+    return nullptr;
 
-  TRY
+  try
     {
-      write_memory_with_notification (addr, (gdb_byte *) buffer, length);
+      write_memory_with_notification (addr, buffer, length);
     }
-  CATCH (ex, RETURN_MASK_ALL)
+  catch (gdb_exception &ex)
     {
-      except = ex;
+      except = std::move (ex);
     }
-  END_CATCH
 
-#ifdef IS_PY3K
-  PyBuffer_Release (&pybuf);
-#endif
   GDB_PY_HANDLE_EXCEPTION (except);
 
   Py_RETURN_NONE;
-
- fail:
-#ifdef IS_PY3K
-  PyBuffer_Release (&pybuf);
-#endif
-  return NULL;
 }
 
 /* Destructor of Membuf objects.  */
@@ -648,7 +615,10 @@ get_buffer (PyObject *self, Py_buffer *buf, int flags)
   ret = PyBuffer_FillInfo (buf, self, membuf_obj->buffer,
                           membuf_obj->length, 0,
                           PyBUF_CONTIG);
-  buf->format = "c";
+
+  /* Despite the documentation saying this field is a "const char *",
+     in Python 3.4 at least, it's really a "char *".  */
+  buf->format = (char *) "c";
 
   return ret;
 }
@@ -712,55 +682,36 @@ get_char_buffer (PyObject *self, Py_ssize_t segment, char **ptrptr)
 static PyObject *
 infpy_search_memory (PyObject *self, PyObject *args, PyObject *kw)
 {
-  struct gdb_exception except = exception_none;
+  struct gdb_exception except;
   CORE_ADDR start_addr, length;
-  static char *keywords[] = { "address", "length", "pattern", NULL };
+  static const char *keywords[] = { "address", "length", "pattern", NULL };
   PyObject *start_addr_obj, *length_obj;
   Py_ssize_t pattern_size;
-  const void *buffer;
+  const gdb_byte *buffer;
   CORE_ADDR found_addr;
   int found = 0;
-#ifdef IS_PY3K
   Py_buffer pybuf;
 
-  if (! PyArg_ParseTupleAndKeywords (args, kw, "OOs*", keywords,
-                                    &start_addr_obj, &length_obj,
-                                    &pybuf))
+  if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "OOs*", keywords,
+                                       &start_addr_obj, &length_obj,
+                                       &pybuf))
     return NULL;
 
-  buffer = pybuf.buf;
+  Py_buffer_up buffer_up (&pybuf);
+  buffer = (const gdb_byte *) pybuf.buf;
   pattern_size = pybuf.len;
-#else
-  PyObject *pattern;
-
-  if (! PyArg_ParseTupleAndKeywords (args, kw, "OOO", keywords,
-                                    &start_addr_obj, &length_obj,
-                                    &pattern))
-     return NULL;
-
-  if (!PyObject_CheckReadBuffer (pattern))
-    {
-      PyErr_SetString (PyExc_RuntimeError,
-                      _("The pattern is not a Python buffer."));
-
-      return NULL;
-    }
-
-  if (PyObject_AsReadBuffer (pattern, &buffer, &pattern_size) == -1)
-    return NULL;
-#endif
 
   if (get_addr_from_python (start_addr_obj, &start_addr) < 0)
-    goto fail;
+    return nullptr;
 
   if (get_addr_from_python (length_obj, &length) < 0)
-    goto fail;
+    return nullptr;
 
   if (!length)
     {
       PyErr_SetString (PyExc_ValueError,
                       _("Search range is empty."));
-      goto fail;
+      return nullptr;
     }
   /* Watch for overflows.  */
   else if (length > CORE_ADDR_MAX
@@ -768,36 +719,26 @@ infpy_search_memory (PyObject *self, PyObject *args, PyObject *kw)
     {
       PyErr_SetString (PyExc_ValueError,
                       _("The search range is too large."));
-      goto fail;
+      return nullptr;
     }
 
-  TRY
+  try
     {
       found = target_search_memory (start_addr, length,
                                    buffer, pattern_size,
                                    &found_addr);
     }
-  CATCH (ex, RETURN_MASK_ALL)
+  catch (gdb_exception &ex)
     {
-      except = ex;
+      except = std::move (ex);
     }
-  END_CATCH
 
-#ifdef IS_PY3K
-  PyBuffer_Release (&pybuf);
-#endif
   GDB_PY_HANDLE_EXCEPTION (except);
 
   if (found)
     return PyLong_FromLong (found_addr);
   else
     Py_RETURN_NONE;
-
- fail:
-#ifdef IS_PY3K
-  PyBuffer_Release (&pybuf);
-#endif
-  return NULL;
 }
 
 /* Implementation of gdb.Inferior.is_valid (self) -> Boolean.
@@ -814,6 +755,93 @@ infpy_is_valid (PyObject *self, PyObject *args)
   Py_RETURN_TRUE;
 }
 
+/* Implementation of gdb.Inferior.thread_from_handle (self, handle)
+                        ->  gdb.InferiorThread.  */
+
+static PyObject *
+infpy_thread_from_thread_handle (PyObject *self, PyObject *args, PyObject *kw)
+{
+  PyObject *handle_obj;
+  inferior_object *inf_obj = (inferior_object *) self;
+  static const char *keywords[] = { "handle", NULL };
+
+  INFPY_REQUIRE_VALID (inf_obj);
+
+  if (! gdb_PyArg_ParseTupleAndKeywords (args, kw, "O", keywords, &handle_obj))
+    return NULL;
+
+  const gdb_byte *bytes;
+  size_t bytes_len;
+  Py_buffer_up buffer_up;
+  Py_buffer py_buf;
+
+  if (PyObject_CheckBuffer (handle_obj)
+      && PyObject_GetBuffer (handle_obj, &py_buf, PyBUF_SIMPLE) == 0)
+    {
+      buffer_up.reset (&py_buf);
+      bytes = (const gdb_byte *) py_buf.buf;
+      bytes_len = py_buf.len;
+    }
+  else if (gdbpy_is_value_object (handle_obj))
+    {
+      struct value *val = value_object_to_value (handle_obj);
+      bytes = value_contents_all (val);
+      bytes_len = TYPE_LENGTH (value_type (val));
+    }
+  else
+    {
+      PyErr_SetString (PyExc_TypeError,
+                      _("Argument 'handle' must be a thread handle object."));
+
+      return NULL;
+    }
+
+  try
+    {
+      struct thread_info *thread_info;
+
+      thread_info = find_thread_by_handle
+        (gdb::array_view<const gdb_byte> (bytes, bytes_len),
+        inf_obj->inferior);
+      if (thread_info != NULL)
+       return thread_to_thread_object (thread_info).release ();
+    }
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
+
+  Py_RETURN_NONE;
+}
+
+/* Implementation of gdb.Inferior.architecture.  */
+
+static PyObject *
+infpy_architecture (PyObject *self, PyObject *args)
+{
+  inferior_object *inf = (inferior_object *) self;
+
+  INFPY_REQUIRE_VALID (inf);
+
+  return gdbarch_to_arch_object (inf->inferior->gdbarch);
+}
+
+/* Implement repr() for gdb.Inferior.  */
+
+static PyObject *
+infpy_repr (PyObject *obj)
+{
+  inferior_object *self = (inferior_object *) obj;
+  inferior *inf = self->inferior;
+
+  if (inf == nullptr)
+    return PyString_FromString ("<gdb.Inferior (invalid)>");
+
+  return PyString_FromFormat ("<gdb.Inferior num=%d, pid=%d>",
+                             inf->num, inf->pid);
+}
+
+
 static void
 infpy_dealloc (PyObject *obj)
 {
@@ -824,6 +852,7 @@ infpy_dealloc (PyObject *obj)
     return;
 
   set_inferior_data (inf, infpy_inf_data_key, NULL);
+  Py_TYPE (obj)->tp_free (obj);
 }
 
 /* Clear the INFERIOR pointer in an Inferior object and clear the
@@ -831,32 +860,25 @@ infpy_dealloc (PyObject *obj)
 static void
 py_free_inferior (struct inferior *inf, void *datum)
 {
-
-  struct cleanup *cleanup;
-  inferior_object *inf_obj = (inferior_object *) datum;
   struct threadlist_entry *th_entry, *th_tmp;
 
   if (!gdb_python_initialized)
     return;
 
-  cleanup = ensure_python_env (python_gdbarch, python_language);
+  gdbpy_enter enter_py (python_gdbarch, python_language);
+  gdbpy_ref<inferior_object> inf_obj ((inferior_object *) datum);
 
   inf_obj->inferior = NULL;
 
   /* Deallocate threads list.  */
   for (th_entry = inf_obj->threads; th_entry != NULL;)
     {
-      Py_DECREF (th_entry->thread_obj);
-
       th_tmp = th_entry;
       th_entry = th_entry->next;
-      xfree (th_tmp);
+      delete th_tmp;
     }
 
   inf_obj->nthreads = 0;
-
-  Py_DECREF ((PyObject *) inf_obj);
-  do_cleanups (cleanup);
 }
 
 /* Implementation of gdb.selected_inferior() -> gdb.Inferior.
@@ -865,7 +887,8 @@ py_free_inferior (struct inferior *inf, void *datum)
 PyObject *
 gdbpy_selected_inferior (PyObject *self, PyObject *args)
 {
-  return inferior_to_inferior_object (current_inferior ());
+  return ((PyObject *)
+         inferior_to_inferior_object (current_inferior ()).release ());
 }
 
 int
@@ -881,32 +904,35 @@ gdbpy_initialize_inferior (void)
   infpy_inf_data_key =
     register_inferior_data_with_cleanup (NULL, py_free_inferior);
 
-  observer_attach_new_thread (add_thread_object);
-  observer_attach_thread_exit (delete_thread_object);
-  observer_attach_normal_stop (python_on_normal_stop);
-  observer_attach_target_resumed (python_on_resume);
-  observer_attach_inferior_call_pre (python_on_inferior_call_pre);
-  observer_attach_inferior_call_post (python_on_inferior_call_post);
-  observer_attach_memory_changed (python_on_memory_change);
-  observer_attach_register_changed (python_on_register_change);
-  observer_attach_inferior_exit (python_inferior_exit);
-  observer_attach_new_objfile (python_new_objfile);
+  gdb::observers::new_thread.attach (add_thread_object);
+  gdb::observers::thread_exit.attach (delete_thread_object);
+  gdb::observers::normal_stop.attach (python_on_normal_stop);
+  gdb::observers::target_resumed.attach (python_on_resume);
+  gdb::observers::inferior_call_pre.attach (python_on_inferior_call_pre);
+  gdb::observers::inferior_call_post.attach (python_on_inferior_call_post);
+  gdb::observers::memory_changed.attach (python_on_memory_change);
+  gdb::observers::register_changed.attach (python_on_register_change);
+  gdb::observers::inferior_exit.attach (python_inferior_exit);
+  gdb::observers::new_objfile.attach (python_new_objfile);
+  gdb::observers::inferior_added.attach (python_new_inferior);
+  gdb::observers::inferior_removed.attach (python_inferior_deleted);
 
   membuf_object_type.tp_new = PyType_GenericNew;
   if (PyType_Ready (&membuf_object_type) < 0)
     return -1;
 
-  return gdb_pymodule_addobject (gdb_module, "Membuf", (PyObject *)
-                                &membuf_object_type);
+  return gdb_pymodule_addobject (gdb_module, "Membuf",
+                                (PyObject *) &membuf_object_type);
 }
 
-static PyGetSetDef inferior_object_getset[] =
+static gdb_PyGetSetDef inferior_object_getset[] =
 {
   { "num", infpy_get_num, NULL, "ID of inferior, as assigned by GDB.", NULL },
   { "pid", infpy_get_pid, NULL, "PID of inferior, as assigned by the OS.",
     NULL },
   { "was_attached", infpy_get_was_attached, NULL,
     "True if the inferior was created using 'attach'.", NULL },
+  { "progspace", infpy_get_progspace, NULL, "Program space of this inferior" },
   { NULL }
 };
 
@@ -929,6 +955,19 @@ Write the given buffer object to the inferior's memory." },
     METH_VARARGS | METH_KEYWORDS,
     "search_memory (address, length, pattern) -> long\n\
 Return a long with the address of a match, or None." },
+  /* thread_from_thread_handle is deprecated.  */
+  { "thread_from_thread_handle", (PyCFunction) infpy_thread_from_thread_handle,
+    METH_VARARGS | METH_KEYWORDS,
+    "thread_from_thread_handle (handle) -> gdb.InferiorThread.\n\
+Return thread object corresponding to thread handle.\n\
+This method is deprecated - use thread_from_handle instead." },
+  { "thread_from_handle", (PyCFunction) infpy_thread_from_thread_handle,
+    METH_VARARGS | METH_KEYWORDS,
+    "thread_from_handle (handle) -> gdb.InferiorThread.\n\
+Return thread object corresponding to thread handle." },
+  { "architecture", (PyCFunction) infpy_architecture, METH_NOARGS,
+    "architecture () -> gdb.Architecture\n\
+Return architecture of this inferior." },
   { NULL }
 };
 
@@ -943,7 +982,7 @@ PyTypeObject inferior_object_type =
   0,                             /* tp_getattr */
   0,                             /* tp_setattr */
   0,                             /* tp_compare */
-  0,                             /* tp_repr */
+  infpy_repr,                    /* tp_repr */
   0,                             /* tp_as_number */
   0,                             /* tp_as_sequence */
   0,                             /* tp_as_mapping */
@@ -982,20 +1021,11 @@ static PyBufferProcs buffer_procs =
 
 #else
 
-/* Python doesn't provide a decent way to get compatibility here.  */
-#if HAVE_LIBPYTHON2_4
-#define CHARBUFFERPROC_NAME getcharbufferproc
-#else
-#define CHARBUFFERPROC_NAME charbufferproc
-#endif
-
 static PyBufferProcs buffer_procs = {
   get_read_buffer,
   get_write_buffer,
   get_seg_count,
-  /* The cast here works around a difference between Python 2.4 and
-     Python 2.5.  */
-  (CHARBUFFERPROC_NAME) get_char_buffer
+  get_char_buffer
 };
 #endif /* IS_PY3K */
 
This page took 0.03613 seconds and 4 git commands to generate.