X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fframe.c;h=dcdf2994d0dc561eaf23ab54e3011f7e5b87a3c3;hb=d78749b4b8e6a309b5ec3e43de8667cd320b1a4f;hp=b3c9c57c1b8516c29fdb21c4e9abb384603f90e9;hpb=2f72f85088251ea8b84c05cec60e1674d86917b9;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/frame.c b/gdb/frame.c index b3c9c57c1b..dcdf2994d0 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -40,6 +40,8 @@ #include "command.h" #include "gdbcmd.h" #include "observer.h" +#include "objfiles.h" +#include "exceptions.h" static struct frame_info *get_prev_frame_1 (struct frame_info *this_frame); @@ -66,29 +68,6 @@ struct frame_info moment leave this as speculation. */ int level; - /* The frame's type. */ - /* FIXME: cagney/2003-04-02: Should instead be returning - ->unwind->type. Unfortunately, legacy code is still explicitly - setting the type using the method deprecated_set_frame_type. - Eliminate that method and this field can be eliminated. */ - enum frame_type type; - - /* For each register, address of where it was saved on entry to the - frame, or zero if it was not saved on entry to this frame. This - includes special registers such as pc and fp saved in special - ways in the stack frame. The SP_REGNUM is even more special, the - address here is the sp for the previous frame, not the address - where the sp was saved. */ - /* Allocated by frame_saved_regs_zalloc () which is called / - initialized by DEPRECATED_FRAME_INIT_SAVED_REGS(). */ - CORE_ADDR *saved_regs; /*NUM_REGS + NUM_PSEUDO_REGS*/ - - /* Anything extra for this structure that may have been defined in - the machine dependent files. */ - /* Allocated by frame_extra_info_zalloc () which is called / - initialized by DEPRECATED_INIT_EXTRA_FRAME_INFO */ - struct frame_extra_info *extra_info; - /* 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 @@ -133,20 +112,65 @@ struct frame_info /* Flag to control debugging. */ static int frame_debug; +static void +show_frame_debug (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("Frame debugging is %s.\n"), value); +} /* Flag to indicate whether backtraces should stop at main et.al. */ static int backtrace_past_main; -static unsigned int backtrace_limit = UINT_MAX; +static void +show_backtrace_past_main (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("\ +Whether backtraces should continue past \"main\" is %s.\n"), + value); +} +static int backtrace_past_entry; +static void +show_backtrace_past_entry (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("\ +Whether backtraces should continue past the entry point of a program is %s.\n"), + value); +} + +static int backtrace_limit = INT_MAX; +static void +show_backtrace_limit (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("\ +An upper bound on the number of backtrace levels is %s.\n"), + value); +} + + +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); +} void fprint_frame_id (struct ui_file *file, struct frame_id id) { - fprintf_unfiltered (file, "{stack=0x%s,code=0x%s,special=0x%s}", - paddr_nz (id.stack_addr), - paddr_nz (id.code_addr), - paddr_nz (id.special_addr)); + 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, "}"); } static void @@ -154,9 +178,6 @@ fprint_frame_type (struct ui_file *file, enum frame_type type) { switch (type) { - case UNKNOWN_FRAME: - fprintf_unfiltered (file, "UNKNOWN_FRAME"); - return; case NORMAL_FRAME: fprintf_unfiltered (file, "NORMAL_FRAME"); return; @@ -184,7 +205,10 @@ fprint_frame (struct ui_file *file, struct frame_info *fi) fprintf_unfiltered (file, "level=%d", fi->level); fprintf_unfiltered (file, ","); fprintf_unfiltered (file, "type="); - fprint_frame_type (file, fi->type); + if (fi->unwind != NULL) + fprint_frame_type (file, fi->unwind->type); + else + fprintf_unfiltered (file, ""); fprintf_unfiltered (file, ","); fprintf_unfiltered (file, "unwind="); if (fi->unwind != NULL) @@ -224,22 +248,13 @@ get_frame_id (struct frame_info *fi) } if (!fi->this_id.p) { - gdb_assert (!legacy_frame_p (current_gdbarch)); if (frame_debug) fprintf_unfiltered (gdb_stdlog, "{ get_frame_id (fi=%d) ", fi->level); /* Find the unwinder. */ if (fi->unwind == NULL) - { - fi->unwind = frame_unwind_find_by_frame (fi->next, - &fi->prologue_cache); - /* FIXME: cagney/2003-04-02: Rather than storing the frame's - type in the frame, the unwinder's type should be returned - directly. Unfortunately legacy code, called by - legacy_get_prev_frame(), explicitly sets the frame's type - using the method deprecated_set_frame_type(). */ - fi->type = fi->unwind->type; - } + fi->unwind = frame_unwind_find_by_frame (fi->next, + &fi->prologue_cache); /* Find THIS frame's ID. */ fi->unwind->this_id (fi->next, &fi->prologue_cache, &fi->this_id.value); fi->this_id.p = 1; @@ -269,25 +284,42 @@ struct frame_id frame_id_build_special (CORE_ADDR stack_addr, CORE_ADDR code_addr, CORE_ADDR special_addr) { - struct frame_id id; + 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; id.special_addr = special_addr; + id.special_addr_p = 1; return id; } struct frame_id frame_id_build (CORE_ADDR stack_addr, CORE_ADDR code_addr) { - return frame_id_build_special (stack_addr, code_addr, 0); + 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; } int frame_id_p (struct frame_id l) { int p; - /* The .code can be NULL but the .stack cannot. */ - p = (l.stack_addr != 0); + /* The frame is valid iff it has a valid stack address. */ + p = l.stack_addr_p; if (frame_debug) { fprintf_unfiltered (gdb_stdlog, "{ frame_id_p (l="); @@ -301,20 +333,21 @@ int frame_id_eq (struct frame_id l, struct frame_id r) { int eq; - if (l.stack_addr == 0 || r.stack_addr == 0) - /* Like a NaN, if either ID is invalid, the result is false. */ + 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. */ eq = 0; else if (l.stack_addr != r.stack_addr) /* If .stack addresses are different, the frames are different. */ eq = 0; - else if (l.code_addr == 0 || r.code_addr == 0) - /* A zero code addr is a wild card, always succeed. */ + else if (!l.code_addr_p || !r.code_addr_p) + /* An invalid code addr is a wild card, always succeed. */ eq = 1; else if (l.code_addr != r.code_addr) /* If .code addresses are different, the frames are different. */ eq = 0; - else if (l.special_addr == 0 || r.special_addr == 0) - /* A zero special addr is a wild card (or unused), always succeed. */ + else if (!l.special_addr_p || !r.special_addr_p) + /* An invalid special addr is a wild card (or unused), always succeed. */ eq = 1; else if (l.special_addr == r.special_addr) /* Frames are equal. */ @@ -337,7 +370,7 @@ int frame_id_inner (struct frame_id l, struct frame_id r) { int inner; - if (l.stack_addr == 0 || r.stack_addr == 0) + if (!l.stack_addr_p || !r.stack_addr_p) /* Like NaN, any operation involving an invalid ID always fails. */ inner = 0; else @@ -392,7 +425,15 @@ frame_pc_unwind (struct frame_info *this_frame) if (!this_frame->prev_pc.p) { CORE_ADDR pc; - if (gdbarch_unwind_pc_p (current_gdbarch)) + if (this_frame->unwind == NULL) + this_frame->unwind + = frame_unwind_find_by_frame (this_frame->next, + &this_frame->prologue_cache); + if (this_frame->unwind->prev_pc != NULL) + /* A per-frame unwinder, prefer it. */ + pc = this_frame->unwind->prev_pc (this_frame->next, + &this_frame->prologue_cache); + else 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 @@ -412,25 +453,8 @@ frame_pc_unwind (struct frame_info *this_frame) different ways that a PC could be unwound. */ pc = gdbarch_unwind_pc (current_gdbarch, this_frame); } - else if (this_frame->level < 0) - { - /* FIXME: cagney/2003-03-06: Old code and a sentinel - frame. Do like was always done. Fetch the PC's value - directly from the global registers array (via read_pc). - This assumes that this frame belongs to the current - global register cache. The assumption is dangerous. */ - pc = read_pc (); - } - else if (DEPRECATED_FRAME_SAVED_PC_P ()) - { - /* FIXME: cagney/2003-03-06: Old code, but not a sentinel - frame. Do like was always done. Note that this method, - unlike unwind_pc(), tries to handle all the different - frame cases directly. It fails. */ - pc = DEPRECATED_FRAME_SAVED_PC (this_frame); - } else - internal_error (__FILE__, __LINE__, "No gdbarch_unwind_pc method"); + internal_error (__FILE__, __LINE__, _("No unwind_pc method")); this_frame->prev_pc.value = pc; this_frame->prev_pc.p = 1; if (frame_debug) @@ -467,48 +491,46 @@ get_frame_func (struct frame_info *fi) } static int -do_frame_unwind_register (void *src, int regnum, void *buf) +do_frame_register_read (void *src, int regnum, gdb_byte *buf) { - frame_unwind_register (src, regnum, buf); + frame_register_read (src, regnum, buf); return 1; } +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; +} + void frame_pop (struct frame_info *this_frame) { - struct regcache *scratch_regcache; - struct cleanup *cleanups; + /* 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. */ + struct regcache *scratch + = frame_save_as_regcache (get_prev_frame_1 (this_frame)); + 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); - if (DEPRECATED_POP_FRAME_P ()) - { - /* A legacy architecture that has implemented a custom pop - function. All new architectures should instead be using the - generic code below. */ - DEPRECATED_POP_FRAME; - } - else - { - /* 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. */ - struct regcache *scratch = regcache_xmalloc (current_gdbarch); - struct cleanup *cleanups = make_cleanup_regcache_xfree (scratch); - regcache_save (scratch, do_frame_unwind_register, this_frame); - /* 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); - } /* We've made right mess of GDB's local state, just discard everything. */ flush_cached_frames (); @@ -517,7 +539,7 @@ frame_pop (struct frame_info *this_frame) void frame_register_unwind (struct frame_info *frame, int regnum, int *optimizedp, enum lval_type *lvalp, - CORE_ADDR *addrp, int *realnump, void *bufferp) + CORE_ADDR *addrp, int *realnump, gdb_byte *bufferp) { struct frame_unwind_cache *cache; @@ -545,16 +567,8 @@ frame_register_unwind (struct frame_info *frame, int regnum, /* Find the unwinder. */ if (frame->unwind == NULL) - { - frame->unwind = frame_unwind_find_by_frame (frame->next, - &frame->prologue_cache); - /* FIXME: cagney/2003-04-02: Rather than storing the frame's - type in the frame, the unwinder's type should be returned - directly. Unfortunately, legacy code, called by - legacy_get_prev_frame(), explicitly set the frames type using - the method deprecated_set_frame_type(). */ - frame->type = frame->unwind->type; - } + frame->unwind = frame_unwind_find_by_frame (frame->next, + &frame->prologue_cache); /* Ask this frame to unwind its register. See comment in "frame-unwind.h" for why NEXT frame and this unwind cache are @@ -587,7 +601,7 @@ frame_register_unwind (struct frame_info *frame, int regnum, void frame_register (struct frame_info *frame, int regnum, int *optimizedp, enum lval_type *lvalp, - CORE_ADDR *addrp, int *realnump, void *bufferp) + CORE_ADDR *addrp, int *realnump, gdb_byte *bufferp) { /* Require all but BUFFERP to be valid. A NULL BUFFERP indicates that the value proper does not need to be fetched. */ @@ -597,33 +611,6 @@ frame_register (struct frame_info *frame, int regnum, gdb_assert (realnump != NULL); /* gdb_assert (bufferp != NULL); */ - /* Ulgh! Old code that, for lval_register, sets ADDRP to the offset - of the register in the register cache. It should instead return - the REGNUM corresponding to that register. Translate the . */ - if (DEPRECATED_GET_SAVED_REGISTER_P ()) - { - DEPRECATED_GET_SAVED_REGISTER (bufferp, optimizedp, addrp, frame, - regnum, lvalp); - /* Compute the REALNUM if the caller wants it. */ - if (*lvalp == lval_register) - { - int regnum; - for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++) - { - if (*addrp == register_offset_hack (current_gdbarch, regnum)) - { - *realnump = regnum; - return; - } - } - internal_error (__FILE__, __LINE__, - "Failed to compute the register number corresponding" - " to 0x%s", paddr_d (*addrp)); - } - *realnump = -1; - return; - } - /* Obtain the register value by unwinding the register from the next (more inner frame). */ gdb_assert (frame != NULL && frame->next != NULL); @@ -632,7 +619,7 @@ frame_register (struct frame_info *frame, int regnum, } void -frame_unwind_register (struct frame_info *frame, int regnum, void *buf) +frame_unwind_register (struct frame_info *frame, int regnum, gdb_byte *buf) { int optimized; CORE_ADDR addr; @@ -644,7 +631,7 @@ frame_unwind_register (struct frame_info *frame, int regnum, void *buf) void get_frame_register (struct frame_info *frame, - int regnum, void *buf) + int regnum, gdb_byte *buf) { frame_unwind_register (frame->next, regnum, buf); } @@ -652,9 +639,10 @@ get_frame_register (struct frame_info *frame, LONGEST frame_unwind_register_signed (struct frame_info *frame, int regnum) { - char buf[MAX_REGISTER_SIZE]; + gdb_byte buf[MAX_REGISTER_SIZE]; frame_unwind_register (frame, regnum, buf); - return extract_signed_integer (buf, DEPRECATED_REGISTER_VIRTUAL_SIZE (regnum)); + return extract_signed_integer (buf, register_size (get_frame_arch (frame), + regnum)); } LONGEST @@ -666,9 +654,10 @@ get_frame_register_signed (struct frame_info *frame, int regnum) ULONGEST frame_unwind_register_unsigned (struct frame_info *frame, int regnum) { - char buf[MAX_REGISTER_SIZE]; + gdb_byte buf[MAX_REGISTER_SIZE]; frame_unwind_register (frame, regnum, buf); - return extract_unsigned_integer (buf, DEPRECATED_REGISTER_VIRTUAL_SIZE (regnum)); + return extract_unsigned_integer (buf, register_size (get_frame_arch (frame), + regnum)); } ULONGEST @@ -681,13 +670,16 @@ void frame_unwind_unsigned_register (struct frame_info *frame, int regnum, ULONGEST *val) { - char buf[MAX_REGISTER_SIZE]; + gdb_byte buf[MAX_REGISTER_SIZE]; frame_unwind_register (frame, regnum, buf); - (*val) = extract_unsigned_integer (buf, DEPRECATED_REGISTER_VIRTUAL_SIZE (regnum)); + (*val) = extract_unsigned_integer (buf, + register_size (get_frame_arch (frame), + regnum)); } void -put_frame_register (struct frame_info *frame, int regnum, const void *buf) +put_frame_register (struct frame_info *frame, int regnum, + const gdb_byte *buf) { struct gdbarch *gdbarch = get_frame_arch (frame); int realnum; @@ -696,14 +688,14 @@ put_frame_register (struct frame_info *frame, int regnum, const void *buf) 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."); + 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]; + gdb_byte tmp[MAX_REGISTER_SIZE]; memcpy (tmp, buf, register_size (gdbarch, regnum)); write_memory (addr, tmp, register_size (gdbarch, regnum)); break; @@ -712,20 +704,20 @@ put_frame_register (struct frame_info *frame, int regnum, const void *buf) regcache_cooked_write (current_regcache, realnum, buf); break; default: - error ("Attempt to assign to an unmodifiable value."); + error (_("Attempt to assign to an unmodifiable value.")); } } /* frame_register_read () Find and return the value of REGNUM for the specified stack frame. - The number of bytes copied is DEPRECATED_REGISTER_RAW_SIZE - (REGNUM). + The number of bytes copied is REGISTER_SIZE (REGNUM). Returns 0 if the register value could not be found. */ int -frame_register_read (struct frame_info *frame, int regnum, void *myaddr) +frame_register_read (struct frame_info *frame, int regnum, + gdb_byte *myaddr) { int optimized; enum lval_type lval; @@ -769,7 +761,6 @@ static struct frame_info * create_sentinel_frame (struct regcache *regcache) { struct frame_info *frame = FRAME_OBSTACK_ZALLOC (struct frame_info); - frame->type = NORMAL_FRAME; frame->level = -1; /* Explicitly initialize the sentinel frame's cache. Provide it with the underlying regcache. In the future additional @@ -811,20 +802,6 @@ frame_obstack_zalloc (unsigned long size) return data; } -CORE_ADDR * -frame_saved_regs_zalloc (struct frame_info *fi) -{ - fi->saved_regs = (CORE_ADDR *) - frame_obstack_zalloc (SIZEOF_FRAME_SAVED_REGS); - return fi->saved_regs; -} - -CORE_ADDR * -deprecated_get_frame_saved_regs (struct frame_info *fi) -{ - return fi->saved_regs; -} - /* 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 @@ -851,17 +828,17 @@ get_current_frame (void) explicitly checks that ``print $pc'' with no registers prints "No registers". */ if (!target_has_registers) - error ("No registers."); + error (_("No registers.")); if (!target_has_stack) - error ("No stack."); + error (_("No stack.")); if (!target_has_memory) - error ("No memory."); + error (_("No memory.")); if (current_frame == NULL) { 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) + RETURN_MASK_ERROR) != 0) { /* Oops! Fake a current frame? Is this useful? It has a PC of zero, for instance. */ @@ -881,13 +858,19 @@ struct frame_info *deprecated_selected_frame; thrown. */ struct frame_info * -get_selected_frame (void) +get_selected_frame (const char *message) { 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 ()); + { + if (message != NULL && (!target_has_registers + || !target_has_stack + || !target_has_memory)) + error (("%s"), message); + /* 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; @@ -902,7 +885,7 @@ deprecated_safe_get_selected_frame (void) { if (!target_has_registers || !target_has_stack || !target_has_memory) return NULL; - return get_selected_frame (); + return get_selected_frame (NULL); } /* Select frame FI (or NULL - to invalidate the current frame). */ @@ -947,240 +930,7 @@ select_frame (struct frame_info *fi) } } } - -/* Return the register saved in the simplistic ``saved_regs'' cache. - If the value isn't here AND a value is needed, try the next inner - most frame. */ - -static void -legacy_saved_regs_prev_register (struct frame_info *next_frame, - void **this_prologue_cache, - int regnum, int *optimizedp, - enum lval_type *lvalp, CORE_ADDR *addrp, - int *realnump, void *bufferp) -{ - /* HACK: New code is passed the next frame and this cache. - Unfortunately, old code expects this frame. Since this is a - backward compatibility hack, cheat by walking one level along the - prologue chain to the frame the old code expects. - - Do not try this at home. Professional driver, closed course. */ - struct frame_info *frame = next_frame->prev; - gdb_assert (frame != NULL); - - if (deprecated_get_frame_saved_regs (frame) == NULL) - { - /* If nothing has initialized the saved regs, do it now. */ - gdb_assert (DEPRECATED_FRAME_INIT_SAVED_REGS_P ()); - DEPRECATED_FRAME_INIT_SAVED_REGS (frame); - gdb_assert (deprecated_get_frame_saved_regs (frame) != NULL); - } - - if (deprecated_get_frame_saved_regs (frame) != NULL - && deprecated_get_frame_saved_regs (frame)[regnum] != 0) - { - if (regnum == SP_REGNUM) - { - /* SP register treated specially. */ - *optimizedp = 0; - *lvalp = not_lval; - *addrp = 0; - *realnump = -1; - if (bufferp != NULL) - /* NOTE: cagney/2003-05-09: In-lined store_address() with - it's body - store_unsigned_integer(). */ - store_unsigned_integer (bufferp, DEPRECATED_REGISTER_RAW_SIZE (regnum), - deprecated_get_frame_saved_regs (frame)[regnum]); - } - else - { - /* Any other register is saved in memory, fetch it but cache - a local copy of its value. */ - *optimizedp = 0; - *lvalp = lval_memory; - *addrp = deprecated_get_frame_saved_regs (frame)[regnum]; - *realnump = -1; - if (bufferp != NULL) - { -#if 1 - /* Save each register value, as it is read in, in a - frame based cache. */ - void **regs = (*this_prologue_cache); - if (regs == NULL) - { - int sizeof_cache = ((NUM_REGS + NUM_PSEUDO_REGS) - * sizeof (void *)); - regs = frame_obstack_zalloc (sizeof_cache); - (*this_prologue_cache) = regs; - } - if (regs[regnum] == NULL) - { - regs[regnum] - = frame_obstack_zalloc (DEPRECATED_REGISTER_RAW_SIZE (regnum)); - read_memory (deprecated_get_frame_saved_regs (frame)[regnum], regs[regnum], - DEPRECATED_REGISTER_RAW_SIZE (regnum)); - } - memcpy (bufferp, regs[regnum], DEPRECATED_REGISTER_RAW_SIZE (regnum)); -#else - /* Read the value in from memory. */ - read_memory (deprecated_get_frame_saved_regs (frame)[regnum], bufferp, - DEPRECATED_REGISTER_RAW_SIZE (regnum)); -#endif - } - } - return; - } - - /* No luck. Assume this and the next frame have the same register - value. Pass the unwind request down the frame chain to the next - frame. Hopefully that frame will find the register's location. */ - frame_register_unwind (next_frame, regnum, optimizedp, lvalp, addrp, - realnump, bufferp); -} - -static void -legacy_saved_regs_this_id (struct frame_info *next_frame, - void **this_prologue_cache, - struct frame_id *id) -{ - /* A developer is trying to bring up a new architecture, help them - by providing a default unwinder that refuses to unwind anything - (the ID is always NULL). In the case of legacy code, - legacy_get_prev_frame() will have previously set ->this_id.p, so - this code won't be called. */ - (*id) = null_frame_id; -} -const struct frame_unwind legacy_saved_regs_unwinder = { - /* Not really. It gets overridden by legacy_get_prev_frame(). */ - UNKNOWN_FRAME, - legacy_saved_regs_this_id, - legacy_saved_regs_prev_register -}; -const struct frame_unwind *legacy_saved_regs_unwind = &legacy_saved_regs_unwinder; - - -/* Function: deprecated_generic_get_saved_register - Find register number REGNUM relative to FRAME and put its (raw, - target format) contents in *RAW_BUFFER. - - Set *OPTIMIZED if the variable was optimized out (and thus can't be - fetched). Note that this is never set to anything other than zero - in this implementation. - - Set *LVAL to lval_memory, lval_register, or not_lval, depending on - whether the value was fetched from memory, from a register, or in a - strange and non-modifiable way (e.g. a frame pointer which was - calculated rather than fetched). We will use not_lval for values - fetched from generic dummy frames. - - Set *ADDRP to the address, either in memory or as a - DEPRECATED_REGISTER_BYTE offset into the registers array. If the - value is stored in a dummy frame, set *ADDRP to zero. - - The argument RAW_BUFFER must point to aligned memory. */ - -void -deprecated_generic_get_saved_register (char *raw_buffer, int *optimized, - CORE_ADDR *addrp, - struct frame_info *frame, int regnum, - enum lval_type *lval) -{ - if (!target_has_registers) - error ("No registers."); - - /* Normal systems don't optimize out things with register numbers. */ - if (optimized != NULL) - *optimized = 0; - - if (addrp) /* default assumption: not found in memory */ - *addrp = 0; - - /* Note: since the current frame's registers could only have been - saved by frames INTERIOR TO the current frame, we skip examining - the current frame itself: otherwise, we would be getting the - previous frame's registers which were saved by the current frame. */ - - if (frame != NULL) - { - for (frame = get_next_frame (frame); - frame_relative_level (frame) >= 0; - frame = get_next_frame (frame)) - { - if (get_frame_type (frame) == DUMMY_FRAME) - { - if (lval) /* found it in a CALL_DUMMY frame */ - *lval = not_lval; - if (raw_buffer) - /* FIXME: cagney/2002-06-26: This should be via the - gdbarch_register_read() method so that it, on the - fly, constructs either a raw or pseudo register - from the raw register cache. */ - regcache_raw_read - (deprecated_find_dummy_frame_regcache (get_frame_pc (frame), - get_frame_base (frame)), - regnum, raw_buffer); - return; - } - - DEPRECATED_FRAME_INIT_SAVED_REGS (frame); - if (deprecated_get_frame_saved_regs (frame) != NULL - && deprecated_get_frame_saved_regs (frame)[regnum] != 0) - { - if (lval) /* found it saved on the stack */ - *lval = lval_memory; - if (regnum == SP_REGNUM) - { - if (raw_buffer) /* SP register treated specially */ - /* NOTE: cagney/2003-05-09: In-line store_address() - with it's body - store_unsigned_integer(). */ - store_unsigned_integer (raw_buffer, - DEPRECATED_REGISTER_RAW_SIZE (regnum), - deprecated_get_frame_saved_regs (frame)[regnum]); - } - else - { - if (addrp) /* any other register */ - *addrp = deprecated_get_frame_saved_regs (frame)[regnum]; - if (raw_buffer) - read_memory (deprecated_get_frame_saved_regs (frame)[regnum], raw_buffer, - DEPRECATED_REGISTER_RAW_SIZE (regnum)); - } - return; - } - } - } - - /* If we get thru the loop to this point, it means the register was - not saved in any frame. Return the actual live-register value. */ - - if (lval) /* found it in a live register */ - *lval = lval_register; - if (addrp) - *addrp = DEPRECATED_REGISTER_BYTE (regnum); - if (raw_buffer) - deprecated_read_register_gen (regnum, raw_buffer); -} - -/* Determine the frame's type based on its PC. */ - -static enum frame_type -frame_type_from_pc (CORE_ADDR pc) -{ - if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES - && deprecated_pc_in_call_dummy (pc, 0, 0)) - return DUMMY_FRAME; - else - { - char *name; - find_pc_partial_function (pc, &name, NULL, NULL); - if (DEPRECATED_PC_IN_SIGTRAMP (pc, name)) - return SIGTRAMP_FRAME; - else - return NORMAL_FRAME; - } -} - /* Create an arbitrary (i.e. address specified by user) or innermost frame. Always returns a non-NULL value. */ @@ -1203,18 +953,11 @@ create_new_frame (CORE_ADDR addr, CORE_ADDR pc) /* Select/initialize both the unwind function and the frame's type based on the PC. */ fi->unwind = frame_unwind_find_by_frame (fi->next, &fi->prologue_cache); - if (fi->unwind->type != UNKNOWN_FRAME) - fi->type = fi->unwind->type; - else - fi->type = frame_type_from_pc (pc); fi->this_id.p = 1; deprecated_update_frame_base_hack (fi, addr); deprecated_update_frame_pc_hack (fi, pc); - if (DEPRECATED_INIT_EXTRA_FRAME_INFO_P ()) - DEPRECATED_INIT_EXTRA_FRAME_INFO (0, fi); - if (frame_debug) { fprintf_unfiltered (gdb_stdlog, "-> "); @@ -1276,461 +1019,6 @@ reinit_frame_cache (void) } } -/* Create the previous frame using the deprecated methods - INIT_EXTRA_INFO, and INIT_FRAME_PC. */ - -static struct frame_info * -legacy_get_prev_frame (struct frame_info *this_frame) -{ - CORE_ADDR address = 0; - struct frame_info *prev; - int fromleaf; - - /* Don't frame_debug print legacy_get_prev_frame() here, just - confuses the output. */ - - /* Allocate the new frame. - - 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, in get_prev_frame() will stop repeated - memory allocation calls. */ - prev = FRAME_OBSTACK_ZALLOC (struct frame_info); - prev->level = this_frame->level + 1; - - /* Do not completely wire it in to the frame chain. Some (bad) code - in INIT_FRAME_EXTRA_INFO tries to look along frame->prev to pull - some fancy tricks (of course such code is, by definition, - recursive). - - On the other hand, methods, such as get_frame_pc() and - get_frame_base() rely on being able to walk along the frame - chain. Make certain that at least they work by providing that - link. Of course things manipulating prev can't go back. */ - 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 - DEPRECATED_INIT_EXTRA_FRAME_INFO, DEPRECATED_INIT_FRAME_PC, and - DEPRECATED_FRAME_INIT_SAVED_REGS methods are full of work-arounds - that handle the frame not being correctly set from the start. - Unfortunately those same work-arounds rely on the type defaulting - to NORMAL_FRAME. Ulgh! The new frame code does not have this - problem. */ - prev->type = UNKNOWN_FRAME; - - /* A legacy frame's ID is always computed here. Mark it as valid. */ - prev->this_id.p = 1; - - /* Handle sentinel frame unwind as a special case. */ - if (this_frame->level < 0) - { - /* Try to unwind the PC. If that doesn't work, assume we've reached - the oldest frame and simply return. Is there a better sentinal - value? The unwound PC value is then used to initialize the new - previous frame's type. - - Note that the pc-unwind is intentionally performed before the - frame chain. This is ok since, for old targets, both - frame_pc_unwind() (nee, DEPRECATED_FRAME_SAVED_PC) and - DEPRECATED_FRAME_CHAIN()) assume THIS_FRAME's data structures - have already been initialized (using - DEPRECATED_INIT_EXTRA_FRAME_INFO) and hence the call order - doesn't matter. - - By unwinding the PC first, it becomes possible to, in the case of - a dummy frame, avoid also unwinding the frame ID. This is - because (well ignoring the PPC) a dummy frame can be located - using THIS_FRAME's frame ID. */ - - deprecated_update_frame_pc_hack (prev, frame_pc_unwind (this_frame)); - if (get_frame_pc (prev) == 0) - { - /* The allocated PREV_FRAME will be reclaimed when the frame - obstack is next purged. */ - if (frame_debug) - { - fprintf_unfiltered (gdb_stdlog, "-> "); - fprint_frame (gdb_stdlog, NULL); - fprintf_unfiltered (gdb_stdlog, - " // unwound legacy PC zero }\n"); - } - return NULL; - } - - /* Set the unwind functions based on that identified PC. Ditto - for the "type" but strongly prefer the unwinder's frame type. */ - prev->unwind = frame_unwind_find_by_frame (prev->next, - &prev->prologue_cache); - if (prev->unwind->type == UNKNOWN_FRAME) - prev->type = frame_type_from_pc (get_frame_pc (prev)); - else - prev->type = prev->unwind->type; - - /* Find the prev's frame's ID. */ - if (prev->type == DUMMY_FRAME - && gdbarch_unwind_dummy_id_p (current_gdbarch)) - { - /* When unwinding a normal frame, the stack structure is - determined by analyzing the frame's function's code (be - it using brute force prologue analysis, or the dwarf2 - CFI). In the case of a dummy frame, that simply isn't - possible. The The PC is either the program entry point, - or some random address on the stack. Trying to use that - PC to apply standard frame ID unwind techniques is just - asking for trouble. */ - /* Use an architecture specific method to extract the prev's - dummy ID from the next frame. Note that this method uses - frame_register_unwind to obtain the register values - needed to determine the dummy frame's ID. */ - prev->this_id.value = gdbarch_unwind_dummy_id (current_gdbarch, - this_frame); - } - else - { - /* We're 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. Once all architectures supply the - unwind_dummy_id method, this code can go away. */ - prev->this_id.value = frame_id_build (deprecated_read_fp (), - read_pc ()); - } - - /* Check that the unwound ID is valid. */ - if (!frame_id_p (prev->this_id.value)) - { - if (frame_debug) - { - fprintf_unfiltered (gdb_stdlog, "-> "); - fprint_frame (gdb_stdlog, NULL); - fprintf_unfiltered (gdb_stdlog, - " // unwound legacy ID invalid }\n"); - } - return NULL; - } - - /* Check that the new frame isn't inner to (younger, below, - next) the old frame. If that happens the frame unwind is - going backwards. */ - /* FIXME: cagney/2003-02-25: Ignore the sentinel frame since - that doesn't have a valid frame ID. Should instead set the - sentinel frame's frame ID to a `sentinel'. Leave it until - after the switch to storing the frame ID, instead of the - frame base, in the frame object. */ - - /* Link it in. */ - this_frame->prev = prev; - - /* FIXME: cagney/2002-01-19: This call will go away. Instead of - initializing extra info, all frames will use the frame_cache - (passed to the unwind functions) to store additional frame - info. Unfortunately legacy targets can't use - legacy_get_prev_frame() to unwind the sentinel frame and, - consequently, are forced to take this code path and rely on - the below call to DEPRECATED_INIT_EXTRA_FRAME_INFO to - initialize the inner-most frame. */ - if (DEPRECATED_INIT_EXTRA_FRAME_INFO_P ()) - { - DEPRECATED_INIT_EXTRA_FRAME_INFO (0, prev); - } - - if (prev->type == NORMAL_FRAME) - prev->this_id.value.code_addr - = get_pc_function_start (prev->this_id.value.code_addr); - - if (frame_debug) - { - fprintf_unfiltered (gdb_stdlog, "-> "); - fprint_frame (gdb_stdlog, prev); - fprintf_unfiltered (gdb_stdlog, " } // legacy innermost frame\n"); - } - return prev; - } - - /* This code only works on normal frames. A sentinel frame, where - the level is -1, should never reach this code. */ - gdb_assert (this_frame->level >= 0); - - /* On some machines it is possible to call a function without - setting up a stack frame for it. On these machines, we - define this macro to take two args; a frameinfo pointer - identifying a frame and a variable to set or clear if it is - or isn't leafless. */ - - /* Still don't want to worry about this except on the innermost - frame. This macro will set FROMLEAF if THIS_FRAME is a frameless - function invocation. */ - if (this_frame->level == 0) - /* FIXME: 2002-11-09: Frameless functions can occur anywhere in - the frame chain, not just the inner most frame! The generic, - per-architecture, frame code should handle this and the below - should simply be removed. */ - fromleaf = (DEPRECATED_FRAMELESS_FUNCTION_INVOCATION_P () - && DEPRECATED_FRAMELESS_FUNCTION_INVOCATION (this_frame)); - else - fromleaf = 0; - - if (fromleaf) - /* A frameless inner-most frame. The `FP' (which isn't an - architecture frame-pointer register!) of the caller is the same - as the callee. */ - /* FIXME: 2002-11-09: There isn't any reason to special case this - edge condition. Instead the per-architecture code should handle - it locally. */ - /* FIXME: cagney/2003-06-16: This returns the inner most stack - address for the previous frame, that, however, is wrong. It - should be the inner most stack address for the previous to - previous frame. This is because it is the previous to previous - frame's innermost stack address that is constant through out - the lifetime of the previous frame (trust me :-). */ - address = get_frame_base (this_frame); - else - { - /* Two macros defined in tm.h specify the machine-dependent - actions to be performed here. - - First, get the frame's chain-pointer. - - If that is zero, the frame is the outermost frame or a leaf - called by the outermost frame. This means that if start - calls main without a frame, we'll return 0 (which is fine - anyway). - - Nope; there's a problem. This also returns when the current - routine is a leaf of main. This is unacceptable. We move - this to after the ffi test; I'd rather have backtraces from - start go curfluy than have an abort called from main not show - main. */ - if (DEPRECATED_FRAME_CHAIN_P ()) - address = DEPRECATED_FRAME_CHAIN (this_frame); - else - { - /* Someone is part way through coverting an old architecture - to the new frame code. Implement FRAME_CHAIN the way the - new frame will. */ - /* Find PREV frame's unwinder. */ - prev->unwind = frame_unwind_find_by_frame (this_frame, - &prev->prologue_cache); - /* FIXME: cagney/2003-04-02: Rather than storing the frame's - type in the frame, the unwinder's type should be returned - directly. Unfortunately, legacy code, called by - legacy_get_prev_frame(), explicitly set the frames type - using the method deprecated_set_frame_type(). */ - prev->type = prev->unwind->type; - /* Find PREV frame's ID. */ - prev->unwind->this_id (this_frame, - &prev->prologue_cache, - &prev->this_id.value); - prev->this_id.p = 1; - address = prev->this_id.value.stack_addr; - } - - if (!legacy_frame_chain_valid (address, this_frame)) - { - if (frame_debug) - { - fprintf_unfiltered (gdb_stdlog, "-> "); - fprint_frame (gdb_stdlog, NULL); - fprintf_unfiltered (gdb_stdlog, - " // legacy frame chain invalid }\n"); - } - return NULL; - } - } - if (address == 0) - { - if (frame_debug) - { - fprintf_unfiltered (gdb_stdlog, "-> "); - fprint_frame (gdb_stdlog, NULL); - fprintf_unfiltered (gdb_stdlog, - " // legacy frame chain NULL }\n"); - } - return NULL; - } - - /* Link in the already allocated prev frame. */ - this_frame->prev = prev; - 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 - after DEPRECATED_INIT_EXTRA_FRAME_INFO and come up with a simple - way to express what goes on here. - - DEPRECATED_INIT_EXTRA_FRAME_INFO is called from two places: - create_new_frame (where the PC is already set up) and here (where - it isn't). DEPRECATED_INIT_FRAME_PC is only called from here, - always after DEPRECATED_INIT_EXTRA_FRAME_INFO. - - The catch is the MIPS, where DEPRECATED_INIT_EXTRA_FRAME_INFO - requires the PC value (which hasn't been set yet). Some other - machines appear to require DEPRECATED_INIT_EXTRA_FRAME_INFO - before they can do DEPRECATED_INIT_FRAME_PC. Phoo. - - Assuming that some machines need DEPRECATED_INIT_FRAME_PC after - DEPRECATED_INIT_EXTRA_FRAME_INFO, one possible scheme: - - SETUP_INNERMOST_FRAME(): Default version is just create_new_frame - (deprecated_read_fp ()), read_pc ()). Machines with extra frame - info would do that (or the local equivalent) and then set the - extra fields. - - SETUP_ARBITRARY_FRAME(argc, argv): Only change here is that - create_new_frame would no longer init extra frame info; - SETUP_ARBITRARY_FRAME would have to do that. - - INIT_PREV_FRAME(fromleaf, prev) Replace - DEPRECATED_INIT_EXTRA_FRAME_INFO and DEPRECATED_INIT_FRAME_PC. - This should also return a flag saying whether to keep the new - frame, or whether to discard it, because on some machines (e.g. - mips) it is really awkward to have DEPRECATED_FRAME_CHAIN_VALID - called BEFORE DEPRECATED_INIT_EXTRA_FRAME_INFO (there is no good - way to get information deduced in DEPRECATED_FRAME_CHAIN_VALID - into the extra fields of the new frame). std_frame_pc(fromleaf, - prev) - - This is the default setting for INIT_PREV_FRAME. It just does - what the default DEPRECATED_INIT_FRAME_PC does. Some machines - will call it from INIT_PREV_FRAME (either at the beginning, the - end, or in the middle). Some machines won't use it. - - kingdon@cygnus.com, 13Apr93, 31Jan94, 14Dec94. */ - - /* NOTE: cagney/2002-11-09: Just ignore the above! There is no - reason for things to be this complicated. - - The trick is to assume that there is always a frame. Instead of - special casing the inner-most frame, create a fake frame - (containing the hardware registers) that is inner to the - user-visible inner-most frame (...) and then unwind from that. - That way architecture code can use the standard - frame_XX_unwind() functions and not differentiate between the - inner most and any other case. - - Since there is always a frame to unwind from, there is always - somewhere (THIS_FRAME) to store all the info needed to construct - a new (previous) frame without having to first create it. This - means that the convolution below - needing to carefully order a - frame's initialization - isn't needed. - - The irony here though, is that DEPRECATED_FRAME_CHAIN(), at least - for a more up-to-date architecture, always calls - FRAME_SAVED_PC(), and FRAME_SAVED_PC() computes the PC but - without first needing the frame! Instead of the convolution - below, we could have simply called FRAME_SAVED_PC() and been done - with it! Note that FRAME_SAVED_PC() is being superseded by - frame_pc_unwind() and that function does have somewhere to cache - that PC value. */ - - if (DEPRECATED_INIT_EXTRA_FRAME_INFO_P ()) - DEPRECATED_INIT_EXTRA_FRAME_INFO (fromleaf, prev); - - /* This entry is in the frame queue now, which is good since - 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 ()) - 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 (get_frame_base (prev) == get_frame_base (this_frame) - && get_frame_pc (prev) == get_frame_pc (this_frame)) - { - this_frame->prev = NULL; - obstack_free (&frame_cache_obstack, prev); - if (frame_debug) - { - fprintf_unfiltered (gdb_stdlog, "-> "); - fprint_frame (gdb_stdlog, NULL); - fprintf_unfiltered (gdb_stdlog, - " // legacy this.id == prev.id }\n"); - } - return NULL; - } - - /* Initialize the code used to unwind the frame PREV based on the PC - (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. - - If there isn't a FRAME_CHAIN, the code above will have already - done this. */ - if (prev->unwind == NULL) - prev->unwind = frame_unwind_find_by_frame (prev->next, - &prev->prologue_cache); - - /* If the unwinder provides a frame type, use it. Otherwise - continue on to that heuristic mess. */ - if (prev->unwind->type != UNKNOWN_FRAME) - { - prev->type = prev->unwind->type; - if (prev->type == NORMAL_FRAME) - /* FIXME: cagney/2003-06-16: would get_frame_pc() be better? */ - prev->this_id.value.code_addr - = get_pc_function_start (prev->this_id.value.code_addr); - if (frame_debug) - { - fprintf_unfiltered (gdb_stdlog, "-> "); - fprint_frame (gdb_stdlog, prev); - fprintf_unfiltered (gdb_stdlog, " } // legacy with unwound type\n"); - } - return prev; - } - - /* NOTE: cagney/2002-11-18: The code segments, found in - create_new_frame() and get_prev_frame(), that initialize the - frame's type is subtly different. The latter only updates ->type - when it encounters a SIGTRAMP_FRAME or DUMMY_FRAME. This stops - get_prev_frame() overriding the frame's type when the INIT code - has previously set it. This is really somewhat bogus. The - initialization, as seen in create_new_frame(), should occur - before the INIT function has been called. */ - if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES - && deprecated_pc_in_call_dummy (get_frame_pc (prev), 0, 0)) - prev->type = DUMMY_FRAME; - else - { - /* FIXME: cagney/2002-11-10: This should be moved to before the - INIT code above so that the INIT code knows what the frame's - type is (in fact, for a [generic] dummy-frame, the type can - be set and then the entire initialization can be skipped). - Unfortunately, it's the INIT code that sets the PC (Hmm, catch - 22). */ - char *name; - find_pc_partial_function (get_frame_pc (prev), &name, NULL, NULL); - if (DEPRECATED_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 - don't want to override it here. Remember, NORMAL_FRAME == 0, - so it all works (just :-/). Once this initialization is - moved to the start of this function, all this nastness will - go away. */ - } - - if (prev->type == NORMAL_FRAME) - prev->this_id.value.code_addr - = get_pc_function_start (prev->this_id.value.code_addr); - - if (frame_debug) - { - fprintf_unfiltered (gdb_stdlog, "-> "); - fprint_frame (gdb_stdlog, prev); - fprintf_unfiltered (gdb_stdlog, " } // legacy with confused type\n"); - } - - return prev; -} - /* Return a "struct frame_info" corresponding to the frame that called THIS_FRAME. Returns NULL if there is no such frame. @@ -1741,6 +1029,7 @@ static struct frame_info * get_prev_frame_1 (struct frame_info *this_frame) { struct frame_info *prev_frame; + struct frame_id this_id; gdb_assert (this_frame != NULL); @@ -1767,18 +1056,11 @@ get_prev_frame_1 (struct frame_info *this_frame) } this_frame->prev_p = 1; - /* If any of the old frame initialization methods are around, use - the legacy get_prev_frame() method. */ - if (legacy_frame_p (current_gdbarch)) - { - prev_frame = legacy_get_prev_frame (this_frame); - return prev_frame; - } - /* 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. */ - if (this_frame->level >= 0 && !frame_id_p (get_frame_id (this_frame))) + this_id = get_frame_id (this_frame); + if (this_frame->level >= 0 && !frame_id_p (this_id)) { if (frame_debug) { @@ -1794,18 +1076,16 @@ get_prev_frame_1 (struct frame_info *this_frame) 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 - && this_frame->next->type != SIGTRAMP_FRAME - && frame_id_inner (get_frame_id (this_frame), - get_frame_id (this_frame->next))) - error ("Previous frame inner to this frame (corrupt stack?)"); + && this_frame->next->unwind->type != SIGTRAMP_FRAME + && frame_id_inner (this_id, get_frame_id (this_frame->next))) + 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 - && frame_id_eq (get_frame_id (this_frame), - get_frame_id (this_frame->next))) - error ("Previous frame identical to this frame (corrupt stack?)"); + && frame_id_eq (this_id, get_frame_id (this_frame->next))) + 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 @@ -1871,6 +1151,35 @@ frame_debug_got_null_frame (struct ui_file *file, } } +/* Is this (non-sentinel) frame in the "main"() function? */ + +static int +inside_main_func (struct frame_info *this_frame) +{ + struct minimal_symbol *msymbol; + CORE_ADDR maddr; + + if (symfile_objfile == 0) + return 0; + msymbol = lookup_minimal_symbol (main_name (), NULL, symfile_objfile); + if (msymbol == NULL) + return 0; + /* Make certain that the code, and not descriptor, address is + returned. */ + maddr = gdbarch_convert_from_func_ptr_addr (current_gdbarch, + SYMBOL_VALUE_ADDRESS (msymbol), + ¤t_target); + return maddr == get_frame_func (this_frame); +} + +/* Test whether THIS_FRAME is inside the process entry point function. */ + +static int +inside_entry_func (struct frame_info *this_frame) +{ + return (get_frame_func (this_frame) == entry_point_address ()); +} + /* 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 @@ -1926,25 +1235,39 @@ get_prev_frame (struct frame_info *this_frame) get_current_frame(). */ gdb_assert (this_frame != NULL); - /* Make sure we pass an address within THIS_FRAME's code block to - inside_main_func(). Otherwise, we might stop unwinding at a - function which has a call instruction as its last instruction if - that function immediately precedes main(). */ + /* tausq/2004-12-07: Dummy frames are skipped because it doesn't make much + sense to stop unwinding at a dummy frame. One place where a dummy + frame may have an address "inside_main_func" is on HPUX. On HPUX, the + pcsqh register (space register for the instruction at the head of the + instruction queue) cannot be written directly; the only way to set it + is to branch to code that is in the target space. In order to implement + frame dummies on HPUX, the called function is made to jump back to where + the inferior was when the user function was called. If gdb was inside + the main function when we created the dummy frame, the dummy frame will + point inside the main function. */ if (this_frame->level >= 0 + && get_frame_type (this_frame) != DUMMY_FRAME && !backtrace_past_main - && inside_main_func (get_frame_address_in_block (this_frame))) - /* Don't unwind past main(), but always unwind the sentinel frame. - 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. */ + && inside_main_func (this_frame)) + /* Don't unwind past main(). Note, this is done _before_ the + frame has been marked as previously unwound. That way if the + user later decides to enable unwinds past main(), that will + automatically happen. */ { frame_debug_got_null_frame (gdb_stdlog, this_frame, "inside main func"); return NULL; } - if (this_frame->level > backtrace_limit) + /* If the user's backtrace limit has been exceeded, stop. We must + add two to the current level; one of those accounts for backtrace_limit + being 1-based and the level being 0-based, and the other accounts for + the level of the new frame instead of the level of the current + frame. */ + if (this_frame->level + 2 > backtrace_limit) { - error ("Backtrace limit of %d exceeded", backtrace_limit); + frame_debug_got_null_frame (gdb_stdlog, this_frame, + "backtrace limit exceeded"); + return NULL; } /* If we're already inside the entry function for the main objfile, @@ -1952,8 +1275,6 @@ get_prev_frame (struct frame_info *this_frame) dummy frame PCs typically land in the entry func. Don't apply 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. */ /* 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 @@ -1966,20 +1287,31 @@ get_prev_frame (struct frame_info *this_frame) I guess) to determine the address range of the start function. 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 - && this_frame->type != DUMMY_FRAME && this_frame->level >= 0 + /* NOTE: tausq/2004-10-09: this is needed if, for example, the compiler + applied tail-call optimizations to main so that a function called + from main returns directly to the caller of main. Since we don't + stop at main, we should at least stop at the entry point of the + application. */ + if (!backtrace_past_entry + && get_frame_type (this_frame) != DUMMY_FRAME && this_frame->level >= 0 && inside_entry_func (this_frame)) { frame_debug_got_null_frame (gdb_stdlog, this_frame, "inside entry func"); return NULL; } + /* Assume that the only way to get a zero PC is through something + like a SIGSEGV or a dummy frame, and hence that NORMAL frames + will never unwind a zero PC. */ + if (this_frame->level > 0 + && get_frame_type (this_frame) == NORMAL_FRAME + && get_frame_type (get_next_frame (this_frame)) == NORMAL_FRAME + && get_frame_pc (this_frame) == 0) + { + frame_debug_got_null_frame (gdb_stdlog, this_frame, "zero PC"); + return NULL; + } + return get_prev_frame_1 (this_frame); } @@ -2115,53 +1447,12 @@ frame_relative_level (struct frame_info *fi) enum frame_type get_frame_type (struct frame_info *frame) { - /* Some targets still don't use [generic] dummy frames. Catch them - here. */ - if (!DEPRECATED_USE_GENERIC_DUMMY_FRAMES - && deprecated_frame_in_dummy (frame)) - return DUMMY_FRAME; - - /* Some legacy code, e.g, mips_init_extra_frame_info() wants - to determine the frame's type prior to it being completely - initialized. Don't attempt to lazily initialize ->unwind for - legacy code. It will be initialized in legacy_get_prev_frame(). */ - if (frame->unwind == NULL && !legacy_frame_p (current_gdbarch)) - { - /* 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); - /* FIXME: cagney/2003-04-02: Rather than storing the frame's - type in the frame, the unwinder's type should be returned - directly. Unfortunately, legacy code, called by - legacy_get_prev_frame(), explicitly set the frames type using - the method deprecated_set_frame_type(). */ - frame->type = frame->unwind->type; - } - if (frame->type == UNKNOWN_FRAME) - return NORMAL_FRAME; - else - return frame->type; -} - -void -deprecated_set_frame_type (struct frame_info *frame, enum frame_type type) -{ - /* Arrrg! See comment in "frame.h". */ - frame->type = type; -} - -struct frame_extra_info * -get_frame_extra_info (struct frame_info *fi) -{ - return fi->extra_info; -} - -struct frame_extra_info * -frame_extra_info_zalloc (struct frame_info *fi, long size) -{ - fi->extra_info = frame_obstack_zalloc (size); - return fi->extra_info; + 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; } void @@ -2196,32 +1487,11 @@ deprecated_update_frame_base_hack (struct frame_info *frame, CORE_ADDR base) frame->this_id.value.stack_addr = base; } -struct frame_info * -deprecated_frame_xmalloc_with_cleanup (long sizeof_saved_regs, - long sizeof_extra_info) -{ - struct frame_info *frame = XMALLOC (struct frame_info); - memset (frame, 0, sizeof (*frame)); - frame->this_id.p = 1; - make_cleanup (xfree, frame); - if (sizeof_saved_regs > 0) - { - frame->saved_regs = xcalloc (1, sizeof_saved_regs); - make_cleanup (xfree, frame->saved_regs); - } - if (sizeof_extra_info > 0) - { - frame->extra_info = xcalloc (1, sizeof_extra_info); - make_cleanup (xfree, frame->extra_info); - } - return frame; -} - /* Memory access methods. */ void -get_frame_memory (struct frame_info *this_frame, CORE_ADDR addr, void *buf, - int len) +get_frame_memory (struct frame_info *this_frame, CORE_ADDR addr, + gdb_byte *buf, int len) { read_memory (addr, buf, len); } @@ -2242,10 +1512,10 @@ get_frame_memory_unsigned (struct frame_info *this_frame, CORE_ADDR addr, int safe_frame_unwind_memory (struct frame_info *this_frame, - CORE_ADDR addr, void *buf, int len) + CORE_ADDR addr, gdb_byte *buf, int len) { - /* NOTE: read_memory_nobpt returns zero on success! */ - return !read_memory_nobpt (addr, buf, len); + /* NOTE: deprecated_read_memory_nobpt returns zero on success! */ + return !deprecated_read_memory_nobpt (addr, buf, len); } /* Architecture method. */ @@ -2283,34 +1553,7 @@ frame_sp_unwind (struct frame_info *next_frame) frame_unwind_unsigned_register (next_frame, SP_REGNUM, &sp); return sp; } - internal_error (__FILE__, __LINE__, "Missing unwind SP method"); -} - - -int -legacy_frame_p (struct gdbarch *current_gdbarch) -{ - if (DEPRECATED_INIT_FRAME_PC_P () - || DEPRECATED_INIT_EXTRA_FRAME_INFO_P () - || DEPRECATED_FRAME_CHAIN_P ()) - /* No question, it's a legacy frame. */ - return 1; - if (gdbarch_unwind_dummy_id_p (current_gdbarch)) - /* No question, it's not a legacy frame (provided none of the - deprecated methods checked above are present that is). */ - return 0; - if (DEPRECATED_TARGET_READ_FP_P () - || DEPRECATED_FP_REGNUM >= 0) - /* Assume it's legacy. If you're trying to convert a legacy frame - target to the new mechanism, get rid of these. legacy - get_prev_frame() requires these when unwind_frame_id() isn't - available. */ - return 1; - /* Default to assuming that it's brand new code, and hence not - legacy. Force it down the non-legacy path so that the new code - uses the new frame mechanism from day one. Dummy frames won't - work very well but we can live with that. */ - return 0; + internal_error (__FILE__, __LINE__, _("Missing unwind SP method")); } extern initialize_file_ftype _initialize_frame; /* -Wmissing-prototypes */ @@ -2337,42 +1580,60 @@ _initialize_frame (void) observer_attach_target_changed (frame_observer_target_changed); - add_prefix_cmd ("backtrace", class_maintenance, set_backtrace_cmd, "\ + add_prefix_cmd ("backtrace", class_maintenance, set_backtrace_cmd, _("\ Set backtrace specific variables.\n\ -Configure backtrace variables such as the backtrace limit", +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, "\ + add_prefix_cmd ("backtrace", class_maintenance, show_backtrace_cmd, _("\ Show backtrace specific variables\n\ -Show backtrace variables such as the backtrace limit", +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, "\ -Set whether backtraces should continue past \"main\".\n\ -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.", "\ -Show whether backtraces should continue past \"main\".\n\ + &backtrace_past_main, _("\ +Set whether backtraces should continue past \"main\"."), _("\ +Show whether backtraces should continue past \"main\"."), _("\ 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.", - NULL, NULL, &set_backtrace_cmdlist, +of the stack trace."), + NULL, + show_backtrace_past_main, + &set_backtrace_cmdlist, + &show_backtrace_cmdlist); + + add_setshow_boolean_cmd ("past-entry", class_obscure, + &backtrace_past_entry, _("\ +Set whether backtraces should continue past the entry point of a program."), + _("\ +Show whether backtraces should continue past the entry point of a program."), + _("\ +Normally there are no callers beyond the entry point of a program, so GDB\n\ +will terminate the backtrace there. Set this variable if you need to see \n\ +the rest of the stack trace."), + NULL, + show_backtrace_past_entry, + &set_backtrace_cmdlist, &show_backtrace_cmdlist); - add_setshow_uinteger_cmd ("limit", class_obscure, - &backtrace_limit, "\ -Set an upper bound on the number of backtrace levels.\n\ + add_setshow_integer_cmd ("limit", class_obscure, + &backtrace_limit, _("\ +Set an upper bound on the number of backtrace levels."), _("\ +Show the upper bound on the number of backtrace levels."), _("\ No more than the specified number of frames can be displayed or examined.\n\ -Zero is unlimited.", "\ -Show the upper bound on the number of backtrace levels.", - NULL, NULL, &set_backtrace_cmdlist, - &show_backtrace_cmdlist); +Zero is unlimited."), + NULL, + show_backtrace_limit, + &set_backtrace_cmdlist, + &show_backtrace_cmdlist); /* Debug this files internals. */ - add_show_from_set (add_set_cmd ("frame", class_maintenance, var_zinteger, - &frame_debug, "Set frame debugging.\n\ -When non-zero, frame specific internal debugging is enabled.", &setdebuglist), - &showdebuglist); + add_setshow_zinteger_cmd ("frame", class_maintenance, &frame_debug, _("\ +Set frame debugging."), _("\ +Show frame debugging."), _("\ +When non-zero, frame specific internal debugging is enabled."), + NULL, + show_frame_debug, + &setdebuglist, &showdebuglist); }