[RFC][patch 6/9] export frames to Python

Thiago Jung Bauermann
2008-04-29T15:58:38Z

[-- Attachment #1: python-frames.diff --]
[-- Type: text/plain, Size: 26227 bytes --]

2008-04-29 Thiago Jung Bauermann <bauerman@br.ibm.com>
Tom Tromey <tromey@redhat.com>

* Makefile.in (SUBDIR_PYTHON_OBS): Add python-frame.o.
(SUBDIR_PYTHON_SRCS): Add python/frame.c.
(python.o): Depend on solib.h.
(python-frame.o): New target.
* python/frame.c: New file.
* python/python-internal.h (gdbpy_get_frames,
gdbpy_get_current_frame, gdbpy_frame_stop_reason_string,
gdbpy_get_selected_frame, gdbpy_initialize_frames): Declare.
* python/python.c (demand_python): Add frame functions. Call
gdbpy_initialize_frames.
(gdbpy_solib_address): New function.
Include solib.h
* stack.c (print_frame): Factor out code to find function name
and language into ...
(find_frame_funname): ... this new function.
* stack.h (find_frame_funname): Declare.

Index: tromey.git/gdb/Makefile.in
===================================================================
--- tromey.git.orig/gdb/Makefile.in 2008-04-29 11:05:20.000000000 -0300
+++ tromey.git/gdb/Makefile.in 2008-04-29 11:05:45.000000000 -0300
@@ -264,12 +264,14 @@ SUBDIR_PYTHON_OBS = \
python.o \
python-breakpoint.o \
python-cmd.o \
+ python-frame.o \
python-hooks.o \
python-value.o
SUBDIR_PYTHON_SRCS = \
python/python.c \
python/breakpoint.c \
python/cmd.c \
+ python/frame.c \
python/hooks.c \
python/value.c
SUBDIR_PYTHON_DEPS =
@@ -3417,7 +3419,7 @@ PYTHON_CFLAGS=-fno-strict-aliasing

python.o: $(srcdir)/python/python.c $(defs_h) $(python_h) \
$(command_h) $(libiberty_h) $(cli_decode_h) $(charset_h) $(top_h) \
- $(exceptions_h) $(python_internal_h) $(version_h)
+ $(exceptions_h) $(python_internal_h) $(version_h) $(solib_h)
$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) $(srcdir)/python/python.c
python-breakpoint.o: $(srcdir)/python/breakpoint.c $(defs_h) $(python_h) \
$(value_h) $(exceptions_h) $(python_internal_h) $(charset_h) \
@@ -3429,6 +3431,11 @@ python-cmd.o: $(srcdir)/python/cmd.c $(d
$(gdbcmd_h) $(cli_decode_h)
$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
$(srcdir)/python/cmd.c -o python-cmd.o
+python-frame.o: $(srcdir)/python/frame.c $(defs_h) $(python_h) \
+ $(python_internal_h) $(frame_h) $(exceptions_h) $(symtab_h) \
+ $(charset_h) $(stack_h) $(value_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
+ $(srcdir)/python/frame.c -o python-frame.o
python-hooks.o: $(srcdir)/python/hooks.c $(defs_h) $(cli_decode_h) \
$(charset_h) $(gdb_events_h) $(python_h) $(python_internal_h)
$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
Index: tromey.git/gdb/python/frame.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ tromey.git/gdb/python/frame.c 2008-04-29 11:05:54.000000000 -0300
@@ -0,0 +1,536 @@
+/* Python interface to stack frames
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "charset.h"
+#include "frame.h"
+#include "exceptions.h"
+#include "symtab.h"
+#include "stack.h"
+#include "value.h"
+#include "python-internal.h"
+
+typedef struct {
+ PyObject_HEAD
+ struct frame_id frame_id;
+ struct gdbarch *gdbarch;
+
+ /* Marks that the FRAME_ID member actually holds the ID of the frame next
+ to this, and not this frames' ID itself. This is a hack to permit Python
+ frame objects which represent invalid frames (i.e., the last frame_info
+ in a corrupt stack). The problem arises from the fact that this code
+ relies on FRAME_ID to uniquely identify a frame, which is not always true
+ for the last "frame" in a corrupt stack (it can have a null ID, or the same
+ ID as the previous frame). Whenever get_prev_frame returns NULL, we
+ record the frame_id of the next frame and set FRAME_ID_IS_NEXT to 1. */
+ int frame_id_is_next;
+} frame_object;
+
+static frame_object *frame_info_to_frame_object (struct frame_info *frame);
+static struct frame_info *frame_object_to_frame_info (frame_object *frame_obj);
+
+static PyObject *frapy_str (PyObject *self);
+static PyObject *frapy_equal_p (PyObject *self, PyObject *args);
+static PyObject *frapy_inner_p (PyObject *self, PyObject *args);
+static PyObject *frapy_is_valid (PyObject *self, PyObject *args);
+static PyObject *frapy_get_name (PyObject *self, PyObject *args);
+static PyObject *frapy_get_type (PyObject *self, PyObject *args);
+static PyObject *frapy_get_unwind_stop_reason (PyObject *self, PyObject *args);
+static PyObject *frapy_get_pc (PyObject *self, PyObject *args);
+static PyObject *frapy_get_address_in_block (PyObject *self, PyObject *args);
+static PyObject *frapy_get_prev (PyObject *self, PyObject *args);
+static PyObject *frapy_get_next (PyObject *self, PyObject *args);
+
+#define FRAPY_REQUIRE_VALID(frame_obj, frame) \
+ do { \
+ frame = frame_object_to_frame_info (frame_obj); \
+ if (frame == NULL) \
+ { \
+ PyErr_SetString (PyExc_RuntimeError, "Frame is invalid."); \
+ return NULL; \
+ } \
+ } while (0)
+
+static PyMethodDef frame_object_methods[] = {
+ { "equals", frapy_equal_p, METH_VARARGS, "Compare frames." },
+ { "is_inner_than", frapy_inner_p, METH_VARARGS,
+ "Return true if this frame is strictly inner than the other frame." },
+ { "is_valid", frapy_is_valid, METH_NOARGS,
+ "Return true if this frame is valid, false if not." },
+ { "get_name", frapy_get_name, METH_NOARGS,
+ "Return the function name of the frame." },
+ { "get_type", frapy_get_type, METH_NOARGS, "Return the type of the frame." },
+ { "get_unwind_stop_reason", frapy_get_unwind_stop_reason,
+ METH_NOARGS, "Return the function name of the frame." },
+ { "get_pc", frapy_get_pc, METH_NOARGS, "Return the frame's resume address." },
+ { "get_address_in_block", frapy_get_address_in_block, METH_NOARGS,
+ "Return an address which falls within the frame's code block." },
+ { "get_prev", frapy_get_prev, METH_NOARGS,
+ "Return the previous (outer) frame." },
+ { "get_next", frapy_get_next, METH_NOARGS, "Return the next (inner) frame." },
+ {NULL} /* Sentinel */
+};
+
+static PyTypeObject frame_object_type = {
+ PyObject_HEAD_INIT (NULL)
+ 0, /*ob_size*/
+ "gdb.Frame", /*tp_name*/
+ sizeof (frame_object), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ frapy_str, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "GDB frame object", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ frame_object_methods /* tp_methods */
+};
+
+
+static PyObject *
+frapy_str (PyObject *self)
+{
+ char *s;
+ long len;
+ PyObject *result;
+ struct ui_file *strfile;
+
+ strfile = mem_fileopen ();
+ fprint_frame_id (strfile, ((frame_object *) self)->frame_id);
+ s = ui_file_xstrdup (strfile, &len);
+ result = PyString_FromString (s);
+ xfree (s);
+
+ return result;
+}
+
+static PyObject *
+frapy_is_valid (PyObject *self, PyObject *args)
+{
+ struct frame_info *frame;
+
+ frame = frame_object_to_frame_info ((frame_object *) self);
+ if (frame == NULL)
+ Py_RETURN_FALSE;
+
+ Py_RETURN_TRUE;
+}
+
+static PyObject *
+frapy_equal_p (PyObject *self, PyObject *args)
+{
+ int equalp = 0; /* Initialize to appease gcc warning. */
+ frame_object *self_frame = (frame_object *) self;
+ frame_object *other;
+ volatile struct gdb_exception except;
+
+ if (!PyArg_ParseTuple (args, "O!", &frame_object_type, &other))
+ return NULL;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ equalp = frame_id_eq (self_frame->frame_id, other->frame_id);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ if (equalp)
+ Py_RETURN_TRUE;
+
+ Py_RETURN_FALSE;
+}
+
+static PyObject *
+frapy_inner_p (PyObject *self, PyObject *args)
+{
+ int innerp = 0; /* Initialize to appease gcc warning. */
+ frame_object *self_frame = (frame_object *) self;
+ frame_object *other;
+ volatile struct gdb_exception except;
+
+ if (!PyArg_ParseTuple (args, "O!", &frame_object_type, &other))
+ return NULL;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ /* It doesn't make sense to compare frames from different arches. */
+ if (self_frame->gdbarch != other->gdbarch)
+ {
+ PyErr_SetString (PyExc_ValueError,
+ "Frames are from different architectures.");
+ return NULL;
+ }
+
+ innerp = frame_id_inner (self_frame->gdbarch,
+ self_frame->frame_id, other->frame_id);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ if (innerp)
+ Py_RETURN_TRUE;
+
+ Py_RETURN_FALSE;
+}
+
+static PyObject *
+frapy_get_name (PyObject *self, PyObject *args)
+{
+ struct frame_info *frame;
+ char *name;
+ enum language lang;
+ PyObject *result;
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
+
+ find_frame_funname (frame, &name, &lang);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ if (name)
+ result = PyString_Decode (name, strlen (name), host_charset (),
+ NULL /* FIXME */);
+ else
+ {
+ result = Py_None;
+ Py_INCREF (Py_None);
+ }
+
+ return result;
+}
+
+static PyObject *
+frapy_get_type (PyObject *self, PyObject *args)
+{
+ struct frame_info *frame;
+ enum frame_type type = NORMAL_FRAME;/* Initialize to appease gcc warning. */
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
+
+ type = get_frame_type (frame);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return PyInt_FromLong (type);
+}
+
+static PyObject *
+frapy_get_unwind_stop_reason (PyObject *self, PyObject *args)
+{
+ struct frame_info *frame = NULL; /* Initialize to appease gcc warning. */
+ volatile struct gdb_exception except;
+ enum unwind_stop_reason stop_reason;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ stop_reason = get_frame_unwind_stop_reason (frame);
+
+ return PyInt_FromLong (stop_reason);
+}
+
+static PyObject *
+frapy_get_pc (PyObject *self, PyObject *args)
+{
+ CORE_ADDR pc = 0; /* Initialize to appease gcc warning. */
+ struct frame_info *frame;
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
+
+ pc = get_frame_pc (frame);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return PyLong_FromUnsignedLongLong (pc);
+}
+
+static PyObject *
+frapy_get_address_in_block (PyObject *self, PyObject *args)
+{
+ CORE_ADDR pc = 0; /* Initialize to appease gcc warning. */
+ struct frame_info *frame;
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
+
+ pc = get_frame_address_in_block (frame);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return PyLong_FromUnsignedLongLong (pc);
+}
+
+static frame_object *
+frame_info_to_frame_object (struct frame_info *frame)
+{
+ frame_object *frame_obj;
+
+ frame_obj = PyObject_New (frame_object, &frame_object_type);
+ if (frame_obj == NULL)
+ {
+ PyErr_SetString (PyExc_MemoryError, "Could not allocate frame object.");
+ 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)
+ {
+ 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);
+
+ return frame_obj;
+}
+
+static struct frame_info *
+frame_object_to_frame_info (frame_object *frame_obj)
+{
+ struct frame_info *frame;
+
+ frame = frame_find_by_id (frame_obj->frame_id);
+ if (frame == NULL)
+ return NULL;
+
+ if (frame_obj->frame_id_is_next)
+ frame = get_prev_frame (frame);
+
+ return frame;
+}
+
+static PyObject *
+frapy_get_prev (PyObject *self, PyObject *args)
+{
+ struct frame_info *frame, *prev;
+ 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);
+
+ 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);
+
+ return prev_obj;
+}
+
+static PyObject *
+frapy_get_next (PyObject *self, PyObject *args)
+{
+ struct frame_info *frame, *next;
+ 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);
+
+ 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);
+
+ return next_obj;
+}
+
+PyObject *
+gdbpy_get_frames (PyObject *self, PyObject *args)
+{
+ int result = 0;
+ struct frame_info *frame;
+ frame_object *frame_obj;
+ PyObject *list, *tuple;
+ volatile struct gdb_exception except;
+
+ list = PyList_New (0);
+ if (list == NULL)
+ {
+ PyErr_SetString (PyExc_MemoryError, "Could not allocate frames list.");
+ return NULL;
+ }
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ for (frame = get_current_frame (); frame; frame = get_prev_frame (frame))
+ {
+ frame_obj = frame_info_to_frame_object (frame);
+ if (frame_obj == NULL)
+ {
+ Py_DECREF (list);
+ return NULL;
+ }
+
+ PyList_Append (list, (PyObject *) frame_obj);
+ }
+ }
+ if (except.reason < 0)
+ {
+ Py_DECREF (list);
+ return PyErr_Format (except.reason == RETURN_QUIT
+ ? PyExc_KeyboardInterrupt : PyExc_RuntimeError,
+ "%s", except.message);
+ }
+
+ tuple = PyList_AsTuple (list);
+ Py_DECREF (list);
+
+ return tuple;
+}
+
+PyObject *
+gdbpy_get_current_frame (PyObject *self, PyObject *args)
+{
+ struct frame_info *frame;
+ frame_object *frame_obj = NULL; /* Initialize to appease gcc warning. */
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ frame = get_current_frame ();
+ frame_obj = frame_info_to_frame_object (frame);
+ if (frame_obj == NULL)
+ return NULL;
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return (PyObject *) frame_obj;
+}
+
+PyObject *
+gdbpy_get_selected_frame (PyObject *self, PyObject *args)
+{
+ struct frame_info *frame;
+ frame_object *frame_obj = NULL; /* Initialize to appease gcc warning. */
+ 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);
+ if (frame_obj == NULL)
+ return NULL;
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return (PyObject *) frame_obj;
+}
+
+PyObject *
+gdbpy_frame_stop_reason_string (PyObject *self, PyObject *args)
+{
+ int reason;
+ const char *str;
+
+ if (!PyArg_ParseTuple (args, "i", &reason))
+ return NULL;
+
+ if (reason < 0 || reason > UNWIND_NO_SAVED_PC)
+ {
+ PyErr_SetString (PyExc_ValueError, "Invalid frame stop reason.");
+ return NULL;
+ }
+
+ str = frame_stop_reason_string (reason);
+ return PyString_Decode (str, strlen (str), host_charset (), NULL /* FIXME */);
+}
+
+void
+gdbpy_initialize_frames (void)
+{
+ frame_object_type.tp_new = PyType_GenericNew;
+ if (PyType_Ready (&frame_object_type) < 0)
+ return;
+
+ /* FIXME: 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);
+}
Index: tromey.git/gdb/python/python-internal.h
===================================================================
--- tromey.git.orig/gdb/python/python-internal.h 2008-04-29 11:05:20.000000000 -0300
+++ tromey.git/gdb/python/python-internal.h 2008-04-29 11:05:45.000000000 -0300
@@ -32,6 +32,10 @@ extern PyTypeObject value_object_type;
PyObject *gdbpy_make_value_from_int (PyObject *self, PyObject *args);
PyObject *gdbpy_get_value_from_history (PyObject *self, PyObject *args);
PyObject *gdbpy_get_breakpoints (PyObject *, PyObject *);
+PyObject *gdbpy_get_frames (PyObject *, PyObject *);
+PyObject *gdbpy_get_current_frame (PyObject *, PyObject *);
+PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *);
+PyObject *gdbpy_get_selected_frame (PyObject *self, PyObject *args);

PyObject *variable_to_python (struct cmd_list_element *);
PyObject *value_to_value_object (struct value *v);
@@ -44,6 +48,7 @@ PyObject *gdbpy_get_hook_function (const
void gdbpy_initialize_values (void);
void gdbpy_initialize_hooks (void);
void gdbpy_initialize_breakpoints (void);
+void gdbpy_initialize_frames (void);
void gdbpy_initialize_commands (void);

/* Use this after a TRY_EXCEPT to throw the appropriate Python
Index: tromey.git/gdb/python/python.c
===================================================================
--- tromey.git.orig/gdb/python/python.c 2008-04-29 11:05:20.000000000 -0300
+++ tromey.git/gdb/python/python.c 2008-04-29 11:05:45.000000000 -0300
@@ -24,6 +24,7 @@
#include "cli/cli-decode.h"
#include "charset.h"
#include "top.h"
+#include "solib.h"
#include "exceptions.h"
#include "python-internal.h"
#include "version.h"
@@ -34,6 +35,7 @@ PyObject *gdb_module;

static PyObject *get_show_variable (PyObject *, PyObject *);
static PyObject *execute_gdb_command (PyObject *, PyObject *);
+static PyObject *gdbpy_solib_address (PyObject *, PyObject *);

void
@@ -56,6 +58,18 @@ demand_python ()
{ "get_breakpoints", gdbpy_get_breakpoints, METH_NOARGS,
"Return a tuple of all breakpoint objects" },

+ { "get_frames", gdbpy_get_frames, METH_NOARGS,
+ "Return a tuple of all frame objects" },
+ { "get_current_frame", gdbpy_get_current_frame, METH_NOARGS,
+ "Return the current frame object" },
+ { "get_selected_frame", gdbpy_get_selected_frame, METH_NOARGS,
+ "Return the selected frame object" },
+ { "frame_stop_reason_string", gdbpy_frame_stop_reason_string,
+ METH_VARARGS, "Return a string explaining unwind stop reason" },
+
+ { "solib_address", gdbpy_solib_address, METH_VARARGS,
+ "Return shared library holding a given address, or None." },
+
{NULL, NULL, 0, NULL}
};

@@ -70,6 +84,7 @@ demand_python ()
gdbpy_initialize_hooks ();
gdbpy_initialize_values ();
gdbpy_initialize_breakpoints ();
+ gdbpy_initialize_frames ();
gdbpy_initialize_commands ();

PyRun_SimpleString ("import gdb");
@@ -327,6 +342,29 @@ value_of_python (char *expr, int length)
return value;
}

+PyObject *
+gdbpy_solib_address (PyObject *self, PyObject *args)
+{
+ unsigned long long pc;
+ char *soname;
+ PyObject *str_obj;
+
+ if (!PyArg_ParseTuple (args, "K", &pc))
+ return NULL;
+
+ soname = solib_address (pc);
+ if (soname)
+ str_obj = PyString_Decode (soname, strlen (soname), host_charset (),
+ NULL /* FIXME */);
+ else
+ {
+ str_obj = Py_None;
+ Py_INCREF (Py_None);
+ }
+
+ return str_obj;
+}
+
\f

