X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fblockframe.c;h=6ac35b774c6c8d925e27d479e922de706fcf369a;hb=4478b372e973afcd2253fe4c1ec3f2d083ac3943;hp=9366ca650e2079633fd9bf470f6e471f3f21bd3f;hpb=1996fae84682e8ddd146215dd2959ad1ec924c09;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/blockframe.c b/gdb/blockframe.c index 9366ca650e..6ac35b774c 100644 --- a/gdb/blockframe.c +++ b/gdb/blockframe.c @@ -1,23 +1,24 @@ /* Get info from stack frames; convert between frames, blocks, functions and pc values. Copyright 1986, 87, 88, 89, 91, 94, 95, 96, 97, 1998 - Free Software Foundation, Inc. + Free Software Foundation, Inc. -This file is part of GDB. + 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 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. + 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. */ + 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 "symtab.h" @@ -33,37 +34,37 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Prototypes for exported functions. */ -void _initialize_blockframe PARAMS ((void)); +void _initialize_blockframe (void); /* A default FRAME_CHAIN_VALID, in the form that is suitable for most targets. If FRAME_CHAIN_VALID returns zero it means that the given frame is the outermost one and has no caller. */ int -default_frame_chain_valid (chain, thisframe) +file_frame_chain_valid (chain, thisframe) CORE_ADDR chain; struct frame_info *thisframe; { return ((chain) != 0 - && !inside_main_func ((thisframe) -> pc) - && !inside_entry_func ((thisframe) -> pc)); + && !inside_entry_file (FRAME_SAVED_PC (thisframe))); } /* Use the alternate method of avoiding running up off the end of the frame chain or following frames back into the startup code. See the comments in objfiles.h. */ - + int -alternate_frame_chain_valid (chain, thisframe) +func_frame_chain_valid (chain, thisframe) CORE_ADDR chain; struct frame_info *thisframe; { return ((chain) != 0 - && !inside_entry_file (FRAME_SAVED_PC (thisframe))); + && !inside_main_func ((thisframe)->pc) + && !inside_entry_func ((thisframe)->pc)); } /* A very simple method of determining a valid frame */ - + int nonnull_frame_chain_valid (chain, thisframe) CORE_ADDR chain; @@ -88,15 +89,16 @@ inside_entry_file (addr) return 1; if (symfile_objfile == 0) return 0; -#if CALL_DUMMY_LOCATION == AT_ENTRY_POINT - /* Do not stop backtracing if the pc is in the call dummy - at the entry point. */ -/* FIXME: Won't always work with zeros for the last two arguments */ - if (PC_IN_CALL_DUMMY (addr, 0, 0)) - return 0; -#endif - return (addr >= symfile_objfile -> ei.entry_file_lowpc && - addr < symfile_objfile -> ei.entry_file_highpc); + if (CALL_DUMMY_LOCATION == AT_ENTRY_POINT) + { + /* Do not stop backtracing if the pc is in the call dummy + at the entry point. */ + /* FIXME: Won't always work with zeros for the last two arguments */ + if (PC_IN_CALL_DUMMY (addr, 0, 0)) + return 0; + } + return (addr >= symfile_objfile->ei.entry_file_lowpc && + addr < symfile_objfile->ei.entry_file_highpc); } /* Test a specified PC value to see if it is in the range of addresses @@ -109,7 +111,7 @@ inside_entry_file (addr) int inside_main_func (pc) -CORE_ADDR pc; + CORE_ADDR pc; { if (pc == 0) return 1; @@ -120,22 +122,22 @@ CORE_ADDR pc; This is for FRAME_CHAIN_VALID_ALTERNATE. I do this for coff, because it is unable to set it up and symbol reading time. */ - if (symfile_objfile -> ei.main_func_lowpc == INVALID_ENTRY_LOWPC && - symfile_objfile -> ei.main_func_highpc == INVALID_ENTRY_HIGHPC) + if (symfile_objfile->ei.main_func_lowpc == INVALID_ENTRY_LOWPC && + symfile_objfile->ei.main_func_highpc == INVALID_ENTRY_HIGHPC) { struct symbol *mainsym; mainsym = lookup_symbol ("main", NULL, VAR_NAMESPACE, NULL, NULL); - if (mainsym && SYMBOL_CLASS(mainsym) == LOC_BLOCK) - { - symfile_objfile->ei.main_func_lowpc = + if (mainsym && SYMBOL_CLASS (mainsym) == LOC_BLOCK) + { + symfile_objfile->ei.main_func_lowpc = BLOCK_START (SYMBOL_BLOCK_VALUE (mainsym)); - symfile_objfile->ei.main_func_highpc = + symfile_objfile->ei.main_func_highpc = BLOCK_END (SYMBOL_BLOCK_VALUE (mainsym)); - } + } } - return (symfile_objfile -> ei.main_func_lowpc <= pc && - symfile_objfile -> ei.main_func_highpc > pc); + return (symfile_objfile->ei.main_func_lowpc <= pc && + symfile_objfile->ei.main_func_highpc > pc); } /* Test a specified PC value to see if it is in the range of addresses @@ -148,21 +150,22 @@ CORE_ADDR pc; int inside_entry_func (pc) -CORE_ADDR pc; + CORE_ADDR pc; { if (pc == 0) return 1; if (symfile_objfile == 0) return 0; -#if CALL_DUMMY_LOCATION == AT_ENTRY_POINT - /* Do not stop backtracing if the pc is in the call dummy - at the entry point. */ -/* FIXME: Won't always work with zeros for the last two arguments */ - if (PC_IN_CALL_DUMMY (pc, 0, 0)) - return 0; -#endif - return (symfile_objfile -> ei.entry_func_lowpc <= pc && - symfile_objfile -> ei.entry_func_highpc > pc); + if (CALL_DUMMY_LOCATION == AT_ENTRY_POINT) + { + /* Do not stop backtracing if the pc is in the call dummy + at the entry point. */ + /* FIXME: Won't always work with zeros for the last two arguments */ + if (PC_IN_CALL_DUMMY (pc, 0, 0)) + return 0; + } + return (symfile_objfile->ei.entry_func_lowpc <= pc && + symfile_objfile->ei.entry_func_highpc > pc); } /* Info about the innermost stack frame (contents of FP register) */ @@ -186,7 +189,7 @@ void frame_saved_regs_zalloc (fi) struct frame_info *fi; { - fi->saved_regs = (CORE_ADDR*) + fi->saved_regs = (CORE_ADDR *) frame_obstack_alloc (SIZEOF_FRAME_SAVED_REGS); memset (fi->saved_regs, 0, SIZEOF_FRAME_SAVED_REGS); } @@ -235,7 +238,7 @@ create_new_frame (addr, pc) fi->prev = NULL; fi->frame = addr; fi->pc = pc; - find_pc_partial_function (pc, &name, (CORE_ADDR *)NULL,(CORE_ADDR *)NULL); + find_pc_partial_function (pc, &name, (CORE_ADDR *) NULL, (CORE_ADDR *) NULL); fi->signal_handler_caller = IN_SIGTRAMP (fi->pc, name); #ifdef INIT_EXTRA_FRAME_INFO @@ -245,16 +248,6 @@ create_new_frame (addr, pc) return fi; } -/* Return the frame that called FI. - If FI is the original frame (it has no caller), return 0. */ - -struct frame_info * -get_prev_frame (frame) - struct frame_info *frame; -{ - return get_prev_frame_info (frame); -} - /* Return the frame that FRAME calls (NULL if FRAME is the innermost frame). */ @@ -274,7 +267,7 @@ flush_cached_frames () obstack_free (&frame_cache_obstack, 0); obstack_init (&frame_cache_obstack); - current_frame = NULL; /* Invalidate cache */ + current_frame = NULL; /* Invalidate cache */ select_frame (NULL, -1); annotate_frames_invalid (); } @@ -293,11 +286,6 @@ reinit_frame_cache () } } -/* If a machine allows frameless functions, it should define a macro - FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) in param.h. FI is the struct - frame_info for the frame, and FRAMELESS should be set to nonzero - if it represents a frameless function invocation. */ - /* Return nonzero if the function for this frame lacks a prologue. Many machines can define FRAMELESS_FUNCTION_INVOCATION to just call this function. */ @@ -307,25 +295,26 @@ frameless_look_for_prologue (frame) struct frame_info *frame; { CORE_ADDR func_start, after_prologue; + func_start = get_pc_function_start (frame->pc); if (func_start) { func_start += FUNCTION_START_OFFSET; after_prologue = func_start; #ifdef SKIP_PROLOGUE_FRAMELESS_P - /* This is faster, since only care whether there *is* a prologue, - not how long it is. */ - SKIP_PROLOGUE_FRAMELESS_P (after_prologue); + /* This is faster, since only care whether there *is* a + prologue, not how long it is. */ + after_prologue = SKIP_PROLOGUE_FRAMELESS_P (after_prologue); #else - SKIP_PROLOGUE (after_prologue); + after_prologue = SKIP_PROLOGUE (after_prologue); #endif return after_prologue == func_start; } else if (frame->pc == 0) - /* A frame with a zero PC is usually created by dereferencing a NULL - function pointer, normally causing an immediate core dump of the - inferior. Mark function as frameless, as the inferior has no chance - of setting up a stack frame. */ + /* A frame with a zero PC is usually created by dereferencing a + NULL function pointer, normally causing an immediate core dump + of the inferior. Mark function as frameless, as the inferior + has no chance of setting up a stack frame. */ return 1; else /* If we can't find the start of the function, we don't really @@ -352,7 +341,7 @@ frameless_look_for_prologue (frame) if there is no such frame. */ struct frame_info * -get_prev_frame_info (next_frame) +get_prev_frame (next_frame) struct frame_info *next_frame; { CORE_ADDR address = 0; @@ -368,9 +357,9 @@ get_prev_frame_info (next_frame) { #if 0 /* This screws value_of_variable, which just wants a nice clean - NULL return from block_innermost_frame if there are no frames. - I don't think I've ever seen this message happen otherwise. - And returning NULL here is a perfectly legitimate thing to do. */ + NULL return from block_innermost_frame if there are no frames. + I don't think I've ever seen this message happen otherwise. + And returning NULL here is a perfectly legitimate thing to do. */ if (!current_frame) { error ("You haven't set up a process's stack to examine."); @@ -389,33 +378,32 @@ get_prev_frame_info (next_frame) 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. */ -#ifdef FRAMELESS_FUNCTION_INVOCATION + /* Still don't want to worry about this except on the innermost frame. This macro will set FROMLEAF if NEXT_FRAME is a frameless function invocation. */ if (!(next_frame->next)) { - FRAMELESS_FUNCTION_INVOCATION (next_frame, fromleaf); + fromleaf = FRAMELESS_FUNCTION_INVOCATION (next_frame); if (fromleaf) address = FRAME_FP (next_frame); } -#endif if (!fromleaf) { /* 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. */ + 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. */ address = FRAME_CHAIN (next_frame); if (!FRAME_CHAIN_VALID (address, next_frame)) return 0; @@ -441,11 +429,11 @@ get_prev_frame_info (next_frame) after INIT_EXTRA_FRAME_INFO and come up with a simple way to express what goes on here. - 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). - INIT_FRAME_PC is only called from here, always after - INIT_EXTRA_FRAME_INFO. - + 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). + INIT_FRAME_PC is only called from here, always after + INIT_EXTRA_FRAME_INFO. + The catch is the MIPS, where INIT_EXTRA_FRAME_INFO requires the PC value (which hasn't been set yet). Some other machines appear to require INIT_EXTRA_FRAME_INFO before they can do INIT_FRAME_PC. Phoo. @@ -457,24 +445,24 @@ get_prev_frame_info (next_frame) INIT_EXTRA_FRAME_INFO, one possible scheme: SETUP_INNERMOST_FRAME() - Default version is just create_new_frame (read_fp ()), - read_pc ()). Machines with extra frame info would do that (or the - local equivalent) and then set the extra fields. + Default version is just create_new_frame (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. + 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 INIT_EXTRA_FRAME_INFO and 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 FRAME_CHAIN_VALID called *before* - INIT_EXTRA_FRAME_INFO (there is no good way to get information - deduced in FRAME_CHAIN_VALID into the extra fields of the new frame). + Replace INIT_EXTRA_FRAME_INFO and 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 FRAME_CHAIN_VALID called *before* + INIT_EXTRA_FRAME_INFO (there is no good way to get information + deduced in 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 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. + This is the default setting for INIT_PREV_FRAME. It just does what + the default 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. */ #ifdef INIT_FRAME_PC_FIRST @@ -482,13 +470,13 @@ get_prev_frame_info (next_frame) #endif #ifdef INIT_EXTRA_FRAME_INFO - INIT_EXTRA_FRAME_INFO(fromleaf, prev); + INIT_EXTRA_FRAME_INFO (fromleaf, prev); #endif /* 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. */ - INIT_FRAME_PC(fromleaf, prev); + 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 @@ -506,7 +494,7 @@ get_prev_frame_info (next_frame) } find_pc_partial_function (prev->pc, &name, - (CORE_ADDR *)NULL,(CORE_ADDR *)NULL); + (CORE_ADDR *) NULL, (CORE_ADDR *) NULL); if (IN_SIGTRAMP (prev->pc, name)) prev->signal_handler_caller = 1; @@ -533,7 +521,7 @@ get_frame_saved_regs (frame, saved_regs_addr) { if (frame->saved_regs == NULL) { - frame->saved_regs = (CORE_ADDR*) + frame->saved_regs = (CORE_ADDR *) frame_obstack_alloc (SIZEOF_FRAME_SAVED_REGS); } if (saved_regs_addr == NULL) @@ -627,13 +615,13 @@ blockvector_for_pc_sect (pc, section, pindex, symtab) struct sec *section; int *pindex; struct symtab *symtab; - + { register struct block *b; register int bot, top, half; struct blockvector *bl; - if (symtab == 0) /* if no symtab specified by caller */ + if (symtab == 0) /* if no symtab specified by caller */ { /* First search all symtabs for one whose file contains our pc */ if ((symtab = find_pc_sect_symtab (pc, section)) == 0) @@ -664,7 +652,7 @@ blockvector_for_pc_sect (pc, section, pindex, symtab) while (bot >= 0) { b = BLOCKVECTOR_BLOCK (bl, bot); - if (BLOCK_END (b) >= pc) + if (BLOCK_END (b) > pc) { if (pindex) *pindex = bot; @@ -742,19 +730,19 @@ find_pc_function (pc) /* These variables are used to cache the most recent result * of find_pc_partial_function. */ -static CORE_ADDR cache_pc_function_low = 0; -static CORE_ADDR cache_pc_function_high = 0; -static char *cache_pc_function_name = 0; +static CORE_ADDR cache_pc_function_low = 0; +static CORE_ADDR cache_pc_function_high = 0; +static char *cache_pc_function_name = 0; static struct sec *cache_pc_function_section = NULL; /* Clear cache, e.g. when symbol table is discarded. */ void -clear_pc_function_cache() +clear_pc_function_cache () { cache_pc_function_low = 0; cache_pc_function_high = 0; - cache_pc_function_name = (char *)0; + cache_pc_function_name = (char *) 0; cache_pc_function_section = NULL; } @@ -771,23 +759,23 @@ clear_pc_function_cache() int find_pc_sect_partial_function (pc, section, name, address, endaddr) - CORE_ADDR pc; - asection *section; - char **name; + CORE_ADDR pc; + asection *section; + char **name; CORE_ADDR *address; CORE_ADDR *endaddr; { struct partial_symtab *pst; - struct symbol *f; + struct symbol *f; struct minimal_symbol *msymbol; struct partial_symbol *psb; - struct obj_section *osect; + struct obj_section *osect; int i; CORE_ADDR mapped_pc; mapped_pc = overlay_mapped_address (pc, section); - if (mapped_pc >= cache_pc_function_low && + if (mapped_pc >= cache_pc_function_low && mapped_pc < cache_pc_function_high && section == cache_pc_function_section) goto return_cached_value; @@ -795,11 +783,11 @@ find_pc_sect_partial_function (pc, section, name, address, endaddr) /* If sigtramp is in the u area, it counts as a function (especially important for step_1). */ #if defined SIGTRAMP_START - if (IN_SIGTRAMP (mapped_pc, (char *)NULL)) + if (IN_SIGTRAMP (mapped_pc, (char *) NULL)) { - cache_pc_function_low = SIGTRAMP_START (mapped_pc); - cache_pc_function_high = SIGTRAMP_END (mapped_pc); - cache_pc_function_name = ""; + cache_pc_function_low = SIGTRAMP_START (mapped_pc); + cache_pc_function_high = SIGTRAMP_END (mapped_pc); + cache_pc_function_name = ""; cache_pc_function_section = section; goto return_cached_value; } @@ -828,9 +816,9 @@ find_pc_sect_partial_function (pc, section, name, address, endaddr) || (BLOCK_START (SYMBOL_BLOCK_VALUE (f)) >= SYMBOL_VALUE_ADDRESS (msymbol)))) { - cache_pc_function_low = BLOCK_START (SYMBOL_BLOCK_VALUE (f)); - cache_pc_function_high = BLOCK_END (SYMBOL_BLOCK_VALUE (f)); - cache_pc_function_name = SYMBOL_NAME (f); + cache_pc_function_low = BLOCK_START (SYMBOL_BLOCK_VALUE (f)); + cache_pc_function_high = BLOCK_END (SYMBOL_BLOCK_VALUE (f)); + cache_pc_function_name = SYMBOL_NAME (f); cache_pc_function_section = section; goto return_cached_value; } @@ -881,21 +869,21 @@ find_pc_sect_partial_function (pc, section, name, address, endaddr) return 0; } - cache_pc_function_low = SYMBOL_VALUE_ADDRESS (msymbol); - cache_pc_function_name = SYMBOL_NAME (msymbol); + cache_pc_function_low = SYMBOL_VALUE_ADDRESS (msymbol); + cache_pc_function_name = SYMBOL_NAME (msymbol); cache_pc_function_section = section; /* Use the lesser of the next minimal symbol in the same section, or the end of the section, as the end of the function. */ - + /* Step over other symbols at this same address, and symbols in other sections, to find the next symbol in this section with a different address. */ - for (i=1; SYMBOL_NAME (msymbol+i) != NULL; i++) + for (i = 1; SYMBOL_NAME (msymbol + i) != NULL; i++) { - if (SYMBOL_VALUE_ADDRESS (msymbol+i) != SYMBOL_VALUE_ADDRESS (msymbol) - && SYMBOL_BFD_SECTION (msymbol+i) == SYMBOL_BFD_SECTION (msymbol)) + if (SYMBOL_VALUE_ADDRESS (msymbol + i) != SYMBOL_VALUE_ADDRESS (msymbol) + && SYMBOL_BFD_SECTION (msymbol + i) == SYMBOL_BFD_SECTION (msymbol)) break; } @@ -907,33 +895,33 @@ find_pc_sect_partial_function (pc, section, name, address, endaddr) So the end address is the end of the section. */ cache_pc_function_high = osect->endaddr; - return_cached_value: +return_cached_value: if (address) { if (pc_in_unmapped_range (pc, section)) - *address = overlay_unmapped_address (cache_pc_function_low, section); + *address = overlay_unmapped_address (cache_pc_function_low, section); else - *address = cache_pc_function_low; + *address = cache_pc_function_low; } - + if (name) *name = cache_pc_function_name; if (endaddr) { if (pc_in_unmapped_range (pc, section)) - { + { /* Because the high address is actually beyond the end of the function (and therefore possibly beyond the end of the overlay), we must actually convert (high - 1) and then add one to that. */ - *endaddr = 1 + overlay_unmapped_address (cache_pc_function_high - 1, + *endaddr = 1 + overlay_unmapped_address (cache_pc_function_high - 1, section); - } + } else - *endaddr = cache_pc_function_high; + *endaddr = cache_pc_function_high; } return 1; @@ -943,12 +931,12 @@ find_pc_sect_partial_function (pc, section, name, address, endaddr) int find_pc_partial_function (pc, name, address, endaddr) - CORE_ADDR pc; - char **name; + CORE_ADDR pc; + char **name; CORE_ADDR *address; CORE_ADDR *endaddr; { - asection *section; + asection *section; section = find_pc_overlay (pc); return find_pc_sect_partial_function (pc, section, name, address, endaddr); @@ -991,7 +979,7 @@ find_frame_addr_in_frame_chain (frame_addr) { struct frame_info *frame = NULL; - if (frame_addr == (CORE_ADDR)0) + if (frame_addr == (CORE_ADDR) 0) return NULL; while (1) @@ -1024,7 +1012,7 @@ sigtramp_saved_pc (frame) ptrbytes); else sigcontext_addr = read_memory_integer (read_register (SP_REGNUM) - + sigcontext_offs, + + sigcontext_offs, ptrbytes); /* Don't cause a memory_error when accessing sigcontext in case the stack @@ -1034,7 +1022,72 @@ sigtramp_saved_pc (frame) } #endif /* SIGCONTEXT_PC_OFFSET */ -#ifdef USE_GENERIC_DUMMY_FRAMES + +/* Are we in a call dummy? The code below which allows DECR_PC_AFTER_BREAK + below is for infrun.c, which may give the macro a pc without that + subtracted out. */ + +extern CORE_ADDR text_end; + +int +pc_in_call_dummy_before_text_end (pc, sp, frame_address) + CORE_ADDR pc; + CORE_ADDR sp; + CORE_ADDR frame_address; +{ + return ((pc) >= text_end - CALL_DUMMY_LENGTH + && (pc) <= text_end + DECR_PC_AFTER_BREAK); +} + +int +pc_in_call_dummy_after_text_end (pc, sp, frame_address) + CORE_ADDR pc; + CORE_ADDR sp; + CORE_ADDR frame_address; +{ + return ((pc) >= text_end + && (pc) <= text_end + CALL_DUMMY_LENGTH + DECR_PC_AFTER_BREAK); +} + +/* Is the PC in a call dummy? SP and FRAME_ADDRESS are the bottom and + top of the stack frame which we are checking, where "bottom" and + "top" refer to some section of memory which contains the code for + the call dummy. Calls to this macro assume that the contents of + SP_REGNUM and FP_REGNUM (or the saved values thereof), respectively, + are the things to pass. + + This won't work on the 29k, where SP_REGNUM and FP_REGNUM don't + have that meaning, but the 29k doesn't use ON_STACK. This could be + fixed by generalizing this scheme, perhaps by passing in a frame + and adding a few fields, at least on machines which need them for + PC_IN_CALL_DUMMY. + + Something simpler, like checking for the stack segment, doesn't work, + since various programs (threads implementations, gcc nested function + stubs, etc) may either allocate stack frames in another segment, or + allocate other kinds of code on the stack. */ + +int +pc_in_call_dummy_on_stack (pc, sp, frame_address) + CORE_ADDR pc; + CORE_ADDR sp; + CORE_ADDR frame_address; +{ + return (INNER_THAN ((sp), (pc)) + && (frame_address != 0) + && INNER_THAN ((pc), (frame_address))); +} + +int +pc_in_call_dummy_at_entry_point (pc, sp, frame_address) + CORE_ADDR pc; + CORE_ADDR sp; + CORE_ADDR frame_address; +{ + return ((pc) >= CALL_DUMMY_ADDRESS () + && (pc) <= (CALL_DUMMY_ADDRESS () + DECR_PC_AFTER_BREAK)); +} + /* * GENERIC DUMMY FRAMES @@ -1051,7 +1104,23 @@ sigtramp_saved_pc (frame) * zero, and CALL_DUMMY_LOCATION to AT_ENTRY. Then you must remember * to define PUSH_RETURN_ADDRESS, because no call instruction will be * being executed by the target. Also FRAME_CHAIN_VALID as - * generic_frame_chain_valid. */ + * generic_{file,func}_frame_chain_valid and FIX_CALL_DUMMY as + * generic_fix_call_dummy. */ + +/* Dummy frame. This saves the processor state just prior to setting + up the inferior function call. Older targets save the registers + target stack (but that really slows down function calls). */ + +struct dummy_frame +{ + struct dummy_frame *next; + + CORE_ADDR pc; + CORE_ADDR fp; + CORE_ADDR sp; + CORE_ADDR top; + char *registers; +}; static struct dummy_frame *dummy_frame_stack = NULL; @@ -1059,21 +1128,23 @@ static struct dummy_frame *dummy_frame_stack = NULL; Search the stack of dummy frames for one matching the given PC, FP and SP. This is the work-horse for pc_in_call_dummy and read_register_dummy */ -char * +char * generic_find_dummy_frame (pc, fp) CORE_ADDR pc; CORE_ADDR fp; { - struct dummy_frame * dummyframe; + struct dummy_frame *dummyframe; if (pc != entry_point_address ()) return 0; for (dummyframe = dummy_frame_stack; dummyframe != NULL; dummyframe = dummyframe->next) - if (fp == dummyframe->fp || fp == dummyframe->sp) + if (fp == dummyframe->fp + || fp == dummyframe->sp + || fp == dummyframe->top) /* The frame in question lies between the saved fp and sp, inclusive */ - return dummyframe->regs; + return dummyframe->registers; return 0; } @@ -1082,12 +1153,14 @@ generic_find_dummy_frame (pc, fp) Return true if this is a dummy frame created by gdb for an inferior call */ int -generic_pc_in_call_dummy (pc, fp) +generic_pc_in_call_dummy (pc, sp, fp) CORE_ADDR pc; + CORE_ADDR sp; CORE_ADDR fp; { /* if find_dummy_frame succeeds, then PC is in a call dummy */ - return (generic_find_dummy_frame (pc, fp) != 0); + /* Note: SP and not FP is passed on. */ + return (generic_find_dummy_frame (pc, sp) != 0); } /* Function: read_register_dummy @@ -1103,7 +1176,7 @@ generic_read_register_dummy (pc, fp, regno) if (dummy_regs) return extract_address (&dummy_regs[REGISTER_BYTE (regno)], - REGISTER_RAW_SIZE(regno)); + REGISTER_RAW_SIZE (regno)); else return 0; } @@ -1130,6 +1203,7 @@ generic_push_dummy_frame () if (INNER_THAN (dummy_frame->fp, fp)) /* stale -- destroy! */ { dummy_frame_stack = dummy_frame->next; + free (dummy_frame->registers); free (dummy_frame); dummy_frame = dummy_frame_stack; } @@ -1137,27 +1211,36 @@ generic_push_dummy_frame () dummy_frame = dummy_frame->next; dummy_frame = xmalloc (sizeof (struct dummy_frame)); - dummy_frame->pc = read_register (PC_REGNUM); - dummy_frame->sp = read_register (SP_REGNUM); - dummy_frame->fp = fp; - read_register_bytes (0, dummy_frame->regs, REGISTER_BYTES); + dummy_frame->registers = xmalloc (REGISTER_BYTES); + + dummy_frame->pc = read_pc (); + dummy_frame->sp = read_sp (); + dummy_frame->top = dummy_frame->sp; + dummy_frame->fp = fp; + read_register_bytes (0, dummy_frame->registers, REGISTER_BYTES); dummy_frame->next = dummy_frame_stack; dummy_frame_stack = dummy_frame; } -/* Function: pop_frame - Restore the machine state from either the saved dummy stack or a +void +generic_save_dummy_frame_tos (sp) + CORE_ADDR sp; +{ + dummy_frame_stack->top = sp; +} + +/* Restore the machine state from either the saved dummy stack or a real stack frame. */ void -generic_pop_current_frame (pop) - void (*pop) PARAMS ((struct frame_info *frame)); +generic_pop_current_frame (void (*popper) (struct frame_info * frame)) { struct frame_info *frame = get_current_frame (); - if (PC_IN_CALL_DUMMY(frame->pc, frame->frame, frame->frame)) + + if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame)) generic_pop_dummy_frame (); else - pop (frame); + (*popper) (frame); } /* Function: pop_dummy_frame @@ -1174,28 +1257,61 @@ generic_pop_dummy_frame () if (!dummy_frame) error ("Can't pop dummy frame!"); dummy_frame_stack = dummy_frame->next; - write_register_bytes (0, dummy_frame->regs, REGISTER_BYTES); + write_register_bytes (0, dummy_frame->registers, REGISTER_BYTES); flush_cached_frames (); + + free (dummy_frame->registers); free (dummy_frame); } /* Function: frame_chain_valid Returns true for a user frame or a call_function_by_hand dummy frame, and false for the CRT0 start-up frame. Purpose is to terminate backtrace */ - + int -generic_frame_chain_valid (fp, fi) +generic_file_frame_chain_valid (fp, fi) CORE_ADDR fp; struct frame_info *fi; { - if (PC_IN_CALL_DUMMY(FRAME_SAVED_PC(fi), fp, fp)) - return 1; /* don't prune CALL_DUMMY frames */ - else /* fall back to default algorithm (see frame.h) */ + if (PC_IN_CALL_DUMMY (FRAME_SAVED_PC (fi), fp, fp)) + return 1; /* don't prune CALL_DUMMY frames */ + else /* fall back to default algorithm (see frame.h) */ return (fp != 0 && (INNER_THAN (fi->frame, fp) || fi->frame == fp) - && !inside_entry_file (FRAME_SAVED_PC(fi))); + && !inside_entry_file (FRAME_SAVED_PC (fi))); } - + +int +generic_func_frame_chain_valid (fp, fi) + CORE_ADDR fp; + struct frame_info *fi; +{ + if (PC_IN_CALL_DUMMY ((fi)->pc, fp, fp)) + return 1; /* don't prune CALL_DUMMY frames */ + else /* fall back to default algorithm (see frame.h) */ + return (fp != 0 + && (INNER_THAN (fi->frame, fp) || fi->frame == fp) + && !inside_main_func ((fi)->pc) + && !inside_entry_func ((fi)->pc)); +} + +/* Function: fix_call_dummy + Stub function. Generic dumy frames typically do not need to fix + the frame being created */ + +void +generic_fix_call_dummy (dummy, pc, fun, nargs, args, type, gcc_p) + char *dummy; + CORE_ADDR pc; + CORE_ADDR fun; + int nargs; + struct value **args; + struct type *type; + int gcc_p; +{ + return; +} + /* Function: get_saved_register Find register number REGNUM relative to FRAME and put its (raw, target format) contents in *RAW_BUFFER. @@ -1236,7 +1352,7 @@ generic_get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval) if (optimized != NULL) *optimized = 0; - if (addrp) /* default assumption: not found in memory */ + if (addrp) /* default assumption: not found in memory */ *addrp = 0; /* Note: since the current frame's registers could only have been @@ -1248,34 +1364,34 @@ generic_get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval) { if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame)) { - if (lval) /* found it in a CALL_DUMMY frame */ + if (lval) /* found it in a CALL_DUMMY frame */ *lval = not_lval; if (raw_buffer) - memcpy (raw_buffer, - generic_find_dummy_frame (frame->pc, frame->frame) + + memcpy (raw_buffer, + generic_find_dummy_frame (frame->pc, frame->frame) + REGISTER_BYTE (regnum), REGISTER_RAW_SIZE (regnum)); - return; + return; } FRAME_INIT_SAVED_REGS (frame); if (frame->saved_regs != NULL && frame->saved_regs[regnum] != 0) { - if (lval) /* found it saved on the stack */ + if (lval) /* found it saved on the stack */ *lval = lval_memory; if (regnum == SP_REGNUM) { - if (raw_buffer) /* SP register treated specially */ - store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), + if (raw_buffer) /* SP register treated specially */ + store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), frame->saved_regs[regnum]); } else { - if (addrp) /* any other register */ + if (addrp) /* any other register */ *addrp = frame->saved_regs[regnum]; if (raw_buffer) - read_memory (frame->saved_regs[regnum], raw_buffer, + read_memory (frame->saved_regs[regnum], raw_buffer, REGISTER_RAW_SIZE (regnum)); } return; @@ -1285,17 +1401,16 @@ generic_get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval) /* 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 */ + if (lval) /* found it in a live register */ *lval = lval_register; if (addrp) *addrp = REGISTER_BYTE (regnum); if (raw_buffer) read_register_gen (regnum, raw_buffer); } -#endif /* USE_GENERIC_DUMMY_FRAMES */ void -_initialize_blockframe () +_initialize_blockframe (void) { obstack_init (&frame_cache_obstack); }