/* Python interface to stack frames
- Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 2008-2014 Free Software Foundation, Inc.
This file is part of GDB.
#include "stack.h"
#include "value.h"
#include "python-internal.h"
+#include "symfile.h"
+#include "objfiles.h"
typedef struct {
PyObject_HEAD
do { \
frame = frame_object_to_frame_info (frame_obj); \
if (frame == NULL) \
- error ("Frame is invalid."); \
+ error (_("Frame is invalid.")); \
} while (0)
-static PyTypeObject frame_object_type;
-
/* Returns the frame_info object corresponding to the given Python Frame
object. If the frame doesn't exist anymore (the frame id doesn't
correspond to any frame in the inferior), returns NULL. */
-static struct frame_info *
-frame_object_to_frame_info (frame_object *frame_obj)
+struct frame_info *
+frame_object_to_frame_info (PyObject *obj)
{
+ frame_object *frame_obj = (frame_object *) obj;
struct frame_info *frame;
frame = frame_find_by_id (frame_obj->frame_id);
static PyObject *
frapy_is_valid (PyObject *self, PyObject *args)
{
- struct frame_info *frame;
+ struct frame_info *frame = NULL;
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ frame = frame_object_to_frame_info (self);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
- frame = frame_object_to_frame_info ((frame_object *) self);
if (frame == NULL)
Py_RETURN_FALSE;
frapy_name (PyObject *self, PyObject *args)
{
struct frame_info *frame;
- char *name;
+ char *name = NULL;
enum language lang;
PyObject *result;
volatile struct gdb_exception except;
TRY_CATCH (except, RETURN_MASK_ALL)
{
- FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
+ FRAPY_REQUIRE_VALID (self, frame);
- find_frame_funname (frame, &name, &lang);
+ find_frame_funname (frame, &name, &lang, NULL);
}
+
+ if (except.reason < 0)
+ xfree (name);
+
GDB_PY_HANDLE_EXCEPTION (except);
if (name)
- result = PyUnicode_Decode (name, strlen (name), host_charset (), NULL);
+ {
+ result = PyUnicode_Decode (name, strlen (name), host_charset (), NULL);
+ xfree (name);
+ }
else
{
result = Py_None;
TRY_CATCH (except, RETURN_MASK_ALL)
{
- FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
+ FRAPY_REQUIRE_VALID (self, frame);
type = get_frame_type (frame);
}
return PyInt_FromLong (type);
}
+/* Implementation of gdb.Frame.architecture (self) -> gdb.Architecture.
+ Returns the frame's architecture as a gdb.Architecture object. */
+
+static PyObject *
+frapy_arch (PyObject *self, PyObject *args)
+{
+ struct frame_info *frame = NULL; /* Initialize to appease gcc warning. */
+ frame_object *obj = (frame_object *) self;
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ FRAPY_REQUIRE_VALID (self, frame);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return gdbarch_to_arch_object (obj->gdbarch);
+}
+
/* Implementation of gdb.Frame.unwind_stop_reason (self) -> Integer.
Returns one of the gdb.FRAME_UNWIND_* constants. */
TRY_CATCH (except, RETURN_MASK_ALL)
{
- FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
+ FRAPY_REQUIRE_VALID (self, frame);
}
GDB_PY_HANDLE_EXCEPTION (except);
TRY_CATCH (except, RETURN_MASK_ALL)
{
- FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
+ FRAPY_REQUIRE_VALID (self, frame);
pc = get_frame_pc (frame);
}
GDB_PY_HANDLE_EXCEPTION (except);
- return PyLong_FromUnsignedLongLong (pc);
+ return gdb_py_long_from_ulongest (pc);
+}
+
+/* Implementation of gdb.Frame.block (self) -> gdb.Block.
+ Returns the frame's code block. */
+
+static PyObject *
+frapy_block (PyObject *self, PyObject *args)
+{
+ struct frame_info *frame;
+ struct block *block = NULL, *fn_block;
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ FRAPY_REQUIRE_VALID (self, frame);
+ block = get_frame_block (frame, NULL);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ for (fn_block = block;
+ fn_block != NULL && BLOCK_FUNCTION (fn_block) == NULL;
+ fn_block = BLOCK_SUPERBLOCK (fn_block))
+ ;
+
+ if (block == NULL || fn_block == NULL || BLOCK_FUNCTION (fn_block) == NULL)
+ {
+ PyErr_SetString (PyExc_RuntimeError,
+ _("Cannot locate block for frame."));
+ return NULL;
+ }
+
+ if (block)
+ {
+ struct symtab *symt;
+
+ symt = SYMBOL_SYMTAB (BLOCK_FUNCTION (fn_block));
+ return block_to_block_object (block, symt->objfile);
+ }
+
+ Py_RETURN_NONE;
+}
+
+
+/* Implementation of gdb.Frame.function (self) -> gdb.Symbol.
+ Returns the symbol for the function corresponding to this frame. */
+
+static PyObject *
+frapy_function (PyObject *self, PyObject *args)
+{
+ struct symbol *sym = NULL;
+ struct frame_info *frame;
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ FRAPY_REQUIRE_VALID (self, frame);
+
+ sym = find_pc_function (get_frame_address_in_block (frame));
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ if (sym)
+ return symbol_to_symbol_object (sym);
+
+ Py_RETURN_NONE;
}
/* Convert a frame_info struct to a Python Frame object.
Sets a Python exception and returns NULL on error. */
-static frame_object *
+PyObject *
frame_info_to_frame_object (struct frame_info *frame)
{
frame_object *frame_obj;
+ volatile struct gdb_exception except;
frame_obj = PyObject_New (frame_object, &frame_object_type);
if (frame_obj == NULL)
- {
- PyErr_SetString (PyExc_MemoryError, "Could not allocate frame object.");
- return NULL;
- }
+ return NULL;
- /* Try to get the previous frame, to determine if this is the last frame
- in a corrupt stack. If so, we need to store the frame_id of the next
- frame and not of this one (which is possibly invalid). */
- if (get_prev_frame (frame) == NULL
- && get_frame_unwind_stop_reason (frame) != UNWIND_NO_REASON
- && get_next_frame (frame) != NULL)
+ TRY_CATCH (except, RETURN_MASK_ALL)
{
- frame_obj->frame_id = get_frame_id (get_next_frame (frame));
- frame_obj->frame_id_is_next = 1;
+
+ /* Try to get the previous frame, to determine if this is the last frame
+ in a corrupt stack. If so, we need to store the frame_id of the next
+ frame and not of this one (which is possibly invalid). */
+ if (get_prev_frame (frame) == NULL
+ && get_frame_unwind_stop_reason (frame) != UNWIND_NO_REASON
+ && get_next_frame (frame) != NULL)
+ {
+ frame_obj->frame_id = get_frame_id (get_next_frame (frame));
+ frame_obj->frame_id_is_next = 1;
+ }
+ else
+ {
+ frame_obj->frame_id = get_frame_id (frame);
+ frame_obj->frame_id_is_next = 0;
+ }
+ frame_obj->gdbarch = get_frame_arch (frame);
}
- else
+ if (except.reason < 0)
{
- frame_obj->frame_id = get_frame_id (frame);
- frame_obj->frame_id_is_next = 0;
+ Py_DECREF (frame_obj);
+ gdbpy_convert_exception (except);
+ return NULL;
}
-
- frame_obj->gdbarch = get_frame_arch (frame);
-
- return frame_obj;
+ return (PyObject *) frame_obj;
}
/* Implementation of gdb.Frame.older (self) -> gdb.Frame.
static PyObject *
frapy_older (PyObject *self, PyObject *args)
{
- struct frame_info *frame, *prev;
+ struct frame_info *frame, *prev = NULL;
volatile struct gdb_exception except;
PyObject *prev_obj = NULL; /* Initialize to appease gcc warning. */
TRY_CATCH (except, RETURN_MASK_ALL)
{
- FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
+ FRAPY_REQUIRE_VALID (self, frame);
prev = get_prev_frame (frame);
- if (prev)
- prev_obj = (PyObject *) frame_info_to_frame_object (prev);
- else
- {
- Py_INCREF (Py_None);
- prev_obj = Py_None;
- }
}
GDB_PY_HANDLE_EXCEPTION (except);
+ if (prev)
+ prev_obj = (PyObject *) frame_info_to_frame_object (prev);
+ else
+ {
+ Py_INCREF (Py_None);
+ prev_obj = Py_None;
+ }
+
return prev_obj;
}
static PyObject *
frapy_newer (PyObject *self, PyObject *args)
{
- struct frame_info *frame, *next;
+ struct frame_info *frame, *next = NULL;
volatile struct gdb_exception except;
PyObject *next_obj = NULL; /* Initialize to appease gcc warning. */
TRY_CATCH (except, RETURN_MASK_ALL)
{
- FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
+ FRAPY_REQUIRE_VALID (self, frame);
next = get_next_frame (frame);
- if (next)
- next_obj = (PyObject *) frame_info_to_frame_object (next);
- else
- {
- Py_INCREF (Py_None);
- next_obj = Py_None;
- }
}
GDB_PY_HANDLE_EXCEPTION (except);
+ if (next)
+ next_obj = (PyObject *) frame_info_to_frame_object (next);
+ else
+ {
+ Py_INCREF (Py_None);
+ next_obj = Py_None;
+ }
+
return next_obj;
}
-/* Implementation of gdb.Frame.read_var_value (self, variable) -> gdb.Value.
- Returns the value of the given variable in this frame. The argument must be
- a string. Returns None if GDB can't find the specified variable. */
+/* Implementation of gdb.Frame.find_sal (self) -> gdb.Symtab_and_line.
+ Returns the frame's symtab and line. */
+
+static PyObject *
+frapy_find_sal (PyObject *self, PyObject *args)
+{
+ struct frame_info *frame;
+ struct symtab_and_line sal;
+ volatile struct gdb_exception except;
+ PyObject *sal_obj = NULL; /* Initialize to appease gcc warning. */
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ FRAPY_REQUIRE_VALID (self, frame);
+
+ find_frame_sal (frame, &sal);
+ sal_obj = symtab_and_line_to_sal_object (sal);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return sal_obj;
+}
+/* Implementation of gdb.Frame.read_var_value (self, variable,
+ [block]) -> gdb.Value. If the optional block argument is provided
+ start the search from that block, otherwise search from the frame's
+ current block (determined by examining the resume address of the
+ frame). The variable argument must be a string or an instance of a
+ gdb.Symbol. The block argument must be an instance of gdb.Block. Returns
+ NULL on error, with a python exception set. */
static PyObject *
frapy_read_var (PyObject *self, PyObject *args)
{
struct frame_info *frame;
- PyObject *sym_obj;
+ PyObject *sym_obj, *block_obj = NULL;
struct symbol *var = NULL; /* gcc-4.3.2 false warning. */
struct value *val = NULL;
volatile struct gdb_exception except;
- if (!PyArg_ParseTuple (args, "O", &sym_obj))
+ if (!PyArg_ParseTuple (args, "O|O", &sym_obj, &block_obj))
return NULL;
- if (gdbpy_is_string (sym_obj))
+ if (PyObject_TypeCheck (sym_obj, &symbol_object_type))
+ var = symbol_object_to_symbol (sym_obj);
+ else if (gdbpy_is_string (sym_obj))
{
char *var_name;
- struct block *block = NULL;
+ const struct block *block = NULL;
struct cleanup *cleanup;
volatile struct gdb_exception except;
return NULL;
cleanup = make_cleanup (xfree, var_name);
+ if (block_obj)
+ {
+ block = block_object_to_block (block_obj);
+ if (!block)
+ {
+ PyErr_SetString (PyExc_RuntimeError,
+ _("Second argument must be block."));
+ do_cleanups (cleanup);
+ return NULL;
+ }
+ }
+
TRY_CATCH (except, RETURN_MASK_ALL)
{
- FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
+ FRAPY_REQUIRE_VALID (self, frame);
- block = block_for_pc (get_frame_address_in_block (frame));
+ if (!block)
+ block = get_frame_block (frame, NULL);
var = lookup_symbol (var_name, block, VAR_DOMAIN, NULL);
}
- GDB_PY_HANDLE_EXCEPTION (except);
+ if (except.reason < 0)
+ {
+ do_cleanups (cleanup);
+ gdbpy_convert_exception (except);
+ return NULL;
+ }
if (!var)
{
PyErr_Format (PyExc_ValueError,
- _("variable '%s' not found"), var_name);
+ _("Variable '%s' not found."), var_name);
do_cleanups (cleanup);
return NULL;
else
{
PyErr_SetString (PyExc_TypeError,
- _("argument must be a symbol or string"));
+ _("Argument must be a symbol or string."));
return NULL;
}
TRY_CATCH (except, RETURN_MASK_ALL)
{
- FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
+ FRAPY_REQUIRE_VALID (self, frame);
val = read_var_value (var, frame);
}
GDB_PY_HANDLE_EXCEPTION (except);
- if (val)
- return value_to_value_object (val);
+ return value_to_value_object (val);
+}
+
+/* Select this frame. */
+
+static PyObject *
+frapy_select (PyObject *self, PyObject *args)
+{
+ struct frame_info *fi;
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ FRAPY_REQUIRE_VALID (self, fi);
+
+ select_frame (fi);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
Py_RETURN_NONE;
}
+/* Implementation of gdb.newest_frame () -> gdb.Frame.
+ Returns the newest frame object. */
+
+PyObject *
+gdbpy_newest_frame (PyObject *self, PyObject *args)
+{
+ struct frame_info *frame = NULL;
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ frame = get_current_frame ();
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return frame_info_to_frame_object (frame);
+}
+
/* Implementation of gdb.selected_frame () -> gdb.Frame.
Returns the selected frame object. */
PyObject *
gdbpy_selected_frame (PyObject *self, PyObject *args)
{
- struct frame_info *frame;
- frame_object *frame_obj = NULL; /* Initialize to appease gcc warning. */
+ struct frame_info *frame = NULL;
volatile struct gdb_exception except;
TRY_CATCH (except, RETURN_MASK_ALL)
{
frame = get_selected_frame ("No frame is currently selected.");
- frame_obj = frame_info_to_frame_object (frame);
}
GDB_PY_HANDLE_EXCEPTION (except);
- return (PyObject *) frame_obj;
+ return frame_info_to_frame_object (frame);
}
/* Implementation of gdb.stop_reason_string (Integer) -> String.
if (!PyArg_ParseTuple (args, "i", &reason))
return NULL;
- if (reason < 0 || reason > UNWIND_NO_SAVED_PC)
+ if (reason < UNWIND_FIRST || reason > UNWIND_LAST)
{
- PyErr_SetString (PyExc_ValueError, "Invalid frame stop reason.");
+ PyErr_SetString (PyExc_ValueError,
+ _("Invalid frame stop reason."));
return NULL;
}
/* Sets up the Frame API in the gdb module. */
-void
+int
gdbpy_initialize_frames (void)
{
+ frame_object_type.tp_new = PyType_GenericNew;
if (PyType_Ready (&frame_object_type) < 0)
- return;
-
- /* Note: These would probably be best exposed as class attributes of Frame,
- but I don't know how to do it except by messing with the type's dictionary.
- That seems too messy. */
- PyModule_AddIntConstant (gdb_module, "NORMAL_FRAME", NORMAL_FRAME);
- PyModule_AddIntConstant (gdb_module, "DUMMY_FRAME", DUMMY_FRAME);
- PyModule_AddIntConstant (gdb_module, "SIGTRAMP_FRAME", SIGTRAMP_FRAME);
- PyModule_AddIntConstant (gdb_module, "SENTINEL_FRAME", SENTINEL_FRAME);
- PyModule_AddIntConstant (gdb_module,
- "FRAME_UNWIND_NO_REASON", UNWIND_NO_REASON);
- PyModule_AddIntConstant (gdb_module,
- "FRAME_UNWIND_NULL_ID", UNWIND_NULL_ID);
- PyModule_AddIntConstant (gdb_module,
- "FRAME_UNWIND_FIRST_ERROR", UNWIND_FIRST_ERROR);
- PyModule_AddIntConstant (gdb_module,
- "FRAME_UNWIND_INNER_ID", UNWIND_INNER_ID);
- PyModule_AddIntConstant (gdb_module,
- "FRAME_UNWIND_SAME_ID", UNWIND_SAME_ID);
- PyModule_AddIntConstant (gdb_module,
- "FRAME_UNWIND_NO_SAVED_PC", UNWIND_NO_SAVED_PC);
-
- Py_INCREF (&frame_object_type);
- PyModule_AddObject (gdb_module, "Frame", (PyObject *) &frame_object_type);
+ return -1;
+
+ /* Note: These would probably be best exposed as class attributes of
+ Frame, but I don't know how to do it except by messing with the
+ type's dictionary. That seems too messy. */
+ if (PyModule_AddIntConstant (gdb_module, "NORMAL_FRAME", NORMAL_FRAME) < 0
+ || PyModule_AddIntConstant (gdb_module, "DUMMY_FRAME", DUMMY_FRAME) < 0
+ || PyModule_AddIntConstant (gdb_module, "INLINE_FRAME", INLINE_FRAME) < 0
+ || PyModule_AddIntConstant (gdb_module, "TAILCALL_FRAME",
+ TAILCALL_FRAME) < 0
+ || PyModule_AddIntConstant (gdb_module, "SIGTRAMP_FRAME",
+ SIGTRAMP_FRAME) < 0
+ || PyModule_AddIntConstant (gdb_module, "ARCH_FRAME", ARCH_FRAME) < 0
+ || PyModule_AddIntConstant (gdb_module, "SENTINEL_FRAME",
+ SENTINEL_FRAME) < 0)
+ return -1;
+
+#define SET(name, description) \
+ if (PyModule_AddIntConstant (gdb_module, "FRAME_"#name, name) < 0) \
+ return -1;
+#include "unwind_stop_reasons.def"
+#undef SET
+
+ return gdb_pymodule_addobject (gdb_module, "Frame",
+ (PyObject *) &frame_object_type);
}
\f
{ "type", frapy_type, METH_NOARGS,
"type () -> Integer.\n\
Return the type of the frame." },
+ { "architecture", frapy_arch, METH_NOARGS,
+ "architecture () -> gdb.Architecture.\n\
+Return the architecture of the frame." },
{ "unwind_stop_reason", frapy_unwind_stop_reason, METH_NOARGS,
"unwind_stop_reason () -> Integer.\n\
Return the reason why it's not possible to find frames older than this." },
{ "pc", frapy_pc, METH_NOARGS,
"pc () -> Long.\n\
Return the frame's resume address." },
+ { "block", frapy_block, METH_NOARGS,
+ "block () -> gdb.Block.\n\
+Return the frame's code block." },
+ { "function", frapy_function, METH_NOARGS,
+ "function () -> gdb.Symbol.\n\
+Returns the symbol for the function corresponding to this frame." },
{ "older", frapy_older, METH_NOARGS,
"older () -> gdb.Frame.\n\
Return the frame that called this frame." },
{ "newer", frapy_newer, METH_NOARGS,
"newer () -> gdb.Frame.\n\
Return the frame called by this frame." },
+ { "find_sal", frapy_find_sal, METH_NOARGS,
+ "find_sal () -> gdb.Symtab_and_line.\n\
+Return the frame's symtab and line." },
{ "read_var", frapy_read_var, METH_VARARGS,
"read_var (variable) -> gdb.Value.\n\
Return the value of the variable in this frame." },
+ { "select", frapy_select, METH_NOARGS,
+ "Select this frame as the user's current frame." },
{NULL} /* Sentinel */
};
-static PyTypeObject frame_object_type = {
- PyObject_HEAD_INIT (NULL)
- 0, /* ob_size */
+PyTypeObject frame_object_type = {
+ PyVarObject_HEAD_INIT (NULL, 0)
"gdb.Frame", /* tp_name */
sizeof (frame_object), /* tp_basicsize */
0, /* tp_itemsize */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
- PyType_GenericNew /* tp_new */
};