diff options
author | Per Bothner <per@bothner.com> | 1992-03-02 01:55:31 +0000 |
---|---|---|
committer | Per Bothner <per@bothner.com> | 1992-03-02 01:55:31 +0000 |
commit | 6c6afbb92bc10dbb693e8e74804cdffa8de65521 (patch) | |
tree | 56fd0e1a800a17cd3dfe2a4eb55d192253006ec2 /gdb/rs6000-xdep.c | |
parent | 4b8333decafe6c9495555aaecae4c392bdae1874 (diff) | |
download | gdb-6c6afbb92bc10dbb693e8e74804cdffa8de65521.zip gdb-6c6afbb92bc10dbb693e8e74804cdffa8de65521.tar.gz gdb-6c6afbb92bc10dbb693e8e74804cdffa8de65521.tar.bz2 |
More changes, mostly from IBM for rs6000. (See ChangeLog.)
Diffstat (limited to 'gdb/rs6000-xdep.c')
-rw-r--r-- | gdb/rs6000-xdep.c | 105 |
1 files changed, 102 insertions, 3 deletions
diff --git a/gdb/rs6000-xdep.c b/gdb/rs6000-xdep.c index 7f14dfa..afb24c6 100644 --- a/gdb/rs6000-xdep.c +++ b/gdb/rs6000-xdep.c @@ -227,7 +227,7 @@ frameless_function_invocation (fi) struct frame_info *fi; { CORE_ADDR func_start; - int frameless, dummy; + struct aix_framedata fdata; func_start = get_pc_function_start (fi->pc) + FUNCTION_START_OFFSET; @@ -237,11 +237,110 @@ struct frame_info *fi; if (!func_start) return 0; - function_frame_info (func_start, &frameless, &dummy, &dummy, &dummy); - return frameless; + function_frame_info (func_start, &fdata); + return fdata.frameless; } +/* Return the address of a frame. This is the inital %sp value when the frame + was first allocated. For functions calling alloca(), it might be saved in + an alloca register. */ + +CORE_ADDR +frame_initial_stack_address (fi) +struct frame_info *fi; +{ + CORE_ADDR frame_addr, tmpaddr; + struct aix_framedata fdata; + struct frame_info *callee_fi; + int ii; + + extern struct obstack frame_cache_obstack; + + /* if the initial stack pointer (frame address) of this frame is known, + just return it. */ + + if (fi->initial_sp) + return fi->initial_sp; + + /* find out if this function is using an alloca register.. */ + + tmpaddr = get_pc_function_start (fi->pc); + function_frame_info (tmpaddr, &fdata); + + /* if saved registers of this frame are not known yet, read and cache them. */ + + if (!fi->cache_fsr) { + fi->cache_fsr = (struct frame_saved_regs *) + obstack_alloc (&frame_cache_obstack, sizeof (struct frame_saved_regs)); + bzero (fi->cache_fsr, sizeof (struct frame_saved_regs)); + + if (fi->prev && fi->prev->frame) + frame_addr = fi->prev->frame; + else + frame_addr = read_memory_integer (fi->frame, 4); + + /* if != -1, fdata.saved_fpr is the smallest number of saved_fpr. All fpr's + from saved_fpr to fp31 are saved right underneath caller stack pointer, + starting from fp31 first. */ + + if (fdata.saved_fpr >= 0) { + for (ii=31; ii >= fdata.saved_fpr; --ii) + fi->cache_fsr->regs [FP0_REGNUM + ii] = frame_addr - ((32 - ii) * 8); + frame_addr -= (32 - fdata.saved_fpr) * 8; + } + + /* if != -1, fdata.saved_gpr is the smallest number of saved_gpr. All gpr's + from saved_gpr to gpr31 are saved right under saved fprs, starting + from r31 first. */ + + if (fdata.saved_gpr >= 0) + for (ii=31; ii >= fdata.saved_gpr; --ii) + fi->cache_fsr->regs [ii] = frame_addr - ((32 - ii) * 4); + } + + /* If no alloca register used, then fi->frame is the value of the %sp for + this frame, and it is good enough. */ + + if (fdata.alloca_reg < 0) { + fi->initial_sp = fi->frame; + return fi->initial_sp; + } + + /* This function has an alloca register. If this is the top-most frame + (with the lowest address), the value in alloca register is good. */ + + if (!fi->next) + return fi->initial_sp = read_register (fdata.alloca_reg); + + /* Otherwise, this is a caller frame. Callee has already saved (???) its + registers. Find the address in which caller's alloca register is saved. */ + + for (callee_fi = fi->next; callee_fi; callee_fi = callee_fi->next) { + + if (!callee_fi->cache_fsr) + fatal ("Callee has not saved caller's registers."); + + /* this is the address in which alloca register is saved. */ + + tmpaddr = callee_fi->cache_fsr->regs [fdata.alloca_reg]; + if (tmpaddr) { + fi->initial_sp = read_memory_integer (tmpaddr, 4); + return fi->initial_sp; + } + + /* Go look into deeper levels of the frame chain to see if any one of + the callees has saved alloca register. */ + } + + /* If alloca register was not saved, by the callee (or any of its callees) + then the value in the register is still good. */ + + return fi->initial_sp = read_register (fdata.alloca_reg); +} + + + /* aixcoff_relocate_symtab - hook for symbol table relocation. also reads shared libraries.. */ |