System notice: In light of the Debian OpenSSL security issue we've regenerated the server keys. See this thread for instructions and the new key fingerprints.

Commit 097ec191782b2a15fe24c544ad4dc9b7d8cc3850

Expose frames to Python.

Commit diff

gdb/Makefile.in

 
264264 python.o \
265265 python-breakpoint.o \
266266 python-cmd.o \
267 python-frame.o \
267268 python-hooks.o \
268269 python-value.o
269270SUBDIR_PYTHON_SRCS = \
270271 python/python.c \
271272 python/breakpoint.c \
272273 python/cmd.c \
274 python/frame.c \
273275 python/hooks.c \
274276 python/value.c
275277SUBDIR_PYTHON_DEPS =
34193419
34203420python.o: $(srcdir)/python/python.c $(defs_h) $(python_h) \
34213421 $(command_h) $(libiberty_h) $(cli_decode_h) $(charset_h) $(top_h) \
3422 $(exceptions_h) $(python_internal_h) $(version_h)
3422 $(exceptions_h) $(python_internal_h) $(version_h) $(solib_h)
34233423 $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) $(srcdir)/python/python.c
34243424python-breakpoint.o: $(srcdir)/python/breakpoint.c $(defs_h) $(python_h) \
34253425 $(value_h) $(exceptions_h) $(python_internal_h) $(charset_h) \
34313431 $(gdbcmd_h) $(cli_decode_h)
34323432 $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
34333433 $(srcdir)/python/cmd.c -o python-cmd.o
3434python-frame.o: $(srcdir)/python/frame.c $(defs_h) $(python_h) \
3435 $(python_internal_h) $(frame_h) $(exceptions_h) $(symtab_h) \
3436 $(charset_h) $(stack_h) $(value_h)
3437 $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
3438 $(srcdir)/python/frame.c -o python-frame.o
34343439python-hooks.o: $(srcdir)/python/hooks.c $(defs_h) $(cli_decode_h) \
34353440 $(charset_h) $(gdb_events_h) $(python_h) $(python_internal_h)
34363441 $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
toggle raw diff

