2002-06-01 22:44:21 +02:00
|
|
|
/* Cache and manage frames for GDB, the GNU debugger.
|
2002-04-10 00:14:39 +02:00
|
|
|
|
|
|
|
Copyright 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000,
|
2004-01-11 17:52:16 +01:00
|
|
|
2001, 2002, 2003, 2004 Free Software Foundation, Inc.
|
2001-02-20 23:39:03 +01:00
|
|
|
|
|
|
|
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 2 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, write to the Free Software
|
|
|
|
Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
|
Boston, MA 02111-1307, USA. */
|
|
|
|
|
|
|
|
#include "defs.h"
|
|
|
|
#include "frame.h"
|
|
|
|
#include "target.h"
|
|
|
|
#include "value.h"
|
2001-05-04 06:15:33 +02:00
|
|
|
#include "inferior.h" /* for inferior_ptid */
|
2001-03-01 02:39:22 +01:00
|
|
|
#include "regcache.h"
|
2002-06-01 22:44:21 +02:00
|
|
|
#include "gdb_assert.h"
|
2002-09-25 22:30:38 +02:00
|
|
|
#include "gdb_string.h"
|
2003-07-07 16:36:58 +02:00
|
|
|
#include "user-regs.h"
|
2002-11-08 21:48:55 +01:00
|
|
|
#include "gdb_obstack.h"
|
|
|
|
#include "dummy-frame.h"
|
2003-01-27 22:41:41 +01:00
|
|
|
#include "sentinel-frame.h"
|
2002-11-08 21:48:55 +01:00
|
|
|
#include "gdbcore.h"
|
|
|
|
#include "annotate.h"
|
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* stack.c (selected_frame, select_frame): Move from here ...
* frame.c (selected_frame, select_frame): ... to here. Include
"language.h".
* Makefile.in (frame.o): Update dependencies.
* frame.c (get_selected_frame): New function.
* frame.h (get_selected_frame): Declare.
(deprecated_selected_frame): Rename selected_frame.
* ada-lang.c, ada-tasks.c, breakpoint.c, corelow.c: Update.
* eval.c, f-valprint.c, findvar.c, frame.c, frame.h: Update.
* h8300-tdep.c, h8500-tdep.c, hppa-tdep.c, infcmd.c: Update.
* inflow.c, infrun.c, macroscope.c, mips-tdep.c: Update.
* mn10300-tdep.c, ocd.c, regcache.h, remote-e7000.c: Update.
* remote-mips.c, remote-rdp.c, sh-tdep.c, sparc-tdep.c: Update.
* stack.c, thread.c, tracepoint.c, valops.c, varobj.c: Update.
* z8k-tdep.c, cli/cli-cmds.c: Update.
Index: mi/ChangeLog
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* mi/mi-cmd-stack.c, mi/mi-main.c: Update to use
deprecated_selected_frame.
Index: tui/ChangeLog
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* tui/tui-hooks.c: Update to use deprecated_selected_frame.
* tui/tui.c, tui/tuiDisassem.c, tui/tuiRegs.c: Ditto.
* tui/tuiSource.c, tui/tuiSourceWin.c, tui/tuiWin.c: Ditto.
2002-11-29 20:15:16 +01:00
|
|
|
#include "language.h"
|
2003-01-18 Andrew Cagney <ac131313@redhat.com>
* dummy-frame.h (dummy_frame_id_unwind): Delete declaration.
(dummy_frame_pc_unwind, dummy_frame_register_unwind): Ditto.
(struct frame_unwind): Declare opaque.
(dummy_frame_p): Declare function.
* dummy-frame.c (dummy_frame_id_unwind): Make static.
(dummy_frame_pc_unwind, dummy_frame_register_unwind): Ditto.
* dummy-frame.c: Include "frame-unwind.h".
(dummy_frame_p): New function.
(dummy_frame_unwind): New variable.
* frame.c: Include "frame-unwind.h".
(frame_pc_unwind, frame_id_unwind, frame_register_unwind): Update
to use the new unwind field.
(set_unwind_by_pc): Delete function.
(create_new_frame, get_prev_frame): Set unwind field using
frame_unwind_find_by_pc.
(trad_frame_unwind, trad_frame_unwinder): New variables.
* frame.h (trad_frame_unwind): Declare variable.
(frame_id_unwind_ftype): Delete declaration.
(frame_pc_unwind_ftype, frame_register_unwind_ftype): Ditto.
(struct frame_unwind): Declare opaque.
(struct frame_info): Replace the fields id_unwind, pc_unwind and
register_unwind with a single unwind pointer.
* frame-unwind.h, frame-unwind.c: New files.
* Makefile.in (SFILES): Add frame-unwind.c.
(frame_unwind_h): Define.
(COMMON_OBS): Add frame-unwind.o.
(frame-unwind.o): Specify dependencies.
(frame.o, dummy-frame.o): Update dependencies.
2003-01-18 18:25:23 +01:00
|
|
|
#include "frame-unwind.h"
|
2003-04-01 21:11:01 +02:00
|
|
|
#include "frame-base.h"
|
2003-01-21 20:32:42 +01:00
|
|
|
#include "command.h"
|
|
|
|
#include "gdbcmd.h"
|
2004-04-26 11:49:36 +02:00
|
|
|
#include "observer.h"
|
2003-01-21 20:32:42 +01:00
|
|
|
|
2004-03-31 21:40:28 +02:00
|
|
|
static struct frame_info *get_prev_frame_1 (struct frame_info *this_frame);
|
|
|
|
|
2003-04-13 02:10:22 +02:00
|
|
|
/* We keep a cache of stack frames, each of which is a "struct
|
|
|
|
frame_info". The innermost one gets allocated (in
|
|
|
|
wait_for_inferior) each time the inferior stops; current_frame
|
|
|
|
points to it. Additional frames get allocated (in get_prev_frame)
|
|
|
|
as needed, and are chained through the next and prev fields. Any
|
|
|
|
time that the frame cache becomes invalid (most notably when we
|
|
|
|
execute something, but also if we change how we interpret the
|
|
|
|
frames (e.g. "set heuristic-fence-post" in mips-tdep.c, or anything
|
|
|
|
which reads new symbols)), we should call reinit_frame_cache. */
|
|
|
|
|
|
|
|
struct frame_info
|
|
|
|
{
|
|
|
|
/* Level of this frame. The inner-most (youngest) frame is at level
|
|
|
|
0. As you move towards the outer-most (oldest) frame, the level
|
|
|
|
increases. This is a cached value. It could just as easily be
|
|
|
|
computed by counting back from the selected frame to the inner
|
|
|
|
most frame. */
|
2004-04-17 02:48:25 +02:00
|
|
|
/* NOTE: cagney/2002-04-05: Perhaps a level of ``-1'' should be
|
2003-04-13 02:10:22 +02:00
|
|
|
reserved to indicate a bogus frame - one that has been created
|
|
|
|
just to keep GDB happy (GDB always needs a frame). For the
|
|
|
|
moment leave this as speculation. */
|
|
|
|
int level;
|
|
|
|
|
|
|
|
/* The frame's low-level unwinder and corresponding cache. The
|
|
|
|
low-level unwinder is responsible for unwinding register values
|
|
|
|
for the previous frame. The low-level unwind methods are
|
2004-04-17 02:48:25 +02:00
|
|
|
selected based on the presence, or otherwise, of register unwind
|
2003-04-13 02:10:22 +02:00
|
|
|
information such as CFI. */
|
|
|
|
void *prologue_cache;
|
|
|
|
const struct frame_unwind *unwind;
|
|
|
|
|
|
|
|
/* Cached copy of the previous frame's resume address. */
|
|
|
|
struct {
|
|
|
|
int p;
|
|
|
|
CORE_ADDR value;
|
|
|
|
} prev_pc;
|
|
|
|
|
|
|
|
/* Cached copy of the previous frame's function address. */
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
CORE_ADDR addr;
|
|
|
|
int p;
|
|
|
|
} prev_func;
|
|
|
|
|
|
|
|
/* This frame's ID. */
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
int p;
|
|
|
|
struct frame_id value;
|
|
|
|
} this_id;
|
|
|
|
|
|
|
|
/* The frame's high-level base methods, and corresponding cache.
|
|
|
|
The high level base methods are selected based on the frame's
|
|
|
|
debug info. */
|
|
|
|
const struct frame_base *base;
|
|
|
|
void *base_cache;
|
|
|
|
|
|
|
|
/* Pointers to the next (down, inner, younger) and previous (up,
|
|
|
|
outer, older) frame_info's in the frame cache. */
|
|
|
|
struct frame_info *next; /* down, inner, younger */
|
|
|
|
int prev_p;
|
|
|
|
struct frame_info *prev; /* up, outer, older */
|
|
|
|
};
|
|
|
|
|
2003-02-26 00:12:22 +01:00
|
|
|
/* Flag to control debugging. */
|
|
|
|
|
|
|
|
static int frame_debug;
|
|
|
|
|
2003-08-09 17:10:09 +02:00
|
|
|
/* Flag to indicate whether backtraces should stop at main et.al. */
|
|
|
|
|
|
|
|
static int backtrace_past_main;
|
|
|
|
static unsigned int backtrace_limit = UINT_MAX;
|
2003-01-21 20:32:42 +01:00
|
|
|
|
2004-07-16 21:00:12 +02:00
|
|
|
static void
|
|
|
|
fprint_field (struct ui_file *file, const char *name, int p, CORE_ADDR addr)
|
|
|
|
{
|
|
|
|
if (p)
|
|
|
|
fprintf_unfiltered (file, "%s=0x%s", name, paddr_nz (addr));
|
|
|
|
else
|
|
|
|
fprintf_unfiltered (file, "!%s", name);
|
|
|
|
}
|
2001-02-20 23:39:03 +01:00
|
|
|
|
2003-05-05 20:33:11 +02:00
|
|
|
void
|
2003-04-10 17:32:27 +02:00
|
|
|
fprint_frame_id (struct ui_file *file, struct frame_id id)
|
|
|
|
{
|
2004-07-16 21:00:12 +02:00
|
|
|
fprintf_unfiltered (file, "{");
|
|
|
|
fprint_field (file, "stack", id.stack_addr_p, id.stack_addr);
|
|
|
|
fprintf_unfiltered (file, ",");
|
|
|
|
fprint_field (file, "code", id.code_addr_p, id.code_addr);
|
|
|
|
fprintf_unfiltered (file, ",");
|
|
|
|
fprint_field (file, "special", id.special_addr_p, id.special_addr);
|
|
|
|
fprintf_unfiltered (file, "}");
|
2003-04-10 17:32:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fprint_frame_type (struct ui_file *file, enum frame_type type)
|
|
|
|
{
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case NORMAL_FRAME:
|
|
|
|
fprintf_unfiltered (file, "NORMAL_FRAME");
|
|
|
|
return;
|
|
|
|
case DUMMY_FRAME:
|
|
|
|
fprintf_unfiltered (file, "DUMMY_FRAME");
|
|
|
|
return;
|
|
|
|
case SIGTRAMP_FRAME:
|
|
|
|
fprintf_unfiltered (file, "SIGTRAMP_FRAME");
|
|
|
|
return;
|
|
|
|
default:
|
|
|
|
fprintf_unfiltered (file, "<unknown type>");
|
|
|
|
return;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fprint_frame (struct ui_file *file, struct frame_info *fi)
|
|
|
|
{
|
|
|
|
if (fi == NULL)
|
|
|
|
{
|
|
|
|
fprintf_unfiltered (file, "<NULL frame>");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
fprintf_unfiltered (file, "{");
|
|
|
|
fprintf_unfiltered (file, "level=%d", fi->level);
|
|
|
|
fprintf_unfiltered (file, ",");
|
|
|
|
fprintf_unfiltered (file, "type=");
|
2004-07-31 23:41:50 +02:00
|
|
|
if (fi->unwind != NULL)
|
|
|
|
fprint_frame_type (file, fi->unwind->type);
|
|
|
|
else
|
|
|
|
fprintf_unfiltered (file, "<unknown>");
|
2003-04-10 17:32:27 +02:00
|
|
|
fprintf_unfiltered (file, ",");
|
|
|
|
fprintf_unfiltered (file, "unwind=");
|
|
|
|
if (fi->unwind != NULL)
|
|
|
|
gdb_print_host_address (fi->unwind, file);
|
|
|
|
else
|
|
|
|
fprintf_unfiltered (file, "<unknown>");
|
|
|
|
fprintf_unfiltered (file, ",");
|
|
|
|
fprintf_unfiltered (file, "pc=");
|
|
|
|
if (fi->next != NULL && fi->next->prev_pc.p)
|
|
|
|
fprintf_unfiltered (file, "0x%s", paddr_nz (fi->next->prev_pc.value));
|
|
|
|
else
|
|
|
|
fprintf_unfiltered (file, "<unknown>");
|
|
|
|
fprintf_unfiltered (file, ",");
|
|
|
|
fprintf_unfiltered (file, "id=");
|
|
|
|
if (fi->this_id.p)
|
|
|
|
fprint_frame_id (file, fi->this_id.value);
|
|
|
|
else
|
|
|
|
fprintf_unfiltered (file, "<unknown>");
|
|
|
|
fprintf_unfiltered (file, ",");
|
|
|
|
fprintf_unfiltered (file, "func=");
|
|
|
|
if (fi->next != NULL && fi->next->prev_func.p)
|
|
|
|
fprintf_unfiltered (file, "0x%s", paddr_nz (fi->next->prev_func.addr));
|
|
|
|
else
|
|
|
|
fprintf_unfiltered (file, "<unknown>");
|
|
|
|
fprintf_unfiltered (file, "}");
|
|
|
|
}
|
|
|
|
|
2002-12-04 01:05:54 +01:00
|
|
|
/* Return a frame uniq ID that can be used to, later, re-find the
|
2002-06-11 01:25:50 +02:00
|
|
|
frame. */
|
|
|
|
|
2002-12-04 01:05:54 +01:00
|
|
|
struct frame_id
|
|
|
|
get_frame_id (struct frame_info *fi)
|
2002-06-11 01:25:50 +02:00
|
|
|
{
|
|
|
|
if (fi == NULL)
|
|
|
|
{
|
2002-12-04 01:05:54 +01:00
|
|
|
return null_frame_id;
|
2002-06-11 01:25:50 +02:00
|
|
|
}
|
2003-04-10 05:30:36 +02:00
|
|
|
if (!fi->this_id.p)
|
2002-06-11 01:25:50 +02:00
|
|
|
{
|
2003-04-10 17:32:27 +02:00
|
|
|
if (frame_debug)
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "{ get_frame_id (fi=%d) ",
|
|
|
|
fi->level);
|
2003-04-16 16:39:47 +02:00
|
|
|
/* Find the unwinder. */
|
|
|
|
if (fi->unwind == NULL)
|
2004-07-31 23:41:50 +02:00
|
|
|
fi->unwind = frame_unwind_find_by_frame (fi->next,
|
|
|
|
&fi->prologue_cache);
|
2003-03-30 18:16:25 +02:00
|
|
|
/* Find THIS frame's ID. */
|
2003-04-10 05:30:36 +02:00
|
|
|
fi->unwind->this_id (fi->next, &fi->prologue_cache, &fi->this_id.value);
|
|
|
|
fi->this_id.p = 1;
|
2003-04-10 17:32:27 +02:00
|
|
|
if (frame_debug)
|
|
|
|
{
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "-> ");
|
|
|
|
fprint_frame_id (gdb_stdlog, fi->this_id.value);
|
|
|
|
fprintf_unfiltered (gdb_stdlog, " }\n");
|
|
|
|
}
|
2002-06-11 01:25:50 +02:00
|
|
|
}
|
2003-04-12 06:27:29 +02:00
|
|
|
return fi->this_id.value;
|
2002-06-11 01:25:50 +02:00
|
|
|
}
|
|
|
|
|
2004-03-31 21:40:28 +02:00
|
|
|
struct frame_id
|
|
|
|
frame_unwind_id (struct frame_info *next_frame)
|
|
|
|
{
|
|
|
|
/* Use prev_frame, and not get_prev_frame. The latter will truncate
|
|
|
|
the frame chain, leading to this function unintentionally
|
|
|
|
returning a null_frame_id (e.g., when a caller requests the frame
|
|
|
|
ID of "main()"s caller. */
|
|
|
|
return get_frame_id (get_prev_frame_1 (next_frame));
|
|
|
|
}
|
|
|
|
|
2002-12-04 01:05:54 +01:00
|
|
|
const struct frame_id null_frame_id; /* All zeros. */
|
|
|
|
|
|
|
|
struct frame_id
|
2003-10-17 18:32:17 +02:00
|
|
|
frame_id_build_special (CORE_ADDR stack_addr, CORE_ADDR code_addr,
|
|
|
|
CORE_ADDR special_addr)
|
2002-12-04 01:05:54 +01:00
|
|
|
{
|
2004-06-27 22:45:05 +02:00
|
|
|
struct frame_id id = null_frame_id;
|
2003-04-10 05:30:36 +02:00
|
|
|
id.stack_addr = stack_addr;
|
2004-06-27 22:45:05 +02:00
|
|
|
id.stack_addr_p = 1;
|
2003-04-10 05:30:36 +02:00
|
|
|
id.code_addr = code_addr;
|
2004-06-27 22:45:05 +02:00
|
|
|
id.code_addr_p = 1;
|
2003-10-17 18:32:17 +02:00
|
|
|
id.special_addr = special_addr;
|
2004-06-27 22:45:05 +02:00
|
|
|
id.special_addr_p = 1;
|
2002-12-04 01:05:54 +01:00
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
2003-10-17 18:32:17 +02:00
|
|
|
struct frame_id
|
|
|
|
frame_id_build (CORE_ADDR stack_addr, CORE_ADDR code_addr)
|
|
|
|
{
|
2004-06-27 22:45:05 +02:00
|
|
|
struct frame_id id = null_frame_id;
|
|
|
|
id.stack_addr = stack_addr;
|
|
|
|
id.stack_addr_p = 1;
|
|
|
|
id.code_addr = code_addr;
|
|
|
|
id.code_addr_p = 1;
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct frame_id
|
|
|
|
frame_id_build_wild (CORE_ADDR stack_addr)
|
|
|
|
{
|
|
|
|
struct frame_id id = null_frame_id;
|
|
|
|
id.stack_addr = stack_addr;
|
|
|
|
id.stack_addr_p = 1;
|
|
|
|
return id;
|
2003-10-17 18:32:17 +02:00
|
|
|
}
|
|
|
|
|
2002-12-04 01:05:54 +01:00
|
|
|
int
|
|
|
|
frame_id_p (struct frame_id l)
|
|
|
|
{
|
2003-04-10 05:30:36 +02:00
|
|
|
int p;
|
2004-06-27 22:45:05 +02:00
|
|
|
/* The frame is valid iff it has a valid stack address. */
|
|
|
|
p = l.stack_addr_p;
|
2003-04-10 17:32:27 +02:00
|
|
|
if (frame_debug)
|
|
|
|
{
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "{ frame_id_p (l=");
|
|
|
|
fprint_frame_id (gdb_stdlog, l);
|
|
|
|
fprintf_unfiltered (gdb_stdlog, ") -> %d }\n", p);
|
|
|
|
}
|
2003-04-10 05:30:36 +02:00
|
|
|
return p;
|
2002-12-04 01:05:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
frame_id_eq (struct frame_id l, struct frame_id r)
|
|
|
|
{
|
2003-04-10 05:30:36 +02:00
|
|
|
int eq;
|
2004-06-27 22:45:05 +02:00
|
|
|
if (!l.stack_addr_p || !r.stack_addr_p)
|
|
|
|
/* Like a NaN, if either ID is invalid, the result is false.
|
|
|
|
Note that a frame ID is invalid iff it is the null frame ID. */
|
2003-04-10 05:30:36 +02:00
|
|
|
eq = 0;
|
|
|
|
else if (l.stack_addr != r.stack_addr)
|
|
|
|
/* If .stack addresses are different, the frames are different. */
|
|
|
|
eq = 0;
|
2004-06-27 22:45:05 +02:00
|
|
|
else if (!l.code_addr_p || !r.code_addr_p)
|
|
|
|
/* An invalid code addr is a wild card, always succeed. */
|
2003-04-10 05:30:36 +02:00
|
|
|
eq = 1;
|
2003-10-17 18:32:17 +02:00
|
|
|
else if (l.code_addr != r.code_addr)
|
|
|
|
/* If .code addresses are different, the frames are different. */
|
|
|
|
eq = 0;
|
2004-06-27 22:45:05 +02:00
|
|
|
else if (!l.special_addr_p || !r.special_addr_p)
|
|
|
|
/* An invalid special addr is a wild card (or unused), always succeed. */
|
2003-10-17 18:32:17 +02:00
|
|
|
eq = 1;
|
|
|
|
else if (l.special_addr == r.special_addr)
|
|
|
|
/* Frames are equal. */
|
2003-04-10 05:30:36 +02:00
|
|
|
eq = 1;
|
|
|
|
else
|
2003-04-21 21:34:02 +02:00
|
|
|
/* No luck. */
|
|
|
|
eq = 0;
|
2003-04-10 17:32:27 +02:00
|
|
|
if (frame_debug)
|
|
|
|
{
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "{ frame_id_eq (l=");
|
|
|
|
fprint_frame_id (gdb_stdlog, l);
|
|
|
|
fprintf_unfiltered (gdb_stdlog, ",r=");
|
|
|
|
fprint_frame_id (gdb_stdlog, r);
|
|
|
|
fprintf_unfiltered (gdb_stdlog, ") -> %d }\n", eq);
|
|
|
|
}
|
2003-04-10 05:30:36 +02:00
|
|
|
return eq;
|
2002-12-04 01:05:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
frame_id_inner (struct frame_id l, struct frame_id r)
|
|
|
|
{
|
2003-04-10 05:30:36 +02:00
|
|
|
int inner;
|
2004-06-27 22:45:05 +02:00
|
|
|
if (!l.stack_addr_p || !r.stack_addr_p)
|
2003-04-10 05:30:36 +02:00
|
|
|
/* Like NaN, any operation involving an invalid ID always fails. */
|
|
|
|
inner = 0;
|
|
|
|
else
|
|
|
|
/* Only return non-zero when strictly inner than. Note that, per
|
|
|
|
comment in "frame.h", there is some fuzz here. Frameless
|
|
|
|
functions are not strictly inner than (same .stack but
|
2003-10-17 18:32:17 +02:00
|
|
|
different .code and/or .special address). */
|
2003-04-10 05:30:36 +02:00
|
|
|
inner = INNER_THAN (l.stack_addr, r.stack_addr);
|
2003-04-10 17:32:27 +02:00
|
|
|
if (frame_debug)
|
|
|
|
{
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "{ frame_id_inner (l=");
|
|
|
|
fprint_frame_id (gdb_stdlog, l);
|
|
|
|
fprintf_unfiltered (gdb_stdlog, ",r=");
|
|
|
|
fprint_frame_id (gdb_stdlog, r);
|
|
|
|
fprintf_unfiltered (gdb_stdlog, ") -> %d }\n", inner);
|
|
|
|
}
|
2003-04-10 05:30:36 +02:00
|
|
|
return inner;
|
2002-12-04 01:05:54 +01:00
|
|
|
}
|
|
|
|
|
2002-06-11 01:25:50 +02:00
|
|
|
struct frame_info *
|
|
|
|
frame_find_by_id (struct frame_id id)
|
|
|
|
{
|
|
|
|
struct frame_info *frame;
|
|
|
|
|
|
|
|
/* ZERO denotes the null frame, let the caller decide what to do
|
|
|
|
about it. Should it instead return get_current_frame()? */
|
2002-12-04 01:05:54 +01:00
|
|
|
if (!frame_id_p (id))
|
2002-06-11 01:25:50 +02:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (frame = get_current_frame ();
|
|
|
|
frame != NULL;
|
|
|
|
frame = get_prev_frame (frame))
|
|
|
|
{
|
2002-12-04 01:05:54 +01:00
|
|
|
struct frame_id this = get_frame_id (frame);
|
|
|
|
if (frame_id_eq (id, this))
|
|
|
|
/* An exact match. */
|
|
|
|
return frame;
|
|
|
|
if (frame_id_inner (id, this))
|
|
|
|
/* Gone to far. */
|
2002-06-11 01:25:50 +02:00
|
|
|
return NULL;
|
2004-04-17 02:48:25 +02:00
|
|
|
/* Either we're not yet gone far enough out along the frame
|
|
|
|
chain (inner(this,id)), or we're comparing frameless functions
|
2002-12-04 01:05:54 +01:00
|
|
|
(same .base, different .func, no test available). Struggle
|
|
|
|
on until we've definitly gone to far. */
|
2002-06-11 01:25:50 +02:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2002-11-15 23:16:25 +01:00
|
|
|
CORE_ADDR
|
2003-03-10 16:28:41 +01:00
|
|
|
frame_pc_unwind (struct frame_info *this_frame)
|
2002-11-15 23:16:25 +01:00
|
|
|
{
|
2003-04-09 22:49:22 +02:00
|
|
|
if (!this_frame->prev_pc.p)
|
2002-11-15 23:16:25 +01:00
|
|
|
{
|
2003-03-10 16:28:41 +01:00
|
|
|
CORE_ADDR pc;
|
|
|
|
if (gdbarch_unwind_pc_p (current_gdbarch))
|
|
|
|
{
|
|
|
|
/* The right way. The `pure' way. The one true way. This
|
|
|
|
method depends solely on the register-unwind code to
|
|
|
|
determine the value of registers in THIS frame, and hence
|
|
|
|
the value of this frame's PC (resume address). A typical
|
|
|
|
implementation is no more than:
|
|
|
|
|
|
|
|
frame_unwind_register (this_frame, ISA_PC_REGNUM, buf);
|
2003-05-22 20:37:05 +02:00
|
|
|
return extract_unsigned_integer (buf, size of ISA_PC_REGNUM);
|
2003-03-10 16:28:41 +01:00
|
|
|
|
|
|
|
Note: this method is very heavily dependent on a correct
|
|
|
|
register-unwind implementation, it pays to fix that
|
|
|
|
method first; this method is frame type agnostic, since
|
|
|
|
it only deals with register values, it works with any
|
|
|
|
frame. This is all in stark contrast to the old
|
|
|
|
FRAME_SAVED_PC which would try to directly handle all the
|
|
|
|
different ways that a PC could be unwound. */
|
|
|
|
pc = gdbarch_unwind_pc (current_gdbarch, this_frame);
|
|
|
|
}
|
|
|
|
else if (this_frame->level < 0)
|
|
|
|
{
|
2004-04-17 02:48:25 +02:00
|
|
|
/* FIXME: cagney/2003-03-06: Old code and a sentinel
|
2003-03-10 16:28:41 +01:00
|
|
|
frame. Do like was always done. Fetch the PC's value
|
2004-04-17 02:48:25 +02:00
|
|
|
directly from the global registers array (via read_pc).
|
2003-03-10 16:28:41 +01:00
|
|
|
This assumes that this frame belongs to the current
|
|
|
|
global register cache. The assumption is dangerous. */
|
|
|
|
pc = read_pc ();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
internal_error (__FILE__, __LINE__, "No gdbarch_unwind_pc method");
|
2003-04-09 22:49:22 +02:00
|
|
|
this_frame->prev_pc.value = pc;
|
|
|
|
this_frame->prev_pc.p = 1;
|
2003-04-10 17:32:27 +02:00
|
|
|
if (frame_debug)
|
|
|
|
fprintf_unfiltered (gdb_stdlog,
|
|
|
|
"{ frame_pc_unwind (this_frame=%d) -> 0x%s }\n",
|
|
|
|
this_frame->level,
|
|
|
|
paddr_nz (this_frame->prev_pc.value));
|
2002-11-15 23:16:25 +01:00
|
|
|
}
|
2003-04-09 22:49:22 +02:00
|
|
|
return this_frame->prev_pc.value;
|
2002-11-15 23:16:25 +01:00
|
|
|
}
|
|
|
|
|
2003-04-05 20:54:38 +02:00
|
|
|
CORE_ADDR
|
|
|
|
frame_func_unwind (struct frame_info *fi)
|
|
|
|
{
|
|
|
|
if (!fi->prev_func.p)
|
|
|
|
{
|
2003-08-04 17:42:43 +02:00
|
|
|
/* Make certain that this, and not the adjacent, function is
|
|
|
|
found. */
|
|
|
|
CORE_ADDR addr_in_block = frame_unwind_address_in_block (fi);
|
2003-04-05 20:54:38 +02:00
|
|
|
fi->prev_func.p = 1;
|
2003-08-04 17:42:43 +02:00
|
|
|
fi->prev_func.addr = get_pc_function_start (addr_in_block);
|
2003-04-10 17:32:27 +02:00
|
|
|
if (frame_debug)
|
|
|
|
fprintf_unfiltered (gdb_stdlog,
|
|
|
|
"{ frame_func_unwind (fi=%d) -> 0x%s }\n",
|
|
|
|
fi->level, paddr_nz (fi->prev_func.addr));
|
2003-04-05 20:54:38 +02:00
|
|
|
}
|
|
|
|
return fi->prev_func.addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
CORE_ADDR
|
|
|
|
get_frame_func (struct frame_info *fi)
|
|
|
|
{
|
|
|
|
return frame_func_unwind (fi->next);
|
|
|
|
}
|
|
|
|
|
2003-03-12 16:39:30 +01:00
|
|
|
static int
|
2004-08-02 05:36:24 +02:00
|
|
|
do_frame_register_read (void *src, int regnum, void *buf)
|
2003-03-12 16:39:30 +01:00
|
|
|
{
|
2004-08-02 05:36:24 +02:00
|
|
|
frame_register_read (src, regnum, buf);
|
2003-03-12 16:39:30 +01:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2004-08-02 05:36:24 +02:00
|
|
|
struct regcache *
|
|
|
|
frame_save_as_regcache (struct frame_info *this_frame)
|
|
|
|
{
|
|
|
|
struct regcache *regcache = regcache_xmalloc (current_gdbarch);
|
|
|
|
struct cleanup *cleanups = make_cleanup_regcache_xfree (regcache);
|
|
|
|
regcache_save (regcache, do_frame_register_read, this_frame);
|
|
|
|
discard_cleanups (cleanups);
|
|
|
|
return regcache;
|
|
|
|
}
|
|
|
|
|
2003-01-19 18:39:16 +01:00
|
|
|
void
|
2003-03-12 16:39:30 +01:00
|
|
|
frame_pop (struct frame_info *this_frame)
|
|
|
|
{
|
2004-07-31 23:41:50 +02:00
|
|
|
/* Make a copy of all the register values unwound from this frame.
|
|
|
|
Save them in a scratch buffer so that there isn't a race between
|
|
|
|
trying to extract the old values from the current_regcache while
|
|
|
|
at the same time writing new values into that same cache. */
|
2004-08-02 05:36:24 +02:00
|
|
|
struct regcache *scratch
|
|
|
|
= frame_save_as_regcache (get_prev_frame_1 (this_frame));
|
2004-07-31 23:41:50 +02:00
|
|
|
struct cleanup *cleanups = make_cleanup_regcache_xfree (scratch);
|
|
|
|
|
|
|
|
/* FIXME: cagney/2003-03-16: It should be possible to tell the
|
|
|
|
target's register cache that it is about to be hit with a burst
|
|
|
|
register transfer and that the sequence of register writes should
|
|
|
|
be batched. The pair target_prepare_to_store() and
|
|
|
|
target_store_registers() kind of suggest this functionality.
|
|
|
|
Unfortunately, they don't implement it. Their lack of a formal
|
|
|
|
definition can lead to targets writing back bogus values
|
|
|
|
(arguably a bug in the target code mind). */
|
|
|
|
/* Now copy those saved registers into the current regcache.
|
|
|
|
Here, regcache_cpy() calls regcache_restore(). */
|
|
|
|
regcache_cpy (current_regcache, scratch);
|
|
|
|
do_cleanups (cleanups);
|
2003-03-12 16:39:30 +01:00
|
|
|
|
|
|
|
/* We've made right mess of GDB's local state, just discard
|
|
|
|
everything. */
|
2003-01-19 18:39:16 +01:00
|
|
|
flush_cached_frames ();
|
|
|
|
}
|
2002-12-13 17:40:25 +01:00
|
|
|
|
2002-06-01 22:44:21 +02:00
|
|
|
void
|
|
|
|
frame_register_unwind (struct frame_info *frame, int regnum,
|
|
|
|
int *optimizedp, enum lval_type *lvalp,
|
|
|
|
CORE_ADDR *addrp, int *realnump, void *bufferp)
|
|
|
|
{
|
|
|
|
struct frame_unwind_cache *cache;
|
|
|
|
|
2003-04-10 17:32:27 +02:00
|
|
|
if (frame_debug)
|
|
|
|
{
|
2004-02-09 05:10:58 +01:00
|
|
|
fprintf_unfiltered (gdb_stdlog, "\
|
|
|
|
{ frame_register_unwind (frame=%d,regnum=%d(%s),...) ",
|
|
|
|
frame->level, regnum,
|
|
|
|
frame_map_regnum_to_name (frame, regnum));
|
2003-04-10 17:32:27 +02:00
|
|
|
}
|
|
|
|
|
2002-06-01 22:44:21 +02:00
|
|
|
/* Require all but BUFFERP to be valid. A NULL BUFFERP indicates
|
|
|
|
that the value proper does not need to be fetched. */
|
|
|
|
gdb_assert (optimizedp != NULL);
|
|
|
|
gdb_assert (lvalp != NULL);
|
|
|
|
gdb_assert (addrp != NULL);
|
|
|
|
gdb_assert (realnump != NULL);
|
|
|
|
/* gdb_assert (bufferp != NULL); */
|
|
|
|
|
2003-01-27 22:41:41 +01:00
|
|
|
/* NOTE: cagney/2002-11-27: A program trying to unwind a NULL frame
|
|
|
|
is broken. There is always a frame. If there, for some reason,
|
2004-04-17 02:48:25 +02:00
|
|
|
isn't a frame, there is some pretty busted code as it should have
|
2003-01-27 22:41:41 +01:00
|
|
|
detected the problem before calling here. */
|
|
|
|
gdb_assert (frame != NULL);
|
2002-06-01 22:44:21 +02:00
|
|
|
|
2003-04-16 16:39:47 +02:00
|
|
|
/* Find the unwinder. */
|
|
|
|
if (frame->unwind == NULL)
|
2004-07-31 23:41:50 +02:00
|
|
|
frame->unwind = frame_unwind_find_by_frame (frame->next,
|
|
|
|
&frame->prologue_cache);
|
2003-04-16 16:39:47 +02:00
|
|
|
|
2003-03-17 15:23:50 +01:00
|
|
|
/* Ask this frame to unwind its register. See comment in
|
2004-04-17 02:48:25 +02:00
|
|
|
"frame-unwind.h" for why NEXT frame and this unwind cache are
|
2003-03-17 15:23:50 +01:00
|
|
|
passed in. */
|
|
|
|
frame->unwind->prev_register (frame->next, &frame->prologue_cache, regnum,
|
|
|
|
optimizedp, lvalp, addrp, realnump, bufferp);
|
|
|
|
|
2003-04-10 17:32:27 +02:00
|
|
|
if (frame_debug)
|
|
|
|
{
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "->");
|
|
|
|
fprintf_unfiltered (gdb_stdlog, " *optimizedp=%d", (*optimizedp));
|
|
|
|
fprintf_unfiltered (gdb_stdlog, " *lvalp=%d", (int) (*lvalp));
|
|
|
|
fprintf_unfiltered (gdb_stdlog, " *addrp=0x%s", paddr_nz ((*addrp)));
|
|
|
|
fprintf_unfiltered (gdb_stdlog, " *bufferp=");
|
|
|
|
if (bufferp == NULL)
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "<NULL>");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int i;
|
2003-06-29 15:27:26 +02:00
|
|
|
const unsigned char *buf = bufferp;
|
2003-04-10 17:32:27 +02:00
|
|
|
fprintf_unfiltered (gdb_stdlog, "[");
|
|
|
|
for (i = 0; i < register_size (current_gdbarch, regnum); i++)
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]);
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "]");
|
|
|
|
}
|
|
|
|
fprintf_unfiltered (gdb_stdlog, " }\n");
|
|
|
|
}
|
2002-06-01 22:44:21 +02:00
|
|
|
}
|
|
|
|
|
2002-11-05 22:44:05 +01:00
|
|
|
void
|
|
|
|
frame_register (struct frame_info *frame, int regnum,
|
|
|
|
int *optimizedp, enum lval_type *lvalp,
|
|
|
|
CORE_ADDR *addrp, int *realnump, void *bufferp)
|
|
|
|
{
|
|
|
|
/* Require all but BUFFERP to be valid. A NULL BUFFERP indicates
|
|
|
|
that the value proper does not need to be fetched. */
|
|
|
|
gdb_assert (optimizedp != NULL);
|
|
|
|
gdb_assert (lvalp != NULL);
|
|
|
|
gdb_assert (addrp != NULL);
|
|
|
|
gdb_assert (realnump != NULL);
|
|
|
|
/* gdb_assert (bufferp != NULL); */
|
|
|
|
|
2003-01-27 22:41:41 +01:00
|
|
|
/* Obtain the register value by unwinding the register from the next
|
|
|
|
(more inner frame). */
|
|
|
|
gdb_assert (frame != NULL && frame->next != NULL);
|
|
|
|
frame_register_unwind (frame->next, regnum, optimizedp, lvalp, addrp,
|
|
|
|
realnump, bufferp);
|
2002-11-05 22:44:05 +01:00
|
|
|
}
|
|
|
|
|
2002-09-17 22:42:01 +02:00
|
|
|
void
|
2003-02-02 21:31:43 +01:00
|
|
|
frame_unwind_register (struct frame_info *frame, int regnum, void *buf)
|
2002-09-17 22:42:01 +02:00
|
|
|
{
|
|
|
|
int optimized;
|
|
|
|
CORE_ADDR addr;
|
|
|
|
int realnum;
|
|
|
|
enum lval_type lval;
|
|
|
|
frame_register_unwind (frame, regnum, &optimized, &lval, &addr,
|
|
|
|
&realnum, buf);
|
2003-02-02 21:31:43 +01:00
|
|
|
}
|
|
|
|
|
2003-06-21 18:26:02 +02:00
|
|
|
void
|
|
|
|
get_frame_register (struct frame_info *frame,
|
|
|
|
int regnum, void *buf)
|
|
|
|
{
|
|
|
|
frame_unwind_register (frame->next, regnum, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
LONGEST
|
|
|
|
frame_unwind_register_signed (struct frame_info *frame, int regnum)
|
|
|
|
{
|
|
|
|
char buf[MAX_REGISTER_SIZE];
|
|
|
|
frame_unwind_register (frame, regnum, buf);
|
2004-08-01 23:47:19 +02:00
|
|
|
return extract_signed_integer (buf, register_size (get_frame_arch (frame),
|
|
|
|
regnum));
|
2003-06-21 18:26:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
LONGEST
|
|
|
|
get_frame_register_signed (struct frame_info *frame, int regnum)
|
|
|
|
{
|
|
|
|
return frame_unwind_register_signed (frame->next, regnum);
|
|
|
|
}
|
|
|
|
|
|
|
|
ULONGEST
|
|
|
|
frame_unwind_register_unsigned (struct frame_info *frame, int regnum)
|
|
|
|
{
|
|
|
|
char buf[MAX_REGISTER_SIZE];
|
|
|
|
frame_unwind_register (frame, regnum, buf);
|
2004-08-01 23:47:19 +02:00
|
|
|
return extract_unsigned_integer (buf, register_size (get_frame_arch (frame),
|
|
|
|
regnum));
|
2003-06-21 18:26:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ULONGEST
|
|
|
|
get_frame_register_unsigned (struct frame_info *frame, int regnum)
|
|
|
|
{
|
|
|
|
return frame_unwind_register_unsigned (frame->next, regnum);
|
|
|
|
}
|
|
|
|
|
2002-09-17 22:42:01 +02:00
|
|
|
void
|
|
|
|
frame_unwind_unsigned_register (struct frame_info *frame, int regnum,
|
|
|
|
ULONGEST *val)
|
|
|
|
{
|
2003-05-08 Andrew Cagney <cagney@redhat.com>
* gdbarch.sh: Delete references to MAX_REGISTER_RAW_SIZE.
* gdbarch.h: Re-generate.
* defs.h (MAX_REGISTER_RAW_SIZE): Delete macro.
(legacy_max_register_raw_size): Delete declaration.
* regcache.c (legacy_max_register_raw_size): Delete function.
* valops.c: Replace MAX_REGISTER_RAW_SIZE with MAX_REGISTER_SIZE.
* target.c, stack.c, sparc-tdep.c, sh-tdep.c: Update.
* rs6000-tdep.c, rs6000-nat.c, remote.c, remote-sim.c: Update.
* remote-rdp.c, remote-array.c, regcache.c: Update.
* ppc-linux-nat.c, monitor.c, mn10300-tdep.c: Update.
* mips-tdep.c, mips-linux-tdep.c, m68klinux-nat.c: Update.
* infptrace.c, ia64-tdep.c, i386-tdep.c, frame.c: Update.
* findvar.c, dwarf2cfi.c: Update.
Index: tui/ChangeLog
2003-05-08 Andrew Cagney <cagney@redhat.com>
* tuiRegs.c: Use MAX_REGISTER_SIZE instead of
MAX_REGISTER_RAW_SIZE.
Index: mi/ChangeLog
2003-05-08 Andrew Cagney <cagney@redhat.com>
* mi-main.c (register_changed_p): Use MAX_REGISTER_SIZE instead of
MAX_REGISTER_RAW_SIZE.
2003-05-08 22:52:49 +02:00
|
|
|
char buf[MAX_REGISTER_SIZE];
|
2003-02-02 21:31:43 +01:00
|
|
|
frame_unwind_register (frame, regnum, buf);
|
2004-08-01 23:47:19 +02:00
|
|
|
(*val) = extract_unsigned_integer (buf,
|
|
|
|
register_size (get_frame_arch (frame),
|
|
|
|
regnum));
|
2002-09-17 22:42:01 +02:00
|
|
|
}
|
2002-06-01 22:44:21 +02:00
|
|
|
|
2003-06-14 Andrew Cagney <cagney@redhat.com>
Mark Kettenis <kettenis@gnu.org>
* gdbarch.sh (CONVERT_REGISTER_P): Add "type" parameter.
(REGISTER_TO_VALUE, VALUE_TO_REGISTER): Replace raw buffer
parameter with "frame".
* gdbarch.h, gdbarch.c: Re-generate.
* frame.h (put_frame_register): Declare.
* frame.c (put_frame_register): New function.
* arch-utils.c (legacy_convert_register_p): Add "type" parameter.
(legacy_register_to_value): Rewrite, use "frame" to get the
register value.
(legacy_value_to_register): Rewrite, use "frame" to find the
register's location before storing.
* arch-utils.h (legacy_convert_register_p): Update.
(legacy_register_to_value, legacy_value_to_register): Update.
* findvar.c (value_from_register): Rewrite, eliminate use of
REGISTER_CONVERT_TO_TYPE, pass "type" to CONVERT_REGISTER_P, pass
"frame" to REGISTER_TO_VALUE.
* valops.c (value_assign): Move the CONVERT_REGISTER code to the
lval_reg_frame_relative + lval_register branch of the switch. Do
not use REGISTER_CONVERT_FROM_TYPE. Use put_frame_register.
* i386-tdep.c (I386_EBX_REGNUM, I386_ECX_REGNUM, I386_ESI_REGNUM,
I386_EDI_REGNUM): New defines.
(i386_next_regnum, i386_convert_register_p,
i386_register_to_value, i386_value_to_register): New functions.
(i386_register_convertible, i386_register_convert_to_virtual,
i386_convert_to_raw): Remove functions.
(i386_gdbarch_init): Set convert_register_p, register_to_value and
value_to_register instead of register_convertible,
register_convert_to_virtual and register_convert_to_raw.
* mips-tdep.c (mips_convert_register_p): New function.
(mips_value_to_register): Replace mips_register_convert_from_type.
(mips_register_to_value): Replace mips_register_convert_to_type.
(mips_gdbarch_init): Set conver_register_p, value_to_register and
register_to_value.
* alpha-tdep.c (alpha_convert_register_p): Update.
(alpha_value_to_register): Update, store the register.
(alpha_register_to_value): Update, fetch the register.
2003-06-15 00:35:25 +02:00
|
|
|
void
|
|
|
|
put_frame_register (struct frame_info *frame, int regnum, const void *buf)
|
|
|
|
{
|
|
|
|
struct gdbarch *gdbarch = get_frame_arch (frame);
|
|
|
|
int realnum;
|
|
|
|
int optim;
|
|
|
|
enum lval_type lval;
|
|
|
|
CORE_ADDR addr;
|
|
|
|
frame_register (frame, regnum, &optim, &lval, &addr, &realnum, NULL);
|
|
|
|
if (optim)
|
|
|
|
error ("Attempt to assign to a value that was optimized out.");
|
|
|
|
switch (lval)
|
|
|
|
{
|
|
|
|
case lval_memory:
|
|
|
|
{
|
|
|
|
/* FIXME: write_memory doesn't yet take constant buffers.
|
|
|
|
Arrrg! */
|
|
|
|
char tmp[MAX_REGISTER_SIZE];
|
|
|
|
memcpy (tmp, buf, register_size (gdbarch, regnum));
|
|
|
|
write_memory (addr, tmp, register_size (gdbarch, regnum));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case lval_register:
|
|
|
|
regcache_cooked_write (current_regcache, realnum, buf);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
error ("Attempt to assign to an unmodifiable value.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-04-12 20:18:59 +02:00
|
|
|
/* frame_register_read ()
|
2001-02-20 23:39:03 +01:00
|
|
|
|
2002-04-12 20:18:59 +02:00
|
|
|
Find and return the value of REGNUM for the specified stack frame.
|
2004-08-01 23:47:19 +02:00
|
|
|
The number of bytes copied is REGISTER_SIZE (REGNUM).
|
2001-02-20 23:39:03 +01:00
|
|
|
|
2002-04-12 20:18:59 +02:00
|
|
|
Returns 0 if the register value could not be found. */
|
2001-02-20 23:39:03 +01:00
|
|
|
|
2002-04-12 20:18:59 +02:00
|
|
|
int
|
|
|
|
frame_register_read (struct frame_info *frame, int regnum, void *myaddr)
|
2001-02-20 23:39:03 +01:00
|
|
|
{
|
2002-11-05 22:44:05 +01:00
|
|
|
int optimized;
|
|
|
|
enum lval_type lval;
|
|
|
|
CORE_ADDR addr;
|
|
|
|
int realnum;
|
|
|
|
frame_register (frame, regnum, &optimized, &lval, &addr, &realnum, myaddr);
|
2001-02-20 23:39:03 +01:00
|
|
|
|
2004-04-17 02:48:25 +02:00
|
|
|
/* FIXME: cagney/2002-05-15: This test is just bogus.
|
2002-05-15 03:01:56 +02:00
|
|
|
|
|
|
|
It indicates that the target failed to supply a value for a
|
|
|
|
register because it was "not available" at this time. Problem
|
|
|
|
is, the target still has the register and so get saved_register()
|
|
|
|
may be returning a value saved on the stack. */
|
|
|
|
|
2001-02-20 23:39:03 +01:00
|
|
|
if (register_cached (regnum) < 0)
|
2002-04-12 20:18:59 +02:00
|
|
|
return 0; /* register value not available */
|
2001-02-20 23:39:03 +01:00
|
|
|
|
2002-11-05 22:44:05 +01:00
|
|
|
return !optimized;
|
2001-02-20 23:39:03 +01:00
|
|
|
}
|
2002-09-25 22:30:38 +02:00
|
|
|
|
|
|
|
|
|
|
|
/* Map between a frame register number and its name. A frame register
|
|
|
|
space is a superset of the cooked register space --- it also
|
|
|
|
includes builtin registers. */
|
|
|
|
|
|
|
|
int
|
2003-07-07 16:36:58 +02:00
|
|
|
frame_map_name_to_regnum (struct frame_info *frame, const char *name, int len)
|
2002-09-25 22:30:38 +02:00
|
|
|
{
|
2003-07-07 16:36:58 +02:00
|
|
|
return user_reg_map_name_to_regnum (get_frame_arch (frame), name, len);
|
2002-09-25 22:30:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
2003-07-07 16:36:58 +02:00
|
|
|
frame_map_regnum_to_name (struct frame_info *frame, int regnum)
|
2002-09-25 22:30:38 +02:00
|
|
|
{
|
2003-07-07 16:36:58 +02:00
|
|
|
return user_reg_map_regnum_to_name (get_frame_arch (frame), regnum);
|
2002-09-25 22:30:38 +02:00
|
|
|
}
|
2002-11-08 21:48:55 +01:00
|
|
|
|
2003-01-27 22:41:41 +01:00
|
|
|
/* Create a sentinel frame. */
|
|
|
|
|
2003-06-08 Andrew Cagney <cagney@redhat.com>
* acinclude.m4 (gcc_AC_CHECK_DECL, (gcc_AC_CHECK_DECL): Stolen
from GCC's acinclude.m4.
* configure.in: Check for getopt's delcaration.
* aclocal.m4, config.in, configure: Re-generate.
* main.c (error_init): Delete declaration.
* defs.h (error_init): Declare.
* rs6000-tdep.c (rs6000_fetch_pointer_argument): Make static.
(rs6000_convert_from_func_ptr_addr): Make static.
(_initialize_rs6000_tdep): Add declaration.
* cli/cli-cmds.c (dont_repeat): Delete declaration.
(show_commands, set_verbose, show_history): Delete declaration.
* top.h (set_verbose): Add declaration.
(show_history, set_history, show_commands): Add declaration.
(do_restore_instream_cleanup): Add declaration.
* objc-lang.c (specialcmp): Make static.
(print_object_command): Make static.
(find_objc_msgsend): Make static.
(find_objc_msgcall_submethod_helper): Make static.
(find_objc_msgcall_submethod): Make static.
(_initialize_objc_language): Add declaration.
(find_implementation_from_class): Make static.
(find_implementation): Make static.
* objc-exp.y (yylex): Delete lookup_struct_typedef declaration.
* objc-lang.h (lookup_struct_typedef): Add declaration.
* cli/cli-interp.c (_initialize_cli_interp): Add declaration.
* cli/cli-script.c (clear_hook_in_cleanup): Make static.
(do_restore_user_call_depth): Make static.
(do_restore_instream_cleanup): Delete declaration.
(dont_repeat): Delete declaration.
* cli/cli-decode.c (add_abbrev_cmd): Delete function.
* cli/cli-dump.c (_initialize_cli_dump): Add declaration.
* reggroups.c (_initialize_reggroup): Add declaration.
* cp-support.c (_initialize_cp_support): Add declaration.
* cp-abi.c (_initialize_cp_abi): Add declaration.
* hpacc-abi.c (_initialize_hpacc_abi): Add declaration.
* gnu-v3-abi.c (gnuv3_baseclass_offset): Make static.
(_initialize_gnu_v3_abi): Add declaration.
* gnu-v2-abi.c (gnuv2_value_rtti_type): Make static.
(_initialize_gnu_v2_abi): Add declaration.
* frame-base.c (_initialize_frame_base): Add declaration.
* doublest.c (floatformat_from_length): Make static.
* frame-unwind.c (_initialize_frame_unwind): Add declaration.
* frame.c (create_sentinel_frame): Make static.
(_initialize_frame): Add declaration.
* top.c (do_catch_errors): Make static.
(gdb_rl_operate_and_get_next_completion): Make static.
* typeprint.c: Include "typeprint.h".
* sentinel-frame.c (sentinel_frame_prev_register): Make static.
(sentinel_frame_this_id): Make static.
* p-valprint.c (_initialize_pascal_valprint): Add declaration.
* ui-out.c (make_cleanup_ui_out_begin_end): Delete function.
* dwarf2-frame.c (dwarf2_frame_cache): Make static.
* p-exp.y (push_current_type, pop_current_type): ISO C declaration.
* dwarf2expr.h (dwarf_expr_context): ISO C declaration.
* maint.c (maintenance_print_architecture): Make static.
* signals/signals.c (_initialize_signals): Add declaration.
* std-regs.c (_initialize_frame_reg): Add declaration.
* jv-exp.y (push_variable): ISO C definition.
(push_qualified_expression_name): Ditto.
* memattr.c (_initialize_mem): Add declaration.
* remote.c (remote_check_watch_resources): Make static.
(remote_stopped_by_watchpoint): Make static.
(remote_stopped_data_address): Make static.
* d10v-tdep.c (nr_dmap_regs): Make static.
(a0_regnum): Make static.
(d10v_frame_unwind_cache): Make static.
(d10v_frame_p): Make static.
* osabi.c (show_osabi): Make static.
(_initialize_gdb_osabi): Add extern declaration.
* gdbtypes.c (make_qualified_type): Make static.
(safe_parse_type): Make static.
* macrocmd.c (_initialize_macrocmd): Add extern declaration.
* macrotab.c (macro_bcache_free): Make static.
* interps.c (interp_set_quiet): Make static.
(interpreter_exec_cmd): Make static.
* stack.h (select_frame_command): New file.
* stack.c: Include "stack.h".
(select_frame_command_wrapper): Delete function.
(select_frame_command): Make global.
* infcall.c: Include "infcall.h".
* linespec.c: Include "linespec.h".
* symfile.c (sections_overlap): Make static.
* cp-support.h (cp_initialize_namespace): ISO C declaration.
* charset.c (_initialize_charset): Add missing prototype.
* regcache.c (init_legacy_regcache_descr): Make static.
(do_regcache_xfree): Make static.
(regcache_xfer_part): Make static.
(_initialize_regcache): Add missing prototype.
* breakpoint.c (parse_breakpoint_sals): Make static.
(breakpoint_sals_to_pc): Make static.
* interps.h (clear_interpreter_hooks): ISO C declaration.
* Makefile.in (stack_h): Define.
(stack.o, typeprint.o, mi-main.o): Update dependencies.
(mi-cmd-stack.o, infcall.o, linespec.o): Update dependencies.
Index: mi/ChangeLog
2003-06-08 Andrew Cagney <cagney@redhat.com>
* mi-parse.c (_initialize_mi_parse): Delete function.
* mi-main.c: Include "mi-main.h".
* mi-interp.c (_initialize_mi_interp): Add declaration.
* mi-cmd-stack.c: Include "stack.h".
(select_frame_command_wrapper): Delete extern declaration.
(mi_cmd_stack_select_frame): Replace select_frame_command_wrapper
with select_frame_command.
2003-06-08 20:27:14 +02:00
|
|
|
static struct frame_info *
|
2003-01-27 22:41:41 +01:00
|
|
|
create_sentinel_frame (struct regcache *regcache)
|
|
|
|
{
|
|
|
|
struct frame_info *frame = FRAME_OBSTACK_ZALLOC (struct frame_info);
|
|
|
|
frame->level = -1;
|
|
|
|
/* Explicitly initialize the sentinel frame's cache. Provide it
|
|
|
|
with the underlying regcache. In the future additional
|
|
|
|
information, such as the frame's thread will be added. */
|
2003-03-17 15:23:50 +01:00
|
|
|
frame->prologue_cache = sentinel_frame_cache (regcache);
|
2003-01-27 22:41:41 +01:00
|
|
|
/* For the moment there is only one sentinel frame implementation. */
|
|
|
|
frame->unwind = sentinel_frame_unwind;
|
|
|
|
/* Link this frame back to itself. The frame is self referential
|
|
|
|
(the unwound PC is the same as the pc), so make it so. */
|
|
|
|
frame->next = frame;
|
2003-04-04 16:46:00 +02:00
|
|
|
/* Make the sentinel frame's ID valid, but invalid. That way all
|
|
|
|
comparisons with it should fail. */
|
2003-04-10 05:30:36 +02:00
|
|
|
frame->this_id.p = 1;
|
|
|
|
frame->this_id.value = null_frame_id;
|
2003-04-10 17:32:27 +02:00
|
|
|
if (frame_debug)
|
|
|
|
{
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "{ create_sentinel_frame (...) -> ");
|
|
|
|
fprint_frame (gdb_stdlog, frame);
|
|
|
|
fprintf_unfiltered (gdb_stdlog, " }\n");
|
|
|
|
}
|
2003-01-27 22:41:41 +01:00
|
|
|
return frame;
|
|
|
|
}
|
|
|
|
|
2002-11-08 21:48:55 +01:00
|
|
|
/* Info about the innermost stack frame (contents of FP register) */
|
|
|
|
|
|
|
|
static struct frame_info *current_frame;
|
|
|
|
|
|
|
|
/* Cache for frame addresses already read by gdb. Valid only while
|
|
|
|
inferior is stopped. Control variables for the frame cache should
|
|
|
|
be local to this module. */
|
|
|
|
|
|
|
|
static struct obstack frame_cache_obstack;
|
|
|
|
|
|
|
|
void *
|
2003-01-09 19:53:21 +01:00
|
|
|
frame_obstack_zalloc (unsigned long size)
|
2002-11-08 21:48:55 +01:00
|
|
|
{
|
2003-01-09 19:53:21 +01:00
|
|
|
void *data = obstack_alloc (&frame_cache_obstack, size);
|
|
|
|
memset (data, 0, size);
|
|
|
|
return data;
|
2002-11-08 21:48:55 +01:00
|
|
|
}
|
|
|
|
|
2003-01-27 22:41:41 +01:00
|
|
|
/* Return the innermost (currently executing) stack frame. This is
|
|
|
|
split into two functions. The function unwind_to_current_frame()
|
|
|
|
is wrapped in catch exceptions so that, even when the unwind of the
|
|
|
|
sentinel frame fails, the function still returns a stack frame. */
|
|
|
|
|
|
|
|
static int
|
|
|
|
unwind_to_current_frame (struct ui_out *ui_out, void *args)
|
|
|
|
{
|
|
|
|
struct frame_info *frame = get_prev_frame (args);
|
2004-04-17 02:48:25 +02:00
|
|
|
/* A sentinel frame can fail to unwind, e.g., because its PC value
|
2003-01-27 22:41:41 +01:00
|
|
|
lands in somewhere like start. */
|
|
|
|
if (frame == NULL)
|
|
|
|
return 1;
|
|
|
|
current_frame = frame;
|
|
|
|
return 0;
|
|
|
|
}
|
2002-11-08 21:48:55 +01:00
|
|
|
|
|
|
|
struct frame_info *
|
|
|
|
get_current_frame (void)
|
|
|
|
{
|
2003-03-12 23:39:16 +01:00
|
|
|
/* First check, and report, the lack of registers. Having GDB
|
|
|
|
report "No stack!" or "No memory" when the target doesn't even
|
|
|
|
have registers is very confusing. Besides, "printcmd.exp"
|
|
|
|
explicitly checks that ``print $pc'' with no registers prints "No
|
|
|
|
registers". */
|
2003-01-27 22:41:41 +01:00
|
|
|
if (!target_has_registers)
|
|
|
|
error ("No registers.");
|
2003-03-12 23:39:16 +01:00
|
|
|
if (!target_has_stack)
|
|
|
|
error ("No stack.");
|
2003-01-27 22:41:41 +01:00
|
|
|
if (!target_has_memory)
|
|
|
|
error ("No memory.");
|
2002-11-08 21:48:55 +01:00
|
|
|
if (current_frame == NULL)
|
|
|
|
{
|
2003-01-27 22:41:41 +01:00
|
|
|
struct frame_info *sentinel_frame =
|
|
|
|
create_sentinel_frame (current_regcache);
|
|
|
|
if (catch_exceptions (uiout, unwind_to_current_frame, sentinel_frame,
|
|
|
|
NULL, RETURN_MASK_ERROR) != 0)
|
|
|
|
{
|
|
|
|
/* Oops! Fake a current frame? Is this useful? It has a PC
|
|
|
|
of zero, for instance. */
|
|
|
|
current_frame = sentinel_frame;
|
|
|
|
}
|
2002-11-08 21:48:55 +01:00
|
|
|
}
|
|
|
|
return current_frame;
|
|
|
|
}
|
|
|
|
|
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* stack.c (selected_frame, select_frame): Move from here ...
* frame.c (selected_frame, select_frame): ... to here. Include
"language.h".
* Makefile.in (frame.o): Update dependencies.
* frame.c (get_selected_frame): New function.
* frame.h (get_selected_frame): Declare.
(deprecated_selected_frame): Rename selected_frame.
* ada-lang.c, ada-tasks.c, breakpoint.c, corelow.c: Update.
* eval.c, f-valprint.c, findvar.c, frame.c, frame.h: Update.
* h8300-tdep.c, h8500-tdep.c, hppa-tdep.c, infcmd.c: Update.
* inflow.c, infrun.c, macroscope.c, mips-tdep.c: Update.
* mn10300-tdep.c, ocd.c, regcache.h, remote-e7000.c: Update.
* remote-mips.c, remote-rdp.c, sh-tdep.c, sparc-tdep.c: Update.
* stack.c, thread.c, tracepoint.c, valops.c, varobj.c: Update.
* z8k-tdep.c, cli/cli-cmds.c: Update.
Index: mi/ChangeLog
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* mi/mi-cmd-stack.c, mi/mi-main.c: Update to use
deprecated_selected_frame.
Index: tui/ChangeLog
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* tui/tui-hooks.c: Update to use deprecated_selected_frame.
* tui/tui.c, tui/tuiDisassem.c, tui/tuiRegs.c: Ditto.
* tui/tuiSource.c, tui/tuiSourceWin.c, tui/tuiWin.c: Ditto.
2002-11-29 20:15:16 +01:00
|
|
|
/* The "selected" stack frame is used by default for local and arg
|
|
|
|
access. May be zero, for no selected frame. */
|
|
|
|
|
|
|
|
struct frame_info *deprecated_selected_frame;
|
|
|
|
|
2004-04-17 02:48:25 +02:00
|
|
|
/* Return the selected frame. Always non-NULL (unless there isn't an
|
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* stack.c (selected_frame, select_frame): Move from here ...
* frame.c (selected_frame, select_frame): ... to here. Include
"language.h".
* Makefile.in (frame.o): Update dependencies.
* frame.c (get_selected_frame): New function.
* frame.h (get_selected_frame): Declare.
(deprecated_selected_frame): Rename selected_frame.
* ada-lang.c, ada-tasks.c, breakpoint.c, corelow.c: Update.
* eval.c, f-valprint.c, findvar.c, frame.c, frame.h: Update.
* h8300-tdep.c, h8500-tdep.c, hppa-tdep.c, infcmd.c: Update.
* inflow.c, infrun.c, macroscope.c, mips-tdep.c: Update.
* mn10300-tdep.c, ocd.c, regcache.h, remote-e7000.c: Update.
* remote-mips.c, remote-rdp.c, sh-tdep.c, sparc-tdep.c: Update.
* stack.c, thread.c, tracepoint.c, valops.c, varobj.c: Update.
* z8k-tdep.c, cli/cli-cmds.c: Update.
Index: mi/ChangeLog
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* mi/mi-cmd-stack.c, mi/mi-main.c: Update to use
deprecated_selected_frame.
Index: tui/ChangeLog
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* tui/tui-hooks.c: Update to use deprecated_selected_frame.
* tui/tui.c, tui/tuiDisassem.c, tui/tuiRegs.c: Ditto.
* tui/tuiSource.c, tui/tuiSourceWin.c, tui/tuiWin.c: Ditto.
2002-11-29 20:15:16 +01:00
|
|
|
inferior sufficient for creating a frame) in which case an error is
|
|
|
|
thrown. */
|
|
|
|
|
|
|
|
struct frame_info *
|
|
|
|
get_selected_frame (void)
|
|
|
|
{
|
|
|
|
if (deprecated_selected_frame == NULL)
|
|
|
|
/* Hey! Don't trust this. It should really be re-finding the
|
|
|
|
last selected frame of the currently selected thread. This,
|
|
|
|
though, is better than nothing. */
|
|
|
|
select_frame (get_current_frame ());
|
|
|
|
/* There is always a frame. */
|
|
|
|
gdb_assert (deprecated_selected_frame != NULL);
|
|
|
|
return deprecated_selected_frame;
|
|
|
|
}
|
|
|
|
|
2004-04-17 02:48:25 +02:00
|
|
|
/* This is a variant of get_selected_frame() which can be called when
|
2003-09-08 20:56:03 +02:00
|
|
|
the inferior does not have a frame; in that case it will return
|
2004-04-17 02:48:25 +02:00
|
|
|
NULL instead of calling error(). */
|
2003-09-08 20:56:03 +02:00
|
|
|
|
|
|
|
struct frame_info *
|
|
|
|
deprecated_safe_get_selected_frame (void)
|
|
|
|
{
|
|
|
|
if (!target_has_registers || !target_has_stack || !target_has_memory)
|
|
|
|
return NULL;
|
|
|
|
return get_selected_frame ();
|
|
|
|
}
|
|
|
|
|
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* stack.c (selected_frame, select_frame): Move from here ...
* frame.c (selected_frame, select_frame): ... to here. Include
"language.h".
* Makefile.in (frame.o): Update dependencies.
* frame.c (get_selected_frame): New function.
* frame.h (get_selected_frame): Declare.
(deprecated_selected_frame): Rename selected_frame.
* ada-lang.c, ada-tasks.c, breakpoint.c, corelow.c: Update.
* eval.c, f-valprint.c, findvar.c, frame.c, frame.h: Update.
* h8300-tdep.c, h8500-tdep.c, hppa-tdep.c, infcmd.c: Update.
* inflow.c, infrun.c, macroscope.c, mips-tdep.c: Update.
* mn10300-tdep.c, ocd.c, regcache.h, remote-e7000.c: Update.
* remote-mips.c, remote-rdp.c, sh-tdep.c, sparc-tdep.c: Update.
* stack.c, thread.c, tracepoint.c, valops.c, varobj.c: Update.
* z8k-tdep.c, cli/cli-cmds.c: Update.
Index: mi/ChangeLog
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* mi/mi-cmd-stack.c, mi/mi-main.c: Update to use
deprecated_selected_frame.
Index: tui/ChangeLog
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* tui/tui-hooks.c: Update to use deprecated_selected_frame.
* tui/tui.c, tui/tuiDisassem.c, tui/tuiRegs.c: Ditto.
* tui/tuiSource.c, tui/tuiSourceWin.c, tui/tuiWin.c: Ditto.
2002-11-29 20:15:16 +01:00
|
|
|
/* Select frame FI (or NULL - to invalidate the current frame). */
|
|
|
|
|
|
|
|
void
|
|
|
|
select_frame (struct frame_info *fi)
|
|
|
|
{
|
2003-09-14 Andrew Cagney <cagney@redhat.com>
* alpha-nat.c: Remove some occurances of "register".
* alpha-tdep.c, arm-tdep.c, blockframe.c, breakpoint.c: Ditto.
* buildsym.c, c-typeprint.c, c-valprint.c, coffread.c: Ditto.
* corefile.c, cp-support.c, cp-valprint.c, cris-tdep.c: Ditto.
* dbxread.c, dcache.c, dwarf2read.c, elfread.c: Ditto.
* environ.c, eval.c, event-top.c, f-typeprint.c: Ditto.
* f-valprint.c, findvar.c, frame.c, gdbtypes.c: Ditto.
* h8300-tdep.c, hppa-tdep.c, hppab-nat.c, hppah-nat.c: Ditto.
* hppam3-nat.c, hpread.c, ia64-aix-nat.c, ia64-linux-nat.c: Ditto.
* infcall.c, infcmd.c, inflow.c, infptrace.c, infrun.c: Ditto.
* infttrace.c, irix5-nat.c, jv-typeprint.c: Ditto.
* jv-valprint.c, m68k-tdep.c, m68klinux-nat.c, main.c: Ditto.
* mdebugread.c, minsyms.c, mips-linux-tdep.c: Ditto.
* mips-nat.c, mips-tdep.c, mipsread.c, mipsv4-nat.c: Ditto.
* ns32k-tdep.c, objfiles.c, p-typeprint.c: Ditto.
* p-valprint.c, ppc-linux-nat.c, printcmd.c: Ditto.
* remote-mips.c, remote-vx.c, rs6000-nat.c: Ditto.
* rs6000-tdep.c, scm-exp.c, sh-tdep.c, sh64-tdep.c: Ditto.
* solib.c, somread.c, source.c, sparc-tdep.c: Ditto.
* stabsread.c, stack.c, standalone.c, symfile.c: Ditto.
* symmisc.c, symtab.c, top.c, tracepoint.c: Ditto.
* typeprint.c, utils.c, valarith.c, valops.c: Ditto.
* values.c, vax-tdep.c, xcoffread.c: Ditto.
2003-09-14 18:32:14 +02:00
|
|
|
struct symtab *s;
|
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* stack.c (selected_frame, select_frame): Move from here ...
* frame.c (selected_frame, select_frame): ... to here. Include
"language.h".
* Makefile.in (frame.o): Update dependencies.
* frame.c (get_selected_frame): New function.
* frame.h (get_selected_frame): Declare.
(deprecated_selected_frame): Rename selected_frame.
* ada-lang.c, ada-tasks.c, breakpoint.c, corelow.c: Update.
* eval.c, f-valprint.c, findvar.c, frame.c, frame.h: Update.
* h8300-tdep.c, h8500-tdep.c, hppa-tdep.c, infcmd.c: Update.
* inflow.c, infrun.c, macroscope.c, mips-tdep.c: Update.
* mn10300-tdep.c, ocd.c, regcache.h, remote-e7000.c: Update.
* remote-mips.c, remote-rdp.c, sh-tdep.c, sparc-tdep.c: Update.
* stack.c, thread.c, tracepoint.c, valops.c, varobj.c: Update.
* z8k-tdep.c, cli/cli-cmds.c: Update.
Index: mi/ChangeLog
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* mi/mi-cmd-stack.c, mi/mi-main.c: Update to use
deprecated_selected_frame.
Index: tui/ChangeLog
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* tui/tui-hooks.c: Update to use deprecated_selected_frame.
* tui/tui.c, tui/tuiDisassem.c, tui/tuiRegs.c: Ditto.
* tui/tuiSource.c, tui/tuiSourceWin.c, tui/tuiWin.c: Ditto.
2002-11-29 20:15:16 +01:00
|
|
|
|
|
|
|
deprecated_selected_frame = fi;
|
2004-04-17 02:48:25 +02:00
|
|
|
/* NOTE: cagney/2002-05-04: FI can be NULL. This occurs when the
|
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* stack.c (selected_frame, select_frame): Move from here ...
* frame.c (selected_frame, select_frame): ... to here. Include
"language.h".
* Makefile.in (frame.o): Update dependencies.
* frame.c (get_selected_frame): New function.
* frame.h (get_selected_frame): Declare.
(deprecated_selected_frame): Rename selected_frame.
* ada-lang.c, ada-tasks.c, breakpoint.c, corelow.c: Update.
* eval.c, f-valprint.c, findvar.c, frame.c, frame.h: Update.
* h8300-tdep.c, h8500-tdep.c, hppa-tdep.c, infcmd.c: Update.
* inflow.c, infrun.c, macroscope.c, mips-tdep.c: Update.
* mn10300-tdep.c, ocd.c, regcache.h, remote-e7000.c: Update.
* remote-mips.c, remote-rdp.c, sh-tdep.c, sparc-tdep.c: Update.
* stack.c, thread.c, tracepoint.c, valops.c, varobj.c: Update.
* z8k-tdep.c, cli/cli-cmds.c: Update.
Index: mi/ChangeLog
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* mi/mi-cmd-stack.c, mi/mi-main.c: Update to use
deprecated_selected_frame.
Index: tui/ChangeLog
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* tui/tui-hooks.c: Update to use deprecated_selected_frame.
* tui/tui.c, tui/tuiDisassem.c, tui/tuiRegs.c: Ditto.
* tui/tuiSource.c, tui/tuiSourceWin.c, tui/tuiWin.c: Ditto.
2002-11-29 20:15:16 +01:00
|
|
|
frame is being invalidated. */
|
2004-04-21 Andrew Cagney <cagney@redhat.com>
* annotate.h (deprecated_annotate_starting_hook)
(deprecated_annotate_stopped_hook)
(deprecated_annotate_exited_hook)
(deprecated_annotate_signal_hook)
(deprecated_annotate_signalled_hook): Deprecate.
* tracepoint.h (deprecated_create_tracepoint_hook)
(deprecated_delete_tracepoint_hook)
(deprecated_modify_tracepoint_hook)
(deprecated_trace_find_hook)
(deprecated_trace_start_stop_hook): Deprecate.
* target.h (deprecated_target_new_objfile_hook): Deprecate.
* remote.h (deprecated_target_resume_hook)
(deprecated_target_wait_loop_hook): Deprecate.
* gdbcore.h (deprecated_exec_file_display_hook)
(deprecated_file_changed_hook): Deprecate.
* frame.h (deprecated_selected_frame_level_changed_hook): Deprecate.
* defs.h (deprecated_modify_breakpoint_hook)
(deprecated_command_loop_hook, deprecated_show_load_progress)
(deprecated_print_frame_info_listing_hook)
(deprecated_query_hook, deprecated_warning_hook)
(deprecated_flush_hook, deprecated_create_breakpoint_hook)
(deprecated_delete_breakpoint_hook)
(deprecated_interactive_hook, deprecated_registers_changed_hook)
(deprecated_readline_begin_hook, deprecated_readline_hook)
(deprecated_readline_end_hook, deprecated_register_changed_hook)
(deprecated_memory_changed_hook, deprecated_init_ui_hook)
(deprecated_context_hook, deprecated_target_wait_hook)
(deprecated_attach_hook, deprecated_detach_hook)
(deprecated_call_command_hook, deprecated_set_hook)
(deprecated_error_hook, deprecated_error_begin_hook)
(deprecated_ui_load_progress_hook): Deprecate.
* valops.c, uw-thread.c, utils.c, tui/tui-io.c: Update.
* tui/tui-hooks.c, tracepoint.c, top.c, thread-db.c: Update.
* target.c, symfile.c, stack.c, sol-thread.c, rs6000-nat.c: Update.
* remote.c, remote-mips.c, regcache.c, mi/mi-interp.c: Update.
* main.c, interps.c, infcmd.c, hpux-thread.c, frame.c: Update.
* exec.c, dsrec.c, d10v-tdep.c, corefile.c, complaints.c: Update.
* cli/cli-script.c, cli/cli-setshow.c, breakpoint.c: Update.
* annotate.c, aix-thread.c: Update.
2004-04-22 01:52:21 +02:00
|
|
|
if (deprecated_selected_frame_level_changed_hook)
|
|
|
|
deprecated_selected_frame_level_changed_hook (frame_relative_level (fi));
|
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* stack.c (selected_frame, select_frame): Move from here ...
* frame.c (selected_frame, select_frame): ... to here. Include
"language.h".
* Makefile.in (frame.o): Update dependencies.
* frame.c (get_selected_frame): New function.
* frame.h (get_selected_frame): Declare.
(deprecated_selected_frame): Rename selected_frame.
* ada-lang.c, ada-tasks.c, breakpoint.c, corelow.c: Update.
* eval.c, f-valprint.c, findvar.c, frame.c, frame.h: Update.
* h8300-tdep.c, h8500-tdep.c, hppa-tdep.c, infcmd.c: Update.
* inflow.c, infrun.c, macroscope.c, mips-tdep.c: Update.
* mn10300-tdep.c, ocd.c, regcache.h, remote-e7000.c: Update.
* remote-mips.c, remote-rdp.c, sh-tdep.c, sparc-tdep.c: Update.
* stack.c, thread.c, tracepoint.c, valops.c, varobj.c: Update.
* z8k-tdep.c, cli/cli-cmds.c: Update.
Index: mi/ChangeLog
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* mi/mi-cmd-stack.c, mi/mi-main.c: Update to use
deprecated_selected_frame.
Index: tui/ChangeLog
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* tui/tui-hooks.c: Update to use deprecated_selected_frame.
* tui/tui.c, tui/tuiDisassem.c, tui/tuiRegs.c: Ditto.
* tui/tuiSource.c, tui/tuiSourceWin.c, tui/tuiWin.c: Ditto.
2002-11-29 20:15:16 +01:00
|
|
|
|
|
|
|
/* FIXME: kseitz/2002-08-28: It would be nice to call
|
2004-04-17 02:48:25 +02:00
|
|
|
selected_frame_level_changed_event() right here, but due to limitations
|
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* stack.c (selected_frame, select_frame): Move from here ...
* frame.c (selected_frame, select_frame): ... to here. Include
"language.h".
* Makefile.in (frame.o): Update dependencies.
* frame.c (get_selected_frame): New function.
* frame.h (get_selected_frame): Declare.
(deprecated_selected_frame): Rename selected_frame.
* ada-lang.c, ada-tasks.c, breakpoint.c, corelow.c: Update.
* eval.c, f-valprint.c, findvar.c, frame.c, frame.h: Update.
* h8300-tdep.c, h8500-tdep.c, hppa-tdep.c, infcmd.c: Update.
* inflow.c, infrun.c, macroscope.c, mips-tdep.c: Update.
* mn10300-tdep.c, ocd.c, regcache.h, remote-e7000.c: Update.
* remote-mips.c, remote-rdp.c, sh-tdep.c, sparc-tdep.c: Update.
* stack.c, thread.c, tracepoint.c, valops.c, varobj.c: Update.
* z8k-tdep.c, cli/cli-cmds.c: Update.
Index: mi/ChangeLog
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* mi/mi-cmd-stack.c, mi/mi-main.c: Update to use
deprecated_selected_frame.
Index: tui/ChangeLog
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* tui/tui-hooks.c: Update to use deprecated_selected_frame.
* tui/tui.c, tui/tuiDisassem.c, tui/tuiRegs.c: Ditto.
* tui/tuiSource.c, tui/tuiSourceWin.c, tui/tuiWin.c: Ditto.
2002-11-29 20:15:16 +01:00
|
|
|
in the current interfaces, we would end up flooding UIs with events
|
2004-04-17 02:48:25 +02:00
|
|
|
because select_frame() is used extensively internally.
|
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* stack.c (selected_frame, select_frame): Move from here ...
* frame.c (selected_frame, select_frame): ... to here. Include
"language.h".
* Makefile.in (frame.o): Update dependencies.
* frame.c (get_selected_frame): New function.
* frame.h (get_selected_frame): Declare.
(deprecated_selected_frame): Rename selected_frame.
* ada-lang.c, ada-tasks.c, breakpoint.c, corelow.c: Update.
* eval.c, f-valprint.c, findvar.c, frame.c, frame.h: Update.
* h8300-tdep.c, h8500-tdep.c, hppa-tdep.c, infcmd.c: Update.
* inflow.c, infrun.c, macroscope.c, mips-tdep.c: Update.
* mn10300-tdep.c, ocd.c, regcache.h, remote-e7000.c: Update.
* remote-mips.c, remote-rdp.c, sh-tdep.c, sparc-tdep.c: Update.
* stack.c, thread.c, tracepoint.c, valops.c, varobj.c: Update.
* z8k-tdep.c, cli/cli-cmds.c: Update.
Index: mi/ChangeLog
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* mi/mi-cmd-stack.c, mi/mi-main.c: Update to use
deprecated_selected_frame.
Index: tui/ChangeLog
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* tui/tui-hooks.c: Update to use deprecated_selected_frame.
* tui/tui.c, tui/tuiDisassem.c, tui/tuiRegs.c: Ditto.
* tui/tuiSource.c, tui/tuiSourceWin.c, tui/tuiWin.c: Ditto.
2002-11-29 20:15:16 +01:00
|
|
|
|
|
|
|
Once we have frame-parameterized frame (and frame-related) commands,
|
|
|
|
the event notification can be moved here, since this function will only
|
2004-04-17 02:48:25 +02:00
|
|
|
be called when the user's selected frame is being changed. */
|
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* stack.c (selected_frame, select_frame): Move from here ...
* frame.c (selected_frame, select_frame): ... to here. Include
"language.h".
* Makefile.in (frame.o): Update dependencies.
* frame.c (get_selected_frame): New function.
* frame.h (get_selected_frame): Declare.
(deprecated_selected_frame): Rename selected_frame.
* ada-lang.c, ada-tasks.c, breakpoint.c, corelow.c: Update.
* eval.c, f-valprint.c, findvar.c, frame.c, frame.h: Update.
* h8300-tdep.c, h8500-tdep.c, hppa-tdep.c, infcmd.c: Update.
* inflow.c, infrun.c, macroscope.c, mips-tdep.c: Update.
* mn10300-tdep.c, ocd.c, regcache.h, remote-e7000.c: Update.
* remote-mips.c, remote-rdp.c, sh-tdep.c, sparc-tdep.c: Update.
* stack.c, thread.c, tracepoint.c, valops.c, varobj.c: Update.
* z8k-tdep.c, cli/cli-cmds.c: Update.
Index: mi/ChangeLog
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* mi/mi-cmd-stack.c, mi/mi-main.c: Update to use
deprecated_selected_frame.
Index: tui/ChangeLog
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* tui/tui-hooks.c: Update to use deprecated_selected_frame.
* tui/tui.c, tui/tuiDisassem.c, tui/tuiRegs.c: Ditto.
* tui/tuiSource.c, tui/tuiSourceWin.c, tui/tuiWin.c: Ditto.
2002-11-29 20:15:16 +01:00
|
|
|
|
|
|
|
/* Ensure that symbols for this frame are read in. Also, determine the
|
|
|
|
source language of this frame, and switch to it if desired. */
|
|
|
|
if (fi)
|
|
|
|
{
|
2003-12-10 18:40:43 +01:00
|
|
|
/* We retrieve the frame's symtab by using the frame PC. However
|
2004-04-17 02:48:25 +02:00
|
|
|
we cannot use the frame PC as-is, because it usually points to
|
2003-12-10 18:40:43 +01:00
|
|
|
the instruction following the "call", which is sometimes the
|
|
|
|
first instruction of another function. So we rely on
|
|
|
|
get_frame_address_in_block() which provides us with a PC which
|
|
|
|
is guaranteed to be inside the frame's code block. */
|
|
|
|
s = find_pc_symtab (get_frame_address_in_block (fi));
|
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* stack.c (selected_frame, select_frame): Move from here ...
* frame.c (selected_frame, select_frame): ... to here. Include
"language.h".
* Makefile.in (frame.o): Update dependencies.
* frame.c (get_selected_frame): New function.
* frame.h (get_selected_frame): Declare.
(deprecated_selected_frame): Rename selected_frame.
* ada-lang.c, ada-tasks.c, breakpoint.c, corelow.c: Update.
* eval.c, f-valprint.c, findvar.c, frame.c, frame.h: Update.
* h8300-tdep.c, h8500-tdep.c, hppa-tdep.c, infcmd.c: Update.
* inflow.c, infrun.c, macroscope.c, mips-tdep.c: Update.
* mn10300-tdep.c, ocd.c, regcache.h, remote-e7000.c: Update.
* remote-mips.c, remote-rdp.c, sh-tdep.c, sparc-tdep.c: Update.
* stack.c, thread.c, tracepoint.c, valops.c, varobj.c: Update.
* z8k-tdep.c, cli/cli-cmds.c: Update.
Index: mi/ChangeLog
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* mi/mi-cmd-stack.c, mi/mi-main.c: Update to use
deprecated_selected_frame.
Index: tui/ChangeLog
2002-11-29 Andrew Cagney <ac131313@redhat.com>
* tui/tui-hooks.c: Update to use deprecated_selected_frame.
* tui/tui.c, tui/tuiDisassem.c, tui/tuiRegs.c: Ditto.
* tui/tuiSource.c, tui/tuiSourceWin.c, tui/tuiWin.c: Ditto.
2002-11-29 20:15:16 +01:00
|
|
|
if (s
|
|
|
|
&& s->language != current_language->la_language
|
|
|
|
&& s->language != language_unknown
|
|
|
|
&& language_mode == language_mode_auto)
|
|
|
|
{
|
|
|
|
set_language (s->language);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2002-12-13 17:40:25 +01:00
|
|
|
|
2002-11-08 21:48:55 +01:00
|
|
|
/* Create an arbitrary (i.e. address specified by user) or innermost frame.
|
|
|
|
Always returns a non-NULL value. */
|
|
|
|
|
|
|
|
struct frame_info *
|
|
|
|
create_new_frame (CORE_ADDR addr, CORE_ADDR pc)
|
|
|
|
{
|
|
|
|
struct frame_info *fi;
|
|
|
|
|
2003-04-10 17:32:27 +02:00
|
|
|
if (frame_debug)
|
|
|
|
{
|
|
|
|
fprintf_unfiltered (gdb_stdlog,
|
|
|
|
"{ create_new_frame (addr=0x%s, pc=0x%s) ",
|
|
|
|
paddr_nz (addr), paddr_nz (pc));
|
|
|
|
}
|
|
|
|
|
2003-01-09 19:53:21 +01:00
|
|
|
fi = frame_obstack_zalloc (sizeof (struct frame_info));
|
2002-11-08 21:48:55 +01:00
|
|
|
|
2003-01-27 22:41:41 +01:00
|
|
|
fi->next = create_sentinel_frame (current_regcache);
|
2003-04-05 05:56:00 +02:00
|
|
|
|
|
|
|
/* Select/initialize both the unwind function and the frame's type
|
|
|
|
based on the PC. */
|
2004-03-21 23:28:52 +01:00
|
|
|
fi->unwind = frame_unwind_find_by_frame (fi->next, &fi->prologue_cache);
|
2003-04-05 05:56:00 +02:00
|
|
|
|
2003-04-12 06:27:29 +02:00
|
|
|
fi->this_id.p = 1;
|
2003-04-04 23:04:33 +02:00
|
|
|
deprecated_update_frame_base_hack (fi, addr);
|
|
|
|
deprecated_update_frame_pc_hack (fi, pc);
|
2002-11-08 21:48:55 +01:00
|
|
|
|
2003-04-10 17:32:27 +02:00
|
|
|
if (frame_debug)
|
|
|
|
{
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "-> ");
|
|
|
|
fprint_frame (gdb_stdlog, fi);
|
|
|
|
fprintf_unfiltered (gdb_stdlog, " }\n");
|
|
|
|
}
|
|
|
|
|
2002-11-08 21:48:55 +01:00
|
|
|
return fi;
|
|
|
|
}
|
|
|
|
|
2003-03-13 00:55:36 +01:00
|
|
|
/* Return the frame that THIS_FRAME calls (NULL if THIS_FRAME is the
|
|
|
|
innermost frame). Be careful to not fall off the bottom of the
|
|
|
|
frame chain and onto the sentinel frame. */
|
2002-11-08 21:48:55 +01:00
|
|
|
|
|
|
|
struct frame_info *
|
2003-03-13 00:55:36 +01:00
|
|
|
get_next_frame (struct frame_info *this_frame)
|
2002-11-08 21:48:55 +01:00
|
|
|
{
|
2003-03-13 00:55:36 +01:00
|
|
|
if (this_frame->level > 0)
|
|
|
|
return this_frame->next;
|
2003-01-27 22:41:41 +01:00
|
|
|
else
|
|
|
|
return NULL;
|
2002-11-08 21:48:55 +01:00
|
|
|
}
|
|
|
|
|
2004-04-26 11:49:36 +02:00
|
|
|
/* Observer for the target_changed event. */
|
|
|
|
|
|
|
|
void
|
|
|
|
frame_observer_target_changed (struct target_ops *target)
|
|
|
|
{
|
|
|
|
flush_cached_frames ();
|
|
|
|
}
|
|
|
|
|
2002-11-08 21:48:55 +01:00
|
|
|
/* Flush the entire frame cache. */
|
|
|
|
|
|
|
|
void
|
|
|
|
flush_cached_frames (void)
|
|
|
|
{
|
|
|
|
/* Since we can't really be sure what the first object allocated was */
|
|
|
|
obstack_free (&frame_cache_obstack, 0);
|
|
|
|
obstack_init (&frame_cache_obstack);
|
|
|
|
|
|
|
|
current_frame = NULL; /* Invalidate cache */
|
|
|
|
select_frame (NULL);
|
|
|
|
annotate_frames_invalid ();
|
2003-04-10 17:32:27 +02:00
|
|
|
if (frame_debug)
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "{ flush_cached_frames () }\n");
|
2002-11-08 21:48:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Flush the frame cache, and start a new one if necessary. */
|
|
|
|
|
|
|
|
void
|
|
|
|
reinit_frame_cache (void)
|
|
|
|
{
|
|
|
|
flush_cached_frames ();
|
|
|
|
|
|
|
|
/* FIXME: The inferior_ptid test is wrong if there is a corefile. */
|
|
|
|
if (PIDGET (inferior_ptid) != 0)
|
|
|
|
{
|
|
|
|
select_frame (get_current_frame ());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-03-31 21:40:28 +02:00
|
|
|
/* Return a "struct frame_info" corresponding to the frame that called
|
|
|
|
THIS_FRAME. Returns NULL if there is no such frame.
|
2004-01-11 17:52:16 +01:00
|
|
|
|
2004-03-31 21:40:28 +02:00
|
|
|
Unlike get_prev_frame, this function always tries to unwind the
|
|
|
|
frame. */
|
2003-01-21 20:32:42 +01:00
|
|
|
|
2004-03-31 21:40:28 +02:00
|
|
|
static struct frame_info *
|
|
|
|
get_prev_frame_1 (struct frame_info *this_frame)
|
2003-01-21 20:32:42 +01:00
|
|
|
{
|
|
|
|
struct frame_info *prev_frame;
|
2004-05-08 01:19:14 +02:00
|
|
|
struct frame_id this_id;
|
2003-01-21 20:32:42 +01:00
|
|
|
|
2004-03-31 21:40:28 +02:00
|
|
|
gdb_assert (this_frame != NULL);
|
|
|
|
|
2003-04-10 17:32:27 +02:00
|
|
|
if (frame_debug)
|
|
|
|
{
|
2004-03-31 21:40:28 +02:00
|
|
|
fprintf_unfiltered (gdb_stdlog, "{ get_prev_frame_1 (this_frame=");
|
2003-04-10 17:32:27 +02:00
|
|
|
if (this_frame != NULL)
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "%d", this_frame->level);
|
|
|
|
else
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "<NULL>");
|
|
|
|
fprintf_unfiltered (gdb_stdlog, ") ");
|
|
|
|
}
|
|
|
|
|
2004-03-31 21:40:28 +02:00
|
|
|
/* Only try to do the unwind once. */
|
|
|
|
if (this_frame->prev_p)
|
|
|
|
{
|
|
|
|
if (frame_debug)
|
|
|
|
{
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "-> ");
|
|
|
|
fprint_frame (gdb_stdlog, this_frame->prev);
|
|
|
|
fprintf_unfiltered (gdb_stdlog, " // cached \n");
|
|
|
|
}
|
|
|
|
return this_frame->prev;
|
|
|
|
}
|
|
|
|
this_frame->prev_p = 1;
|
|
|
|
|
|
|
|
/* Check that this frame's ID was valid. If it wasn't, don't try to
|
|
|
|
unwind to the prev frame. Be careful to not apply this test to
|
|
|
|
the sentinel frame. */
|
2004-05-08 01:19:14 +02:00
|
|
|
this_id = get_frame_id (this_frame);
|
|
|
|
if (this_frame->level >= 0 && !frame_id_p (this_id))
|
2004-03-31 21:40:28 +02:00
|
|
|
{
|
|
|
|
if (frame_debug)
|
|
|
|
{
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "-> ");
|
|
|
|
fprint_frame (gdb_stdlog, NULL);
|
|
|
|
fprintf_unfiltered (gdb_stdlog, " // this ID is NULL }\n");
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check that this frame's ID isn't inner to (younger, below, next)
|
|
|
|
the next frame. This happens when a frame unwind goes backwards.
|
2004-04-02 22:21:07 +02:00
|
|
|
Exclude signal trampolines (due to sigaltstack the frame ID can
|
|
|
|
go backwards) and sentinel frames (the test is meaningless). */
|
|
|
|
if (this_frame->next->level >= 0
|
2004-07-31 23:41:50 +02:00
|
|
|
&& this_frame->next->unwind->type != SIGTRAMP_FRAME
|
2004-05-08 01:19:14 +02:00
|
|
|
&& frame_id_inner (this_id, get_frame_id (this_frame->next)))
|
2004-03-31 21:40:28 +02:00
|
|
|
error ("Previous frame inner to this frame (corrupt stack?)");
|
|
|
|
|
|
|
|
/* Check that this and the next frame are not identical. If they
|
|
|
|
are, there is most likely a stack cycle. As with the inner-than
|
|
|
|
test above, avoid comparing the inner-most and sentinel frames. */
|
|
|
|
if (this_frame->level > 0
|
2004-05-08 01:19:14 +02:00
|
|
|
&& frame_id_eq (this_id, get_frame_id (this_frame->next)))
|
2004-03-31 21:40:28 +02:00
|
|
|
error ("Previous frame identical to this frame (corrupt stack?)");
|
|
|
|
|
|
|
|
/* Allocate the new frame but do not wire it in to the frame chain.
|
|
|
|
Some (bad) code in INIT_FRAME_EXTRA_INFO tries to look along
|
|
|
|
frame->next to pull some fancy tricks (of course such code is, by
|
|
|
|
definition, recursive). Try to prevent it.
|
|
|
|
|
|
|
|
There is no reason to worry about memory leaks, should the
|
|
|
|
remainder of the function fail. The allocated memory will be
|
|
|
|
quickly reclaimed when the frame cache is flushed, and the `we've
|
|
|
|
been here before' check above will stop repeated memory
|
|
|
|
allocation calls. */
|
|
|
|
prev_frame = FRAME_OBSTACK_ZALLOC (struct frame_info);
|
|
|
|
prev_frame->level = this_frame->level + 1;
|
|
|
|
|
|
|
|
/* Don't yet compute ->unwind (and hence ->type). It is computed
|
|
|
|
on-demand in get_frame_type, frame_register_unwind, and
|
|
|
|
get_frame_id. */
|
|
|
|
|
|
|
|
/* Don't yet compute the frame's ID. It is computed on-demand by
|
|
|
|
get_frame_id(). */
|
|
|
|
|
|
|
|
/* The unwound frame ID is validate at the start of this function,
|
|
|
|
as part of the logic to decide if that frame should be further
|
|
|
|
unwound, and not here while the prev frame is being created.
|
|
|
|
Doing this makes it possible for the user to examine a frame that
|
|
|
|
has an invalid frame ID.
|
|
|
|
|
|
|
|
Some very old VAX code noted: [...] For the sake of argument,
|
|
|
|
suppose that the stack is somewhat trashed (which is one reason
|
|
|
|
that "info frame" exists). So, return 0 (indicating we don't
|
|
|
|
know the address of the arglist) if we don't know what frame this
|
|
|
|
frame calls. */
|
|
|
|
|
|
|
|
/* Link it in. */
|
|
|
|
this_frame->prev = prev_frame;
|
|
|
|
prev_frame->next = this_frame;
|
|
|
|
|
|
|
|
if (frame_debug)
|
|
|
|
{
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "-> ");
|
|
|
|
fprint_frame (gdb_stdlog, prev_frame);
|
|
|
|
fprintf_unfiltered (gdb_stdlog, " }\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
return prev_frame;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Debug routine to print a NULL frame being returned. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
frame_debug_got_null_frame (struct ui_file *file,
|
|
|
|
struct frame_info *this_frame,
|
|
|
|
const char *reason)
|
|
|
|
{
|
|
|
|
if (frame_debug)
|
|
|
|
{
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "{ get_prev_frame (this_frame=");
|
|
|
|
if (this_frame != NULL)
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "%d", this_frame->level);
|
|
|
|
else
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "<NULL>");
|
|
|
|
fprintf_unfiltered (gdb_stdlog, ") -> // %s}\n", reason);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return a structure containing various interesting information about
|
|
|
|
the frame that called THIS_FRAME. Returns NULL if there is entier
|
|
|
|
no such frame or the frame fails any of a set of target-independent
|
|
|
|
condition that should terminate the frame chain (e.g., as unwinding
|
|
|
|
past main()).
|
|
|
|
|
|
|
|
This function should not contain target-dependent tests, such as
|
|
|
|
checking whether the program-counter is zero. */
|
|
|
|
|
|
|
|
struct frame_info *
|
|
|
|
get_prev_frame (struct frame_info *this_frame)
|
|
|
|
{
|
|
|
|
struct frame_info *prev_frame;
|
|
|
|
|
2003-01-21 20:32:42 +01:00
|
|
|
/* Return the inner-most frame, when the caller passes in NULL. */
|
|
|
|
/* NOTE: cagney/2002-11-09: Not sure how this would happen. The
|
|
|
|
caller should have previously obtained a valid frame using
|
|
|
|
get_selected_frame() and then called this code - only possibility
|
|
|
|
I can think of is code behaving badly.
|
|
|
|
|
|
|
|
NOTE: cagney/2003-01-10: Talk about code behaving badly. Check
|
|
|
|
block_innermost_frame(). It does the sequence: frame = NULL;
|
|
|
|
while (1) { frame = get_prev_frame (frame); .... }. Ulgh! Why
|
|
|
|
it couldn't be written better, I don't know.
|
|
|
|
|
2004-04-17 02:48:25 +02:00
|
|
|
NOTE: cagney/2003-01-11: I suspect what is happening in
|
2003-01-21 20:32:42 +01:00
|
|
|
block_innermost_frame() is, when the target has no state
|
2004-04-17 02:48:25 +02:00
|
|
|
(registers, memory, ...), it is still calling this function. The
|
2003-01-21 20:32:42 +01:00
|
|
|
assumption being that this function will return NULL indicating
|
|
|
|
that a frame isn't possible, rather than checking that the target
|
|
|
|
has state and then calling get_current_frame() and
|
|
|
|
get_prev_frame(). This is a guess mind. */
|
2003-03-13 00:55:36 +01:00
|
|
|
if (this_frame == NULL)
|
2003-01-21 20:32:42 +01:00
|
|
|
{
|
|
|
|
/* NOTE: cagney/2002-11-09: There was a code segment here that
|
|
|
|
would error out when CURRENT_FRAME was NULL. The comment
|
|
|
|
that went with it made the claim ...
|
|
|
|
|
|
|
|
``This screws value_of_variable, which just wants a nice
|
|
|
|
clean NULL return from block_innermost_frame if there are no
|
|
|
|
frames. I don't think I've ever seen this message happen
|
|
|
|
otherwise. And returning NULL here is a perfectly legitimate
|
|
|
|
thing to do.''
|
|
|
|
|
|
|
|
Per the above, this code shouldn't even be called with a NULL
|
2003-03-13 00:55:36 +01:00
|
|
|
THIS_FRAME. */
|
2004-03-31 21:40:28 +02:00
|
|
|
frame_debug_got_null_frame (gdb_stdlog, this_frame, "this_frame NULL");
|
2003-01-21 20:32:42 +01:00
|
|
|
return current_frame;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* There is always a frame. If this assertion fails, suspect that
|
|
|
|
something should be calling get_selected_frame() or
|
|
|
|
get_current_frame(). */
|
2003-03-13 00:55:36 +01:00
|
|
|
gdb_assert (this_frame != NULL);
|
2003-01-21 20:32:42 +01:00
|
|
|
|
2003-11-19 18:35:46 +01:00
|
|
|
/* Make sure we pass an address within THIS_FRAME's code block to
|
2004-04-17 02:48:25 +02:00
|
|
|
inside_main_func(). Otherwise, we might stop unwinding at a
|
2003-11-19 18:35:46 +01:00
|
|
|
function which has a call instruction as its last instruction if
|
|
|
|
that function immediately precedes main(). */
|
2003-03-13 00:55:36 +01:00
|
|
|
if (this_frame->level >= 0
|
2003-08-09 17:10:09 +02:00
|
|
|
&& !backtrace_past_main
|
2003-11-19 18:35:46 +01:00
|
|
|
&& inside_main_func (get_frame_address_in_block (this_frame)))
|
2004-04-17 02:48:25 +02:00
|
|
|
/* Don't unwind past main(), but always unwind the sentinel frame.
|
2003-01-21 20:32:42 +01:00
|
|
|
Note, this is done _before_ the frame has been marked as
|
|
|
|
previously unwound. That way if the user later decides to
|
|
|
|
allow unwinds past main(), that just happens. */
|
2003-02-26 00:12:22 +01:00
|
|
|
{
|
2004-03-31 21:40:28 +02:00
|
|
|
frame_debug_got_null_frame (gdb_stdlog, this_frame, "inside main func");
|
2003-02-26 00:12:22 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
2003-01-21 20:32:42 +01:00
|
|
|
|
2003-08-09 17:10:09 +02:00
|
|
|
if (this_frame->level > backtrace_limit)
|
|
|
|
{
|
|
|
|
error ("Backtrace limit of %d exceeded", backtrace_limit);
|
|
|
|
}
|
|
|
|
|
2003-07-15 19:23:32 +02:00
|
|
|
/* If we're already inside the entry function for the main objfile,
|
|
|
|
then it isn't valid. Don't apply this test to a dummy frame -
|
2004-04-17 02:48:25 +02:00
|
|
|
dummy frame PCs typically land in the entry func. Don't apply
|
2003-07-15 19:23:32 +02:00
|
|
|
this test to the sentinel frame. Sentinel frames should always
|
|
|
|
be allowed to unwind. */
|
|
|
|
/* NOTE: cagney/2003-02-25: Don't enable until someone has found
|
|
|
|
hard evidence that this is needed. */
|
2004-04-30 22:44:59 +02:00
|
|
|
/* NOTE: cagney/2003-07-07: Fixed a bug in inside_main_func() -
|
|
|
|
wasn't checking for "main" in the minimal symbols. With that
|
|
|
|
fixed asm-source tests now stop in "main" instead of halting the
|
2004-04-17 02:48:25 +02:00
|
|
|
backtrace in weird and wonderful ways somewhere inside the entry
|
2004-04-30 22:44:59 +02:00
|
|
|
file. Suspect that tests for inside the entry file/func were
|
|
|
|
added to work around that (now fixed) case. */
|
2003-07-15 19:23:32 +02:00
|
|
|
/* NOTE: cagney/2003-07-15: danielj (if I'm reading it right)
|
|
|
|
suggested having the inside_entry_func test use the
|
2004-04-17 02:48:25 +02:00
|
|
|
inside_main_func() msymbol trick (along with entry_point_address()
|
|
|
|
I guess) to determine the address range of the start function.
|
2003-07-15 19:23:32 +02:00
|
|
|
That should provide a far better stopper than the current
|
|
|
|
heuristics. */
|
|
|
|
/* NOTE: cagney/2003-07-15: Need to add a "set backtrace
|
|
|
|
beyond-entry-func" command so that this can be selectively
|
|
|
|
disabled. */
|
|
|
|
if (0
|
|
|
|
#if 0
|
|
|
|
&& backtrace_beyond_entry_func
|
|
|
|
#endif
|
2004-07-31 23:41:50 +02:00
|
|
|
&& this_frame->unwind->type != DUMMY_FRAME && this_frame->level >= 0
|
2004-02-04 17:34:51 +01:00
|
|
|
&& inside_entry_func (this_frame))
|
2003-07-15 19:23:32 +02:00
|
|
|
{
|
2004-03-31 21:40:28 +02:00
|
|
|
frame_debug_got_null_frame (gdb_stdlog, this_frame, "inside entry func");
|
2003-07-15 19:23:32 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2004-03-31 21:40:28 +02:00
|
|
|
return get_prev_frame_1 (this_frame);
|
2003-01-21 20:32:42 +01:00
|
|
|
}
|
|
|
|
|
2002-11-08 21:48:55 +01:00
|
|
|
CORE_ADDR
|
|
|
|
get_frame_pc (struct frame_info *frame)
|
|
|
|
{
|
2003-04-09 22:49:22 +02:00
|
|
|
gdb_assert (frame->next != NULL);
|
|
|
|
return frame_pc_unwind (frame->next);
|
2002-11-08 21:48:55 +01:00
|
|
|
}
|
|
|
|
|
2003-07-11 16:52:17 +02:00
|
|
|
/* Return an address of that falls within the frame's code block. */
|
|
|
|
|
|
|
|
CORE_ADDR
|
|
|
|
frame_unwind_address_in_block (struct frame_info *next_frame)
|
|
|
|
{
|
|
|
|
/* A draft address. */
|
|
|
|
CORE_ADDR pc = frame_pc_unwind (next_frame);
|
|
|
|
|
|
|
|
/* If THIS frame is not inner most (i.e., NEXT isn't the sentinel),
|
|
|
|
and NEXT is `normal' (i.e., not a sigtramp, dummy, ....) THIS
|
|
|
|
frame's PC ends up pointing at the instruction fallowing the
|
|
|
|
"call". Adjust that PC value so that it falls on the call
|
|
|
|
instruction (which, hopefully, falls within THIS frame's code
|
|
|
|
block. So far it's proved to be a very good approximation. See
|
2004-04-17 02:48:25 +02:00
|
|
|
get_frame_type() for why ->type can't be used. */
|
2003-07-11 16:52:17 +02:00
|
|
|
if (next_frame->level >= 0
|
|
|
|
&& get_frame_type (next_frame) == NORMAL_FRAME)
|
|
|
|
--pc;
|
|
|
|
return pc;
|
|
|
|
}
|
|
|
|
|
|
|
|
CORE_ADDR
|
|
|
|
get_frame_address_in_block (struct frame_info *this_frame)
|
|
|
|
{
|
|
|
|
return frame_unwind_address_in_block (this_frame->next);
|
|
|
|
}
|
|
|
|
|
2002-11-29 02:52:02 +01:00
|
|
|
static int
|
|
|
|
pc_notcurrent (struct frame_info *frame)
|
|
|
|
{
|
|
|
|
/* If FRAME is not the innermost frame, that normally means that
|
|
|
|
FRAME->pc points at the return instruction (which is *after* the
|
|
|
|
call instruction), and we want to get the line containing the
|
|
|
|
call (because the call is where the user thinks the program is).
|
|
|
|
However, if the next frame is either a SIGTRAMP_FRAME or a
|
|
|
|
DUMMY_FRAME, then the next frame will contain a saved interrupt
|
|
|
|
PC and such a PC indicates the current (rather than next)
|
|
|
|
instruction/line, consequently, for such cases, want to get the
|
|
|
|
line containing fi->pc. */
|
|
|
|
struct frame_info *next = get_next_frame (frame);
|
|
|
|
int notcurrent = (next != NULL && get_frame_type (next) == NORMAL_FRAME);
|
|
|
|
return notcurrent;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
find_frame_sal (struct frame_info *frame, struct symtab_and_line *sal)
|
|
|
|
{
|
2003-04-04 23:04:33 +02:00
|
|
|
(*sal) = find_pc_line (get_frame_pc (frame), pc_notcurrent (frame));
|
2002-11-29 02:52:02 +01:00
|
|
|
}
|
|
|
|
|
2002-11-19 Andrew Cagney <ac131313@redhat.com>
* frame.h (FRAME_FP): Delete macro.
(get_frame_base): New function declaration.
* frame.c (get_frame_base): New function.
(get_frame_id): Use ->frame.
(frame_find_by_id): Rewrite to use get_frame_id.
* blockframe.c: Use get_frame_base instead of FRAME_FP.
* cris-tdep.c, d10v-tdep.c, findvar.c, h8500-tdep.c: Ditto.
* hppa-tdep.c, i386-tdep.c, infcmd.c, infrun.c: Ditto.
* m68hc11-tdep.c, m68k-tdep.c, mcore-tdep.c, mips-tdep.c: Ditto.
* mn10200-tdep.c, mn10300-tdep.c, rs6000-tdep.c: Ditto.
* sh-tdep.c, sparc-tdep.c, stack.c, tracepoint.c: Ditto.
* v850-tdep.c, valops.c, z8k-tdep.c: Ditto.
2002-11-24 20:48:13 +01:00
|
|
|
/* Per "frame.h", return the ``address'' of the frame. Code should
|
|
|
|
really be using get_frame_id(). */
|
|
|
|
CORE_ADDR
|
|
|
|
get_frame_base (struct frame_info *fi)
|
|
|
|
{
|
2003-04-10 05:30:36 +02:00
|
|
|
return get_frame_id (fi).stack_addr;
|
2002-11-19 Andrew Cagney <ac131313@redhat.com>
* frame.h (FRAME_FP): Delete macro.
(get_frame_base): New function declaration.
* frame.c (get_frame_base): New function.
(get_frame_id): Use ->frame.
(frame_find_by_id): Rewrite to use get_frame_id.
* blockframe.c: Use get_frame_base instead of FRAME_FP.
* cris-tdep.c, d10v-tdep.c, findvar.c, h8500-tdep.c: Ditto.
* hppa-tdep.c, i386-tdep.c, infcmd.c, infrun.c: Ditto.
* m68hc11-tdep.c, m68k-tdep.c, mcore-tdep.c, mips-tdep.c: Ditto.
* mn10200-tdep.c, mn10300-tdep.c, rs6000-tdep.c: Ditto.
* sh-tdep.c, sparc-tdep.c, stack.c, tracepoint.c: Ditto.
* v850-tdep.c, valops.c, z8k-tdep.c: Ditto.
2002-11-24 20:48:13 +01:00
|
|
|
}
|
|
|
|
|
2003-04-01 21:11:01 +02:00
|
|
|
/* High-level offsets into the frame. Used by the debug info. */
|
|
|
|
|
|
|
|
CORE_ADDR
|
|
|
|
get_frame_base_address (struct frame_info *fi)
|
|
|
|
{
|
2003-04-05 05:56:00 +02:00
|
|
|
if (get_frame_type (fi) != NORMAL_FRAME)
|
2003-04-01 21:11:01 +02:00
|
|
|
return 0;
|
|
|
|
if (fi->base == NULL)
|
2003-07-15 19:35:00 +02:00
|
|
|
fi->base = frame_base_find_by_frame (fi->next);
|
2003-04-01 21:11:01 +02:00
|
|
|
/* Sneaky: If the low-level unwind and high-level base code share a
|
|
|
|
common unwinder, let them share the prologue cache. */
|
|
|
|
if (fi->base->unwind == fi->unwind)
|
|
|
|
return fi->base->this_base (fi->next, &fi->prologue_cache);
|
|
|
|
return fi->base->this_base (fi->next, &fi->base_cache);
|
|
|
|
}
|
|
|
|
|
|
|
|
CORE_ADDR
|
|
|
|
get_frame_locals_address (struct frame_info *fi)
|
|
|
|
{
|
|
|
|
void **cache;
|
2003-04-05 05:56:00 +02:00
|
|
|
if (get_frame_type (fi) != NORMAL_FRAME)
|
2003-04-01 21:11:01 +02:00
|
|
|
return 0;
|
|
|
|
/* If there isn't a frame address method, find it. */
|
|
|
|
if (fi->base == NULL)
|
2003-07-15 19:35:00 +02:00
|
|
|
fi->base = frame_base_find_by_frame (fi->next);
|
2003-04-01 21:11:01 +02:00
|
|
|
/* Sneaky: If the low-level unwind and high-level base code share a
|
|
|
|
common unwinder, let them share the prologue cache. */
|
|
|
|
if (fi->base->unwind == fi->unwind)
|
|
|
|
cache = &fi->prologue_cache;
|
|
|
|
else
|
|
|
|
cache = &fi->base_cache;
|
|
|
|
return fi->base->this_locals (fi->next, cache);
|
|
|
|
}
|
|
|
|
|
|
|
|
CORE_ADDR
|
|
|
|
get_frame_args_address (struct frame_info *fi)
|
|
|
|
{
|
|
|
|
void **cache;
|
2003-04-05 05:56:00 +02:00
|
|
|
if (get_frame_type (fi) != NORMAL_FRAME)
|
2003-04-01 21:11:01 +02:00
|
|
|
return 0;
|
|
|
|
/* If there isn't a frame address method, find it. */
|
|
|
|
if (fi->base == NULL)
|
2003-07-15 19:35:00 +02:00
|
|
|
fi->base = frame_base_find_by_frame (fi->next);
|
2003-04-01 21:11:01 +02:00
|
|
|
/* Sneaky: If the low-level unwind and high-level base code share a
|
|
|
|
common unwinder, let them share the prologue cache. */
|
|
|
|
if (fi->base->unwind == fi->unwind)
|
|
|
|
cache = &fi->prologue_cache;
|
|
|
|
else
|
|
|
|
cache = &fi->base_cache;
|
|
|
|
return fi->base->this_args (fi->next, cache);
|
|
|
|
}
|
|
|
|
|
2002-11-19 01:46:00 +01:00
|
|
|
/* Level of the selected frame: 0 for innermost, 1 for its caller, ...
|
|
|
|
or -1 for a NULL frame. */
|
|
|
|
|
|
|
|
int
|
|
|
|
frame_relative_level (struct frame_info *fi)
|
|
|
|
{
|
|
|
|
if (fi == NULL)
|
|
|
|
return -1;
|
|
|
|
else
|
|
|
|
return fi->level;
|
|
|
|
}
|
|
|
|
|
2002-11-18 23:19:33 +01:00
|
|
|
enum frame_type
|
|
|
|
get_frame_type (struct frame_info *frame)
|
|
|
|
{
|
2004-07-31 23:41:50 +02:00
|
|
|
if (frame->unwind == NULL)
|
|
|
|
/* Initialize the frame's unwinder because that's what
|
|
|
|
provides the frame's type. */
|
|
|
|
frame->unwind = frame_unwind_find_by_frame (frame->next,
|
|
|
|
&frame->prologue_cache);
|
|
|
|
return frame->unwind->type;
|
2002-11-18 23:19:33 +01:00
|
|
|
}
|
|
|
|
|
2002-12-13 22:57:40 +01:00
|
|
|
void
|
2002-12-18 19:03:42 +01:00
|
|
|
deprecated_update_frame_pc_hack (struct frame_info *frame, CORE_ADDR pc)
|
2002-12-13 22:57:40 +01:00
|
|
|
{
|
2003-04-10 17:32:27 +02:00
|
|
|
if (frame_debug)
|
|
|
|
fprintf_unfiltered (gdb_stdlog,
|
|
|
|
"{ deprecated_update_frame_pc_hack (frame=%d,pc=0x%s) }\n",
|
|
|
|
frame->level, paddr_nz (pc));
|
2003-03-11 18:47:13 +01:00
|
|
|
/* NOTE: cagney/2003-03-11: Some architectures (e.g., Arm) are
|
2004-04-17 02:48:25 +02:00
|
|
|
maintaining a locally allocated frame object. Since such frames
|
2003-03-11 18:47:13 +01:00
|
|
|
are not in the frame chain, it isn't possible to assume that the
|
|
|
|
frame has a next. Sigh. */
|
|
|
|
if (frame->next != NULL)
|
|
|
|
{
|
|
|
|
/* While we're at it, update this frame's cached PC value, found
|
|
|
|
in the next frame. Oh for the day when "struct frame_info"
|
|
|
|
is opaque and this hack on hack can just go away. */
|
2003-04-09 22:49:22 +02:00
|
|
|
frame->next->prev_pc.value = pc;
|
|
|
|
frame->next->prev_pc.p = 1;
|
2003-03-11 18:47:13 +01:00
|
|
|
}
|
2002-12-18 19:03:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
deprecated_update_frame_base_hack (struct frame_info *frame, CORE_ADDR base)
|
|
|
|
{
|
2003-04-10 17:32:27 +02:00
|
|
|
if (frame_debug)
|
|
|
|
fprintf_unfiltered (gdb_stdlog,
|
|
|
|
"{ deprecated_update_frame_base_hack (frame=%d,base=0x%s) }\n",
|
|
|
|
frame->level, paddr_nz (base));
|
2002-12-18 19:03:42 +01:00
|
|
|
/* See comment in "frame.h". */
|
2003-04-10 05:30:36 +02:00
|
|
|
frame->this_id.value.stack_addr = base;
|
2002-12-13 22:57:40 +01:00
|
|
|
}
|
|
|
|
|
2003-06-03 20:53:37 +02:00
|
|
|
/* Memory access methods. */
|
|
|
|
|
|
|
|
void
|
|
|
|
get_frame_memory (struct frame_info *this_frame, CORE_ADDR addr, void *buf,
|
|
|
|
int len)
|
|
|
|
{
|
|
|
|
read_memory (addr, buf, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
LONGEST
|
|
|
|
get_frame_memory_signed (struct frame_info *this_frame, CORE_ADDR addr,
|
|
|
|
int len)
|
|
|
|
{
|
|
|
|
return read_memory_integer (addr, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
ULONGEST
|
|
|
|
get_frame_memory_unsigned (struct frame_info *this_frame, CORE_ADDR addr,
|
|
|
|
int len)
|
|
|
|
{
|
|
|
|
return read_memory_unsigned_integer (addr, len);
|
|
|
|
}
|
|
|
|
|
2004-04-02 21:44:25 +02:00
|
|
|
int
|
|
|
|
safe_frame_unwind_memory (struct frame_info *this_frame,
|
|
|
|
CORE_ADDR addr, void *buf, int len)
|
|
|
|
{
|
2004-07-20 21:45:07 +02:00
|
|
|
/* NOTE: deprecated_read_memory_nobpt returns zero on success! */
|
|
|
|
return !deprecated_read_memory_nobpt (addr, buf, len);
|
2004-04-02 21:44:25 +02:00
|
|
|
}
|
|
|
|
|
2003-06-03 20:53:37 +02:00
|
|
|
/* Architecture method. */
|
|
|
|
|
|
|
|
struct gdbarch *
|
|
|
|
get_frame_arch (struct frame_info *this_frame)
|
|
|
|
{
|
|
|
|
return current_gdbarch;
|
|
|
|
}
|
|
|
|
|
2003-06-09 03:02:07 +02:00
|
|
|
/* Stack pointer methods. */
|
|
|
|
|
|
|
|
CORE_ADDR
|
|
|
|
get_frame_sp (struct frame_info *this_frame)
|
|
|
|
{
|
|
|
|
return frame_sp_unwind (this_frame->next);
|
|
|
|
}
|
|
|
|
|
|
|
|
CORE_ADDR
|
|
|
|
frame_sp_unwind (struct frame_info *next_frame)
|
|
|
|
{
|
2004-04-17 02:48:25 +02:00
|
|
|
/* Normality - an architecture that provides a way of obtaining any
|
2003-06-09 03:02:07 +02:00
|
|
|
frame inner-most address. */
|
|
|
|
if (gdbarch_unwind_sp_p (current_gdbarch))
|
|
|
|
return gdbarch_unwind_sp (current_gdbarch, next_frame);
|
|
|
|
/* Things are looking grim. If it's the inner-most frame and there
|
2004-04-17 02:48:25 +02:00
|
|
|
is a TARGET_READ_SP, then that can be used. */
|
2003-06-09 03:02:07 +02:00
|
|
|
if (next_frame->level < 0 && TARGET_READ_SP_P ())
|
|
|
|
return TARGET_READ_SP ();
|
|
|
|
/* Now things are really are grim. Hope that the value returned by
|
|
|
|
the SP_REGNUM register is meaningful. */
|
|
|
|
if (SP_REGNUM >= 0)
|
|
|
|
{
|
|
|
|
ULONGEST sp;
|
|
|
|
frame_unwind_unsigned_register (next_frame, SP_REGNUM, &sp);
|
|
|
|
return sp;
|
|
|
|
}
|
|
|
|
internal_error (__FILE__, __LINE__, "Missing unwind SP method");
|
|
|
|
}
|
|
|
|
|
2003-06-08 Andrew Cagney <cagney@redhat.com>
* acinclude.m4 (gcc_AC_CHECK_DECL, (gcc_AC_CHECK_DECL): Stolen
from GCC's acinclude.m4.
* configure.in: Check for getopt's delcaration.
* aclocal.m4, config.in, configure: Re-generate.
* main.c (error_init): Delete declaration.
* defs.h (error_init): Declare.
* rs6000-tdep.c (rs6000_fetch_pointer_argument): Make static.
(rs6000_convert_from_func_ptr_addr): Make static.
(_initialize_rs6000_tdep): Add declaration.
* cli/cli-cmds.c (dont_repeat): Delete declaration.
(show_commands, set_verbose, show_history): Delete declaration.
* top.h (set_verbose): Add declaration.
(show_history, set_history, show_commands): Add declaration.
(do_restore_instream_cleanup): Add declaration.
* objc-lang.c (specialcmp): Make static.
(print_object_command): Make static.
(find_objc_msgsend): Make static.
(find_objc_msgcall_submethod_helper): Make static.
(find_objc_msgcall_submethod): Make static.
(_initialize_objc_language): Add declaration.
(find_implementation_from_class): Make static.
(find_implementation): Make static.
* objc-exp.y (yylex): Delete lookup_struct_typedef declaration.
* objc-lang.h (lookup_struct_typedef): Add declaration.
* cli/cli-interp.c (_initialize_cli_interp): Add declaration.
* cli/cli-script.c (clear_hook_in_cleanup): Make static.
(do_restore_user_call_depth): Make static.
(do_restore_instream_cleanup): Delete declaration.
(dont_repeat): Delete declaration.
* cli/cli-decode.c (add_abbrev_cmd): Delete function.
* cli/cli-dump.c (_initialize_cli_dump): Add declaration.
* reggroups.c (_initialize_reggroup): Add declaration.
* cp-support.c (_initialize_cp_support): Add declaration.
* cp-abi.c (_initialize_cp_abi): Add declaration.
* hpacc-abi.c (_initialize_hpacc_abi): Add declaration.
* gnu-v3-abi.c (gnuv3_baseclass_offset): Make static.
(_initialize_gnu_v3_abi): Add declaration.
* gnu-v2-abi.c (gnuv2_value_rtti_type): Make static.
(_initialize_gnu_v2_abi): Add declaration.
* frame-base.c (_initialize_frame_base): Add declaration.
* doublest.c (floatformat_from_length): Make static.
* frame-unwind.c (_initialize_frame_unwind): Add declaration.
* frame.c (create_sentinel_frame): Make static.
(_initialize_frame): Add declaration.
* top.c (do_catch_errors): Make static.
(gdb_rl_operate_and_get_next_completion): Make static.
* typeprint.c: Include "typeprint.h".
* sentinel-frame.c (sentinel_frame_prev_register): Make static.
(sentinel_frame_this_id): Make static.
* p-valprint.c (_initialize_pascal_valprint): Add declaration.
* ui-out.c (make_cleanup_ui_out_begin_end): Delete function.
* dwarf2-frame.c (dwarf2_frame_cache): Make static.
* p-exp.y (push_current_type, pop_current_type): ISO C declaration.
* dwarf2expr.h (dwarf_expr_context): ISO C declaration.
* maint.c (maintenance_print_architecture): Make static.
* signals/signals.c (_initialize_signals): Add declaration.
* std-regs.c (_initialize_frame_reg): Add declaration.
* jv-exp.y (push_variable): ISO C definition.
(push_qualified_expression_name): Ditto.
* memattr.c (_initialize_mem): Add declaration.
* remote.c (remote_check_watch_resources): Make static.
(remote_stopped_by_watchpoint): Make static.
(remote_stopped_data_address): Make static.
* d10v-tdep.c (nr_dmap_regs): Make static.
(a0_regnum): Make static.
(d10v_frame_unwind_cache): Make static.
(d10v_frame_p): Make static.
* osabi.c (show_osabi): Make static.
(_initialize_gdb_osabi): Add extern declaration.
* gdbtypes.c (make_qualified_type): Make static.
(safe_parse_type): Make static.
* macrocmd.c (_initialize_macrocmd): Add extern declaration.
* macrotab.c (macro_bcache_free): Make static.
* interps.c (interp_set_quiet): Make static.
(interpreter_exec_cmd): Make static.
* stack.h (select_frame_command): New file.
* stack.c: Include "stack.h".
(select_frame_command_wrapper): Delete function.
(select_frame_command): Make global.
* infcall.c: Include "infcall.h".
* linespec.c: Include "linespec.h".
* symfile.c (sections_overlap): Make static.
* cp-support.h (cp_initialize_namespace): ISO C declaration.
* charset.c (_initialize_charset): Add missing prototype.
* regcache.c (init_legacy_regcache_descr): Make static.
(do_regcache_xfree): Make static.
(regcache_xfer_part): Make static.
(_initialize_regcache): Add missing prototype.
* breakpoint.c (parse_breakpoint_sals): Make static.
(breakpoint_sals_to_pc): Make static.
* interps.h (clear_interpreter_hooks): ISO C declaration.
* Makefile.in (stack_h): Define.
(stack.o, typeprint.o, mi-main.o): Update dependencies.
(mi-cmd-stack.o, infcall.o, linespec.o): Update dependencies.
Index: mi/ChangeLog
2003-06-08 Andrew Cagney <cagney@redhat.com>
* mi-parse.c (_initialize_mi_parse): Delete function.
* mi-main.c: Include "mi-main.h".
* mi-interp.c (_initialize_mi_interp): Add declaration.
* mi-cmd-stack.c: Include "stack.h".
(select_frame_command_wrapper): Delete extern declaration.
(mi_cmd_stack_select_frame): Replace select_frame_command_wrapper
with select_frame_command.
2003-06-08 20:27:14 +02:00
|
|
|
extern initialize_file_ftype _initialize_frame; /* -Wmissing-prototypes */
|
|
|
|
|
2003-08-09 17:10:09 +02:00
|
|
|
static struct cmd_list_element *set_backtrace_cmdlist;
|
|
|
|
static struct cmd_list_element *show_backtrace_cmdlist;
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_backtrace_cmd (char *args, int from_tty)
|
|
|
|
{
|
|
|
|
help_list (set_backtrace_cmdlist, "set backtrace ", -1, gdb_stdout);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
show_backtrace_cmd (char *args, int from_tty)
|
|
|
|
{
|
|
|
|
cmd_show_list (show_backtrace_cmdlist, from_tty, "");
|
|
|
|
}
|
|
|
|
|
2002-11-08 21:48:55 +01:00
|
|
|
void
|
|
|
|
_initialize_frame (void)
|
|
|
|
{
|
|
|
|
obstack_init (&frame_cache_obstack);
|
2003-01-21 20:32:42 +01:00
|
|
|
|
2004-04-26 11:49:36 +02:00
|
|
|
observer_attach_target_changed (frame_observer_target_changed);
|
|
|
|
|
2003-08-09 17:10:09 +02:00
|
|
|
add_prefix_cmd ("backtrace", class_maintenance, set_backtrace_cmd, "\
|
|
|
|
Set backtrace specific variables.\n\
|
|
|
|
Configure backtrace variables such as the backtrace limit",
|
|
|
|
&set_backtrace_cmdlist, "set backtrace ",
|
|
|
|
0/*allow-unknown*/, &setlist);
|
|
|
|
add_prefix_cmd ("backtrace", class_maintenance, show_backtrace_cmd, "\
|
|
|
|
Show backtrace specific variables\n\
|
|
|
|
Show backtrace variables such as the backtrace limit",
|
|
|
|
&show_backtrace_cmdlist, "show backtrace ",
|
|
|
|
0/*allow-unknown*/, &showlist);
|
|
|
|
|
|
|
|
add_setshow_boolean_cmd ("past-main", class_obscure,
|
|
|
|
&backtrace_past_main, "\
|
2004-07-28 19:26:27 +02:00
|
|
|
Set whether backtraces should continue past \"main\".", "\
|
|
|
|
Show whether backtraces should continue past \"main\".", "\
|
2003-01-21 20:32:42 +01:00
|
|
|
Normally the caller of \"main\" is not of interest, so GDB will terminate\n\
|
|
|
|
the backtrace at \"main\". Set this variable if you need to see the rest\n\
|
|
|
|
of the stack trace.", "\
|
2004-07-28 19:26:27 +02:00
|
|
|
Whether backtraces should continue past \"main\" is %s.",
|
2003-08-09 17:10:09 +02:00
|
|
|
NULL, NULL, &set_backtrace_cmdlist,
|
|
|
|
&show_backtrace_cmdlist);
|
|
|
|
|
|
|
|
add_setshow_uinteger_cmd ("limit", class_obscure,
|
|
|
|
&backtrace_limit, "\
|
2004-07-28 19:26:27 +02:00
|
|
|
Set an upper bound on the number of backtrace levels.", "\
|
|
|
|
Show the upper bound on the number of backtrace levels.", "\
|
2003-08-10 16:56:23 +02:00
|
|
|
No more than the specified number of frames can be displayed or examined.\n\
|
2003-08-09 17:10:09 +02:00
|
|
|
Zero is unlimited.", "\
|
2004-07-28 19:26:27 +02:00
|
|
|
An upper bound on the number of backtrace levels is %s.",
|
2003-08-09 17:10:09 +02:00
|
|
|
NULL, NULL, &set_backtrace_cmdlist,
|
|
|
|
&show_backtrace_cmdlist);
|
2003-02-26 00:12:22 +01:00
|
|
|
|
|
|
|
/* Debug this files internals. */
|
2004-07-26 16:53:06 +02:00
|
|
|
deprecated_add_show_from_set
|
|
|
|
(add_set_cmd ("frame", class_maintenance, var_zinteger,
|
|
|
|
&frame_debug, "Set frame debugging.\n\
|
2003-02-26 00:12:22 +01:00
|
|
|
When non-zero, frame specific internal debugging is enabled.", &setdebuglist),
|
2004-07-26 16:53:06 +02:00
|
|
|
&showdebuglist);
|
2002-11-08 21:48:55 +01:00
|
|
|
}
|