]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/python/py-finishbreakpoint.c
gdb: remove target_gdbarch
[thirdparty/binutils-gdb.git] / gdb / python / py-finishbreakpoint.c
CommitLineData
cc72b2a2
KP
1/* Python interface to finish breakpoints
2
213516ef 3 Copyright (C) 2011-2023 Free Software Foundation, Inc.
cc72b2a2
KP
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
21
22#include "defs.h"
ef0f16cc 23#include "top.h"
cc72b2a2
KP
24#include "python-internal.h"
25#include "breakpoint.h"
26#include "frame.h"
27#include "gdbthread.h"
28#include "arch-utils.h"
29#include "language.h"
76727919 30#include "observable.h"
cc72b2a2 31#include "inferior.h"
6a3a010b 32#include "block.h"
f00aae0f 33#include "location.h"
cc72b2a2 34
cc72b2a2 35/* Function that is called when a Python finish bp is found out of scope. */
a121b7c1 36static const char outofscope_func[] = "out_of_scope";
cc72b2a2
KP
37
38/* struct implementing the gdb.FinishBreakpoint object by extending
39 the gdb.Breakpoint class. */
40struct finish_breakpoint_object
41{
42 /* gdb.Breakpoint base class. */
4cb0213d 43 gdbpy_breakpoint_object py_bp;
e6b36367
LS
44
45 /* gdb.Symbol object of the function finished by this breakpoint.
46
47 nullptr if no debug information was available or return type was VOID. */
48 PyObject *func_symbol;
49
50 /* gdb.Value object of the function finished by this breakpoint.
51
52 nullptr if no debug information was available or return type was VOID. */
6a3a010b 53 PyObject *function_value;
e6b36367 54
cc72b2a2
KP
55 /* When stopped at this FinishBreakpoint, gdb.Value object returned by
56 the function; Py_None if the value is not computable; NULL if GDB is
57 not stopped at a FinishBreakpoint. */
58 PyObject *return_value;
64760036
TV
59
60 /* The initiating frame for this operation, used to decide when we have
61 left this frame. */
62 struct frame_id initiating_frame;
cc72b2a2
KP
63};
64
e36122e9 65extern PyTypeObject finish_breakpoint_object_type
62eec1a5
TT
66 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("finish_breakpoint_object");
67
cc72b2a2
KP
68/* Python function to get the 'return_value' attribute of
69 FinishBreakpoint. */
70
71static PyObject *
72bpfinishpy_get_returnvalue (PyObject *self, void *closure)
73{
74 struct finish_breakpoint_object *self_finishbp =
75 (struct finish_breakpoint_object *) self;
76
77 if (!self_finishbp->return_value)
78 Py_RETURN_NONE;
79
80 Py_INCREF (self_finishbp->return_value);
81 return self_finishbp->return_value;
82}
83
84/* Deallocate FinishBreakpoint object. */
85
86static void
87bpfinishpy_dealloc (PyObject *self)
88{
89 struct finish_breakpoint_object *self_bpfinish =
dda83cd7 90 (struct finish_breakpoint_object *) self;
cc72b2a2 91
e6b36367 92 Py_XDECREF (self_bpfinish->func_symbol);
6a3a010b 93 Py_XDECREF (self_bpfinish->function_value);
cc72b2a2 94 Py_XDECREF (self_bpfinish->return_value);
2e953aca 95 Py_TYPE (self)->tp_free (self);
cc72b2a2
KP
96}
97
d0d41b77
JS
98/* Triggered when gdbpy_breakpoint_cond_says_stop is about to execute the `stop'
99 callback of the gdb.FinishBreakpoint object BP_OBJ. Will compute and cache
100 the `return_value', if possible. */
cc72b2a2
KP
101
102void
4cb0213d 103bpfinishpy_pre_stop_hook (struct gdbpy_breakpoint_object *bp_obj)
cc72b2a2
KP
104{
105 struct finish_breakpoint_object *self_finishbp =
dda83cd7 106 (struct finish_breakpoint_object *) bp_obj;
cc72b2a2
KP
107
108 /* Can compute return_value only once. */
109 gdb_assert (!self_finishbp->return_value);
110
e6b36367 111 if (self_finishbp->func_symbol == nullptr)
cc72b2a2
KP
112 return;
113
a70b8144 114 try
cc72b2a2 115 {
f3d3bbbc
TT
116 scoped_value_mark free_values;
117
e6b36367
LS
118 struct symbol *func_symbol =
119 symbol_object_to_symbol (self_finishbp->func_symbol);
6a3a010b 120 struct value *function =
dda83cd7 121 value_object_to_value (self_finishbp->function_value);
e6b36367
LS
122 struct value *ret =
123 get_return_value (func_symbol, function);
cc72b2a2
KP
124
125 if (ret)
dda83cd7
SM
126 {
127 self_finishbp->return_value = value_to_value_object (ret);
128 if (!self_finishbp->return_value)
129 gdbpy_print_stack ();
130 }
cc72b2a2 131 else
dda83cd7
SM
132 {
133 Py_INCREF (Py_None);
134 self_finishbp->return_value = Py_None;
135 }
cc72b2a2 136 }
230d2906 137 catch (const gdb_exception &except)
cc72b2a2
KP
138 {
139 gdbpy_convert_exception (except);
140 gdbpy_print_stack ();
141 }
142}
143
d0d41b77
JS
144/* Triggered when gdbpy_breakpoint_cond_says_stop has triggered the `stop'
145 callback of the gdb.FinishBreakpoint object BP_OBJ. */
cc72b2a2
KP
146
147void
4cb0213d 148bpfinishpy_post_stop_hook (struct gdbpy_breakpoint_object *bp_obj)
cc72b2a2 149{
cc72b2a2 150
a70b8144 151 try
cc72b2a2
KP
152 {
153 /* Can't delete it here, but it will be removed at the next stop. */
154 disable_breakpoint (bp_obj->bp);
6533cbee 155 bp_obj->bp->disposition = disp_del_at_next_stop;
cc72b2a2 156 }
230d2906 157 catch (const gdb_exception &except)
cc72b2a2
KP
158 {
159 gdbpy_convert_exception (except);
160 gdbpy_print_stack ();
161 }
162}
163
164/* Python function to create a new breakpoint. */
165
166static int
167bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
168{
2adadf51 169 static const char *keywords[] = { "frame", "internal", NULL };
cc72b2a2
KP
170 struct finish_breakpoint_object *self_bpfinish =
171 (struct finish_breakpoint_object *) self;
cc72b2a2
KP
172 PyObject *frame_obj = NULL;
173 int thread;
bd2b40ac
TT
174 frame_info_ptr frame = NULL; /* init for gcc -Wall */
175 frame_info_ptr prev_frame = NULL;
cc72b2a2
KP
176 struct frame_id frame_id;
177 PyObject *internal = NULL;
178 int internal_bp = 0;
a06efdd6 179 CORE_ADDR pc;
cc72b2a2 180
2adadf51
PA
181 if (!gdb_PyArg_ParseTupleAndKeywords (args, kwargs, "|OO", keywords,
182 &frame_obj, &internal))
cc72b2a2
KP
183 return -1;
184
a70b8144 185 try
cc72b2a2 186 {
dd5fa3e7
TT
187 /* Default frame to newest frame if necessary. */
188 if (frame_obj == NULL)
189 frame = get_current_frame ();
cc72b2a2 190 else
dd5fa3e7
TT
191 frame = frame_object_to_frame_info (frame_obj);
192
193 if (frame == NULL)
194 {
256458bc 195 PyErr_SetString (PyExc_ValueError,
dd5fa3e7
TT
196 _("Invalid ID for the `frame' object."));
197 }
198 else
199 {
200 prev_frame = get_prev_frame (frame);
201 if (prev_frame == 0)
202 {
203 PyErr_SetString (PyExc_ValueError,
204 _("\"FinishBreakpoint\" not "
205 "meaningful in the outermost "
206 "frame."));
207 }
208 else if (get_frame_type (prev_frame) == DUMMY_FRAME)
209 {
210 PyErr_SetString (PyExc_ValueError,
211 _("\"FinishBreakpoint\" cannot "
212 "be set on a dummy frame."));
213 }
214 else
04ea6b63 215 frame_id = get_frame_id (prev_frame);
dd5fa3e7 216 }
cc72b2a2 217 }
230d2906 218 catch (const gdb_exception &except)
cc72b2a2
KP
219 {
220 gdbpy_convert_exception (except);
221 return -1;
222 }
492d29ea
PA
223
224 if (PyErr_Occurred ())
cc72b2a2
KP
225 return -1;
226
00431a78 227 if (inferior_ptid == null_ptid)
cc72b2a2
KP
228 {
229 PyErr_SetString (PyExc_ValueError,
dda83cd7 230 _("No thread currently selected."));
cc72b2a2
KP
231 return -1;
232 }
233
00431a78
PA
234 thread = inferior_thread ()->global_num;
235
cc72b2a2
KP
236 if (internal)
237 {
238 internal_bp = PyObject_IsTrue (internal);
256458bc 239 if (internal_bp == -1)
dda83cd7
SM
240 {
241 PyErr_SetString (PyExc_ValueError,
242 _("The value of `internal' must be a boolean."));
243 return -1;
244 }
cc72b2a2
KP
245 }
246
247 /* Find the function we will return from. */
e6b36367
LS
248 self_bpfinish->func_symbol = nullptr;
249 self_bpfinish->function_value = nullptr;
cc72b2a2 250
a70b8144 251 try
cc72b2a2
KP
252 {
253 if (get_frame_pc_if_available (frame, &pc))
dda83cd7 254 {
e6b36367
LS
255 struct symbol *function = find_pc_function (pc);
256 if (function != nullptr)
dda83cd7
SM
257 {
258 struct type *ret_type =
27710edb 259 check_typedef (function->type ()->target_type ());
cc72b2a2 260
dda83cd7
SM
261 /* Remember only non-void return types. */
262 if (ret_type->code () != TYPE_CODE_VOID)
263 {
f3d3bbbc
TT
264 scoped_value_mark free_values;
265
dda83cd7 266 /* Ignore Python errors at this stage. */
e6b36367
LS
267 value *func_value = read_var_value (function, NULL, frame);
268 self_bpfinish->function_value
269 = value_to_value_object (func_value);
dda83cd7 270 PyErr_Clear ();
e6b36367
LS
271
272 self_bpfinish->func_symbol
273 = symbol_to_symbol_object (function);
dda83cd7
SM
274 PyErr_Clear ();
275 }
276 }
277 }
cc72b2a2 278 }
b940a061
KB
279 catch (const gdb_exception_forced_quit &except)
280 {
281 quit_force (NULL, 0);
282 }
230d2906 283 catch (const gdb_exception &except)
7556d4a4
PA
284 {
285 /* Just swallow. Either the return type or the function value
286 remain NULL. */
287 }
288
e6b36367
LS
289 if (self_bpfinish->func_symbol == nullptr
290 || self_bpfinish->function_value == nullptr)
cc72b2a2
KP
291 {
292 /* Won't be able to compute return value. */
e6b36367 293 Py_XDECREF (self_bpfinish->func_symbol);
6a3a010b 294 Py_XDECREF (self_bpfinish->function_value);
cc72b2a2 295
e6b36367
LS
296 self_bpfinish->func_symbol = nullptr;
297 self_bpfinish->function_value = nullptr;
cc72b2a2
KP
298 }
299
300 bppy_pending_object = &self_bpfinish->py_bp;
301 bppy_pending_object->number = -1;
302 bppy_pending_object->bp = NULL;
303
a70b8144 304 try
cc72b2a2
KP
305 {
306 /* Set a breakpoint on the return address. */
264f9890
PA
307 location_spec_up locspec
308 = new_address_location_spec (get_frame_pc (prev_frame), NULL, 0);
1da5d0e6 309 create_breakpoint (gdbpy_enter::get_gdbarch (),
b080fe54 310 locspec.get (), NULL, thread, -1, NULL, false,
dda83cd7
SM
311 0,
312 1 /*temp_flag*/,
313 bp_breakpoint,
314 0,
315 AUTO_BOOLEAN_TRUE,
74421c0b 316 &code_breakpoint_ops,
dda83cd7 317 0, 1, internal_bp, 0);
cc72b2a2 318 }
230d2906 319 catch (const gdb_exception &except)
492d29ea
PA
320 {
321 GDB_PY_SET_HANDLE_EXCEPTION (except);
322 }
256458bc 323
cc72b2a2
KP
324 self_bpfinish->py_bp.bp->frame_id = frame_id;
325 self_bpfinish->py_bp.is_finish_bp = 1;
64760036 326 self_bpfinish->initiating_frame = get_frame_id (frame);
256458bc 327
cc72b2a2
KP
328 /* Bind the breakpoint with the current program space. */
329 self_bpfinish->py_bp.bp->pspace = current_program_space;
330
331 return 0;
cc72b2a2
KP
332}
333
334/* Called when GDB notices that the finish breakpoint BP_OBJ is out of
335 the current callstack. Triggers the method OUT_OF_SCOPE if implemented,
336 then delete the breakpoint. */
337
338static void
339bpfinishpy_out_of_scope (struct finish_breakpoint_object *bpfinish_obj)
340{
4cb0213d 341 gdbpy_breakpoint_object *bp_obj = (gdbpy_breakpoint_object *) bpfinish_obj;
cc72b2a2
KP
342 PyObject *py_obj = (PyObject *) bp_obj;
343
344 if (bpfinish_obj->py_bp.bp->enable_state == bp_enabled
345 && PyObject_HasAttrString (py_obj, outofscope_func))
346 {
7780f186
TT
347 gdbpy_ref<> meth_result (PyObject_CallMethod (py_obj, outofscope_func,
348 NULL));
18868860
TT
349 if (meth_result == NULL)
350 gdbpy_print_stack ();
cc72b2a2 351 }
cc72b2a2
KP
352}
353
354/* Callback for `bpfinishpy_detect_out_scope'. Triggers Python's
2968b79f
AB
355 `B->out_of_scope' function if B is a FinishBreakpoint out of its scope.
356
357 When DELETE_BP is true then breakpoint B will be deleted if B is a
358 FinishBreakpoint and it is out of scope, otherwise B will not be
359 deleted. */
cc72b2a2 360
240edef6 361static void
95da600f 362bpfinishpy_detect_out_scope_cb (struct breakpoint *b,
2968b79f
AB
363 struct breakpoint *bp_stopped,
364 bool delete_bp)
cc72b2a2 365{
cc72b2a2 366 PyObject *py_bp = (PyObject *) b->py_bp_object;
256458bc 367
cc72b2a2
KP
368 /* Trigger out_of_scope if this is a FinishBreakpoint and its frame is
369 not anymore in the current callstack. */
370 if (py_bp != NULL && b->py_bp_object->is_finish_bp)
371 {
372 struct finish_breakpoint_object *finish_bp =
dda83cd7 373 (struct finish_breakpoint_object *) py_bp;
cc72b2a2
KP
374
375 /* Check scope if not currently stopped at the FinishBreakpoint. */
376 if (b != bp_stopped)
dda83cd7
SM
377 {
378 try
379 {
64760036
TV
380 struct frame_id initiating_frame = finish_bp->initiating_frame;
381
dda83cd7
SM
382 if (b->pspace == current_inferior ()->pspace
383 && (!target_has_registers ()
64760036 384 || frame_find_by_id (initiating_frame) == NULL))
2968b79f
AB
385 {
386 bpfinishpy_out_of_scope (finish_bp);
387 if (delete_bp)
388 delete_breakpoint (finish_bp->py_bp.bp);
389 }
dda83cd7
SM
390 }
391 catch (const gdb_exception &except)
392 {
393 gdbpy_convert_exception (except);
394 gdbpy_print_stack ();
395 }
396 }
cc72b2a2 397 }
cc72b2a2
KP
398}
399
2968b79f
AB
400/* Called when gdbpy_breakpoint_deleted is about to delete a breakpoint. A
401 chance to trigger the out_of_scope callback (if appropriate) for the
402 associated Python object. */
403
404void
405bpfinishpy_pre_delete_hook (struct gdbpy_breakpoint_object *bp_obj)
406{
407 breakpoint *bp = bp_obj->bp;
408 bpfinishpy_detect_out_scope_cb (bp, nullptr, false);
409}
410
cc72b2a2
KP
411/* Attached to `stop' notifications, check if the execution has run
412 out of the scope of any FinishBreakpoint before it has been hit. */
413
414static void
313f3b21 415bpfinishpy_handle_stop (struct bpstat *bs, int print_frame)
cc72b2a2 416{
1da5d0e6 417 gdbpy_enter enter_py;
cc72b2a2 418
a1decfc1 419 for (breakpoint &bp : all_breakpoints_safe ())
2968b79f 420 bpfinishpy_detect_out_scope_cb
a1decfc1 421 (&bp, bs == NULL ? NULL : bs->breakpoint_at, true);
cc72b2a2
KP
422}
423
424/* Attached to `exit' notifications, triggers all the necessary out of
425 scope notifications. */
426
427static void
428bpfinishpy_handle_exit (struct inferior *inf)
429{
99d9c3b9 430 gdbpy_enter enter_py (current_inferior ()->arch ());
cc72b2a2 431
a1decfc1
SM
432 for (breakpoint &bp : all_breakpoints_safe ())
433 bpfinishpy_detect_out_scope_cb (&bp, nullptr, true);
cc72b2a2
KP
434}
435
436/* Initialize the Python finish breakpoint code. */
437
3965bff5 438static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
cc72b2a2
KP
439gdbpy_initialize_finishbreakpoints (void)
440{
8a3b1706
AB
441 if (!gdbpy_breakpoint_init_breakpoint_type ())
442 return -1;
443
cc72b2a2 444 if (PyType_Ready (&finish_breakpoint_object_type) < 0)
999633ed 445 return -1;
256458bc 446
aa36459a
TT
447 if (gdb_pymodule_addobject (gdb_module, "FinishBreakpoint",
448 (PyObject *) &finish_breakpoint_object_type) < 0)
999633ed 449 return -1;
256458bc 450
c90e7d63
SM
451 gdb::observers::normal_stop.attach (bpfinishpy_handle_stop,
452 "py-finishbreakpoint");
453 gdb::observers::inferior_exit.attach (bpfinishpy_handle_exit,
454 "py-finishbreakpoint");
999633ed
TT
455
456 return 0;
cc72b2a2
KP
457}
458
3965bff5
AB
459GDBPY_INITIALIZE_FILE (gdbpy_initialize_finishbreakpoints);
460
461\f
462
0d1f4ceb 463static gdb_PyGetSetDef finish_breakpoint_object_getset[] = {
cc72b2a2
KP
464 { "return_value", bpfinishpy_get_returnvalue, NULL,
465 "gdb.Value object representing the return value, if any. \
466None otherwise.", NULL },
467 { NULL } /* Sentinel. */
468};
469
e36122e9 470PyTypeObject finish_breakpoint_object_type =
cc72b2a2 471{
9a27f2c6 472 PyVarObject_HEAD_INIT (NULL, 0)
cc72b2a2
KP
473 "gdb.FinishBreakpoint", /*tp_name*/
474 sizeof (struct finish_breakpoint_object), /*tp_basicsize*/
475 0, /*tp_itemsize*/
476 bpfinishpy_dealloc, /*tp_dealloc*/
477 0, /*tp_print*/
478 0, /*tp_getattr*/
479 0, /*tp_setattr*/
480 0, /*tp_compare*/
481 0, /*tp_repr*/
482 0, /*tp_as_number*/
483 0, /*tp_as_sequence*/
484 0, /*tp_as_mapping*/
485 0, /*tp_hash */
486 0, /*tp_call*/
487 0, /*tp_str*/
488 0, /*tp_getattro*/
489 0, /*tp_setattro */
490 0, /*tp_as_buffer*/
491 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
492 "GDB finish breakpoint object", /* tp_doc */
493 0, /* tp_traverse */
494 0, /* tp_clear */
495 0, /* tp_richcompare */
496 0, /* tp_weaklistoffset */
497 0, /* tp_iter */
498 0, /* tp_iternext */
499 0, /* tp_methods */
500 0, /* tp_members */
501 finish_breakpoint_object_getset,/* tp_getset */
502 &breakpoint_object_type, /* tp_base */
503 0, /* tp_dict */
504 0, /* tp_descr_get */
505 0, /* tp_descr_set */
506 0, /* tp_dictoffset */
507 bpfinishpy_init, /* tp_init */
508 0, /* tp_alloc */
509 0 /* tp_new */
510};