gdb/python/frame.c

 
1/* Python interface to stack frames
2
3 Copyright (C) 2008 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 "charset.h"
22#include "frame.h"
23#include "exceptions.h"
24#include "symtab.h"
25#include "stack.h"
26#include "value.h"
27#include "python-internal.h"
28
29typedef struct {
30 PyObject_HEAD
31 struct frame_id frame_id;
32 struct gdbarch *gdbarch;
33
34 /* Marks that the FRAME_ID member actually holds the ID of the frame next
35 to this, and not this frames' ID itself. This is a hack to permit Python
36 frame objects which represent invalid frames (i.e., the last frame_info
37 in a corrupt stack). The problem arises from the fact that this code
38 relies on FRAME_ID to uniquely identify a frame, which is not always true
39 for the last "frame" in a corrupt stack (it can have a null ID, or the same
40 ID as the previous frame). Whenever get_prev_frame returns NULL, we
41 record the frame_id of the next frame and set FRAME_ID_IS_NEXT to 1. */
42 int frame_id_is_next;
43} frame_object;
44
45static frame_object *frame_info_to_frame_object (struct frame_info *frame);
46static struct frame_info *frame_object_to_frame_info (frame_object *frame_obj);
47
48static PyObject *frapy_str (PyObject *self);
49static PyObject *frapy_equal_p (PyObject *self, PyObject *args);
50static PyObject *frapy_inner_p (PyObject *self, PyObject *args);
51static PyObject *frapy_is_valid (PyObject *self, PyObject *args);
52static PyObject *frapy_get_name (PyObject *self, PyObject *args);
53static PyObject *frapy_get_type (PyObject *self, PyObject *args);
54static PyObject *frapy_get_unwind_stop_reason (PyObject *self, PyObject *args);
55static PyObject *frapy_get_pc (PyObject *self, PyObject *args);
56static PyObject *frapy_get_address_in_block (PyObject *self, PyObject *args);
57static PyObject *frapy_get_prev (PyObject *self, PyObject *args);
58static PyObject *frapy_get_next (PyObject *self, PyObject *args);
59
60#define FRAPY_REQUIRE_VALID(frame_obj, frame) \
61 do { \
62 frame = frame_object_to_frame_info (frame_obj); \
63 if (frame == NULL) \
64 { \
65 PyErr_SetString (PyExc_RuntimeError, "Frame is invalid."); \
66 return NULL; \
67 } \
68 } while (0)
69
70static PyMethodDef frame_object_methods[] = {
71 { "equals", frapy_equal_p, METH_VARARGS, "Compare frames." },
72 { "is_inner_than", frapy_inner_p, METH_VARARGS,
73 "Return true if this frame is strictly inner than the other frame." },
74 { "is_valid", frapy_is_valid, METH_NOARGS,
75 "Return true if this frame is valid, false if not." },
76 { "get_name", frapy_get_name, METH_NOARGS,
77 "Return the function name of the frame." },
78 { "get_type", frapy_get_type, METH_NOARGS, "Return the type of the frame." },
79 { "get_unwind_stop_reason", frapy_get_unwind_stop_reason,
80 METH_NOARGS, "Return the function name of the frame." },
81 { "get_pc", frapy_get_pc, METH_NOARGS, "Return the frame's resume address." },
82 { "get_address_in_block", frapy_get_address_in_block, METH_NOARGS,
83 "Return an address which falls within the frame's code block." },
84 { "get_prev", frapy_get_prev, METH_NOARGS,
85 "Return the previous (outer) frame." },
86 { "get_next", frapy_get_next, METH_NOARGS, "Return the next (inner) frame." },
87 {NULL} /* Sentinel */
88};
89
90static PyTypeObject frame_object_type = {
91 PyObject_HEAD_INIT (NULL)
92 0, /*ob_size*/
93 "gdb.Frame", /*tp_name*/
94 sizeof (frame_object), /*tp_basicsize*/
95 0, /*tp_itemsize*/
96 0, /*tp_dealloc*/
97 0, /*tp_print*/
98 0, /*tp_getattr*/
99 0, /*tp_setattr*/
100 0, /*tp_compare*/
101 0, /*tp_repr*/
102 0, /*tp_as_number*/
103 0, /*tp_as_sequence*/
104 0, /*tp_as_mapping*/
105 0, /*tp_hash */
106 0, /*tp_call*/
107 frapy_str, /*tp_str*/
108 0, /*tp_getattro*/
109 0, /*tp_setattro*/
110 0, /*tp_as_buffer*/
111 Py_TPFLAGS_DEFAULT, /*tp_flags*/
112 "GDB frame object", /* tp_doc */
113 0, /* tp_traverse */
114 0, /* tp_clear */
115 0, /* tp_richcompare */
116 0, /* tp_weaklistoffset */
117 0, /* tp_iter */
118 0, /* tp_iternext */
119 frame_object_methods /* tp_methods */
120};
121
122
123static PyObject *
124frapy_str (PyObject *self)
125{
126 char *s;
127 long len;
128 PyObject *result;
129 struct ui_file *strfile;
130
131 strfile = mem_fileopen ();
132 fprint_frame_id (strfile, ((frame_object *) self)->frame_id);
133 s = ui_file_xstrdup (strfile, &len);
134 result = PyString_FromString (s);
135 xfree (s);
136
137 return result;
138}
139
140static PyObject *
141frapy_is_valid (PyObject *self, PyObject *args)
142{
143 struct frame_info *frame;
144
145 frame = frame_object_to_frame_info ((frame_object *) self);
146 if (frame == NULL)
147 Py_RETURN_FALSE;
148
149 Py_RETURN_TRUE;
150}
151
152static PyObject *
153frapy_equal_p (PyObject *self, PyObject *args)
154{
155 int equalp = 0; /* Initialize to appease gcc warning. */
156 frame_object *self_frame = (frame_object *) self;
157 frame_object *other;
158 volatile struct gdb_exception except;
159
160 if (!PyArg_ParseTuple (args, "O!", &frame_object_type, &other))
161 return NULL;
162
163 TRY_CATCH (except, RETURN_MASK_ALL)
164 {
165 equalp = frame_id_eq (self_frame->frame_id, other->frame_id);
166 }
167 GDB_PY_HANDLE_EXCEPTION (except);
168
169 if (equalp)
170 Py_RETURN_TRUE;
171
172 Py_RETURN_FALSE;
173}
174
175static PyObject *
176frapy_inner_p (PyObject *self, PyObject *args)
177{
178 int innerp = 0; /* Initialize to appease gcc warning. */
179 frame_object *self_frame = (frame_object *) self;
180 frame_object *other;
181 volatile struct gdb_exception except;
182
183 if (!PyArg_ParseTuple (args, "O!", &frame_object_type, &other))
184 return NULL;
185
186 TRY_CATCH (except, RETURN_MASK_ALL)
187 {
188 /* It doesn't make sense to compare frames from different arches. */
189 if (self_frame->gdbarch != other->gdbarch)
190 {
191 PyErr_SetString (PyExc_ValueError,
192 "Frames are from different architectures.");
193 return NULL;
194 }
195
196 innerp = frame_id_inner (self_frame->gdbarch,
197 self_frame->frame_id, other->frame_id);
198 }
199 GDB_PY_HANDLE_EXCEPTION (except);
200
201 if (innerp)
202 Py_RETURN_TRUE;
203
204 Py_RETURN_FALSE;
205}
206
207static PyObject *
208frapy_get_name (PyObject *self, PyObject *args)
209{
210 struct frame_info *frame;
211 char *name;
212 enum language lang;
213 PyObject *result;
214 volatile struct gdb_exception except;
215
216 TRY_CATCH (except, RETURN_MASK_ALL)
217 {
218 FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
219
220 find_frame_funname (frame, &name, &lang);
221 }
222 GDB_PY_HANDLE_EXCEPTION (except);
223
224 if (name)
225 result = PyString_Decode (name, strlen (name), host_charset (),
226 NULL /* FIXME */);
227 else
228 {
229 result = Py_None;
230 Py_INCREF (Py_None);
231 }
232
233 return result;
234}
235
236static PyObject *
237frapy_get_type (PyObject *self, PyObject *args)
238{
239 struct frame_info *frame;
240 enum frame_type type = NORMAL_FRAME;/* Initialize to appease gcc warning. */
241 volatile struct gdb_exception except;
242
243 TRY_CATCH (except, RETURN_MASK_ALL)
244 {
245 FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
246
247 type = get_frame_type (frame);
248 }
249 GDB_PY_HANDLE_EXCEPTION (except);
250
251 return PyInt_FromLong (type);
252}
253
254static PyObject *
255frapy_get_unwind_stop_reason (PyObject *self, PyObject *args)
256{
257 struct frame_info *frame = NULL; /* Initialize to appease gcc warning. */
258 volatile struct gdb_exception except;
259 enum unwind_stop_reason stop_reason;
260
261 TRY_CATCH (except, RETURN_MASK_ALL)
262 {
263 FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
264 }
265 GDB_PY_HANDLE_EXCEPTION (except);
266
267 stop_reason = get_frame_unwind_stop_reason (frame);
268
269 return PyInt_FromLong (stop_reason);
270}
271
272static PyObject *
273frapy_get_pc (PyObject *self, PyObject *args)
274{
275 CORE_ADDR pc = 0; /* Initialize to appease gcc warning. */
276 struct frame_info *frame;
277 volatile struct gdb_exception except;
278
279 TRY_CATCH (except, RETURN_MASK_ALL)
280 {
281 FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
282
283 pc = get_frame_pc (frame);
284 }
285 GDB_PY_HANDLE_EXCEPTION (except);
286
287 return PyLong_FromUnsignedLongLong (pc);
288}
289
290static PyObject *
291frapy_get_address_in_block (PyObject *self, PyObject *args)
292{
293 CORE_ADDR pc = 0; /* Initialize to appease gcc warning. */
294 struct frame_info *frame;
295 volatile struct gdb_exception except;
296
297 TRY_CATCH (except, RETURN_MASK_ALL)
298 {
299 FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
300
301 pc = get_frame_address_in_block (frame);
302 }
303 GDB_PY_HANDLE_EXCEPTION (except);
304
305 return PyLong_FromUnsignedLongLong (pc);
306}
307
308static frame_object *
309frame_info_to_frame_object (struct frame_info *frame)
310{
311 frame_object *frame_obj;
312
313 frame_obj = PyObject_New (frame_object, &frame_object_type);
314 if (frame_obj == NULL)
315 {
316 PyErr_SetString (PyExc_MemoryError, "Could not allocate frame object.");
317 return NULL;
318 }
319
320 /* Try to get the previous frame, to determine if this is the last frame
321 in a corrupt stack. If so, we need to store the frame_id of the next
322 frame and not of this one (which is possibly invalid). */
323 if (get_prev_frame (frame) == NULL
324 && get_frame_unwind_stop_reason (frame) != UNWIND_NO_REASON
325 && get_next_frame (frame) != NULL)
326 {
327 frame_obj->frame_id = get_frame_id (get_next_frame (frame));
328 frame_obj->frame_id_is_next = 1;
329 }
330 else
331 {
332 frame_obj->frame_id = get_frame_id (frame);
333 frame_obj->frame_id_is_next = 0;
334 }
335
336 frame_obj->gdbarch = get_frame_arch (frame);
337
338 return frame_obj;
339}
340
341static struct frame_info *
342frame_object_to_frame_info (frame_object *frame_obj)
343{
344 struct frame_info *frame;
345
346 frame = frame_find_by_id (frame_obj->frame_id);
347 if (frame == NULL)
348 return NULL;
349
350 if (frame_obj->frame_id_is_next)
351 frame = get_prev_frame (frame);
352
353 return frame;
354}
355
356static PyObject *
357frapy_get_prev (PyObject *self, PyObject *args)
358{
359 struct frame_info *frame, *prev;
360 volatile struct gdb_exception except;
361 PyObject *prev_obj = NULL; /* Initialize to appease gcc warning. */
362
363 TRY_CATCH (except, RETURN_MASK_ALL)
364 {
365 FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
366
367 prev = get_prev_frame (frame);
368 if (prev)
369 prev_obj = (PyObject *) frame_info_to_frame_object (prev);
370 else
371 {
372 Py_INCREF (Py_None);
373 prev_obj = Py_None;
374 }
375 }
376 GDB_PY_HANDLE_EXCEPTION (except);
377
378 return prev_obj;
379}
380
381static PyObject *
382frapy_get_next (PyObject *self, PyObject *args)
383{
384 struct frame_info *frame, *next;
385 volatile struct gdb_exception except;
386 PyObject *next_obj = NULL; /* Initialize to appease gcc warning. */
387
388 TRY_CATCH (except, RETURN_MASK_ALL)
389 {
390 FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
391
392 next = get_next_frame (frame);
393 if (next)
394 next_obj = (PyObject *) frame_info_to_frame_object (next);
395 else
396 {
397 Py_INCREF (Py_None);
398 next_obj = Py_None;
399 }
400 }
401 GDB_PY_HANDLE_EXCEPTION (except);
402
403 return next_obj;
404}
405
406PyObject *
407gdbpy_get_frames (PyObject *self, PyObject *args)
408{
409 int result = 0;
410 struct frame_info *frame;
411 frame_object *frame_obj;
412 PyObject *list, *tuple;
413 volatile struct gdb_exception except;
414
415 list = PyList_New (0);
416 if (list == NULL)
417 {
418 PyErr_SetString (PyExc_MemoryError, "Could not allocate frames list.");
419 return NULL;
420 }
421
422 TRY_CATCH (except, RETURN_MASK_ALL)
423 {
424 for (frame = get_current_frame (); frame; frame = get_prev_frame (frame))
425 {
426 frame_obj = frame_info_to_frame_object (frame);
427 if (frame_obj == NULL)
428 {
429 Py_DECREF (list);
430 return NULL;
431 }
432
433 PyList_Append (list, (PyObject *) frame_obj);
434 }
435 }
436 if (except.reason < 0)
437 {
438 Py_DECREF (list);
439 return PyErr_Format (except.reason == RETURN_QUIT
440 ? PyExc_KeyboardInterrupt : PyExc_RuntimeError,
441 "%s", except.message);
442 }
443
444 tuple = PyList_AsTuple (list);
445 Py_DECREF (list);
446
447 return tuple;
448}
449
450PyObject *
451gdbpy_get_current_frame (PyObject *self, PyObject *args)
452{
453 struct frame_info *frame;
454 frame_object *frame_obj = NULL; /* Initialize to appease gcc warning. */
455 volatile struct gdb_exception except;
456
457 TRY_CATCH (except, RETURN_MASK_ALL)
458 {
459 frame = get_current_frame ();
460 frame_obj = frame_info_to_frame_object (frame);
461 if (frame_obj == NULL)
462 return NULL;
463 }
464 GDB_PY_HANDLE_EXCEPTION (except);
465
466 return (PyObject *) frame_obj;
467}
468
469PyObject *
470gdbpy_get_selected_frame (PyObject *self, PyObject *args)
471{
472 struct frame_info *frame;
473 frame_object *frame_obj = NULL; /* Initialize to appease gcc warning. */
474 volatile struct gdb_exception except;
475
476 TRY_CATCH (except, RETURN_MASK_ALL)
477 {
478 frame = get_selected_frame ("No frame is currently selected.");
479 frame_obj = frame_info_to_frame_object (frame);
480 if (frame_obj == NULL)
481 return NULL;
482 }
483 GDB_PY_HANDLE_EXCEPTION (except);
484
485 return (PyObject *) frame_obj;
486}
487
488PyObject *
489gdbpy_frame_stop_reason_string (PyObject *self, PyObject *args)
490{
491 int reason;
492 const char *str;
493
494 if (!PyArg_ParseTuple (args, "i", &reason))
495 return NULL;
496
497 if (reason < 0 || reason > UNWIND_NO_SAVED_PC)
498 {
499 PyErr_SetString (PyExc_ValueError, "Invalid frame stop reason.");
500 return NULL;
501 }
502
503 str = frame_stop_reason_string (reason);
504 return PyString_Decode (str, strlen (str), host_charset (), NULL /* FIXME */);
505}
506
507void
508gdbpy_initialize_frames (void)
509{
510 frame_object_type.tp_new = PyType_GenericNew;
511 if (PyType_Ready (&frame_object_type) < 0)
512 return;
513
514 /* FIXME: These would probably be best exposed as class attributes of Frame,
515 but I don't know how to do it except by messing with the type's dictionary.
516 That seems too messy. */
517 PyModule_AddIntConstant (gdb_module, "NORMAL_FRAME", NORMAL_FRAME);
518 PyModule_AddIntConstant (gdb_module, "DUMMY_FRAME", DUMMY_FRAME);
519 PyModule_AddIntConstant (gdb_module, "SIGTRAMP_FRAME", SIGTRAMP_FRAME);
520 PyModule_AddIntConstant (gdb_module, "SENTINEL_FRAME", SENTINEL_FRAME);
521 PyModule_AddIntConstant (gdb_module,
522 "FRAME_UNWIND_NO_REASON", UNWIND_NO_REASON);
523 PyModule_AddIntConstant (gdb_module,
524 "FRAME_UNWIND_NULL_ID", UNWIND_NULL_ID);
525 PyModule_AddIntConstant (gdb_module,
526 "FRAME_UNWIND_FIRST_ERROR", UNWIND_FIRST_ERROR);
527 PyModule_AddIntConstant (gdb_module,
528 "FRAME_UNWIND_INNER_ID", UNWIND_INNER_ID);
529 PyModule_AddIntConstant (gdb_module,
530 "FRAME_UNWIND_SAME_ID", UNWIND_SAME_ID);
531 PyModule_AddIntConstant (gdb_module,
532 "FRAME_UNWIND_NO_SAVED_PC", UNWIND_NO_SAVED_PC);
533
534 Py_INCREF (&frame_object_type);
535 PyModule_AddObject (gdb_module, "Frame", (PyObject *) &frame_object_type);
536}
toggle raw diff

gdb/python/python-internal.h

 
3232PyObject *gdbpy_make_value_from_int (PyObject *self, PyObject *args);
3333PyObject *gdbpy_get_value_from_history (PyObject *self, PyObject *args);
3434PyObject *gdbpy_get_breakpoints (PyObject *, PyObject *);
35PyObject *gdbpy_get_frames (PyObject *, PyObject *);
36PyObject *gdbpy_get_current_frame (PyObject *, PyObject *);
37PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *);
38PyObject *gdbpy_get_selected_frame (PyObject *self, PyObject *args);
3539
3640PyObject *variable_to_python (struct cmd_list_element *);
3741PyObject *value_to_value_object (struct value *v);
4848void gdbpy_initialize_values (void);
4949void gdbpy_initialize_hooks (void);
5050void gdbpy_initialize_breakpoints (void);
51void gdbpy_initialize_frames (void);
5152void gdbpy_initialize_commands (void);
5253
5354/* Use this after a TRY_EXCEPT to throw the appropriate Python
toggle raw diff

gdb/python/python.c

 
2424#include "cli/cli-decode.h"
2525#include "charset.h"
2626#include "top.h"
27#include "solib.h"
2728#include "exceptions.h"
2829#include "python-internal.h"
2930#include "version.h"
3535
3636static PyObject *get_show_variable (PyObject *, PyObject *);
3737static PyObject *execute_gdb_command (PyObject *, PyObject *);
38static PyObject *gdbpy_solib_address (PyObject *, PyObject *);
3839
3940
4041void
5858 { "get_breakpoints", gdbpy_get_breakpoints, METH_NOARGS,
5959 "Return a tuple of all breakpoint objects" },
6060
61 { "get_frames", gdbpy_get_frames, METH_NOARGS,
62 "Return a tuple of all frame objects" },
63 { "get_current_frame", gdbpy_get_current_frame, METH_NOARGS,
64 "Return the current frame object" },
65 { "get_selected_frame", gdbpy_get_selected_frame, METH_NOARGS,
66 "Return the selected frame object" },
67 { "frame_stop_reason_string", gdbpy_frame_stop_reason_string,
68 METH_VARARGS, "Return a string explaining unwind stop reason" },
69
70 { "solib_address", gdbpy_solib_address, METH_VARARGS,
71 "Return shared library holding a given address, or None." },
72
6173 {NULL, NULL, 0, NULL}
6274 };
6375
8484 gdbpy_initialize_hooks ();
8585 gdbpy_initialize_values ();
8686 gdbpy_initialize_breakpoints ();
87 gdbpy_initialize_frames ();
8788 gdbpy_initialize_commands ();
8889
8990 PyRun_SimpleString ("import gdb");
342342 return value;
343343}
344344
345PyObject *
346gdbpy_solib_address (PyObject *self, PyObject *args)
347{
348 unsigned long long pc;
349 char *soname;
350 PyObject *str_obj;
351
352 if (!PyArg_ParseTuple (args, "K", &pc))
353 return NULL;
354
355 soname = solib_address (pc);
356 if (soname)
357 str_obj = PyString_Decode (soname, strlen (soname), host_charset (),
358 NULL /* FIXME */);
359 else
360 {
361 str_obj = Py_None;
362 Py_INCREF (Py_None);
363 }
364
365 return str_obj;
366}
367
345368
346369
347370void
toggle raw diff

gdb/stack.c

 
562562 gdb_flush (gd