2003-04-01 Andrew Cagney <cagney@redhat.com>

Add frame debug info addresses:
	* frame-base.c: New file.
	* frame-base.h: New file.
	* frame.h (struct frame_base): Add opaque declaration.
	(get_frame_base): Update comment.
	(get_frame_base_address): Declare.
	(get_frame_locals_address): Declare.
	(get_frame_args_address): Declare.
	(struct frame_info): Add "base" and "base_cache".  Update
	comments on the unwinder.
	* frame.c: Include "frame-base.h".
	(get_frame_locals_address): New function.
	(get_frame_base_address): New function.
	(get_frame_args_address): New function.
	* findvar.c (read_var_value): Use get_frame_locals_address and
	get_frame_args_address.
	* stack.c (frame_info): Use get_frame_locals_address and
	get_frame_args_address.
	(FRAME_ARGS_ADDRESS_CORRECT): Delete conditionally defined macro,
	moved to "frame-base.c".
	* printcmd.c (print_frame_nameless_args): Ditto.
	* symtab.h (address_class): Update comments.
	* dwarf2loc.c (dwarf_expr_frame_base): Add note about
	get_frame_base_address.
	* dwarf2expr.c (execute_stack_op): Ditto.
	* Makefile.in (frame_base_h): Define.
	(frame.o): Update dependencies.
	(frame-base.o): Add dependencies.
	(SFILES): Add frame-base.c.
	(COMMON_OBS): Add frame-base.o.
This commit is contained in:
Andrew Cagney 2003-04-01 19:11:01 +00:00
parent 3d30e9c264
commit da62e63311
11 changed files with 400 additions and 61 deletions

View File

@ -1,3 +1,36 @@
2003-04-01 Andrew Cagney <cagney@redhat.com>
Add frame debug info addresses:
* frame-base.c: New file.
* frame-base.h: New file.
* frame.h (struct frame_base): Add opaque declaration.
(get_frame_base): Update comment.
(get_frame_base_address): Declare.
(get_frame_locals_address): Declare.
(get_frame_args_address): Declare.
(struct frame_info): Add "base" and "base_cache". Update
comments on the unwinder.
* frame.c: Include "frame-base.h".
(get_frame_locals_address): New function.
(get_frame_base_address): New function.
(get_frame_args_address): New function.
* findvar.c (read_var_value): Use get_frame_locals_address and
get_frame_args_address.
* stack.c (frame_info): Use get_frame_locals_address and
get_frame_args_address.
(FRAME_ARGS_ADDRESS_CORRECT): Delete conditionally defined macro,
moved to "frame-base.c".
* printcmd.c (print_frame_nameless_args): Ditto.
* symtab.h (address_class): Update comments.
* dwarf2loc.c (dwarf_expr_frame_base): Add note about
get_frame_base_address.
* dwarf2expr.c (execute_stack_op): Ditto.
* Makefile.in (frame_base_h): Define.
(frame.o): Update dependencies.
(frame-base.o): Add dependencies.
(SFILES): Add frame-base.c.
(COMMON_OBS): Add frame-base.o.
2003-04-01 Andrew Cagney <cagney@redhat.com>
* gdbarch.sh (CALL_DUMMY_START_OFFSET): Default to zero.

View File

