Home | History | Annotate | Line # | Download | only in python
py-arch.c revision 1.10
      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