2008-04-29 Thiago Jung Bauermann Tom Tromey * 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 . */ + +#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; +} + 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