@ -517,6 +517,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
dummy-frame.c dwarfread.c dwarf2expr.c dwarf2loc.c dwarf2read.c \
elfread.c environ.c eval.c event-loop.c event-top.c expprint.c \
f-exp.y f-lang.c f-typeprint.c f-valprint.c findvar.c frame.c \
frame-base.c \
frame-unwind.c \
gdbarch.c arch-utils.c gdbtypes.c gnu-v2-abi.c gnu-v3-abi.c \
hpacc-abi.c \
@ -641,6 +642,7 @@ expression_h = expression.h $(symtab_h) $(doublest_h)
f_lang_h = f-lang.h
frame_h = frame.h
frame_unwind_h = frame-unwind.h
frame_base_h = frame-base.h
gdb_events_h = gdb-events.h
gdb_stabs_h = gdb-stabs.h
gdb_h = gdb.h
@ -859,6 +861,7 @@ COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o regcache.o \
nlmread.o serial.o mdebugread.o top.o utils.o \
ui-file.o \
frame.o frame-unwind.o doublest.o \
frame-base.o \
gnu-v2-abi.o gnu-v3-abi.o hpacc-abi.o cp-abi.o cp-support.o \
reggroups.o
@ -1702,9 +1705,10 @@ fork-child.o: fork-child.c $(defs_h) $(gdb_string_h) $(frame_h) \
$(terminal_h) $(gdbthread_h) $(command_h)
frame.o: frame.c $(defs_h) $(frame_h) $(target_h) $(value_h) $(inferior_h) \
$(regcache_h) $(gdb_assert_h) $(gdb_string_h) $(builtin_regs_h) \
$(gdb_obstack_h) $(dummy_frame_h) $(gdbcore_h) $(annotate_h) \
$(language_h) $(frame_unwind_h) $(command_h) $(gdbcmd_h) \
$(sentinel_frame_h)
$(gdb_obstack_h) $(dummy_frame_h) $(sentinel_frame_h) $(gdbcore_h) \
$(annotate_h) $(language_h) $(frame_unwind_h) $(frame_base_h) \
$(command_h) $(gdbcmd_h)
frame-base.o: frame-base.c $(defs_h) $(frame_base_h) $(frame_h)
frame-unwind.o: frame-unwind.c $(defs_h) $(frame_h) $(frame_unwind_h) \
$(gdb_assert_h) $(dummy_frame_h) $(legacy_frame_h)
frv-tdep.o: frv-tdep.c $(defs_h) $(inferior_h) $(symfile_h) $(gdbcore_h) \

View File

@ -454,6 +454,9 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
afterwards, effectively erasing whatever the recursive
call put there. */
before_stack_len = ctx->stack_len;
/* FIXME: cagney/2003-03-26: This code should be using
get_frame_base_address(), and then implement a dwarf2
specific this_base method. */
(ctx->get_frame_base) (ctx->baton, &datastart, &datalen);
dwarf_expr_eval (ctx, datastart, datalen);
result = dwarf_expr_fetch (ctx, 0);

View File

