xref: /netbsd-src/external/gpl3/gdb/dist/gdb/python/py-inferior.c (revision 53b02e147d4ed531c0d2a5ca9b3e8026ba3e99b5)
1 /* Python interface to inferiors.
2 
3    Copyright (C) 2009-2020 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 "gdbcore.h"
22 #include "gdbthread.h"
23 #include "inferior.h"
24 #include "objfiles.h"
25 #include "observable.h"
26 #include "python-internal.h"
27 #include "arch-utils.h"
28 #include "language.h"
29 #include "gdbsupport/gdb_signals.h"
30 #include "py-event.h"
31 #include "py-stopevent.h"
32 
33 struct threadlist_entry
34 {
35   threadlist_entry (gdbpy_ref<thread_object> &&ref)
36     : thread_obj (std::move (ref))
37   {
38   }
39 
40   gdbpy_ref<thread_object> thread_obj;
41   struct threadlist_entry *next;
42 };
43 
44 struct inferior_object
45 {
46   PyObject_HEAD
47 
48   /* The inferior we represent.  */
49   struct inferior *inferior;
50 
51   /* thread_object instances under this inferior.  This list owns a
52      reference to each object it contains.  */
53   struct threadlist_entry *threads;
54 
55   /* Number of threads in the list.  */
56   int nthreads;
57 };
58 
59 extern PyTypeObject inferior_object_type
60     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("inferior_object");
61 
62 static const struct inferior_data *infpy_inf_data_key;
63 
64 typedef struct {
65   PyObject_HEAD
66   void *buffer;
67 
68   /* These are kept just for mbpy_str.  */
69   CORE_ADDR addr;
70   CORE_ADDR length;
71 } membuf_object;
72 
73 extern PyTypeObject membuf_object_type
74     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("membuf_object");
75 
76 /* Require that INFERIOR be a valid inferior ID.  */
77 #define INFPY_REQUIRE_VALID(Inferior)				\
78   do {								\
79     if (!Inferior->inferior)					\
80       {								\
81 	PyErr_SetString (PyExc_RuntimeError,			\
82 			 _("Inferior no longer exists."));	\
83 	return NULL;						\
84       }								\
85   } while (0)
86 
87 static void
88 python_on_normal_stop (struct bpstats *bs, int print_frame)
89 {
90   enum gdb_signal stop_signal;
91 
92   if (!gdb_python_initialized)
93     return;
94 
95   if (inferior_ptid == null_ptid)
96     return;
97 
98   stop_signal = inferior_thread ()->suspend.stop_signal;
99 
100   gdbpy_enter enter_py (get_current_arch (), current_language);
101 
102   if (emit_stop_event (bs, stop_signal) < 0)
103     gdbpy_print_stack ();
104 }
105 
106 static void
107 python_on_resume (ptid_t ptid)
108 {
109   if (!gdb_python_initialized)
110     return;
111 
112   gdbpy_enter enter_py (target_gdbarch (), current_language);
113 
114   if (emit_continue_event (ptid) < 0)
115     gdbpy_print_stack ();
116 }
117 
118 /* Callback, registered as an observer, that notifies Python listeners
119    when an inferior function call is about to be made. */
120 
121 static void
122 python_on_inferior_call_pre (ptid_t thread, CORE_ADDR address)
123 {
124   gdbpy_enter enter_py (target_gdbarch (), current_language);
125 
126   if (emit_inferior_call_event (INFERIOR_CALL_PRE, thread, address) < 0)
127     gdbpy_print_stack ();
128 }
129 
130 /* Callback, registered as an observer, that notifies Python listeners
131    when an inferior function call has completed. */
132 
133 static void
134 python_on_inferior_call_post (ptid_t thread, CORE_ADDR address)
135 {
136   gdbpy_enter enter_py (target_gdbarch (), current_language);
137 
138   if (emit_inferior_call_event (INFERIOR_CALL_POST, thread, address) < 0)
139     gdbpy_print_stack ();
140 }
141 
142 /* Callback, registered as an observer, that notifies Python listeners
143    when a part of memory has been modified by user action (eg via a
144    'set' command). */
145 
146 static void
147 python_on_memory_change (struct inferior *inferior, CORE_ADDR addr, ssize_t len, const bfd_byte *data)
148 {
149   gdbpy_enter enter_py (target_gdbarch (), current_language);
150 
151   if (emit_memory_changed_event (addr, len) < 0)
152     gdbpy_print_stack ();
153 }
154 
155 /* Callback, registered as an observer, that notifies Python listeners
156    when a register has been modified by user action (eg via a 'set'
157    command). */
158 
159 static void
160 python_on_register_change (struct frame_info *frame, int regnum)
161 {
162   gdbpy_enter enter_py (target_gdbarch (), current_language);
163 
164   if (emit_register_changed_event (frame, regnum) < 0)
165     gdbpy_print_stack ();
166 }
167 
168 static void
169 python_inferior_exit (struct inferior *inf)
170 {
171   const LONGEST *exit_code = NULL;
172 
173   if (!gdb_python_initialized)
174     return;
175 
176   gdbpy_enter enter_py (target_gdbarch (), current_language);
177 
178   if (inf->has_exit_code)
179     exit_code = &inf->exit_code;
180 
181   if (emit_exited_event (exit_code, inf) < 0)
182     gdbpy_print_stack ();
183 }
184 
185 /* Callback used to notify Python listeners about new objfiles loaded in the
186    inferior.  OBJFILE may be NULL which means that the objfile list has been
187    cleared (emptied).  */
188 
189 static void
190 python_new_objfile (struct objfile *objfile)
191 {
192   if (!gdb_python_initialized)
193     return;
194 
195   gdbpy_enter enter_py (objfile != NULL
196 			? objfile->arch ()
197 			: target_gdbarch (),
198 			current_language);
199 
200   if (objfile == NULL)
201     {
202       if (emit_clear_objfiles_event () < 0)
203 	gdbpy_print_stack ();
204     }
205   else
206     {
207       if (emit_new_objfile_event (objfile) < 0)
208 	gdbpy_print_stack ();
209     }
210 }
211 
212 /* Return a reference to the Python object of type Inferior
213    representing INFERIOR.  If the object has already been created,
214    return it and increment the reference count,  otherwise, create it.
215    Return NULL on failure.  */
216 
217 gdbpy_ref<inferior_object>
218 inferior_to_inferior_object (struct inferior *inferior)
219 {
220   inferior_object *inf_obj;
221 
222   inf_obj = (inferior_object *) inferior_data (inferior, infpy_inf_data_key);
223   if (!inf_obj)
224     {
225       inf_obj = PyObject_New (inferior_object, &inferior_object_type);
226       if (!inf_obj)
227 	return NULL;
228 
229       inf_obj->inferior = inferior;
230       inf_obj->threads = NULL;
231       inf_obj->nthreads = 0;
232 
233       /* PyObject_New initializes the new object with a refcount of 1.  This
234 	 counts for the reference we are keeping in the inferior data.  */
235       set_inferior_data (inferior, infpy_inf_data_key, inf_obj);
236     }
237 
238   /* We are returning a new reference.  */
239   gdb_assert (inf_obj != nullptr);
240   return gdbpy_ref<inferior_object>::new_reference (inf_obj);
241 }
242 
243 /* Called when a new inferior is created.  Notifies any Python event
244    listeners.  */
245 static void
246 python_new_inferior (struct inferior *inf)
247 {
248   if (!gdb_python_initialized)
249     return;
250 
251   gdbpy_enter enter_py (python_gdbarch, python_language);
252 
253   if (evregpy_no_listeners_p (gdb_py_events.new_inferior))
254     return;
255 
256   gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (inf);
257   if (inf_obj == NULL)
258     {
259       gdbpy_print_stack ();
260       return;
261     }
262 
263   gdbpy_ref<> event = create_event_object (&new_inferior_event_object_type);
264   if (event == NULL
265       || evpy_add_attribute (event.get (), "inferior",
266 			     (PyObject *) inf_obj.get ()) < 0
267       || evpy_emit_event (event.get (), gdb_py_events.new_inferior) < 0)
268     gdbpy_print_stack ();
269 }
270 
271 /* Called when an inferior is removed.  Notifies any Python event
272    listeners.  */
273 static void
274 python_inferior_deleted (struct inferior *inf)
275 {
276   if (!gdb_python_initialized)
277     return;
278 
279   gdbpy_enter enter_py (python_gdbarch, python_language);
280 
281   if (evregpy_no_listeners_p (gdb_py_events.inferior_deleted))
282     return;
283 
284   gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (inf);
285   if (inf_obj == NULL)
286     {
287       gdbpy_print_stack ();
288       return;
289     }
290 
291   gdbpy_ref<> event = create_event_object (&inferior_deleted_event_object_type);
292   if (event == NULL
293       || evpy_add_attribute (event.get (), "inferior",
294 			     (PyObject *) inf_obj.get ()) < 0
295       || evpy_emit_event (event.get (), gdb_py_events.inferior_deleted) < 0)
296     gdbpy_print_stack ();
297 }
298 
299 gdbpy_ref<>
300 thread_to_thread_object (thread_info *thr)
301 {
302   gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (thr->inf);
303   if (inf_obj == NULL)
304     return NULL;
305 
306   for (threadlist_entry *thread = inf_obj->threads;
307        thread != NULL;
308        thread = thread->next)
309     if (thread->thread_obj->thread == thr)
310       return gdbpy_ref<>::new_reference ((PyObject *) thread->thread_obj.get ());
311 
312   PyErr_SetString (PyExc_SystemError,
313 		   _("could not find gdb thread object"));
314   return NULL;
315 }
316 
317 static void
318 add_thread_object (struct thread_info *tp)
319 {
320   inferior_object *inf_obj;
321   struct threadlist_entry *entry;
322 
323   if (!gdb_python_initialized)
324     return;
325 
326   gdbpy_enter enter_py (python_gdbarch, python_language);
327 
328   gdbpy_ref<thread_object> thread_obj = create_thread_object (tp);
329   if (thread_obj == NULL)
330     {
331       gdbpy_print_stack ();
332       return;
333     }
334 
335   inf_obj = (inferior_object *) thread_obj->inf_obj;
336 
337   entry = new threadlist_entry (std::move (thread_obj));
338   entry->next = inf_obj->threads;
339 
340   inf_obj->threads = entry;
341   inf_obj->nthreads++;
342 
343   if (evregpy_no_listeners_p (gdb_py_events.new_thread))
344     return;
345 
346   gdbpy_ref<> event = create_thread_event_object (&new_thread_event_object_type,
347 						  (PyObject *) inf_obj);
348   if (event == NULL
349       || evpy_emit_event (event.get (), gdb_py_events.new_thread) < 0)
350     gdbpy_print_stack ();
351 }
352 
353 static void
354 delete_thread_object (struct thread_info *tp, int ignore)
355 {
356   struct threadlist_entry **entry, *tmp;
357 
358   if (!gdb_python_initialized)
359     return;
360 
361   gdbpy_enter enter_py (python_gdbarch, python_language);
362 
363   gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (tp->inf);
364   if (inf_obj == NULL)
365     return;
366 
367   /* Find thread entry in its inferior's thread_list.  */
368   for (entry = &inf_obj->threads; *entry != NULL; entry =
369 	 &(*entry)->next)
370     if ((*entry)->thread_obj->thread == tp)
371       break;
372 
373   if (!*entry)
374     return;
375 
376   tmp = *entry;
377   tmp->thread_obj->thread = NULL;
378 
379   *entry = (*entry)->next;
380   inf_obj->nthreads--;
381 
382   delete tmp;
383 }
384 
385 static PyObject *
386 infpy_threads (PyObject *self, PyObject *args)
387 {
388   int i;
389   struct threadlist_entry *entry;
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->nthreads);
405   if (!tuple)
406     return NULL;
407 
408   for (i = 0, entry = inf_obj->threads; i < inf_obj->nthreads;
409        i++, entry = entry->next)
410     {
411       PyObject *thr = (PyObject *) entry->thread_obj.get ();
412       Py_INCREF (thr);
413       PyTuple_SET_ITEM (tuple, i, thr);
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 PyLong_FromLong (inf->inferior->num);
427 }
428 
429 static PyObject *
430 infpy_get_pid (PyObject *self, void *closure)
431 {
432   inferior_object *inf = (inferior_object *) self;
433 
434   INFPY_REQUIRE_VALID (inf);
435 
436   return PyLong_FromLong (inf->inferior->pid);
437 }
438 
439 static PyObject *
440 infpy_get_was_attached (PyObject *self, void *closure)
441 {
442   inferior_object *inf = (inferior_object *) self;
443 
444   INFPY_REQUIRE_VALID (inf);
445   if (inf->inferior->attach_flag)
446     Py_RETURN_TRUE;
447   Py_RETURN_FALSE;
448 }
449 
450 /* Getter of gdb.Inferior.progspace.  */
451 
452 static PyObject *
453 infpy_get_progspace (PyObject *self, void *closure)
454 {
455   inferior_object *inf = (inferior_object *) self;
456 
457   INFPY_REQUIRE_VALID (inf);
458 
459   program_space *pspace = inf->inferior->pspace;
460   gdb_assert (pspace != nullptr);
461 
462   return pspace_to_pspace_object (pspace).release ();
463 }
464 
465 /* Implementation of gdb.inferiors () -> (gdb.Inferior, ...).
466    Returns a tuple of all inferiors.  */
467 PyObject *
468 gdbpy_inferiors (PyObject *unused, PyObject *unused2)
469 {
470   gdbpy_ref<> list (PyList_New (0));
471   if (list == NULL)
472     return NULL;
473 
474   for (inferior *inf : all_inferiors ())
475     {
476       gdbpy_ref<inferior_object> inferior = inferior_to_inferior_object (inf);
477 
478       if (inferior == NULL)
479 	continue;
480 
481       if (PyList_Append (list.get (), (PyObject *) inferior.get ()) != 0)
482 	return NULL;
483     }
484 
485   return PyList_AsTuple (list.get ());
486 }
487 
488 /* Membuf and memory manipulation.  */
489 
490 /* Implementation of Inferior.read_memory (address, length).
491    Returns a Python buffer object with LENGTH bytes of the inferior's
492    memory at ADDRESS.  Both arguments are integers.  Returns NULL on error,
493    with a python exception set.  */
494 static PyObject *
495 infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw)
496 {
497   CORE_ADDR addr, length;
498   gdb::unique_xmalloc_ptr<gdb_byte> buffer;
499   PyObject *addr_obj, *length_obj, *result;
500   static const char *keywords[] = { "address", "length", NULL };
501 
502   if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "OO", keywords,
503 					&addr_obj, &length_obj))
504     return NULL;
505 
506   if (get_addr_from_python (addr_obj, &addr) < 0
507       || get_addr_from_python (length_obj, &length) < 0)
508     return NULL;
509 
510   try
511     {
512       buffer.reset ((gdb_byte *) xmalloc (length));
513 
514       read_memory (addr, buffer.get (), length);
515     }
516   catch (const gdb_exception &except)
517     {
518       GDB_PY_HANDLE_EXCEPTION (except);
519     }
520 
521   gdbpy_ref<membuf_object> membuf_obj (PyObject_New (membuf_object,
522 						     &membuf_object_type));
523   if (membuf_obj == NULL)
524     return NULL;
525 
526   membuf_obj->buffer = buffer.release ();
527   membuf_obj->addr = addr;
528   membuf_obj->length = length;
529 
530 #ifdef IS_PY3K
531   result = PyMemoryView_FromObject ((PyObject *) membuf_obj.get ());
532 #else
533   result = PyBuffer_FromReadWriteObject ((PyObject *) membuf_obj.get (), 0,
534 					 Py_END_OF_BUFFER);
535 #endif
536 
537   return result;
538 }
539 
540 /* Implementation of Inferior.write_memory (address, buffer [, length]).
541    Writes the contents of BUFFER (a Python object supporting the read
542    buffer protocol) at ADDRESS in the inferior's memory.  Write LENGTH
543    bytes from BUFFER, or its entire contents if the argument is not
544    provided.  The function returns nothing.  Returns NULL on error, with
545    a python exception set.  */
546 static PyObject *
547 infpy_write_memory (PyObject *self, PyObject *args, PyObject *kw)
548 {
549   struct gdb_exception except;
550   Py_ssize_t buf_len;
551   const gdb_byte *buffer;
552   CORE_ADDR addr, length;
553   PyObject *addr_obj, *length_obj = NULL;
554   static const char *keywords[] = { "address", "buffer", "length", NULL };
555   Py_buffer pybuf;
556 
557   if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "Os*|O", keywords,
558 					&addr_obj, &pybuf, &length_obj))
559     return NULL;
560 
561   Py_buffer_up buffer_up (&pybuf);
562   buffer = (const gdb_byte *) pybuf.buf;
563   buf_len = pybuf.len;
564 
565   if (get_addr_from_python (addr_obj, &addr) < 0)
566     return nullptr;
567 
568   if (!length_obj)
569     length = buf_len;
570   else if (get_addr_from_python (length_obj, &length) < 0)
571     return nullptr;
572 
573   try
574     {
575       write_memory_with_notification (addr, buffer, length);
576     }
577   catch (gdb_exception &ex)
578     {
579       except = std::move (ex);
580     }
581 
582   GDB_PY_HANDLE_EXCEPTION (except);
583 
584   Py_RETURN_NONE;
585 }
586 
587 /* Destructor of Membuf objects.  */
588 static void
589 mbpy_dealloc (PyObject *self)
590 {
591   xfree (((membuf_object *) self)->buffer);
592   Py_TYPE (self)->tp_free (self);
593 }
594 
595 /* Return a description of the Membuf object.  */
596 static PyObject *
597 mbpy_str (PyObject *self)
598 {
599   membuf_object *membuf_obj = (membuf_object *) self;
600 
601   return PyString_FromFormat (_("Memory buffer for address %s, \
602 which is %s bytes long."),
603 			      paddress (python_gdbarch, membuf_obj->addr),
604 			      pulongest (membuf_obj->length));
605 }
606 
607 #ifdef IS_PY3K
608 
609 static int
610 get_buffer (PyObject *self, Py_buffer *buf, int flags)
611 {
612   membuf_object *membuf_obj = (membuf_object *) self;
613   int ret;
614 
615   ret = PyBuffer_FillInfo (buf, self, membuf_obj->buffer,
616 			   membuf_obj->length, 0,
617 			   PyBUF_CONTIG);
618 
619   /* Despite the documentation saying this field is a "const char *",
620      in Python 3.4 at least, it's really a "char *".  */
621   buf->format = (char *) "c";
622 
623   return ret;
624 }
625 
626 #else
627 
628 static Py_ssize_t
629 get_read_buffer (PyObject *self, Py_ssize_t segment, void **ptrptr)
630 {
631   membuf_object *membuf_obj = (membuf_object *) self;
632 
633   if (segment)
634     {
635       PyErr_SetString (PyExc_SystemError,
636 		       _("The memory buffer supports only one segment."));
637       return -1;
638     }
639 
640   *ptrptr = membuf_obj->buffer;
641 
642   return membuf_obj->length;
643 }
644 
645 static Py_ssize_t
646 get_write_buffer (PyObject *self, Py_ssize_t segment, void **ptrptr)
647 {
648   return get_read_buffer (self, segment, ptrptr);
649 }
650 
651 static Py_ssize_t
652 get_seg_count (PyObject *self, Py_ssize_t *lenp)
653 {
654   if (lenp)
655     *lenp = ((membuf_object *) self)->length;
656 
657   return 1;
658 }
659 
660 static Py_ssize_t
661 get_char_buffer (PyObject *self, Py_ssize_t segment, char **ptrptr)
662 {
663   void *ptr = NULL;
664   Py_ssize_t ret;
665 
666   ret = get_read_buffer (self, segment, &ptr);
667   *ptrptr = (char *) ptr;
668 
669   return ret;
670 }
671 
672 #endif	/* IS_PY3K */
673 
674 /* Implementation of
675    gdb.search_memory (address, length, pattern).  ADDRESS is the
676    address to start the search.  LENGTH specifies the scope of the
677    search from ADDRESS.  PATTERN is the pattern to search for (and
678    must be a Python object supporting the buffer protocol).
679    Returns a Python Long object holding the address where the pattern
680    was located, or if the pattern was not found, returns None.  Returns NULL
681    on error, with a python exception set.  */
682 static PyObject *
683 infpy_search_memory (PyObject *self, PyObject *args, PyObject *kw)
684 {
685   struct gdb_exception except;
686   CORE_ADDR start_addr, length;
687   static const char *keywords[] = { "address", "length", "pattern", NULL };
688   PyObject *start_addr_obj, *length_obj;
689   Py_ssize_t pattern_size;
690   const gdb_byte *buffer;
691   CORE_ADDR found_addr;
692   int found = 0;
693   Py_buffer pybuf;
694 
695   if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "OOs*", keywords,
696 					&start_addr_obj, &length_obj,
697 					&pybuf))
698     return NULL;
699 
700   Py_buffer_up buffer_up (&pybuf);
701   buffer = (const gdb_byte *) pybuf.buf;
702   pattern_size = pybuf.len;
703 
704   if (get_addr_from_python (start_addr_obj, &start_addr) < 0)
705     return nullptr;
706 
707   if (get_addr_from_python (length_obj, &length) < 0)
708     return nullptr;
709 
710   if (!length)
711     {
712       PyErr_SetString (PyExc_ValueError,
713 		       _("Search range is empty."));
714       return nullptr;
715     }
716   /* Watch for overflows.  */
717   else if (length > CORE_ADDR_MAX
718 	   || (start_addr + length - 1) < start_addr)
719     {
720       PyErr_SetString (PyExc_ValueError,
721 		       _("The search range is too large."));
722       return nullptr;
723     }
724 
725   try
726     {
727       found = target_search_memory (start_addr, length,
728 				    buffer, pattern_size,
729 				    &found_addr);
730     }
731   catch (gdb_exception &ex)
732     {
733       except = std::move (ex);
734     }
735 
736   GDB_PY_HANDLE_EXCEPTION (except);
737 
738   if (found)
739     return gdb_py_object_from_ulongest (found_addr).release ();
740   else
741     Py_RETURN_NONE;
742 }
743 
744 /* Implementation of gdb.Inferior.is_valid (self) -> Boolean.
745    Returns True if this inferior object still exists in GDB.  */
746 
747 static PyObject *
748 infpy_is_valid (PyObject *self, PyObject *args)
749 {
750   inferior_object *inf = (inferior_object *) self;
751 
752   if (! inf->inferior)
753     Py_RETURN_FALSE;
754 
755   Py_RETURN_TRUE;
756 }
757 
758 /* Implementation of gdb.Inferior.thread_from_handle (self, handle)
759                         ->  gdb.InferiorThread.  */
760 
761 static PyObject *
762 infpy_thread_from_thread_handle (PyObject *self, PyObject *args, PyObject *kw)
763 {
764   PyObject *handle_obj;
765   inferior_object *inf_obj = (inferior_object *) self;
766   static const char *keywords[] = { "handle", NULL };
767 
768   INFPY_REQUIRE_VALID (inf_obj);
769 
770   if (! gdb_PyArg_ParseTupleAndKeywords (args, kw, "O", keywords, &handle_obj))
771     return NULL;
772 
773   const gdb_byte *bytes;
774   size_t bytes_len;
775   Py_buffer_up buffer_up;
776   Py_buffer py_buf;
777 
778   if (PyObject_CheckBuffer (handle_obj)
779       && PyObject_GetBuffer (handle_obj, &py_buf, PyBUF_SIMPLE) == 0)
780     {
781       buffer_up.reset (&py_buf);
782       bytes = (const gdb_byte *) py_buf.buf;
783       bytes_len = py_buf.len;
784     }
785   else if (gdbpy_is_value_object (handle_obj))
786     {
787       struct value *val = value_object_to_value (handle_obj);
788       bytes = value_contents_all (val);
789       bytes_len = TYPE_LENGTH (value_type (val));
790     }
791   else
792     {
793       PyErr_SetString (PyExc_TypeError,
794 		       _("Argument 'handle' must be a thread handle object."));
795 
796       return NULL;
797     }
798 
799   try
800     {
801       struct thread_info *thread_info;
802 
803       thread_info = find_thread_by_handle
804         (gdb::array_view<const gdb_byte> (bytes, bytes_len),
805 	 inf_obj->inferior);
806       if (thread_info != NULL)
807 	return thread_to_thread_object (thread_info).release ();
808     }
809   catch (const gdb_exception &except)
810     {
811       GDB_PY_HANDLE_EXCEPTION (except);
812     }
813 
814   Py_RETURN_NONE;
815 }
816 
817 /* Implementation of gdb.Inferior.architecture.  */
818 
819 static PyObject *
820 infpy_architecture (PyObject *self, PyObject *args)
821 {
822   inferior_object *inf = (inferior_object *) self;
823 
824   INFPY_REQUIRE_VALID (inf);
825 
826   return gdbarch_to_arch_object (inf->inferior->gdbarch);
827 }
828 
829 /* Implement repr() for gdb.Inferior.  */
830 
831 static PyObject *
832 infpy_repr (PyObject *obj)
833 {
834   inferior_object *self = (inferior_object *) obj;
835   inferior *inf = self->inferior;
836 
837   if (inf == nullptr)
838     return PyString_FromString ("<gdb.Inferior (invalid)>");
839 
840   return PyString_FromFormat ("<gdb.Inferior num=%d, pid=%d>",
841 			      inf->num, inf->pid);
842 }
843 
844 
845 static void
846 infpy_dealloc (PyObject *obj)
847 {
848   inferior_object *inf_obj = (inferior_object *) obj;
849   struct inferior *inf = inf_obj->inferior;
850 
851   if (! inf)
852     return;
853 
854   set_inferior_data (inf, infpy_inf_data_key, NULL);
855   Py_TYPE (obj)->tp_free (obj);
856 }
857 
858 /* Clear the INFERIOR pointer in an Inferior object and clear the
859    thread list.  */
860 static void
861 py_free_inferior (struct inferior *inf, void *datum)
862 {
863   struct threadlist_entry *th_entry, *th_tmp;
864 
865   if (!gdb_python_initialized)
866     return;
867 
868   gdbpy_enter enter_py (python_gdbarch, python_language);
869   gdbpy_ref<inferior_object> inf_obj ((inferior_object *) datum);
870 
871   inf_obj->inferior = NULL;
872 
873   /* Deallocate threads list.  */
874   for (th_entry = inf_obj->threads; th_entry != NULL;)
875     {
876       th_tmp = th_entry;
877       th_entry = th_entry->next;
878       delete th_tmp;
879     }
880 
881   inf_obj->nthreads = 0;
882 }
883 
884 /* Implementation of gdb.selected_inferior() -> gdb.Inferior.
885    Returns the current inferior object.  */
886 
887 PyObject *
888 gdbpy_selected_inferior (PyObject *self, PyObject *args)
889 {
890   return ((PyObject *)
891 	  inferior_to_inferior_object (current_inferior ()).release ());
892 }
893 
894 int
895 gdbpy_initialize_inferior (void)
896 {
897   if (PyType_Ready (&inferior_object_type) < 0)
898     return -1;
899 
900   if (gdb_pymodule_addobject (gdb_module, "Inferior",
901 			      (PyObject *) &inferior_object_type) < 0)
902     return -1;
903 
904   infpy_inf_data_key =
905     register_inferior_data_with_cleanup (NULL, py_free_inferior);
906 
907   gdb::observers::new_thread.attach (add_thread_object);
908   gdb::observers::thread_exit.attach (delete_thread_object);
909   gdb::observers::normal_stop.attach (python_on_normal_stop);
910   gdb::observers::target_resumed.attach (python_on_resume);
911   gdb::observers::inferior_call_pre.attach (python_on_inferior_call_pre);
912   gdb::observers::inferior_call_post.attach (python_on_inferior_call_post);
913   gdb::observers::memory_changed.attach (python_on_memory_change);
914   gdb::observers::register_changed.attach (python_on_register_change);
915   gdb::observers::inferior_exit.attach (python_inferior_exit);
916   gdb::observers::new_objfile.attach (python_new_objfile);
917   gdb::observers::inferior_added.attach (python_new_inferior);
918   gdb::observers::inferior_removed.attach (python_inferior_deleted);
919 
920   membuf_object_type.tp_new = PyType_GenericNew;
921   if (PyType_Ready (&membuf_object_type) < 0)
922     return -1;
923 
924   return gdb_pymodule_addobject (gdb_module, "Membuf",
925 				 (PyObject *) &membuf_object_type);
926 }
927 
928 static gdb_PyGetSetDef inferior_object_getset[] =
929 {
930   { "num", infpy_get_num, NULL, "ID of inferior, as assigned by GDB.", NULL },
931   { "pid", infpy_get_pid, NULL, "PID of inferior, as assigned by the OS.",
932     NULL },
933   { "was_attached", infpy_get_was_attached, NULL,
934     "True if the inferior was created using 'attach'.", NULL },
935   { "progspace", infpy_get_progspace, NULL, "Program space of this inferior" },
936   { NULL }
937 };
938 
939 static PyMethodDef inferior_object_methods[] =
940 {
941   { "is_valid", infpy_is_valid, METH_NOARGS,
942     "is_valid () -> Boolean.\n\
943 Return true if this inferior is valid, false if not." },
944   { "threads", infpy_threads, METH_NOARGS,
945     "Return all the threads of this inferior." },
946   { "read_memory", (PyCFunction) infpy_read_memory,
947     METH_VARARGS | METH_KEYWORDS,
948     "read_memory (address, length) -> buffer\n\
949 Return a buffer object for reading from the inferior's memory." },
950   { "write_memory", (PyCFunction) infpy_write_memory,
951     METH_VARARGS | METH_KEYWORDS,
952     "write_memory (address, buffer [, length])\n\
953 Write the given buffer object to the inferior's memory." },
954   { "search_memory", (PyCFunction) infpy_search_memory,
955     METH_VARARGS | METH_KEYWORDS,
956     "search_memory (address, length, pattern) -> long\n\
957 Return a long with the address of a match, or None." },
958   /* thread_from_thread_handle is deprecated.  */
959   { "thread_from_thread_handle", (PyCFunction) infpy_thread_from_thread_handle,
960     METH_VARARGS | METH_KEYWORDS,
961     "thread_from_thread_handle (handle) -> gdb.InferiorThread.\n\
962 Return thread object corresponding to thread handle.\n\
963 This method is deprecated - use thread_from_handle instead." },
964   { "thread_from_handle", (PyCFunction) infpy_thread_from_thread_handle,
965     METH_VARARGS | METH_KEYWORDS,
966     "thread_from_handle (handle) -> gdb.InferiorThread.\n\
967 Return thread object corresponding to thread handle." },
968   { "architecture", (PyCFunction) infpy_architecture, METH_NOARGS,
969     "architecture () -> gdb.Architecture\n\
970 Return architecture of this inferior." },
971   { NULL }
972 };
973 
974 PyTypeObject inferior_object_type =
975 {
976   PyVarObject_HEAD_INIT (NULL, 0)
977   "gdb.Inferior",		  /* tp_name */
978   sizeof (inferior_object),	  /* tp_basicsize */
979   0,				  /* tp_itemsize */
980   infpy_dealloc,		  /* tp_dealloc */
981   0,				  /* tp_print */
982   0,				  /* tp_getattr */
983   0,				  /* tp_setattr */
984   0,				  /* tp_compare */
985   infpy_repr,			  /* tp_repr */
986   0,				  /* tp_as_number */
987   0,				  /* tp_as_sequence */
988   0,				  /* tp_as_mapping */
989   0,				  /* tp_hash  */
990   0,				  /* tp_call */
991   0,				  /* tp_str */
992   0,				  /* tp_getattro */
993   0,				  /* tp_setattro */
994   0,				  /* tp_as_buffer */
995   Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER,  /* tp_flags */
996   "GDB inferior object",	  /* tp_doc */
997   0,				  /* tp_traverse */
998   0,				  /* tp_clear */
999   0,				  /* tp_richcompare */
1000   0,				  /* tp_weaklistoffset */
1001   0,				  /* tp_iter */
1002   0,				  /* tp_iternext */
1003   inferior_object_methods,	  /* tp_methods */
1004   0,				  /* tp_members */
1005   inferior_object_getset,	  /* tp_getset */
1006   0,				  /* tp_base */
1007   0,				  /* tp_dict */
1008   0,				  /* tp_descr_get */
1009   0,				  /* tp_descr_set */
1010   0,				  /* tp_dictoffset */
1011   0,				  /* tp_init */
1012   0				  /* tp_alloc */
1013 };
1014 
1015 #ifdef IS_PY3K
1016 
1017 static PyBufferProcs buffer_procs =
1018 {
1019   get_buffer
1020 };
1021 
1022 #else
1023 
1024 static PyBufferProcs buffer_procs = {
1025   get_read_buffer,
1026   get_write_buffer,
1027   get_seg_count,
1028   get_char_buffer
1029 };
1030 #endif	/* IS_PY3K */
1031 
1032 PyTypeObject membuf_object_type = {
1033   PyVarObject_HEAD_INIT (NULL, 0)
1034   "gdb.Membuf",			  /*tp_name*/
1035   sizeof (membuf_object),	  /*tp_basicsize*/
1036   0,				  /*tp_itemsize*/
1037   mbpy_dealloc,			  /*tp_dealloc*/
1038   0,				  /*tp_print*/
1039   0,				  /*tp_getattr*/
1040   0,				  /*tp_setattr*/
1041   0,				  /*tp_compare*/
1042   0,				  /*tp_repr*/
1043   0,				  /*tp_as_number*/
1044   0,				  /*tp_as_sequence*/
1045   0,				  /*tp_as_mapping*/
1046   0,				  /*tp_hash */
1047   0,				  /*tp_call*/
1048   mbpy_str,			  /*tp_str*/
1049   0,				  /*tp_getattro*/
1050   0,				  /*tp_setattro*/
1051   &buffer_procs,		  /*tp_as_buffer*/
1052   Py_TPFLAGS_DEFAULT,		  /*tp_flags*/
1053   "GDB memory buffer object", 	  /*tp_doc*/
1054   0,				  /* tp_traverse */
1055   0,				  /* tp_clear */
1056   0,				  /* tp_richcompare */
1057   0,				  /* tp_weaklistoffset */
1058   0,				  /* tp_iter */
1059   0,				  /* tp_iternext */
1060   0,				  /* tp_methods */
1061   0,				  /* tp_members */
1062   0,				  /* tp_getset */
1063   0,				  /* tp_base */
1064   0,				  /* tp_dict */
1065   0,				  /* tp_descr_get */
1066   0,				  /* tp_descr_set */
1067   0,				  /* tp_dictoffset */
1068   0,				  /* tp_init */
1069   0,				  /* tp_alloc */
1070 };
1071