From de3375b747d17f0e3f4b27cd63a8e5d9f623bf4b Mon Sep 17 00:00:00 2001 From: Andrew Cagney Date: Thu, 3 Apr 2003 17:01:49 +0000 Subject: [PATCH] 2003-04-03 Andrew Cagney * frame.c (frame_id_eq): Update. Compare function addresses. (get_frame_func): New function. (frame_func_unwind): New function. (legacy_get_prev_frame): Move linking of prev to next to the start of the function. (frame_id_p): Update. (get_frame_id): Return the frame's "id". Do not set "frame". (frame_id_build): Update. (frame_id_inner): Update. (create_sentinel_frame): Do not set the "pc". (select_frame): Use get_frame_pc. (legacy_saved_regs_this_id): Use frame_id_build. (create_new_frame): Set the frame's ID. Store the PC in the sentinel frame's PC unwind cache. (legacy_get_prev_frame): Do not set "pc" or "frame". Instead use frame_pc_unwind, frame_id_build, deprecated_update_frame_pc_hack, and deprecated_update_frame_base_hack. (get_prev_frame): Do not set "pc" or "frame", instead use frame_pc_unwind. (get_frame_pc): Use frame_pc_unwind. (find_frame_sal): Use get_frame_pc. (get_frame_base): Return the frame ID's stack address. (deprecated_update_frame_base_hack): Set the frame ID's stack address. (frame_id_eq, frame_id_p, frame_id_inner, get_frame_id): Add debug print statements. * d10v-tdep.c (d10v_frame_unwind_cache): Use frame_func_unwind. (d10v_frame_this_id): Get the frame's function. (d10v_frame_this_id): Use frame_id_eq. (d10v_unwind_dummy_id): Use frame_id_build. * stack.c (print_frame_info): Use get_frame_pc. * dummy-frame.c (dummy_frame_this_id): Use frame_id_build. Update parameter to find_dummy_frame. * breakpoint.c (print_one_breakpoint): Update. * frame.h (struct frame_id): Rename "base" to "stack_addr", replace "pc" with "func_addr". (frame_id_build): Update parameter names and comment. (struct frame_info): Delete "frame" and "pc" fields. (frame_func_unwind): Declare. (get_frame_func): Declare. (struct frame_info): Add field "func". --- gdb/ChangeLog | 49 +++++++++ gdb/breakpoint.c | 2 +- gdb/d10v-tdep.c | 16 ++- gdb/dummy-frame.c | 11 +- gdb/frame.c | 250 +++++++++++++++++++++++++++++++++------------- gdb/frame.h | 53 +++++----- gdb/stack.c | 2 +- 7 files changed, 272 insertions(+), 111 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index e5d2ce6ac28..4c3ec8f591c 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,52 @@ +2003-04-03 Andrew Cagney + + * frame.c (frame_id_eq): Update. Compare function addresses. + (get_frame_func): New function. + (frame_func_unwind): New function. + (legacy_get_prev_frame): Move linking of prev to next to the start + of the function. + (frame_id_p): Update. + (get_frame_id): Return the frame's "id". Do not set "frame". + (frame_id_build): Update. + (frame_id_inner): Update. + (create_sentinel_frame): Do not set the "pc". + (select_frame): Use get_frame_pc. + (legacy_saved_regs_this_id): Use frame_id_build. + (create_new_frame): Set the frame's ID. Store the PC in the + sentinel frame's PC unwind cache. + (legacy_get_prev_frame): Do not set "pc" or "frame". Instead use + frame_pc_unwind, frame_id_build, deprecated_update_frame_pc_hack, + and deprecated_update_frame_base_hack. + (get_prev_frame): Do not set "pc" or "frame", instead use + frame_pc_unwind. + (get_frame_pc): Use frame_pc_unwind. + (find_frame_sal): Use get_frame_pc. + (get_frame_base): Return the frame ID's stack address. + (deprecated_update_frame_base_hack): Set the frame ID's stack + address. + (frame_id_eq, frame_id_p, frame_id_inner, get_frame_id): Add debug + print statements. + + * d10v-tdep.c (d10v_frame_unwind_cache): Use frame_func_unwind. + (d10v_frame_this_id): Get the frame's function. + (d10v_frame_this_id): Use frame_id_eq. + (d10v_unwind_dummy_id): Use frame_id_build. + + * stack.c (print_frame_info): Use get_frame_pc. + + * dummy-frame.c (dummy_frame_this_id): Use frame_id_build. Update + parameter to find_dummy_frame. + + * breakpoint.c (print_one_breakpoint): Update. + + * frame.h (struct frame_id): Rename "base" to "stack_addr", + replace "pc" with "func_addr". + (frame_id_build): Update parameter names and comment. + (struct frame_info): Delete "frame" and "pc" fields. + (frame_func_unwind): Declare. + (get_frame_func): Declare. + (struct frame_info): Add field "func". + 2003-04-02 Bob Rossi * Makefile.in (SUBDIR_MI_OBS): Add "mi-cmd-file.o". diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index b3494576618..8ab9e541f23 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -3418,7 +3418,7 @@ print_one_breakpoint (struct breakpoint *b, ui_out_text (uiout, "\tstop only in stack frame at "); /* FIXME: cagney/2002-12-01: Shouldn't be poeking around inside the frame ID. */ - ui_out_field_core_addr (uiout, "frame", b->frame_id.base); + ui_out_field_core_addr (uiout, "frame", b->frame_id.stack_addr); ui_out_text (uiout, "\n"); } diff --git a/gdb/d10v-tdep.c b/gdb/d10v-tdep.c index 9d56169d7df..a6bc742e783 100644 --- a/gdb/d10v-tdep.c +++ b/gdb/d10v-tdep.c @@ -720,8 +720,8 @@ d10v_frame_unwind_cache (struct frame_info *next_frame, info->sp_offset = 0; info->uses_frame = 0; - for (pc = get_pc_function_start (frame_pc_unwind (next_frame)); - pc < frame_pc_unwind (next_frame); + for (pc = frame_func_unwind (next_frame); + pc > 0 && pc < frame_pc_unwind (next_frame); pc += 4) { op = (unsigned long) read_memory_integer (pc, 4); @@ -1453,8 +1453,8 @@ d10v_frame_this_id (struct frame_info *next_frame, CORE_ADDR base; CORE_ADDR pc; - /* The PC is easy. */ - pc = frame_pc_unwind (next_frame); + /* The PC/FUNC is easy. */ + pc = frame_func_unwind (next_frame); /* This is meant to halt the backtrace at "_start". Make sure we don't halt it at a generic dummy frame. */ @@ -1474,8 +1474,8 @@ d10v_frame_this_id (struct frame_info *next_frame, compare the frame's PC value. */ if (frame_relative_level (next_frame) >= 0 && get_frame_type (next_frame) != DUMMY_FRAME - && get_frame_id (next_frame).pc == pc - && get_frame_id (next_frame).base == base) + && frame_id_eq (get_frame_id (next_frame), + frame_id_build (base, pc))) return; (*this_id) = frame_id_build (base, pc); @@ -1588,10 +1588,8 @@ d10v_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame) { ULONGEST base; struct frame_id id; - id.pc = frame_pc_unwind (next_frame); frame_unwind_unsigned_register (next_frame, SP_REGNUM, &base); - id.base = d10v_make_daddr (base); - return id; + return frame_id_build (d10v_make_daddr (base), frame_pc_unwind (next_frame)); } static gdbarch_init_ftype d10v_gdbarch_init; diff --git a/gdb/dummy-frame.c b/gdb/dummy-frame.c index f088405213e..eee36c69b2c 100644 --- a/gdb/dummy-frame.c +++ b/gdb/dummy-frame.c @@ -374,8 +374,7 @@ dummy_frame_this_id (struct frame_info *next_frame, same sequence as is found a traditional unwinder. Once all architectures supply the unwind_dummy_id method, this code can go away. */ - (*this_id).base = read_fp (); - (*this_id).pc = read_pc (); + (*this_id) = frame_id_build (read_fp (), read_pc ()); } else if (legacy_frame_p (current_gdbarch) && get_prev_frame (next_frame)) @@ -384,8 +383,9 @@ dummy_frame_this_id (struct frame_info *next_frame, get_prev_frame code has already created THIS frame and linked it in to the frame chain (a pretty bold assumption), extract the ID from THIS base / pc. */ - (*this_id).base = get_frame_base (get_prev_frame (next_frame)); - (*this_id).pc = get_frame_pc (get_prev_frame (next_frame)); + (*this_id) + = frame_id_build (get_frame_base (get_prev_frame (next_frame)), + get_frame_pc (get_prev_frame (next_frame))); } else { @@ -398,7 +398,8 @@ dummy_frame_this_id (struct frame_info *next_frame, (*this_id) = null_frame_id; return; } - (*this_prologue_cache) = find_dummy_frame ((*this_id).pc, (*this_id).base); + (*this_prologue_cache) = find_dummy_frame ((*this_id).func_addr, + (*this_id).stack_addr); } static struct frame_unwind dummy_frame_unwind = diff --git a/gdb/frame.c b/gdb/frame.c index 09dea5e4c02..fecb48949e6 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -48,6 +48,23 @@ static int frame_debug; static int backtrace_below_main; +/* Utility to print a frame ID. */ +static void +fprint_frame_id (struct ui_file *file, struct frame_id id) +{ + fprintf_unfiltered (file, "stack=0x%s func=0x%s", + paddr (id.stack_addr), + paddr (id.func_addr)); +} + +static void +fprint_frame (struct ui_file *file, struct frame_info *fi) +{ + fprintf_unfiltered (gdb_stdlog, "frame %d @0x%s: ID ", + fi->level, paddr (get_frame_pc (fi))); + fprint_frame_id (gdb_stdlog, fi->id); +} + /* Return a frame uniq ID that can be used to, later, re-find the frame. */ @@ -64,52 +81,99 @@ get_frame_id (struct frame_info *fi) /* Find THIS frame's ID. */ fi->unwind->this_id (fi->next, &fi->prologue_cache, &fi->id); fi->id_p = 1; - /* FIXME: cagney/2002-12-18: Instead of this hack, should only - store the frame ID in PREV_FRAME. Unfortunatly, some - architectures (HP/UX) still reply on EXTRA_FRAME_INFO and, - hence, still poke at the "struct frame_info" object directly. */ - fi->frame = fi->id.base; + if (frame_debug) + { + fprint_frame (gdb_stdlog, fi); + fprintf_unfiltered (gdb_stdlog, "\n"); + } } - return frame_id_build (fi->frame, fi->pc); + return fi->id; } const struct frame_id null_frame_id; /* All zeros. */ struct frame_id -frame_id_build (CORE_ADDR base, CORE_ADDR func_or_pc) +frame_id_build (CORE_ADDR stack_addr, CORE_ADDR func_addr) { struct frame_id id; - id.base = base; - id.pc = func_or_pc; + id.stack_addr = stack_addr; + id.func_addr = func_addr; return id; } int frame_id_p (struct frame_id l) { + int p; /* The .func can be NULL but the .base cannot. */ - return (l.base != 0); + p = (l.stack_addr != 0); + if (frame_debug) + { + fprintf_unfiltered (gdb_stdlog, "ID "); + fprint_frame_id (gdb_stdlog, l); + if (p) + fprintf_unfiltered (gdb_stdlog, " .OK"); + else + fprintf_unfiltered (gdb_stdlog, " !OK"); + fprintf_unfiltered (gdb_stdlog, "\n"); + } + return p; } int frame_id_eq (struct frame_id l, struct frame_id r) { - /* If .base is different, the frames are different. */ - if (l.base != r.base) - return 0; - /* Add a test to check that the frame ID's are for the same function - here. */ - return 1; + int eq; + /* Compare stacks. The stack addresses must always match and can + never be zero. */ + if (l.stack_addr == 0 || r.stack_addr == 0) + eq = 0; + else if (l.stack_addr != r.stack_addr) + eq = 0; + /* Compare functions. A zero function address acts like a wild + card, otherwize a perfect match is expected. */ + else if (l.func_addr == 0 || r.func_addr == 0) + eq = 1; + else if (l.func_addr == r.func_addr) + eq = 1; + else + /* No luck. */ + eq = 0; + if (frame_debug) + { + fprintf_unfiltered (gdb_stdlog, "ID "); + fprint_frame_id (gdb_stdlog, l); + if (eq) + fprintf_unfiltered (gdb_stdlog, " .EQ "); + else + fprintf_unfiltered (gdb_stdlog, " !EQ "); + fprintf_unfiltered (gdb_stdlog, "ID "); + fprint_frame_id (gdb_stdlog, r) ; + fprintf_unfiltered (gdb_stdlog, "\n"); + } + return eq; } int frame_id_inner (struct frame_id l, struct frame_id r) { + int inner; /* 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 .base but different .func). */ - return INNER_THAN (l.base, r.base); + inner = gdbarch_inner_than (current_gdbarch, l.stack_addr, r.stack_addr); + if (frame_debug) + { + fprint_frame_id (gdb_stdlog, l); + if (inner) + fprintf_unfiltered (gdb_stdlog, " .INNER "); + else + fprintf_unfiltered (gdb_stdlog, " !INNER "); + fprint_frame_id (gdb_stdlog, r); + fprintf_unfiltered (gdb_stdlog, "\n"); + } + return inner; } struct frame_info * @@ -192,6 +256,24 @@ frame_pc_unwind (struct frame_info *this_frame) return this_frame->pc_unwind_cache; } +CORE_ADDR +frame_func_unwind (struct frame_info *this_frame) +{ + if (!this_frame->func.p) + { + CORE_ADDR pc = frame_pc_unwind (this_frame); + this_frame->func.cache = get_pc_function_start (pc); + } + return this_frame->func.cache; +} + +CORE_ADDR +get_frame_func (struct frame_info *this_frame) +{ + return frame_func_unwind (this_frame->next); +} + + static int do_frame_unwind_register (void *src, int regnum, void *buf) { @@ -503,15 +585,15 @@ create_sentinel_frame (struct regcache *regcache) frame->prologue_cache = sentinel_frame_cache (regcache); /* For the moment there is only one sentinel frame implementation. */ frame->unwind = sentinel_frame_unwind; + /* Give it a really large frame ID. */ + frame->id_p = 1; + if (INNER_THAN (1, 2)) + frame->id = frame_id_build (0, 0); + else + frame->id = frame_id_build (-1, 0); /* 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; - /* Always unwind the PC as part of creating this frame. This - ensures that the frame's PC points at something valid. */ - /* FIXME: cagney/2003-01-10: Problem here. Unwinding a sentinel - frame's PC may require information such as the frame's thread's - stop reason. Is it possible to get to that? */ - frame->pc = frame_pc_unwind (frame); return frame; } @@ -585,6 +667,10 @@ get_current_frame (void) if (catch_exceptions (uiout, unwind_to_current_frame, sentinel_frame, NULL, RETURN_MASK_ERROR) != 0) { + if (frame_debug) + { + fprintf_unfiltered (gdb_stdlog, "Oops!\n"); + } /* Oops! Fake a current frame? Is this useful? It has a PC of zero, for instance. */ current_frame = sentinel_frame; @@ -641,7 +727,7 @@ select_frame (struct frame_info *fi) source language of this frame, and switch to it if desired. */ if (fi) { - s = find_pc_symtab (fi->pc); + s = find_pc_symtab (get_frame_pc (fi)); if (s && s->language != current_language->la_language && s->language != language_unknown @@ -756,8 +842,7 @@ legacy_saved_regs_this_id (struct frame_info *next_frame, unwinding a sentinel frame, the PC of which is pointing at a stack dummy. Fake up the dummy frame's ID using the same sequence as is found a traditional unwinder. */ - (*id).base = read_fp (); - (*id).pc = read_pc (); + (*id) = frame_id_build (read_fp (), 0 /*read_pc ()*/); return; } @@ -810,8 +895,7 @@ legacy_saved_regs_this_id (struct frame_info *next_frame, /* FIXME: cagney/2002-06-08: This should probably return the frame's function and not the PC (a.k.a. resume address). */ pc = frame_pc_unwind (next_frame); - id->pc = pc; - id->base = base; + (*id) = frame_id_build (base, 0 /*pc*/); } const struct frame_unwind legacy_saved_regs_unwinder = { @@ -955,16 +1039,25 @@ create_new_frame (CORE_ADDR addr, CORE_ADDR pc) fi = frame_obstack_zalloc (sizeof (struct frame_info)); - fi->frame = addr; - fi->pc = pc; + /* FIXME: cagney/2003-04-02: Should this instead try to map that pc + onto a function. */ + if (frame_debug) + fprintf_unfiltered (gdb_stdlog, "create new frame\n"); + + fi->id = frame_id_build (addr, pc); + fi->id_p = 1; + fi->next = create_sentinel_frame (current_regcache); + fi->next->pc_unwind_cache = pc; + fi->next->pc_unwind_cache_p = 1; + fi->type = frame_type_from_pc (pc); if (DEPRECATED_INIT_EXTRA_FRAME_INFO_P ()) DEPRECATED_INIT_EXTRA_FRAME_INFO (0, fi); /* Select/initialize an unwind function. */ - fi->unwind = frame_unwind_find_by_pc (current_gdbarch, fi->pc); + fi->unwind = frame_unwind_find_by_pc (current_gdbarch, get_frame_pc (fi)); return fi; } @@ -1033,6 +1126,13 @@ legacy_get_prev_frame (struct frame_info *this_frame) prev = FRAME_OBSTACK_ZALLOC (struct frame_info); prev->level = this_frame->level + 1; + /* Link prev to this. This ensures that functions such as + get_frame_pc(), called by all the deprecated init functions + below, and implemented using frame_pc_unwind (prev->next) work. + Don't link this to prev as this stops functions walking up the + frame chain to this partially initialized method. */ + prev->next = this_frame; + /* NOTE: cagney/2002-11-18: Should have been correctly setting the frame's type here, before anything else, and not last, at the bottom of this function. The various @@ -1069,8 +1169,7 @@ legacy_get_prev_frame (struct frame_info *this_frame) because (well ignoring the PPC) a dummy frame can be located using THIS_FRAME's frame ID. */ - prev->pc = frame_pc_unwind (this_frame); - if (prev->pc == 0) + if (frame_pc_unwind (this_frame) == 0) { /* The allocated PREV_FRAME will be reclaimed when the frame obstack is next purged. */ @@ -1079,10 +1178,11 @@ legacy_get_prev_frame (struct frame_info *this_frame) "Outermost frame - unwound PC zero\n"); return NULL; } - prev->type = frame_type_from_pc (prev->pc); + prev->type = frame_type_from_pc (frame_pc_unwind (this_frame)); /* Set the unwind functions based on that identified PC. */ - prev->unwind = frame_unwind_find_by_pc (current_gdbarch, prev->pc); + prev->unwind = frame_unwind_find_by_pc (current_gdbarch, + frame_pc_unwind (this_frame)); /* Find the prev's frame's ID. */ if (prev->type == DUMMY_FRAME @@ -1113,8 +1213,7 @@ legacy_get_prev_frame (struct frame_info *this_frame) using the same sequence as is found a traditional unwinder. Once all architectures supply the unwind_dummy_id method, this code can go away. */ - prev->id.base = read_fp (); - prev->id.pc = read_pc (); + prev->id = frame_id_build (read_fp (), read_pc ()); } /* Check that the unwound ID is valid. */ @@ -1135,15 +1234,8 @@ legacy_get_prev_frame (struct frame_info *this_frame) after the switch to storing the frame ID, instead of the frame base, in the frame object. */ - /* FIXME: cagney/2002-12-18: Instead of this hack, should only - store the frame ID in PREV_FRAME. Unfortunatly, some - architectures (HP/UX) still reply on EXTRA_FRAME_INFO and, - hence, still poke at the "struct frame_info" object directly. */ - prev->frame = prev->id.base; - /* Link it in. */ this_frame->prev = prev; - prev->next = this_frame; /* FIXME: cagney/2002-01-19: This call will go away. Instead of initializing extra info, all frames will use the frame_cache @@ -1157,6 +1249,16 @@ legacy_get_prev_frame (struct frame_info *this_frame) { DEPRECATED_INIT_EXTRA_FRAME_INFO (0, prev); } + + if (prev->type == NORMAL_FRAME) + prev->id.func_addr = get_pc_function_start (prev->id.func_addr); + + if (frame_debug) + { + fprint_frame (gdb_stdlog, prev); + fprintf_unfiltered (gdb_stdlog, "\n"); + } + return prev; } @@ -1219,7 +1321,7 @@ legacy_get_prev_frame (struct frame_info *this_frame) /* Link in the already allocated prev frame. */ this_frame->prev = prev; prev->next = this_frame; - prev->frame = address; + deprecated_update_frame_base_hack (prev, address); /* This change should not be needed, FIXME! We should determine whether any targets *need* DEPRECATED_INIT_FRAME_PC to happen @@ -1295,7 +1397,8 @@ legacy_get_prev_frame (struct frame_info *this_frame) that PC value. */ if (DEPRECATED_INIT_FRAME_PC_FIRST_P ()) - prev->pc = (DEPRECATED_INIT_FRAME_PC_FIRST (fromleaf, prev)); + deprecated_update_frame_pc_hack + (prev, DEPRECATED_INIT_FRAME_PC_FIRST (fromleaf, prev)); if (DEPRECATED_INIT_EXTRA_FRAME_INFO_P ()) DEPRECATED_INIT_EXTRA_FRAME_INFO (fromleaf, prev); @@ -1304,15 +1407,16 @@ legacy_get_prev_frame (struct frame_info *this_frame) FRAME_SAVED_PC may use that queue to figure out its value (see tm-sparc.h). We want the pc saved in the inferior frame. */ if (DEPRECATED_INIT_FRAME_PC_P ()) - prev->pc = DEPRECATED_INIT_FRAME_PC (fromleaf, prev); + deprecated_update_frame_pc_hack + (prev, DEPRECATED_INIT_FRAME_PC (fromleaf, prev)); /* If ->frame and ->pc are unchanged, we are in the process of getting ourselves into an infinite backtrace. Some architectures check this in DEPRECATED_FRAME_CHAIN or thereabouts, but it seems like there is no reason this can't be an architecture-independent check. */ - if (prev->frame == this_frame->frame - && prev->pc == this_frame->pc) + if (this_frame->level > 0 + && frame_id_eq (get_frame_id (prev), get_frame_id (this_frame))) { this_frame->prev = NULL; obstack_free (&frame_cache_obstack, prev); @@ -1323,7 +1427,8 @@ legacy_get_prev_frame (struct frame_info *this_frame) (and probably other architectural information). The PC lets you check things like the debug info at that point (dwarf2cfi?) and use that to decide how the frame should be unwound. */ - prev->unwind = frame_unwind_find_by_pc (current_gdbarch, prev->pc); + prev->unwind = frame_unwind_find_by_pc (current_gdbarch, + get_frame_pc (prev)); /* NOTE: cagney/2002-11-18: The code segments, found in create_new_frame and get_prev_frame(), that initializes the @@ -1335,8 +1440,8 @@ legacy_get_prev_frame (struct frame_info *this_frame) before the INIT function has been called. */ if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES && (DEPRECATED_PC_IN_CALL_DUMMY_P () - ? DEPRECATED_PC_IN_CALL_DUMMY (prev->pc, 0, 0) - : pc_in_dummy_frame (prev->pc))) + ? DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (prev), 0, 0) + : pc_in_dummy_frame (get_frame_pc (prev)))) prev->type = DUMMY_FRAME; else { @@ -1347,8 +1452,9 @@ legacy_get_prev_frame (struct frame_info *this_frame) Unforunatly, its the INIT code that sets the PC (Hmm, catch 22). */ char *name; - find_pc_partial_function (prev->pc, &name, NULL, NULL); - if (PC_IN_SIGTRAMP (prev->pc, name)) + find_pc_partial_function (get_frame_pc (prev), + &name, NULL, NULL); + if (PC_IN_SIGTRAMP (get_frame_pc (prev), name)) prev->type = SIGTRAMP_FRAME; /* FIXME: cagney/2002-11-11: Leave prev->type alone. Some architectures are forcing the frame's type in INIT so we @@ -1358,6 +1464,17 @@ legacy_get_prev_frame (struct frame_info *this_frame) go away. */ } + if (frame_debug) + { + fprintf_unfiltered (gdb_stdlog, "frame %d @0x%s: ID ", + prev->level, paddr (get_frame_pc (prev))); + fprint_frame_id (gdb_stdlog, prev->id); + fprintf_unfiltered (gdb_stdlog, "\n"); + } + + if (prev->type == NORMAL_FRAME) + prev->id.func_addr = get_pc_function_start (prev->id.func_addr); + return prev; } @@ -1551,8 +1668,7 @@ get_prev_frame (struct frame_info *this_frame) because (well ignoring the PPC) a dummy frame can be located using THIS_FRAME's frame ID. */ - prev_frame->pc = frame_pc_unwind (this_frame); - if (prev_frame->pc == 0) + if (frame_pc_unwind (this_frame) == 0) { /* The allocated PREV_FRAME will be reclaimed when the frame obstack is next purged. */ @@ -1561,11 +1677,11 @@ get_prev_frame (struct frame_info *this_frame) "Outermost frame - unwound PC zero\n"); return NULL; } - prev_frame->type = frame_type_from_pc (prev_frame->pc); + prev_frame->type = frame_type_from_pc (frame_pc_unwind (this_frame)); /* Set the unwind functions based on that identified PC. */ prev_frame->unwind = frame_unwind_find_by_pc (current_gdbarch, - prev_frame->pc); + frame_pc_unwind (this_frame)); /* The prev's frame's ID is computed by demand in get_frame_id(). */ @@ -1591,7 +1707,7 @@ get_prev_frame (struct frame_info *this_frame) CORE_ADDR get_frame_pc (struct frame_info *frame) { - return frame->pc; + return frame_pc_unwind (frame->next); } static int @@ -1614,7 +1730,7 @@ pc_notcurrent (struct frame_info *frame) void find_frame_sal (struct frame_info *frame, struct symtab_and_line *sal) { - (*sal) = find_pc_line (frame->pc, pc_notcurrent (frame)); + (*sal) = find_pc_line (get_frame_pc (frame), pc_notcurrent (frame)); } /* Per "frame.h", return the ``address'' of the frame. Code should @@ -1622,13 +1738,7 @@ find_frame_sal (struct frame_info *frame, struct symtab_and_line *sal) CORE_ADDR get_frame_base (struct frame_info *fi) { - if (!fi->id_p) - { - /* HACK: Force the ID code to (indirectly) initialize the - ->frame pointer. */ - get_frame_id (fi); - } - return fi->frame; + return get_frame_id (fi).stack_addr; } /* High-level offsets into the frame. Used by the debug info. */ @@ -1757,8 +1867,6 @@ frame_extra_info_zalloc (struct frame_info *fi, long size) void deprecated_update_frame_pc_hack (struct frame_info *frame, CORE_ADDR pc) { - /* See comment in "frame.h". */ - frame->pc = pc; /* NOTE: cagney/2003-03-11: Some architectures (e.g., Arm) are maintaining a locally allocated frame object. Since such frame's are not in the frame chain, it isn't possible to assume that the @@ -1776,8 +1884,8 @@ deprecated_update_frame_pc_hack (struct frame_info *frame, CORE_ADDR pc) void deprecated_update_frame_base_hack (struct frame_info *frame, CORE_ADDR base) { - /* See comment in "frame.h". */ - frame->frame = base; + frame->id_p = 1; + frame->id.stack_addr = base; } void diff --git a/gdb/frame.h b/gdb/frame.h index 231aaadbd0f..4e96bfe911c 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -43,15 +43,18 @@ struct frame_info; struct frame_id { - /* The frame's address. This should be constant through out the - lifetime of a frame. */ + /* The frame's stack address. This shall be constant through out + the lifetime of a frame. Since the frame's lifetime includes the + prologue, and the value needs to always fall on or within the + bounds of the frame, this stack value is best pointed at the + inner-most address of the previous frame. */ /* NOTE: cagney/2002-11-16: The ia64 has two stacks and hence two frame bases. This will need to be expanded to accomodate that. */ - CORE_ADDR base; - /* The frame's current PC. While the PC within the function may - change, the function that contains the PC does not. Should this - instead be the frame's function? */ - CORE_ADDR pc; + CORE_ADDR stack_addr; + /* The frame's function address. This shall be constant through out + the lifetime of the frame. While the PC within the function may + change, the function that contains the PC does not. */ + CORE_ADDR func_addr; }; /* Methods for constructing and comparing Frame IDs. @@ -65,12 +68,11 @@ struct frame_id /* For convenience. All fields are zero. */ extern const struct frame_id null_frame_id; -/* Construct a frame ID. The second parameter isn't yet well defined. - It might be the containing function, or the resume PC (see comment - above in `struct frame_id')? A func/pc of zero indicates a - wildcard (i.e., do not use func in frame ID comparisons). */ -extern struct frame_id frame_id_build (CORE_ADDR base, - CORE_ADDR func_or_pc); +/* Construct a frame ID. The first parameter is the frame's stack + address, and the second the frame's function (or zero, to indicate + a wild card). */ +extern struct frame_id frame_id_build (CORE_ADDR stack_addr, + CORE_ADDR func_addr); /* Returns non-zero when L is a valid frame (a valid frame has a non-zero .base). */ @@ -309,6 +311,13 @@ extern const char *frame_map_regnum_to_name (int regnum); extern CORE_ADDR frame_pc_unwind (struct frame_info *frame); +/* Unwind/return the frame's function, or 0 if the frame's function is + unknown. This is a wrapper to get_pc_function_start of + frame_pc_unwind. */ +extern CORE_ADDR frame_func_unwind (struct frame_info *frame); +extern CORE_ADDR get_frame_func (struct frame_info *frame); + + /* Discard the specified frame. Restoring the registers to the state of the caller. */ extern void frame_pop (struct frame_info *frame); @@ -344,17 +353,6 @@ struct frame_saved_regs struct frame_info { - /* Nominal address of the frame described. See comments at - get_frame_base() about what this means outside the *FRAME* - macros; in the *FRAME* macros, it can mean whatever makes most - sense for this machine. */ - CORE_ADDR frame; - - /* Address at which execution is occurring in this frame. - For the innermost frame, it's the current pc. - For other frames, it is a pc saved in the next frame. */ - CORE_ADDR pc; - /* 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 @@ -408,6 +406,13 @@ struct frame_info int pc_unwind_cache_p; CORE_ADDR pc_unwind_cache; + /* Cached copy of the previous frame's function. */ + struct + { + int p; + CORE_ADDR cache; + } func; + /* This frame's ID. Note that the frame's ID, base and PC contain redundant information. */ int id_p; diff --git a/gdb/stack.c b/gdb/stack.c index 27fcaf6f6db..2cb9a95dc3d 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -216,7 +216,7 @@ print_frame_info (struct frame_info *fi, int level, int source, int args) if (ui_out_is_mi_like_p (uiout)) { annotate_frame_address (); - ui_out_field_core_addr (uiout, "addr", fi->pc); + ui_out_field_core_addr (uiout, "addr", get_frame_pc (fi)); annotate_frame_address_end (); } -- 2.47.2