Home | History | Annotate | Line # | Download | only in python
py-xmethods.c revision 1.1.1.7
      1 /* Support for debug methods in Python.
      2 
      3    Copyright (C) 2013-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 #include "arch-utils.h"
     21 #include "extension-priv.h"
     22 #include "objfiles.h"
     23 #include "value.h"
     24 #include "language.h"
     25 
     26 #include "python.h"
     27 #include "python-internal.h"
     28 
     29 static const char enabled_field_name[] = "enabled";
     30 static const char match_method_name[] = "match";
     31 static const char get_arg_types_method_name[] = "get_arg_types";
     32 static const char get_result_type_method_name[] = "get_result_type";
     33 static const char matchers_attr_str[] = "xmethods";
     34 
     35 static PyObject *py_match_method_name = NULL;
     36 static PyObject *py_get_arg_types_method_name = NULL;
     37 
     38 struct python_xmethod_worker : xmethod_worker
     39 {
     40   python_xmethod_worker (PyObject *worker, PyObject *this_type);
     41   ~python_xmethod_worker ();
     42 
     43   DISABLE_COPY_AND_ASSIGN (python_xmethod_worker);
     44 
     45   /* Implementation of xmethod_worker::invoke for Python.  */
     46 
     47   value *invoke (value *obj, gdb::array_view<value *> args) override;
     48 
     49   /* Implementation of xmethod_worker::do_get_arg_types for Python.  */
     50 
     51   ext_lang_rc do_get_arg_types (std::vector<type *> *type_args) override;
     52 
     53   /* Implementation of xmethod_worker::do_get_result_type for Python.
     54 
     55      For backward compatibility with 7.9, which did not support getting the
     56      result type, if the get_result_type operation is not provided by WORKER
     57      then EXT_LANG_RC_OK is returned and NULL is returned in *RESULT_TYPE.  */
     58 
     59   ext_lang_rc do_get_result_type (value *obj, gdb::array_view<value *> args,
     60 				  type **result_type_ptr) override;
     61 
     62 private:
     63 
     64   PyObject *m_py_worker;
     65   PyObject *m_this_type;
     66 };
     67 
     68 python_xmethod_worker::~python_xmethod_worker ()
     69 {
     70   /* We don't do much here, but we still need the GIL.  */
     71   gdbpy_enter enter_py;
     72 
     73   Py_DECREF (m_py_worker);
     74   Py_DECREF (m_this_type);
     75 }
     76 
     77 /* Invoke the "match" method of the MATCHER and return a new reference
     78    to the result.  Returns NULL on error.  */
     79 
     80 static PyObject *
     81 invoke_match_method (PyObject *matcher, PyObject *py_obj_type,
     82 		     const char *xmethod_name)
     83 {
     84   int enabled;
     85 
     86   gdbpy_ref<> enabled_field (PyObject_GetAttrString (matcher,
     87 						     enabled_field_name));
     88   if (enabled_field == NULL)
     89     return NULL;
     90 
     91   enabled = PyObject_IsTrue (enabled_field.get ());
     92   if (enabled == -1)
     93     return NULL;
     94   if (enabled == 0)
     95     {
     96       /* Return 'None' if the matcher is not enabled.  */
     97       Py_RETURN_NONE;
     98     }
     99 
    100   gdbpy_ref<> match_method (PyObject_GetAttrString (matcher,
    101 						    match_method_name));
    102   if (match_method == NULL)
    103     return NULL;
    104 
    105   gdbpy_ref<> py_xmethod_name (PyUnicode_FromString (xmethod_name));
    106   if (py_xmethod_name == NULL)
    107     return NULL;
    108 
    109   return PyObject_CallMethodObjArgs (matcher, py_match_method_name,
    110 				     py_obj_type, py_xmethod_name.get (),
    111 				     NULL);
    112 }
    113 
    114 /* Implementation of get_matching_xmethod_workers for Python.  */
    115 
    116 enum ext_lang_rc
    117 gdbpy_get_matching_xmethod_workers
    118   (const struct extension_language_defn *extlang,
    119    struct type *obj_type, const char *method_name,
    120    std::vector<xmethod_worker_up> *dm_vec)
    121 {
    122   gdb_assert (obj_type != NULL && method_name != NULL);
    123 
    124   gdbpy_enter enter_py;
    125 
    126   gdbpy_ref<> py_type (type_to_type_object (obj_type));
    127   if (py_type == NULL)
    128     {
    129       gdbpy_print_stack ();
    130       return EXT_LANG_RC_ERROR;
    131     }
    132 
    133   /* Create an empty list of debug methods.  */
    134   gdbpy_ref<> py_xmethod_matcher_list (PyList_New (0));
    135   if (py_xmethod_matcher_list == NULL)
    136     {
    137       gdbpy_print_stack ();
    138       return EXT_LANG_RC_ERROR;
    139     }
    140 
    141   /* Gather debug method matchers registered with the object files.
    142      This could be done differently by iterating over each objfile's matcher
    143      list individually, but there's no data yet to show it's needed.  */
    144   for (objfile *objfile : current_program_space->objfiles ())
    145     {
    146       gdbpy_ref<> py_objfile = objfile_to_objfile_object (objfile);
    147 
    148       if (py_objfile == NULL)
    149 	{
    150 	  gdbpy_print_stack ();
    151 	  return EXT_LANG_RC_ERROR;
    152 	}
    153 
    154       gdbpy_ref<> objfile_matchers (objfpy_get_xmethods (py_objfile.get (),
    155 							 NULL));
    156       gdbpy_ref<> temp (PySequence_Concat (py_xmethod_matcher_list.get (),
    157 					   objfile_matchers.get ()));
    158       if (temp == NULL)
    159 	{
    160 	  gdbpy_print_stack ();
    161 	  return EXT_LANG_RC_ERROR;
    162 	}
    163 
    164       py_xmethod_matcher_list = std::move (temp);
    165     }
    166 
    167   /* Gather debug methods matchers registered with the current program
    168      space.  */
    169   gdbpy_ref<> py_progspace = pspace_to_pspace_object (current_program_space);
    170   if (py_progspace != NULL)
    171     {
    172       gdbpy_ref<> pspace_matchers (pspy_get_xmethods (py_progspace.get (),
    173 						      NULL));
    174 
    175       gdbpy_ref<> temp (PySequence_Concat (py_xmethod_matcher_list.get (),
    176 					   pspace_matchers.get ()));
    177       if (temp == NULL)
    178 	{
    179 	  gdbpy_print_stack ();
    180 	  return EXT_LANG_RC_ERROR;
    181 	}
    182 
    183       py_xmethod_matcher_list = std::move (temp);
    184     }
    185   else
    186     {
    187       gdbpy_print_stack ();
    188       return EXT_LANG_RC_ERROR;
    189     }
    190 
    191   /* Gather debug method matchers registered globally.  */
    192   if (gdb_python_module != NULL
    193       && PyObject_HasAttrString (gdb_python_module, matchers_attr_str))
    194     {
    195       gdbpy_ref<> gdb_matchers (PyObject_GetAttrString (gdb_python_module,
    196 							matchers_attr_str));
    197       if (gdb_matchers != NULL)
    198 	{
    199 	  gdbpy_ref<> temp (PySequence_Concat (py_xmethod_matcher_list.get (),
    200 					       gdb_matchers.get ()));
    201 	  if (temp == NULL)
    202 	    {
    203 	      gdbpy_print_stack ();
    204 	      return EXT_LANG_RC_ERROR;
    205 	    }
    206 
    207 	  py_xmethod_matcher_list = std::move (temp);
    208 	}
    209       else
    210 	{
    211 	  gdbpy_print_stack ();
    212 	  return EXT_LANG_RC_ERROR;
    213 	}
    214     }
    215 
    216   gdbpy_ref<> list_iter (PyObject_GetIter (py_xmethod_matcher_list.get ()));
    217   if (list_iter == NULL)
    218     {
    219       gdbpy_print_stack ();
    220       return EXT_LANG_RC_ERROR;
    221     }
    222   while (true)
    223     {
    224       gdbpy_ref<> matcher (PyIter_Next (list_iter.get ()));
    225       if (matcher == NULL)
    226 	{
    227 	  if (PyErr_Occurred ())
    228 	    {
    229 	      gdbpy_print_stack ();
    230 	      return EXT_LANG_RC_ERROR;
    231 	    }
    232 	  break;
    233 	}
    234 
    235       gdbpy_ref<> match_result (invoke_match_method (matcher.get (),
    236 						     py_type.get (),
    237 						     method_name));
    238 
    239       if (match_result == NULL)
    240 	{
    241 	  gdbpy_print_stack ();
    242 	  return EXT_LANG_RC_ERROR;
    243 	}
    244       if (match_result == Py_None)
    245 	; /* This means there was no match.  */
    246       else if (PySequence_Check (match_result.get ()))
    247 	{
    248 	  gdbpy_ref<> iter (PyObject_GetIter (match_result.get ()));
    249 
    250 	  if (iter == NULL)
    251 	    {
    252 	      gdbpy_print_stack ();
    253 	      return EXT_LANG_RC_ERROR;
    254 	    }
    255 	  while (true)
    256 	    {
    257 	      struct xmethod_worker *worker;
    258 
    259 	      gdbpy_ref<> py_worker (PyIter_Next (iter.get ()));
    260 	      if (py_worker == NULL)
    261 		{
    262 		  if (PyErr_Occurred ())
    263 		    {
    264 		      gdbpy_print_stack ();
    265 		      return EXT_LANG_RC_ERROR;
    266 		    }
    267 		  break;
    268 		}
    269 
    270 	      worker = new python_xmethod_worker (py_worker.get (),
    271 						  py_type.get ());
    272 
    273 	      dm_vec->emplace_back (worker);
    274 	    }
    275 	}
    276       else
    277 	{
    278 	  struct xmethod_worker *worker;
    279 
    280 	  worker = new python_xmethod_worker (match_result.get (),
    281 					      py_type.get ());
    282 	  dm_vec->emplace_back (worker);
    283 	}
    284     }
    285 
    286   return EXT_LANG_RC_OK;
    287 }
    288 
    289 /* See declaration.  */
    290 
    291 ext_lang_rc
    292 python_xmethod_worker::do_get_arg_types (std::vector<type *> *arg_types)
    293 {
    294   /* The gdbpy_enter object needs to be placed first, so that it's the last to
    295      be destroyed.  */
    296   gdbpy_enter enter_py;
    297   struct type *obj_type;
    298   int i = 1, arg_count;
    299   gdbpy_ref<> list_iter;
    300 
    301   gdbpy_ref<> get_arg_types_method
    302     (PyObject_GetAttrString (m_py_worker, get_arg_types_method_name));
    303   if (get_arg_types_method == NULL)
    304     {
    305       gdbpy_print_stack ();
    306       return EXT_LANG_RC_ERROR;
    307     }
    308 
    309   gdbpy_ref<> py_argtype_list
    310     (PyObject_CallMethodObjArgs (m_py_worker, py_get_arg_types_method_name,
    311 				 NULL));
    312   if (py_argtype_list == NULL)
    313     {
    314       gdbpy_print_stack ();
    315       return EXT_LANG_RC_ERROR;
    316     }
    317 
    318   if (py_argtype_list == Py_None)
    319     arg_count = 0;
    320   else if (PySequence_Check (py_argtype_list.get ()))
    321     {
    322       arg_count = PySequence_Size (py_argtype_list.get ());
    323       if (arg_count == -1)
    324 	{
    325 	  gdbpy_print_stack ();
    326 	  return EXT_LANG_RC_ERROR;
    327 	}
    328 
    329       list_iter.reset (PyObject_GetIter (py_argtype_list.get ()));
    330       if (list_iter == NULL)
    331 	{
    332 	  gdbpy_print_stack ();
    333 	  return EXT_LANG_RC_ERROR;
    334 	}
    335     }
    336   else
    337     arg_count = 1;
    338 
    339   /* Include the 'this' argument in the size.  */
    340   arg_types->resize (arg_count + 1);
    341   i = 1;
    342   if (list_iter != NULL)
    343     {
    344       while (true)
    345 	{
    346 	  gdbpy_ref<> item (PyIter_Next (list_iter.get ()));
    347 	  if (item == NULL)
    348 	    {
    349 	      if (PyErr_Occurred ())
    350 		{
    351 		  gdbpy_print_stack ();
    352 		  return EXT_LANG_RC_ERROR;
    353 		}
    354 	      break;
    355 	    }
    356 
    357 	  struct type *arg_type = type_object_to_type (item.get ());
    358 	  if (arg_type == NULL)
    359 	    {
    360 	      PyErr_SetString (PyExc_TypeError,
    361 			       _("Arg type returned by the get_arg_types "
    362 				 "method of a debug method worker object is "
    363 				 "not a gdb.Type object."));
    364 	      return EXT_LANG_RC_ERROR;
    365 	    }
    366 
    367 	  (*arg_types)[i] = arg_type;
    368 	  i++;
    369 	}
    370     }
    371   else if (arg_count == 1)
    372     {
    373       /* py_argtype_list is not actually a list but a single gdb.Type
    374 	 object.  */
    375       struct type *arg_type = type_object_to_type (py_argtype_list.get ());
    376 
    377       if (arg_type == NULL)
    378 	{
    379 	  PyErr_SetString (PyExc_TypeError,
    380 			   _("Arg type returned by the get_arg_types method "
    381 			     "of an xmethod worker object is not a gdb.Type "
    382 			     "object."));
    383 	  return EXT_LANG_RC_ERROR;
    384 	}
    385       else
    386 	{
    387 	  (*arg_types)[i] = arg_type;
    388 	  i++;
    389 	}
    390     }
    391 
    392   /* Add the type of 'this' as the first argument.  The 'this' pointer should
    393      be a 'const' value.  Hence, create a 'const' variant of the 'this' pointer
    394      type.  */
    395   obj_type = type_object_to_type (m_this_type);
    396   (*arg_types)[0] = make_cv_type (1, 0, lookup_pointer_type (obj_type),
    397 				  NULL);
    398 
    399   return EXT_LANG_RC_OK;
    400 }
    401 
    402 /* See declaration.  */
    403 
    404 ext_lang_rc
    405 python_xmethod_worker::do_get_result_type (value *obj,
    406 					   gdb::array_view<value *> args,
    407 					   type **result_type_ptr)
    408 {
    409   struct type *obj_type, *this_type;
    410   int i;
    411 
    412   gdbpy_enter enter_py;
    413 
    414   /* First see if there is a get_result_type method.
    415      If not this could be an old xmethod (pre 7.9.1).  */
    416   gdbpy_ref<> get_result_type_method
    417     (PyObject_GetAttrString (m_py_worker, get_result_type_method_name));
    418   if (get_result_type_method == NULL)
    419     {
    420       PyErr_Clear ();
    421       *result_type_ptr = NULL;
    422       return EXT_LANG_RC_OK;
    423     }
    424 
    425   scoped_value_mark free_values;
    426   obj_type = check_typedef (obj->type ());
    427   this_type = check_typedef (type_object_to_type (m_this_type));
    428   if (obj_type->code () == TYPE_CODE_PTR)
    429     {
    430       struct type *this_ptr = lookup_pointer_type (this_type);
    431 
    432       if (!types_equal (obj_type, this_ptr))
    433 	obj = value_cast (this_ptr, obj);
    434     }
    435   else if (TYPE_IS_REFERENCE (obj_type))
    436     {
    437       struct type *this_ref
    438 	= lookup_reference_type (this_type, obj_type->code ());
    439 
    440       if (!types_equal (obj_type, this_ref))
    441 	obj = value_cast (this_ref, obj);
    442     }
    443   else
    444     {
    445       if (!types_equal (obj_type, this_type))
    446 	obj = value_cast (this_type, obj);
    447     }
    448   gdbpy_ref<> py_value_obj (value_to_value_object (obj));
    449   if (py_value_obj == NULL)
    450     {
    451       gdbpy_print_stack ();
    452       return EXT_LANG_RC_ERROR;
    453     }
    454 
    455   gdbpy_ref<> py_arg_tuple (PyTuple_New (args.size () + 1));
    456   if (py_arg_tuple == NULL)
    457     {
    458       gdbpy_print_stack ();
    459       return EXT_LANG_RC_ERROR;
    460     }
    461 
    462   /* PyTuple_SET_ITEM steals the reference of the element, hence the
    463      release.  */
    464   PyTuple_SET_ITEM (py_arg_tuple.get (), 0, py_value_obj.release ());
    465 
    466   for (i = 0; i < args.size (); i++)
    467     {
    468       PyObject *py_value_arg = value_to_value_object (args[i]);
    469 
    470       if (py_value_arg == NULL)
    471 	{
    472 	  gdbpy_print_stack ();
    473 	  return EXT_LANG_RC_ERROR;
    474 	}
    475       PyTuple_SET_ITEM (py_arg_tuple.get (), i + 1, py_value_arg);
    476     }
    477 
    478   gdbpy_ref<> py_result_type
    479     (PyObject_CallObject (get_result_type_method.get (), py_arg_tuple.get ()));
    480   if (py_result_type == NULL)
    481     {
    482       gdbpy_print_stack ();
    483       return EXT_LANG_RC_ERROR;
    484     }
    485 
    486   *result_type_ptr = type_object_to_type (py_result_type.get ());
    487   if (*result_type_ptr == NULL)
    488     {
    489       PyErr_SetString (PyExc_TypeError,
    490 		       _("Type returned by the get_result_type method of an"
    491 			 " xmethod worker object is not a gdb.Type object."));
    492       gdbpy_print_stack ();
    493       return EXT_LANG_RC_ERROR;
    494     }
    495 
    496   return EXT_LANG_RC_OK;
    497 }
    498 
    499 /* See declaration.  */
    500 
    501 struct value *
    502 python_xmethod_worker::invoke (struct value *obj,
    503 			       gdb::array_view<value *> args)
    504 {
    505   gdbpy_enter enter_py;
    506 
    507   int i;
    508   struct type *obj_type, *this_type;
    509   struct value *res = NULL;
    510 
    511   obj_type = check_typedef (obj->type ());
    512   this_type = check_typedef (type_object_to_type (m_this_type));
    513   if (obj_type->code () == TYPE_CODE_PTR)
    514     {
    515       struct type *this_ptr = lookup_pointer_type (this_type);
    516 
    517       if (!types_equal (obj_type, this_ptr))
    518 	obj = value_cast (this_ptr, obj);
    519     }
    520   else if (TYPE_IS_REFERENCE (obj_type))
    521     {
    522       struct type *this_ref
    523 	= lookup_reference_type (this_type, obj_type->code ());
    524 
    525       if (!types_equal (obj_type, this_ref))
    526 	obj = value_cast (this_ref, obj);
    527     }
    528   else
    529     {
    530       if (!types_equal (obj_type, this_type))
    531 	obj = value_cast (this_type, obj);
    532     }
    533   gdbpy_ref<> py_value_obj (value_to_value_object (obj));
    534   if (py_value_obj == NULL)
    535     {
    536       gdbpy_print_stack ();
    537       error (_("Error while executing Python code."));
    538     }
    539 
    540   gdbpy_ref<> py_arg_tuple (PyTuple_New (args.size () + 1));
    541   if (py_arg_tuple == NULL)
    542     {
    543       gdbpy_print_stack ();
    544       error (_("Error while executing Python code."));
    545     }
    546 
    547   /* PyTuple_SET_ITEM steals the reference of the element, hence the
    548      release.  */
    549   PyTuple_SET_ITEM (py_arg_tuple.get (), 0, py_value_obj.release ());
    550 
    551   for (i = 0; i < args.size (); i++)
    552     {
    553       PyObject *py_value_arg = value_to_value_object (args[i]);
    554 
    555       if (py_value_arg == NULL)
    556 	{
    557 	  gdbpy_print_stack ();
    558 	  error (_("Error while executing Python code."));
    559 	}
    560 
    561       PyTuple_SET_ITEM (py_arg_tuple.get (), i + 1, py_value_arg);
    562     }
    563 
    564   gdbpy_ref<> py_result (PyObject_CallObject (m_py_worker,
    565 					      py_arg_tuple.get ()));
    566   if (py_result == NULL)
    567     {
    568       gdbpy_print_stack ();
    569       error (_("Error while executing Python code."));
    570     }
    571 
    572   if (py_result != Py_None)
    573     {
    574       res = convert_value_from_python (py_result.get ());
    575       if (res == NULL)
    576 	{
    577 	  gdbpy_print_stack ();
    578 	  error (_("Error while executing Python code."));
    579 	}
    580     }
    581   else
    582     {
    583       res = value::allocate (lookup_typename (current_language,
    584 					     "void", NULL, 0));
    585     }
    586 
    587   return res;
    588 }
    589 
    590 python_xmethod_worker::python_xmethod_worker (PyObject *py_worker,
    591 					       PyObject *this_type)
    592 : xmethod_worker (&extension_language_python),
    593   m_py_worker (py_worker), m_this_type (this_type)
    594 {
    595   gdb_assert (m_py_worker != NULL && m_this_type != NULL);
    596 
    597   Py_INCREF (py_worker);
    598   Py_INCREF (this_type);
    599 }
    600 
    601 static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
    602 gdbpy_initialize_xmethods (void)
    603 {
    604   py_match_method_name = PyUnicode_FromString (match_method_name);
    605   if (py_match_method_name == NULL)
    606     return -1;
    607 
    608   py_get_arg_types_method_name
    609     = PyUnicode_FromString (get_arg_types_method_name);
    610   if (py_get_arg_types_method_name == NULL)
    611     return -1;
    612 
    613   return 1;
    614 }
    615 
    616 GDBPY_INITIALIZE_FILE (gdbpy_initialize_xmethods);
    617