Home | History | Annotate | Line # | Download | only in python
py-inferior.c revision 1.10
      1 /* Python interface to inferiors.
      2 
      3    Copyright (C) 2009-2023 Free Software Foundation, Inc.
      4 
      5    This file is part of GDB.
      6 
      7    This program is free software; you can redistribute it and/or modify
      8    it under the terms of the GNU General Public License as published by
      9    the Free Software Foundation; either version 3 of the License, or
     10    (at your option) any later version.
     11 
     12    This program is distributed in the hope that it will be useful,
     13    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15    GNU General Public License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     19 
     20 #include "defs.h"
     21 #include "auto-load.h"
     22 #include "gdbcore.h"
     23 #include "gdbthread.h"
     24 #include "inferior.h"
     25 #include "objfiles.h"
     26 #include "observable.h"
     27 #include "python-internal.h"
     28 #include "arch-utils.h"
     29 #include "language.h"
     30 #include "gdbsupport/gdb_signals.h"
     31 #include "py-event.h"
     32 #include "py-stopevent.h"
     33 #include <unordered_map>
     34 
     35 using thread_map_t
     36   = std::unordered_map<thread_info *, gdbpy_ref<thread_object>>;
     37 
     38 struct inferior_object
     39 {
     40   PyObject_HEAD
     41 
     42   /* The inferior we represent.  */
     43   struct inferior *inferior;
     44 
     45   /* thread_object instances under this inferior.  This owns a
     46      reference to each object it contains.  */
     47   thread_map_t *threads;
     48 };
     49 
     50 extern PyTypeObject inferior_object_type
     51     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("inferior_object");
     52 
     53 /* Deleter to clean up when an inferior is removed.  */
     54 struct infpy_deleter
     55 {
     56   void operator() (inferior_object *obj)
     57   {
     58     if (!gdb_python_initialized)
     59       return;
     60 
     61     gdbpy_enter enter_py;
     62     gdbpy_ref<inferior_object> inf_obj (obj);
     63 
     64     inf_obj->inferior = NULL;
     65 
     66     delete inf_obj->threads;
     67   }
     68 };
     69 
     70 static const registry<inferior>::key<inferior_object, infpy_deleter>
     71      infpy_inf_data_key;
     72 
     73 /* Require that INFERIOR be a valid inferior ID.  */
     74 #define INFPY_REQUIRE_VALID(Inferior)				\
     75   do {								\
     76     if (!Inferior->inferior)					\
     77       {								\
     78 	PyErr_SetString (PyExc_RuntimeError,			\
     79 			 _("Inferior no longer exists."));	\
     80 	return NULL;						\
     81       }								\
     82   } while (0)
     83 
     84 static void
     85 python_on_normal_stop (struct bpstat *bs, int print_frame)
     86 {
     87   enum gdb_signal stop_signal;
     88 
     89   if (!gdb_python_initialized)
     90     return;
     91 
     92   if (inferior_ptid == null_ptid)
     93     return;
     94 
     95   stop_signal = inferior_thread ()->stop_signal ();
     96 
     97   gdbpy_enter enter_py;
     98 
     99   if (emit_stop_event (bs, stop_signal) < 0)
    100     gdbpy_print_stack ();
    101 }
    102 
    103 static void
    104 python_on_resume (ptid_t ptid)
    105 {
    106   if (!gdb_python_initialized)
    107     return;
    108 
    109   gdbpy_enter enter_py (target_gdbarch ());
    110 
    111   if (emit_continue_event (ptid) < 0)
    112     gdbpy_print_stack ();
    113 }
    114 
    115 /* Callback, registered as an observer, that notifies Python listeners
    116    when an inferior function call is about to be made. */
    117 
    118 static void
    119 python_on_inferior_call_pre (ptid_t thread, CORE_ADDR address)
    120 {
    121   gdbpy_enter enter_py (target_gdbarch ());
    122 
    123   if (emit_inferior_call_event (INFERIOR_CALL_PRE, thread, address) < 0)
    124     gdbpy_print_stack ();
    125 }
    126 
    127 /* Callback, registered as an observer, that notifies Python listeners
    128    when an inferior function call has completed. */
    129 
    130 static void
    131 python_on_inferior_call_post (ptid_t thread, CORE_ADDR address)
    132 {
    133   gdbpy_enter enter_py (target_gdbarch ());
    134 
    135   if (emit_inferior_call_event (INFERIOR_CALL_POST, thread, address) < 0)
    136     gdbpy_print_stack ();
    137 }
    138 
    139 /* Callback, registered as an observer, that notifies Python listeners
    140    when a part of memory has been modified by user action (eg via a
    141    'set' command). */
    142 
    143 static void
    144 python_on_memory_change (struct inferior *inferior, CORE_ADDR addr, ssize_t len, const bfd_byte *data)
    145 {
    146   gdbpy_enter enter_py (target_gdbarch ());
    147 
    148   if (emit_memory_changed_event (addr, len) < 0)
    149     gdbpy_print_stack ();
    150 }
    151 
    152 /* Callback, registered as an observer, that notifies Python listeners
    153    when a register has been modified by user action (eg via a 'set'
    154    command). */
    155 
    156 static void
    157 python_on_register_change (frame_info_ptr frame, int regnum)
    158 {
    159   gdbpy_enter enter_py (target_gdbarch ());
    160 
    161   if (emit_register_changed_event (frame, regnum) < 0)
    162     gdbpy_print_stack ();
    163 }
    164 
    165 static void
    166 python_inferior_exit (struct inferior *inf)
    167 {
    168   const LONGEST *exit_code = NULL;
    169 
    170   if (!gdb_python_initialized)
    171     return;
    172 
    173   gdbpy_enter enter_py (target_gdbarch ());
    174 
    175   if (inf->has_exit_code)
    176     exit_code = &inf->exit_code;
    177 
    178   if (emit_exited_event (exit_code, inf) < 0)
    179     gdbpy_print_stack ();
    180 }
    181 
    182 /* Callback used to notify Python listeners about new objfiles loaded in the
    183    inferior.  OBJFILE may be NULL which means that the objfile list has been
    184    cleared (emptied).  */
    185 
    186 static void
    187 python_new_objfile (struct objfile *objfile)
    188 {
    189   if (!gdb_python_initialized)
    190     return;
    191 
    192   gdbpy_enter enter_py (objfile != NULL
    193 			? objfile->arch ()
    194 			: target_gdbarch ());
    195 
    196   if (objfile == NULL)
    197     {
    198       if (emit_clear_objfiles_event () < 0)
    199 	gdbpy_print_stack ();
    200     }
    201   else
    202     {
    203       if (emit_new_objfile_event (objfile) < 0)
    204 	gdbpy_print_stack ();
    205     }
    206 }
    207 
    208 /* Emit a Python event when an objfile is about to be removed.  */
    209 
    210 static void
    211 python_free_objfile (struct objfile *objfile)
    212 {
    213   if (!gdb_python_initialized)
    214     return;
    215 
    216   gdbpy_enter enter_py (objfile->arch ());
    217 
    218   if (emit_free_objfile_event (objfile) < 0)
    219     gdbpy_print_stack ();
    220 }
    221 
    222 /* Return a reference to the Python object of type Inferior
    223    representing INFERIOR.  If the object has already been created,
    224    return it and increment the reference count,  otherwise, create it.
    225    Return NULL on failure.  */
    226 
    227 gdbpy_ref<inferior_object>
    228 inferior_to_inferior_object (struct inferior *inferior)
    229 {
    230   inferior_object *inf_obj;
    231 
    232   inf_obj = infpy_inf_data_key.get (inferior);
    233   if (!inf_obj)
    234     {
    235       inf_obj = PyObject_New (inferior_object, &inferior_object_type);
    236       if (!inf_obj)
    237 	return NULL;
    238 
    239       inf_obj->inferior = inferior;
    240       inf_obj->threads = new thread_map_t ();
    241 
    242       /* PyObject_New initializes the new object with a refcount of 1.  This
    243 	 counts for the reference we are keeping in the inferior data.  */
    244       infpy_inf_data_key.set (inferior, inf_obj);
    245     }
    246 
    247   /* We are returning a new reference.  */
    248   gdb_assert (inf_obj != nullptr);
    249   return gdbpy_ref<inferior_object>::new_reference (inf_obj);
    250 }
    251 
    252 /* Called when a new inferior is created.  Notifies any Python event
    253    listeners.  */
    254 static void
    255 python_new_inferior (struct inferior *inf)
    256 {
    257   if (!gdb_python_initialized)
    258     return;
    259 
    260   gdbpy_enter enter_py;
    261 
    262   if (evregpy_no_listeners_p (gdb_py_events.new_inferior))
    263     return;
    264 
    265   gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (inf);
    266   if (inf_obj == NULL)
    267     {
    268       gdbpy_print_stack ();
    269       return;
    270     }
    271 
    272   gdbpy_ref<> event = create_event_object (&new_inferior_event_object_type);
    273   if (event == NULL
    274       || evpy_add_attribute (event.get (), "inferior",
    275 			     (PyObject *) inf_obj.get ()) < 0
    276       || evpy_emit_event (event.get (), gdb_py_events.new_inferior) < 0)
    277     gdbpy_print_stack ();
    278 }
    279 
    280 /* Called when an inferior is removed.  Notifies any Python event
    281    listeners.  */
    282 static void
    283 python_inferior_deleted (struct inferior *inf)
    284 {
    285   if (!gdb_python_initialized)
    286     return;
    287 
    288   gdbpy_enter enter_py;
    289 
    290   if (evregpy_no_listeners_p (gdb_py_events.inferior_deleted))
    291     return;
    292 
    293   gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (inf);
    294   if (inf_obj == NULL)
    295     {
    296       gdbpy_print_stack ();
    297       return;
    298     }
    299 
    300   gdbpy_ref<> event = create_event_object (&inferior_deleted_event_object_type);
    301   if (event == NULL
    302       || evpy_add_attribute (event.get (), "inferior",
    303 			     (PyObject *) inf_obj.get ()) < 0
    304       || evpy_emit_event (event.get (), gdb_py_events.inferior_deleted) < 0)
    305     gdbpy_print_stack ();
    306 }
    307 
    308 gdbpy_ref<>
    309 thread_to_thread_object (thread_info *thr)
    310 {
    311   gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (thr->inf);
    312   if (inf_obj == NULL)
    313     return NULL;
    314 
    315   auto thread_it = inf_obj->threads->find (thr);
    316   if (thread_it != inf_obj->threads->end ())
    317     return gdbpy_ref<>::new_reference
    318       ((PyObject *) (thread_it->second.get ()));
    319 
    320   PyErr_SetString (PyExc_SystemError,
    321 		   _("could not find gdb thread object"));
    322   return NULL;
    323 }
    324 
    325 static void
    326 add_thread_object (struct thread_info *tp)
    327 {
    328   inferior_object *inf_obj;
    329 
    330   if (!gdb_python_initialized)
    331     return;
    332 
    333   gdbpy_enter enter_py;
    334 
    335   gdbpy_ref<thread_object> thread_obj = create_thread_object (tp);
    336   if (thread_obj == NULL)
    337     {
    338       gdbpy_print_stack ();
    339       return;
    340     }
    341 
    342   inf_obj = (inferior_object *) thread_obj->inf_obj;
    343 
    344   auto ins_result = inf_obj->threads->emplace
    345     (thread_map_t::value_type (tp, std::move (thread_obj)));
    346 
    347   if (!ins_result.second)
    348     return;
    349 
    350   if (evregpy_no_listeners_p (gdb_py_events.new_thread))
    351     return;
    352 
    353   gdbpy_ref<> event = create_thread_event_object
    354     (&new_thread_event_object_type,
    355      (PyObject *) ins_result.first->second.get ());
    356 
    357   if (event == NULL
    358       || evpy_emit_event (event.get (), gdb_py_events.new_thread) < 0)
    359     gdbpy_print_stack ();
    360 }
    361 
    362 static void
    363 delete_thread_object (struct thread_info *tp, int ignore)
    364 {
    365   if (!gdb_python_initialized)
    366     return;
    367 
    368   gdbpy_enter enter_py;
    369 
    370   gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (tp->inf);
    371   if (inf_obj == NULL)
    372     return;
    373 
    374   auto it = inf_obj->threads->find (tp);
    375   if (it != inf_obj->threads->end ())
    376     {
    377       /* Some python code can still hold a reference to the thread_object
    378 	 instance.   Make sure to remove the link to the associated
    379 	 thread_info object as it will be freed soon.  This makes the python
    380 	 object invalid (i.e. gdb.InfThread.is_valid returns False).  */
    381       it->second->thread = nullptr;
    382       inf_obj->threads->erase (it);
    383     }
    384 }
    385 
    386 static PyObject *
    387 infpy_threads (PyObject *self, PyObject *args)
    388 {
    389   int i = 0;
    390   inferior_object *inf_obj = (inferior_object *) self;
    391   PyObject *tuple;
    392 
    393   INFPY_REQUIRE_VALID (inf_obj);
    394 
    395   try
    396     {
    397       update_thread_list ();
    398     }
    399   catch (const gdb_exception &except)
    400     {
    401       GDB_PY_HANDLE_EXCEPTION (except);
    402     }
    403 
    404   tuple = PyTuple_New (inf_obj->threads->size ());
    405   if (!tuple)
    406     return NULL;
    407 
    408   for (const thread_map_t::value_type &entry : *inf_obj->threads)
    409     {
    410       PyObject *thr = (PyObject *) entry.second.get ();
    411       Py_INCREF (thr);
    412       PyTuple_SET_ITEM (tuple, i, thr);
    413       i = i + 1;
    414     }
    415 
    416   return tuple;
    417 }
    418 
    419 static PyObject *
    420 infpy_get_num (PyObject *self, void *closure)
    421 {
    422   inferior_object *inf = (inferior_object *) self;
    423 
    424   INFPY_REQUIRE_VALID (inf);
    425 
    426   return gdb_py_object_from_longest (inf->inferior->num).release ();
    427 }
    428 
    429 /* Return the gdb.TargetConnection object for this inferior, or None if a
    430    connection does not exist.  */
    431 
    432 static PyObject *
    433 infpy_get_connection (PyObject *self, void *closure)
    434 {
    435   inferior_object *inf = (inferior_object *) self;
    436 
    437   INFPY_REQUIRE_VALID (inf);
    438 
    439   process_stratum_target *target = inf->inferior->process_target ();
    440   return target_to_connection_object (target).release ();
    441 }
    442 
    443 /* Return the connection number of the given inferior, or None if a
    444    connection does not exist.  */
    445 
    446 static PyObject *
    447 infpy_get_connection_num (PyObject *self, void *closure)
    448 {
    449   inferior_object *inf = (inferior_object *) self;
    450 
    451   INFPY_REQUIRE_VALID (inf);
    452 
    453   process_stratum_target *target = inf->inferior->process_target ();
    454   if (target == nullptr)
    455     Py_RETURN_NONE;
    456 
    457   return gdb_py_object_from_longest (target->connection_number).release ();
    458 }
    459 
    460 static PyObject *
    461 infpy_get_pid (PyObject *self, void *closure)
    462 {
    463   inferior_object *inf = (inferior_object *) self;
    464 
    465   INFPY_REQUIRE_VALID (inf);
    466 
    467   return gdb_py_object_from_longest (inf->inferior->pid).release ();
    468 }
    469 
    470 static PyObject *
    471 infpy_get_was_attached (PyObject *self, void *closure)
    472 {
    473   inferior_object *inf = (inferior_object *) self;
    474 
    475   INFPY_REQUIRE_VALID (inf);
    476   if (inf->inferior->attach_flag)
    477     Py_RETURN_TRUE;
    478   Py_RETURN_FALSE;
    479 }
    480 
    481 /* Getter of gdb.Inferior.progspace.  */
    482 
    483 static PyObject *
    484 infpy_get_progspace (PyObject *self, void *closure)
    485 {
    486   inferior_object *inf = (inferior_object *) self;
    487 
    488   INFPY_REQUIRE_VALID (inf);
    489 
    490   program_space *pspace = inf->inferior->pspace;
    491   gdb_assert (pspace != nullptr);
    492 
    493   return pspace_to_pspace_object (pspace).release ();
    494 }
    495 
    496 /* Implementation of gdb.inferiors () -> (gdb.Inferior, ...).
    497    Returns a tuple of all inferiors.  */
    498 PyObject *
    499 gdbpy_inferiors (PyObject *unused, PyObject *unused2)
    500 {
    501   gdbpy_ref<> list (PyList_New (0));
    502   if (list == NULL)
    503     return NULL;
    504 
    505   for (inferior *inf : all_inferiors ())
    506     {
    507       gdbpy_ref<inferior_object> inferior = inferior_to_inferior_object (inf);
    508 
    509       if (inferior == NULL)
    510 	continue;
    511 
    512       if (PyList_Append (list.get (), (PyObject *) inferior.get ()) != 0)
    513 	return NULL;
    514     }
    515 
    516   return PyList_AsTuple (list.get ());
    517 }
    518 
    519 /* Membuf and memory manipulation.  */
    520 
    521 /* Implementation of Inferior.read_memory (address, length).
    522    Returns a Python buffer object with LENGTH bytes of the inferior's
    523    memory at ADDRESS.  Both arguments are integers.  Returns NULL on error,
    524    with a python exception set.  */
    525 static PyObject *
    526 infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw)
    527 {
    528   CORE_ADDR addr, length;
    529   gdb::unique_xmalloc_ptr<gdb_byte> buffer;
    530   PyObject *addr_obj, *length_obj;
    531   static const char *keywords[] = { "address", "length", NULL };
    532 
    533   if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "OO", keywords,
    534 					&addr_obj, &length_obj))
    535     return NULL;
    536 
    537   if (get_addr_from_python (addr_obj, &addr) < 0
    538       || get_addr_from_python (length_obj, &length) < 0)
    539     return NULL;
    540 
    541   try
    542     {
    543       buffer.reset ((gdb_byte *) xmalloc (length));
    544 
    545       read_memory (addr, buffer.get (), length);
    546     }
    547   catch (const gdb_exception &except)
    548     {
    549       GDB_PY_HANDLE_EXCEPTION (except);
    550     }
    551 
    552 
    553   return gdbpy_buffer_to_membuf (std::move (buffer), addr, length);
    554 }
    555 
    556 /* Implementation of Inferior.write_memory (address, buffer [, length]).
    557    Writes the contents of BUFFER (a Python object supporting the read
    558    buffer protocol) at ADDRESS in the inferior's memory.  Write LENGTH
    559    bytes from BUFFER, or its entire contents if the argument is not
    560    provided.  The function returns nothing.  Returns NULL on error, with
    561    a python exception set.  */
    562 static PyObject *
    563 infpy_write_memory (PyObject *self, PyObject *args, PyObject *kw)
    564 {
    565   struct gdb_exception except;
    566   Py_ssize_t buf_len;
    567   const gdb_byte *buffer;
    568   CORE_ADDR addr, length;
    569   PyObject *addr_obj, *length_obj = NULL;
    570   static const char *keywords[] = { "address", "buffer", "length", NULL };
    571   Py_buffer pybuf;
    572 
    573   if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "Os*|O", keywords,
    574 					&addr_obj, &pybuf, &length_obj))
    575     return NULL;
    576 
    577   Py_buffer_up buffer_up (&pybuf);
    578   buffer = (const gdb_byte *) pybuf.buf;
    579   buf_len = pybuf.len;
    580 
    581   if (get_addr_from_python (addr_obj, &addr) < 0)
    582     return nullptr;
    583 
    584   if (!length_obj)
    585     length = buf_len;
    586   else if (get_addr_from_python (length_obj, &length) < 0)
    587     return nullptr;
    588 
    589   try
    590     {
    591       write_memory_with_notification (addr, buffer, length);
    592     }
    593   catch (gdb_exception &ex)
    594     {
    595       except = std::move (ex);
    596     }
    597 
    598   GDB_PY_HANDLE_EXCEPTION (except);
    599 
    600   Py_RETURN_NONE;
    601 }
    602 
    603 /* Implementation of
    604    gdb.search_memory (address, length, pattern).  ADDRESS is the
    605    address to start the search.  LENGTH specifies the scope of the
    606    search from ADDRESS.  PATTERN is the pattern to search for (and
    607    must be a Python object supporting the buffer protocol).
    608    Returns a Python Long object holding the address where the pattern
    609    was located, or if the pattern was not found, returns None.  Returns NULL
    610    on error, with a python exception set.  */
    611 static PyObject *
    612 infpy_search_memory (PyObject *self, PyObject *args, PyObject *kw)
    613 {
    614   struct gdb_exception except;
    615   CORE_ADDR start_addr, length;
    616   static const char *keywords[] = { "address", "length", "pattern", NULL };
    617   PyObject *start_addr_obj, *length_obj;
    618   Py_ssize_t pattern_size;
    619   const gdb_byte *buffer;
    620   CORE_ADDR found_addr;
    621   int found = 0;
    622   Py_buffer pybuf;
    623 
    624   if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "OOs*", keywords,
    625 					&start_addr_obj, &length_obj,
    626 					&pybuf))
    627     return NULL;
    628 
    629   Py_buffer_up buffer_up (&pybuf);
    630   buffer = (const gdb_byte *) pybuf.buf;
    631   pattern_size = pybuf.len;
    632 
    633   if (get_addr_from_python (start_addr_obj, &start_addr) < 0)
    634     return nullptr;
    635 
    636   if (get_addr_from_python (length_obj, &length) < 0)
    637     return nullptr;
    638 
    639   if (!length)
    640     {
    641       PyErr_SetString (PyExc_ValueError,
    642 		       _("Search range is empty."));
    643       return nullptr;
    644     }
    645   /* Watch for overflows.  */
    646   else if (length > CORE_ADDR_MAX
    647 	   || (start_addr + length - 1) < start_addr)
    648     {
    649       PyErr_SetString (PyExc_ValueError,
    650 		       _("The search range is too large."));
    651       return nullptr;
    652     }
    653 
    654   try
    655     {
    656       found = target_search_memory (start_addr, length,
    657 				    buffer, pattern_size,
    658 				    &found_addr);
    659     }
    660   catch (gdb_exception &ex)
    661     {
    662       except = std::move (ex);
    663     }
    664 
    665   GDB_PY_HANDLE_EXCEPTION (except);
    666 
    667   if (found)
    668     return gdb_py_object_from_ulongest (found_addr).release ();
    669   else
    670     Py_RETURN_NONE;
    671 }
    672 
    673 /* Implementation of gdb.Inferior.is_valid (self) -> Boolean.
    674    Returns True if this inferior object still exists in GDB.  */
    675 
    676 static PyObject *
    677 infpy_is_valid (PyObject *self, PyObject *args)
    678 {
    679   inferior_object *inf = (inferior_object *) self;
    680 
    681   if (! inf->inferior)
    682     Py_RETURN_FALSE;
    683 
    684   Py_RETURN_TRUE;
    685 }
    686 
    687 /* Implementation of gdb.Inferior.thread_from_handle (self, handle)
    688 			->  gdb.InferiorThread.  */
    689 
    690 static PyObject *
    691 infpy_thread_from_thread_handle (PyObject *self, PyObject *args, PyObject *kw)
    692 {
    693   PyObject *handle_obj;
    694   inferior_object *inf_obj = (inferior_object *) self;
    695   static const char *keywords[] = { "handle", NULL };
    696 
    697   INFPY_REQUIRE_VALID (inf_obj);
    698 
    699   if (! gdb_PyArg_ParseTupleAndKeywords (args, kw, "O", keywords, &handle_obj))
    700     return NULL;
    701 
    702   const gdb_byte *bytes;
    703   size_t bytes_len;
    704   Py_buffer_up buffer_up;
    705   Py_buffer py_buf;
    706 
    707   if (PyObject_CheckBuffer (handle_obj)
    708       && PyObject_GetBuffer (handle_obj, &py_buf, PyBUF_SIMPLE) == 0)
    709     {
    710       buffer_up.reset (&py_buf);
    711       bytes = (const gdb_byte *) py_buf.buf;
    712       bytes_len = py_buf.len;
    713     }
    714   else if (gdbpy_is_value_object (handle_obj))
    715     {
    716       struct value *val = value_object_to_value (handle_obj);
    717       bytes = value_contents_all (val).data ();
    718       bytes_len = value_type (val)->length ();
    719     }
    720   else
    721     {
    722       PyErr_SetString (PyExc_TypeError,
    723 		       _("Argument 'handle' must be a thread handle object."));
    724 
    725       return NULL;
    726     }
    727 
    728   try
    729     {
    730       struct thread_info *thread_info;
    731 
    732       thread_info = find_thread_by_handle
    733 	(gdb::array_view<const gdb_byte> (bytes, bytes_len),
    734 	 inf_obj->inferior);
    735       if (thread_info != NULL)
    736 	return thread_to_thread_object (thread_info).release ();
    737     }
    738   catch (const gdb_exception &except)
    739     {
    740       GDB_PY_HANDLE_EXCEPTION (except);
    741     }
    742 
    743   Py_RETURN_NONE;
    744 }
    745 
    746 /* Implementation of gdb.Inferior.architecture.  */
    747 
    748 static PyObject *
    749 infpy_architecture (PyObject *self, PyObject *args)
    750 {
    751   inferior_object *inf = (inferior_object *) self;
    752 
    753   INFPY_REQUIRE_VALID (inf);
    754 
    755   return gdbarch_to_arch_object (inf->inferior->gdbarch);
    756 }
    757 
    758 /* Implement repr() for gdb.Inferior.  */
    759 
    760 static PyObject *
    761 infpy_repr (PyObject *obj)
    762 {
    763   inferior_object *self = (inferior_object *) obj;
    764   inferior *inf = self->inferior;
    765 
    766   if (inf == nullptr)
    767     return PyUnicode_FromString ("<gdb.Inferior (invalid)>");
    768 
    769   return PyUnicode_FromFormat ("<gdb.Inferior num=%d, pid=%d>",
    770 			       inf->num, inf->pid);
    771 }
    772 
    773 
    774 static void
    775 infpy_dealloc (PyObject *obj)
    776 {
    777   inferior_object *inf_obj = (inferior_object *) obj;
    778 
    779   /* The inferior itself holds a reference to this Python object, which
    780      will keep the reference count of this object above zero until GDB
    781      deletes the inferior and py_free_inferior is called.
    782 
    783      Once py_free_inferior has been called then the link between this
    784      Python object and the inferior is set to nullptr, and then the
    785      reference count on this Python object is decremented.
    786 
    787      The result of all this is that the link between this Python object and
    788      the inferior should always have been set to nullptr before this
    789      function is called.  */
    790   gdb_assert (inf_obj->inferior == nullptr);
    791 
    792   Py_TYPE (obj)->tp_free (obj);
    793 }
    794 
    795 /* Implementation of gdb.selected_inferior() -> gdb.Inferior.
    796    Returns the current inferior object.  */
    797 
    798 PyObject *
    799 gdbpy_selected_inferior (PyObject *self, PyObject *args)
    800 {
    801   return ((PyObject *)
    802 	  inferior_to_inferior_object (current_inferior ()).release ());
    803 }
    804 
    805 int
    806 gdbpy_initialize_inferior (void)
    807 {
    808   if (PyType_Ready (&inferior_object_type) < 0)
    809     return -1;
    810 
    811   if (gdb_pymodule_addobject (gdb_module, "Inferior",
    812 			      (PyObject *) &inferior_object_type) < 0)
    813     return -1;
    814 
    815   gdb::observers::new_thread.attach (add_thread_object, "py-inferior");
    816   gdb::observers::thread_exit.attach (delete_thread_object, "py-inferior");
    817   gdb::observers::normal_stop.attach (python_on_normal_stop, "py-inferior");
    818   gdb::observers::target_resumed.attach (python_on_resume, "py-inferior");
    819   gdb::observers::inferior_call_pre.attach (python_on_inferior_call_pre,
    820 					    "py-inferior");
    821   gdb::observers::inferior_call_post.attach (python_on_inferior_call_post,
    822 					     "py-inferior");
    823   gdb::observers::memory_changed.attach (python_on_memory_change,
    824 					 "py-inferior");
    825   gdb::observers::register_changed.attach (python_on_register_change,
    826 					   "py-inferior");
    827   gdb::observers::inferior_exit.attach (python_inferior_exit, "py-inferior");
    828   /* Need to run after auto-load's new_objfile observer, so that
    829      auto-loaded pretty-printers are available.  */
    830   gdb::observers::new_objfile.attach
    831     (python_new_objfile, "py-inferior",
    832      { &auto_load_new_objfile_observer_token });
    833   gdb::observers::free_objfile.attach (python_free_objfile, "py-inferior");
    834   gdb::observers::inferior_added.attach (python_new_inferior, "py-inferior");
    835   gdb::observers::inferior_removed.attach (python_inferior_deleted,
    836 					   "py-inferior");
    837 
    838   return 0;
    839 }
    840 
    841 static gdb_PyGetSetDef inferior_object_getset[] =
    842 {
    843   { "num", infpy_get_num, NULL, "ID of inferior, as assigned by GDB.", NULL },
    844   { "connection", infpy_get_connection, NULL,
    845     "The gdb.TargetConnection for this inferior.", NULL },
    846   { "connection_num", infpy_get_connection_num, NULL,
    847     "ID of inferior's connection, as assigned by GDB.", NULL },
    848   { "pid", infpy_get_pid, NULL, "PID of inferior, as assigned by the OS.",
    849     NULL },
    850   { "was_attached", infpy_get_was_attached, NULL,
    851     "True if the inferior was created using 'attach'.", NULL },
    852   { "progspace", infpy_get_progspace, NULL, "Program space of this inferior" },
    853   { NULL }
    854 };
    855 
    856 static PyMethodDef inferior_object_methods[] =
    857 {
    858   { "is_valid", infpy_is_valid, METH_NOARGS,
    859     "is_valid () -> Boolean.\n\
    860 Return true if this inferior is valid, false if not." },
    861   { "threads", infpy_threads, METH_NOARGS,
    862     "Return all the threads of this inferior." },
    863   { "read_memory", (PyCFunction) infpy_read_memory,
    864     METH_VARARGS | METH_KEYWORDS,
    865     "read_memory (address, length) -> buffer\n\
    866 Return a buffer object for reading from the inferior's memory." },
    867   { "write_memory", (PyCFunction) infpy_write_memory,
    868     METH_VARARGS | METH_KEYWORDS,
    869     "write_memory (address, buffer [, length])\n\
    870 Write the given buffer object to the inferior's memory." },
    871   { "search_memory", (PyCFunction) infpy_search_memory,
    872     METH_VARARGS | METH_KEYWORDS,
    873     "search_memory (address, length, pattern) -> long\n\
    874 Return a long with the address of a match, or None." },
    875   /* thread_from_thread_handle is deprecated.  */
    876   { "thread_from_thread_handle", (PyCFunction) infpy_thread_from_thread_handle,
    877     METH_VARARGS | METH_KEYWORDS,
    878     "thread_from_thread_handle (handle) -> gdb.InferiorThread.\n\
    879 Return thread object corresponding to thread handle.\n\
    880 This method is deprecated - use thread_from_handle instead." },
    881   { "thread_from_handle", (PyCFunction) infpy_thread_from_thread_handle,
    882     METH_VARARGS | METH_KEYWORDS,
    883     "thread_from_handle (handle) -> gdb.InferiorThread.\n\
    884 Return thread object corresponding to thread handle." },
    885   { "architecture", (PyCFunction) infpy_architecture, METH_NOARGS,
    886     "architecture () -> gdb.Architecture\n\
    887 Return architecture of this inferior." },
    888   { NULL }
    889 };
    890 
    891 PyTypeObject inferior_object_type =
    892 {
    893   PyVarObject_HEAD_INIT (NULL, 0)
    894   "gdb.Inferior",		  /* tp_name */
    895   sizeof (inferior_object),	  /* tp_basicsize */
    896   0,				  /* tp_itemsize */
    897   infpy_dealloc,		  /* tp_dealloc */
    898   0,				  /* tp_print */
    899   0,				  /* tp_getattr */
    900   0,				  /* tp_setattr */
    901   0,				  /* tp_compare */
    902   infpy_repr,			  /* tp_repr */
    903   0,				  /* tp_as_number */
    904   0,				  /* tp_as_sequence */
    905   0,				  /* tp_as_mapping */
    906   0,				  /* tp_hash  */
    907   0,				  /* tp_call */
    908   0,				  /* tp_str */
    909   0,				  /* tp_getattro */
    910   0,				  /* tp_setattro */
    911   0,				  /* tp_as_buffer */
    912   Py_TPFLAGS_DEFAULT,		  /* tp_flags */
    913   "GDB inferior object",	  /* tp_doc */
    914   0,				  /* tp_traverse */
    915   0,				  /* tp_clear */
    916   0,				  /* tp_richcompare */
    917   0,				  /* tp_weaklistoffset */
    918   0,				  /* tp_iter */
    919   0,				  /* tp_iternext */
    920   inferior_object_methods,	  /* tp_methods */
    921   0,				  /* tp_members */
    922   inferior_object_getset,	  /* tp_getset */
    923   0,				  /* tp_base */
    924   0,				  /* tp_dict */
    925   0,				  /* tp_descr_get */
    926   0,				  /* tp_descr_set */
    927   0,				  /* tp_dictoffset */
    928   0,				  /* tp_init */
    929   0				  /* tp_alloc */
    930 };
    931