1 /* Python interface to architecture 2 3 Copyright (C) 2013-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 "gdbarch.h" 22 #include "arch-utils.h" 23 #include "disasm.h" 24 #include "python-internal.h" 25 26 struct arch_object { 27 PyObject_HEAD 28 struct gdbarch *gdbarch; 29 }; 30 31 static const registry<gdbarch>::key<PyObject, gdb::noop_deleter<PyObject>> 32 arch_object_data; 33 34 /* Require a valid Architecture. */ 35 #define ARCHPY_REQUIRE_VALID(arch_obj, arch) \ 36 do { \ 37 arch = arch_object_to_gdbarch (arch_obj); \ 38 if (arch == NULL) \ 39 { \ 40 PyErr_SetString (PyExc_RuntimeError, \ 41 _("Architecture is invalid.")); \ 42 return NULL; \ 43 } \ 44 } while (0) 45 46 extern PyTypeObject arch_object_type 47 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("arch_object"); 48 49 /* Associates an arch_object with GDBARCH as gdbarch_data via the gdbarch 50 post init registration mechanism (gdbarch_data_register_post_init). */ 51 52 static PyObject * 53 arch_object_data_init (struct gdbarch *gdbarch) 54 { 55 arch_object *arch_obj = PyObject_New (arch_object, &arch_object_type); 56 57 if (arch_obj == NULL) 58 return NULL; 59 60 arch_obj->gdbarch = gdbarch; 61 62 return (PyObject *) arch_obj; 63 } 64 65 /* Returns the struct gdbarch value corresponding to the given Python 66 architecture object OBJ, which must be a gdb.Architecture object. */ 67 68 struct gdbarch * 69 arch_object_to_gdbarch (PyObject *obj) 70 { 71 gdb_assert (gdbpy_is_architecture (obj)); 72 73 arch_object *py_arch = (arch_object *) obj; 74 return py_arch->gdbarch; 75 } 76 77 /* See python-internal.h. */ 78 79 bool 80 gdbpy_is_architecture (PyObject *obj) 81 { 82 return PyObject_TypeCheck (obj, &arch_object_type); 83 } 84 85 /* Returns the Python architecture object corresponding to GDBARCH. 86 Returns a new reference to the arch_object associated as data with 87 GDBARCH. */ 88 89 PyObject * 90 gdbarch_to_arch_object (struct gdbarch *gdbarch) 91 { 92 PyObject *new_ref = arch_object_data.get (gdbarch); 93 if (new_ref == nullptr) 94 { 95 new_ref = arch_object_data_init (gdbarch); 96 arch_object_data.set (gdbarch, new_ref); 97 } 98 99 /* new_ref could be NULL if creation failed. */ 100 Py_XINCREF (new_ref); 101 102 return new_ref; 103 } 104 105 /* Implementation of gdb.Architecture.name (self) -> String. 106 Returns the name of the architecture as a string value. */ 107 108 static PyObject * 109 archpy_name (PyObject *self, PyObject *args) 110 { 111 struct gdbarch *gdbarch = NULL; 112 const char *name; 113 114 ARCHPY_REQUIRE_VALID (self, gdbarch); 115 116 name = (gdbarch_bfd_arch_info (gdbarch))->printable_name; 117 return PyUnicode_FromString (name); 118 } 119 120 /* Implementation of 121 gdb.Architecture.disassemble (self, start_pc [, end_pc [,count]]) -> List. 122 Returns a list of instructions in a memory address range. Each instruction 123 in the list is a Python dict object. 124 */ 125 126 static PyObject * 127 archpy_disassemble (PyObject *self, PyObject *args, PyObject *kw) 128 { 129 static const char *keywords[] = { "start_pc", "end_pc", "count", NULL }; 130 CORE_ADDR start = 0, end = 0; 131 CORE_ADDR pc; 132 long count = 0, i; 133 PyObject *start_obj = nullptr, *end_obj = nullptr, *count_obj = nullptr; 134 struct gdbarch *gdbarch = NULL; 135 136 ARCHPY_REQUIRE_VALID (self, gdbarch); 137 138 if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "O|OO", 139 keywords, &start_obj, &end_obj, 140 &count_obj)) 141 return NULL; 142 143 if (get_addr_from_python (start_obj, &start) < 0) 144 return nullptr; 145 146 if (end_obj != nullptr) 147 { 148 if (get_addr_from_python (end_obj, &end) < 0) 149 return nullptr; 150 151 if (end < start) 152 { 153 PyErr_SetString (PyExc_ValueError, 154 _("Argument 'end_pc' should be greater than or " 155 "equal to the argument 'start_pc'.")); 156 157 return NULL; 158 } 159 } 160 if (count_obj) 161 { 162 count = PyLong_AsLong (count_obj); 163 if (PyErr_Occurred () || count < 0) 164 { 165 PyErr_SetString (PyExc_TypeError, 166 _("Argument 'count' should be an non-negative " 167 "integer.")); 168 169 return NULL; 170 } 171 } 172 173 gdbpy_ref<> result_list (PyList_New (0)); 174 if (result_list == NULL) 175 return NULL; 176 177 for (pc = start, i = 0; 178 /* All args are specified. */ 179 (end_obj && count_obj && pc <= end && i < count) 180 /* end_pc is specified, but no count. */ 181 || (end_obj && count_obj == NULL && pc <= end) 182 /* end_pc is not specified, but a count is. */ 183 || (end_obj == NULL && count_obj && i < count) 184 /* Both end_pc and count are not specified. */ 185 || (end_obj == NULL && count_obj == NULL && pc == start);) 186 { 187 int insn_len = 0; 188 gdbpy_ref<> insn_dict (PyDict_New ()); 189 190 if (insn_dict == NULL) 191 return NULL; 192 if (PyList_Append (result_list.get (), insn_dict.get ())) 193 return NULL; /* PyList_Append Sets the exception. */ 194 195 string_file stb; 196 197 try 198 { 199 insn_len = gdb_print_insn (gdbarch, pc, &stb, NULL); 200 } 201 catch (const gdb_exception &except) 202 { 203 gdbpy_convert_exception (except); 204 return NULL; 205 } 206 207 gdbpy_ref<> pc_obj = gdb_py_object_from_ulongest (pc); 208 if (pc_obj == nullptr) 209 return nullptr; 210 211 gdbpy_ref<> asm_obj 212 (PyUnicode_FromString (!stb.empty () ? stb.c_str () : "<unknown>")); 213 if (asm_obj == nullptr) 214 return nullptr; 215 216 gdbpy_ref<> len_obj = gdb_py_object_from_longest (insn_len); 217 if (len_obj == nullptr) 218 return nullptr; 219 220 if (PyDict_SetItemString (insn_dict.get (), "addr", pc_obj.get ()) 221 || PyDict_SetItemString (insn_dict.get (), "asm", asm_obj.get ()) 222 || PyDict_SetItemString (insn_dict.get (), "length", len_obj.get ())) 223 return NULL; 224 225 pc += insn_len; 226 i++; 227 } 228 229 return result_list.release (); 230 } 231 232 /* Implementation of gdb.Architecture.registers (self, reggroup) -> Iterator. 233 Returns an iterator over register descriptors for registers in GROUP 234 within the architecture SELF. */ 235 236 static PyObject * 237 archpy_registers (PyObject *self, PyObject *args, PyObject *kw) 238 { 239 static const char *keywords[] = { "reggroup", NULL }; 240 struct gdbarch *gdbarch = NULL; 241 const char *group_name = NULL; 242 243 /* Parse method arguments. */ 244 if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "|s", keywords, 245 &group_name)) 246 return NULL; 247 248 /* Extract the gdbarch from the self object. */ 249 ARCHPY_REQUIRE_VALID (self, gdbarch); 250 251 return gdbpy_new_register_descriptor_iterator (gdbarch, group_name); 252 } 253 254 /* Implementation of gdb.Architecture.register_groups (self) -> Iterator. 255 Returns an iterator that will give up all valid register groups in the 256 architecture SELF. */ 257 258 static PyObject * 259 archpy_register_groups (PyObject *self, PyObject *args) 260 { 261 struct gdbarch *gdbarch = NULL; 262 263 /* Extract the gdbarch from the self object. */ 264 ARCHPY_REQUIRE_VALID (self, gdbarch); 265 return gdbpy_new_reggroup_iterator (gdbarch); 266 } 267 268 /* Implementation of gdb.integer_type. */ 269 static PyObject * 270 archpy_integer_type (PyObject *self, PyObject *args, PyObject *kw) 271 { 272 static const char *keywords[] = { "size", "signed", NULL }; 273 int size; 274 PyObject *is_signed_obj = nullptr; 275 276 if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "i|O", keywords, 277 &size, &is_signed_obj)) 278 return nullptr; 279 280 /* Assume signed by default. */ 281 bool is_signed = (is_signed_obj == nullptr 282 || PyObject_IsTrue (is_signed_obj)); 283 284 struct gdbarch *gdbarch; 285 ARCHPY_REQUIRE_VALID (self, gdbarch); 286 287 const struct builtin_type *builtins = builtin_type (gdbarch); 288 struct type *type = nullptr; 289 switch (size) 290 { 291 case 0: 292 type = builtins->builtin_int0; 293 break; 294 case 8: 295 type = is_signed ? builtins->builtin_int8 : builtins->builtin_uint8; 296 break; 297 case 16: 298 type = is_signed ? builtins->builtin_int16 : builtins->builtin_uint16; 299 break; 300 case 24: 301 type = is_signed ? builtins->builtin_int24 : builtins->builtin_uint24; 302 break; 303 case 32: 304 type = is_signed ? builtins->builtin_int32 : builtins->builtin_uint32; 305 break; 306 case 64: 307 type = is_signed ? builtins->builtin_int64 : builtins->builtin_uint64; 308 break; 309 case 128: 310 type = is_signed ? builtins->builtin_int128 : builtins->builtin_uint128; 311 break; 312 313 default: 314 PyErr_SetString (PyExc_ValueError, 315 _("no integer type of that size is available")); 316 return nullptr; 317 } 318 319 return type_to_type_object (type); 320 } 321 322 /* Implementation of gdb.architecture_names(). Return a list of all the 323 BFD architecture names that GDB understands. */ 324 325 PyObject * 326 gdbpy_all_architecture_names (PyObject *self, PyObject *args) 327 { 328 gdbpy_ref<> list (PyList_New (0)); 329 if (list == nullptr) 330 return nullptr; 331 332 std::vector<const char *> name_list = gdbarch_printable_names (); 333 for (const char *name : name_list) 334 { 335 gdbpy_ref <> py_name (PyUnicode_FromString (name)); 336 if (py_name == nullptr) 337 return nullptr; 338 if (PyList_Append (list.get (), py_name.get ()) < 0) 339 return nullptr; 340 } 341 342 return list.release (); 343 } 344 345 /* Initializes the Architecture class in the gdb module. */ 346 347 int 348 gdbpy_initialize_arch (void) 349 { 350 arch_object_type.tp_new = PyType_GenericNew; 351 if (PyType_Ready (&arch_object_type) < 0) 352 return -1; 353 354 return gdb_pymodule_addobject (gdb_module, "Architecture", 355 (PyObject *) &arch_object_type); 356 } 357 358 static PyMethodDef arch_object_methods [] = { 359 { "name", archpy_name, METH_NOARGS, 360 "name () -> String.\n\ 361 Return the name of the architecture as a string value." }, 362 { "disassemble", (PyCFunction) archpy_disassemble, 363 METH_VARARGS | METH_KEYWORDS, 364 "disassemble (start_pc [, end_pc [, count]]) -> List.\n\ 365 Return a list of at most COUNT disassembled instructions from START_PC to\n\ 366 END_PC." }, 367 { "integer_type", (PyCFunction) archpy_integer_type, 368 METH_VARARGS | METH_KEYWORDS, 369 "integer_type (size [, signed]) -> type\n\ 370 Return an integer Type corresponding to the given bitsize and signed-ness.\n\ 371 If not specified, the type defaults to signed." }, 372 { "registers", (PyCFunction) archpy_registers, 373 METH_VARARGS | METH_KEYWORDS, 374 "registers ([ group-name ]) -> Iterator.\n\ 375 Return an iterator of register descriptors for the registers in register\n\ 376 group GROUP-NAME." }, 377 { "register_groups", archpy_register_groups, 378 METH_NOARGS, 379 "register_groups () -> Iterator.\n\ 380 Return an iterator over all of the register groups in this architecture." }, 381 {NULL} /* Sentinel */ 382 }; 383 384 PyTypeObject arch_object_type = { 385 PyVarObject_HEAD_INIT (NULL, 0) 386 "gdb.Architecture", /* tp_name */ 387 sizeof (arch_object), /* tp_basicsize */ 388 0, /* tp_itemsize */ 389 0, /* tp_dealloc */ 390 0, /* tp_print */ 391 0, /* tp_getattr */ 392 0, /* tp_setattr */ 393 0, /* tp_compare */ 394 0, /* tp_repr */ 395 0, /* tp_as_number */ 396 0, /* tp_as_sequence */ 397 0, /* tp_as_mapping */ 398 0, /* tp_hash */ 399 0, /* tp_call */ 400 0, /* tp_str */ 401 0, /* tp_getattro */ 402 0, /* tp_setattro */ 403 0, /* tp_as_buffer */ 404 Py_TPFLAGS_DEFAULT, /* tp_flags */ 405 "GDB architecture object", /* tp_doc */ 406 0, /* tp_traverse */ 407 0, /* tp_clear */ 408 0, /* tp_richcompare */ 409 0, /* tp_weaklistoffset */ 410 0, /* tp_iter */ 411 0, /* tp_iternext */ 412 arch_object_methods, /* tp_methods */ 413 0, /* tp_members */ 414 0, /* tp_getset */ 415 0, /* tp_base */ 416 0, /* tp_dict */ 417 0, /* tp_descr_get */ 418 0, /* tp_descr_set */ 419 0, /* tp_dictoffset */ 420 0, /* tp_init */ 421 0, /* tp_alloc */ 422 }; 423