1 /* Python interface to inferiors. 2 3 Copyright (C) 2009-2023 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20 #include "defs.h" 21 #include "auto-load.h" 22 #include "gdbcore.h" 23 #include "gdbthread.h" 24 #include "inferior.h" 25 #include "objfiles.h" 26 #include "observable.h" 27 #include "python-internal.h" 28 #include "arch-utils.h" 29 #include "language.h" 30 #include "gdbsupport/gdb_signals.h" 31 #include "py-event.h" 32 #include "py-stopevent.h" 33 #include <unordered_map> 34 35 using thread_map_t 36 = std::unordered_map<thread_info *, gdbpy_ref<thread_object>>; 37 38 struct 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 50 extern PyTypeObject inferior_object_type 51 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("inferior_object"); 52 53 /* Deleter to clean up when an inferior is removed. */ 54 struct infpy_deleter 55 { 56 void operator() (inferior_object *obj) 57 { 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 66 delete inf_obj->threads; 67 } 68 }; 69 70 static const registry<inferior>::key<inferior_object, infpy_deleter> 71 infpy_inf_data_key; 72 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 84 static void 85 python_on_normal_stop (struct bpstat *bs, int print_frame) 86 { 87 enum gdb_signal stop_signal; 88 89 if (!gdb_python_initialized) 90 return; 91 92 if (inferior_ptid == null_ptid) 93 return; 94 95 stop_signal = inferior_thread ()->stop_signal (); 96 97 gdbpy_enter enter_py; 98 99 if (emit_stop_event (bs, stop_signal) < 0) 100 gdbpy_print_stack (); 101 } 102 103 static void 104 python_on_resume (ptid_t ptid) 105 { 106 if (!gdb_python_initialized) 107 return; 108 109 gdbpy_enter enter_py (target_gdbarch ()); 110 111 if (emit_continue_event (ptid) < 0) 112 gdbpy_print_stack (); 113 } 114 115 /* Callback, registered as an observer, that notifies Python listeners 116 when an inferior function call is about to be made. */ 117 118 static void 119 python_on_inferior_call_pre (ptid_t thread, CORE_ADDR address) 120 { 121 gdbpy_enter enter_py (target_gdbarch ()); 122 123 if (emit_inferior_call_event (INFERIOR_CALL_PRE, thread, address) < 0) 124 gdbpy_print_stack (); 125 } 126 127 /* Callback, registered as an observer, that notifies Python listeners 128 when an inferior function call has completed. */ 129 130 static void 131 python_on_inferior_call_post (ptid_t thread, CORE_ADDR address) 132 { 133 gdbpy_enter enter_py (target_gdbarch ()); 134 135 if (emit_inferior_call_event (INFERIOR_CALL_POST, thread, address) < 0) 136 gdbpy_print_stack (); 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 143 static void 144 python_on_memory_change (struct inferior *inferior, CORE_ADDR addr, ssize_t len, const bfd_byte *data) 145 { 146 gdbpy_enter enter_py (target_gdbarch ()); 147 148 if (emit_memory_changed_event (addr, len) < 0) 149 gdbpy_print_stack (); 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 156 static void 157 python_on_register_change (frame_info_ptr frame, int regnum) 158 { 159 gdbpy_enter enter_py (target_gdbarch ()); 160 161 if (emit_register_changed_event (frame, regnum) < 0) 162 gdbpy_print_stack (); 163 } 164 165 static void 166 python_inferior_exit (struct inferior *inf) 167 { 168 const LONGEST *exit_code = NULL; 169 170 if (!gdb_python_initialized) 171 return; 172 173 gdbpy_enter enter_py (target_gdbarch ()); 174 175 if (inf->has_exit_code) 176 exit_code = &inf->exit_code; 177 178 if (emit_exited_event (exit_code, inf) < 0) 179 gdbpy_print_stack (); 180 } 181 182 /* Callback used to notify Python listeners about new objfiles loaded in the 183 inferior. OBJFILE may be NULL which means that the objfile list has been 184 cleared (emptied). */ 185 186 static void 187 python_new_objfile (struct objfile *objfile) 188 { 189 if (!gdb_python_initialized) 190 return; 191 192 gdbpy_enter enter_py (objfile != NULL 193 ? objfile->arch () 194 : target_gdbarch ()); 195 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 } 206 } 207 208 /* Emit a Python event when an objfile is about to be removed. */ 209 210 static void 211 python_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 222 /* Return a reference to the Python object of type Inferior 223 representing INFERIOR. If the object has already been created, 224 return it and increment the reference count, otherwise, create it. 225 Return NULL on failure. */ 226 227 gdbpy_ref<inferior_object> 228 inferior_to_inferior_object (struct inferior *inferior) 229 { 230 inferior_object *inf_obj; 231 232 inf_obj = infpy_inf_data_key.get (inferior); 233 if (!inf_obj) 234 { 235 inf_obj = PyObject_New (inferior_object, &inferior_object_type); 236 if (!inf_obj) 237 return NULL; 238 239 inf_obj->inferior = inferior; 240 inf_obj->threads = new thread_map_t (); 241 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. */ 244 infpy_inf_data_key.set (inferior, inf_obj); 245 } 246 247 /* We are returning a new reference. */ 248 gdb_assert (inf_obj != nullptr); 249 return gdbpy_ref<inferior_object>::new_reference (inf_obj); 250 } 251 252 /* Called when a new inferior is created. Notifies any Python event 253 listeners. */ 254 static void 255 python_new_inferior (struct inferior *inf) 256 { 257 if (!gdb_python_initialized) 258 return; 259 260 gdbpy_enter enter_py; 261 262 if (evregpy_no_listeners_p (gdb_py_events.new_inferior)) 263 return; 264 265 gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (inf); 266 if (inf_obj == NULL) 267 { 268 gdbpy_print_stack (); 269 return; 270 } 271 272 gdbpy_ref<> event = create_event_object (&new_inferior_event_object_type); 273 if (event == NULL 274 || evpy_add_attribute (event.get (), "inferior", 275 (PyObject *) inf_obj.get ()) < 0 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. */ 282 static void 283 python_inferior_deleted (struct inferior *inf) 284 { 285 if (!gdb_python_initialized) 286 return; 287 288 gdbpy_enter enter_py; 289 290 if (evregpy_no_listeners_p (gdb_py_events.inferior_deleted)) 291 return; 292 293 gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (inf); 294 if (inf_obj == NULL) 295 { 296 gdbpy_print_stack (); 297 return; 298 } 299 300 gdbpy_ref<> event = create_event_object (&inferior_deleted_event_object_type); 301 if (event == NULL 302 || evpy_add_attribute (event.get (), "inferior", 303 (PyObject *) inf_obj.get ()) < 0 304 || evpy_emit_event (event.get (), gdb_py_events.inferior_deleted) < 0) 305 gdbpy_print_stack (); 306 } 307 308 gdbpy_ref<> 309 thread_to_thread_object (thread_info *thr) 310 { 311 gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (thr->inf); 312 if (inf_obj == NULL) 313 return NULL; 314 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 ())); 319 320 PyErr_SetString (PyExc_SystemError, 321 _("could not find gdb thread object")); 322 return NULL; 323 } 324 325 static void 326 add_thread_object (struct thread_info *tp) 327 { 328 inferior_object *inf_obj; 329 330 if (!gdb_python_initialized) 331 return; 332 333 gdbpy_enter enter_py; 334 335 gdbpy_ref<thread_object> thread_obj = create_thread_object (tp); 336 if (thread_obj == NULL) 337 { 338 gdbpy_print_stack (); 339 return; 340 } 341 342 inf_obj = (inferior_object *) thread_obj->inf_obj; 343 344 auto ins_result = inf_obj->threads->emplace 345 (thread_map_t::value_type (tp, std::move (thread_obj))); 346 347 if (!ins_result.second) 348 return; 349 350 if (evregpy_no_listeners_p (gdb_py_events.new_thread)) 351 return; 352 353 gdbpy_ref<> event = create_thread_event_object 354 (&new_thread_event_object_type, 355 (PyObject *) ins_result.first->second.get ()); 356 357 if (event == NULL 358 || evpy_emit_event (event.get (), gdb_py_events.new_thread) < 0) 359 gdbpy_print_stack (); 360 } 361 362 static void 363 delete_thread_object (struct thread_info *tp, int ignore) 364 { 365 if (!gdb_python_initialized) 366 return; 367 368 gdbpy_enter enter_py; 369 370 gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (tp->inf); 371 if (inf_obj == NULL) 372 return; 373 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 } 384 } 385 386 static PyObject * 387 infpy_threads (PyObject *self, PyObject *args) 388 { 389 int i = 0; 390 inferior_object *inf_obj = (inferior_object *) self; 391 PyObject *tuple; 392 393 INFPY_REQUIRE_VALID (inf_obj); 394 395 try 396 { 397 update_thread_list (); 398 } 399 catch (const gdb_exception &except) 400 { 401 GDB_PY_HANDLE_EXCEPTION (except); 402 } 403 404 tuple = PyTuple_New (inf_obj->threads->size ()); 405 if (!tuple) 406 return NULL; 407 408 for (const thread_map_t::value_type &entry : *inf_obj->threads) 409 { 410 PyObject *thr = (PyObject *) entry.second.get (); 411 Py_INCREF (thr); 412 PyTuple_SET_ITEM (tuple, i, thr); 413 i = i + 1; 414 } 415 416 return tuple; 417 } 418 419 static PyObject * 420 infpy_get_num (PyObject *self, void *closure) 421 { 422 inferior_object *inf = (inferior_object *) self; 423 424 INFPY_REQUIRE_VALID (inf); 425 426 return gdb_py_object_from_longest (inf->inferior->num).release (); 427 } 428 429 /* Return the gdb.TargetConnection object for this inferior, or None if a 430 connection does not exist. */ 431 432 static PyObject * 433 infpy_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 443 /* Return the connection number of the given inferior, or None if a 444 connection does not exist. */ 445 446 static PyObject * 447 infpy_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 457 return gdb_py_object_from_longest (target->connection_number).release (); 458 } 459 460 static PyObject * 461 infpy_get_pid (PyObject *self, void *closure) 462 { 463 inferior_object *inf = (inferior_object *) self; 464 465 INFPY_REQUIRE_VALID (inf); 466 467 return gdb_py_object_from_longest (inf->inferior->pid).release (); 468 } 469 470 static PyObject * 471 infpy_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 481 /* Getter of gdb.Inferior.progspace. */ 482 483 static PyObject * 484 infpy_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 493 return pspace_to_pspace_object (pspace).release (); 494 } 495 496 /* Implementation of gdb.inferiors () -> (gdb.Inferior, ...). 497 Returns a tuple of all inferiors. */ 498 PyObject * 499 gdbpy_inferiors (PyObject *unused, PyObject *unused2) 500 { 501 gdbpy_ref<> list (PyList_New (0)); 502 if (list == NULL) 503 return NULL; 504 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 } 515 516 return PyList_AsTuple (list.get ()); 517 } 518 519 /* Membuf and memory manipulation. */ 520 521 /* Implementation of Inferior.read_memory (address, length). 522 Returns a Python buffer object with LENGTH bytes of the inferior's 523 memory at ADDRESS. Both arguments are integers. Returns NULL on error, 524 with a python exception set. */ 525 static PyObject * 526 infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw) 527 { 528 CORE_ADDR addr, length; 529 gdb::unique_xmalloc_ptr<gdb_byte> buffer; 530 PyObject *addr_obj, *length_obj; 531 static const char *keywords[] = { "address", "length", NULL }; 532 533 if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "OO", keywords, 534 &addr_obj, &length_obj)) 535 return NULL; 536 537 if (get_addr_from_python (addr_obj, &addr) < 0 538 || get_addr_from_python (length_obj, &length) < 0) 539 return NULL; 540 541 try 542 { 543 buffer.reset ((gdb_byte *) xmalloc (length)); 544 545 read_memory (addr, buffer.get (), length); 546 } 547 catch (const gdb_exception &except) 548 { 549 GDB_PY_HANDLE_EXCEPTION (except); 550 } 551 552 553 return gdbpy_buffer_to_membuf (std::move (buffer), addr, length); 554 } 555 556 /* Implementation of Inferior.write_memory (address, buffer [, length]). 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 560 provided. The function returns nothing. Returns NULL on error, with 561 a python exception set. */ 562 static PyObject * 563 infpy_write_memory (PyObject *self, PyObject *args, PyObject *kw) 564 { 565 struct gdb_exception except; 566 Py_ssize_t buf_len; 567 const gdb_byte *buffer; 568 CORE_ADDR addr, length; 569 PyObject *addr_obj, *length_obj = NULL; 570 static const char *keywords[] = { "address", "buffer", "length", NULL }; 571 Py_buffer pybuf; 572 573 if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "Os*|O", keywords, 574 &addr_obj, &pybuf, &length_obj)) 575 return NULL; 576 577 Py_buffer_up buffer_up (&pybuf); 578 buffer = (const gdb_byte *) pybuf.buf; 579 buf_len = pybuf.len; 580 581 if (get_addr_from_python (addr_obj, &addr) < 0) 582 return nullptr; 583 584 if (!length_obj) 585 length = buf_len; 586 else if (get_addr_from_python (length_obj, &length) < 0) 587 return nullptr; 588 589 try 590 { 591 write_memory_with_notification (addr, buffer, length); 592 } 593 catch (gdb_exception &ex) 594 { 595 except = std::move (ex); 596 } 597 598 GDB_PY_HANDLE_EXCEPTION (except); 599 600 Py_RETURN_NONE; 601 } 602 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 609 was located, or if the pattern was not found, returns None. Returns NULL 610 on error, with a python exception set. */ 611 static PyObject * 612 infpy_search_memory (PyObject *self, PyObject *args, PyObject *kw) 613 { 614 struct gdb_exception except; 615 CORE_ADDR start_addr, length; 616 static const char *keywords[] = { "address", "length", "pattern", NULL }; 617 PyObject *start_addr_obj, *length_obj; 618 Py_ssize_t pattern_size; 619 const gdb_byte *buffer; 620 CORE_ADDR found_addr; 621 int found = 0; 622 Py_buffer pybuf; 623 624 if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "OOs*", keywords, 625 &start_addr_obj, &length_obj, 626 &pybuf)) 627 return NULL; 628 629 Py_buffer_up buffer_up (&pybuf); 630 buffer = (const gdb_byte *) pybuf.buf; 631 pattern_size = pybuf.len; 632 633 if (get_addr_from_python (start_addr_obj, &start_addr) < 0) 634 return nullptr; 635 636 if (get_addr_from_python (length_obj, &length) < 0) 637 return nullptr; 638 639 if (!length) 640 { 641 PyErr_SetString (PyExc_ValueError, 642 _("Search range is empty.")); 643 return nullptr; 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.")); 651 return nullptr; 652 } 653 654 try 655 { 656 found = target_search_memory (start_addr, length, 657 buffer, pattern_size, 658 &found_addr); 659 } 660 catch (gdb_exception &ex) 661 { 662 except = std::move (ex); 663 } 664 665 GDB_PY_HANDLE_EXCEPTION (except); 666 667 if (found) 668 return gdb_py_object_from_ulongest (found_addr).release (); 669 else 670 Py_RETURN_NONE; 671 } 672 673 /* Implementation of gdb.Inferior.is_valid (self) -> Boolean. 674 Returns True if this inferior object still exists in GDB. */ 675 676 static PyObject * 677 infpy_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 687 /* Implementation of gdb.Inferior.thread_from_handle (self, handle) 688 -> gdb.InferiorThread. */ 689 690 static PyObject * 691 infpy_thread_from_thread_handle (PyObject *self, PyObject *args, PyObject *kw) 692 { 693 PyObject *handle_obj; 694 inferior_object *inf_obj = (inferior_object *) self; 695 static const char *keywords[] = { "handle", NULL }; 696 697 INFPY_REQUIRE_VALID (inf_obj); 698 699 if (! gdb_PyArg_ParseTupleAndKeywords (args, kw, "O", keywords, &handle_obj)) 700 return NULL; 701 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); 717 bytes = value_contents_all (val).data (); 718 bytes_len = value_type (val)->length (); 719 } 720 else 721 { 722 PyErr_SetString (PyExc_TypeError, 723 _("Argument 'handle' must be a thread handle object.")); 724 725 return NULL; 726 } 727 728 try 729 { 730 struct thread_info *thread_info; 731 732 thread_info = find_thread_by_handle 733 (gdb::array_view<const gdb_byte> (bytes, bytes_len), 734 inf_obj->inferior); 735 if (thread_info != NULL) 736 return thread_to_thread_object (thread_info).release (); 737 } 738 catch (const gdb_exception &except) 739 { 740 GDB_PY_HANDLE_EXCEPTION (except); 741 } 742 743 Py_RETURN_NONE; 744 } 745 746 /* Implementation of gdb.Inferior.architecture. */ 747 748 static PyObject * 749 infpy_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 758 /* Implement repr() for gdb.Inferior. */ 759 760 static PyObject * 761 infpy_repr (PyObject *obj) 762 { 763 inferior_object *self = (inferior_object *) obj; 764 inferior *inf = self->inferior; 765 766 if (inf == nullptr) 767 return PyUnicode_FromString ("<gdb.Inferior (invalid)>"); 768 769 return PyUnicode_FromFormat ("<gdb.Inferior num=%d, pid=%d>", 770 inf->num, inf->pid); 771 } 772 773 774 static void 775 infpy_dealloc (PyObject *obj) 776 { 777 inferior_object *inf_obj = (inferior_object *) obj; 778 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); 791 792 Py_TYPE (obj)->tp_free (obj); 793 } 794 795 /* Implementation of gdb.selected_inferior() -> gdb.Inferior. 796 Returns the current inferior object. */ 797 798 PyObject * 799 gdbpy_selected_inferior (PyObject *self, PyObject *args) 800 { 801 return ((PyObject *) 802 inferior_to_inferior_object (current_inferior ()).release ()); 803 } 804 805 int 806 gdbpy_initialize_inferior (void) 807 { 808 if (PyType_Ready (&inferior_object_type) < 0) 809 return -1; 810 811 if (gdb_pymodule_addobject (gdb_module, "Inferior", 812 (PyObject *) &inferior_object_type) < 0) 813 return -1; 814 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"); 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 }); 833 gdb::observers::free_objfile.attach (python_free_objfile, "py-inferior"); 834 gdb::observers::inferior_added.attach (python_new_inferior, "py-inferior"); 835 gdb::observers::inferior_removed.attach (python_inferior_deleted, 836 "py-inferior"); 837 838 return 0; 839 } 840 841 static gdb_PyGetSetDef inferior_object_getset[] = 842 { 843 { "num", infpy_get_num, NULL, "ID of inferior, as assigned by GDB.", NULL }, 844 { "connection", infpy_get_connection, NULL, 845 "The gdb.TargetConnection for this inferior.", NULL }, 846 { "connection_num", infpy_get_connection_num, NULL, 847 "ID of inferior's connection, as assigned by GDB.", NULL }, 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 }, 852 { "progspace", infpy_get_progspace, NULL, "Program space of this inferior" }, 853 { NULL } 854 }; 855 856 static PyMethodDef inferior_object_methods[] = 857 { 858 { "is_valid", infpy_is_valid, METH_NOARGS, 859 "is_valid () -> Boolean.\n\ 860 Return true if this inferior is valid, false if not." }, 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\ 866 Return 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\ 870 Write 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\ 874 Return a long with the address of a match, or None." }, 875 /* thread_from_thread_handle is deprecated. */ 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\ 879 Return thread object corresponding to thread handle.\n\ 880 This 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\ 884 Return thread object corresponding to thread handle." }, 885 { "architecture", (PyCFunction) infpy_architecture, METH_NOARGS, 886 "architecture () -> gdb.Architecture\n\ 887 Return architecture of this inferior." }, 888 { NULL } 889 }; 890 891 PyTypeObject inferior_object_type = 892 { 893 PyVarObject_HEAD_INIT (NULL, 0) 894 "gdb.Inferior", /* tp_name */ 895 sizeof (inferior_object), /* tp_basicsize */ 896 0, /* tp_itemsize */ 897 infpy_dealloc, /* tp_dealloc */ 898 0, /* tp_print */ 899 0, /* tp_getattr */ 900 0, /* tp_setattr */ 901 0, /* tp_compare */ 902 infpy_repr, /* tp_repr */ 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 */ 912 Py_TPFLAGS_DEFAULT, /* tp_flags */ 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 }; 931