GDB (xrefs)
Loading...
Searching...
No Matches
py-xmethods.c
Go to the documentation of this file.
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
30static const char enabled_field_name[] = "enabled";
31static const char match_method_name[] = "match";
32static const char get_arg_types_method_name[] = "get_arg_types";
33static const char get_result_type_method_name[] = "get_result_type";
34static const char matchers_attr_str[] = "xmethods";
35
38
40{
41 python_xmethod_worker (PyObject *worker, PyObject *this_type);
43
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
63private:
64
67};
68
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
81static PyObject *
82invoke_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,
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,
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
117enum ext_lang_rc
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 {
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 {
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. */
146 {
148
149 if (py_objfile == NULL)
150 {
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 {
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. */
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 {
181 return EXT_LANG_RC_ERROR;
182 }
183
184 py_xmethod_matcher_list = std::move (temp);
185 }
186 else
187 {
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,
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 {
205 return EXT_LANG_RC_ERROR;
206 }
207
208 py_xmethod_matcher_list = std::move (temp);
209 }
210 else
211 {
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 {
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 {
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 {
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 {
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 {
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
293python_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 {
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 {
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 {
327 return EXT_LANG_RC_ERROR;
328 }
329
330 list_iter.reset (PyObject_GetIter (py_argtype_list.get ()));
331 if (list_iter == NULL)
332 {
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 {
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
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 scoped_value_mark free_values;
427 obj_type = check_typedef (obj->type ());
429 if (obj_type->code () == TYPE_CODE_PTR)
430 {
431 struct type *this_ptr = lookup_pointer_type (this_type);
432
433 if (!types_equal (obj_type, this_ptr))
434 obj = value_cast (this_ptr, obj);
435 }
436 else if (TYPE_IS_REFERENCE (obj_type))
437 {
438 struct type *this_ref
439 = lookup_reference_type (this_type, obj_type->code ());
440
441 if (!types_equal (obj_type, this_ref))
442 obj = value_cast (this_ref, obj);
443 }
444 else
445 {
446 if (!types_equal (obj_type, this_type))
447 obj = value_cast (this_type, obj);
448 }
449 gdbpy_ref<> py_value_obj (value_to_value_object (obj));
450 if (py_value_obj == NULL)
451 {
453 return EXT_LANG_RC_ERROR;
454 }
455
456 gdbpy_ref<> py_arg_tuple (PyTuple_New (args.size () + 1));
457 if (py_arg_tuple == NULL)
458 {
460 return EXT_LANG_RC_ERROR;
461 }
462
463 /* PyTuple_SET_ITEM steals the reference of the element, hence the
464 release. */
465 PyTuple_SET_ITEM (py_arg_tuple.get (), 0, py_value_obj.release ());
466
467 for (i = 0; i < args.size (); i++)
468 {
469 PyObject *py_value_arg = value_to_value_object (args[i]);
470
471 if (py_value_arg == NULL)
472 {
474 return EXT_LANG_RC_ERROR;
475 }
476 PyTuple_SET_ITEM (py_arg_tuple.get (), i + 1, py_value_arg);
477 }
478
479 gdbpy_ref<> py_result_type
480 (PyObject_CallObject (get_result_type_method.get (), py_arg_tuple.get ()));
481 if (py_result_type == NULL)
482 {
484 return EXT_LANG_RC_ERROR;
485 }
486
487 *result_type_ptr = type_object_to_type (py_result_type.get ());
488 if (*result_type_ptr == NULL)
489 {
490 PyErr_SetString (PyExc_TypeError,
491 _("Type returned by the get_result_type method of an"
492 " xmethod worker object is not a gdb.Type object."));
494 return EXT_LANG_RC_ERROR;
495 }
496
497 return EXT_LANG_RC_OK;
498}
499
500/* See declaration. */
501
502struct value *
504 gdb::array_view<value *> args)
505{
506 gdbpy_enter enter_py;
507
508 int i;
509 struct type *obj_type, *this_type;
510 struct value *res = NULL;
511
512 obj_type = check_typedef (obj->type ());
514 if (obj_type->code () == TYPE_CODE_PTR)
515 {
516 struct type *this_ptr = lookup_pointer_type (this_type);
517
518 if (!types_equal (obj_type, this_ptr))
519 obj = value_cast (this_ptr, obj);
520 }
521 else if (TYPE_IS_REFERENCE (obj_type))
522 {
523 struct type *this_ref
524 = lookup_reference_type (this_type, obj_type->code ());
525
526 if (!types_equal (obj_type, this_ref))
527 obj = value_cast (this_ref, obj);
528 }
529 else
530 {
531 if (!types_equal (obj_type, this_type))
532 obj = value_cast (this_type, obj);
533 }
534 gdbpy_ref<> py_value_obj (value_to_value_object (obj));
535 if (py_value_obj == NULL)
536 {
538 error (_("Error while executing Python code."));
539 }
540
541 gdbpy_ref<> py_arg_tuple (PyTuple_New (args.size () + 1));
542 if (py_arg_tuple == NULL)
543 {
545 error (_("Error while executing Python code."));
546 }
547
548 /* PyTuple_SET_ITEM steals the reference of the element, hence the
549 release. */
550 PyTuple_SET_ITEM (py_arg_tuple.get (), 0, py_value_obj.release ());
551
552 for (i = 0; i < args.size (); i++)
553 {
554 PyObject *py_value_arg = value_to_value_object (args[i]);
555
556 if (py_value_arg == NULL)
557 {
559 error (_("Error while executing Python code."));
560 }
561
562 PyTuple_SET_ITEM (py_arg_tuple.get (), i + 1, py_value_arg);
563 }
564
565 gdbpy_ref<> py_result (PyObject_CallObject (m_py_worker,
566 py_arg_tuple.get ()));
567 if (py_result == NULL)
568 {
570 error (_("Error while executing Python code."));
571 }
572
573 if (py_result != Py_None)
574 {
575 res = convert_value_from_python (py_result.get ());
576 if (res == NULL)
577 {
579 error (_("Error while executing Python code."));
580 }
581 }
582 else
583 {
585 "void", NULL, 0));
586 }
587
588 return res;
589}
590
592 PyObject *this_type)
594 m_py_worker (py_worker), m_this_type (this_type)
595{
596 gdb_assert (m_py_worker != NULL && m_this_type != NULL);
597
598 Py_INCREF (py_worker);
599 Py_INCREF (this_type);
600}
601
604{
605 py_match_method_name = PyUnicode_FromString (match_method_name);
606 if (py_match_method_name == NULL)
607 return -1;
608
610 = PyUnicode_FromString (get_arg_types_method_name);
612 return -1;
613
614 return 1;
615}
616
ext_lang_rc
Definition extension.h:165
@ EXT_LANG_RC_OK
Definition extension.h:167
@ EXT_LANG_RC_ERROR
Definition extension.h:179
struct type * lookup_pointer_type(struct type *type)
Definition gdbtypes.c:430
struct type * lookup_typename(const struct language_defn *language, const char *name, const struct block *block, int noerr)
Definition gdbtypes.c:1651
struct type * make_cv_type(int cnst, int voltl, struct type *type, struct type **typeptr)
Definition gdbtypes.c:740
struct type * lookup_reference_type(struct type *type, enum type_code refcode)
Definition gdbtypes.c:510
bool types_equal(struct type *a, struct type *b)
Definition gdbtypes.c:4114
struct type * check_typedef(struct type *type)
Definition gdbtypes.c:2966
#define TYPE_IS_REFERENCE(t)
Definition gdbtypes.h:139
const struct language_defn * current_language
Definition language.c:82
struct program_space * current_program_space
Definition progspace.c:40
gdbpy_ref objfile_to_objfile_object(struct objfile *objfile)
Definition py-objfile.c:686
PyObject * objfpy_get_xmethods(PyObject *o, void *ignore)
Definition py-objfile.c:383
PyObject * pspy_get_xmethods(PyObject *o, void *ignore)
gdbpy_ref pspace_to_pspace_object(struct program_space *pspace)
gdb::ref_ptr< T, gdbpy_ref_policy< T > > gdbpy_ref
Definition py-ref.h:42
PyObject * type_to_type_object(struct type *type)
Definition py-type.c:1460
struct type * type_object_to_type(PyObject *obj)
Definition py-type.c:1483
struct value * convert_value_from_python(PyObject *obj)
Definition py-value.c:1892
PyObject * value_to_value_object(struct value *val)
Definition py-value.c:1854
static PyObject * invoke_match_method(PyObject *matcher, PyObject *py_obj_type, const char *xmethod_name)
Definition py-xmethods.c:82
static const char get_result_type_method_name[]
Definition py-xmethods.c:33
static const char matchers_attr_str[]
Definition py-xmethods.c:34
enum ext_lang_rc gdbpy_get_matching_xmethod_workers(const struct extension_language_defn *extlang, struct type *obj_type, const char *method_name, std::vector< xmethod_worker_up > *dm_vec)
static const char match_method_name[]
Definition py-xmethods.c:31
static PyObject * py_match_method_name
Definition py-xmethods.c:36
static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_xmethods(void)
static const char enabled_field_name[]
Definition py-xmethods.c:30
static PyObject * py_get_arg_types_method_name
Definition py-xmethods.c:37
static const char get_arg_types_method_name[]
Definition py-xmethods.c:32
void gdbpy_print_stack(void)
#define CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
#define GDBPY_INITIALIZE_FILE(INIT,...)
PyObject * gdb_python_module
const struct extension_language_defn extension_language_python
Definition python.c:179
objfiles_range objfiles()
Definition progspace.h:209
DISABLE_COPY_AND_ASSIGN(python_xmethod_worker)
python_xmethod_worker(PyObject *worker, PyObject *this_type)
ext_lang_rc do_get_arg_types(std::vector< type * > *type_args) override
ext_lang_rc do_get_result_type(value *obj, gdb::array_view< value * > args, type **result_type_ptr) override
value * invoke(value *obj, gdb::array_view< value * > args) override
type_code code() const
Definition gdbtypes.h:956
Definition value.h:130
static struct value * allocate(struct type *type)
Definition value.c:957
struct type * type() const
Definition value.h:180
struct value * value_cast(struct type *type, struct value *arg2)
Definition valops.c:403
int PyObject
Definition varobj.c:41