]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/python/py-inferior.c
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / python / py-inferior.c
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 };