void
Index: tromey.git/gdb/stack.c
===================================================================
--- tromey.git.orig/gdb/stack.c 2008-04-29 10:57:39.000000000 -0300
+++ tromey.git/gdb/stack.c 2008-04-29 11:05:45.000000000 -0300
@@ -562,19 +562,16 @@ print_frame_info (struct frame_info *fra
gdb_flush (gdb_stdout);
}

-static void
-print_frame (struct frame_info *frame, int print_level,
- enum print_what print_what, int print_args,
- struct symtab_and_line sal)
+/* Attempt to obtain the FUNNAME and FUNLANG of the function corresponding
+ to FRAME. */
+void
+find_frame_funname (struct frame_info *frame, char **funname,
+ enum language *funlang)
{
struct symbol *func;
- char *funname = NULL;
- enum language funlang = language_unknown;
- struct ui_stream *stb;
- struct cleanup *old_chain, *list_chain;

- stb = ui_out_stream_new (uiout);
- old_chain = make_cleanup_ui_out_stream_delete (stb);
+ *funname = NULL;
+ *funlang = language_unknown;

func = find_pc_function (get_frame_address_in_block (frame));
if (func)
@@ -607,14 +604,14 @@ print_frame (struct frame_info *frame, i
/* We also don't know anything about the function besides
its address and name. */
func = 0;
- funname = DEPRECATED_SYMBOL_NAME (msymbol);
- funlang = SYMBOL_LANGUAGE (msymbol);
+ *funname = DEPRECATED_SYMBOL_NAME (msymbol);
+ *funlang = SYMBOL_LANGUAGE (msymbol);
}
else
{
- funname = DEPRECATED_SYMBOL_NAME (func);
- funlang = SYMBOL_LANGUAGE (func);
- if (funlang == language_cplus)
+ *funname = DEPRECATED_SYMBOL_NAME (func);
+ *funlang = SYMBOL_LANGUAGE (func);
+ if (*funlang == language_cplus)
{
/* It seems appropriate to use SYMBOL_PRINT_NAME() here,
to display the demangled name that we already have
@@ -629,12 +626,12 @@ print_frame (struct frame_info *frame, i
too. So we want to catch the failure (where DEMANGLED
is NULL below) here, while we still have our hands on
the function symbol.) */
- char *demangled = cplus_demangle (funname, DMGL_ANSI);
+ char *demangled = cplus_demangle (*funname, DMGL_ANSI);
if (demangled == NULL)
/* If the demangler fails, try the demangled name from
the symbol table. That'll have parameters, but
that's preferable to displaying a mangled name. */
- funname = SYMBOL_PRINT_NAME (func);
+ *funname = SYMBOL_PRINT_NAME (func);
else
xfree (demangled);
}
@@ -647,10 +644,26 @@ print_frame (struct frame_info *frame, i

if (msymbol != NULL)
{
- funname = DEPRECATED_SYMBOL_NAME (msymbol);
- funlang = SYMBOL_LANGUAGE (msymbol);
+ *funname = DEPRECATED_SYMBOL_NAME (msymbol);
+ *funlang = SYMBOL_LANGUAGE (msymbol);
}
}
+}
+
+static void
+print_frame (struct frame_info *frame, int print_level,
+ enum print_what print_what, int print_args,
+ struct symtab_and_line sal)
+{
+ char *funname = NULL;
+ enum language funlang = language_unknown;
+ struct ui_stream *stb;
+ struct cleanup *old_chain, *list_chain;
+
+ stb = ui_out_stream_new (uiout);
+ old_chain = make_cleanup_ui_out_stream_delete (stb);
+
+ find_frame_funname (frame, &funname, &funlang);

annotate_frame_begin (print_level ? frame_relative_level (frame) : 0,
get_frame_pc (frame));
@@ -685,7 +698,7 @@ print_frame (struct frame_info *frame, i
struct print_args_args args;
struct cleanup *args_list_chain;
args.frame = frame;
- args.func = func;
+ args.func = find_pc_function (get_frame_address_in_block (frame));
args.stream = gdb_stdout;
args_list_chain = make_cleanup_ui_out_list_begin_end (uiout, "args");
catch_errors (print_args_stub, &args, "", RETURN_MASK_ERROR);
Index: tromey.git/gdb/stack.h
===================================================================
--- tromey.git.orig/gdb/stack.h 2008-04-29 10:57:39.000000000 -0300
+++ tromey.git/gdb/stack.h 2008-04-29 11:05:45.000000000 -0300
@@ -22,4 +22,9 @@

void select_frame_command (char *level_exp, int from_tty);

+/* Attempt to obtain the FUNNAME and FUNLANG of the function corresponding
+ to FRAME. */
+void find_frame_funname (struct frame_info *frame, char **funname,
+ enum language *funlang);
+
#endif /* #ifndef STACK_H */

--
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center