* mips-tdep.c (mips_skip_prologue): New argument lenient.
Use read_memory_nobpt. (is_delayed, mips_in_lenient_prologue): New functions. (init_extra_frame_info): If in the prologue, don't use saved registers. * config/mips/tm-mips.h: Declare mips_skip_prologue.
This commit is contained in:
parent
0ffccbfb6c
commit
ee5fb95969
@ -1,5 +1,11 @@
|
||||
Sun Jul 18 15:22:45 1993 Jim Kingdon (kingdon@rtl.cygnus.com)
|
||||
|
||||
* mips-tdep.c (mips_skip_prologue): New argument lenient.
|
||||
Use read_memory_nobpt.
|
||||
(is_delayed, mips_in_lenient_prologue): New functions.
|
||||
(init_extra_frame_info): If in the prologue, don't use saved registers.
|
||||
* config/mips/tm-mips.h: Declare mips_skip_prologue.
|
||||
|
||||
* partial-stab.h (N_SO): Add the text offset to valu before, not after,
|
||||
passing it to END_PSYMTAB.
|
||||
|
||||
|
@ -42,7 +42,8 @@ extern int mips_fpu;
|
||||
/* Advance PC across any function entry prologue instructions
|
||||
to reach some "real" code. */
|
||||
|
||||
#define SKIP_PROLOGUE(pc) pc = mips_skip_prologue(pc)
|
||||
#define SKIP_PROLOGUE(pc) pc = mips_skip_prologue (pc, 0)
|
||||
extern CORE_ADDR mips_skip_prologue PARAMS ((CORE_ADDR addr, int lenient));
|
||||
|
||||
/* Immediately after a function call, return the saved pc.
|
||||
Can't always go through the frames for this because on some machines
|
||||
|
100
gdb/mips-tdep.c
100
gdb/mips-tdep.c
@ -30,8 +30,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include "symfile.h"
|
||||
#include "objfiles.h"
|
||||
|
||||
#include "opcode/mips.h"
|
||||
|
||||
#define VM_MIN_ADDRESS (unsigned)0x400000
|
||||
|
||||
static int mips_in_lenient_prologue PARAMS ((CORE_ADDR, CORE_ADDR));
|
||||
|
||||
/* Some MIPS boards don't support floating point, so we permit the
|
||||
user to turn it off. */
|
||||
int mips_fpu = 1;
|
||||
@ -315,14 +319,14 @@ init_extra_frame_info(fci)
|
||||
{
|
||||
extern struct obstack frame_cache_obstack;
|
||||
/* Use proc_desc calculated in frame_chain */
|
||||
mips_extra_func_info_t proc_desc = fci->next ? cached_proc_desc :
|
||||
find_proc_desc(fci->pc, fci->next);
|
||||
mips_extra_func_info_t proc_desc =
|
||||
fci->next ? cached_proc_desc : find_proc_desc(fci->pc, fci->next);
|
||||
|
||||
fci->saved_regs = (struct frame_saved_regs*)
|
||||
obstack_alloc (&frame_cache_obstack, sizeof(struct frame_saved_regs));
|
||||
bzero(fci->saved_regs, sizeof(struct frame_saved_regs));
|
||||
memset (fci->saved_regs, 0, sizeof (struct frame_saved_regs));
|
||||
fci->proc_desc =
|
||||
proc_desc == &temp_proc_desc ? 0 : proc_desc;
|
||||
proc_desc == &temp_proc_desc ? 0 : proc_desc;
|
||||
if (proc_desc)
|
||||
{
|
||||
int ireg;
|
||||
@ -339,32 +343,41 @@ init_extra_frame_info(fci)
|
||||
fci->frame = READ_FRAME_REG(fci, PROC_FRAME_REG(proc_desc))
|
||||
+ PROC_FRAME_OFFSET(proc_desc);
|
||||
|
||||
if (proc_desc == &temp_proc_desc)
|
||||
*fci->saved_regs = temp_saved_regs;
|
||||
/* If this is the innermost frame, and we are still in the
|
||||
prologue (loosely defined), then the registers may not have
|
||||
been saved yet. But they haven't been clobbered either, so
|
||||
it's fine to say they have not been saved. */
|
||||
if (fci->next == NULL
|
||||
&& mips_in_lenient_prologue (PROC_LOW_ADDR (proc_desc), fci->pc))
|
||||
/* We already zeroed the saved regs. */
|
||||
;
|
||||
else if (proc_desc == &temp_proc_desc)
|
||||
*fci->saved_regs = temp_saved_regs;
|
||||
else
|
||||
{
|
||||
{
|
||||
/* find which general-purpose registers were saved */
|
||||
reg_position = fci->frame + PROC_REG_OFFSET(proc_desc);
|
||||
mask = kernel_trap ? 0xFFFFFFFF : PROC_REG_MASK(proc_desc);
|
||||
for (ireg= 31; mask; --ireg, mask <<= 1)
|
||||
if (mask & 0x80000000)
|
||||
if (mask & 0x80000000)
|
||||
{
|
||||
fci->saved_regs->regs[ireg] = reg_position;
|
||||
reg_position -= 4;
|
||||
fci->saved_regs->regs[ireg] = reg_position;
|
||||
reg_position -= 4;
|
||||
}
|
||||
/* find which floating-point registers were saved */
|
||||
reg_position = fci->frame + PROC_FREG_OFFSET(proc_desc);
|
||||
/* The freg_offset points to where the first *double* register is saved.
|
||||
* So skip to the high-order word. */
|
||||
|
||||
/* The freg_offset points to where the first *double* register
|
||||
is saved. So skip to the high-order word. */
|
||||
reg_position += 4;
|
||||
mask = kernel_trap ? 0xFFFFFFFF : PROC_FREG_MASK(proc_desc);
|
||||
for (ireg = 31; mask; --ireg, mask <<= 1)
|
||||
if (mask & 0x80000000)
|
||||
if (mask & 0x80000000)
|
||||
{
|
||||
fci->saved_regs->regs[FP0_REGNUM+ireg] = reg_position;
|
||||
reg_position -= 4;
|
||||
fci->saved_regs->regs[FP0_REGNUM+ireg] = reg_position;
|
||||
reg_position -= 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* hack: if argument regs are saved, guess these contain args */
|
||||
if ((PROC_REG_MASK(proc_desc) & 0xF0) == 0) fci->num_args = -1;
|
||||
@ -692,14 +705,32 @@ mips_frame_num_args(fip)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* To skip prologues, I use this predicate. Returns either PC
|
||||
itself if the code at PC does not look like a function prologue;
|
||||
otherwise returns an address that (if we're lucky) follows
|
||||
the prologue. */
|
||||
/* Does this instruction involve use of a delay slot? */
|
||||
static int
|
||||
is_delayed (insn)
|
||||
unsigned long insn;
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < NUMOPCODES; ++i)
|
||||
if (mips_opcodes[i].pinfo != INSN_MACRO
|
||||
&& (insn & mips_opcodes[i].mask) == mips_opcodes[i].match)
|
||||
break;
|
||||
return i < NUMOPCODES && (mips_opcodes[i].pinfo & ANY_DELAY);
|
||||
}
|
||||
|
||||
/* To skip prologues, I use this predicate. Returns either PC itself
|
||||
if the code at PC does not look like a function prologue; otherwise
|
||||
returns an address that (if we're lucky) follows the prologue. If
|
||||
LENIENT, then we must skip everything which is involved in setting
|
||||
up the frame (it's OK to skip more, just so long as we don't skip
|
||||
anything which might clobber the registers which are being saved.
|
||||
We must skip more in the case where part of the prologue is in the
|
||||
delay slot of a non-prologue instruction). */
|
||||
|
||||
CORE_ADDR
|
||||
mips_skip_prologue(pc)
|
||||
mips_skip_prologue (pc, lenient)
|
||||
CORE_ADDR pc;
|
||||
int lenient;
|
||||
{
|
||||
struct symbol *f;
|
||||
struct block *b;
|
||||
@ -710,8 +741,19 @@ mips_skip_prologue(pc)
|
||||
/* Skip the typical prologue instructions. These are the stack adjustment
|
||||
instruction and the instructions that save registers on the stack
|
||||
or in the gcc frame. */
|
||||
for (offset = 0; offset < 100; offset += 4) {
|
||||
inst = read_memory_integer(pc + offset, 4);
|
||||
for (offset = 0; offset < 100; offset += 4)
|
||||
{
|
||||
char buf[4];
|
||||
int status;
|
||||
|
||||
status = read_memory_nobpt (pc + offset, buf, 4);
|
||||
if (status)
|
||||
memory_error (status, pc + offset);
|
||||
inst = extract_unsigned_integer (buf, 4);
|
||||
|
||||
if (lenient && is_delayed (inst))
|
||||
continue;
|
||||
|
||||
if ((inst & 0xffff0000) == 0x27bd0000) /* addiu $sp,$sp,offset */
|
||||
seen_sp_adjust = 1;
|
||||
else if ((inst & 0xFFE00000) == 0xAFA00000 && (inst & 0x001F0000))
|
||||
@ -761,6 +803,18 @@ mips_skip_prologue(pc)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Is address PC in the prologue (loosely defined) for function at
|
||||
STARTADDR? */
|
||||
|
||||
static int
|
||||
mips_in_lenient_prologue (startaddr, pc)
|
||||
CORE_ADDR startaddr;
|
||||
CORE_ADDR pc;
|
||||
{
|
||||
CORE_ADDR end_prologue = mips_skip_prologue (startaddr, 1);
|
||||
return pc >= startaddr && pc < end_prologue;
|
||||
}
|
||||
|
||||
/* Given a return value in `regbuf' with a type `valtype',
|
||||
extract and copy its value into `valbuf'. */
|
||||
void
|
||||
|
Loading…
Reference in New Issue
Block a user