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