GDB (xrefs)
Loading...
Searching...
No Matches
py-inferior.c
Go to the documentation of this file.
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"
34#include <unordered_map>
35
37 = std::unordered_map<thread_info *, gdbpy_ref<thread_object>>;
39struct inferior_object
40{
41 PyObject_HEAD
42
43 /* The inferior we represent. */
44 struct inferior *inferior;
45
46 /* thread_object instances under this inferior. This owns a
47 reference to each object it contains. */
49};
50
51extern PyTypeObject inferior_object_type
52 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("inferior_object");
53
54/* Deleter to clean up when an inferior is removed. */
55struct infpy_deleter
58 {
60 return;
61
62 gdbpy_enter enter_py;
63 gdbpy_ref<inferior_object> inf_obj (obj);
64
65 inf_obj->inferior = NULL;
66
67 delete inf_obj->threads;
68 }
69};
70
73
74/* Require that INFERIOR be a valid inferior ID. */
75#define INFPY_REQUIRE_VALID(Inferior) \
76 do { \
77 if (!Inferior->inferior) \
78 { \
79 PyErr_SetString (PyExc_RuntimeError, \
80 _("Inferior no longer exists.")); \
81 return NULL; \
82 } \
83 } while (0)
84
85static void
87{
88 enum gdb_signal stop_signal;
89
91 return;
92
93 if (inferior_ptid == null_ptid)
94 return;
95
96 stop_signal = inferior_thread ()->stop_signal ();
97
98 gdbpy_enter enter_py;
99
100 if (emit_stop_event (bs, stop_signal) < 0)
102}
103
104static void
105python_on_resume (ptid_t ptid)
106{
108 return;
109
110 gdbpy_enter enter_py (target_gdbarch ());
111
112 if (emit_continue_event (ptid) < 0)
114}
115
116/* Callback, registered as an observer, that notifies Python listeners
117 when an inferior function call is about to be made. */
118
119static void
120python_on_inferior_call_pre (ptid_t thread, CORE_ADDR address)
121{
122 gdbpy_enter enter_py (target_gdbarch ());
123
124 if (emit_inferior_call_event (INFERIOR_CALL_PRE, thread, address) < 0)
126}
127
128/* Callback, registered as an observer, that notifies Python listeners
129 when an inferior function call has completed. */
130
131static void
132python_on_inferior_call_post (ptid_t thread, CORE_ADDR address)
133{
134 gdbpy_enter enter_py (target_gdbarch ());
135
136 if (emit_inferior_call_event (INFERIOR_CALL_POST, thread, address) < 0)
138}
139
140/* Callback, registered as an observer, that notifies Python listeners
141 when a part of memory has been modified by user action (eg via a
142 'set' command). */
143
144static void
145python_on_memory_change (struct inferior *inferior, CORE_ADDR addr, ssize_t len, const bfd_byte *data)
146{
147 gdbpy_enter enter_py (target_gdbarch ());
148
149 if (emit_memory_changed_event (addr, len) < 0)
151}
152
153/* Callback, registered as an observer, that notifies Python listeners
154 when a register has been modified by user action (eg via a 'set'
155 command). */
156
157static void
159{
160 gdbpy_enter enter_py (target_gdbarch ());
161
162 if (emit_register_changed_event (frame, regnum) < 0)
164}
165
166static void
168{
169 const LONGEST *exit_code = NULL;
170
172 return;
173
174 gdbpy_enter enter_py (target_gdbarch ());
175
176 if (inf->has_exit_code)
177 exit_code = &inf->exit_code;
178
179 if (emit_exited_event (exit_code, inf) < 0)
181}
182
183/* Callback used to notify Python listeners about new objfiles loaded in the
184 inferior. OBJFILE may be NULL which means that the objfile list has been
185 cleared (emptied). */
186
187static void
189{
191 return;
192
193 gdbpy_enter enter_py (objfile->arch ());
194
197}
198
199static void
201{
203 return;
204
205 gdbpy_enter enter_py (target_gdbarch ());
206
207 if (emit_clear_objfiles_event (pspace) < 0)
209}
210
211/* Emit a Python event when an objfile is about to be removed. */
212
213static void
215{
217 return;
218
219 gdbpy_enter enter_py (objfile->arch ());
220
223}
224
225/* Return a reference to the Python object of type Inferior
226 representing INFERIOR. If the object has already been created,
227 return it and increment the reference count, otherwise, create it.
228 Return NULL on failure. */
229
232{
233 inferior_object *inf_obj;
234
235 inf_obj = infpy_inf_data_key.get (inferior);
236 if (!inf_obj)
237 {
238 inf_obj = PyObject_New (inferior_object, &inferior_object_type);
239 if (!inf_obj)
240 return NULL;
241
242 inf_obj->inferior = inferior;
243 inf_obj->threads = new thread_map_t ();
244
245 /* PyObject_New initializes the new object with a refcount of 1. This
246 counts for the reference we are keeping in the inferior data. */
248 }
249
250 /* We are returning a new reference. */
251 gdb_assert (inf_obj != nullptr);
253}
254
255/* Called when a new inferior is created. Notifies any Python event
256 listeners. */
257static void
259{
261 return;
262
263 gdbpy_enter enter_py;
264
265 if (evregpy_no_listeners_p (gdb_py_events.new_inferior))
266 return;
267
269 if (inf_obj == NULL)
270 {
272 return;
273 }
274
275 gdbpy_ref<> event = create_event_object (&new_inferior_event_object_type);
276 if (event == NULL
277 || evpy_add_attribute (event.get (), "inferior",
278 (PyObject *) inf_obj.get ()) < 0
279 || evpy_emit_event (event.get (), gdb_py_events.new_inferior) < 0)
281}
282
283/* Called when an inferior is removed. Notifies any Python event
284 listeners. */
285static void
287{
289 return;
290
291 gdbpy_enter enter_py;
292
293 if (evregpy_no_listeners_p (gdb_py_events.inferior_deleted))
294 return;
295
297 if (inf_obj == NULL)
298 {
300 return;
301 }
302
303 gdbpy_ref<> event = create_event_object (&inferior_deleted_event_object_type);
304 if (event == NULL
305 || evpy_add_attribute (event.get (), "inferior",
306 (PyObject *) inf_obj.get ()) < 0
307 || evpy_emit_event (event.get (), gdb_py_events.inferior_deleted) < 0)
309}
310
313{
315 if (inf_obj == NULL)
316 return NULL;
317
318 auto thread_it = inf_obj->threads->find (thr);
319 if (thread_it != inf_obj->threads->end ())
321 ((PyObject *) (thread_it->second.get ()));
322
323 PyErr_SetString (PyExc_SystemError,
324 _("could not find gdb thread object"));
325 return NULL;
326}
327
328static void
330{
331 inferior_object *inf_obj;
332
334 return;
335
336 gdbpy_enter enter_py;
337
339 if (thread_obj == NULL)
340 {
342 return;
343 }
344
345 inf_obj = (inferior_object *) thread_obj->inf_obj;
346
347 auto ins_result = inf_obj->threads->emplace
348 (thread_map_t::value_type (tp, std::move (thread_obj)));
349
350 if (!ins_result.second)
351 return;
352
353 if (evregpy_no_listeners_p (gdb_py_events.new_thread))
354 return;
355
357 (&new_thread_event_object_type,
358 (PyObject *) ins_result.first->second.get ());
359
360 if (event == NULL
361 || evpy_emit_event (event.get (), gdb_py_events.new_thread) < 0)
363}
364
365static void
367 gdb::optional<ULONGEST> /* exit_code */,
368 bool /* silent */)
369{
371 return;
372
373 gdbpy_enter enter_py;
374
376 if (inf_obj == NULL)
377 return;
378
379 if (emit_thread_exit_event (tp) < 0)
381
382 auto it = inf_obj->threads->find (tp);
383 if (it != inf_obj->threads->end ())
384 {
385 /* Some python code can still hold a reference to the thread_object
386 instance. Make sure to remove the link to the associated
387 thread_info object as it will be freed soon. This makes the python
388 object invalid (i.e. gdb.InfThread.is_valid returns False). */
389 it->second->thread = nullptr;
390 inf_obj->threads->erase (it);
391 }
392}
393
394static PyObject *
395infpy_threads (PyObject *self, PyObject *args)
396{
397 int i = 0;
398 inferior_object *inf_obj = (inferior_object *) self;
399 PyObject *tuple;
400
401 INFPY_REQUIRE_VALID (inf_obj);
402
403 try
404 {
406 }
407 catch (const gdb_exception &except)
408 {
410 }
411
412 tuple = PyTuple_New (inf_obj->threads->size ());
413 if (!tuple)
414 return NULL;
415
416 for (const thread_map_t::value_type &entry : *inf_obj->threads)
417 {
418 PyObject *thr = (PyObject *) entry.second.get ();
419 Py_INCREF (thr);
420 PyTuple_SET_ITEM (tuple, i, thr);
421 i = i + 1;
422 }
423
424 return tuple;
425}
426
427static PyObject *
428infpy_get_num (PyObject *self, void *closure)
429{
431
433
434 return gdb_py_object_from_longest (inf->inferior->num).release ();
435}
436
437/* Return the gdb.TargetConnection object for this inferior, or None if a
438 connection does not exist. */
439
440static PyObject *
441infpy_get_connection (PyObject *self, void *closure)
442{
444
446
447 process_stratum_target *target = inf->inferior->process_target ();
448 return target_to_connection_object (target).release ();
449}
450
451/* Return the connection number of the given inferior, or None if a
452 connection does not exist. */
453
454static PyObject *
455infpy_get_connection_num (PyObject *self, void *closure)
456{
458
460
461 process_stratum_target *target = inf->inferior->process_target ();
462 if (target == nullptr)
463 Py_RETURN_NONE;
464
465 return gdb_py_object_from_longest (target->connection_number).release ();
466}
467
468static PyObject *
469infpy_get_pid (PyObject *self, void *closure)
470{
472
474
475 return gdb_py_object_from_longest (inf->inferior->pid).release ();
476}
477
478static PyObject *
479infpy_get_was_attached (PyObject *self, void *closure)
480{
482
484 if (inf->inferior->attach_flag)
485 Py_RETURN_TRUE;
486 Py_RETURN_FALSE;
487}
488
489/* Getter of gdb.Inferior.progspace. */
490
491static PyObject *
492infpy_get_progspace (PyObject *self, void *closure)
493{
495
497
498 program_space *pspace = inf->inferior->pspace;
499 gdb_assert (pspace != nullptr);
500
501 return pspace_to_pspace_object (pspace).release ();
502}
503
504/* Implementation of gdb.inferiors () -> (gdb.Inferior, ...).
505 Returns a tuple of all inferiors. */
507gdbpy_inferiors (PyObject *unused, PyObject *unused2)
508{
509 gdbpy_ref<> list (PyList_New (0));
510 if (list == NULL)
511 return NULL;
512
513 for (inferior *inf : all_inferiors ())
514 {
516
517 if (inferior == NULL)
518 continue;
519
520 if (PyList_Append (list.get (), (PyObject *) inferior.get ()) != 0)
521 return NULL;
522 }
523
524 return PyList_AsTuple (list.get ());
525}
526
527/* Membuf and memory manipulation. */
528
529/* Implementation of Inferior.read_memory (address, length).
530 Returns a Python buffer object with LENGTH bytes of the inferior's
531 memory at ADDRESS. Both arguments are integers. Returns NULL on error,
532 with a python exception set. */
533static PyObject *
535{
537 CORE_ADDR addr, length;
538 gdb::unique_xmalloc_ptr<gdb_byte> buffer;
539 PyObject *addr_obj, *length_obj;
540 static const char *keywords[] = { "address", "length", NULL };
541
543
544 if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "OO", keywords,
545 &addr_obj, &length_obj))
546 return NULL;
547
548 if (get_addr_from_python (addr_obj, &addr) < 0
549 || get_addr_from_python (length_obj, &length) < 0)
550 return NULL;
551
552 try
553 {
554 /* Use this scoped-restore because we want to be able to read
555 memory from an unwinder. */
557 (inf->inferior);
558
559 buffer.reset ((gdb_byte *) xmalloc (length));
560
561 read_memory (addr, buffer.get (), length);
562 }
563 catch (const gdb_exception &except)
564 {
566 }
567
568
569 return gdbpy_buffer_to_membuf (std::move (buffer), addr, length);
570}
571
572/* Implementation of Inferior.write_memory (address, buffer [, length]).
573 Writes the contents of BUFFER (a Python object supporting the read
574 buffer protocol) at ADDRESS in the inferior's memory. Write LENGTH
575 bytes from BUFFER, or its entire contents if the argument is not
576 provided. The function returns nothing. Returns NULL on error, with
577 a python exception set. */
578static PyObject *
580{
582 struct gdb_exception except;
583 Py_ssize_t buf_len;
584 const gdb_byte *buffer;
585 CORE_ADDR addr, length;
586 PyObject *addr_obj, *length_obj = NULL;
587 static const char *keywords[] = { "address", "buffer", "length", NULL };
588 Py_buffer pybuf;
589
591
592 if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "Os*|O", keywords,
593 &addr_obj, &pybuf, &length_obj))
594 return NULL;
595
596 Py_buffer_up buffer_up (&pybuf);
597 buffer = (const gdb_byte *) pybuf.buf;
598 buf_len = pybuf.len;
599
600 if (get_addr_from_python (addr_obj, &addr) < 0)
601 return nullptr;
602
603 if (!length_obj)
604 length = buf_len;
605 else if (get_addr_from_python (length_obj, &length) < 0)
606 return nullptr;
607
608 try
609 {
610 /* It's probably not too important to avoid invalidating the
611 frame cache when writing memory, but this scoped-restore is
612 still used here, just to keep the code similar to other code
613 in this file. */
615 (inf->inferior);
616
617 write_memory_with_notification (addr, buffer, length);
618 }
619 catch (gdb_exception &ex)
620 {
621 except = std::move (ex);
622 }
623
625
626 Py_RETURN_NONE;
627}
628
629/* Implementation of
630 Inferior.search_memory (address, length, pattern). ADDRESS is the
631 address to start the search. LENGTH specifies the scope of the
632 search from ADDRESS. PATTERN is the pattern to search for (and
633 must be a Python object supporting the buffer protocol).
634 Returns a Python Long object holding the address where the pattern
635 was located, or if the pattern was not found, returns None. Returns NULL
636 on error, with a python exception set. */
637static PyObject *
639{
641 struct gdb_exception except;
642 CORE_ADDR start_addr, length;
643 static const char *keywords[] = { "address", "length", "pattern", NULL };
644 PyObject *start_addr_obj, *length_obj;
645 Py_ssize_t pattern_size;
646 const gdb_byte *buffer;
647 CORE_ADDR found_addr;
648 int found = 0;
649 Py_buffer pybuf;
650
652
653 if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "OOs*", keywords,
654 &start_addr_obj, &length_obj,
655 &pybuf))
656 return NULL;
657
658 Py_buffer_up buffer_up (&pybuf);
659 buffer = (const gdb_byte *) pybuf.buf;
660 pattern_size = pybuf.len;
661
662 if (get_addr_from_python (start_addr_obj, &start_addr) < 0)
663 return nullptr;
664
665 if (get_addr_from_python (length_obj, &length) < 0)
666 return nullptr;
667
668 if (!length)
669 {
670 PyErr_SetString (PyExc_ValueError,
671 _("Search range is empty."));
672 return nullptr;
673 }
674 /* Watch for overflows. */
675 else if (length > CORE_ADDR_MAX
676 || (start_addr + length - 1) < start_addr)
677 {
678 PyErr_SetString (PyExc_ValueError,
679 _("The search range is too large."));
680 return nullptr;
681 }
682
683 try
684 {
685 /* It's probably not too important to avoid invalidating the
686 frame cache when searching memory, but this scoped-restore is
687 still used here, just to keep the code similar to other code
688 in this file. */
690 (inf->inferior);
691
692 found = target_search_memory (start_addr, length,
693 buffer, pattern_size,
694 &found_addr);
695 }
696 catch (gdb_exception &ex)
697 {
698 except = std::move (ex);
699 }
700
702
703 if (found)
704 return gdb_py_object_from_ulongest (found_addr).release ();
705 else
706 Py_RETURN_NONE;
707}
708
709/* Implementation of gdb.Inferior.is_valid (self) -> Boolean.
710 Returns True if this inferior object still exists in GDB. */
711
712static PyObject *
713infpy_is_valid (PyObject *self, PyObject *args)
714{
716
717 if (! inf->inferior)
718 Py_RETURN_FALSE;
719
720 Py_RETURN_TRUE;
721}
722
723/* Implementation of gdb.Inferior.thread_from_handle (self, handle)
724 -> gdb.InferiorThread. */
725
726static PyObject *
728{
729 PyObject *handle_obj;
730 inferior_object *inf_obj = (inferior_object *) self;
731 static const char *keywords[] = { "handle", NULL };
732
733 INFPY_REQUIRE_VALID (inf_obj);
734
735 if (! gdb_PyArg_ParseTupleAndKeywords (args, kw, "O", keywords, &handle_obj))
736 return NULL;
737
738 const gdb_byte *bytes;
739 size_t bytes_len;
740 Py_buffer_up buffer_up;
741 Py_buffer py_buf;
742
743 if (PyObject_CheckBuffer (handle_obj)
744 && PyObject_GetBuffer (handle_obj, &py_buf, PyBUF_SIMPLE) == 0)
745 {
746 buffer_up.reset (&py_buf);
747 bytes = (const gdb_byte *) py_buf.buf;
748 bytes_len = py_buf.len;
749 }
750 else if (gdbpy_is_value_object (handle_obj))
751 {
752 struct value *val = value_object_to_value (handle_obj);
753 bytes = val->contents_all ().data ();
754 bytes_len = val->type ()->length ();
755 }
756 else
757 {
758 PyErr_SetString (PyExc_TypeError,
759 _("Argument 'handle' must be a thread handle object."));
760
761 return NULL;
762 }
763
764 try
765 {
766 struct thread_info *thread_info;
767
769 (gdb::array_view<const gdb_byte> (bytes, bytes_len),
770 inf_obj->inferior);
771 if (thread_info != NULL)
772 return thread_to_thread_object (thread_info).release ();
773 }
774 catch (const gdb_exception &except)
775 {
777 }
778
779 Py_RETURN_NONE;
780}
781
782/* Implementation of gdb.Inferior.architecture. */
783
784static PyObject *
786{
788
790
791 return gdbarch_to_arch_object (inf->inferior->gdbarch);
792}
793
794/* Implement repr() for gdb.Inferior. */
795
796static PyObject *
797infpy_repr (PyObject *obj)
798{
799 inferior_object *self = (inferior_object *) obj;
800 inferior *inf = self->inferior;
801
802 if (inf == nullptr)
803 return PyUnicode_FromString ("<gdb.Inferior (invalid)>");
804
805 return PyUnicode_FromFormat ("<gdb.Inferior num=%d, pid=%d>",
806 inf->num, inf->pid);
807}
808
809/* Implement clear_env. */
810
811static PyObject *
813{
814 inferior_object *self = (inferior_object *) obj;
815
816 INFPY_REQUIRE_VALID (self);
817
818 self->inferior->environment.clear ();
819 Py_RETURN_NONE;
820}
821
822/* Implement set_env. */
823
824static PyObject *
825infpy_set_env (PyObject *obj, PyObject *args, PyObject *kw)
826{
827 inferior_object *self = (inferior_object *) obj;
828 INFPY_REQUIRE_VALID (self);
829
830 const char *name, *val;
831 static const char *keywords[] = { "name", "value", nullptr };
832
833 if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "ss", keywords,
834 &name, &val))
835 return nullptr;
836
837 self->inferior->environment.set (name, val);
838 Py_RETURN_NONE;
839}
840
841/* Implement unset_env. */
842
843static PyObject *
844infpy_unset_env (PyObject *obj, PyObject *args, PyObject *kw)
845{
846 inferior_object *self = (inferior_object *) obj;
847 INFPY_REQUIRE_VALID (self);
848
849 const char *name;
850 static const char *keywords[] = { "name", nullptr };
851 if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s", keywords, &name))
852 return nullptr;
853
854 self->inferior->environment.unset (name);
855 Py_RETURN_NONE;
856}
857
858/* Getter for "arguments". */
859
860static PyObject *
861infpy_get_args (PyObject *self, void *closure)
862{
864
866
867 const std::string &args = inf->inferior->args ();
868 if (args.empty ())
869 Py_RETURN_NONE;
870
871 return host_string_to_python_string (args.c_str ()).release ();
872}
873
874/* Setter for "arguments". */
875
876static int
877infpy_set_args (PyObject *self, PyObject *value, void *closure)
878{
880
881 if (!inf->inferior)
882 {
883 PyErr_SetString (PyExc_RuntimeError, _("Inferior no longer exists."));
884 return -1;
885 }
886
887 if (value == nullptr)
888 {
889 PyErr_SetString (PyExc_TypeError,
890 _("Cannot delete 'arguments' attribute."));
891 return -1;
892 }
893
895 {
896 gdb::unique_xmalloc_ptr<char> str = python_string_to_host_string (value);
897 if (str == nullptr)
898 return -1;
899 inf->inferior->set_args (std::string (str.get ()));
900 }
901 else if (PySequence_Check (value))
902 {
903 std::vector<gdb::unique_xmalloc_ptr<char>> args;
904 Py_ssize_t len = PySequence_Size (value);
905 if (len == -1)
906 return -1;
907 for (Py_ssize_t i = 0; i < len; ++i)
908 {
909 gdbpy_ref<> item (PySequence_ITEM (value, i));
910 if (item == nullptr)
911 return -1;
912 gdb::unique_xmalloc_ptr<char> str
913 = python_string_to_host_string (item.get ());
914 if (str == nullptr)
915 return -1;
916 args.push_back (std::move (str));
917 }
918 std::vector<char *> argvec;
919 for (const auto &arg : args)
920 argvec.push_back (arg.get ());
921 gdb::array_view<char * const> view (argvec.data (), argvec.size ());
922 inf->inferior->set_args (view);
923 }
924 else
925 {
926 PyErr_SetString (PyExc_TypeError,
927 _("string or sequence required for 'arguments'"));
928 return -1;
929 }
930 return 0;
931}
932
933/* Getter for "main_name". */
934
935static PyObject *
936infpy_get_main_name (PyObject *self, void *closure)
937{
939
941
942 const char *name = nullptr;
943 try
944 {
945 /* This is unfortunate but the implementation of main_name can
946 reach into memory. It's probably not too important to avoid
947 invalidating the frame cache here, but this scoped-restore is
948 still used, just to keep the code similar to other code in
949 this file. */
951 (inf->inferior);
952
953 name = main_name ();
954 }
955 catch (const gdb_exception &except)
956 {
957 /* We can just ignore this. */
958 }
959
960 if (name == nullptr)
961 Py_RETURN_NONE;
962
963 return host_string_to_python_string (name).release ();
964}
965
966static void
968{
969 inferior_object *inf_obj = (inferior_object *) obj;
970
971 /* The inferior itself holds a reference to this Python object, which
972 will keep the reference count of this object above zero until GDB
973 deletes the inferior and py_free_inferior is called.
974
975 Once py_free_inferior has been called then the link between this
976 Python object and the inferior is set to nullptr, and then the
977 reference count on this Python object is decremented.
978
979 The result of all this is that the link between this Python object and
980 the inferior should always have been set to nullptr before this
981 function is called. */
982 gdb_assert (inf_obj->inferior == nullptr);
983
984 Py_TYPE (obj)->tp_free (obj);
985}
986
987/* Implementation of gdb.selected_inferior() -> gdb.Inferior.
988 Returns the current inferior object. */
989
992{
993 return ((PyObject *)
995}
996
999{
1000 if (PyType_Ready (&inferior_object_type) < 0)
1001 return -1;
1002
1003 if (gdb_pymodule_addobject (gdb_module, "Inferior",
1005 return -1;
1006
1007 gdb::observers::new_thread.attach (add_thread_object, "py-inferior");
1008 gdb::observers::thread_exit.attach (delete_thread_object, "py-inferior");
1009 gdb::observers::normal_stop.attach (python_on_normal_stop, "py-inferior");
1010 gdb::observers::target_resumed.attach (python_on_resume, "py-inferior");
1012 "py-inferior");
1014 "py-inferior");
1016 "py-inferior");
1018 "py-inferior");
1020 /* Need to run after auto-load's new_objfile observer, so that
1021 auto-loaded pretty-printers are available. */
1023 (python_new_objfile, "py-inferior",
1026 "py-inferior");
1027 gdb::observers::free_objfile.attach (python_free_objfile, "py-inferior");
1030 "py-inferior");
1031
1032 return 0;
1033}
1036
1037
1040{
1041 { "arguments", infpy_get_args, infpy_set_args,
1042 "Arguments to this program.", nullptr },
1043 { "num", infpy_get_num, NULL, "ID of inferior, as assigned by GDB.", NULL },
1044 { "connection", infpy_get_connection, NULL,
1045 "The gdb.TargetConnection for this inferior.", NULL },
1046 { "connection_num", infpy_get_connection_num, NULL,
1047 "ID of inferior's connection, as assigned by GDB.", NULL },
1048 { "pid", infpy_get_pid, NULL, "PID of inferior, as assigned by the OS.",
1049 NULL },
1050 { "was_attached", infpy_get_was_attached, NULL,
1051 "True if the inferior was created using 'attach'.", NULL },
1052 { "progspace", infpy_get_progspace, NULL, "Program space of this inferior" },
1053 { "main_name", infpy_get_main_name, nullptr,
1054 "Name of 'main' function, if known.", nullptr },
1055 { NULL }
1056};
1058static PyMethodDef inferior_object_methods[] =
1059{
1060 { "is_valid", infpy_is_valid, METH_NOARGS,
1061 "is_valid () -> Boolean.\n\
1062Return true if this inferior is valid, false if not." },
1063 { "threads", infpy_threads, METH_NOARGS,
1064 "Return all the threads of this inferior." },
1065 { "read_memory", (PyCFunction) infpy_read_memory,
1066 METH_VARARGS | METH_KEYWORDS,
1067 "read_memory (address, length) -> buffer\n\
1068Return a buffer object for reading from the inferior's memory." },
1069 { "write_memory", (PyCFunction) infpy_write_memory,
1070 METH_VARARGS | METH_KEYWORDS,
1071 "write_memory (address, buffer [, length])\n\
1072Write the given buffer object to the inferior's memory." },
1073 { "search_memory", (PyCFunction) infpy_search_memory,
1074 METH_VARARGS | METH_KEYWORDS,
1075 "search_memory (address, length, pattern) -> long\n\
1076Return a long with the address of a match, or None." },
1077 /* thread_from_thread_handle is deprecated. */
1078 { "thread_from_thread_handle", (PyCFunction) infpy_thread_from_thread_handle,
1079 METH_VARARGS | METH_KEYWORDS,
1080 "thread_from_thread_handle (handle) -> gdb.InferiorThread.\n\
1081Return thread object corresponding to thread handle.\n\
1082This method is deprecated - use thread_from_handle instead." },
1083 { "thread_from_handle", (PyCFunction) infpy_thread_from_thread_handle,
1084 METH_VARARGS | METH_KEYWORDS,
1085 "thread_from_handle (handle) -> gdb.InferiorThread.\n\
1086Return thread object corresponding to thread handle." },
1087 { "architecture", (PyCFunction) infpy_architecture, METH_NOARGS,
1088 "architecture () -> gdb.Architecture\n\
1089Return architecture of this inferior." },
1090 { "clear_env", (PyCFunction) infpy_clear_env, METH_NOARGS,
1091 "clear_env () -> None\n\
1092Clear environment of this inferior." },
1093 { "set_env", (PyCFunction) infpy_set_env, METH_VARARGS | METH_KEYWORDS,
1094 "set_env (name, value) -> None\n\
1095Set an environment variable of this inferior." },
1096 { "unset_env", (PyCFunction) infpy_unset_env, METH_VARARGS | METH_KEYWORDS,
1097 "unset_env (name) -> None\n\
1098Unset an environment of this inferior." },
1099 { NULL }
1100};
1102PyTypeObject inferior_object_type =
1103{
1104 PyVarObject_HEAD_INIT (NULL, 0)
1105 "gdb.Inferior", /* tp_name */
1106 sizeof (inferior_object), /* tp_basicsize */
1107 0, /* tp_itemsize */
1108 infpy_dealloc, /* tp_dealloc */
1109 0, /* tp_print */
1110 0, /* tp_getattr */
1111 0, /* tp_setattr */
1112 0, /* tp_compare */
1113 infpy_repr, /* tp_repr */
1114 0, /* tp_as_number */
1115 0, /* tp_as_sequence */
1116 0, /* tp_as_mapping */
1117 0, /* tp_hash */
1118 0, /* tp_call */
1119 0, /* tp_str */
1120 0, /* tp_getattro */
1121 0, /* tp_setattro */
1122 0, /* tp_as_buffer */
1123 Py_TPFLAGS_DEFAULT, /* tp_flags */
1124 "GDB inferior object", /* tp_doc */
1125 0, /* tp_traverse */
1126 0, /* tp_clear */
1127 0, /* tp_richcompare */
1128 0, /* tp_weaklistoffset */
1129 0, /* tp_iter */
1130 0, /* tp_iternext */
1131 inferior_object_methods, /* tp_methods */
1132 0, /* tp_members */
1133 inferior_object_getset, /* tp_getset */
1134 0, /* tp_base */
1135 0, /* tp_dict */
1136 0, /* tp_descr_get */
1137 0, /* tp_descr_set */
1138 0, /* tp_dictoffset */
1139 0, /* tp_init */
1140 0 /* tp_alloc */
1141};
int regnum
const char *const name
void * xmalloc(YYSIZE_T)
struct gdbarch * target_gdbarch(void)
gdb::observers::token auto_load_new_objfile_observer_token
Definition auto-load.c:1508
gdb_environ environment
Definition inferior.h:590
void set(unsigned key, void *datum)
Definition registry.h:204
void * get(unsigned key)
Definition registry.h:211
gdb_signal stop_signal() const
Definition gdbthread.h:424
struct inferior * inf
Definition gdbthread.h:301
void read_memory(CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
Definition corefile.c:238
void write_memory_with_notification(CORE_ADDR memaddr, const bfd_byte *myaddr, ssize_t len)
Definition corefile.c:370
void update_thread_list(void)
Definition thread.c:2086
struct thread_info * inferior_thread(void)
Definition thread.c:85
struct thread_info * find_thread_by_handle(gdb::array_view< const gdb_byte > handle, struct inferior *inf)
Definition thread.c:561
#define thread_info
Definition gnu-nat.h:26
ptid_t inferior_ptid
Definition infcmd.c:74
struct inferior * current_inferior(void)
Definition inferior.c:55
all_inferiors_range all_inferiors(process_stratum_target *proc_target=nullptr)
Definition inferior.h:821
observable< ptid_t, CORE_ADDR > inferior_call_pre
observable< struct inferior *, CORE_ADDR, ssize_t, const bfd_byte * > memory_changed
observable< struct inferior * > inferior_added
observable< struct inferior * > inferior_exit
observable< struct objfile * > free_objfile
observable< struct objfile * > new_objfile
observable< struct thread_info * > new_thread
observable< struct inferior * > inferior_removed
observable< ptid_t, CORE_ADDR > inferior_call_post
observable< ptid_t > target_resumed
observable< program_space * > all_objfiles_removed
observable< struct bpstat *, int > normal_stop
observable< frame_info_ptr, int > register_changed
observable< thread_info *, gdb::optional< ULONGEST >, bool > thread_exit
PyObject * gdbarch_to_arch_object(struct gdbarch *gdbarch)
Definition py-arch.c:90
gdbpy_ref target_to_connection_object(process_stratum_target *target)
int emit_continue_event(ptid_t ptid)
gdbpy_ref create_event_object(PyTypeObject *py_type)
Definition py-event.c:31
int evpy_add_attribute(PyObject *event, const char *name, PyObject *attr)
Definition py-event.c:50
int evpy_emit_event(PyObject *event, eventregistry_object *registry)
Definition py-event.c:83
gdbpy_ref create_thread_event_object(PyTypeObject *py_type, PyObject *thread)
int emit_inferior_call_event(inferior_call_kind kind, ptid_t thread, CORE_ADDR addr)
int emit_clear_objfiles_event(program_space *pspace)
int emit_memory_changed_event(CORE_ADDR addr, ssize_t len)
int emit_register_changed_event(frame_info_ptr frame, int regnum)
int emit_new_objfile_event(struct objfile *objfile)
int emit_exited_event(const LONGEST *exit_code, struct inferior *inf)
int emit_free_objfile_event(struct objfile *objfile)
@ INFERIOR_CALL_POST
Definition py-event.h:53
@ INFERIOR_CALL_PRE
Definition py-event.h:51
int emit_thread_exit_event(thread_info *thread)
events_object gdb_py_events
bool evregpy_no_listeners_p(eventregistry_object *registry)
static PyMethodDef inferior_object_methods[]
static void delete_thread_object(thread_info *tp, gdb::optional< ULONGEST >, bool)
static PyObject * infpy_get_was_attached(PyObject *self, void *closure)
static void python_on_inferior_call_post(ptid_t thread, CORE_ADDR address)
static void python_all_objfiles_removed(program_space *pspace)
static void python_on_register_change(frame_info_ptr frame, int regnum)
static void python_on_inferior_call_pre(ptid_t thread, CORE_ADDR address)
static int infpy_set_args(PyObject *self, PyObject *value, void *closure)
static PyObject * infpy_search_memory(PyObject *self, PyObject *args, PyObject *kw)
static PyObject * infpy_get_num(PyObject *self, void *closure)
static void infpy_dealloc(PyObject *obj)
static PyObject * infpy_clear_env(PyObject *obj)
static const registry< inferior >::key< inferior_object, infpy_deleter > infpy_inf_data_key
Definition py-inferior.c:71
static PyObject * infpy_get_progspace(PyObject *self, void *closure)
gdbpy_ref< inferior_object > inferior_to_inferior_object(struct inferior *inferior)
PyObject * gdbpy_selected_inferior(PyObject *self, PyObject *args)
static PyObject * infpy_get_pid(PyObject *self, void *closure)
static PyObject * infpy_get_main_name(PyObject *self, void *closure)
static PyObject * infpy_read_memory(PyObject *self, PyObject *args, PyObject *kw)
static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_inferior(void)
static PyObject * infpy_get_args(PyObject *self, void *closure)
static void python_inferior_deleted(struct inferior *inf)
static gdb_PyGetSetDef inferior_object_getset[]
static void python_on_resume(ptid_t ptid)
static PyObject * infpy_write_memory(PyObject *self, PyObject *args, PyObject *kw)
static void python_new_inferior(struct inferior *inf)
static void python_on_memory_change(struct inferior *inferior, CORE_ADDR addr, ssize_t len, const bfd_byte *data)
gdbpy_ref thread_to_thread_object(thread_info *thr)
static void python_on_normal_stop(struct bpstat *bs, int print_frame)
Definition py-inferior.c:85
static PyObject * infpy_threads(PyObject *self, PyObject *args)
static PyObject * infpy_unset_env(PyObject *obj, PyObject *args, PyObject *kw)
static PyObject * infpy_set_env(PyObject *obj, PyObject *args, PyObject *kw)
PyObject * gdbpy_inferiors(PyObject *unused, PyObject *unused2)
static void add_thread_object(struct thread_info *tp)
#define INFPY_REQUIRE_VALID(Inferior)
Definition py-inferior.c:74
static PyObject * infpy_is_valid(PyObject *self, PyObject *args)
std::unordered_map< thread_info *, gdbpy_ref< thread_object > > thread_map_t
Definition py-inferior.c:36
static PyObject * infpy_repr(PyObject *obj)
static void python_free_objfile(struct objfile *objfile)
static PyObject * infpy_get_connection_num(PyObject *self, void *closure)
static PyObject * infpy_get_connection(PyObject *self, void *closure)
PyTypeObject inferior_object_type
static PyObject * infpy_thread_from_thread_handle(PyObject *self, PyObject *args, PyObject *kw)
static void python_inferior_exit(struct inferior *inf)
static void python_new_objfile(struct objfile *objfile)
static PyObject * infpy_architecture(PyObject *self, PyObject *args)
gdbpy_ref< thread_object > create_thread_object(struct thread_info *tp)
PyObject * gdbpy_buffer_to_membuf(gdb::unique_xmalloc_ptr< gdb_byte > buffer, CORE_ADDR address, ULONGEST length)
Definition py-membuf.c:44
gdbpy_ref pspace_to_pspace_object(struct program_space *pspace)
gdb::ref_ptr< T, gdbpy_ref_policy< T > > gdbpy_ref
Definition py-ref.h:42
int emit_stop_event(struct bpstat *bs, enum gdb_signal stop_signal)
gdbpy_ref host_string_to_python_string(const char *str)
Definition py-utils.c:154
gdbpy_ref gdb_py_object_from_longest(LONGEST l)
Definition py-utils.c:282
int get_addr_from_python(PyObject *obj, CORE_ADDR *addr)
Definition py-utils.c:239
int gdb_pymodule_addobject(PyObject *module, const char *name, PyObject *object)
Definition py-utils.c:334
gdb::unique_xmalloc_ptr< char > python_string_to_host_string(PyObject *obj)
Definition py-utils.c:142
int gdbpy_is_string(PyObject *obj)
Definition py-utils.c:164
gdbpy_ref gdb_py_object_from_ulongest(ULONGEST l)
Definition py-utils.c:293
int gdbpy_is_value_object(PyObject *obj)
Definition py-value.c:2122
struct value * value_object_to_value(PyObject *self)
Definition py-value.c:1877
void gdbpy_print_stack(void)
std::unique_ptr< Py_buffer, Py_buffer_deleter > Py_buffer_up
PyObject * gdb_module
int gdb_python_initialized
#define CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF(ARG)
#define CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
#define GDBPY_INITIALIZE_FILE(INIT,...)
#define GDB_PY_HANDLE_EXCEPTION(Exception)
static int gdb_PyArg_ParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format, const char **keywords,...)
static void print_frame(const frame_print_options &opts, frame_info_ptr frame, int print_level, enum print_what print_what, int print_args, struct symtab_and_line sal)
Definition gnu-nat.c:153
pid_t pid
Definition gnu-nat.c:165
PyObject_HEAD struct inferior * inferior
Definition py-inferior.c:43
thread_map_t * threads
Definition py-inferior.c:47
void operator()(inferior_object *obj)
Definition py-inferior.c:56
struct gdbarch * arch() const
Definition objfiles.h:507
ULONGEST length() const
Definition gdbtypes.h:983
Definition value.h:130
gdb::array_view< const gdb_byte > contents_all()
Definition value.c:1119
struct type * type() const
Definition value.h:180
const char * main_name()
Definition symtab.c:6322
int target_search_memory(CORE_ADDR start_addr, ULONGEST search_space_len, const gdb_byte *pattern, ULONGEST pattern_len, CORE_ADDR *found_addrp)
Definition target.c:2807
int PyObject
Definition varobj.c:41