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