* [RFA/mips] merge mips32_skip_prologue into mips32_scan_prologue
@ 2004-10-11 5:51 Joel Brobecker
2004-10-12 21:17 ` Andrew Cagney
0 siblings, 1 reply; 3+ messages in thread
From: Joel Brobecker @ 2004-10-11 5:51 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1924 bytes --]
This patch covers mips32 only for now, but mips16 will follow shortly
once the principle is approved.
2004-10-11 Joel Brobecker <brobecker@gnat.com>
* mips-tdep.c (mips32_scan_prologue): Merge code from
mips32_skip_prologue. Now return the address of the first
instruction past the function prologue.
(mips32_skip_prologue): Remove. No longer necessary.
(mips16_skip_prologue): Add parameter end_pc instead of
computing it.
(mips_skip_prologue): Compute the upper limit for the
prologue scanning. Update call to mips16_skip_prologue.
Replace call to mips32_skip_prologue by call to
mips32_scan_prologue.
A few remarks:
- The change of prototype for mips16_skip_prologue is not really
necessary, as this function will be removed at the next iteration.
It was just a change I made to make it clearer for me where the
code was going, at how I was to avoid code duplication. I can
remove this change from this patch, if necessary.
- What do you think of this FIXME?
+ /* FIXME: brobecker/2004-10-10: Can't we just break out of this
+ loop now? Why would we need to continue scanning the function
+ instructions? */
+ if (end_prologue_addr == 0)
+ end_prologue_addr = cur_pc;
Running the testsuite on our IRIX machine is a bit longish
right now (we have nightly builds running right now), so I didn't
give this idea a short at the testsuite yet. But I don't see any
reason for us to keep going in this loop if we've determined that
we're past the prologue. Unless we want to take into account any
subsequent instructions in the function body that would move the
location of registers, etc? I can test this idea tomorrow, when
the CPU usage is lighter on the machine.
Tested on mips-irix, no regression. OK to commit?
Thanks,
--
Joel
[-- Attachment #2: mips-tdep.c.diff --]
[-- Type: text/plain, Size: 9905 bytes --]
Index: mips-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/mips-tdep.c,v
retrieving revision 1.331
diff -u -p -r1.331 mips-tdep.c
--- mips-tdep.c 11 Oct 2004 02:27:13 -0000 1.331
+++ mips-tdep.c 11 Oct 2004 05:39:37 -0000
@@ -2419,9 +2419,10 @@ reset_saved_regs (struct mips_frame_cach
}
/* Analyze the function prologue from START_PC to LIMIT_PC. Builds
- the associated FRAME_CACHE if not null. */
+ the associated FRAME_CACHE if not null.
+ Return the address of the first instruction past the prologue. */
-static void
+static CORE_ADDR
mips32_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc, CORE_ADDR sp,
struct frame_info *next_frame,
struct mips_frame_cache *this_cache)
@@ -2431,6 +2432,10 @@ mips32_scan_prologue (CORE_ADDR start_pc
long frame_offset;
int frame_reg = MIPS_SP_REGNUM;
+ CORE_ADDR end_prologue_addr = 0;
+ int seen_sp_adjust = 0;
+ int load_immediate_bytes = 0;
+
restart:
frame_offset = 0;
@@ -2458,6 +2463,7 @@ restart:
usually means that the stack cleanup code in the function
epilogue is reached. */
break;
+ seen_sp_adjust = 1;
}
else if ((high_word & 0xFFE0) == 0xafa0) /* sw reg,offset($sp) */
{
@@ -2465,8 +2471,7 @@ restart:
}
else if ((high_word & 0xFFE0) == 0xffa0) /* sd reg,offset($sp) */
{
- /* Irix 6.2 N32 ABI uses sd instructions for saving $gp and
- $ra. */
+ /* Irix 6.2 N32 ABI uses sd instructions for saving $gp and $ra. */
set_reg_offset (this_cache, reg, sp + low_word);
}
else if (high_word == 0x27be) /* addiu $30,$sp,size */
@@ -2528,6 +2533,45 @@ restart:
{
set_reg_offset (this_cache, reg, frame_addr + low_word);
}
+ else if ((high_word & 0xFFE0) == 0xE7A0 /* swc1 freg,n($sp) */
+ || (high_word & 0xF3E0) == 0xA3C0 /* sx reg,n($s8) */
+ || (inst & 0xFF9F07FF) == 0x00800021 /* move reg,$a0-$a3 */
+ || high_word == 0x3c1c /* lui $gp,n */
+ || high_word == 0x279c /* addiu $gp,$gp,n */
+ || inst == 0x0399e021 /* addu $gp,$gp,$t9 */
+ || inst == 0x033ce021 /* addu $gp,$t9,$gp */
+ )
+ {
+ /* These instructions are part of the prologue, but we don't
+ need to do anything special to handle them. */
+ }
+ /* The instructions below load $at or $t0 with an immediate
+ value in preparation for a stack adjustment via
+ subu $sp,$sp,[$at,$t0]. These instructions could also
+ initialize a local variable, so we accept them only before
+ a stack adjustment instruction was seen. */
+ else if (!seen_sp_adjust
+ && (high_word == 0x3c01 /* lui $at,n */
+ || high_word == 0x3c08 /* lui $t0,n */
+ || high_word == 0x3421 /* ori $at,$at,n */
+ || high_word == 0x3508 /* ori $t0,$t0,n */
+ || high_word == 0x3401 /* ori $at,$zero,n */
+ || high_word == 0x3408 /* ori $t0,$zero,n */
+ ))
+ {
+ load_immediate_bytes += MIPS_INSTLEN; /* FIXME!! */
+ }
+ else
+ {
+ /* This instruction is not an instruction typically found
+ in a prologue, so we must have reached the end of the
+ prologue. */
+ /* FIXME: brobecker/2004-10-10: Can't we just break out of this
+ loop now? Why would we need to continue scanning the function
+ instructions? */
+ if (end_prologue_addr == 0)
+ end_prologue_addr = cur_pc;
+ }
}
if (this_cache != NULL)
@@ -2541,6 +2585,23 @@ restart:
this_cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->pc]
= this_cache->saved_regs[NUM_REGS + RA_REGNUM];
}
+
+ /* If we didn't reach the end of the prologue when scanning the function
+ instructions, then set end_prologue_addr to the address of the
+ instruction immediately after the last one we scanned. */
+ /* brobecker/2004-10-10: I don't think this would ever happen, but
+ we may as well be careful and do our best if we have a null
+ end_prologue_addr. */
+ if (end_prologue_addr == 0)
+ end_prologue_addr = cur_pc;
+
+ /* In a frameless function, we might have incorrectly
+ skipped some load immediate instructions. Undo the skipping
+ if the load immediate was not followed by a stack adjustment. */
+ if (load_immediate_bytes && !seen_sp_adjust)
+ end_prologue_addr -= load_immediate_bytes;
+
+ return end_prologue_addr;
}
static mips_extra_func_info_t
@@ -4860,107 +4921,12 @@ mips_step_skips_delay (CORE_ADDR pc)
extract_unsigned_integer (buf, MIPS_INSTLEN));
}
-/* Skip the PC past function prologue instructions (32-bit version).
- This is a helper function for mips_skip_prologue. */
-
-static CORE_ADDR
-mips32_skip_prologue (CORE_ADDR pc)
-{
- t_inst inst;
- CORE_ADDR end_pc;
- int seen_sp_adjust = 0;
- int load_immediate_bytes = 0;
-
- /* Find an upper bound on the prologue. */
- end_pc = skip_prologue_using_sal (pc);
- if (end_pc == 0)
- end_pc = pc + 100; /* Magic. */
-
- /* 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 (; pc < end_pc; pc += MIPS_INSTLEN)
- {
- unsigned long high_word;
-
- inst = mips_fetch_instruction (pc);
- high_word = (inst >> 16) & 0xffff;
-
- if (high_word == 0x27bd /* addiu $sp,$sp,offset */
- || high_word == 0x67bd) /* daddiu $sp,$sp,offset */
- seen_sp_adjust = 1;
- else if (inst == 0x03a1e823 || /* subu $sp,$sp,$at */
- inst == 0x03a8e823) /* subu $sp,$sp,$t0 */
- seen_sp_adjust = 1;
- else if (((inst & 0xFFE00000) == 0xAFA00000 /* sw reg,n($sp) */
- || (inst & 0xFFE00000) == 0xFFA00000) /* sd reg,n($sp) */
- && (inst & 0x001F0000)) /* reg != $zero */
- continue;
-
- else if ((inst & 0xFFE00000) == 0xE7A00000) /* swc1 freg,n($sp) */
- continue;
- else if ((inst & 0xF3E00000) == 0xA3C00000 && (inst & 0x001F0000))
- /* sx reg,n($s8) */
- continue; /* reg != $zero */
-
- /* move $s8,$sp. With different versions of gas this will be either
- `addu $s8,$sp,$zero' or `or $s8,$sp,$zero' or `daddu s8,sp,$0'.
- Accept any one of these. */
- else if (inst == 0x03A0F021 || inst == 0x03a0f025 || inst == 0x03a0f02d)
- continue;
-
- else if ((inst & 0xFF9F07FF) == 0x00800021) /* move reg,$a0-$a3 */
- continue;
- else if (high_word == 0x3c1c) /* lui $gp,n */
- continue;
- else if (high_word == 0x279c) /* addiu $gp,$gp,n */
- continue;
- else if (inst == 0x0399e021 /* addu $gp,$gp,$t9 */
- || inst == 0x033ce021) /* addu $gp,$t9,$gp */
- continue;
- /* The following instructions load $at or $t0 with an immediate
- value in preparation for a stack adjustment via
- subu $sp,$sp,[$at,$t0]. These instructions could also initialize
- a local variable, so we accept them only before a stack adjustment
- instruction was seen. */
- else if (!seen_sp_adjust)
- {
- if (high_word == 0x3c01 || /* lui $at,n */
- high_word == 0x3c08) /* lui $t0,n */
- {
- load_immediate_bytes += MIPS_INSTLEN; /* FIXME!! */
- continue;
- }
- else if (high_word == 0x3421 || /* ori $at,$at,n */
- high_word == 0x3508 || /* ori $t0,$t0,n */
- high_word == 0x3401 || /* ori $at,$zero,n */
- high_word == 0x3408) /* ori $t0,$zero,n */
- {
- load_immediate_bytes += MIPS_INSTLEN; /* FIXME!! */
- continue;
- }
- else
- break;
- }
- else
- break;
- }
-
- /* In a frameless function, we might have incorrectly
- skipped some load immediate instructions. Undo the skipping
- if the load immediate was not followed by a stack adjustment. */
- if (load_immediate_bytes && !seen_sp_adjust)
- pc -= load_immediate_bytes;
- return pc;
-}
-
/* Skip the PC past function prologue instructions (16-bit version).
This is a helper function for mips_skip_prologue. */
static CORE_ADDR
-mips16_skip_prologue (CORE_ADDR pc)
+mips16_skip_prologue (CORE_ADDR pc, CORE_ADDR end_pc)
{
- CORE_ADDR end_pc;
int extend_bytes = 0;
int prev_extend_bytes;
@@ -5009,11 +4975,6 @@ mips16_skip_prologue (CORE_ADDR pc)
0, 0} /* end of table marker */
};
- /* Find an upper bound on the prologue. */
- end_pc = skip_prologue_using_sal (pc);
- if (end_pc == 0)
- end_pc = pc + 100; /* Magic. */
-
/* 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. */
@@ -5070,6 +5031,7 @@ mips_skip_prologue (CORE_ADDR pc)
is greater. */
CORE_ADDR post_prologue_pc = after_prologue (pc);
+ CORE_ADDR limit_pc;
if (post_prologue_pc != 0)
return max (pc, post_prologue_pc);
@@ -5077,10 +5039,17 @@ mips_skip_prologue (CORE_ADDR pc)
/* Can't determine prologue from the symbol table, need to examine
instructions. */
+ /* Find an upper limit on the function prologue using the debug
+ information. If the debug information could not be used to provide
+ that bound, then use an arbitrary large number as the upper bound. */
+ limit_pc = skip_prologue_using_sal (pc);
+ if (limit_pc == 0)
+ limit_pc = pc + 100; /* Magic. */
+
if (pc_is_mips16 (pc))
- return mips16_skip_prologue (pc);
+ return mips16_skip_prologue (pc, limit_pc);
else
- return mips32_skip_prologue (pc);
+ return mips32_scan_prologue (pc, limit_pc, 0, NULL, NULL);
}
/* Root of all "set mips "/"show mips " commands. This will eventually be
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [RFA/mips] merge mips32_skip_prologue into mips32_scan_prologue
2004-10-11 5:51 [RFA/mips] merge mips32_skip_prologue into mips32_scan_prologue Joel Brobecker
@ 2004-10-12 21:17 ` Andrew Cagney
2004-10-14 22:37 ` Joel Brobecker
0 siblings, 1 reply; 3+ messages in thread
From: Andrew Cagney @ 2004-10-12 21:17 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
> This patch covers mips32 only for now, but mips16 will follow shortly
> once the principle is approved.
>
> 2004-10-11 Joel Brobecker <brobecker@gnat.com>
>
> * mips-tdep.c (mips32_scan_prologue): Merge code from
> mips32_skip_prologue. Now return the address of the first
> instruction past the function prologue.
> (mips32_skip_prologue): Remove. No longer necessary.
> (mips16_skip_prologue): Add parameter end_pc instead of
> computing it.
> (mips_skip_prologue): Compute the upper limit for the
> prologue scanning. Update call to mips16_skip_prologue.
> Replace call to mips32_skip_prologue by call to
> mips32_scan_prologue.
>
> A few remarks:
>
> - The change of prototype for mips16_skip_prologue is not really
> necessary, as this function will be removed at the next iteration.
> It was just a change I made to make it clearer for me where the
> code was going, at how I was to avoid code duplication. I can
> remove this change from this patch, if necessary.
M'kay.
> - What do you think of this FIXME?
>
> + /* FIXME: brobecker/2004-10-10: Can't we just break out of this
> + loop now? Why would we need to continue scanning the function
> + instructions? */
> + if (end_prologue_addr == 0)
> + end_prologue_addr = cur_pc;
>
> Running the testsuite on our IRIX machine is a bit longish
> right now (we have nightly builds running right now), so I didn't
> give this idea a short at the testsuite yet. But I don't see any
> reason for us to keep going in this loop if we've determined that
> we're past the prologue. Unless we want to take into account any
> subsequent instructions in the function body that would move the
> location of registers, etc? I can test this idea tomorrow, when
> the CPU usage is lighter on the machine.
My understanding is that there are two cases:
- skipping the prologue (i.e., finding the end)
Yes, bail
- scanning the prologue
historically scanners had this habit of scanning beyond the
end-of-prologue (and sometimes beyond the current PC -> big oops for
that one!), sometimes it was a mistake, sometimes it was deliberate
trying to handle optomized code
GDB should behave consistently, so yes, I think it should bail. Complex
prologues can be handled by mdebug or dwarf2.
> Tested on mips-irix, no regression. OK to commit?
Yes, and also ok to follow-on patches at this incremental level.
thanks for this,
Andrew
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [RFA/mips] merge mips32_skip_prologue into mips32_scan_prologue
2004-10-12 21:17 ` Andrew Cagney
@ 2004-10-14 22:37 ` Joel Brobecker
0 siblings, 0 replies; 3+ messages in thread
From: Joel Brobecker @ 2004-10-14 22:37 UTC (permalink / raw)
To: Andrew Cagney; +Cc: gdb-patches
> >2004-10-11 Joel Brobecker <brobecker@gnat.com>
> >
> > * mips-tdep.c (mips32_scan_prologue): Merge code from
> > mips32_skip_prologue. Now return the address of the first
> > instruction past the function prologue.
> > (mips32_skip_prologue): Remove. No longer necessary.
> > (mips16_skip_prologue): Add parameter end_pc instead of
> > computing it.
> > (mips_skip_prologue): Compute the upper limit for the
> > prologue scanning. Update call to mips16_skip_prologue.
> > Replace call to mips32_skip_prologue by call to
> > mips32_scan_prologue.
> Yes, and also ok to follow-on patches at this incremental level.
Thanks! This one has been committed. I will work on the mips16
equivalent, and then look at the couple of items raised in this
thread.
--
Joel
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2004-10-14 22:37 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-10-11 5:51 [RFA/mips] merge mips32_skip_prologue into mips32_scan_prologue Joel Brobecker
2004-10-12 21:17 ` Andrew Cagney
2004-10-14 22:37 ` Joel Brobecker
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox