]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/python/py-inferior.c
gdb, gdbserver, gdbsupport: remove includes of early headers
[thirdparty/binutils-gdb.git] / gdb / python / py-inferior.c
CommitLineData
595939de
PM
1/* Python interface to inferiors.
2
1d506c26 3 Copyright (C) 2009-2024 Free Software Foundation, Inc.
595939de
PM
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
2c473def 20#include "auto-load.h"
595939de
PM
21#include "gdbcore.h"
22#include "gdbthread.h"
23#include "inferior.h"
20c168b5 24#include "objfiles.h"
76727919 25#include "observable.h"
595939de
PM
26#include "python-internal.h"
27#include "arch-utils.h"
28#include "language.h"
268a13a5 29#include "gdbsupport/gdb_signals.h"
505500db
SW
30#include "py-event.h"
31#include "py-stopevent.h"
75ec0982 32#include "progspace-and-thread.h"
40b355f2 33#include <unordered_map>
595939de 34
40b355f2
LS
35using thread_map_t
36 = std::unordered_map<thread_info *, gdbpy_ref<thread_object>>;
595939de 37
00431a78 38struct inferior_object
595939de
PM
39{
40 PyObject_HEAD
41
42 /* The inferior we represent. */
43 struct inferior *inferior;
44
40b355f2 45 /* thread_object instances under this inferior. This owns a
595939de 46 reference to each object it contains. */
40b355f2 47 thread_map_t *threads;
13cd9bce
AB
48
49 /* Dictionary holding user-added attributes.
50 This is the __dict__ attribute of the object. */
51 PyObject *dict;
00431a78 52};
595939de 53
e36122e9 54extern PyTypeObject inferior_object_type
62eec1a5 55 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("inferior_object");
595939de 56
08b8a139
TT
57/* Deleter to clean up when an inferior is removed. */
58struct infpy_deleter
59{
60 void operator() (inferior_object *obj)
61 {
08b8a139
TT
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
40b355f2 70 delete inf_obj->threads;
08b8a139
TT
71 }
72};
73
74static const registry<inferior>::key<inferior_object, infpy_deleter>
75 infpy_inf_data_key;
595939de 76
595939de
PM
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
505500db 88static void
313f3b21 89python_on_normal_stop (struct bpstat *bs, int print_frame)
505500db 90{
2ea28649 91 enum gdb_signal stop_signal;
505500db 92
0646da15
TT
93 if (!gdb_python_initialized)
94 return;
95
151bb4a5
PA
96 if (inferior_ptid == null_ptid)
97 return;
505500db 98
1edb66d8 99 stop_signal = inferior_thread ()->stop_signal ();
505500db 100
1da5d0e6 101 gdbpy_enter enter_py;
505500db
SW
102
103 if (emit_stop_event (bs, stop_signal) < 0)
104 gdbpy_print_stack ();
505500db
SW
105}
106
107static void
108python_on_resume (ptid_t ptid)
109{
0646da15
TT
110 if (!gdb_python_initialized)
111 return;
112
99d9c3b9 113 gdbpy_enter enter_py (current_inferior ()->arch ());
505500db
SW
114
115 if (emit_continue_event (ptid) < 0)
116 gdbpy_print_stack ();
505500db
SW
117}
118
162078c8
NB
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{
99d9c3b9 125 gdbpy_enter enter_py (current_inferior ()->arch ());
162078c8
NB
126
127 if (emit_inferior_call_event (INFERIOR_CALL_PRE, thread, address) < 0)
128 gdbpy_print_stack ();
162078c8
NB
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{
99d9c3b9 137 gdbpy_enter enter_py (current_inferior ()->arch ());
162078c8
NB
138
139 if (emit_inferior_call_event (INFERIOR_CALL_POST, thread, address) < 0)
140 gdbpy_print_stack ();
162078c8
NB
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{
99d9c3b9 150 gdbpy_enter enter_py (current_inferior ()->arch ());
162078c8
NB
151
152 if (emit_memory_changed_event (addr, len) < 0)
153 gdbpy_print_stack ();
162078c8
NB
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
8480a37e 161python_on_register_change (const frame_info_ptr &frame, int regnum)
162078c8 162{
99d9c3b9 163 gdbpy_enter enter_py (current_inferior ()->arch ());
162078c8
NB
164
165 if (emit_register_changed_event (frame, regnum) < 0)
166 gdbpy_print_stack ();
162078c8
NB
167}
168
505500db
SW
169static void
170python_inferior_exit (struct inferior *inf)
171{
8cf64490 172 const LONGEST *exit_code = NULL;
505500db 173
0646da15
TT
174 if (!gdb_python_initialized)
175 return;
176
99d9c3b9 177 gdbpy_enter enter_py (current_inferior ()->arch ());
505500db 178
8cf64490
TT
179 if (inf->has_exit_code)
180 exit_code = &inf->exit_code;
505500db 181
cb6be26b 182 if (emit_exited_event (exit_code, inf) < 0)
505500db 183 gdbpy_print_stack ();
505500db
SW
184}
185
20c168b5 186/* Callback used to notify Python listeners about new objfiles loaded in the
4ffbba72
DE
187 inferior. OBJFILE may be NULL which means that the objfile list has been
188 cleared (emptied). */
20c168b5
KP
189
190static void
191python_new_objfile (struct objfile *objfile)
192{
0646da15
TT
193 if (!gdb_python_initialized)
194 return;
195
74daa597 196 gdbpy_enter enter_py (objfile->arch ());
20c168b5 197
74daa597
SM
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
99d9c3b9 208 gdbpy_enter enter_py (current_inferior ()->arch ());
74daa597
SM
209
210 if (emit_clear_objfiles_event (pspace) < 0)
211 gdbpy_print_stack ();
20c168b5
KP
212}
213
0b4fe76f
TT
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
754eadd1 228/* Return a reference to the Python object of type Inferior
595939de 229 representing INFERIOR. If the object has already been created,
754eadd1
PM
230 return it and increment the reference count, otherwise, create it.
231 Return NULL on failure. */
00431a78 232
61fd3e73 233gdbpy_ref<inferior_object>
595939de
PM
234inferior_to_inferior_object (struct inferior *inferior)
235{
236 inferior_object *inf_obj;
237
08b8a139 238 inf_obj = infpy_inf_data_key.get (inferior);
595939de
PM
239 if (!inf_obj)
240 {
595939de
PM
241 inf_obj = PyObject_New (inferior_object, &inferior_object_type);
242 if (!inf_obj)
61fd3e73 243 return NULL;
595939de
PM
244
245 inf_obj->inferior = inferior;
40b355f2 246 inf_obj->threads = new thread_map_t ();
13cd9bce
AB
247 inf_obj->dict = PyDict_New ();
248 if (inf_obj->dict == nullptr)
249 return nullptr;
595939de 250
72bc1d24
SM
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. */
08b8a139 253 infpy_inf_data_key.set (inferior, inf_obj);
595939de 254 }
72bc1d24
SM
255
256 /* We are returning a new reference. */
61fd3e73
TT
257 gdb_assert (inf_obj != nullptr);
258 return gdbpy_ref<inferior_object>::new_reference (inf_obj);
595939de
PM
259}
260
7c96f8c1
TT
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
1da5d0e6 269 gdbpy_enter enter_py;
7c96f8c1
TT
270
271 if (evregpy_no_listeners_p (gdb_py_events.new_inferior))
272 return;
273
61fd3e73 274 gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (inf);
7c96f8c1
TT
275 if (inf_obj == NULL)
276 {
277 gdbpy_print_stack ();
278 return;
279 }
280
d98fc15b 281 gdbpy_ref<> event = create_event_object (&new_inferior_event_object_type);
7c96f8c1 282 if (event == NULL
00431a78
PA
283 || evpy_add_attribute (event.get (), "inferior",
284 (PyObject *) inf_obj.get ()) < 0
7c96f8c1
TT
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
1da5d0e6 297 gdbpy_enter enter_py;
7c96f8c1
TT
298
299 if (evregpy_no_listeners_p (gdb_py_events.inferior_deleted))
300 return;
301
61fd3e73 302 gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (inf);
7c96f8c1
TT
303 if (inf_obj == NULL)
304 {
305 gdbpy_print_stack ();
306 return;
307 }
308
d98fc15b 309 gdbpy_ref<> event = create_event_object (&inferior_deleted_event_object_type);
7c96f8c1 310 if (event == NULL
00431a78
PA
311 || evpy_add_attribute (event.get (), "inferior",
312 (PyObject *) inf_obj.get ()) < 0
7c96f8c1
TT
313 || evpy_emit_event (event.get (), gdb_py_events.inferior_deleted) < 0)
314 gdbpy_print_stack ();
315}
316
db1337cc 317gdbpy_ref<>
00431a78 318thread_to_thread_object (thread_info *thr)
595939de 319{
61fd3e73 320 gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (thr->inf);
9205649a 321 if (inf_obj == NULL)
754eadd1
PM
322 return NULL;
323
40b355f2
LS
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 ()));
595939de 328
4a137fec
TT
329 PyErr_SetString (PyExc_SystemError,
330 _("could not find gdb thread object"));
595939de
PM
331 return NULL;
332}
333
334static void
335add_thread_object (struct thread_info *tp)
336{
595939de 337 inferior_object *inf_obj;
595939de 338
0646da15
TT
339 if (!gdb_python_initialized)
340 return;
341
1da5d0e6 342 gdbpy_enter enter_py;
595939de 343
05b08ac1
TT
344 gdbpy_ref<thread_object> thread_obj = create_thread_object (tp);
345 if (thread_obj == NULL)
595939de
PM
346 {
347 gdbpy_print_stack ();
595939de
PM
348 return;
349 }
350
351 inf_obj = (inferior_object *) thread_obj->inf_obj;
352
40b355f2
LS
353 auto ins_result = inf_obj->threads->emplace
354 (thread_map_t::value_type (tp, std::move (thread_obj)));
595939de 355
40b355f2
LS
356 if (!ins_result.second)
357 return;
7c96f8c1
TT
358
359 if (evregpy_no_listeners_p (gdb_py_events.new_thread))
360 return;
361
40b355f2
LS
362 gdbpy_ref<> event = create_thread_event_object
363 (&new_thread_event_object_type,
364 (PyObject *) ins_result.first->second.get ());
365
7c96f8c1
TT
366 if (event == NULL
367 || evpy_emit_event (event.get (), gdb_py_events.new_thread) < 0)
368 gdbpy_print_stack ();
595939de
PM
369}
370
371static void
9d7d58e7 372delete_thread_object (thread_info *tp,
6b09f134 373 std::optional<ULONGEST> /* exit_code */,
9d7d58e7 374 bool /* silent */)
595939de 375{
0646da15
TT
376 if (!gdb_python_initialized)
377 return;
378
1da5d0e6 379 gdbpy_enter enter_py;
595939de 380
61fd3e73 381 gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (tp->inf);
88b6faea 382 if (inf_obj == NULL)
07bc7329 383 return;
595939de 384
28ab5960
SF
385 if (emit_thread_exit_event (tp) < 0)
386 gdbpy_print_stack ();
387
40b355f2
LS
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 }
595939de
PM
398}
399
400static PyObject *
401infpy_threads (PyObject *self, PyObject *args)
402{
40b355f2 403 int i = 0;
595939de
PM
404 inferior_object *inf_obj = (inferior_object *) self;
405 PyObject *tuple;
406
407 INFPY_REQUIRE_VALID (inf_obj);
408
a70b8144 409 try
492d29ea
PA
410 {
411 update_thread_list ();
412 }
230d2906 413 catch (const gdb_exception &except)
492d29ea
PA
414 {
415 GDB_PY_HANDLE_EXCEPTION (except);
416 }
f66713d2 417
40b355f2 418 tuple = PyTuple_New (inf_obj->threads->size ());
595939de
PM
419 if (!tuple)
420 return NULL;
421
40b355f2 422 for (const thread_map_t::value_type &entry : *inf_obj->threads)
595939de 423 {
40b355f2 424 PyObject *thr = (PyObject *) entry.second.get ();
05b08ac1
TT
425 Py_INCREF (thr);
426 PyTuple_SET_ITEM (tuple, i, thr);
40b355f2 427 i = i + 1;
595939de
PM
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
062534d4 440 return gdb_py_object_from_longest (inf->inferior->num).release ();
595939de
PM
441}
442
0e3b7c25
AB
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
55789354
TBA
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
8b9c48b2 471 return gdb_py_object_from_longest (target->connection_number).release ();
55789354
TBA
472}
473
595939de
PM
474static PyObject *
475infpy_get_pid (PyObject *self, void *closure)
476{
477 inferior_object *inf = (inferior_object *) self;
478
479 INFPY_REQUIRE_VALID (inf);
480
062534d4 481 return gdb_py_object_from_longest (inf->inferior->pid).release ();
595939de
PM
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
a40bf0c2
SM
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
3c7aa307 507 return pspace_to_pspace_object (pspace).release ();
a40bf0c2
SM
508}
509
595939de
PM
510/* Implementation of gdb.inferiors () -> (gdb.Inferior, ...).
511 Returns a tuple of all inferiors. */
512PyObject *
513gdbpy_inferiors (PyObject *unused, PyObject *unused2)
514{
7780f186 515 gdbpy_ref<> list (PyList_New (0));
f59fe7f8 516 if (list == NULL)
595939de
PM
517 return NULL;
518
d9bc85b6
SM
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 }
27ca1a5b 529
f59fe7f8 530 return PyList_AsTuple (list.get ());
595939de
PM
531}
532
533/* Membuf and memory manipulation. */
534
2678e2af 535/* Implementation of Inferior.read_memory (address, length).
595939de 536 Returns a Python buffer object with LENGTH bytes of the inferior's
8dc78533
JK
537 memory at ADDRESS. Both arguments are integers. Returns NULL on error,
538 with a python exception set. */
595939de
PM
539static PyObject *
540infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw)
541{
75ec0982 542 inferior_object *inf = (inferior_object *) self;
595939de 543 CORE_ADDR addr, length;
075c55e0 544 gdb::unique_xmalloc_ptr<gdb_byte> buffer;
625f7b1c 545 PyObject *addr_obj, *length_obj;
2adadf51 546 static const char *keywords[] = { "address", "length", NULL };
595939de 547
75ec0982
TT
548 INFPY_REQUIRE_VALID (inf);
549
2adadf51
PA
550 if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "OO", keywords,
551 &addr_obj, &length_obj))
595939de
PM
552 return NULL;
553
b86af38a
TT
554 if (get_addr_from_python (addr_obj, &addr) < 0
555 || get_addr_from_python (length_obj, &length) < 0)
556 return NULL;
557
a70b8144 558 try
595939de 559 {
75ec0982
TT
560 /* Use this scoped-restore because we want to be able to read
561 memory from an unwinder. */
562 scoped_restore_current_inferior_for_memory restore_inferior
6d30ada8 563 (inf->inferior);
75ec0982 564
075c55e0 565 buffer.reset ((gdb_byte *) xmalloc (length));
595939de 566
075c55e0 567 read_memory (addr, buffer.get (), length);
595939de 568 }
230d2906 569 catch (const gdb_exception &except)
595939de 570 {
595939de
PM
571 GDB_PY_HANDLE_EXCEPTION (except);
572 }
573
595939de 574
625f7b1c 575 return gdbpy_buffer_to_membuf (std::move (buffer), addr, length);
595939de
PM
576}
577
2678e2af 578/* Implementation of Inferior.write_memory (address, buffer [, length]).
595939de
PM
579 Writes the contents of BUFFER (a Python object supporting the read
580 buffer protocol) at ADDRESS in the inferior's memory. Write LENGTH
581 bytes from BUFFER, or its entire contents if the argument is not
8dc78533
JK
582 provided. The function returns nothing. Returns NULL on error, with
583 a python exception set. */
595939de
PM
584static PyObject *
585infpy_write_memory (PyObject *self, PyObject *args, PyObject *kw)
586{
75ec0982 587 inferior_object *inf = (inferior_object *) self;
ddd49eee 588 Py_ssize_t buf_len;
7c543f7b 589 const gdb_byte *buffer;
595939de
PM
590 CORE_ADDR addr, length;
591 PyObject *addr_obj, *length_obj = NULL;
2adadf51 592 static const char *keywords[] = { "address", "buffer", "length", NULL };
9a27f2c6 593 Py_buffer pybuf;
595939de 594
75ec0982
TT
595 INFPY_REQUIRE_VALID (inf);
596
2adadf51
PA
597 if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "Os*|O", keywords,
598 &addr_obj, &pybuf, &length_obj))
9a27f2c6 599 return NULL;
595939de 600
6ca62222 601 Py_buffer_up buffer_up (&pybuf);
7c543f7b 602 buffer = (const gdb_byte *) pybuf.buf;
9a27f2c6 603 buf_len = pybuf.len;
595939de 604
b86af38a 605 if (get_addr_from_python (addr_obj, &addr) < 0)
6ca62222 606 return nullptr;
b86af38a
TT
607
608 if (!length_obj)
609 length = buf_len;
610 else if (get_addr_from_python (length_obj, &length) < 0)
6ca62222 611 return nullptr;
b86af38a 612
a70b8144 613 try
595939de 614 {
75ec0982
TT
615 /* It's probably not too important to avoid invalidating the
616 frame cache when writing memory, but this scoped-restore is
617 still used here, just to keep the code similar to other code
618 in this file. */
619 scoped_restore_current_inferior_for_memory restore_inferior
6d30ada8 620 (inf->inferior);
75ec0982 621
7c543f7b 622 write_memory_with_notification (addr, buffer, length);
595939de 623 }
94aeb44b 624 catch (gdb_exception &ex)
492d29ea 625 {
b0e7d28e 626 GDB_PY_HANDLE_EXCEPTION (ex);
492d29ea 627 }
492d29ea 628
595939de
PM
629 Py_RETURN_NONE;
630}
631
595939de 632/* Implementation of
75ec0982 633 Inferior.search_memory (address, length, pattern). ADDRESS is the
595939de
PM
634 address to start the search. LENGTH specifies the scope of the
635 search from ADDRESS. PATTERN is the pattern to search for (and
636 must be a Python object supporting the buffer protocol).
637 Returns a Python Long object holding the address where the pattern
8dc78533
JK
638 was located, or if the pattern was not found, returns None. Returns NULL
639 on error, with a python exception set. */
595939de
PM
640static PyObject *
641infpy_search_memory (PyObject *self, PyObject *args, PyObject *kw)
642{
75ec0982 643 inferior_object *inf = (inferior_object *) self;
595939de 644 CORE_ADDR start_addr, length;
2adadf51 645 static const char *keywords[] = { "address", "length", "pattern", NULL };
9a27f2c6 646 PyObject *start_addr_obj, *length_obj;
595939de 647 Py_ssize_t pattern_size;
7c543f7b 648 const gdb_byte *buffer;
595939de
PM
649 CORE_ADDR found_addr;
650 int found = 0;
9a27f2c6 651 Py_buffer pybuf;
595939de 652
75ec0982
TT
653 INFPY_REQUIRE_VALID (inf);
654
2adadf51
PA
655 if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "OOs*", keywords,
656 &start_addr_obj, &length_obj,
657 &pybuf))
9a27f2c6
PK
658 return NULL;
659
6ca62222 660 Py_buffer_up buffer_up (&pybuf);
7c543f7b 661 buffer = (const gdb_byte *) pybuf.buf;
9a27f2c6 662 pattern_size = pybuf.len;
595939de 663
b86af38a 664 if (get_addr_from_python (start_addr_obj, &start_addr) < 0)
6ca62222 665 return nullptr;
256458bc 666
b86af38a 667 if (get_addr_from_python (length_obj, &length) < 0)
6ca62222 668 return nullptr;
9a27f2c6 669
b86af38a
TT
670 if (!length)
671 {
672 PyErr_SetString (PyExc_ValueError,
673 _("Search range is empty."));
6ca62222 674 return nullptr;
b86af38a
TT
675 }
676 /* Watch for overflows. */
677 else if (length > CORE_ADDR_MAX
678 || (start_addr + length - 1) < start_addr)
679 {
680 PyErr_SetString (PyExc_ValueError,
681 _("The search range is too large."));
6ca62222 682 return nullptr;
595939de 683 }
595939de 684
a70b8144 685 try
595939de 686 {
75ec0982
TT
687 /* It's probably not too important to avoid invalidating the
688 frame cache when searching memory, but this scoped-restore is
689 still used here, just to keep the code similar to other code
690 in this file. */
691 scoped_restore_current_inferior_for_memory restore_inferior
6d30ada8 692 (inf->inferior);
75ec0982 693
595939de
PM
694 found = target_search_memory (start_addr, length,
695 buffer, pattern_size,
696 &found_addr);
697 }
94aeb44b 698 catch (gdb_exception &ex)
492d29ea 699 {
b0e7d28e 700 GDB_PY_HANDLE_EXCEPTION (ex);
492d29ea 701 }
492d29ea 702
595939de 703 if (found)
b017825f 704 return gdb_py_object_from_ulongest (found_addr).release ();
595939de
PM
705 else
706 Py_RETURN_NONE;
707}
708
29703da4
PM
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{
715 inferior_object *inf = (inferior_object *) self;
716
717 if (! inf->inferior)
718 Py_RETURN_FALSE;
719
720 Py_RETURN_TRUE;
721}
722
2b0c8b01 723/* Implementation of gdb.Inferior.thread_from_handle (self, handle)
dda83cd7 724 -> gdb.InferiorThread. */
fbbe5337 725
7d221512 726static PyObject *
fbbe5337
KB
727infpy_thread_from_thread_handle (PyObject *self, PyObject *args, PyObject *kw)
728{
db1337cc 729 PyObject *handle_obj;
fbbe5337 730 inferior_object *inf_obj = (inferior_object *) self;
2b0c8b01 731 static const char *keywords[] = { "handle", NULL };
fbbe5337
KB
732
733 INFPY_REQUIRE_VALID (inf_obj);
734
735 if (! gdb_PyArg_ParseTupleAndKeywords (args, kw, "O", keywords, &handle_obj))
736 return NULL;
737
50a82723
KB
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);
efaf1ae0 753 bytes = val->contents_all ().data ();
d0c97917 754 bytes_len = val->type ()->length ();
50a82723
KB
755 }
756 else
fbbe5337
KB
757 {
758 PyErr_SetString (PyExc_TypeError,
2b0c8b01 759 _("Argument 'handle' must be a thread handle object."));
fbbe5337
KB
760
761 return NULL;
762 }
db1337cc 763
a70b8144 764 try
db1337cc
TT
765 {
766 struct thread_info *thread_info;
db1337cc 767
50a82723 768 thread_info = find_thread_by_handle
dda83cd7 769 (gdb::array_view<const gdb_byte> (bytes, bytes_len),
50a82723 770 inf_obj->inferior);
db1337cc 771 if (thread_info != NULL)
4a137fec 772 return thread_to_thread_object (thread_info).release ();
db1337cc 773 }
230d2906 774 catch (const gdb_exception &except)
fbbe5337 775 {
db1337cc 776 GDB_PY_HANDLE_EXCEPTION (except);
fbbe5337
KB
777 }
778
4a137fec 779 Py_RETURN_NONE;
fbbe5337
KB
780}
781
add5ded5
TT
782/* Implementation of gdb.Inferior.architecture. */
783
784static PyObject *
785infpy_architecture (PyObject *self, PyObject *args)
786{
787 inferior_object *inf = (inferior_object *) self;
788
789 INFPY_REQUIRE_VALID (inf);
790
27b1f19f 791 return gdbarch_to_arch_object (inf->inferior->arch ());
add5ded5
TT
792}
793
1256af7d
SM
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)
aef117b7 803 return gdb_py_invalid_object_repr (obj);
1256af7d 804
5aee4587
SM
805 return PyUnicode_FromFormat ("<gdb.Inferior num=%d, pid=%d>",
806 inf->num, inf->pid);
1256af7d
SM
807}
808
31531132
TT
809/* Implement clear_env. */
810
811static PyObject *
812infpy_clear_env (PyObject *obj)
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{
863 inferior_object *inf = (inferior_object *) self;
864
865 INFPY_REQUIRE_VALID (inf);
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{
879 inferior_object *inf = (inferior_object *) self;
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
894 if (gdbpy_is_string (value))
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{
938 inferior_object *inf = (inferior_object *) self;
939
940 INFPY_REQUIRE_VALID (inf);
941
942 const char *name = nullptr;
943 try
944 {
945 /* This is unfortunate but the implementation of main_name can
75ec0982
TT
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. */
950 scoped_restore_current_inferior_for_memory restore_inferior
6d30ada8 951 (inf->inferior);
31531132
TT
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}
fbbe5337 965
754eadd1
PM
966static void
967infpy_dealloc (PyObject *obj)
968{
969 inferior_object *inf_obj = (inferior_object *) obj;
754eadd1 970
cb6e6bb8
AB
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);
754eadd1 983
13cd9bce
AB
984 Py_XDECREF (inf_obj->dict);
985
2e953aca 986 Py_TYPE (obj)->tp_free (obj);
754eadd1 987}
595939de 988
2aa48337
KP
989/* Implementation of gdb.selected_inferior() -> gdb.Inferior.
990 Returns the current inferior object. */
991
992PyObject *
993gdbpy_selected_inferior (PyObject *self, PyObject *args)
994{
61fd3e73
TT
995 return ((PyObject *)
996 inferior_to_inferior_object (current_inferior ()).release ());
2aa48337
KP
997}
998
3965bff5 999static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
595939de
PM
1000gdbpy_initialize_inferior (void)
1001{
1002 if (PyType_Ready (&inferior_object_type) < 0)
999633ed 1003 return -1;
595939de 1004
aa36459a
TT
1005 if (gdb_pymodule_addobject (gdb_module, "Inferior",
1006 (PyObject *) &inferior_object_type) < 0)
999633ed 1007 return -1;
595939de 1008
c90e7d63
SM
1009 gdb::observers::new_thread.attach (add_thread_object, "py-inferior");
1010 gdb::observers::thread_exit.attach (delete_thread_object, "py-inferior");
1011 gdb::observers::normal_stop.attach (python_on_normal_stop, "py-inferior");
1012 gdb::observers::target_resumed.attach (python_on_resume, "py-inferior");
1013 gdb::observers::inferior_call_pre.attach (python_on_inferior_call_pre,
1014 "py-inferior");
1015 gdb::observers::inferior_call_post.attach (python_on_inferior_call_post,
1016 "py-inferior");
1017 gdb::observers::memory_changed.attach (python_on_memory_change,
1018 "py-inferior");
1019 gdb::observers::register_changed.attach (python_on_register_change,
1020 "py-inferior");
1021 gdb::observers::inferior_exit.attach (python_inferior_exit, "py-inferior");
2c473def
MW
1022 /* Need to run after auto-load's new_objfile observer, so that
1023 auto-loaded pretty-printers are available. */
1024 gdb::observers::new_objfile.attach
1025 (python_new_objfile, "py-inferior",
1026 { &auto_load_new_objfile_observer_token });
74daa597
SM
1027 gdb::observers::all_objfiles_removed.attach (python_all_objfiles_removed,
1028 "py-inferior");
0b4fe76f 1029 gdb::observers::free_objfile.attach (python_free_objfile, "py-inferior");
c90e7d63
SM
1030 gdb::observers::inferior_added.attach (python_new_inferior, "py-inferior");
1031 gdb::observers::inferior_removed.attach (python_inferior_deleted,
1032 "py-inferior");
595939de 1033
625f7b1c 1034 return 0;
595939de
PM
1035}
1036
3965bff5
AB
1037GDBPY_INITIALIZE_FILE (gdbpy_initialize_inferior);
1038
1039\f
1040
0d1f4ceb 1041static gdb_PyGetSetDef inferior_object_getset[] =
595939de 1042{
13cd9bce
AB
1043 { "__dict__", gdb_py_generic_dict, nullptr,
1044 "The __dict__ for this inferior.", &inferior_object_type },
31531132
TT
1045 { "arguments", infpy_get_args, infpy_set_args,
1046 "Arguments to this program.", nullptr },
595939de 1047 { "num", infpy_get_num, NULL, "ID of inferior, as assigned by GDB.", NULL },
0e3b7c25
AB
1048 { "connection", infpy_get_connection, NULL,
1049 "The gdb.TargetConnection for this inferior.", NULL },
55789354
TBA
1050 { "connection_num", infpy_get_connection_num, NULL,
1051 "ID of inferior's connection, as assigned by GDB.", NULL },
595939de
PM
1052 { "pid", infpy_get_pid, NULL, "PID of inferior, as assigned by the OS.",
1053 NULL },
1054 { "was_attached", infpy_get_was_attached, NULL,
1055 "True if the inferior was created using 'attach'.", NULL },
a40bf0c2 1056 { "progspace", infpy_get_progspace, NULL, "Program space of this inferior" },
31531132
TT
1057 { "main_name", infpy_get_main_name, nullptr,
1058 "Name of 'main' function, if known.", nullptr },
595939de
PM
1059 { NULL }
1060};
1061
1062static PyMethodDef inferior_object_methods[] =
1063{
29703da4
PM
1064 { "is_valid", infpy_is_valid, METH_NOARGS,
1065 "is_valid () -> Boolean.\n\
1066Return true if this inferior is valid, false if not." },
595939de
PM
1067 { "threads", infpy_threads, METH_NOARGS,
1068 "Return all the threads of this inferior." },
1069 { "read_memory", (PyCFunction) infpy_read_memory,
1070 METH_VARARGS | METH_KEYWORDS,
1071 "read_memory (address, length) -> buffer\n\
1072Return a buffer object for reading from the inferior's memory." },
1073 { "write_memory", (PyCFunction) infpy_write_memory,
1074 METH_VARARGS | METH_KEYWORDS,
1075 "write_memory (address, buffer [, length])\n\
1076Write the given buffer object to the inferior's memory." },
1077 { "search_memory", (PyCFunction) infpy_search_memory,
1078 METH_VARARGS | METH_KEYWORDS,
1079 "search_memory (address, length, pattern) -> long\n\
1080Return a long with the address of a match, or None." },
2b0c8b01 1081 /* thread_from_thread_handle is deprecated. */
fbbe5337
KB
1082 { "thread_from_thread_handle", (PyCFunction) infpy_thread_from_thread_handle,
1083 METH_VARARGS | METH_KEYWORDS,
1084 "thread_from_thread_handle (handle) -> gdb.InferiorThread.\n\
2b0c8b01
KB
1085Return thread object corresponding to thread handle.\n\
1086This method is deprecated - use thread_from_handle instead." },
1087 { "thread_from_handle", (PyCFunction) infpy_thread_from_thread_handle,
1088 METH_VARARGS | METH_KEYWORDS,
1089 "thread_from_handle (handle) -> gdb.InferiorThread.\n\
fbbe5337 1090Return thread object corresponding to thread handle." },
add5ded5
TT
1091 { "architecture", (PyCFunction) infpy_architecture, METH_NOARGS,
1092 "architecture () -> gdb.Architecture\n\
1093Return architecture of this inferior." },
31531132
TT
1094 { "clear_env", (PyCFunction) infpy_clear_env, METH_NOARGS,
1095 "clear_env () -> None\n\
1096Clear environment of this inferior." },
1097 { "set_env", (PyCFunction) infpy_set_env, METH_VARARGS | METH_KEYWORDS,
1098 "set_env (name, value) -> None\n\
1099Set an environment variable of this inferior." },
1100 { "unset_env", (PyCFunction) infpy_unset_env, METH_VARARGS | METH_KEYWORDS,
1101 "unset_env (name) -> None\n\
1102Unset an environment of this inferior." },
595939de
PM
1103 { NULL }
1104};
1105
e36122e9 1106PyTypeObject inferior_object_type =
595939de 1107{
9a27f2c6 1108 PyVarObject_HEAD_INIT (NULL, 0)
595939de
PM
1109 "gdb.Inferior", /* tp_name */
1110 sizeof (inferior_object), /* tp_basicsize */
1111 0, /* tp_itemsize */
754eadd1 1112 infpy_dealloc, /* tp_dealloc */
595939de
PM
1113 0, /* tp_print */
1114 0, /* tp_getattr */
1115 0, /* tp_setattr */
1116 0, /* tp_compare */
1256af7d 1117 infpy_repr, /* tp_repr */
595939de
PM
1118 0, /* tp_as_number */
1119 0, /* tp_as_sequence */
1120 0, /* tp_as_mapping */
1121 0, /* tp_hash */
1122 0, /* tp_call */
1123 0, /* tp_str */
1124 0, /* tp_getattro */
1125 0, /* tp_setattro */
1126 0, /* tp_as_buffer */
0b233e34 1127 Py_TPFLAGS_DEFAULT, /* tp_flags */
595939de
PM
1128 "GDB inferior object", /* tp_doc */
1129 0, /* tp_traverse */
1130 0, /* tp_clear */
1131 0, /* tp_richcompare */
1132 0, /* tp_weaklistoffset */
1133 0, /* tp_iter */
1134 0, /* tp_iternext */
1135 inferior_object_methods, /* tp_methods */
1136 0, /* tp_members */
1137 inferior_object_getset, /* tp_getset */
1138 0, /* tp_base */
1139 0, /* tp_dict */
1140 0, /* tp_descr_get */
1141 0, /* tp_descr_set */
13cd9bce 1142 offsetof (inferior_object, dict), /* tp_dictoffset */
595939de
PM
1143 0, /* tp_init */
1144 0 /* tp_alloc */
1145};