xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/python/py-xmethods.c (revision 8b657b0747480f8989760d71343d6dd33f8d4cf9)
1 /* Support for debug methods in Python.
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 "arch-utils.h"
22 #include "extension-priv.h"
23 #include "objfiles.h"
24 #include "value.h"
25 #include "language.h"
26 
27 #include "python.h"
28 #include "python-internal.h"
29 
30 static const char enabled_field_name[] = "enabled";
31 static const char match_method_name[] = "match";
32 static const char get_arg_types_method_name[] = "get_arg_types";
33 static const char get_result_type_method_name[] = "get_result_type";
34 static const char matchers_attr_str[] = "xmethods";
35 
36 static PyObject *py_match_method_name = NULL;
37 static PyObject *py_get_arg_types_method_name = NULL;
38 
39 struct python_xmethod_worker : xmethod_worker
40 {
41   python_xmethod_worker (PyObject *worker, PyObject *this_type);
42   ~python_xmethod_worker ();
43 
44   DISABLE_COPY_AND_ASSIGN (python_xmethod_worker);
45 
46   /* Implementation of xmethod_worker::invoke for Python.  */
47 
48   value *invoke (value *obj, gdb::array_view<value *> args) override;
49 
50   /* Implementation of xmethod_worker::do_get_arg_types for Python.  */
51 
52   ext_lang_rc do_get_arg_types (std::vector<type *> *type_args) override;
53 
54   /* Implementation of xmethod_worker::do_get_result_type for Python.
55 
56      For backward compatibility with 7.9, which did not support getting the
57      result type, if the get_result_type operation is not provided by WORKER
58      then EXT_LANG_RC_OK is returned and NULL is returned in *RESULT_TYPE.  */
59 
60   ext_lang_rc do_get_result_type (value *obj, gdb::array_view<value *> args,
61 				  type **result_type_ptr) override;
62 
63 private:
64 
65   PyObject *m_py_worker;
66   PyObject *m_this_type;
67 };
68 
69 python_xmethod_worker::~python_xmethod_worker ()
70 {
71   /* We don't do much here, but we still need the GIL.  */
72   gdbpy_enter enter_py;
73 
74   Py_DECREF (m_py_worker);
75   Py_DECREF (m_this_type);
76 }
77 
78 /* Invoke the "match" method of the MATCHER and return a new reference
79    to the result.  Returns NULL on error.  */
80 
81 static PyObject *
82 invoke_match_method (PyObject *matcher, PyObject *py_obj_type,
83 		     const char *xmethod_name)
84 {
85   int enabled;
86 
87   gdbpy_ref<> enabled_field (PyObject_GetAttrString (matcher,
88 						     enabled_field_name));
89   if (enabled_field == NULL)
90     return NULL;
91 
92   enabled = PyObject_IsTrue (enabled_field.get ());
93   if (enabled == -1)
94     return NULL;
95   if (enabled == 0)
96     {
97       /* Return 'None' if the matcher is not enabled.  */
98       Py_RETURN_NONE;
99     }
100 
101   gdbpy_ref<> match_method (PyObject_GetAttrString (matcher,
102 						    match_method_name));
103   if (match_method == NULL)
104     return NULL;
105 
106   gdbpy_ref<> py_xmethod_name (PyUnicode_FromString (xmethod_name));
107   if (py_xmethod_name == NULL)
108     return NULL;
109 
110   return PyObject_CallMethodObjArgs (matcher, py_match_method_name,
111 				     py_obj_type, py_xmethod_name.get (),
112 				     NULL);
113 }
114 
115 /* Implementation of get_matching_xmethod_workers for Python.  */
116 
117 enum ext_lang_rc
118 gdbpy_get_matching_xmethod_workers
119   (const struct extension_language_defn *extlang,
120    struct type *obj_type, const char *method_name,
121    std::vector<xmethod_worker_up> *dm_vec)
122 {
123   gdb_assert (obj_type != NULL && method_name != NULL);
124 
125   gdbpy_enter enter_py;
126 
127   gdbpy_ref<> py_type (type_to_type_object (obj_type));
128   if (py_type == NULL)
129     {
130       gdbpy_print_stack ();
131       return EXT_LANG_RC_ERROR;
132     }
133 
134   /* Create an empty list of debug methods.  */
135   gdbpy_ref<> py_xmethod_matcher_list (PyList_New (0));
136   if (py_xmethod_matcher_list == NULL)
137     {
138       gdbpy_print_stack ();
139       return EXT_LANG_RC_ERROR;
140     }
141 
142   /* Gather debug method matchers registered with the object files.
143      This could be done differently by iterating over each objfile's matcher
144      list individually, but there's no data yet to show it's needed.  */
145   for (objfile *objfile : current_program_space->objfiles ())
146     {
147       gdbpy_ref<> py_objfile = objfile_to_objfile_object (objfile);
148 
149       if (py_objfile == NULL)
150 	{
151 	  gdbpy_print_stack ();
152 	  return EXT_LANG_RC_ERROR;
153 	}
154 
155       gdbpy_ref<> objfile_matchers (objfpy_get_xmethods (py_objfile.get (),
156 							 NULL));
157       gdbpy_ref<> temp (PySequence_Concat (py_xmethod_matcher_list.get (),
158 					   objfile_matchers.get ()));
159       if (temp == NULL)
160 	{
161 	  gdbpy_print_stack ();
162 	  return EXT_LANG_RC_ERROR;
163 	}
164 
165       py_xmethod_matcher_list = std::move (temp);
166     }
167 
168   /* Gather debug methods matchers registered with the current program
169      space.  */
170   gdbpy_ref<> py_progspace = pspace_to_pspace_object (current_program_space);
171   if (py_progspace != NULL)
172     {
173       gdbpy_ref<> pspace_matchers (pspy_get_xmethods (py_progspace.get (),
174 						      NULL));
175 
176       gdbpy_ref<> temp (PySequence_Concat (py_xmethod_matcher_list.get (),
177 					   pspace_matchers.get ()));
178       if (temp == NULL)
179 	{
180 	  gdbpy_print_stack ();
181 	  return EXT_LANG_RC_ERROR;
182 	}
183 
184       py_xmethod_matcher_list = std::move (temp);
185     }
186   else
187     {
188       gdbpy_print_stack ();
189       return EXT_LANG_RC_ERROR;
190     }
191 
192   /* Gather debug method matchers registered globally.  */
193   if (gdb_python_module != NULL
194       && PyObject_HasAttrString (gdb_python_module, matchers_attr_str))
195     {
196       gdbpy_ref<> gdb_matchers (PyObject_GetAttrString (gdb_python_module,
197 							matchers_attr_str));
198       if (gdb_matchers != NULL)
199 	{
200 	  gdbpy_ref<> temp (PySequence_Concat (py_xmethod_matcher_list.get (),
201 					       gdb_matchers.get ()));
202 	  if (temp == NULL)
203 	    {
204 	      gdbpy_print_stack ();
205 	      return EXT_LANG_RC_ERROR;
206 	    }
207 
208 	  py_xmethod_matcher_list = std::move (temp);
209 	}
210       else
211 	{
212 	  gdbpy_print_stack ();
213 	  return EXT_LANG_RC_ERROR;
214 	}
215     }
216 
217   gdbpy_ref<> list_iter (PyObject_GetIter (py_xmethod_matcher_list.get ()));
218   if (list_iter == NULL)
219     {
220       gdbpy_print_stack ();
221       return EXT_LANG_RC_ERROR;
222     }
223   while (true)
224     {
225       gdbpy_ref<> matcher (PyIter_Next (list_iter.get ()));
226       if (matcher == NULL)
227 	{
228 	  if (PyErr_Occurred ())
229 	    {
230 	      gdbpy_print_stack ();
231 	      return EXT_LANG_RC_ERROR;
232 	    }
233 	  break;
234 	}
235 
236       gdbpy_ref<> match_result (invoke_match_method (matcher.get (),
237 						     py_type.get (),
238 						     method_name));
239 
240       if (match_result == NULL)
241 	{
242 	  gdbpy_print_stack ();
243 	  return EXT_LANG_RC_ERROR;
244 	}
245       if (match_result == Py_None)
246 	; /* This means there was no match.  */
247       else if (PySequence_Check (match_result.get ()))
248 	{
249 	  gdbpy_ref<> iter (PyObject_GetIter (match_result.get ()));
250 
251 	  if (iter == NULL)
252 	    {
253 	      gdbpy_print_stack ();
254 	      return EXT_LANG_RC_ERROR;
255 	    }
256 	  while (true)
257 	    {
258 	      struct xmethod_worker *worker;
259 
260 	      gdbpy_ref<> py_worker (PyIter_Next (iter.get ()));
261 	      if (py_worker == NULL)
262 		{
263 		  if (PyErr_Occurred ())
264 		    {
265 		      gdbpy_print_stack ();
266 		      return EXT_LANG_RC_ERROR;
267 		    }
268 		  break;
269 		}
270 
271 	      worker = new python_xmethod_worker (py_worker.get (),
272 						  py_type.get ());
273 
274 	      dm_vec->emplace_back (worker);
275 	    }
276 	}
277       else
278 	{
279 	  struct xmethod_worker *worker;
280 
281 	  worker = new python_xmethod_worker (match_result.get (),
282 					      py_type.get ());
283 	  dm_vec->emplace_back (worker);
284 	}
285     }
286 
287   return EXT_LANG_RC_OK;
288 }
289 
290 /* See declaration.  */
291 
292 ext_lang_rc
293 python_xmethod_worker::do_get_arg_types (std::vector<type *> *arg_types)
294 {
295   /* The gdbpy_enter object needs to be placed first, so that it's the last to
296      be destroyed.  */
297   gdbpy_enter enter_py;
298   struct type *obj_type;
299   int i = 1, arg_count;
300   gdbpy_ref<> list_iter;
301 
302   gdbpy_ref<> get_arg_types_method
303     (PyObject_GetAttrString (m_py_worker, get_arg_types_method_name));
304   if (get_arg_types_method == NULL)
305     {
306       gdbpy_print_stack ();
307       return EXT_LANG_RC_ERROR;
308     }
309 
310   gdbpy_ref<> py_argtype_list
311     (PyObject_CallMethodObjArgs (m_py_worker, py_get_arg_types_method_name,
312 				 NULL));
313   if (py_argtype_list == NULL)
314     {
315       gdbpy_print_stack ();
316       return EXT_LANG_RC_ERROR;
317     }
318 
319   if (py_argtype_list == Py_None)
320     arg_count = 0;
321   else if (PySequence_Check (py_argtype_list.get ()))
322     {
323       arg_count = PySequence_Size (py_argtype_list.get ());
324       if (arg_count == -1)
325 	{
326 	  gdbpy_print_stack ();
327 	  return EXT_LANG_RC_ERROR;
328 	}
329 
330       list_iter.reset (PyObject_GetIter (py_argtype_list.get ()));
331       if (list_iter == NULL)
332 	{
333 	  gdbpy_print_stack ();
334 	  return EXT_LANG_RC_ERROR;
335 	}
336     }
337   else
338     arg_count = 1;
339 
340   /* Include the 'this' argument in the size.  */
341   arg_types->resize (arg_count + 1);
342   i = 1;
343   if (list_iter != NULL)
344     {
345       while (true)
346 	{
347 	  gdbpy_ref<> item (PyIter_Next (list_iter.get ()));
348 	  if (item == NULL)
349 	    {
350 	      if (PyErr_Occurred ())
351 		{
352 		  gdbpy_print_stack ();
353 		  return EXT_LANG_RC_ERROR;
354 		}
355 	      break;
356 	    }
357 
358 	  struct type *arg_type = type_object_to_type (item.get ());
359 	  if (arg_type == NULL)
360 	    {
361 	      PyErr_SetString (PyExc_TypeError,
362 			       _("Arg type returned by the get_arg_types "
363 				 "method of a debug method worker object is "
364 				 "not a gdb.Type object."));
365 	      return EXT_LANG_RC_ERROR;
366 	    }
367 
368 	  (*arg_types)[i] = arg_type;
369 	  i++;
370 	}
371     }
372   else if (arg_count == 1)
373     {
374       /* py_argtype_list is not actually a list but a single gdb.Type
375 	 object.  */
376       struct type *arg_type = type_object_to_type (py_argtype_list.get ());
377 
378       if (arg_type == NULL)
379 	{
380 	  PyErr_SetString (PyExc_TypeError,
381 			   _("Arg type returned by the get_arg_types method "
382 			     "of an xmethod worker object is not a gdb.Type "
383 			     "object."));
384 	  return EXT_LANG_RC_ERROR;
385 	}
386       else
387 	{
388 	  (*arg_types)[i] = arg_type;
389 	  i++;
390 	}
391     }
392 
393   /* Add the type of 'this' as the first argument.  The 'this' pointer should
394      be a 'const' value.  Hence, create a 'const' variant of the 'this' pointer
395      type.  */
396   obj_type = type_object_to_type (m_this_type);
397   (*arg_types)[0] = make_cv_type (1, 0, lookup_pointer_type (obj_type),
398 				  NULL);
399 
400   return EXT_LANG_RC_OK;
401 }
402 
403 /* See declaration.  */
404 
405 ext_lang_rc
406 python_xmethod_worker::do_get_result_type (value *obj,
407 					   gdb::array_view<value *> args,
408 					   type **result_type_ptr)
409 {
410   struct type *obj_type, *this_type;
411   int i;
412 
413   gdbpy_enter enter_py;
414 
415   /* First see if there is a get_result_type method.
416      If not this could be an old xmethod (pre 7.9.1).  */
417   gdbpy_ref<> get_result_type_method
418     (PyObject_GetAttrString (m_py_worker, get_result_type_method_name));
419   if (get_result_type_method == NULL)
420     {
421       PyErr_Clear ();
422       *result_type_ptr = NULL;
423       return EXT_LANG_RC_OK;
424     }
425 
426   obj_type = check_typedef (value_type (obj));
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 (value_type (obj));
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 = allocate_value (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 int
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