* [RFA/sparc] Add handling of stack-check probes
@ 2007-03-28 22:49 Joel Brobecker
2007-03-29 4:21 ` Eli Zaretskii
2007-04-10 15:34 ` Daniel Jacobowitz
0 siblings, 2 replies; 4+ messages in thread
From: Joel Brobecker @ 2007-03-28 22:49 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1627 bytes --]
Hello,
GDB is currently unable to unwind past stack-check probes that are
inserted by the compiler when compiling with -stack-check. The attached
patch adds handling for the sequences currently emitted by GCC. Eric
Botcazou told us that they can take 3 forms:
1. A single probe
sethi <some immediate>,%g1
sub %sp, %g1, %g1
clr [%g1 - some immediate]
2. A small number of probes (at most 5)
sethi <some immediate>,%g1
sub %sp, %g1, %g1
clr [%g1]
add %g1, -<some immediate>, %g1
clr [%g1]
[...]
add %g1, -<some immediate>, %g1
clr [%g1]
clr [%g1 - some immediate]
3. A probing loop
sethi <some immediate>,%g1
sub %sp, %g1, %g1
sethi <some immediate>, %g4
sub %g1, %g4, %g4
cmp %g1, %g4
be <disp>
add %g1, -<some immediate>, %g1
ba <disp>
clr [%g1]
clr [%g4 - some immediate]
2007-03-28 Joel Brobecker <brobecker@adacore.com>
* sparc-tdep.c (X_RS2): New macro.
(sparc_skip_stack_check): New function.
(sparc_analyze_prologue): Adjust PC past stack probing
sequence if necessary.
Tested on sparc-solaris, no regression.
OK to apply?
Thanks,
--
Joel
PS: Do other people think that it is simpler for the human brain to understand
if (pc >= current_pc)
than
if (current_pc <= pc)
In other words, the boundary value is put on the rhs of the condition,
and the variable value is put on the lhs... It's just an aesthetic
consideration, but I can change it if others agree.
[-- Attachment #2: stack-check.diff --]
[-- Type: text/plain, Size: 5934 bytes --]
Index: sparc-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/sparc-tdep.c,v
retrieving revision 1.178
diff -u -p -r1.178 sparc-tdep.c
--- sparc-tdep.c 27 Feb 2007 20:17:19 -0000 1.178
+++ sparc-tdep.c 28 Mar 2007 22:44:30 -0000
@@ -82,6 +82,7 @@ struct regset;
#define X_IMM22(i) ((i) & 0x3fffff)
#define X_OP3(i) (((i) >> 19) & 0x3f)
#define X_RS1(i) (((i) >> 14) & 0x1f)
+#define X_RS2(i) ((i) & 0x1f)
#define X_I(i) (((i) >> 13) & 1)
/* Sign extension macros. */
#define X_DISP22(i) ((X_IMM22 (i) ^ 0x200000) - 0x200000)
@@ -571,6 +572,156 @@ sparc_alloc_frame_cache (void)
return cache;
}
+/* GCC generates several well-known sequences of instructions at the begining
+ of each function prologue when compiling with -fstack-check. If one of
+ such sequences starts at START_PC, then return the address of the
+ instruction immediately past this sequence. Otherwise, return START_PC. */
+
+static CORE_ADDR
+sparc_skip_stack_check (const CORE_ADDR start_pc)
+{
+ CORE_ADDR pc = start_pc;
+ unsigned long insn;
+ int offset_stack_checking_sequence = 0;
+
+ /* With GCC, all stack checking sequences begin with the same two
+ instructions. */
+
+ /* sethi <some immediate>,%g1 */
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+ if (!(X_OP (insn) == 0 && X_OP2 (insn) == 0x4 && X_RD (insn) == 1))
+ return start_pc;
+
+ /* sub %sp, %g1, %g1 */
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+ if (!(X_OP (insn) == 2 && X_OP3 (insn) == 0x4 && !X_I(insn)
+ && X_RD (insn) == 1 && X_RS1 (insn) == 14 && X_RS2 (insn) == 1))
+ return start_pc;
+
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+
+ /* First possible sequence:
+ [first two instructions above]
+ clr [%g1 - some immediate] */
+
+ /* clr [%g1 - some immediate] */
+ if (X_OP (insn) == 3 && X_OP3(insn) == 0x4 && X_I(insn)
+ && X_RS1 (insn) == 1 && X_RD (insn) == 0)
+ {
+ /* Valid stack-check sequence, return the new PC. */
+ return pc;
+ }
+
+ /* Second possible sequence: A small number of probes.
+ [first two instructions above]
+ clr [%g1]
+ add %g1, -<some immediate>, %g1
+ clr [%g1]
+ [repeat the two instructions above any (small) number of times]
+ clr [%g1 - some immediate] */
+
+ /* clr [%g1] */
+ else if (X_OP (insn) == 3 && X_OP3(insn) == 0x4 && !X_I(insn)
+ && X_RS1 (insn) == 1 && X_RD (insn) == 0)
+ {
+ while (1)
+ {
+ /* add %g1, -<some immediate>, %g1 */
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+ if (!(X_OP (insn) == 2 && X_OP3(insn) == 0 && X_I(insn)
+ && X_RS1 (insn) == 1 && X_RD (insn) == 1))
+ break;
+
+ /* clr [%g1] */
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+ if (!(X_OP (insn) == 3 && X_OP3(insn) == 0x4 && !X_I(insn)
+ && X_RD (insn) == 0 && X_RS1 (insn) == 1))
+ return start_pc;
+ }
+
+ /* clr [%g1 - some immediate] */
+ if (!(X_OP (insn) == 3 && X_OP3(insn) == 0x4 && X_I(insn)
+ && X_RS1 (insn) == 1 && X_RD (insn) == 0))
+ return start_pc;
+
+ /* We found a valid stack-check sequence, return the new PC. */
+ return pc;
+ }
+
+ /* Third sequence: A probing loop.
+ [first two instructions above]
+ sethi <some immediate>, %g4
+ sub %g1, %g4, %g4
+ cmp %g1, %g4
+ be <disp>
+ add %g1, -<some immediate>, %g1
+ ba <disp>
+ clr [%g1]
+ clr [%g4 - some immediate] */
+
+ /* sethi <some immediate>, %g4 */
+ else if (X_OP (insn) == 0 && X_OP2 (insn) == 0x4 && X_RD (insn) == 4)
+ {
+ /* sub %g1, %g4, %g4 */
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+ if (!(X_OP (insn) == 2 && X_OP3 (insn) == 0x4 && !X_I(insn)
+ && X_RD (insn) == 4 && X_RS1 (insn) == 1 && X_RS2 (insn) == 4))
+ return start_pc;
+
+ /* cmp %g1, %g4 */
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+ if (!(X_OP (insn) == 2 && X_OP3 (insn) == 0x14 && !X_I(insn)
+ && X_RD (insn) == 0 && X_RS1 (insn) == 1 && X_RS2 (insn) == 4))
+ return start_pc;
+
+ /* be <disp> */
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+ if (!(X_OP (insn) == 0 && X_COND (insn) == 0x1))
+ return start_pc;
+
+ /* add %g1, -<some immediate>, %g1 */
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+ if (!(X_OP (insn) == 2 && X_OP3(insn) == 0 && X_I(insn)
+ && X_RS1 (insn) == 1 && X_RD (insn) == 1))
+ return start_pc;
+
+ /* ba <disp> */
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+ if (!(X_OP (insn) == 0 && X_COND (insn) == 0x8))
+ return start_pc;
+
+ /* clr [%g1] */
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+ if (!(X_OP (insn) == 3 && X_OP3(insn) == 0x4 && !X_I(insn)
+ && X_RD (insn) == 0 && X_RS1 (insn) == 1))
+ return start_pc;
+
+ /* clr [%g4 - some immediate] */
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+ if (!(X_OP (insn) == 3 && X_OP3(insn) == 0x4 && X_I(insn)
+ && X_RS1 (insn) == 4 && X_RD (insn) == 0))
+ return start_pc;
+
+ /* We found a valid stack-check sequence, return the new PC. */
+ return pc;
+ }
+
+ /* No stack check code in our prologue, return the start_pc. */
+ return start_pc;
+}
+
CORE_ADDR
sparc_analyze_prologue (CORE_ADDR pc, CORE_ADDR current_pc,
struct sparc_frame_cache *cache)
@@ -580,6 +731,8 @@ sparc_analyze_prologue (CORE_ADDR pc, CO
int offset = 0;
int dest = -1;
+ pc = sparc_skip_stack_check (pc);
+
if (current_pc <= pc)
return current_pc;
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFA/sparc] Add handling of stack-check probes
2007-03-28 22:49 [RFA/sparc] Add handling of stack-check probes Joel Brobecker
@ 2007-03-29 4:21 ` Eli Zaretskii
2007-04-10 15:34 ` Daniel Jacobowitz
1 sibling, 0 replies; 4+ messages in thread
From: Eli Zaretskii @ 2007-03-29 4:21 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
> Date: Wed, 28 Mar 2007 15:50:13 -0700
> From: Joel Brobecker <brobecker@adacore.com>
>
> PS: Do other people think that it is simpler for the human brain to understand
> if (pc >= current_pc)
> than
> if (current_pc <= pc)
>
> In other words, the boundary value is put on the rhs of the condition,
> and the variable value is put on the lhs... It's just an aesthetic
> consideration, but I can change it if others agree.
I prefer the variable to be on the left and the boundary on the right.
The only case where it is justified to reverse the order is when you
use ==, to avoid the frequent typo that uses only one `='.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFA/sparc] Add handling of stack-check probes
2007-03-28 22:49 [RFA/sparc] Add handling of stack-check probes Joel Brobecker
2007-03-29 4:21 ` Eli Zaretskii
@ 2007-04-10 15:34 ` Daniel Jacobowitz
2007-04-11 7:11 ` Joel Brobecker
1 sibling, 1 reply; 4+ messages in thread
From: Daniel Jacobowitz @ 2007-04-10 15:34 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
On Wed, Mar 28, 2007 at 03:50:13PM -0700, Joel Brobecker wrote:
> Hello,
>
> GDB is currently unable to unwind past stack-check probes that are
> inserted by the compiler when compiling with -stack-check. The attached
> patch adds handling for the sequences currently emitted by GCC. Eric
> Botcazou told us that they can take 3 forms:
The patch seems right to me, though I don't know too much about SPARC.
> 2007-03-28 Joel Brobecker <brobecker@adacore.com>
>
> * sparc-tdep.c (X_RS2): New macro.
> (sparc_skip_stack_check): New function.
> (sparc_analyze_prologue): Adjust PC past stack probing
> sequence if necessary.
>
> Tested on sparc-solaris, no regression.
> OK to apply?
Yes, go ahead.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFA/sparc] Add handling of stack-check probes
2007-04-10 15:34 ` Daniel Jacobowitz
@ 2007-04-11 7:11 ` Joel Brobecker
0 siblings, 0 replies; 4+ messages in thread
From: Joel Brobecker @ 2007-04-11 7:11 UTC (permalink / raw)
To: gdb-patches
> > 2007-03-28 Joel Brobecker <brobecker@adacore.com>
> >
> > * sparc-tdep.c (X_RS2): New macro.
> > (sparc_skip_stack_check): New function.
> > (sparc_analyze_prologue): Adjust PC past stack probing
> > sequence if necessary.
> >
> > Tested on sparc-solaris, no regression.
> > OK to apply?
>
> Yes, go ahead.
Thank you! Now checked in.
--
Joel
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2007-04-11 7:11 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-03-28 22:49 [RFA/sparc] Add handling of stack-check probes Joel Brobecker
2007-03-29 4:21 ` Eli Zaretskii
2007-04-10 15:34 ` Daniel Jacobowitz
2007-04-11 7:11 ` Joel Brobecker
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox