1 /* MI Command Set for GDB, the GNU debugger. 2 3 Copyright (C) 2019-2024 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 /* GDB/MI commands implemented in Python. */ 21 22 #include "python-internal.h" 23 #include "arch-utils.h" 24 #include "charset.h" 25 #include "language.h" 26 #include "mi/mi-cmds.h" 27 #include "mi/mi-parse.h" 28 #include "cli/cli-cmds.h" 29 #include <string> 30 31 /* Debugging of Python MI commands. */ 32 33 static bool pymicmd_debug; 34 35 /* Implementation of "show debug py-micmd". */ 36 37 static void 38 show_pymicmd_debug (struct ui_file *file, int from_tty, 39 struct cmd_list_element *c, const char *value) 40 { 41 gdb_printf (file, _("Python MI command debugging is %s.\n"), value); 42 } 43 44 /* Print a "py-micmd" debug statement. */ 45 46 #define pymicmd_debug_printf(fmt, ...) \ 47 debug_prefixed_printf_cond (pymicmd_debug, "py-micmd", fmt, ##__VA_ARGS__) 48 49 /* Print a "py-micmd" enter/exit debug statements. */ 50 51 #define PYMICMD_SCOPED_DEBUG_ENTER_EXIT \ 52 scoped_debug_enter_exit (pymicmd_debug, "py-micmd") 53 54 struct mi_command_py; 55 56 /* Representation of a Python gdb.MICommand object. */ 57 58 struct micmdpy_object 59 { 60 PyObject_HEAD 61 62 /* The object representing this command in the MI command table. This 63 pointer can be nullptr if the command is not currently installed into 64 the MI command table (see gdb.MICommand.installed property). */ 65 struct mi_command_py *mi_command; 66 67 /* The string representing the name of this command, without the leading 68 dash. This string is never nullptr once the Python object has been 69 initialised. 70 71 The memory for this string was allocated with malloc, and needs to be 72 deallocated with free when the Python object is deallocated. 73 74 When the MI_COMMAND field is not nullptr, then the mi_command_py 75 object's name will point back to this string. */ 76 char *mi_command_name; 77 }; 78 79 /* The MI command implemented in Python. */ 80 81 struct mi_command_py : public mi_command 82 { 83 /* Constructs a new mi_command_py object. NAME is command name without 84 leading dash. OBJECT is a reference to a Python object implementing 85 the command. This object must inherit from gdb.MICommand and must 86 implement the invoke method. */ 87 88 mi_command_py (const char *name, micmdpy_object *object) 89 : mi_command (name, nullptr), 90 m_pyobj (gdbpy_ref<micmdpy_object>::new_reference (object)) 91 { 92 pymicmd_debug_printf ("this = %p", this); 93 m_pyobj->mi_command = this; 94 } 95 96 ~mi_command_py () 97 { 98 /* The Python object representing a MI command contains a pointer back 99 to this c++ object. We can safely set this pointer back to nullptr 100 now, to indicate the Python object no longer references a valid c++ 101 object. 102 103 However, the Python object also holds the storage for our name 104 string. We can't clear that here as our parent's destructor might 105 still want to reference that string. Instead we rely on the Python 106 object deallocator to free that memory, and reset the pointer. */ 107 m_pyobj->mi_command = nullptr; 108 109 pymicmd_debug_printf ("this = %p", this); 110 }; 111 112 /* Validate that CMD_OBJ, a non-nullptr pointer, is installed into the MI 113 command table correctly. This function looks up the command in the MI 114 command table and checks that the object we get back references 115 CMD_OBJ. This function is only intended for calling within a 116 gdb_assert. This function performs many assertions internally, and 117 then always returns true. */ 118 static void validate_installation (micmdpy_object *cmd_obj); 119 120 /* Update M_PYOBJ to NEW_PYOBJ. The pointer from M_PYOBJ that points 121 back to this object is swapped with the pointer in NEW_PYOBJ, which 122 must be nullptr, so that NEW_PYOBJ now points back to this object. 123 Additionally our parent's name string is stored in M_PYOBJ, so we 124 swap the name string with NEW_PYOBJ. 125 126 Before this call M_PYOBJ is the Python object representing this MI 127 command object. After this call has completed, NEW_PYOBJ now 128 represents this MI command object. */ 129 void swap_python_object (micmdpy_object *new_pyobj) 130 { 131 /* Current object has a backlink, new object doesn't have a backlink. */ 132 gdb_assert (m_pyobj->mi_command != nullptr); 133 gdb_assert (new_pyobj->mi_command == nullptr); 134 135 /* Clear the current M_PYOBJ's backlink, set NEW_PYOBJ's backlink. */ 136 std::swap (new_pyobj->mi_command, m_pyobj->mi_command); 137 138 /* Both object have names. */ 139 gdb_assert (m_pyobj->mi_command_name != nullptr); 140 gdb_assert (new_pyobj->mi_command_name != nullptr); 141 142 /* mi_command::m_name is the string owned by the current object. */ 143 gdb_assert (m_pyobj->mi_command_name == this->name ()); 144 145 /* The name in mi_command::m_name is owned by the current object. Rather 146 than changing the value of mi_command::m_name (which is not accessible 147 from here) to point to the name owned by the new object, swap the names 148 of the two objects, since we know they are identical strings. */ 149 gdb_assert (strcmp (new_pyobj->mi_command_name, 150 m_pyobj->mi_command_name) == 0); 151 std::swap (new_pyobj->mi_command_name, m_pyobj->mi_command_name); 152 153 /* Take a reference to the new object, drop the reference to the current 154 object. */ 155 m_pyobj = gdbpy_ref<micmdpy_object>::new_reference (new_pyobj); 156 } 157 158 /* Called when the MI command is invoked. */ 159 virtual void invoke(struct mi_parse *parse) const override; 160 161 private: 162 /* The Python object representing this MI command. */ 163 gdbpy_ref<micmdpy_object> m_pyobj; 164 }; 165 166 using mi_command_py_up = std::unique_ptr<mi_command_py>; 167 168 extern PyTypeObject micmdpy_object_type 169 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("micmdpy_object"); 170 171 /* Holds a Python object containing the string 'invoke'. */ 172 173 static PyObject *invoke_cst; 174 175 /* Called when the MI command is invoked. PARSE contains the parsed 176 command line arguments from the user. */ 177 178 void 179 mi_command_py::invoke (struct mi_parse *parse) const 180 { 181 PYMICMD_SCOPED_DEBUG_ENTER_EXIT; 182 183 pymicmd_debug_printf ("this = %p, name = %s", this, name ()); 184 185 parse->parse_argv (); 186 187 if (parse->argv == nullptr) 188 error (_("Problem parsing arguments: %s %s"), parse->command.get (), 189 parse->args ()); 190 191 192 gdbpy_enter enter_py; 193 194 /* Place all the arguments into a list which we pass as a single argument 195 to the MI command's invoke method. */ 196 gdbpy_ref<> argobj (PyList_New (parse->argc)); 197 if (argobj == nullptr) 198 gdbpy_handle_exception (); 199 200 for (int i = 0; i < parse->argc; ++i) 201 { 202 gdbpy_ref<> str (PyUnicode_Decode (parse->argv[i], 203 strlen (parse->argv[i]), 204 host_charset (), nullptr)); 205 if (PyList_SetItem (argobj.get (), i, str.release ()) < 0) 206 gdbpy_handle_exception (); 207 } 208 209 gdb_assert (this->m_pyobj != nullptr); 210 gdb_assert (PyErr_Occurred () == nullptr); 211 gdbpy_ref<> results 212 (PyObject_CallMethodObjArgs ((PyObject *) this->m_pyobj.get (), invoke_cst, 213 argobj.get (), nullptr)); 214 if (results == nullptr) 215 gdbpy_handle_exception (); 216 217 if (results != Py_None) 218 { 219 /* At the top-level, the results must be a dictionary. */ 220 if (!PyDict_Check (results.get ())) 221 gdbpy_error (_("Result from invoke must be a dictionary")); 222 serialize_mi_results (results.get ()); 223 } 224 } 225 226 /* See declaration above. */ 227 228 void 229 mi_command_py::validate_installation (micmdpy_object *cmd_obj) 230 { 231 gdb_assert (cmd_obj != nullptr); 232 mi_command_py *cmd = cmd_obj->mi_command; 233 gdb_assert (cmd != nullptr); 234 const char *name = cmd_obj->mi_command_name; 235 gdb_assert (name != nullptr); 236 gdb_assert (name == cmd->name ()); 237 mi_command *mi_cmd = mi_cmd_lookup (name); 238 gdb_assert (mi_cmd == cmd); 239 gdb_assert (cmd->m_pyobj == cmd_obj); 240 } 241 242 /* Return CMD as an mi_command_py if it is a Python MI command, else 243 nullptr. */ 244 245 static mi_command_py * 246 as_mi_command_py (mi_command *cmd) 247 { 248 return dynamic_cast<mi_command_py *> (cmd); 249 } 250 251 /* Uninstall OBJ, making the MI command represented by OBJ unavailable for 252 use by the user. On success 0 is returned, otherwise -1 is returned 253 and a Python exception will be set. */ 254 255 static int 256 micmdpy_uninstall_command (micmdpy_object *obj) 257 { 258 PYMICMD_SCOPED_DEBUG_ENTER_EXIT; 259 260 gdb_assert (obj->mi_command != nullptr); 261 gdb_assert (obj->mi_command_name != nullptr); 262 263 pymicmd_debug_printf ("name = %s", obj->mi_command_name); 264 265 /* Remove the command from the internal MI table of commands. This will 266 cause the mi_command_py object to be deleted, which will clear the 267 backlink in OBJ. */ 268 bool removed = remove_mi_cmd_entry (obj->mi_command->name ()); 269 gdb_assert (removed); 270 gdb_assert (obj->mi_command == nullptr); 271 272 return 0; 273 } 274 275 /* Install OBJ as a usable MI command. Return 0 on success, and -1 on 276 error, in which case, a Python error will have been set. 277 278 After successful completion the command name associated with OBJ will 279 be installed in the MI command table (so it can be found if the user 280 enters that command name), additionally, OBJ will have been added to 281 the gdb._mi_commands dictionary (using the command name as its key), 282 this will ensure that OBJ remains live even if the user gives up all 283 references. */ 284 285 static int 286 micmdpy_install_command (micmdpy_object *obj) 287 { 288 PYMICMD_SCOPED_DEBUG_ENTER_EXIT; 289 290 gdb_assert (obj->mi_command == nullptr); 291 gdb_assert (obj->mi_command_name != nullptr); 292 293 pymicmd_debug_printf ("name = %s", obj->mi_command_name); 294 295 /* Look up this command name in MI_COMMANDS, a command with this name may 296 already exist. */ 297 mi_command *cmd = mi_cmd_lookup (obj->mi_command_name); 298 mi_command_py *cmd_py = as_mi_command_py (cmd); 299 300 if (cmd != nullptr && cmd_py == nullptr) 301 { 302 /* There is already an MI command registered with that name, and it's not 303 a Python one. Forbid replacing a non-Python MI command. */ 304 PyErr_SetString (PyExc_RuntimeError, 305 _("unable to add command, name is already in use")); 306 return -1; 307 } 308 309 if (cmd_py != nullptr) 310 { 311 /* There is already a Python MI command registered with that name, swap 312 in the new gdb.MICommand implementation. */ 313 cmd_py->swap_python_object (obj); 314 } 315 else 316 { 317 /* There's no MI command registered with that name at all, create one. */ 318 mi_command_py_up mi_cmd (new mi_command_py (obj->mi_command_name, obj)); 319 320 /* Add the command to the gdb internal MI command table. */ 321 bool result = insert_mi_cmd_entry (std::move (mi_cmd)); 322 gdb_assert (result); 323 } 324 325 return 0; 326 } 327 328 /* Implement gdb.MICommand.__init__. The init method takes the name of 329 the MI command as the first argument, which must be a string, starting 330 with a single dash. */ 331 332 static int 333 micmdpy_init (PyObject *self, PyObject *args, PyObject *kwargs) 334 { 335 PYMICMD_SCOPED_DEBUG_ENTER_EXIT; 336 337 micmdpy_object *cmd = (micmdpy_object *) self; 338 339 static const char *keywords[] = { "name", nullptr }; 340 const char *name; 341 342 if (!gdb_PyArg_ParseTupleAndKeywords (args, kwargs, "s", keywords, 343 &name)) 344 return -1; 345 346 /* Validate command name */ 347 const int name_len = strlen (name); 348 if (name_len == 0) 349 { 350 PyErr_SetString (PyExc_ValueError, _("MI command name is empty.")); 351 return -1; 352 } 353 else if ((name_len < 2) || (name[0] != '-') || !isalnum (name[1])) 354 { 355 PyErr_SetString (PyExc_ValueError, 356 _("MI command name does not start with '-'" 357 " followed by at least one letter or digit.")); 358 return -1; 359 } 360 else 361 { 362 for (int i = 2; i < name_len; i++) 363 { 364 if (!isalnum (name[i]) && name[i] != '-') 365 { 366 PyErr_Format 367 (PyExc_ValueError, 368 _("MI command name contains invalid character: %c."), 369 name[i]); 370 return -1; 371 } 372 } 373 374 /* Skip over the leading dash. For the rest of this function the 375 dash is not important. */ 376 ++name; 377 } 378 379 /* If this object already has a name set, then this object has been 380 initialized before. We handle this case a little differently. */ 381 if (cmd->mi_command_name != nullptr) 382 { 383 /* First, we don't allow the user to change the MI command name. 384 Supporting this would be tricky as we would need to delete the 385 mi_command_py from the MI command table, however, the user might 386 be trying to perform this reinitialization from within the very 387 command we're about to delete... it all gets very messy. 388 389 So, for now at least, we don't allow this. This doesn't seem like 390 an excessive restriction. */ 391 if (strcmp (cmd->mi_command_name, name) != 0) 392 { 393 PyErr_SetString 394 (PyExc_ValueError, 395 _("can't reinitialize object with a different command name")); 396 return -1; 397 } 398 399 /* If there's already an object registered with the MI command table, 400 then we're done. That object must be a mi_command_py, which 401 should reference back to this micmdpy_object. */ 402 if (cmd->mi_command != nullptr) 403 { 404 mi_command_py::validate_installation (cmd); 405 return 0; 406 } 407 } 408 else 409 cmd->mi_command_name = xstrdup (name); 410 411 /* Now we can install this mi_command_py in the MI command table. */ 412 return micmdpy_install_command (cmd); 413 } 414 415 /* Called when a gdb.MICommand object is deallocated. */ 416 417 static void 418 micmdpy_dealloc (PyObject *obj) 419 { 420 PYMICMD_SCOPED_DEBUG_ENTER_EXIT; 421 422 micmdpy_object *cmd = (micmdpy_object *) obj; 423 424 /* If the Python object failed to initialize, then the name field might 425 be nullptr. */ 426 pymicmd_debug_printf ("obj = %p, name = %s", cmd, 427 (cmd->mi_command_name == nullptr 428 ? "(null)" : cmd->mi_command_name)); 429 430 /* As the mi_command_py object holds a reference to the micmdpy_object, 431 the only way the dealloc function can be called is if the mi_command_py 432 object has been deleted, in which case the following assert will 433 hold. */ 434 gdb_assert (cmd->mi_command == nullptr); 435 436 /* Free the memory that holds the command name. */ 437 xfree (cmd->mi_command_name); 438 cmd->mi_command_name = nullptr; 439 440 /* Finally, free the memory for this Python object. */ 441 Py_TYPE (obj)->tp_free (obj); 442 } 443 444 /* Python initialization for the MI commands components. */ 445 446 static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION 447 gdbpy_initialize_micommands () 448 { 449 micmdpy_object_type.tp_new = PyType_GenericNew; 450 if (PyType_Ready (&micmdpy_object_type) < 0) 451 return -1; 452 453 if (gdb_pymodule_addobject (gdb_module, "MICommand", 454 (PyObject *) &micmdpy_object_type) 455 < 0) 456 return -1; 457 458 invoke_cst = PyUnicode_FromString ("invoke"); 459 if (invoke_cst == nullptr) 460 return -1; 461 462 return 0; 463 } 464 465 /* Cleanup just before GDB shuts down the Python interpreter. */ 466 467 static void 468 gdbpy_finalize_micommands () 469 { 470 /* mi_command_py objects hold references to micmdpy_object objects. They must 471 be dropped before the Python interpreter is finalized. Do so by removing 472 those MI command entries, thus deleting the mi_command_py objects. */ 473 remove_mi_cmd_entries ([] (mi_command *cmd) 474 { 475 return as_mi_command_py (cmd) != nullptr; 476 }); 477 } 478 479 /* Get the gdb.MICommand.name attribute, returns a string, the name of this 480 MI command. */ 481 482 static PyObject * 483 micmdpy_get_name (PyObject *self, void *closure) 484 { 485 struct micmdpy_object *micmd_obj = (struct micmdpy_object *) self; 486 487 gdb_assert (micmd_obj->mi_command_name != nullptr); 488 std::string name_str = string_printf ("-%s", micmd_obj->mi_command_name); 489 return PyUnicode_FromString (name_str.c_str ()); 490 } 491 492 /* Get the gdb.MICommand.installed property. Returns true if this MI 493 command is installed into the MI command table, otherwise returns 494 false. */ 495 496 static PyObject * 497 micmdpy_get_installed (PyObject *self, void *closure) 498 { 499 struct micmdpy_object *micmd_obj = (struct micmdpy_object *) self; 500 501 if (micmd_obj->mi_command == nullptr) 502 Py_RETURN_FALSE; 503 Py_RETURN_TRUE; 504 } 505 506 /* Set the gdb.MICommand.installed property. The property can be set to 507 either true or false. Setting the property to true will cause the 508 command to be installed into the MI command table (if it isn't 509 already), while setting this property to false will cause the command 510 to be removed from the MI command table (if it is present). */ 511 512 static int 513 micmdpy_set_installed (PyObject *self, PyObject *newvalue, void *closure) 514 { 515 struct micmdpy_object *micmd_obj = (struct micmdpy_object *) self; 516 517 bool installed_p = PyObject_IsTrue (newvalue); 518 if (installed_p == (micmd_obj->mi_command != nullptr)) 519 return 0; 520 521 if (installed_p) 522 return micmdpy_install_command (micmd_obj); 523 else 524 return micmdpy_uninstall_command (micmd_obj); 525 } 526 527 /* The gdb.MICommand properties. */ 528 529 static gdb_PyGetSetDef micmdpy_object_getset[] = { 530 { "name", micmdpy_get_name, nullptr, "The command's name.", nullptr }, 531 { "installed", micmdpy_get_installed, micmdpy_set_installed, 532 "Is this command installed for use.", nullptr }, 533 { nullptr } /* Sentinel. */ 534 }; 535 536 /* The gdb.MICommand descriptor. */ 537 538 PyTypeObject micmdpy_object_type = { 539 PyVarObject_HEAD_INIT (nullptr, 0) "gdb.MICommand", /*tp_name */ 540 sizeof (micmdpy_object), /*tp_basicsize */ 541 0, /*tp_itemsize */ 542 micmdpy_dealloc, /*tp_dealloc */ 543 0, /*tp_print */ 544 0, /*tp_getattr */ 545 0, /*tp_setattr */ 546 0, /*tp_compare */ 547 0, /*tp_repr */ 548 0, /*tp_as_number */ 549 0, /*tp_as_sequence */ 550 0, /*tp_as_mapping */ 551 0, /*tp_hash */ 552 0, /*tp_call */ 553 0, /*tp_str */ 554 0, /*tp_getattro */ 555 0, /*tp_setattro */ 556 0, /*tp_as_buffer */ 557 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags */ 558 "GDB mi-command object", /* tp_doc */ 559 0, /* tp_traverse */ 560 0, /* tp_clear */ 561 0, /* tp_richcompare */ 562 0, /* tp_weaklistoffset */ 563 0, /* tp_iter */ 564 0, /* tp_iternext */ 565 0, /* tp_methods */ 566 0, /* tp_members */ 567 micmdpy_object_getset, /* tp_getset */ 568 0, /* tp_base */ 569 0, /* tp_dict */ 570 0, /* tp_descr_get */ 571 0, /* tp_descr_set */ 572 0, /* tp_dictoffset */ 573 micmdpy_init, /* tp_init */ 574 0, /* tp_alloc */ 575 }; 576 577 void _initialize_py_micmd (); 578 void 579 _initialize_py_micmd () 580 { 581 add_setshow_boolean_cmd 582 ("py-micmd", class_maintenance, &pymicmd_debug, 583 _("Set Python micmd debugging."), 584 _("Show Python micmd debugging."), 585 _("When on, Python micmd debugging is enabled."), 586 nullptr, 587 show_pymicmd_debug, 588 &setdebuglist, &showdebuglist); 589 } 590 591 GDBPY_INITIALIZE_FILE (gdbpy_initialize_micommands, gdbpy_finalize_micommands); 592