1 /* Python interface to program spaces. 2 3 Copyright (C) 2010-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 "python-internal.h" 22 #include "charset.h" 23 #include "progspace.h" 24 #include "objfiles.h" 25 #include "language.h" 26 #include "arch-utils.h" 27 #include "solib.h" 28 #include "block.h" 29 30 struct pspace_object 31 { 32 PyObject_HEAD 33 34 /* The corresponding pspace. */ 35 struct program_space *pspace; 36 37 /* Dictionary holding user-added attributes. 38 This is the __dict__ attribute of the object. */ 39 PyObject *dict; 40 41 /* The pretty-printer list of functions. */ 42 PyObject *printers; 43 44 /* The frame filter list of functions. */ 45 PyObject *frame_filters; 46 47 /* The frame unwinder list. */ 48 PyObject *frame_unwinders; 49 50 /* The type-printer list. */ 51 PyObject *type_printers; 52 53 /* The debug method list. */ 54 PyObject *xmethods; 55 }; 56 57 extern PyTypeObject pspace_object_type 58 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("pspace_object"); 59 60 /* Clear the PSPACE pointer in a Pspace object and remove the reference. */ 61 struct pspace_deleter 62 { 63 void operator() (pspace_object *obj) 64 { 65 /* This is a fiction, but we're in a nasty spot: The pspace is in the 66 process of being deleted, we can't rely on anything in it. Plus 67 this is one time when the current program space and current inferior 68 are not in sync: All inferiors that use PSPACE may no longer exist. 69 We don't need to do much here, and since "there is always an inferior" 70 using target_gdbarch suffices. 71 Note: We cannot call get_current_arch because it may try to access 72 the target, which may involve accessing data in the pspace currently 73 being deleted. */ 74 struct gdbarch *arch = target_gdbarch (); 75 76 gdbpy_enter enter_py (arch); 77 gdbpy_ref<pspace_object> object (obj); 78 object->pspace = NULL; 79 } 80 }; 81 82 static const registry<program_space>::key<pspace_object, pspace_deleter> 83 pspy_pspace_data_key; 84 85 /* Require that PSPACE_OBJ be a valid program space ID. */ 86 #define PSPY_REQUIRE_VALID(pspace_obj) \ 87 do { \ 88 if (pspace_obj->pspace == nullptr) \ 89 { \ 90 PyErr_SetString (PyExc_RuntimeError, \ 91 _("Program space no longer exists.")); \ 92 return NULL; \ 93 } \ 94 } while (0) 95 96 /* An Objfile method which returns the objfile's file name, or None. */ 97 98 static PyObject * 99 pspy_get_filename (PyObject *self, void *closure) 100 { 101 pspace_object *obj = (pspace_object *) self; 102 103 if (obj->pspace) 104 { 105 struct objfile *objfile = obj->pspace->symfile_object_file; 106 107 if (objfile) 108 return (host_string_to_python_string (objfile_name (objfile)) 109 .release ()); 110 } 111 Py_RETURN_NONE; 112 } 113 114 static void 115 pspy_dealloc (PyObject *self) 116 { 117 pspace_object *ps_self = (pspace_object *) self; 118 119 Py_XDECREF (ps_self->dict); 120 Py_XDECREF (ps_self->printers); 121 Py_XDECREF (ps_self->frame_filters); 122 Py_XDECREF (ps_self->frame_unwinders); 123 Py_XDECREF (ps_self->type_printers); 124 Py_XDECREF (ps_self->xmethods); 125 Py_TYPE (self)->tp_free (self); 126 } 127 128 /* Initialize a pspace_object. 129 The result is a boolean indicating success. */ 130 131 static int 132 pspy_initialize (pspace_object *self) 133 { 134 self->pspace = NULL; 135 136 self->dict = PyDict_New (); 137 if (self->dict == NULL) 138 return 0; 139 140 self->printers = PyList_New (0); 141 if (self->printers == NULL) 142 return 0; 143 144 self->frame_filters = PyDict_New (); 145 if (self->frame_filters == NULL) 146 return 0; 147 148 self->frame_unwinders = PyList_New (0); 149 if (self->frame_unwinders == NULL) 150 return 0; 151 152 self->type_printers = PyList_New (0); 153 if (self->type_printers == NULL) 154 return 0; 155 156 self->xmethods = PyList_New (0); 157 if (self->xmethods == NULL) 158 return 0; 159 160 return 1; 161 } 162 163 static PyObject * 164 pspy_new (PyTypeObject *type, PyObject *args, PyObject *keywords) 165 { 166 gdbpy_ref<pspace_object> self ((pspace_object *) type->tp_alloc (type, 0)); 167 168 if (self != NULL) 169 { 170 if (!pspy_initialize (self.get ())) 171 return NULL; 172 } 173 174 return (PyObject *) self.release (); 175 } 176 177 PyObject * 178 pspy_get_printers (PyObject *o, void *ignore) 179 { 180 pspace_object *self = (pspace_object *) o; 181 182 Py_INCREF (self->printers); 183 return self->printers; 184 } 185 186 static int 187 pspy_set_printers (PyObject *o, PyObject *value, void *ignore) 188 { 189 pspace_object *self = (pspace_object *) o; 190 191 if (! value) 192 { 193 PyErr_SetString (PyExc_TypeError, 194 "cannot delete the pretty_printers attribute"); 195 return -1; 196 } 197 198 if (! PyList_Check (value)) 199 { 200 PyErr_SetString (PyExc_TypeError, 201 "the pretty_printers attribute must be a list"); 202 return -1; 203 } 204 205 /* Take care in case the LHS and RHS are related somehow. */ 206 gdbpy_ref<> tmp (self->printers); 207 Py_INCREF (value); 208 self->printers = value; 209 210 return 0; 211 } 212 213 /* Return the Python dictionary attribute containing frame filters for 214 this program space. */ 215 PyObject * 216 pspy_get_frame_filters (PyObject *o, void *ignore) 217 { 218 pspace_object *self = (pspace_object *) o; 219 220 Py_INCREF (self->frame_filters); 221 return self->frame_filters; 222 } 223 224 /* Set this object file's frame filters dictionary to FILTERS. */ 225 static int 226 pspy_set_frame_filters (PyObject *o, PyObject *frame, void *ignore) 227 { 228 pspace_object *self = (pspace_object *) o; 229 230 if (! frame) 231 { 232 PyErr_SetString (PyExc_TypeError, 233 "cannot delete the frame filter attribute"); 234 return -1; 235 } 236 237 if (! PyDict_Check (frame)) 238 { 239 PyErr_SetString (PyExc_TypeError, 240 "the frame filter attribute must be a dictionary"); 241 return -1; 242 } 243 244 /* Take care in case the LHS and RHS are related somehow. */ 245 gdbpy_ref<> tmp (self->frame_filters); 246 Py_INCREF (frame); 247 self->frame_filters = frame; 248 249 return 0; 250 } 251 252 /* Return the list of the frame unwinders for this program space. */ 253 254 PyObject * 255 pspy_get_frame_unwinders (PyObject *o, void *ignore) 256 { 257 pspace_object *self = (pspace_object *) o; 258 259 Py_INCREF (self->frame_unwinders); 260 return self->frame_unwinders; 261 } 262 263 /* Set this program space's list of the unwinders to UNWINDERS. */ 264 265 static int 266 pspy_set_frame_unwinders (PyObject *o, PyObject *unwinders, void *ignore) 267 { 268 pspace_object *self = (pspace_object *) o; 269 270 if (!unwinders) 271 { 272 PyErr_SetString (PyExc_TypeError, 273 "cannot delete the frame unwinders list"); 274 return -1; 275 } 276 277 if (!PyList_Check (unwinders)) 278 { 279 PyErr_SetString (PyExc_TypeError, 280 "the frame unwinders attribute must be a list"); 281 return -1; 282 } 283 284 /* Take care in case the LHS and RHS are related somehow. */ 285 gdbpy_ref<> tmp (self->frame_unwinders); 286 Py_INCREF (unwinders); 287 self->frame_unwinders = unwinders; 288 289 return 0; 290 } 291 292 /* Get the 'type_printers' attribute. */ 293 294 static PyObject * 295 pspy_get_type_printers (PyObject *o, void *ignore) 296 { 297 pspace_object *self = (pspace_object *) o; 298 299 Py_INCREF (self->type_printers); 300 return self->type_printers; 301 } 302 303 /* Get the 'xmethods' attribute. */ 304 305 PyObject * 306 pspy_get_xmethods (PyObject *o, void *ignore) 307 { 308 pspace_object *self = (pspace_object *) o; 309 310 Py_INCREF (self->xmethods); 311 return self->xmethods; 312 } 313 314 /* Set the 'type_printers' attribute. */ 315 316 static int 317 pspy_set_type_printers (PyObject *o, PyObject *value, void *ignore) 318 { 319 pspace_object *self = (pspace_object *) o; 320 321 if (! value) 322 { 323 PyErr_SetString (PyExc_TypeError, 324 "cannot delete the type_printers attribute"); 325 return -1; 326 } 327 328 if (! PyList_Check (value)) 329 { 330 PyErr_SetString (PyExc_TypeError, 331 "the type_printers attribute must be a list"); 332 return -1; 333 } 334 335 /* Take care in case the LHS and RHS are related somehow. */ 336 gdbpy_ref<> tmp (self->type_printers); 337 Py_INCREF (value); 338 self->type_printers = value; 339 340 return 0; 341 } 342 343 /* Implement the objfiles method. */ 344 345 static PyObject * 346 pspy_get_objfiles (PyObject *self_, PyObject *args) 347 { 348 pspace_object *self = (pspace_object *) self_; 349 350 PSPY_REQUIRE_VALID (self); 351 352 gdbpy_ref<> list (PyList_New (0)); 353 if (list == NULL) 354 return NULL; 355 356 if (self->pspace != NULL) 357 { 358 for (objfile *objf : self->pspace->objfiles ()) 359 { 360 gdbpy_ref<> item = objfile_to_objfile_object (objf); 361 362 if (item == nullptr 363 || PyList_Append (list.get (), item.get ()) == -1) 364 return NULL; 365 } 366 } 367 368 return list.release (); 369 } 370 371 /* Implementation of solib_name (Long) -> String. 372 Returns the name of the shared library holding a given address, or None. */ 373 374 static PyObject * 375 pspy_solib_name (PyObject *o, PyObject *args) 376 { 377 CORE_ADDR pc; 378 PyObject *pc_obj; 379 380 pspace_object *self = (pspace_object *) o; 381 382 PSPY_REQUIRE_VALID (self); 383 384 if (!PyArg_ParseTuple (args, "O", &pc_obj)) 385 return NULL; 386 if (get_addr_from_python (pc_obj, &pc) < 0) 387 return nullptr; 388 389 const char *soname = solib_name_from_address (self->pspace, pc); 390 if (soname == nullptr) 391 Py_RETURN_NONE; 392 return host_string_to_python_string (soname).release (); 393 } 394 395 /* Return the innermost lexical block containing the specified pc value, 396 or 0 if there is none. */ 397 static PyObject * 398 pspy_block_for_pc (PyObject *o, PyObject *args) 399 { 400 pspace_object *self = (pspace_object *) o; 401 CORE_ADDR pc; 402 PyObject *pc_obj; 403 const struct block *block = NULL; 404 struct compunit_symtab *cust = NULL; 405 406 PSPY_REQUIRE_VALID (self); 407 408 if (!PyArg_ParseTuple (args, "O", &pc_obj)) 409 return NULL; 410 if (get_addr_from_python (pc_obj, &pc) < 0) 411 return nullptr; 412 413 try 414 { 415 scoped_restore_current_program_space saver; 416 417 set_current_program_space (self->pspace); 418 cust = find_pc_compunit_symtab (pc); 419 420 if (cust != NULL && cust->objfile () != NULL) 421 block = block_for_pc (pc); 422 } 423 catch (const gdb_exception &except) 424 { 425 GDB_PY_HANDLE_EXCEPTION (except); 426 } 427 428 if (cust == NULL || cust->objfile () == NULL) 429 Py_RETURN_NONE; 430 431 if (block) 432 return block_to_block_object (block, cust->objfile ()); 433 434 Py_RETURN_NONE; 435 } 436 437 /* Implementation of the find_pc_line function. 438 Returns the gdb.Symtab_and_line object corresponding to a PC value. */ 439 440 static PyObject * 441 pspy_find_pc_line (PyObject *o, PyObject *args) 442 { 443 CORE_ADDR pc; 444 PyObject *result = NULL; /* init for gcc -Wall */ 445 PyObject *pc_obj; 446 pspace_object *self = (pspace_object *) o; 447 448 PSPY_REQUIRE_VALID (self); 449 450 if (!PyArg_ParseTuple (args, "O", &pc_obj)) 451 return NULL; 452 if (get_addr_from_python (pc_obj, &pc) < 0) 453 return nullptr; 454 455 try 456 { 457 struct symtab_and_line sal; 458 scoped_restore_current_program_space saver; 459 460 set_current_program_space (self->pspace); 461 462 sal = find_pc_line (pc, 0); 463 result = symtab_and_line_to_sal_object (sal); 464 } 465 catch (const gdb_exception &except) 466 { 467 GDB_PY_HANDLE_EXCEPTION (except); 468 } 469 470 return result; 471 } 472 473 /* Implementation of is_valid (self) -> Boolean. 474 Returns True if this program space still exists in GDB. */ 475 476 static PyObject * 477 pspy_is_valid (PyObject *o, PyObject *args) 478 { 479 pspace_object *self = (pspace_object *) o; 480 481 if (self->pspace == NULL) 482 Py_RETURN_FALSE; 483 484 Py_RETURN_TRUE; 485 } 486 487 488 489 /* Return a new reference to the Python object of type Pspace 490 representing PSPACE. If the object has already been created, 491 return it. Otherwise, create it. Return NULL and set the Python 492 error on failure. */ 493 494 gdbpy_ref<> 495 pspace_to_pspace_object (struct program_space *pspace) 496 { 497 PyObject *result = (PyObject *) pspy_pspace_data_key.get (pspace); 498 if (result == NULL) 499 { 500 gdbpy_ref<pspace_object> object 501 ((pspace_object *) PyObject_New (pspace_object, &pspace_object_type)); 502 if (object == NULL) 503 return NULL; 504 if (!pspy_initialize (object.get ())) 505 return NULL; 506 507 object->pspace = pspace; 508 pspy_pspace_data_key.set (pspace, object.get ()); 509 result = (PyObject *) object.release (); 510 } 511 512 return gdbpy_ref<>::new_reference (result); 513 } 514 515 /* See python-internal.h. */ 516 517 struct program_space * 518 progspace_object_to_program_space (PyObject *obj) 519 { 520 gdb_assert (gdbpy_is_progspace (obj)); 521 return ((pspace_object *) obj)->pspace; 522 } 523 524 /* See python-internal.h. */ 525 526 bool 527 gdbpy_is_progspace (PyObject *obj) 528 { 529 return PyObject_TypeCheck (obj, &pspace_object_type); 530 } 531 532 int 533 gdbpy_initialize_pspace (void) 534 { 535 if (PyType_Ready (&pspace_object_type) < 0) 536 return -1; 537 538 return gdb_pymodule_addobject (gdb_module, "Progspace", 539 (PyObject *) &pspace_object_type); 540 } 541 542 543 544 static gdb_PyGetSetDef pspace_getset[] = 545 { 546 { "__dict__", gdb_py_generic_dict, NULL, 547 "The __dict__ for this progspace.", &pspace_object_type }, 548 { "filename", pspy_get_filename, NULL, 549 "The progspace's main filename, or None.", NULL }, 550 { "pretty_printers", pspy_get_printers, pspy_set_printers, 551 "Pretty printers.", NULL }, 552 { "frame_filters", pspy_get_frame_filters, pspy_set_frame_filters, 553 "Frame filters.", NULL }, 554 { "frame_unwinders", pspy_get_frame_unwinders, pspy_set_frame_unwinders, 555 "Frame unwinders.", NULL }, 556 { "type_printers", pspy_get_type_printers, pspy_set_type_printers, 557 "Type printers.", NULL }, 558 { "xmethods", pspy_get_xmethods, NULL, 559 "Debug methods.", NULL }, 560 { NULL } 561 }; 562 563 static PyMethodDef progspace_object_methods[] = 564 { 565 { "objfiles", pspy_get_objfiles, METH_NOARGS, 566 "Return a sequence of objfiles associated to this program space." }, 567 { "solib_name", pspy_solib_name, METH_VARARGS, 568 "solib_name (Long) -> String.\n\ 569 Return the name of the shared library holding a given address, or None." }, 570 { "block_for_pc", pspy_block_for_pc, METH_VARARGS, 571 "Return the block containing the given pc value, or None." }, 572 { "find_pc_line", pspy_find_pc_line, METH_VARARGS, 573 "find_pc_line (pc) -> Symtab_and_line.\n\ 574 Return the gdb.Symtab_and_line object corresponding to the pc value." }, 575 { "is_valid", pspy_is_valid, METH_NOARGS, 576 "is_valid () -> Boolean.\n\ 577 Return true if this program space is valid, false if not." }, 578 { NULL } 579 }; 580 581 PyTypeObject pspace_object_type = 582 { 583 PyVarObject_HEAD_INIT (NULL, 0) 584 "gdb.Progspace", /*tp_name*/ 585 sizeof (pspace_object), /*tp_basicsize*/ 586 0, /*tp_itemsize*/ 587 pspy_dealloc, /*tp_dealloc*/ 588 0, /*tp_print*/ 589 0, /*tp_getattr*/ 590 0, /*tp_setattr*/ 591 0, /*tp_compare*/ 592 0, /*tp_repr*/ 593 0, /*tp_as_number*/ 594 0, /*tp_as_sequence*/ 595 0, /*tp_as_mapping*/ 596 0, /*tp_hash */ 597 0, /*tp_call*/ 598 0, /*tp_str*/ 599 0, /*tp_getattro*/ 600 0, /*tp_setattro*/ 601 0, /*tp_as_buffer*/ 602 Py_TPFLAGS_DEFAULT, /*tp_flags*/ 603 "GDB progspace object", /* tp_doc */ 604 0, /* tp_traverse */ 605 0, /* tp_clear */ 606 0, /* tp_richcompare */ 607 0, /* tp_weaklistoffset */ 608 0, /* tp_iter */ 609 0, /* tp_iternext */ 610 progspace_object_methods, /* tp_methods */ 611 0, /* tp_members */ 612 pspace_getset, /* tp_getset */ 613 0, /* tp_base */ 614 0, /* tp_dict */ 615 0, /* tp_descr_get */ 616 0, /* tp_descr_set */ 617 offsetof (pspace_object, dict), /* tp_dictoffset */ 618 0, /* tp_init */ 619 0, /* tp_alloc */ 620 pspy_new, /* tp_new */ 621 }; 622