diff options
author | Daniel Jacobowitz <drow@false.org> | 2005-09-29 15:37:44 +0000 |
---|---|---|
committer | Daniel Jacobowitz <drow@false.org> | 2005-09-29 15:37:44 +0000 |
commit | e10b1c4cbbec60209f5eb0365481ab62b498abc0 (patch) | |
tree | 8904061945a96db5d179ef8e2e54cf321db096ed /gdb/rs6000-tdep.c | |
parent | ef0241e727d448bf82983b97aa4c2dbe6b66c0d4 (diff) | |
download | gdb-e10b1c4cbbec60209f5eb0365481ab62b498abc0.zip gdb-e10b1c4cbbec60209f5eb0365481ab62b498abc0.tar.gz gdb-e10b1c4cbbec60209f5eb0365481ab62b498abc0.tar.bz2 |
* rs6000-tdep.c (rs6000_frame_cache): Handle misdetected frameless
functions.
Diffstat (limited to 'gdb/rs6000-tdep.c')
-rw-r--r-- | gdb/rs6000-tdep.c | 75 |
1 files changed, 48 insertions, 27 deletions
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index 1fdf1dd..d302425 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -2852,6 +2852,7 @@ rs6000_frame_cache (struct frame_info *next_frame, void **this_cache) struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); struct rs6000_framedata fdata; int wordsize = tdep->wordsize; + CORE_ADDR func, pc; if ((*this_cache) != NULL) return (*this_cache); @@ -2859,35 +2860,55 @@ rs6000_frame_cache (struct frame_info *next_frame, void **this_cache) (*this_cache) = cache; cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); - skip_prologue (frame_func_unwind (next_frame), frame_pc_unwind (next_frame), - &fdata); - - /* If there were any saved registers, figure out parent's stack - pointer. */ - /* The following is true only if the frame doesn't have a call to - alloca(), FIXME. */ - - if (fdata.saved_fpr == 0 - && fdata.saved_gpr == 0 - && fdata.saved_vr == 0 - && fdata.saved_ev == 0 - && fdata.lr_offset == 0 - && fdata.cr_offset == 0 - && fdata.vr_offset == 0 - && fdata.ev_offset == 0) - cache->base = frame_unwind_register_unsigned (next_frame, SP_REGNUM); - else + func = frame_func_unwind (next_frame); + pc = frame_pc_unwind (next_frame); + skip_prologue (func, pc, &fdata); + + /* Figure out the parent's stack pointer. */ + + /* NOTE: cagney/2002-04-14: The ->frame points to the inner-most + address of the current frame. Things might be easier if the + ->frame pointed to the outer-most address of the frame. In + the mean time, the address of the prev frame is used as the + base address of this frame. */ + cache->base = frame_unwind_register_unsigned (next_frame, SP_REGNUM); + + /* If the function appears to be frameless, check a couple of likely + indicators that we have simply failed to find the frame setup. + Two common cases of this are missing symbols (i.e. + frame_func_unwind returns the wrong address or 0), and assembly + stubs which have a fast exit path but set up a frame on the slow + path. + + If the LR appears to return to this function, then presume that + we have an ABI compliant frame that we failed to find. */ + if (fdata.frameless && fdata.lr_offset == 0) { - /* NOTE: cagney/2002-04-14: The ->frame points to the inner-most - address of the current frame. Things might be easier if the - ->frame pointed to the outer-most address of the frame. In - the mean time, the address of the prev frame is used as the - base address of this frame. */ - cache->base = frame_unwind_register_unsigned (next_frame, SP_REGNUM); - if (!fdata.frameless) - /* Frameless really means stackless. */ - cache->base = read_memory_addr (cache->base, wordsize); + CORE_ADDR saved_lr; + int make_frame = 0; + + saved_lr = frame_unwind_register_unsigned (next_frame, + tdep->ppc_lr_regnum); + if (func == 0 && saved_lr == pc) + make_frame = 1; + else if (func != 0) + { + CORE_ADDR saved_func = get_pc_function_start (saved_lr); + if (func == saved_func) + make_frame = 1; + } + + if (make_frame) + { + fdata.frameless = 0; + fdata.lr_offset = wordsize; + } } + + if (!fdata.frameless) + /* Frameless really means stackless. */ + cache->base = read_memory_addr (cache->base, wordsize); + trad_frame_set_value (cache->saved_regs, SP_REGNUM, cache->base); /* if != -1, fdata.saved_fpr is the smallest number of saved_fpr. |