@ -87,6 +87,9 @@ dwarf_expr_read_mem (void *baton, char *buf, CORE_ADDR addr, size_t len)
static void
dwarf_expr_frame_base (void *baton, unsigned char **start, size_t * length)
{
/* FIXME: cagney/2003-03-26: This code should be using
get_frame_base_address(), and then implement a dwarf2 specific
this_base method. */
struct symbol *framefunc;
struct dwarf2_locexpr_baton *symbaton;
struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;

View File

@ -508,7 +508,7 @@ addresses have not been bound by the dynamic loader. Try again when executable i
case LOC_ARG:
if (frame == NULL)
return 0;
addr = FRAME_ARGS_ADDRESS (frame);
addr = get_frame_args_address (frame);
if (!addr)
return 0;
addr += SYMBOL_VALUE (var);
@ -520,7 +520,7 @@ addresses have not been bound by the dynamic loader. Try again when executable i
CORE_ADDR argref;
if (frame == NULL)
return 0;
argref = FRAME_ARGS_ADDRESS (frame);
argref = get_frame_args_address (frame);
if (!argref)
return 0;
argref += SYMBOL_VALUE (var);
@ -533,7 +533,7 @@ addresses have not been bound by the dynamic loader. Try again when executable i
case LOC_LOCAL_ARG:
if (frame == NULL)
return 0;
addr = FRAME_LOCALS_ADDRESS (frame);
addr = get_frame_locals_address (frame);
addr += SYMBOL_VALUE (var);
break;

154
gdb/frame-base.c Normal file
View File

@ -0,0 +1,154 @@
/* Definitions for frame address handler, for GDB, the GNU debugger.
Copyright 2003 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 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-base.h"
#include "frame.h"
/* A default frame base implementations. If it wasn't for the old
FRAME_LOCALS_ADDRESS and FRAME_ARGS_ADDRESS, these could be
combined into a single function. All architectures really need to
override this. */
static CORE_ADDR
default_frame_base_address (struct frame_info *next_frame, void **this_cache)
{
struct frame_info *this_frame = get_prev_frame (next_frame);
return get_frame_base (this_frame); /* sigh! */
}
static CORE_ADDR
default_frame_locals_address (struct frame_info *next_frame, void **this_cache)
{
struct frame_info *this_frame = get_prev_frame (next_frame);
return FRAME_LOCALS_ADDRESS (this_frame);
}
static CORE_ADDR
default_frame_args_address (struct frame_info *next_frame, void **this_cache)
{
struct frame_info *this_frame = get_prev_frame (next_frame);
/* FRAME_ARGS_ADDRESS_CORRECT is just like FRAME_ARGS_ADDRESS except
that if it is unsure about the answer, it returns 0 instead of
guessing (this happens on the VAX and i960, for example).
On most machines, we never have to guess about the args address,
so FRAME_ARGS_ADDRESS{,_CORRECT} are the same. */
#ifdef FRAME_ARGS_ADDRESS_CORRECT
return FRAME_ARGS_ADDRESS_CORRECT (this_frame);
#else
return FRAME_ARGS_ADDRESS (this_frame);
#endif
}
const struct frame_base default_frame_base = {
NULL, /* No parent. */
default_frame_base_address,
default_frame_locals_address,
default_frame_args_address
};
static struct gdbarch_data *frame_base_data;
struct frame_base_table
{
frame_base_p_ftype **p;
const struct frame_base *default_base;
int nr;
};
static void *
frame_base_init (struct gdbarch *gdbarch)
{
struct frame_base_table *table = XCALLOC (1, struct frame_base_table);
table->default_base = &default_frame_base;
return table;
}
static void
frame_base_free (struct gdbarch *gdbarch, void *data)
{
struct frame_base_table *table =
gdbarch_data (gdbarch, frame_base_data);
xfree (table->p);
xfree (table);
}
static struct frame_base_table *
frame_base_table (struct gdbarch *gdbarch)
{
struct frame_base_table *table = gdbarch_data (gdbarch, frame_base_data);
if (table == NULL)
{
/* ULGH, called during architecture initialization. Patch
things up. */
table = frame_base_init (gdbarch);
set_gdbarch_data (gdbarch, frame_base_data, table);
}
return table;
}
/* Append a predicate to the end of the table. */
static void
append_predicate (struct frame_base_table *table, frame_base_p_ftype *p)
{
table->p = xrealloc (table->p, ((table->nr + 1)
* sizeof (frame_base_p_ftype *)));
table->p[table->nr] = p;
table->nr++;
}
void
frame_base_append_predicate (struct gdbarch *gdbarch,
frame_base_p_ftype *p)
{
struct frame_base_table *table = frame_base_table (gdbarch);
append_predicate (table, p);
}
void
frame_base_set_default (struct gdbarch *gdbarch,
const struct frame_base *default_base)
{
struct frame_base_table *table = frame_base_table (gdbarch);
table->default_base = default_base;
}
const struct frame_base *
frame_base_find_by_pc (struct gdbarch *gdbarch, CORE_ADDR pc)
{
int i;
struct frame_base_table *table = frame_base_table (gdbarch);
for (i = 0; i < table->nr; i++)
{
const struct frame_base *desc = table->p[i] (pc);
if (desc != NULL)
return desc;
}
return table->default_base;
}
void
_initialize_frame_base (void)
{
frame_base_data = register_gdbarch_data (frame_base_init,
frame_base_free);
}

94
gdb/frame-base.h Normal file
View File

@ -0,0 +1,94 @@
/* Definitions for a frame base, for GDB, the GNU debugger.
Copyright 2003 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 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. */
#if !defined (FRAME_BASE_H)
#define FRAME_BASE_H 1
struct frame_info;
struct frame_id;
struct frame_unwind;
struct frame_base;
struct gdbarch;
struct regcache;
/* Return the frame base methods for the function that contains PC, or
NULL if it can't handle this frame. */
typedef const struct frame_base *(frame_base_p_ftype) (CORE_ADDR pc);
/* Add a frame base handler to the list. The predicates are polled in
the order that they are appended. */
extern void frame_base_append_predicate (struct gdbarch *gdbarch,
frame_base_p_ftype *p);
/* Set the default frame base. If all else fails, this one is
returned. If this isn't set, the default is to use legacy code
that uses things like the frame ID's base (ulgh!). */
extern void frame_base_set_default (struct gdbarch *gdbarch,
const struct frame_base *def);
/* Iterate through the list of frame base handlers until one returns
an implementation. */
extern const struct frame_base *frame_base_find_by_pc (struct gdbarch *gdbarch,
CORE_ADDR pc);
/* Assuming the frame chain: (outer) prev <-> this <-> next (inner);
and that this is a `normal frame'; use the NEXT frame, and its
register unwind method, to determine the address of THIS frame's
`base'.
The exact meaning of `base' is highly dependant on the type of the
debug info. It is assumed that dwarf2, stabs, ... will each
provide their own methods.
A typical implmentation will return the same value for base,
locals-base and args-base. That value, however, will likely be
different to the frame ID's stack address. */
/* A generic base address. */
typedef CORE_ADDR (frame_this_base_ftype) (struct frame_info *next_frame,
void **this_base_cache);
/* The base address of the frame's local variables. */
typedef CORE_ADDR (frame_this_locals_ftype) (struct frame_info *next_frame,
void **this_base_cache);
/* The base address of the frame's arguments / parameters. */
typedef CORE_ADDR (frame_this_args_ftype) (struct frame_info *next_frame,
void **this_base_cache);
struct frame_base
{
/* If non-NULL, a low-level unwinder that shares its implementation
with this high-level frame-base method. */
const struct frame_unwind *unwind;
frame_this_base_ftype *this_base;
frame_this_locals_ftype *this_locals;
frame_this_args_ftype *this_args;
};
#endif

View File

@ -36,6 +36,7 @@
#include "annotate.h"
#include "language.h"
#include "frame-unwind.h"
#include "frame-base.h"
#include "command.h"
#include "gdbcmd.h"
@ -1630,6 +1631,58 @@ get_frame_base (struct frame_info *fi)
return fi->frame;
}
/* High-level offsets into the frame. Used by the debug info. */
CORE_ADDR
get_frame_base_address (struct frame_info *fi)
{
if (fi->type != NORMAL_FRAME)
return 0;
if (fi->base == NULL)
fi->base = frame_base_find_by_pc (current_gdbarch, get_frame_pc (fi));
/* 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;
if (fi->type != NORMAL_FRAME)
return 0;
/* If there isn't a frame address method, find it. */
if (fi->base == NULL)
fi->base = frame_base_find_by_pc (current_gdbarch, get_frame_pc (fi));
/* 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;
if (fi->type != NORMAL_FRAME)
return 0;
/* If there isn't a frame address method, find it. */
if (fi->base == NULL)
fi->base = frame_base_find_by_pc (current_gdbarch, get_frame_pc (fi));
/* 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);
}
/* Level of the selected frame: 0 for innermost, 1 for its caller, ...
or -1 for a NULL frame. */

View File

@ -25,6 +25,7 @@
struct symtab_and_line;
struct frame_unwind;
struct frame_base;
struct block;
/* A legacy unwinder to prop up architectures using the old style
@ -169,47 +170,25 @@ extern CORE_ADDR get_frame_pc (struct frame_info *);
extern void find_frame_sal (struct frame_info *frame,
struct symtab_and_line *sal);
/* Return the frame address from FI. Except in the machine-dependent
*FRAME* macros, a frame address has no defined meaning other than
as a magic cookie which identifies a frame over calls to the
inferior (um, SEE NOTE BELOW). The only known exception is
inferior.h (DEPRECATED_PC_IN_CALL_DUMMY) [ON_STACK]; see comments
there. You cannot assume that a frame address contains enough
information to reconstruct the frame; if you want more than just to
identify the frame (e.g. be able to fetch variables relative to
that frame), then save the whole struct frame_info (and the next
struct frame_info, since the latter is used for fetching variables
on some machines) (um, again SEE NOTE BELOW).
/* Return the frame base (what ever that is) (DEPRECATED).
NOTE: cagney/2002-11-18: Actually, the frame address isn't
sufficient for identifying a frame, and the counter examples are
wrong!
Old code was trying to use this single method for two conflicting
purposes. Such code needs to be updated to use either of:
Code that needs to (re)identify a frame must use get_frame_id() and
frame_find_by_id() (and in the future, a frame_compare() function
instead of INNER_THAN()). Two reasons: an architecture (e.g.,
ia64) can have more than one frame address (due to multiple stack
pointers) (frame ID is going to be expanded to accomodate this);
successive frameless function calls can only be differientated by
comparing both the frame's base and the frame's enclosing function
(frame_find_by_id() is going to be modified to perform this test).
get_frame_id: A low level frame unique identifier, that consists of
both a stack and a function address, that can be used to uniquely
identify a frame. This value is determined by the frame's
low-level unwinder, the stack part [typically] being the
top-of-stack of the previous frame, and the function part being the
function's start address. Since the correct identification of a
frameless function requires both the a stack and function address,
the old get_frame_base method was not sufficient.
The generic dummy frame version of DEPRECATED_PC_IN_CALL_DUMMY() is
able to identify a dummy frame using only the PC value. So the
frame address is not needed. In fact, most
DEPRECATED_PC_IN_CALL_DUMMY() calls now pass zero as the frame/sp
values as the caller knows that those values won't be used. Once
all architectures are using generic dummy frames,
DEPRECATED_PC_IN_CALL_DUMMY() can drop the sp/frame parameters.
When it comes to finding a dummy frame, the next frame's frame ID
(with out duing an unwind) can be used (ok, could if it wasn't for
the need to change the way the PPC defined frame base in a strange
way).
Modern architectures should be using something like dwarf2's
location expression to describe where a variable lives. Such
expressions specify their own debug info centric frame address.
Consequently, a generic frame address is pretty meaningless. */
get_frame_base_address: get_frame_locals_address:
get_frame_args_address: A set of high-level debug-info dependant
addresses that fall within the frame. These addresses almost
certainly will not match the stack address part of a frame ID (as
returned by get_frame_base). */
extern CORE_ADDR get_frame_base (struct frame_info *);
@ -218,6 +197,25 @@ extern CORE_ADDR get_frame_base (struct frame_info *);
FI is NULL, return the null_frame_id. */
extern struct frame_id get_frame_id (struct frame_info *fi);
/* Assuming that a frame is `normal', return its base-address, or 0 if
the information isn't available. NOTE: This address is really only
meaningful to the frame's high-level debug info. */
extern CORE_ADDR get_frame_base_address (struct frame_info *);
/* Assuming that a frame is `normal', return the address of the first
local variable, or 0 if the information isn't available. NOTE:
This address is really only meaningful to the frame's high-level
debug info. Typically, the argument and locals share a single
base-address. */
extern CORE_ADDR get_frame_locals_address (struct frame_info *);
/* Assuming that a frame is `normal', return the address of the first
parameter, or 0 if that information isn't available. NOTE: This
address is really only meaningful to the frame's high-level debug
info. Typically, the argument and locals share a single
base-address. */
extern CORE_ADDR get_frame_args_address (struct frame_info *);
/* The frame's level: 0 for innermost, 1 for its caller, ...; or -1
for an invalid frame). */
extern int frame_relative_level (struct frame_info *fi);
@ -398,11 +396,12 @@ struct frame_info
related unwind data. */
struct context *context;
/* Prologue cache shared between the unwind functions. See
"frame-unwind.h" for more information. */
/* 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
selected based on the presence, or otherwize, of register
unwind information such as CFI. */
void *prologue_cache;
/* The frame's unwinder. */
const struct frame_unwind *unwind;
/* Cached copy of the previous frame's resume address. */
@ -414,6 +413,12 @@ struct frame_info
int id_p;
struct frame_id 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 */

View File

@ -1959,7 +1959,7 @@ print_frame_nameless_args (struct frame_info *fi, long start, int num,
#ifdef NAMELESS_ARG_VALUE
NAMELESS_ARG_VALUE (fi, start, &arg_value);
#else
argsaddr = FRAME_ARGS_ADDRESS (fi);
argsaddr = get_frame_args_address (fi);
if (!argsaddr)
return;

View File

@ -600,16 +600,6 @@ parse_frame_specification (char *frame_exp)
/* NOTREACHED */
}
/* FRAME_ARGS_ADDRESS_CORRECT is just like FRAME_ARGS_ADDRESS except
that if it is unsure about the answer, it returns 0
instead of guessing (this happens on the VAX and i960, for example).
On most machines, we never have to guess about the args address,
so FRAME_ARGS_ADDRESS{,_CORRECT} are the same. */
#if !defined (FRAME_ARGS_ADDRESS_CORRECT)
#define FRAME_ARGS_ADDRESS_CORRECT FRAME_ARGS_ADDRESS
#endif
/* Print verbosely the selected frame or the frame at address ADDR.
This means absolutely all information in the frame is printed. */
@ -743,7 +733,7 @@ frame_info (char *addr_exp, int from_tty)
{
/* Address of the argument list for this frame, or 0. */
CORE_ADDR arg_list = FRAME_ARGS_ADDRESS_CORRECT (fi);
CORE_ADDR arg_list = get_frame_args_address (fi);
/* Number of args for this frame, or -1 if unknown. */
int numargs;
@ -770,7 +760,7 @@ frame_info (char *addr_exp, int from_tty)
}
{
/* Address of the local variables for this frame, or 0. */
CORE_ADDR arg_list = FRAME_LOCALS_ADDRESS (fi);
CORE_ADDR arg_list = get_frame_locals_address (fi);
if (arg_list == 0)
printf_filtered (" Locals at unknown address,");