* newbie: labels headache
@ 1998-10-15 21:35 Alexander Kjeldaas
1998-10-19 20:14 ` Jeffrey A Law
0 siblings, 1 reply; 2+ messages in thread
From: Alexander Kjeldaas @ 1998-10-15 21:35 UTC (permalink / raw)
To: egcs
Hi, I've tried to rewrite the StackGuard patch for egcs but when I
compile the program with -O2, the label guarding the 'call abort'
instruction is removed, which makes the assembler complain. I'd be
happy if someone could clue me in about my wrongdoings in the
following. This is my first gcc hack so please be gentle :-).
This is what I do in the epilogue code:
(in ix86_expand_epilogue):
[..lots of stuff..]
rts reg = gen_rtx(REG, SImode, 1);
stack_protect_label = gen_label_rtx();
/* documentation suggests this might convince gcc into
not removing the label, but it doesn't work */
LABEL_PRESERVE_P(stack_protect_label) = 1;
rtx null = GEN_INT(0);
emit_cmp_insn (reg, null, EQ, NULL_RTX, GET_MODE(reg), 0, 0);
emit_jump_insn (gen_bne (stack_protect_label));
[.. here the 'ret' instruction is emitted by egcs ..]
rtx savior = gen_rtx (MEM, FUNCTION_MODE,
gen_rtx(SYMBOL_REF, Pmode, "abort"));
emit_label_after(stack_protect_label, get_insns()); <-- (*) PROBLEM
emit_call_insn (gen_call (savior, GEN_INT(0), NULL_RTX, 0));
The following is my test-case:
void humbug(char *s) {
char buf[10];
printf("\"%s\"\n", s);
strcpy(buf, s);
}
Now, tin the non-optimized case, the code produced does the following:
[gcc -fstack-null-protect -S test.c]
humbug:
pushl $0
pushl %ebp
movl %esp,%ebp
subl $12,%esp
movl 12(%ebp),%eax
pushl %eax
pushl $.LC0
call printf
addl $8,%esp
movl 12(%ebp),%eax
pushl %eax
leal -12(%ebp),%eax
pushl %eax
call strcpy
addl $8,%esp
.L1:
movl %ebp,%esp
popl %ebp
popl %edx <- canary test
testl %edx,%edx ...
jne .L2 ...
ret
.L2:
call abort
Now, with -O2 the following is produced:
[gcc -fstack-null-protect -O2 -S test.c]
humbug:
pushl $0
pushl %ebp
movl %esp,%ebp
subl $12,%esp
pushl %ebx
movl 12(%ebp),%ebx
pushl %ebx
pushl $.LC0
call printf
pushl %ebx
leal -12(%ebp),%eax
pushl %eax
call strcpy
movl -16(%ebp),%ebx
movl %ebp,%esp
popl %ebp
popl %edx
testl %edx,%edx
jne .L2
ret
call abort <-- where's the label???
Here's the patch (relative to 1.0.3a)
diff -ur egcs-1.0.3a/gcc/config/i386/i386.c egcs-1.0.3a.new/gcc/config/i386/i386.c
--- egcs-1.0.3a/gcc/config/i386/i386.c Tue May 5 02:40:04 1998
+++ egcs-1.0.3a.new/gcc/config/i386/i386.c Fri Oct 16 02:22:35 1998
@@ -103,6 +103,7 @@
extern FILE *asm_out_file;
extern char *strcat ();
+extern int stack_protect;
char *singlemove_string ();
char *output_move_const_single ();
@@ -1815,6 +1816,7 @@
\f
+static int canaryval = 0;
static rtx pic_label_rtx;
static char pic_label_name [256];
static int pic_label_no = 0;
@@ -1855,6 +1857,8 @@
/* Set up the stack and frame (if desired) for the function. */
+#define debug_stack(x...)
+
void
function_prologue (file, size)
FILE *file;
@@ -1868,6 +1872,15 @@
long tsize = get_frame_size ();
int cfa_offset = INCOMING_FRAME_SP_OFFSET, cfa_store_offset = cfa_offset;
+ if (stack_protect == 2)
+ {
+ canaryval = (canaryval+4) % 512;
+ xops[0] = GEN_INT(canaryval);
+ output_asm_insn("pushl %0(__canary)", xops);
+ }
+ else if (stack_protect == 1)
+ output_asm_insn ("pushl $0", xops);
+
/* pic references don't explicitly mention pic_offset_table_rtx */
if (TARGET_SCHEDULE_PROLOGUE)
{
@@ -2131,6 +2144,7 @@
register int nregs, limit;
int offset;
rtx xops[3];
+ rtx stack_protect_label;
int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
|| current_function_uses_const_pool);
long tsize = get_frame_size ();
@@ -2238,6 +2252,21 @@
}
#endif
+ /* canary (stack) protection */
+ if (stack_protect > 0)
+ {
+ rtx can, reg = gen_rtx(REG, SImode, 1);
+ stack_protect_label = gen_label_rtx();
+
+ emit_insn (gen_pop(reg));
+ if (stack_protect == 2)
+ can = GEN_INT(canaryval);
+ else
+ can = GEN_INT(0);
+ emit_cmp_insn (reg, can, EQ, NULL_RTX, GET_MODE(reg), 0, 0);
+ emit_jump_insn (gen_bne (stack_protect_label));
+ }
+
if (current_function_pops_args && current_function_args_size)
{
xops[1] = GEN_INT (current_function_pops_args);
@@ -2267,7 +2296,20 @@
}
else
/* output_asm_insn ("ret", xops);*/
- emit_jump_insn (gen_return_internal ());
+ emit_jump_insn (gen_return_internal ());
+
+
+ /* canary - put this out-of-line to avoid a mispredicted branch
+ and instruction cache pollution */
+ if (stack_protect > 0)
+ {
+ rtx savior = gen_rtx (MEM, FUNCTION_MODE,
+ gen_rtx(SYMBOL_REF, Pmode, "abort"));
+ LABEL_PRESERVE_P(stack_protect_label) = 1;
+ emit_label_after(stack_protect_label, get_insns()); /* PROBLEM!!! */
+ LABEL_PRESERVE_P(stack_protect_label) = 1;
+ emit_call_insn (gen_call (savior, GEN_INT(0), NULL_RTX, 0));
+ }
}
\f
diff -ur egcs-1.0.3a/gcc/config/i386/i386.h egcs-1.0.3a.new/gcc/config/i386/i386.h
--- egcs-1.0.3a/gcc/config/i386/i386.h Fri Dec 19 09:59:33 1997
+++ egcs-1.0.3a.new/gcc/config/i386/i386.h Fri Oct 16 00:19:40 1998
@@ -924,7 +924,9 @@
#define PUSH_ROUNDING(BYTES) (((BYTES) + 1) & (-2))
/* Offset of first parameter from the argument pointer register value. */
-#define FIRST_PARM_OFFSET(FNDECL) 0
+/* IMMUNIX: if neccessary, allow for space of the canaryvalue, or a
+ null word. */
+#define FIRST_PARM_OFFSET(FNDECL) ((stack_protect == 0) ? 0 : 4)
/* Value is the number of bytes of arguments automatically
popped when returning from a subroutine call.
diff -ur egcs-1.0.3a/gcc/function.c egcs-1.0.3a.new/gcc/function.c
--- egcs-1.0.3a/gcc/function.c Mon Feb 9 00:01:35 1998
+++ egcs-1.0.3a.new/gcc/function.c Fri Oct 16 00:19:40 1998
@@ -2580,6 +2580,7 @@
rtx insns;
{
rtx insn;
+ extern int stack_protect;
/* Compute the offsets to use for this function. */
in_arg_offset = FIRST_PARM_OFFSET (fndecl);
diff -ur egcs-1.0.3a/gcc/toplev.c egcs-1.0.3a.new/gcc/toplev.c
--- egcs-1.0.3a/gcc/toplev.c Mon Feb 9 01:56:08 1998
+++ egcs-1.0.3a.new/gcc/toplev.c Fri Oct 16 00:19:40 1998
@@ -296,6 +296,10 @@
/* Flag to output bytecode instead of native assembler */
int output_bytecode = 0;
+/* Flag to add IMMUNIX StackGuard canary code to function prologues
+ and epilogues, or null-word protection which is slightly faster. */
+int stack_protect = 0;
+
/* Pointer to function to compute the name to use to print a declaration.
DECL is the declaration in question.
VERBOSITY determines what information will be printed:
@@ -747,7 +751,9 @@
{"argument-noalias", &flag_argument_noalias, 1},
{"argument-noalias-global", &flag_argument_noalias, 2},
{"check-memory-usage", &flag_check_memory_usage, 1},
- {"prefix-function-name", &flag_prefix_function_name, 1}
+ {"prefix-function-name", &flag_prefix_function_name, 1},
+ {"stack-canary-protect", &stack_protect, 2},
+ {"stack-null-protect", &stack_protect, 1}
};
/* Table of language-specific options. */
astor
--
Alexander Kjeldaas, Guardian Networks AS, Trondheim, Norway
http://www.guardian.no/
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: newbie: labels headache
1998-10-15 21:35 newbie: labels headache Alexander Kjeldaas
@ 1998-10-19 20:14 ` Jeffrey A Law
0 siblings, 0 replies; 2+ messages in thread
From: Jeffrey A Law @ 1998-10-19 20:14 UTC (permalink / raw)
To: Alexander Kjeldaas; +Cc: egcs
In message < 19981016022955.A22400@lucifer.guardian.no >you write:
> Hi, I've tried to rewrite the StackGuard patch for egcs but when I
> compile the program with -O2, the label guarding the 'call abort'
> instruction is removed, which makes the assembler complain. I'd be
> happy if someone could clue me in about my wrongdoings in the
> following. This is my first gcc hack so please be gentle :-).
Try setting LABEL_NUSES to the number of insns which use the value. It
looks like the right value ought to be 1.
Jeff
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~1998-10-19 20:14 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-10-15 21:35 newbie: labels headache Alexander Kjeldaas
1998-10-19 20:14 ` Jeffrey A Law
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).