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:
parent
3d30e9c264
commit
da62e63311
11 changed files with 400 additions and 61 deletions
|
@ -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.
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
154
gdb/frame-base.c
Normal 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
94
gdb/frame-base.h
Normal 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
|
53
gdb/frame.c
53
gdb/frame.c
|
@ -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. */
|
||||
|
||||
|
|
89
gdb/frame.h
89
gdb/frame.h
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
14
gdb/stack.c
14
gdb/stack.c
|
@ -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,");
|
||||
|
|
Loading…
Reference in a new issue