* mips-tdep.c (init_extra_frame_info): Check to see whether the

registers mentioned in the proc_desc have been saved.  This
	generalizes mips_in_lenient_prologue in the sense that we keep
	searching until we've found saves for all the registers, not just
	look for a "lenient prologue" pattern.
	* mips-tdep.c: #if 0 lenient prologue code.

	* mips-tdep.c (heuristic_proc_desc): Don't assume a host short
	is 16 bits.
This commit is contained in:
Jim Kingdon 1993-11-12 16:35:59 +00:00
parent 6fd1e9eeb1
commit 002a422b22
2 changed files with 98 additions and 34 deletions

View file

@ -1,3 +1,15 @@
Fri Nov 12 09:53:26 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
* mips-tdep.c (init_extra_frame_info): Check to see whether the
registers mentioned in the proc_desc have been saved. This
generalizes mips_in_lenient_prologue in the sense that we keep
searching until we've found saves for all the registers, not just
look for a "lenient prologue" pattern.
* mips-tdep.c: #if 0 lenient prologue code.
* mips-tdep.c (heuristic_proc_desc): Don't assume a host short
is 16 bits.
Thu Nov 11 19:58:05 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
* config/i386/i386sol2.mh: Comment out corelow.o.

View file

@ -34,7 +34,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#define VM_MIN_ADDRESS (unsigned)0x400000
#if 0
static int mips_in_lenient_prologue PARAMS ((CORE_ADDR, CORE_ADDR));
#endif
/* Some MIPS boards don't support floating point, so we permit the
user to turn it off. */
@ -210,16 +212,16 @@ heuristic_proc_desc(start_pc, limit_pc, next_frame)
else if ((word & 0xFFE00000) == 0xafa00000) { /* sw reg,offset($sp) */
int reg = (word & 0x001F0000) >> 16;
reg_mask |= 1 << reg;
temp_saved_regs.regs[reg] = sp + (short)word;
temp_saved_regs.regs[reg] = sp + (word & 0xffff);
}
else if ((word & 0xFFFF0000) == 0x27be0000) { /* addiu $30,$sp,size */
if ((unsigned short)word != frame_size)
reg30 = sp + (unsigned short)word;
if ((word & 0xffff) != frame_size)
reg30 = sp + (word & 0xffff);
else if (!has_frame_reg) {
int alloca_adjust;
has_frame_reg = 1;
reg30 = read_next_frame_reg(next_frame, 30);
alloca_adjust = reg30 - (sp + (unsigned short)word);
alloca_adjust = reg30 - (sp + (word & 0xffff));
if (alloca_adjust > 0) {
/* FP > SP + frame_size. This may be because
/* of an alloca or somethings similar.
@ -233,7 +235,7 @@ heuristic_proc_desc(start_pc, limit_pc, next_frame)
else if ((word & 0xFFE00000) == 0xafc00000) { /* sw reg,offset($30) */
int reg = (word & 0x001F0000) >> 16;
reg_mask |= 1 << reg;
temp_saved_regs.regs[reg] = reg30 + (short)word;
temp_saved_regs.regs[reg] = reg30 + (word & 0xffff);
}
}
if (has_frame_reg) {
@ -386,38 +388,26 @@ init_extra_frame_info(fci)
fci->frame = READ_FRAME_REG(fci, PROC_FRAME_REG(proc_desc))
+ PROC_FRAME_OFFSET(proc_desc);
/* If this is the innermost frame, and we are still in the
prologue (loosely defined), then the registers may not have
been saved yet. */
if (fci->next == NULL
&& !PROC_DESC_IS_DUMMY(proc_desc)
&& mips_in_lenient_prologue (PROC_LOW_ADDR (proc_desc), fci->pc))
{
/* Can't just say that the registers are not saved, because they
might get clobbered halfway through the prologue.
heuristic_proc_desc already has the right code to figure out
exactly what has been saved, so use it. As far as I know we
could be doing this (as we do on the 68k, for example)
regardless of whether we are in the prologue; I'm leaving in
the check for being in the prologue only out of conservatism
(I'm not sure whether heuristic_proc_desc handles all cases,
for example).
This stuff is ugly (and getting uglier by the minute). Probably
the best way to clean it up is to ignore the proc_desc's from
the symbols altogher, and get all the information we need by
examining the prologue (provided we can make the prologue
examining code good enough to get all the cases...). */
proc_desc =
heuristic_proc_desc (PROC_LOW_ADDR (proc_desc),
fci->pc,
fci->next);
}
if (proc_desc == &temp_proc_desc)
*fci->saved_regs = temp_saved_regs;
else
else if (/* In any frame other than the innermost, we assume that all
registers have been saved. This assumes that all register
saves in a function happen before the first function
call. */
fci->next != NULL
/* In a dummy frame we know exactly where things are saved. */
|| PROC_DESC_IS_DUMMY (proc_desc)
/* Not sure exactly what kernel_trap means, but if it means
the kernel saves the registers without a prologue doing it,
we better not examine the prologue to see whether registers
have been saved yet. */
|| kernel_trap)
{
/* All the registers which will be saved have been saved, so we
can believe the proc_desc. */
/* 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);
@ -441,6 +431,58 @@ init_extra_frame_info(fci)
reg_position -= 4;
}
}
else
{
/* We need to figure out whether the registers that the proc_desc
claims are saved have been saved yet. */
CORE_ADDR addr;
int status;
char buf[4];
unsigned long inst;
/* Bitmasks; set if the proc_desc claims the register is saved and we
haven't found a save instruction for it yet. */
unsigned long gen_mask, float_mask;
gen_mask = PROC_REG_MASK (proc_desc);
float_mask = PROC_FREG_MASK (proc_desc);
for (addr = PROC_LOW_ADDR (proc_desc);
addr < fci->pc && (gen_mask | float_mask);
addr += 4)
{
status = read_memory_nobpt (addr, buf, 4);
if (status)
memory_error (status, addr);
inst = extract_unsigned_integer (buf, 4);
if (/* sw reg,n($sp) */
(inst & 0xffe00000) == 0xafa00000
/* sw reg,n($r30) */
|| (inst & 0xffe00000) == 0xafc00000)
{
/* We assume that all saves are relative to the
PROC_FRAME_REG, which is what we used to set up
->frame. */
int reg = (inst & 0x001f0000) >> 16;
if (gen_mask & (1 << reg))
fci->saved_regs.regs[reg] = fci->frame + (inst & 0xffff);
gen_mask &= ~(1 << reg);
}
else if (/* swc1 freg,n($sp) */
(inst & 0xffe00000) == 0xe7a00000
/* swc1 freg,n($r30) */
(inst & 0xffe00000) == 0xe7c00000)
{
int reg = ((inst & 0x001f0000) >> 16);
if (float_mask & (1 << reg))
fci->saved_regs.regs[FP0_REGNUM + reg]
= fci->frame + (inst & 0xffff);
float_mask &= ~(1 << reg);
}
}
}
/* hack: if argument regs are saved, guess these contain args */
if ((PROC_REG_MASK(proc_desc) & 0xF0) == 0) fci->num_args = -1;
@ -773,6 +815,7 @@ mips_frame_num_args(fip)
return -1;
}
#if 0
/* Is this a branch with a delay slot? */
static int
is_delayed (insn)
@ -788,6 +831,7 @@ is_delayed (insn)
| INSN_COND_BRANCH_DELAY
| INSN_COND_BRANCH_LIKELY)));
}
#endif
/* To skip prologues, I use this predicate. Returns either PC itself
if the code at PC does not look like a function prologue; otherwise
@ -822,8 +866,10 @@ mips_skip_prologue (pc, lenient)
memory_error (status, pc + offset);
inst = extract_unsigned_integer (buf, 4);
#if 0
if (lenient && is_delayed (inst))
continue;
#endif
if ((inst & 0xffff0000) == 0x27bd0000) /* addiu $sp,$sp,offset */
seen_sp_adjust = 1;
@ -874,6 +920,11 @@ mips_skip_prologue (pc, lenient)
#endif
}
#if 0
/* The lenient prologue stuff should be superceded by the code in
init_extra_frame_info which looks to see whether the stores mentioned
in the proc_desc have actually taken place. */
/* Is address PC in the prologue (loosely defined) for function at
STARTADDR? */
@ -885,6 +936,7 @@ mips_in_lenient_prologue (startaddr, pc)
CORE_ADDR end_prologue = mips_skip_prologue (startaddr, 1);
return pc >= startaddr && pc < end_prologue;
}
#endif
/* Given a return value in `regbuf' with a type `valtype',
extract and copy its value into `valbuf'. */