]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/python/py-inferior.c
Turn value_type into method
[thirdparty/binutils-gdb.git] / gdb / python / py-inferior.c
CommitLineData
595939de
PM
1/* Python interface to inferiors.
2
213516ef 3 Copyright (C) 2009-2023 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
20#include "defs.h"
2c473def 21#include "auto-load.h"
595939de
PM
22#include "gdbcore.h"
23#include "gdbthread.h"
24#include "inferior.h"
20c168b5 25#include "objfiles.h"
76727919 26#include "observable.h"
595939de
PM
27#include "python-internal.h"
28#include "arch-utils.h"
29#include "language.h"
268a13a5 30#include "gdbsupport/gdb_signals.h"
505500db
SW
31#include "py-event.h"
32#include "py-stopevent.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;
00431a78 48};
595939de 49
e36122e9 50extern PyTypeObject inferior_object_type
62eec1a5 51 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("inferior_object");
595939de 52
08b8a139
TT
53/* Deleter to clean up when an inferior is removed. */
54struct infpy_deleter
55{
56 void operator() (inferior_object *obj)
57 {
08b8a139
TT
58 if (!gdb_python_initialized)
59 return;
60
61 gdbpy_enter enter_py;
62 gdbpy_ref<inferior_object> inf_obj (obj);
63
64 inf_obj->inferior = NULL;
65
40b355f2 66 delete inf_obj->threads;
08b8a139
TT
67 }
68};
69
70static const registry<inferior>::key<inferior_object, infpy_deleter>
71 infpy_inf_data_key;
595939de 72
595939de
PM
73/* Require that INFERIOR be a valid inferior ID. */
74#define INFPY_REQUIRE_VALID(Inferior) \
75 do { \
76 if (!Inferior->inferior) \
77 { \
78 PyErr_SetString (PyExc_RuntimeError, \
79 _("Inferior no longer exists.")); \
80 return NULL; \
81 } \
82 } while (0)
83
505500db 84static void
313f3b21 85python_on_normal_stop (struct bpstat *bs, int print_frame)
505500db 86{
2ea28649 87 enum gdb_signal stop_signal;
505500db 88
0646da15
TT
89 if (!gdb_python_initialized)
90 return;
91
151bb4a5
PA
92 if (inferior_ptid == null_ptid)
93 return;
505500db 94
1edb66d8 95 stop_signal = inferior_thread ()->stop_signal ();
505500db 96
1da5d0e6 97 gdbpy_enter enter_py;
505500db
SW
98
99 if (emit_stop_event (bs, stop_signal) < 0)
100 gdbpy_print_stack ();
505500db
SW
101}
102
103static void
104python_on_resume (ptid_t ptid)
105{
0646da15
TT
106 if (!gdb_python_initialized)
107 return;
108
1da5d0e6 109 gdbpy_enter enter_py (target_gdbarch ());
505500db
SW
110
111 if (emit_continue_event (ptid) < 0)
112 gdbpy_print_stack ();
505500db
SW
113}
114
162078c8
NB
115/* Callback, registered as an observer, that notifies Python listeners
116 when an inferior function call is about to be made. */
117
118static void
119python_on_inferior_call_pre (ptid_t thread, CORE_ADDR address)
120{
1da5d0e6 121 gdbpy_enter enter_py (target_gdbarch ());
162078c8
NB
122
123 if (emit_inferior_call_event (INFERIOR_CALL_PRE, thread, address) < 0)
124 gdbpy_print_stack ();
162078c8
NB
125}
126
127/* Callback, registered as an observer, that notifies Python listeners
128 when an inferior function call has completed. */
129
130static void
131python_on_inferior_call_post (ptid_t thread, CORE_ADDR address)
132{
1da5d0e6 133 gdbpy_enter enter_py (target_gdbarch ());
162078c8
NB
134
135 if (emit_inferior_call_event (INFERIOR_CALL_POST, thread, address) < 0)
136 gdbpy_print_stack ();
162078c8
NB
137}
138
139/* Callback, registered as an observer, that notifies Python listeners
140 when a part of memory has been modified by user action (eg via a
141 'set' command). */
142
143static void
144python_on_memory_change (struct inferior *inferior, CORE_ADDR addr, ssize_t len, const bfd_byte *data)
145{
1da5d0e6 146 gdbpy_enter enter_py (target_gdbarch ());
162078c8
NB
147
148 if (emit_memory_changed_event (addr, len) < 0)
149 gdbpy_print_stack ();
162078c8
NB
150}
151
152/* Callback, registered as an observer, that notifies Python listeners
153 when a register has been modified by user action (eg via a 'set'
154 command). */
155
156static void
bd2b40ac 157python_on_register_change (frame_info_ptr frame, int regnum)
162078c8 158{
1da5d0e6 159 gdbpy_enter enter_py (target_gdbarch ());
162078c8
NB
160
161 if (emit_register_changed_event (frame, regnum) < 0)
162 gdbpy_print_stack ();
162078c8
NB
163}
164
505500db
SW
165static void
166python_inferior_exit (struct inferior *inf)
167{
8cf64490 168 const LONGEST *exit_code = NULL;
505500db 169
0646da15
TT
170 if (!gdb_python_initialized)
171 return;
172
1da5d0e6 173 gdbpy_enter enter_py (target_gdbarch ());
505500db 174
8cf64490
TT
175 if (inf->has_exit_code)
176 exit_code = &inf->exit_code;
505500db 177
cb6be26b 178 if (emit_exited_event (exit_code, inf) < 0)
505500db 179 gdbpy_print_stack ();
505500db
SW
180}
181
20c168b5 182/* Callback used to notify Python listeners about new objfiles loaded in the
4ffbba72
DE
183 inferior. OBJFILE may be NULL which means that the objfile list has been
184 cleared (emptied). */
20c168b5
KP
185
186static void
187python_new_objfile (struct objfile *objfile)
188{
0646da15
TT
189 if (!gdb_python_initialized)
190 return;
191
07bc7329 192 gdbpy_enter enter_py (objfile != NULL
08feed99 193 ? objfile->arch ()
1da5d0e6 194 : target_gdbarch ());
20c168b5 195
4ffbba72
DE
196 if (objfile == NULL)
197 {
198 if (emit_clear_objfiles_event () < 0)
199 gdbpy_print_stack ();
200 }
201 else
202 {
203 if (emit_new_objfile_event (objfile) < 0)
204 gdbpy_print_stack ();
205 }
20c168b5
KP
206}
207
0b4fe76f
TT
208/* Emit a Python event when an objfile is about to be removed. */
209
210static void
211python_free_objfile (struct objfile *objfile)
212{
213 if (!gdb_python_initialized)
214 return;
215
216 gdbpy_enter enter_py (objfile->arch ());
217
218 if (emit_free_objfile_event (objfile) < 0)
219 gdbpy_print_stack ();
220}
221
754eadd1 222/* Return a reference to the Python object of type Inferior
595939de 223 representing INFERIOR. If the object has already been created,
754eadd1
PM
224 return it and increment the reference count, otherwise, create it.
225 Return NULL on failure. */
00431a78 226
61fd3e73 227gdbpy_ref<inferior_object>
595939de
PM
228inferior_to_inferior_object (struct inferior *inferior)
229{
230 inferior_object *inf_obj;
231
08b8a139 232 inf_obj = infpy_inf_data_key.get (inferior);
595939de
PM
233 if (!inf_obj)
234 {
595939de
PM
235 inf_obj = PyObject_New (inferior_object, &inferior_object_type);
236 if (!inf_obj)
61fd3e73 237 return NULL;
595939de
PM
238
239 inf_obj->inferior = inferior;
40b355f2 240 inf_obj->threads = new thread_map_t ();
595939de 241
72bc1d24
SM
242 /* PyObject_New initializes the new object with a refcount of 1. This
243 counts for the reference we are keeping in the inferior data. */
08b8a139 244 infpy_inf_data_key.set (inferior, inf_obj);
595939de 245 }
72bc1d24
SM
246
247 /* We are returning a new reference. */
61fd3e73
TT
248 gdb_assert (inf_obj != nullptr);
249 return gdbpy_ref<inferior_object>::new_reference (inf_obj);
595939de
PM
250}
251
7c96f8c1
TT
252/* Called when a new inferior is created. Notifies any Python event
253 listeners. */
254static void
255python_new_inferior (struct inferior *inf)
256{
257 if (!gdb_python_initialized)
258 return;
259
1da5d0e6 260 gdbpy_enter enter_py;
7c96f8c1
TT
261
262 if (evregpy_no_listeners_p (gdb_py_events.new_inferior))
263 return;
264
61fd3e73 265 gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (inf);
7c96f8c1
TT
266 if (inf_obj == NULL)
267 {
268 gdbpy_print_stack ();
269 return;
270 }
271
d98fc15b 272 gdbpy_ref<> event = create_event_object (&new_inferior_event_object_type);
7c96f8c1 273 if (event == NULL
00431a78
PA
274 || evpy_add_attribute (event.get (), "inferior",
275 (PyObject *) inf_obj.get ()) < 0
7c96f8c1
TT
276 || evpy_emit_event (event.get (), gdb_py_events.new_inferior) < 0)
277 gdbpy_print_stack ();
278}
279
280/* Called when an inferior is removed. Notifies any Python event
281 listeners. */
282static void
283python_inferior_deleted (struct inferior *inf)
284{
285 if (!gdb_python_initialized)
286 return;
287
1da5d0e6 288 gdbpy_enter enter_py;
7c96f8c1
TT
289
290 if (evregpy_no_listeners_p (gdb_py_events.inferior_deleted))
291 return;
292
61fd3e73 293 gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (inf);
7c96f8c1
TT
294 if (inf_obj == NULL)
295 {
296 gdbpy_print_stack ();
297 return;
298 }
299
d98fc15b 300 gdbpy_ref<> event = create_event_object (&inferior_deleted_event_object_type);
7c96f8c1 301 if (event == NULL
00431a78
PA
302 || evpy_add_attribute (event.get (), "inferior",
303 (PyObject *) inf_obj.get ()) < 0
7c96f8c1
TT
304 || evpy_emit_event (event.get (), gdb_py_events.inferior_deleted) < 0)
305 gdbpy_print_stack ();
306}
307
db1337cc 308gdbpy_ref<>
00431a78 309thread_to_thread_object (thread_info *thr)
595939de 310{
61fd3e73 311 gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (thr->inf);
9205649a 312 if (inf_obj == NULL)
754eadd1
PM
313 return NULL;
314
40b355f2
LS
315 auto thread_it = inf_obj->threads->find (thr);
316 if (thread_it != inf_obj->threads->end ())
317 return gdbpy_ref<>::new_reference
318 ((PyObject *) (thread_it->second.get ()));
595939de 319
4a137fec
TT
320 PyErr_SetString (PyExc_SystemError,
321 _("could not find gdb thread object"));
595939de
PM
322 return NULL;
323}
324
325static void
326add_thread_object (struct thread_info *tp)
327{
595939de 328 inferior_object *inf_obj;
595939de 329
0646da15
TT
330 if (!gdb_python_initialized)
331 return;
332
1da5d0e6 333 gdbpy_enter enter_py;
595939de 334
05b08ac1
TT
335 gdbpy_ref<thread_object> thread_obj = create_thread_object (tp);
336 if (thread_obj == NULL)
595939de
PM
337 {
338 gdbpy_print_stack ();
595939de
PM
339 return;
340 }
341
342 inf_obj = (inferior_object *) thread_obj->inf_obj;
343
40b355f2
LS
344 auto ins_result = inf_obj->threads->emplace
345 (thread_map_t::value_type (tp, std::move (thread_obj)));
595939de 346
40b355f2
LS
347 if (!ins_result.second)
348 return;
7c96f8c1
TT
349
350 if (evregpy_no_listeners_p (gdb_py_events.new_thread))
351 return;
352
40b355f2
LS
353 gdbpy_ref<> event = create_thread_event_object
354 (&new_thread_event_object_type,
355 (PyObject *) ins_result.first->second.get ());
356
7c96f8c1
TT
357 if (event == NULL
358 || evpy_emit_event (event.get (), gdb_py_events.new_thread) < 0)
359 gdbpy_print_stack ();
595939de
PM
360}
361
362static void
363delete_thread_object (struct thread_info *tp, int ignore)
364{
0646da15
TT
365 if (!gdb_python_initialized)
366 return;
367
1da5d0e6 368 gdbpy_enter enter_py;
595939de 369
61fd3e73 370 gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (tp->inf);
88b6faea 371 if (inf_obj == NULL)
07bc7329 372 return;
595939de 373
40b355f2
LS
374 auto it = inf_obj->threads->find (tp);
375 if (it != inf_obj->threads->end ())
376 {
377 /* Some python code can still hold a reference to the thread_object
378 instance. Make sure to remove the link to the associated
379 thread_info object as it will be freed soon. This makes the python
380 object invalid (i.e. gdb.InfThread.is_valid returns False). */
381 it->second->thread = nullptr;
382 inf_obj->threads->erase (it);
383 }
595939de
PM
384}
385
386static PyObject *
387infpy_threads (PyObject *self, PyObject *args)
388{
40b355f2 389 int i = 0;
595939de
PM
390 inferior_object *inf_obj = (inferior_object *) self;
391 PyObject *tuple;
392
393 INFPY_REQUIRE_VALID (inf_obj);
394
a70b8144 395 try
492d29ea
PA
396 {
397 update_thread_list ();
398 }
230d2906 399 catch (const gdb_exception &except)
492d29ea
PA
400 {
401 GDB_PY_HANDLE_EXCEPTION (except);
402 }
f66713d2 403
40b355f2 404 tuple = PyTuple_New (inf_obj->threads->size ());
595939de
PM
405 if (!tuple)
406 return NULL;
407
40b355f2 408 for (const thread_map_t::value_type &entry : *inf_obj->threads)
595939de 409 {
40b355f2 410 PyObject *thr = (PyObject *) entry.second.get ();
05b08ac1
TT
411 Py_INCREF (thr);
412 PyTuple_SET_ITEM (tuple, i, thr);
40b355f2 413 i = i + 1;
595939de
PM
414 }
415
416 return tuple;
417}
418
419static PyObject *
420infpy_get_num (PyObject *self, void *closure)
421{
422 inferior_object *inf = (inferior_object *) self;
423
424 INFPY_REQUIRE_VALID (inf);
425
062534d4 426 return gdb_py_object_from_longest (inf->inferior->num).release ();
595939de
PM
427}
428
0e3b7c25
AB
429/* Return the gdb.TargetConnection object for this inferior, or None if a
430 connection does not exist. */
431
432static PyObject *
433infpy_get_connection (PyObject *self, void *closure)
434{
435 inferior_object *inf = (inferior_object *) self;
436
437 INFPY_REQUIRE_VALID (inf);
438
439 process_stratum_target *target = inf->inferior->process_target ();
440 return target_to_connection_object (target).release ();
441}
442
55789354
TBA
443/* Return the connection number of the given inferior, or None if a
444 connection does not exist. */
445
446static PyObject *
447infpy_get_connection_num (PyObject *self, void *closure)
448{
449 inferior_object *inf = (inferior_object *) self;
450
451 INFPY_REQUIRE_VALID (inf);
452
453 process_stratum_target *target = inf->inferior->process_target ();
454 if (target == nullptr)
455 Py_RETURN_NONE;
456
8b9c48b2 457 return gdb_py_object_from_longest (target->connection_number).release ();
55789354
TBA
458}
459
595939de
PM
460static PyObject *
461infpy_get_pid (PyObject *self, void *closure)
462{
463 inferior_object *inf = (inferior_object *) self;
464
465 INFPY_REQUIRE_VALID (inf);
466
062534d4 467 return gdb_py_object_from_longest (inf->inferior->pid).release ();
595939de
PM
468}
469
470static PyObject *
471infpy_get_was_attached (PyObject *self, void *closure)
472{
473 inferior_object *inf = (inferior_object *) self;
474
475 INFPY_REQUIRE_VALID (inf);
476 if (inf->inferior->attach_flag)
477 Py_RETURN_TRUE;
478 Py_RETURN_FALSE;
479}
480
a40bf0c2
SM
481/* Getter of gdb.Inferior.progspace. */
482
483static PyObject *
484infpy_get_progspace (PyObject *self, void *closure)
485{
486 inferior_object *inf = (inferior_object *) self;
487
488 INFPY_REQUIRE_VALID (inf);
489
490 program_space *pspace = inf->inferior->pspace;
491 gdb_assert (pspace != nullptr);
492
3c7aa307 493 return pspace_to_pspace_object (pspace).release ();
a40bf0c2
SM
494}
495
595939de
PM
496/* Implementation of gdb.inferiors () -> (gdb.Inferior, ...).
497 Returns a tuple of all inferiors. */
498PyObject *
499gdbpy_inferiors (PyObject *unused, PyObject *unused2)
500{
7780f186 501 gdbpy_ref<> list (PyList_New (0));
f59fe7f8 502 if (list == NULL)
595939de
PM
503 return NULL;
504
d9bc85b6
SM
505 for (inferior *inf : all_inferiors ())
506 {
507 gdbpy_ref<inferior_object> inferior = inferior_to_inferior_object (inf);
508
509 if (inferior == NULL)
510 continue;
511
512 if (PyList_Append (list.get (), (PyObject *) inferior.get ()) != 0)
513 return NULL;
514 }
27ca1a5b 515
f59fe7f8 516 return PyList_AsTuple (list.get ());
595939de
PM
517}
518
519/* Membuf and memory manipulation. */
520
2678e2af 521/* Implementation of Inferior.read_memory (address, length).
595939de 522 Returns a Python buffer object with LENGTH bytes of the inferior's
8dc78533
JK
523 memory at ADDRESS. Both arguments are integers. Returns NULL on error,
524 with a python exception set. */
595939de
PM
525static PyObject *
526infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw)
527{
595939de 528 CORE_ADDR addr, length;
075c55e0 529 gdb::unique_xmalloc_ptr<gdb_byte> buffer;
625f7b1c 530 PyObject *addr_obj, *length_obj;
2adadf51 531 static const char *keywords[] = { "address", "length", NULL };
595939de 532
2adadf51
PA
533 if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "OO", keywords,
534 &addr_obj, &length_obj))
595939de
PM
535 return NULL;
536
b86af38a
TT
537 if (get_addr_from_python (addr_obj, &addr) < 0
538 || get_addr_from_python (length_obj, &length) < 0)
539 return NULL;
540
a70b8144 541 try
595939de 542 {
075c55e0 543 buffer.reset ((gdb_byte *) xmalloc (length));
595939de 544
075c55e0 545 read_memory (addr, buffer.get (), length);
595939de 546 }
230d2906 547 catch (const gdb_exception &except)
595939de 548 {
595939de
PM
549 GDB_PY_HANDLE_EXCEPTION (except);
550 }
551
595939de 552
625f7b1c 553 return gdbpy_buffer_to_membuf (std::move (buffer), addr, length);
595939de
PM
554}
555
2678e2af 556/* Implementation of Inferior.write_memory (address, buffer [, length]).
595939de
PM
557 Writes the contents of BUFFER (a Python object supporting the read
558 buffer protocol) at ADDRESS in the inferior's memory. Write LENGTH
559 bytes from BUFFER, or its entire contents if the argument is not
8dc78533
JK
560 provided. The function returns nothing. Returns NULL on error, with
561 a python exception set. */
595939de
PM
562static PyObject *
563infpy_write_memory (PyObject *self, PyObject *args, PyObject *kw)
564{
cc06b668 565 struct gdb_exception except;
ddd49eee 566 Py_ssize_t buf_len;
7c543f7b 567 const gdb_byte *buffer;
595939de
PM
568 CORE_ADDR addr, length;
569 PyObject *addr_obj, *length_obj = NULL;
2adadf51 570 static const char *keywords[] = { "address", "buffer", "length", NULL };
9a27f2c6 571 Py_buffer pybuf;
595939de 572
2adadf51
PA
573 if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "Os*|O", keywords,
574 &addr_obj, &pybuf, &length_obj))
9a27f2c6 575 return NULL;
595939de 576
6ca62222 577 Py_buffer_up buffer_up (&pybuf);
7c543f7b 578 buffer = (const gdb_byte *) pybuf.buf;
9a27f2c6 579 buf_len = pybuf.len;
595939de 580
b86af38a 581 if (get_addr_from_python (addr_obj, &addr) < 0)
6ca62222 582 return nullptr;
b86af38a
TT
583
584 if (!length_obj)
585 length = buf_len;
586 else if (get_addr_from_python (length_obj, &length) < 0)
6ca62222 587 return nullptr;
b86af38a 588
a70b8144 589 try
595939de 590 {
7c543f7b 591 write_memory_with_notification (addr, buffer, length);
595939de 592 }
94aeb44b 593 catch (gdb_exception &ex)
492d29ea 594 {
94aeb44b 595 except = std::move (ex);
492d29ea 596 }
492d29ea 597
595939de
PM
598 GDB_PY_HANDLE_EXCEPTION (except);
599
595939de
PM
600 Py_RETURN_NONE;
601}
602
595939de
PM
603/* Implementation of
604 gdb.search_memory (address, length, pattern). ADDRESS is the
605 address to start the search. LENGTH specifies the scope of the
606 search from ADDRESS. PATTERN is the pattern to search for (and
607 must be a Python object supporting the buffer protocol).
608 Returns a Python Long object holding the address where the pattern
8dc78533
JK
609 was located, or if the pattern was not found, returns None. Returns NULL
610 on error, with a python exception set. */
595939de
PM
611static PyObject *
612infpy_search_memory (PyObject *self, PyObject *args, PyObject *kw)
613{
cc06b668 614 struct gdb_exception except;
595939de 615 CORE_ADDR start_addr, length;
2adadf51 616 static const char *keywords[] = { "address", "length", "pattern", NULL };
9a27f2c6 617 PyObject *start_addr_obj, *length_obj;
595939de 618 Py_ssize_t pattern_size;
7c543f7b 619 const gdb_byte *buffer;
595939de
PM
620 CORE_ADDR found_addr;
621 int found = 0;
9a27f2c6 622 Py_buffer pybuf;
595939de 623
2adadf51
PA
624 if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "OOs*", keywords,
625 &start_addr_obj, &length_obj,
626 &pybuf))
9a27f2c6
PK
627 return NULL;
628
6ca62222 629 Py_buffer_up buffer_up (&pybuf);
7c543f7b 630 buffer = (const gdb_byte *) pybuf.buf;
9a27f2c6 631 pattern_size = pybuf.len;
595939de 632
b86af38a 633 if (get_addr_from_python (start_addr_obj, &start_addr) < 0)
6ca62222 634 return nullptr;
256458bc 635
b86af38a 636 if (get_addr_from_python (length_obj, &length) < 0)
6ca62222 637 return nullptr;
9a27f2c6 638
b86af38a
TT
639 if (!length)
640 {
641 PyErr_SetString (PyExc_ValueError,
642 _("Search range is empty."));
6ca62222 643 return nullptr;
b86af38a
TT
644 }
645 /* Watch for overflows. */
646 else if (length > CORE_ADDR_MAX
647 || (start_addr + length - 1) < start_addr)
648 {
649 PyErr_SetString (PyExc_ValueError,
650 _("The search range is too large."));
6ca62222 651 return nullptr;
595939de 652 }
595939de 653
a70b8144 654 try
595939de
PM
655 {
656 found = target_search_memory (start_addr, length,
657 buffer, pattern_size,
658 &found_addr);
659 }
94aeb44b 660 catch (gdb_exception &ex)
492d29ea 661 {
94aeb44b 662 except = std::move (ex);
492d29ea 663 }
492d29ea 664
b86af38a 665 GDB_PY_HANDLE_EXCEPTION (except);
9a27f2c6 666
595939de 667 if (found)
b017825f 668 return gdb_py_object_from_ulongest (found_addr).release ();
595939de
PM
669 else
670 Py_RETURN_NONE;
671}
672
29703da4
PM
673/* Implementation of gdb.Inferior.is_valid (self) -> Boolean.
674 Returns True if this inferior object still exists in GDB. */
675
676static PyObject *
677infpy_is_valid (PyObject *self, PyObject *args)
678{
679 inferior_object *inf = (inferior_object *) self;
680
681 if (! inf->inferior)
682 Py_RETURN_FALSE;
683
684 Py_RETURN_TRUE;
685}
686
2b0c8b01 687/* Implementation of gdb.Inferior.thread_from_handle (self, handle)
dda83cd7 688 -> gdb.InferiorThread. */
fbbe5337 689
7d221512 690static PyObject *
fbbe5337
KB
691infpy_thread_from_thread_handle (PyObject *self, PyObject *args, PyObject *kw)
692{
db1337cc 693 PyObject *handle_obj;
fbbe5337 694 inferior_object *inf_obj = (inferior_object *) self;
2b0c8b01 695 static const char *keywords[] = { "handle", NULL };
fbbe5337
KB
696
697 INFPY_REQUIRE_VALID (inf_obj);
698
699 if (! gdb_PyArg_ParseTupleAndKeywords (args, kw, "O", keywords, &handle_obj))
700 return NULL;
701
50a82723
KB
702 const gdb_byte *bytes;
703 size_t bytes_len;
704 Py_buffer_up buffer_up;
705 Py_buffer py_buf;
706
707 if (PyObject_CheckBuffer (handle_obj)
708 && PyObject_GetBuffer (handle_obj, &py_buf, PyBUF_SIMPLE) == 0)
709 {
710 buffer_up.reset (&py_buf);
711 bytes = (const gdb_byte *) py_buf.buf;
712 bytes_len = py_buf.len;
713 }
714 else if (gdbpy_is_value_object (handle_obj))
715 {
716 struct value *val = value_object_to_value (handle_obj);
50888e42 717 bytes = value_contents_all (val).data ();
d0c97917 718 bytes_len = val->type ()->length ();
50a82723
KB
719 }
720 else
fbbe5337
KB
721 {
722 PyErr_SetString (PyExc_TypeError,
2b0c8b01 723 _("Argument 'handle' must be a thread handle object."));
fbbe5337
KB
724
725 return NULL;
726 }
db1337cc 727
a70b8144 728 try
db1337cc
TT
729 {
730 struct thread_info *thread_info;
db1337cc 731
50a82723 732 thread_info = find_thread_by_handle
dda83cd7 733 (gdb::array_view<const gdb_byte> (bytes, bytes_len),
50a82723 734 inf_obj->inferior);
db1337cc 735 if (thread_info != NULL)
4a137fec 736 return thread_to_thread_object (thread_info).release ();
db1337cc 737 }
230d2906 738 catch (const gdb_exception &except)
fbbe5337 739 {
db1337cc 740 GDB_PY_HANDLE_EXCEPTION (except);
fbbe5337
KB
741 }
742
4a137fec 743 Py_RETURN_NONE;
fbbe5337
KB
744}
745
add5ded5
TT
746/* Implementation of gdb.Inferior.architecture. */
747
748static PyObject *
749infpy_architecture (PyObject *self, PyObject *args)
750{
751 inferior_object *inf = (inferior_object *) self;
752
753 INFPY_REQUIRE_VALID (inf);
754
755 return gdbarch_to_arch_object (inf->inferior->gdbarch);
756}
757
1256af7d
SM
758/* Implement repr() for gdb.Inferior. */
759
760static PyObject *
761infpy_repr (PyObject *obj)
762{
763 inferior_object *self = (inferior_object *) obj;
764 inferior *inf = self->inferior;
765
766 if (inf == nullptr)
5aee4587 767 return PyUnicode_FromString ("<gdb.Inferior (invalid)>");
1256af7d 768
5aee4587
SM
769 return PyUnicode_FromFormat ("<gdb.Inferior num=%d, pid=%d>",
770 inf->num, inf->pid);
1256af7d
SM
771}
772
fbbe5337 773
754eadd1
PM
774static void
775infpy_dealloc (PyObject *obj)
776{
777 inferior_object *inf_obj = (inferior_object *) obj;
754eadd1 778
cb6e6bb8
AB
779 /* The inferior itself holds a reference to this Python object, which
780 will keep the reference count of this object above zero until GDB
781 deletes the inferior and py_free_inferior is called.
782
783 Once py_free_inferior has been called then the link between this
784 Python object and the inferior is set to nullptr, and then the
785 reference count on this Python object is decremented.
786
787 The result of all this is that the link between this Python object and
788 the inferior should always have been set to nullptr before this
789 function is called. */
790 gdb_assert (inf_obj->inferior == nullptr);
754eadd1 791
2e953aca 792 Py_TYPE (obj)->tp_free (obj);
754eadd1 793}
595939de 794
2aa48337
KP
795/* Implementation of gdb.selected_inferior() -> gdb.Inferior.
796 Returns the current inferior object. */
797
798PyObject *
799gdbpy_selected_inferior (PyObject *self, PyObject *args)
800{
61fd3e73
TT
801 return ((PyObject *)
802 inferior_to_inferior_object (current_inferior ()).release ());
2aa48337
KP
803}
804
999633ed 805int
595939de
PM
806gdbpy_initialize_inferior (void)
807{
808 if (PyType_Ready (&inferior_object_type) < 0)
999633ed 809 return -1;
595939de 810
aa36459a
TT
811 if (gdb_pymodule_addobject (gdb_module, "Inferior",
812 (PyObject *) &inferior_object_type) < 0)
999633ed 813 return -1;
595939de 814
c90e7d63
SM
815 gdb::observers::new_thread.attach (add_thread_object, "py-inferior");
816 gdb::observers::thread_exit.attach (delete_thread_object, "py-inferior");
817 gdb::observers::normal_stop.attach (python_on_normal_stop, "py-inferior");
818 gdb::observers::target_resumed.attach (python_on_resume, "py-inferior");
819 gdb::observers::inferior_call_pre.attach (python_on_inferior_call_pre,
820 "py-inferior");
821 gdb::observers::inferior_call_post.attach (python_on_inferior_call_post,
822 "py-inferior");
823 gdb::observers::memory_changed.attach (python_on_memory_change,
824 "py-inferior");
825 gdb::observers::register_changed.attach (python_on_register_change,
826 "py-inferior");
827 gdb::observers::inferior_exit.attach (python_inferior_exit, "py-inferior");
2c473def
MW
828 /* Need to run after auto-load's new_objfile observer, so that
829 auto-loaded pretty-printers are available. */
830 gdb::observers::new_objfile.attach
831 (python_new_objfile, "py-inferior",
832 { &auto_load_new_objfile_observer_token });
0b4fe76f 833 gdb::observers::free_objfile.attach (python_free_objfile, "py-inferior");
c90e7d63
SM
834 gdb::observers::inferior_added.attach (python_new_inferior, "py-inferior");
835 gdb::observers::inferior_removed.attach (python_inferior_deleted,
836 "py-inferior");
595939de 837
625f7b1c 838 return 0;
595939de
PM
839}
840
0d1f4ceb 841static gdb_PyGetSetDef inferior_object_getset[] =
595939de
PM
842{
843 { "num", infpy_get_num, NULL, "ID of inferior, as assigned by GDB.", NULL },
0e3b7c25
AB
844 { "connection", infpy_get_connection, NULL,
845 "The gdb.TargetConnection for this inferior.", NULL },
55789354
TBA
846 { "connection_num", infpy_get_connection_num, NULL,
847 "ID of inferior's connection, as assigned by GDB.", NULL },
595939de
PM
848 { "pid", infpy_get_pid, NULL, "PID of inferior, as assigned by the OS.",
849 NULL },
850 { "was_attached", infpy_get_was_attached, NULL,
851 "True if the inferior was created using 'attach'.", NULL },
a40bf0c2 852 { "progspace", infpy_get_progspace, NULL, "Program space of this inferior" },
595939de
PM
853 { NULL }
854};
855
856static PyMethodDef inferior_object_methods[] =
857{
29703da4
PM
858 { "is_valid", infpy_is_valid, METH_NOARGS,
859 "is_valid () -> Boolean.\n\
860Return true if this inferior is valid, false if not." },
595939de
PM
861 { "threads", infpy_threads, METH_NOARGS,
862 "Return all the threads of this inferior." },
863 { "read_memory", (PyCFunction) infpy_read_memory,
864 METH_VARARGS | METH_KEYWORDS,
865 "read_memory (address, length) -> buffer\n\
866Return a buffer object for reading from the inferior's memory." },
867 { "write_memory", (PyCFunction) infpy_write_memory,
868 METH_VARARGS | METH_KEYWORDS,
869 "write_memory (address, buffer [, length])\n\
870Write the given buffer object to the inferior's memory." },
871 { "search_memory", (PyCFunction) infpy_search_memory,
872 METH_VARARGS | METH_KEYWORDS,
873 "search_memory (address, length, pattern) -> long\n\
874Return a long with the address of a match, or None." },
2b0c8b01 875 /* thread_from_thread_handle is deprecated. */
fbbe5337
KB
876 { "thread_from_thread_handle", (PyCFunction) infpy_thread_from_thread_handle,
877 METH_VARARGS | METH_KEYWORDS,
878 "thread_from_thread_handle (handle) -> gdb.InferiorThread.\n\
2b0c8b01
KB
879Return thread object corresponding to thread handle.\n\
880This method is deprecated - use thread_from_handle instead." },
881 { "thread_from_handle", (PyCFunction) infpy_thread_from_thread_handle,
882 METH_VARARGS | METH_KEYWORDS,
883 "thread_from_handle (handle) -> gdb.InferiorThread.\n\
fbbe5337 884Return thread object corresponding to thread handle." },
add5ded5
TT
885 { "architecture", (PyCFunction) infpy_architecture, METH_NOARGS,
886 "architecture () -> gdb.Architecture\n\
887Return architecture of this inferior." },
595939de
PM
888 { NULL }
889};
890
e36122e9 891PyTypeObject inferior_object_type =
595939de 892{
9a27f2c6 893 PyVarObject_HEAD_INIT (NULL, 0)
595939de
PM
894 "gdb.Inferior", /* tp_name */
895 sizeof (inferior_object), /* tp_basicsize */
896 0, /* tp_itemsize */
754eadd1 897 infpy_dealloc, /* tp_dealloc */
595939de
PM
898 0, /* tp_print */
899 0, /* tp_getattr */
900 0, /* tp_setattr */
901 0, /* tp_compare */
1256af7d 902 infpy_repr, /* tp_repr */
595939de
PM
903 0, /* tp_as_number */
904 0, /* tp_as_sequence */
905 0, /* tp_as_mapping */
906 0, /* tp_hash */
907 0, /* tp_call */
908 0, /* tp_str */
909 0, /* tp_getattro */
910 0, /* tp_setattro */
911 0, /* tp_as_buffer */
0b233e34 912 Py_TPFLAGS_DEFAULT, /* tp_flags */
595939de
PM
913 "GDB inferior object", /* tp_doc */
914 0, /* tp_traverse */
915 0, /* tp_clear */
916 0, /* tp_richcompare */
917 0, /* tp_weaklistoffset */
918 0, /* tp_iter */
919 0, /* tp_iternext */
920 inferior_object_methods, /* tp_methods */
921 0, /* tp_members */
922 inferior_object_getset, /* tp_getset */
923 0, /* tp_base */
924 0, /* tp_dict */
925 0, /* tp_descr_get */
926 0, /* tp_descr_set */
927 0, /* tp_dictoffset */
928 0, /* tp_init */
929 0 /* tp_alloc */
930};