Propolice for GCC 3.3 based on:
authorJoerg Sonnenberger <joerg@dragonflybsd.org>
Fri, 5 Mar 2004 21:38:44 +0000 (21:38 +0000)
committerJoerg Sonnenberger <joerg@dragonflybsd.org>
Fri, 5 Mar 2004 21:38:44 +0000 (21:38 +0000)
http://www.trl.ibm.com/projects/security/ssp/gcc3_3/protector-3.3-7.tar.gz

protector.[ch] has been in integrated into cc3/cc_int and the protector.dif
has been splitted and integrated into cc3/cc_int/patches using the new
patch infrastructure. The old bsd-format.patch has been moved there as well.

The build order in gnu/ has been adjusted since lib/gcc3/libgcc depends on
"make depend" in usr.bin/cc3/cc_int for inclusion of the patched files.

The second stage loader has been adjusted to link when parts are compiled
using -fstack-protector.

23 files changed:
gnu/Makefile
gnu/lib/gcc3/libgcc/Makefile
gnu/usr.bin/cc3/Makefile.inc
gnu/usr.bin/cc3/cc_int/Makefile
gnu/usr.bin/cc3/cc_int/patches/c-format.c.patch [moved from gnu/usr.bin/cc3/cc_int/bsd-printf.patch with 96% similarity]
gnu/usr.bin/cc3/cc_int/patches/calls.c.patch [new file with mode: 0644]
gnu/usr.bin/cc3/cc_int/patches/combine.c.patch [new file with mode: 0644]
gnu/usr.bin/cc3/cc_int/patches/cse.c.patch [new file with mode: 0644]
gnu/usr.bin/cc3/cc_int/patches/explow.c.patch [new file with mode: 0644]
gnu/usr.bin/cc3/cc_int/patches/expr.c.patch [new file with mode: 0644]
gnu/usr.bin/cc3/cc_int/patches/flags.h.patch [new file with mode: 0644]
gnu/usr.bin/cc3/cc_int/patches/function.c.patch [new file with mode: 0644]
gnu/usr.bin/cc3/cc_int/patches/gcse.c.patch [new file with mode: 0644]
gnu/usr.bin/cc3/cc_int/patches/integrate.c.patch [new file with mode: 0644]
gnu/usr.bin/cc3/cc_int/patches/libgcc2.c.patch [new file with mode: 0644]
gnu/usr.bin/cc3/cc_int/patches/loop.c.patch [new file with mode: 0644]
gnu/usr.bin/cc3/cc_int/patches/optabs.c.patch [new file with mode: 0644]
gnu/usr.bin/cc3/cc_int/patches/reload1.c.patch [new file with mode: 0644]
gnu/usr.bin/cc3/cc_int/patches/simplify-rtx.c.patch [new file with mode: 0644]
gnu/usr.bin/cc3/cc_int/patches/toplev.c.patch [new file with mode: 0644]
gnu/usr.bin/cc3/cc_int/protector.c [new file with mode: 0644]
gnu/usr.bin/cc3/cc_int/protector.h [new file with mode: 0644]
sys/boot/ficl/Makefile

index f1ced80..4d4ad47 100644 (file)
@@ -1,7 +1,7 @@
 #      @(#)Makefile    5.33.1.1 (Berkeley) 5/6/91
 # $FreeBSD: src/gnu/Makefile,v 1.33.2.1 2002/07/25 16:33:10 obrien Exp $
-# $DragonFly: src/gnu/Makefile,v 1.2 2003/06/17 04:25:42 dillon Exp $
+# $DragonFly: src/gnu/Makefile,v 1.3 2004/03/05 21:38:43 joerg Exp $
 
-SUBDIR= lib libexec usr.bin usr.sbin
+SUBDIR= usr.bin lib libexec usr.sbin
 
 .include <bsd.subdir.mk>
index 333d74a..0be70fc 100644 (file)
@@ -1,9 +1,11 @@
 # $FreeBSD: src/gnu/lib/libgcc/Makefile,v 1.50 2003/07/11 05:29:11 kan Exp $
-# $DragonFly: src/gnu/lib/gcc3/libgcc/Attic/Makefile,v 1.2 2004/02/02 23:35:09 dillon Exp $
+# $DragonFly: src/gnu/lib/gcc3/libgcc/Attic/Makefile,v 1.3 2004/03/05 21:38:44 joerg Exp $
 
 .include "../Makefile.inc"
 .include "${.CURDIR}/../../../usr.bin/cc3/Makefile.tgt"
 
+.PATH: ${.OBJDIR}/../../../usr.bin/cc3/cc_int
+.PATH: ${.CURDIR}/../../../usr.bin/cc3/cc_int
 .PATH: ${GCCDIR}/gcc/config/${GCC_CPU} ${GCCDIR}/gcc
 
 # allow to be overridden for the a.out case
@@ -55,7 +57,8 @@ LIB2FUNCS_1 = _muldi3 _negdi2 _lshrdi3 _ashldi3 _ashrdi3 _ffsdi2 _clz \
 
 LIB2FUNCS_2 = _floatdixf _fixunsxfsi _fixtfdi _fixunstfdi _floatditf \
     _clear_cache _trampoline __main _exit _absvsi2 _absvdi2 _addvsi3 \
-    _addvdi3 _subvsi3 _subvdi3 _mulvsi3 _mulvdi3 _negvsi2 _negvdi2 _ctors
+    _addvdi3 _subvsi3 _subvdi3 _mulvsi3 _mulvdi3 _negvsi2 _negvdi2 _ctors \
+    _stack_smash_handler
 
 # Defined in libgcc2.c, included only in the static library.
 LIB2FUNCS_ST = _eprintf _bb __gcc_bcmp
index f3ea6a4..4c920fd 100644 (file)
@@ -1,5 +1,5 @@
 # $FreeBSD: src/gnu/usr.bin/cc/Makefile.inc,v 1.63 2002/06/04 19:45:08 obrien Exp $
-# $DragonFly: src/gnu/usr.bin/cc3/Attic/Makefile.inc,v 1.6 2004/02/03 03:47:08 dillon Exp $
+# $DragonFly: src/gnu/usr.bin/cc3/Attic/Makefile.inc,v 1.7 2004/03/05 21:38:44 joerg Exp $
 
 BINDIR?=/usr/libexec/gcc3
 MY_CCVER=gcc3
@@ -9,6 +9,8 @@ MY_CCVER=gcc3
 .if !defined(__CC_MAKEFILE_INC__)
 __CC_MAKEFILE_INC__= ${MFILE}
 
+CFLAGS+=       -I${.CURDIR}/../cc_int -I${.OBJDIR}/../cc_int
+
 GCCDIR=        ${.CURDIR}/../../../../contrib/gcc-3.3
 
 .include "Makefile.tgt"
@@ -56,7 +58,9 @@ gcc_local.c : gcc.c
        mv -f ${.TARGET}.new ${.TARGET}
 
 version_local.c : version.c
-       sed -e 's/const char version.*".* /&[DragonFly] /' < ${.ALLSRC:M*c} > ${.TARGET}.new
+       sed -e 's/\(const char version.*".*\) (/\1 [DragonFly] (propolice, /' < ${.ALLSRC:M*c} > ${.TARGET}.new
        mv -f ${.TARGET}.new ${.TARGET}
 
+CLEANFILES+=   version_local.c
+
 .endif # !__CC_MAKEFILE_INC__
index d0e814e..f327689 100644 (file)
@@ -1,5 +1,5 @@
 # $FreeBSD: src/gnu/usr.bin/cc/cc_int/Makefile,v 1.39 2004/01/12 22:02:31 ru Exp $
-# $DragonFly: src/gnu/usr.bin/cc3/cc_int/Attic/Makefile,v 1.4 2004/02/24 18:04:20 joerg Exp $
+# $DragonFly: src/gnu/usr.bin/cc3/cc_int/Attic/Makefile,v 1.5 2004/03/05 21:38:44 joerg Exp $
 
 .include "../Makefile.inc"
 
@@ -88,8 +88,10 @@ underscore.c: Makefile
        echo '/*WARNING: This file is automatically generated!*/' >${.TARGET}
        echo "int prepends_underscore = ${UNDERSCORES};"          >>${.TARGET}
 
-CLEANFILES+=   c-format.c
-c-format.c: ${GCCDIR}/gcc/c-format.c bsd-printf.patch
-       patch -o ${.OBJDIR}/c-format.c -i ${.CURDIR}/bsd-printf.patch ${GCCDIR}/gcc/c-format.c
+CONTRIBDIR=    ${GCCDIR}/gcc
+
+PATCHES!=      echo ${.CURDIR}/patches/*.patch
+
+SRCS+= ${PATCHES} protector.c
 
 .include <bsd.lib.mk>
similarity index 96%
rename from gnu/usr.bin/cc3/cc_int/bsd-printf.patch
rename to gnu/usr.bin/cc3/cc_int/patches/c-format.c.patch
index b034d8c..ac9e1b7 100644 (file)
@@ -1,4 +1,4 @@
-$DragonFly: src/gnu/usr.bin/cc3/cc_int/Attic/bsd-printf.patch,v 1.1 2004/02/24 18:04:20 joerg Exp $
+$DragonFly: src/gnu/usr.bin/cc3/cc_int/patches/Attic/c-format.c.patch,v 1.1 2004/03/05 21:38:44 joerg Exp $
 --- c-format.c.orig    Tue Feb 24 18:37:09 2004
 +++ c-format.c Tue Feb 24 18:43:03 2004
 @@ -762,6 +762,18 @@
diff --git a/gnu/usr.bin/cc3/cc_int/patches/calls.c.patch b/gnu/usr.bin/cc3/cc_int/patches/calls.c.patch
new file mode 100644 (file)
index 0000000..2e0df05
--- /dev/null
@@ -0,0 +1,17 @@
+$DragonFly: src/gnu/usr.bin/cc3/cc_int/patches/Attic/calls.c.patch,v 1.1 2004/03/05 21:38:44 joerg Exp $
+Index: calls.c
+===================================================================
+RCS file: /cvs/src/contrib/gcc-3.3/gcc/calls.c,v
+retrieving revision 1.1
+diff -u -r1.1 calls.c
+--- calls.c    2 Feb 2004 23:09:46 -0000       1.1
++++ calls.c    4 Mar 2004 15:18:17 -0000
+@@ -2331,7 +2331,7 @@
+           /* For variable-sized objects, we must be called with a target
+              specified.  If we were to allocate space on the stack here,
+              we would have no way of knowing when to free it.  */
+-          rtx d = assign_temp (TREE_TYPE (exp), 1, 1, 1);
++          rtx d = assign_temp (TREE_TYPE (exp), 5, 1, 1);
+           mark_temp_addr_taken (d);
+           structure_value_addr = XEXP (d, 0);
diff --git a/gnu/usr.bin/cc3/cc_int/patches/combine.c.patch b/gnu/usr.bin/cc3/cc_int/patches/combine.c.patch
new file mode 100644 (file)
index 0000000..c769bfa
--- /dev/null
@@ -0,0 +1,51 @@
+$DragonFly: src/gnu/usr.bin/cc3/cc_int/patches/Attic/combine.c.patch,v 1.1 2004/03/05 21:38:44 joerg Exp $
+Index: combine.c
+===================================================================
+RCS file: /cvs/src/contrib/gcc-3.3/gcc/combine.c,v
+retrieving revision 1.1
+diff -u -r1.1 combine.c
+--- combine.c  2 Feb 2004 23:09:46 -0000       1.1
++++ combine.c  4 Mar 2004 15:18:22 -0000
+@@ -3873,7 +3873,17 @@
+         rtx inner_op0 = XEXP (XEXP (x, 0), 1);
+         rtx inner_op1 = XEXP (x, 1);
+         rtx inner;
+-
++        
++#ifndef FRAME_GROWS_DOWNWARD
++        if (flag_propolice_protection
++            && code == PLUS
++            && other == frame_pointer_rtx
++            && GET_CODE (inner_op0) == CONST_INT
++            && GET_CODE (inner_op1) == CONST_INT
++            && INTVAL (inner_op0) > 0
++            && INTVAL (inner_op0) + INTVAL (inner_op1) <= 0)
++          return x;
++#endif
+         /* Make sure we pass the constant operand if any as the second
+            one if this is a commutative operation.  */
+         if (CONSTANT_P (inner_op0) && GET_RTX_CLASS (code) == 'c')
+@@ -4286,6 +4296,11 @@
+        they are now checked elsewhere.  */
+       if (GET_CODE (XEXP (x, 0)) == PLUS
+         && CONSTANT_ADDRESS_P (XEXP (XEXP (x, 0), 1)))
++#ifndef FRAME_GROWS_DOWNWARD
++      if (! (flag_propolice_protection
++             && XEXP (XEXP (x, 0), 0) == frame_pointer_rtx
++             && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
++#endif
+       return gen_binary (PLUS, mode,
+                          gen_binary (PLUS, mode, XEXP (XEXP (x, 0), 0),
+                                      XEXP (x, 1)),
+@@ -4414,7 +4429,10 @@
+       /* Canonicalize (minus A (plus B C)) to (minus (minus A B) C) for
+        integers.  */
+-      if (GET_CODE (XEXP (x, 1)) == PLUS && INTEGRAL_MODE_P (mode))
++      if (GET_CODE (XEXP (x, 1)) == PLUS && INTEGRAL_MODE_P (mode)
++        && (! (flag_propolice_protection
++               && XEXP (XEXP (x, 1), 0) == frame_pointer_rtx
++               && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT)))
+       return gen_binary (MINUS, mode,
+                          gen_binary (MINUS, mode, XEXP (x, 0),
+                                      XEXP (XEXP (x, 1), 0)),
diff --git a/gnu/usr.bin/cc3/cc_int/patches/cse.c.patch b/gnu/usr.bin/cc3/cc_int/patches/cse.c.patch
new file mode 100644 (file)
index 0000000..1372bea
--- /dev/null
@@ -0,0 +1,39 @@
+$DragonFly: src/gnu/usr.bin/cc3/cc_int/patches/Attic/cse.c.patch,v 1.1 2004/03/05 21:38:44 joerg Exp $
+Index: cse.c
+===================================================================
+RCS file: /cvs/src/contrib/gcc-3.3/gcc/cse.c,v
+retrieving revision 1.1
+diff -u -r1.1 cse.c
+--- cse.c      2 Feb 2004 23:09:47 -0000       1.1
++++ cse.c      4 Mar 2004 15:18:25 -0000
+@@ -4288,7 +4288,14 @@
+             if (new_const == 0)
+               break;
+-
++#ifndef FRAME_GROWS_DOWNWARD
++            if (flag_propolice_protection
++                && GET_CODE (y) == PLUS
++                && XEXP (y, 0) == frame_pointer_rtx
++                && INTVAL (inner_const) > 0
++                && INTVAL (new_const) <= 0)
++              break;
++#endif
+             /* If we are associating shift operations, don't let this
+                produce a shift of the size of the object or larger.
+                This could occur when we follow a sign-extend by a right
+@@ -4823,6 +4830,14 @@
+       if (SET_DEST (x) == pc_rtx
+         && GET_CODE (SET_SRC (x)) == LABEL_REF)
+       ;
++      /* cut the reg propagation of stack-protected argument */
++      else if (x->volatil) {
++      rtx x1 = SET_DEST (x);
++      if (GET_CODE (x1) == SUBREG && GET_CODE (SUBREG_REG (x1)) == REG)
++        x1 = SUBREG_REG (x1);
++      if (! REGNO_QTY_VALID_P(REGNO (x1)))
++        make_new_qty (REGNO (x1), GET_MODE (x1));
++      }
+       /* Don't count call-insns, (set (reg 0) (call ...)), as a set.
+        The hard function value register is used only once, to copy to
diff --git a/gnu/usr.bin/cc3/cc_int/patches/explow.c.patch b/gnu/usr.bin/cc3/cc_int/patches/explow.c.patch
new file mode 100644 (file)
index 0000000..43ec0a5
--- /dev/null
@@ -0,0 +1,50 @@
+$DragonFly: src/gnu/usr.bin/cc3/cc_int/patches/Attic/explow.c.patch,v 1.1 2004/03/05 21:38:44 joerg Exp $
+Index: explow.c
+===================================================================
+RCS file: /cvs/src/contrib/gcc-3.3/gcc/explow.c,v
+retrieving revision 1.1
+diff -u -r1.1 explow.c
+--- explow.c   2 Feb 2004 23:09:47 -0000       1.1
++++ explow.c   4 Mar 2004 15:18:26 -0000
+@@ -86,7 +86,8 @@
+   rtx tem;
+   int all_constant = 0;
+-  if (c == 0)
++  if (c == 0
++      && !(flag_propolice_protection && x == virtual_stack_vars_rtx))
+     return x;
+  restart:
+@@ -187,7 +188,8 @@
+       break;
+     }
+-  if (c != 0)
++  if (c != 0
++      || (flag_propolice_protection && x == virtual_stack_vars_rtx))
+     x = gen_rtx_PLUS (mode, x, GEN_INT (c));
+   if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
+@@ -538,6 +540,21 @@
+        in certain cases.  This is not necessary since the code
+        below can handle all possible cases, but machine-dependent
+        transformations can make better code.  */
++      if (flag_propolice_protection)
++      {
++#define FRAMEADDR_P(X) (GET_CODE (X) == PLUS                          \
++                      && XEXP (X, 0) == virtual_stack_vars_rtx        \
++                      && GET_CODE (XEXP (X, 1)) == CONST_INT)
++        rtx y;
++        if (FRAMEADDR_P (x)) goto win;
++        for (y=x; y!=0 && GET_CODE (y)==PLUS; y = XEXP (y, 0))
++          {
++            if (FRAMEADDR_P (XEXP (y, 0)))
++              XEXP (y, 0) = force_reg (GET_MODE (XEXP (y, 0)), XEXP (y, 0));
++            if (FRAMEADDR_P (XEXP (y, 1)))
++              XEXP (y, 1) = force_reg (GET_MODE (XEXP (y, 1)), XEXP (y, 1));
++          }
++      }
+       LEGITIMIZE_ADDRESS (x, oldx, mode, win);
+       /* PLUS and MULT can appear in special ways
diff --git a/gnu/usr.bin/cc3/cc_int/patches/expr.c.patch b/gnu/usr.bin/cc3/cc_int/patches/expr.c.patch
new file mode 100644 (file)
index 0000000..612a92d
--- /dev/null
@@ -0,0 +1,94 @@
+$DragonFly: src/gnu/usr.bin/cc3/cc_int/patches/Attic/expr.c.patch,v 1.1 2004/03/05 21:38:44 joerg Exp $
+Index: expr.c
+===================================================================
+RCS file: /cvs/src/contrib/gcc-3.3/gcc/expr.c,v
+retrieving revision 1.1
+diff -u -r1.1 expr.c
+--- expr.c     2 Feb 2004 23:09:47 -0000       1.1
++++ expr.c     4 Mar 2004 15:18:30 -0000
+@@ -45,6 +45,7 @@
+ #include "langhooks.h"
+ #include "intl.h"
+ #include "tm_p.h"
++#include "protector.h"
+ /* Decide whether a function's arguments should be processed
+    from first to last or from last to first.
+@@ -1527,7 +1528,7 @@
+       if (USE_LOAD_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_from)
+       {
+-        data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len));
++        data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len-GET_MODE_SIZE (mode)));
+         data.autinc_from = 1;
+         data.explicit_inc_from = -1;
+       }
+@@ -1541,7 +1542,7 @@
+       data.from_addr = copy_addr_to_reg (from_addr);
+       if (USE_STORE_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_to)
+       {
+-        data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len));
++        data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len-GET_MODE_SIZE (mode)));
+         data.autinc_to = 1;
+         data.explicit_inc_to = -1;
+       }
+@@ -1658,11 +1659,13 @@
+       from1 = adjust_address (data->from, mode, data->offset);
+       if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
+-      emit_insn (gen_add2_insn (data->to_addr,
+-                                GEN_INT (-(HOST_WIDE_INT)size)));
++      if (data->explicit_inc_to < -1)
++        emit_insn (gen_add2_insn (data->to_addr,
++                                  GEN_INT (-(HOST_WIDE_INT)size)));
+       if (HAVE_PRE_DECREMENT && data->explicit_inc_from < 0)
+-      emit_insn (gen_add2_insn (data->from_addr,
+-                                GEN_INT (-(HOST_WIDE_INT)size)));
++      if (data->explicit_inc_from < -1)
++        emit_insn (gen_add2_insn (data->from_addr,
++                                  GEN_INT (-(HOST_WIDE_INT)size)));
+       if (data->to)
+       emit_insn ((*genfun) (to1, from1));
+@@ -2835,7 +2838,7 @@
+       if (USE_STORE_PRE_DECREMENT (mode) && data->reverse && ! data->autinc_to)
+       {
+-        data->to_addr = copy_addr_to_reg (plus_constant (to_addr, data->len));
++        data->to_addr = copy_addr_to_reg (plus_constant (to_addr, data->len-GET_MODE_SIZE (mode)));
+         data->autinc_to = 1;
+         data->explicit_inc_to = -1;
+       }
+@@ -2906,8 +2909,9 @@
+       to1 = adjust_address (data->to, mode, data->offset);
+       if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
+-      emit_insn (gen_add2_insn (data->to_addr,
+-                                GEN_INT (-(HOST_WIDE_INT) size)));
++      if (data->explicit_inc_to < -1)
++        emit_insn (gen_add2_insn (data->to_addr,
++                                  GEN_INT (-(HOST_WIDE_INT) size)));
+       cst = (*data->constfun) (data->constfundata, data->offset, mode);
+       emit_insn ((*genfun) (to1, cst));
+@@ -5910,7 +5914,9 @@
+         && GET_CODE (XEXP (value, 0)) == PLUS
+         && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG
+         && REGNO (XEXP (XEXP (value, 0), 0)) >= FIRST_VIRTUAL_REGISTER
+-        && REGNO (XEXP (XEXP (value, 0), 0)) <= LAST_VIRTUAL_REGISTER)
++        && REGNO (XEXP (XEXP (value, 0), 0)) <= LAST_VIRTUAL_REGISTER
++        && (!flag_propolice_protection
++            || XEXP (XEXP (value, 0), 0) != virtual_stack_vars_rtx))
+       {
+         rtx temp = expand_simple_binop (GET_MODE (value), code,
+                                         XEXP (XEXP (value, 0), 0), op2,
+@@ -8086,7 +8092,8 @@
+       /* If adding to a sum including a constant,
+        associate it to put the constant outside.  */
+       if (GET_CODE (op1) == PLUS
+-        && CONSTANT_P (XEXP (op1, 1)))
++        && CONSTANT_P (XEXP (op1, 1))
++        && !(flag_propolice_protection && (contains_fp (op0) || contains_fp (op1))))
+       {
+         rtx constant_term = const0_rtx;
diff --git a/gnu/usr.bin/cc3/cc_int/patches/flags.h.patch b/gnu/usr.bin/cc3/cc_int/patches/flags.h.patch
new file mode 100644 (file)
index 0000000..f9b5fdf
--- /dev/null
@@ -0,0 +1,22 @@
+$DragonFly: src/gnu/usr.bin/cc3/cc_int/patches/Attic/flags.h.patch,v 1.1 2004/03/05 21:38:44 joerg Exp $
+Index: flags.h
+===================================================================
+RCS file: /cvs/src/contrib/gcc-3.3/gcc/flags.h,v
+retrieving revision 1.1
+diff -u -r1.1 flags.h
+--- flags.h    2 Feb 2004 23:09:47 -0000       1.1
++++ flags.h    4 Mar 2004 15:18:30 -0000
+@@ -690,4 +690,13 @@
+ #define HONOR_SIGN_DEPENDENT_ROUNDING(MODE) \
+   (MODE_HAS_SIGN_DEPENDENT_ROUNDING (MODE) && !flag_unsafe_math_optimizations)
++/* Nonzero means use propolice as a stack protection method */
++
++extern int flag_propolice_protection;
++extern int flag_stack_protection;
++
++/* Warn when not issuing stack smashing protection for some reason */
++
++extern int warn_stack_protector;
++
+ #endif /* ! GCC_FLAGS_H */
diff --git a/gnu/usr.bin/cc3/cc_int/patches/function.c.patch b/gnu/usr.bin/cc3/cc_int/patches/function.c.patch
new file mode 100644 (file)
index 0000000..6d47e99
--- /dev/null
@@ -0,0 +1,119 @@
+$DragonFly: src/gnu/usr.bin/cc3/cc_int/patches/Attic/function.c.patch,v 1.1 2004/03/05 21:38:44 joerg Exp $
+Index: function.c
+===================================================================
+RCS file: /cvs/src/contrib/gcc-3.3/gcc/function.c,v
+retrieving revision 1.1
+diff -u -r1.1 function.c
+--- function.c 2 Feb 2004 23:09:47 -0000       1.1
++++ function.c 4 Mar 2004 15:18:33 -0000
+@@ -59,6 +59,7 @@
+ #include "tm_p.h"
+ #include "integrate.h"
+ #include "langhooks.h"
++#include "protector.h"
+ #ifndef TRAMPOLINE_ALIGNMENT
+ #define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY
+@@ -145,6 +146,10 @@
+ /* Array of INSN_UIDs to hold the INSN_UIDs for each sibcall epilogue
+    in this function.  */
+ static GTY(()) varray_type sibcall_epilogue;
++
++/* Current boundary mark for character arrays.  */
++int temp_boundary_mark = 0;
++
\f
+ /* In order to evaluate some expressions, such as function calls returning
+    structures in memory, we need to temporarily allocate stack locations.
+@@ -198,6 +203,8 @@
+   /* The size of the slot, including extra space for alignment.  This
+      info is for combine_temp_slots.  */
+   HOST_WIDE_INT full_size;
++  /* Boundary mark of a character array and the others. This info is for propolice */
++  int boundary_mark;
+ };
\f
+ /* This structure is used to record MEMs or pseudos used to replace VAR, any
+@@ -632,6 +639,7 @@
+    whose lifetime is controlled by CLEANUP_POINT_EXPRs.  KEEP is 3
+    if we are to allocate something at an inner level to be treated as
+    a variable in the block (e.g., a SAVE_EXPR).
++   KEEP is 5 if we allocate a place to return structure.
+    TYPE is the type that will be used for the stack slot.  */
+@@ -645,6 +653,8 @@
+   unsigned int align;
+   struct temp_slot *p, *best_p = 0;
+   rtx slot;
++  int char_array = (flag_propolice_protection
++                  && keep == 1 && search_string_def (type));
+   /* If SIZE is -1 it means that somebody tried to allocate a temporary
+      of a variable size.  */
+@@ -670,7 +680,8 @@
+       && ! p->in_use
+       && objects_must_conflict_p (p->type, type)
+       && (best_p == 0 || best_p->size > p->size
+-          || (best_p->size == p->size && best_p->align > p->align)))
++          || (best_p->size == p->size && best_p->align > p->align))
++      && (! char_array || p->boundary_mark != 0))
+       {
+       if (p->align == align && p->size == size)
+         {
+@@ -705,6 +716,7 @@
+             p->address = 0;
+             p->rtl_expr = 0;
+             p->type = best_p->type;
++            p->boundary_mark = best_p->boundary_mark;
+             p->next = temp_slots;
+             temp_slots = p;
+@@ -765,6 +777,7 @@
+       p->full_size = frame_offset - frame_offset_old;
+ #endif
+       p->address = 0;
++      p->boundary_mark = char_array?++temp_boundary_mark:0;
+       p->next = temp_slots;
+       temp_slots = p;
+     }
+@@ -935,14 +948,16 @@
+           int delete_q = 0;
+           if (! q->in_use && GET_MODE (q->slot) == BLKmode)
+             {
+-              if (p->base_offset + p->full_size == q->base_offset)
++              if (p->base_offset + p->full_size == q->base_offset &&
++                  p->boundary_mark == q->boundary_mark)
+                 {
+                   /* Q comes after P; combine Q into P.  */
+                   p->size += q->size;
+                   p->full_size += q->full_size;
+                   delete_q = 1;
+                 }
+-              else if (q->base_offset + q->full_size == p->base_offset)
++              else if (q->base_offset + q->full_size == p->base_offset &&
++                       p->boundary_mark == q->boundary_mark)
+                 {
+                   /* P comes after Q; combine P into Q.  */
+                   q->size += p->size;
+@@ -1502,7 +1517,9 @@
+     new = func->x_parm_reg_stack_loc[regno];
+   if (new == 0)
+-    new = assign_stack_local_1 (decl_mode, GET_MODE_SIZE (decl_mode), 0, func);
++    new = function ?
++      assign_stack_local_1 (decl_mode, GET_MODE_SIZE (decl_mode), 0, func):
++      assign_stack_local_for_pseudo_reg (decl_mode, GET_MODE_SIZE (decl_mode), 0);
+   PUT_CODE (reg, MEM);
+   PUT_MODE (reg, decl_mode);
+@@ -3982,7 +3999,8 @@
+                constant with that register.  */
+             temp = gen_reg_rtx (Pmode);
+             XEXP (x, 0) = new;
+-            if (validate_change (object, &XEXP (x, 1), temp, 0))
++            if (validate_change (object, &XEXP (x, 1), temp, 0)
++                && ! flag_propolice_protection)
+               emit_insn_before (gen_move_insn (temp, new_offset), object);
+             else
+               {
diff --git a/gnu/usr.bin/cc3/cc_int/patches/gcse.c.patch b/gnu/usr.bin/cc3/cc_int/patches/gcse.c.patch
new file mode 100644 (file)
index 0000000..56c0f45
--- /dev/null
@@ -0,0 +1,17 @@
+$DragonFly: src/gnu/usr.bin/cc3/cc_int/patches/Attic/gcse.c.patch,v 1.1 2004/03/05 21:38:44 joerg Exp $
+Index: gcse.c
+===================================================================
+RCS file: /cvs/src/contrib/gcc-3.3/gcc/gcse.c,v
+retrieving revision 1.1
+diff -u -r1.1 gcse.c
+--- gcse.c     2 Feb 2004 23:09:48 -0000       1.1
++++ gcse.c     4 Mar 2004 15:18:36 -0000
+@@ -4212,7 +4212,7 @@
+       /* Find an assignment that sets reg_used and is available
+        at the start of the block.  */
+       set = find_avail_set (regno, insn);
+-      if (! set)
++      if (! set || set->expr->volatil)
+       continue;
+       pat = set->expr;
diff --git a/gnu/usr.bin/cc3/cc_int/patches/integrate.c.patch b/gnu/usr.bin/cc3/cc_int/patches/integrate.c.patch
new file mode 100644 (file)
index 0000000..817e4e7
--- /dev/null
@@ -0,0 +1,30 @@
+$DragonFly: src/gnu/usr.bin/cc3/cc_int/patches/Attic/integrate.c.patch,v 1.1 2004/03/05 21:38:44 joerg Exp $
+Index: integrate.c
+===================================================================
+RCS file: /cvs/src/contrib/gcc-3.3/gcc/integrate.c,v
+retrieving revision 1.1
+diff -u -r1.1 integrate.c
+--- integrate.c        2 Feb 2004 23:09:48 -0000       1.1
++++ integrate.c        4 Mar 2004 15:18:37 -0000
+@@ -401,6 +401,10 @@
+   /* These args would always appear unused, if not for this.  */
+   TREE_USED (copy) = 1;
++  /* The inlined variable is marked as INLINE not to sweep by propolice */
++  if (flag_propolice_protection && TREE_CODE (copy) == VAR_DECL)
++    DECL_INLINE (copy) = 1;
++
+   /* Set the context for the new declaration.  */
+   if (!DECL_CONTEXT (decl))
+     /* Globals stay global.  */
+@@ -1965,6 +1969,10 @@
+             seq = get_insns ();
+             end_sequence ();
++#ifdef FRAME_GROWS_DOWNWARD
++            if (flag_propolice_protection && GET_CODE (seq) == SET)
++              RTX_INTEGRATED_P (SET_SRC (seq)) = 1;
++#endif
+             emit_insn_after (seq, map->insns_at_start);
+             return temp;
+           }
diff --git a/gnu/usr.bin/cc3/cc_int/patches/libgcc2.c.patch b/gnu/usr.bin/cc3/cc_int/patches/libgcc2.c.patch
new file mode 100644 (file)
index 0000000..9c753cf
--- /dev/null
@@ -0,0 +1,113 @@
+$DragonFly: src/gnu/usr.bin/cc3/cc_int/patches/Attic/libgcc2.c.patch,v 1.1 2004/03/05 21:38:44 joerg Exp $
+Index: libgcc2.c
+===================================================================
+RCS file: /cvs/src/contrib/gcc-3.3/gcc/libgcc2.c,v
+retrieving revision 1.1
+diff -u -r1.1 libgcc2.c
+--- libgcc2.c  2 Feb 2004 23:09:48 -0000       1.1
++++ libgcc2.c  4 Mar 2004 15:18:38 -0000
+@@ -1993,3 +1993,104 @@
+ #endif /* NEED_ATEXIT */
+ #endif /* L_exit */
++\f
++#ifdef L_stack_smash_handler
++#ifndef _LIBC_PROVIDES_SSP_
++#include <stdio.h>
++#include <string.h>
++#include <fcntl.h>
++#include <unistd.h>
++
++#ifdef _POSIX_SOURCE
++#include <signal.h>
++#endif
++
++#if defined(HAVE_SYSLOG)
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <sys/un.h>
++
++#include <sys/syslog.h>
++#ifndef _PATH_LOG
++#define _PATH_LOG "/dev/log"
++#endif
++#endif
++
++long __guard[8] = {0,0,0,0,0,0,0,0};
++static void __guard_setup (void) __attribute__ ((constructor)) ;
++static void __guard_setup (void)
++{
++  int fd;
++  if (__guard[0]!=0) return;
++  fd = open ("/dev/urandom", 0);
++  if (fd != -1) {
++    ssize_t size = read (fd, (char*)&__guard, sizeof(__guard));
++    close (fd) ;
++    if (size == sizeof(__guard)) return;
++  }
++  /* If a random generator can't be used, the protector switches the guard
++     to the "terminator canary" */
++  ((char*)__guard)[0] = 0; ((char*)__guard)[1] = 0;
++  ((char*)__guard)[2] = '\n'; ((char*)__guard)[3] = 255;
++}
++void __stack_smash_handler (char func[], int damaged ATTRIBUTE_UNUSED)
++{
++#if defined (__GNU_LIBRARY__)
++  extern char * __progname;
++#endif
++  const char message[] = ": stack smashing attack in function ";
++  int bufsz = 256, len;
++  char buf[bufsz];
++#if defined(HAVE_SYSLOG)
++  int LogFile;
++  struct sockaddr_un SyslogAddr;  /* AF_UNIX address of local logger */
++#endif
++#ifdef _POSIX_SOURCE
++  {
++    sigset_t mask;
++    sigfillset(&mask);
++    sigdelset(&mask, SIGABRT);        /* Block all signal handlers */
++    sigprocmask(SIG_BLOCK, &mask, NULL); /* except SIGABRT */
++  }
++#endif
++
++  strcpy(buf, "<2>"); len=3;  /* send LOG_CRIT */
++#if defined (__GNU_LIBRARY__)
++  strncat(buf, __progname, bufsz-len-1); len = strlen(buf);
++#endif
++  if (bufsz>len) {strncat(buf, message, bufsz-len-1); len = strlen(buf);}
++  if (bufsz>len) {strncat(buf, func, bufsz-len-1); len = strlen(buf);}
++
++  /* print error message */
++  write (STDERR_FILENO, buf+3, len-3);
++#if defined(HAVE_SYSLOG)
++  if ((LogFile = socket(AF_UNIX, SOCK_DGRAM, 0)) != -1) {
++
++    /*
++     * Send "found" message to the "/dev/log" path
++     */
++    SyslogAddr.sun_family = AF_UNIX;
++    (void)strncpy(SyslogAddr.sun_path, _PATH_LOG,
++                sizeof(SyslogAddr.sun_path) - 1);
++    SyslogAddr.sun_path[sizeof(SyslogAddr.sun_path) - 1] = '\0';
++    sendto(LogFile, buf, len, 0, (struct sockaddr *)&SyslogAddr,
++         sizeof(SyslogAddr));
++  }
++#endif
++
++#ifdef _POSIX_SOURCE
++  { /* Make sure the default handler is associated with SIGABRT */
++    struct sigaction sa;
++    
++    memset(&sa, 0, sizeof(struct sigaction));
++    sigfillset(&sa.sa_mask);  /* Block all signals */
++    sa.sa_flags = 0;
++    sa.sa_handler = SIG_DFL;
++    sigaction(SIGABRT, &sa, NULL);
++    (void)kill(getpid(), SIGABRT);
++  }
++#endif
++  _exit(127);
++}
++#endif
++#endif
diff --git a/gnu/usr.bin/cc3/cc_int/patches/loop.c.patch b/gnu/usr.bin/cc3/cc_int/patches/loop.c.patch
new file mode 100644 (file)
index 0000000..34c027b
--- /dev/null
@@ -0,0 +1,23 @@
+$DragonFly: src/gnu/usr.bin/cc3/cc_int/patches/Attic/loop.c.patch,v 1.1 2004/03/05 21:38:44 joerg Exp $
+Index: loop.c
+===================================================================
+RCS file: /cvs/src/contrib/gcc-3.3/gcc/loop.c,v
+retrieving revision 1.1
+diff -u -r1.1 loop.c
+--- loop.c     2 Feb 2004 23:09:49 -0000       1.1
++++ loop.c     4 Mar 2004 15:18:41 -0000
+@@ -6547,6 +6547,14 @@
+   if (GET_CODE (*mult_val) == USE)
+     *mult_val = XEXP (*mult_val, 0);
++#ifndef FRAME_GROWS_DOWNWARD
++  if (flag_propolice_protection
++      && GET_CODE (*add_val) == PLUS
++      && (XEXP (*add_val, 0) == frame_pointer_rtx
++        || XEXP (*add_val, 1) == frame_pointer_rtx))
++    return 0;
++#endif
++
+   if (is_addr)
+     *pbenefit += address_cost (orig_x, addr_mode) - reg_address_cost;
+   else
diff --git a/gnu/usr.bin/cc3/cc_int/patches/optabs.c.patch b/gnu/usr.bin/cc3/cc_int/patches/optabs.c.patch
new file mode 100644 (file)
index 0000000..f42478b
--- /dev/null
@@ -0,0 +1,35 @@
+$DragonFly: src/gnu/usr.bin/cc3/cc_int/patches/Attic/optabs.c.patch,v 1.1 2004/03/05 21:38:44 joerg Exp $
+Index: optabs.c
+===================================================================
+RCS file: /cvs/src/contrib/gcc-3.3/gcc/optabs.c,v
+retrieving revision 1.1
+diff -u -r1.1 optabs.c
+--- optabs.c   2 Feb 2004 23:09:49 -0000       1.1
++++ optabs.c   4 Mar 2004 15:18:42 -0000
+@@ -703,6 +703,26 @@
+   if (target)
+     target = protect_from_queue (target, 1);
++  if (flag_propolice_protection
++      && binoptab->code == PLUS
++      && op0 == virtual_stack_vars_rtx
++      && GET_CODE(op1) == CONST_INT)
++    {
++      int icode = (int) binoptab->handlers[(int) mode].insn_code;
++      if (target)
++      temp = target;
++      else
++      temp = gen_reg_rtx (mode);
++
++      if (! (*insn_data[icode].operand[0].predicate) (temp, mode)
++        || GET_CODE (temp) != REG)
++      temp = gen_reg_rtx (mode);
++
++      emit_insn (gen_rtx_SET (VOIDmode, temp,
++                            gen_rtx_PLUS (GET_MODE (op0), op0, op1)));
++      return temp;
++    }
++
+   if (flag_force_mem)
+     {
+       op0 = force_not_mem (op0);
diff --git a/gnu/usr.bin/cc3/cc_int/patches/reload1.c.patch b/gnu/usr.bin/cc3/cc_int/patches/reload1.c.patch
new file mode 100644 (file)
index 0000000..f37e4ab
--- /dev/null
@@ -0,0 +1,25 @@
+$DragonFly: src/gnu/usr.bin/cc3/cc_int/patches/Attic/reload1.c.patch,v 1.1 2004/03/05 21:38:44 joerg Exp $
+Index: reload1.c
+===================================================================
+RCS file: /cvs/src/contrib/gcc-3.3/gcc/reload1.c,v
+retrieving revision 1.1
+diff -u -r1.1 reload1.c
+--- reload1.c  2 Feb 2004 23:09:49 -0000       1.1
++++ reload1.c  4 Mar 2004 15:18:46 -0000
+@@ -42,6 +42,7 @@
+ #include "toplev.h"
+ #include "except.h"
+ #include "tree.h"
++#include "protector.h"
+ /* This file contains the reload pass of the compiler, which is
+    run after register allocation has been done.  It checks that
+@@ -2000,7 +2001,7 @@
+       if (from_reg == -1)
+       {
+         /* No known place to spill from => no slot to reuse.  */
+-        x = assign_stack_local (GET_MODE (regno_reg_rtx[i]), total_size,
++        x = assign_stack_local_for_pseudo_reg (GET_MODE (regno_reg_rtx[i]), total_size,
+                                 inherent_size == total_size ? 0 : -1);
+         if (BYTES_BIG_ENDIAN)
+           /* Cancel the  big-endian correction done in assign_stack_local.
diff --git a/gnu/usr.bin/cc3/cc_int/patches/simplify-rtx.c.patch b/gnu/usr.bin/cc3/cc_int/patches/simplify-rtx.c.patch
new file mode 100644 (file)
index 0000000..783e6ed
--- /dev/null
@@ -0,0 +1,98 @@
+$DragonFly: src/gnu/usr.bin/cc3/cc_int/patches/Attic/simplify-rtx.c.patch,v 1.1 2004/03/05 21:38:44 joerg Exp $
+Index: simplify-rtx.c
+===================================================================
+RCS file: /cvs/src/contrib/gcc-3.3/gcc/simplify-rtx.c,v
+retrieving revision 1.1
+diff -u -r1.1 simplify-rtx.c
+--- simplify-rtx.c     2 Feb 2004 23:09:50 -0000       1.1
++++ simplify-rtx.c     4 Mar 2004 15:18:47 -0000
+@@ -1670,7 +1670,8 @@
+   int n_ops = 2, input_ops = 2, input_consts = 0, n_consts;
+   int first, negate, changed;
+   int i, j;
+-
++  HOST_WIDE_INT fp_offset = 0;
++  
+   memset ((char *) ops, 0, sizeof ops);
+   /* Set up the two operands and then expand them until nothing has been
+@@ -1695,6 +1696,10 @@
+         switch (this_code)
+           {
+           case PLUS:
++          if (flag_propolice_protection
++              && XEXP (this_op, 0) == virtual_stack_vars_rtx
++              && GET_CODE (XEXP (this_op, 1)) == CONST_INT)
++            fp_offset = INTVAL (XEXP (this_op, 1));
+           case MINUS:
+             if (n_ops == 7)
+               return NULL_RTX;
+@@ -1849,10 +1854,10 @@
+       && GET_CODE (ops[n_ops - 1].op) == CONST_INT
+       && CONSTANT_P (ops[n_ops - 2].op))
+     {
+-      rtx value = ops[n_ops - 1].op;
++      int value = INTVAL (ops[n_ops - 1].op);
+       if (ops[n_ops - 1].neg ^ ops[n_ops - 2].neg)
+-      value = neg_const_int (mode, value);
+-      ops[n_ops - 2].op = plus_constant (ops[n_ops - 2].op, INTVAL (value));
++      value = -value;
++      ops[n_ops - 2].op = plus_constant (ops[n_ops - 2].op, value);
+       n_ops--;
+     }
+@@ -1870,6 +1875,54 @@
+       && (n_ops + n_consts > input_ops
+         || (n_ops + n_consts == input_ops && n_consts <= input_consts)))
+     return NULL_RTX;
++
++  if (flag_propolice_protection)
++    {
++      /* keep the addressing style of local variables
++       as (plus (virtual_stack_vars_rtx) (CONST_int x))
++       (1) inline function is expanded, (+ (+VFP c1) -c2)=>(+ VFP c1-c2)
++       (2) the case ary[r-1], (+ (+VFP c1) (+r -1))=>(+ R (+r -1))
++      */
++      for (i = 0; i < n_ops; i++)
++#ifdef FRAME_GROWS_DOWNWARD
++      if (ops[i].op == virtual_stack_vars_rtx)
++#else
++      if (ops[i].op == virtual_stack_vars_rtx
++          || ops[i].op == frame_pointer_rtx)
++#endif
++        {
++          if (GET_CODE (ops[n_ops - 1].op) == CONST_INT)
++            {
++              HOST_WIDE_INT value = INTVAL (ops[n_ops - 1].op);
++              if (n_ops < 3 || value >= fp_offset)
++                {
++                  ops[i].op = plus_constant (ops[i].op, value);
++                  n_ops--;
++                }
++              else
++                {
++                  if (!force
++                      && (n_ops+1 + n_consts > input_ops
++                          || (n_ops+1 + n_consts == input_ops && n_consts <= input_consts)))
++                    return NULL_RTX;
++                  ops[n_ops - 1].op = GEN_INT (value-fp_offset);
++                  ops[i].op = plus_constant (ops[i].op, fp_offset);
++                }
++            }
++          /* buf[BUFSIZE]: buf is the first local variable (+ (+ fp -S) S) 
++             or (+ (fp 0) r) ==> ((+ (+fp 1) r) -1) */
++          else if (fp_offset != 0)
++            return NULL_RTX;
++#ifndef FRAME_GROWS_DOWNWARD
++          /*
++           * For the case of buf[i], i: REG, buf: (plus fp 0),
++           */
++          else if (fp_offset == 0)
++            return NULL_RTX;
++#endif
++          break;
++        }
++    }
+   /* Put a non-negated operand first.  If there aren't any, make all
+      operands positive and negate the whole thing later.  */
diff --git a/gnu/usr.bin/cc3/cc_int/patches/toplev.c.patch b/gnu/usr.bin/cc3/cc_int/patches/toplev.c.patch
new file mode 100644 (file)
index 0000000..400d11b
--- /dev/null
@@ -0,0 +1,68 @@
+$DragonFly: src/gnu/usr.bin/cc3/cc_int/patches/Attic/toplev.c.patch,v 1.1 2004/03/05 21:38:44 joerg Exp $
+Index: toplev.c
+===================================================================
+RCS file: /cvs/src/contrib/gcc-3.3/gcc/toplev.c,v
+retrieving revision 1.1
+diff -u -r1.1 toplev.c
+--- toplev.c   2 Feb 2004 23:09:50 -0000       1.1
++++ toplev.c   4 Mar 2004 15:18:48 -0000
+@@ -904,6 +904,15 @@
+    minimum function alignment.  Zero means no alignment is forced.  */
+ int force_align_functions_log;
++#if defined(STACK_PROTECTOR) && defined(STACK_GROWS_DOWNWARD)
++/* Nonzero means use propolice as a stack protection method */
++int flag_propolice_protection = 1;
++int flag_stack_protection = 0;
++#else
++int flag_propolice_protection = 0;
++int flag_stack_protection = 0;
++#endif
++
+ /* Table of supported debugging formats.  */
+ static const struct
+ {
+@@ -1188,6 +1197,10 @@
+    N_("Trap for signed overflow in addition / subtraction / multiplication") },
+   { "new-ra", &flag_new_regalloc, 1,
+    N_("Use graph coloring register allocation.") },
++  {"stack-protector", &flag_propolice_protection, 1,
++   N_("Enables stack protection") },
++  {"stack-protector-all", &flag_stack_protection, 1,
++   N_("Enables stack protection of every function") } ,
+ };
+ /* Table of language-specific options.  */
+@@ -1547,7 +1560,9 @@
+   {"missing-noreturn", &warn_missing_noreturn, 1,
+    N_("Warn about functions which might be candidates for attribute noreturn") },
+   {"strict-aliasing", &warn_strict_aliasing, 1,
+-   N_ ("Warn about code which might break the strict aliasing rules") }
++   N_ ("Warn about code which might break the strict aliasing rules") },
++  {"stack-protector", &warn_stack_protector, 1,
++   N_("Warn when disabling stack protector for some reason")}
+ };
+ void
+@@ -2449,6 +2464,8 @@
+       insns = get_insns ();
++      if (flag_propolice_protection) prepare_stack_protection (inlinable);
++  
+       /* Dump the rtl code if we are dumping rtl.  */
+       if (open_dump_file (DFI_rtl, decl))
+@@ -5223,6 +5240,12 @@
+     /* The presence of IEEE signaling NaNs, implies all math can trap.  */
+     if (flag_signaling_nans)
+       flag_trapping_math = 1;
++
++    /* This combination makes optimized frame addressings and causes
++       a internal compilation error at prepare_stack_protection.
++       so don't allow it.  */
++    if (flag_stack_protection && !flag_propolice_protection)
++      flag_propolice_protection = TRUE;
+ }
\f
+ /* Initialize the compiler back end.  */
diff --git a/gnu/usr.bin/cc3/cc_int/protector.c b/gnu/usr.bin/cc3/cc_int/protector.c
new file mode 100644 (file)
index 0000000..1b9b0ee
--- /dev/null
@@ -0,0 +1,2626 @@
+/* $DragonFly: src/gnu/usr.bin/cc3/cc_int/Attic/protector.c,v 1.1 2004/03/05 21:38:44 joerg Exp $ */
+
+/* RTL buffer overflow protection function for GNU C compiler
+   Copyright (C) 1987, 88, 89, 92-7, 1998 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include "config.h"
+#include "system.h"
+#include "machmode.h"
+
+#include "rtl.h"
+#include "tree.h"
+#include "regs.h"
+#include "flags.h"
+#include "insn-config.h"
+#include "insn-flags.h"
+#include "expr.h"
+#include "output.h"
+#include "recog.h"
+#include "hard-reg-set.h"
+#include "real.h"
+#include "except.h"
+#include "function.h"
+#include "toplev.h"
+#include "conditions.h"
+#include "insn-attr.h"
+#include "c-tree.h"
+#include "optabs.h"
+#include "reload.h"
+#include "protector.h"
+
+
+void prepare_stack_protection  PARAMS ((int inlinable));
+int search_string_def PARAMS ((tree names));
+rtx assign_stack_local_for_pseudo_reg PARAMS ((enum machine_mode,
+                                              HOST_WIDE_INT, int));
+
+
+/* Warn when not issuing stack smashing protection for some reason */
+int warn_stack_protector;
+
+/* Round a value to the lowest integer less than it that is a multiple of
+   the required alignment.  Avoid using division in case the value is
+   negative.  Assume the alignment is a power of two.  */
+#define FLOOR_ROUND(VALUE,ALIGN) ((VALUE) & ~((ALIGN) - 1))
+
+/* Similar, but round to the next highest integer that meets the
+   alignment.  */
+#define CEIL_ROUND(VALUE,ALIGN)        (((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1))
+
+
+/* Nonzero means use propolice as a stack protection method */
+extern int flag_propolice_protection;
+
+/* This file contains several memory arrangement functions to protect
+   the return address and the frame pointer of the stack
+   from a stack-smashing attack. It also
+   provides the function that protects pointer variables. */
+
+/* Nonzero if function being compiled can define string buffers that may be
+   damaged by the stack-smash attack */
+static int current_function_defines_vulnerable_string;
+static int current_function_defines_short_string;
+static int current_function_has_variable_string;
+static int current_function_defines_vsized_array;
+static int current_function_is_inlinable;
+static int is_array;
+
+static rtx guard_area, _guard;
+static rtx function_first_insn, prologue_insert_point;
+
+/*  */
+static HOST_WIDE_INT sweep_frame_offset;
+static HOST_WIDE_INT push_allocated_offset = 0;
+static HOST_WIDE_INT push_frame_offset = 0;
+static int saved_cse_not_expected = 0;
+
+static int search_string_from_argsandvars PARAMS ((int caller));
+static int search_string_from_local_vars PARAMS ((tree block));
+static int search_pointer_def PARAMS ((tree names));
+static int search_func_pointer PARAMS ((tree type));
+static void reset_used_flags_for_insns PARAMS ((rtx insn));
+static void reset_used_flags_for_decls PARAMS ((tree block));
+static void reset_used_flags_of_plus PARAMS ((rtx x));
+static void rtl_prologue PARAMS ((rtx insn));
+static void rtl_epilogue PARAMS ((rtx fnlastinsn));
+static void arrange_var_order PARAMS ((tree blocks));
+static void copy_args_for_protection PARAMS ((void));
+static void sweep_string_variable
+       PARAMS ((rtx sweep_var, HOST_WIDE_INT var_size));
+static void sweep_string_in_decls
+       PARAMS ((tree block, HOST_WIDE_INT sweep_offset, HOST_WIDE_INT size));
+static void sweep_string_in_args
+       PARAMS ((tree parms, HOST_WIDE_INT sweep_offset, HOST_WIDE_INT size));
+static void sweep_string_use_of_insns
+       PARAMS ((rtx insn, HOST_WIDE_INT sweep_offset, HOST_WIDE_INT size));
+static void sweep_string_in_operand
+       PARAMS ((rtx insn, rtx *loc,
+                HOST_WIDE_INT sweep_offset, HOST_WIDE_INT size));
+static void move_arg_location
+       PARAMS ((rtx insn, rtx orig, rtx new, HOST_WIDE_INT var_size));
+static void change_arg_use_of_insns
+       PARAMS ((rtx insn, rtx orig, rtx *new, HOST_WIDE_INT size));
+static void change_arg_use_of_insns_2
+       PARAMS ((rtx insn, rtx orig, rtx *new, HOST_WIDE_INT size));
+static void change_arg_use_in_operand
+       PARAMS ((rtx x, rtx orig, rtx *new, HOST_WIDE_INT size));
+static void validate_insns_of_varrefs PARAMS ((rtx insn));
+static void validate_operand_of_varrefs PARAMS ((rtx insn, rtx *loc));
+
+#ifndef SUSPICIOUS_BUF_SIZE
+#define SUSPICIOUS_BUF_SIZE 8
+#endif
+
+#define AUTO_BASEPTR(X) \
+  (GET_CODE (X) == PLUS ? XEXP (X, 0) : X)
+#define AUTO_OFFSET(X) \
+  (GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0)
+#undef PARM_PASSED_IN_MEMORY
+#define PARM_PASSED_IN_MEMORY(PARM) \
+ (GET_CODE (DECL_INCOMING_RTL (PARM)) == MEM)
+#define VIRTUAL_STACK_VARS_P(X) \
+ ((X) == virtual_stack_vars_rtx || (GET_CODE (X) == REG && (X)->used))
+#define TREE_VISITED(NODE) ((NODE)->common.unused_0)
+
+
+
+void
+prepare_stack_protection (inlinable)
+     int inlinable;
+{
+  tree blocks = DECL_INITIAL (current_function_decl);
+  current_function_is_inlinable = inlinable && !flag_no_inline;
+  push_frame_offset = push_allocated_offset = 0;
+  saved_cse_not_expected = 0;
+
+  /*
+    skip the protection if the function has no block
+    or it is an inline function
+  */
+  if (current_function_is_inlinable) validate_insns_of_varrefs (get_insns ());
+  if (! blocks || current_function_is_inlinable) return;
+
+  current_function_defines_vulnerable_string
+    = search_string_from_argsandvars (0);
+
+  if (current_function_defines_vulnerable_string
+      || flag_stack_protection)
+    {
+      HOST_WIDE_INT offset;
+      function_first_insn = get_insns ();
+
+      if (current_function_contains_functions) {
+         if (warn_stack_protector)
+             warning ("not protecting function: it contains functions");
+         return;
+      }
+
+      /* Initialize recognition, indicating that volatile is OK.  */
+      init_recog ();
+
+      sweep_frame_offset = 0;
+       
+#ifdef STACK_GROWS_DOWNWARD
+      /*
+       frame_offset: offset to end of allocated area of stack frame.
+        It is defined in the function.c
+      */
+
+      /* the location must be before buffers */
+      guard_area = assign_stack_local (BLKmode, UNITS_PER_GUARD, -1);
+      PUT_MODE (guard_area, GUARD_m);
+      MEM_VOLATILE_P (guard_area) = 1;
+
+#ifndef FRAME_GROWS_DOWNWARD
+      sweep_frame_offset = frame_offset;
+#endif
+
+      /* For making room for guard value, scan all insns and fix the offset
+        address of the variable that is based on frame pointer.
+        Scan all declarations of variables and fix the offset address
+        of the variable that is based on the frame pointer */
+      sweep_string_variable (guard_area, UNITS_PER_GUARD);
+
+       
+      /* the location of guard area moves to the beginning of stack frame */
+      if ((offset = AUTO_OFFSET(XEXP (guard_area, 0))))
+       XEXP (XEXP (guard_area, 0), 1)
+         = gen_rtx_CONST_INT (VOIDmode, sweep_frame_offset);
+
+
+      /* Insert prologue rtl instructions */
+      rtl_prologue (function_first_insn);
+
+      if (! current_function_has_variable_string)
+       {
+         /* Generate argument saving instruction */
+         copy_args_for_protection ();
+
+#ifndef FRAME_GROWS_DOWNWARD
+         /* If frame grows upward, character string copied from an arg
+            stays top of the guard variable.
+            So sweep the guard variable again */
+         sweep_frame_offset = CEIL_ROUND (frame_offset,
+                                          BIGGEST_ALIGNMENT / BITS_PER_UNIT);
+         sweep_string_variable (guard_area, UNITS_PER_GUARD);
+#endif
+       }
+      else if (warn_stack_protector)
+       warning ("not protecting variables: it has a variable length buffer");
+#endif
+#ifndef FRAME_GROWS_DOWNWARD
+      if (STARTING_FRAME_OFFSET == 0)
+       {
+         /* this may be only for alpha */
+         push_allocated_offset = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
+         assign_stack_local (BLKmode, push_allocated_offset, -1);
+         sweep_frame_offset = frame_offset;
+         sweep_string_variable (const0_rtx, -push_allocated_offset);
+         sweep_frame_offset = AUTO_OFFSET (XEXP (guard_area, 0));
+       }
+#endif
+
+      /* Arrange the order of local variables */
+      arrange_var_order (blocks);
+
+#ifdef STACK_GROWS_DOWNWARD
+      /* Insert epilogue rtl instructions */
+      rtl_epilogue (get_last_insn ());
+#endif
+      init_recog_no_volatile ();
+    }
+  else if (current_function_defines_short_string
+          && warn_stack_protector)
+    warning ("not protecting function: buffer is less than %d bytes long",
+            SUSPICIOUS_BUF_SIZE);
+}
+
+/*
+  search string from arguments and local variables
+  caller: 0 means call from protector_stack_protection
+          1 means call from push_frame
+*/
+static int
+search_string_from_argsandvars (caller)
+     int caller;
+{
+  tree blocks, parms;
+  int string_p;
+
+  /* saves a latest search result as a cached infomation */
+  static tree __latest_search_decl = 0;
+  static int  __latest_search_result = FALSE;
+
+  if (__latest_search_decl == current_function_decl)
+    return __latest_search_result;
+  else if (caller) return FALSE;
+  __latest_search_decl = current_function_decl;
+  __latest_search_result = TRUE;
+  
+  current_function_defines_short_string = FALSE;
+  current_function_has_variable_string = FALSE;
+  current_function_defines_vsized_array = FALSE;
+
+  /*
+    search a string variable from local variables
+  */
+  blocks = DECL_INITIAL (current_function_decl);
+  string_p = search_string_from_local_vars (blocks);
+
+  if (!current_function_defines_vsized_array && current_function_calls_alloca)
+    {
+      current_function_has_variable_string = TRUE;
+      return TRUE;
+    }
+
+  if (string_p) return TRUE;
+
+#ifdef STACK_GROWS_DOWNWARD
+  /*
+    search a string variable from arguments
+  */
+  parms = DECL_ARGUMENTS (current_function_decl);
+
+  for (; parms; parms = TREE_CHAIN (parms))
+    if (DECL_NAME (parms) && TREE_TYPE (parms) != error_mark_node)
+      {
+       if (PARM_PASSED_IN_MEMORY (parms) && DECL_NAME (parms))
+         {
+           string_p = search_string_def (TREE_TYPE(parms));
+           if (string_p) return TRUE;
+         }
+      }
+#endif
+
+  __latest_search_result = FALSE;
+  return FALSE;
+}
+
+
+static int
+search_string_from_local_vars (block)
+     tree block;
+{
+  tree types;
+  int found = FALSE;
+
+  while (block && TREE_CODE(block)==BLOCK)
+    {
+      types = BLOCK_VARS(block);
+
+      while (types)
+       {
+         /* skip the declaration that refers an external variable */
+         /* name: types.decl.name.identifier.id                   */
+         if (! DECL_EXTERNAL (types) && ! TREE_STATIC (types)
+             && TREE_CODE (types) == VAR_DECL
+             && ! DECL_ARTIFICIAL (types)
+             && DECL_RTL_SET_P (types)
+             && GET_CODE (DECL_RTL (types)) == MEM
+
+             && search_string_def (TREE_TYPE (types)))
+           {
+             rtx home = DECL_RTL (types);
+
+             if (GET_CODE (home) == MEM
+                 && (GET_CODE (XEXP (home, 0)) == MEM
+                     ||
+                     (GET_CODE (XEXP (home, 0)) == REG
+                      && XEXP (home, 0) != virtual_stack_vars_rtx
+                      && REGNO (XEXP (home, 0)) != HARD_FRAME_POINTER_REGNUM
+                      && REGNO (XEXP (home, 0)) != STACK_POINTER_REGNUM
+#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+                      && REGNO (XEXP (home, 0)) != ARG_POINTER_REGNUM
+#endif
+                      )))
+               /* If the value is indirect by memory or by a register
+                  that isn't the frame pointer then it means the object is
+                  variable-sized and address through
+                  that register or stack slot.
+                  The protection has no way to hide pointer variables
+                  behind the array, so all we can do is staying
+                  the order of variables and arguments. */
+               {
+                 current_function_has_variable_string = TRUE;
+               }
+           
+             /* found character array */
+             found = TRUE;
+           }
+
+         types = TREE_CHAIN(types);
+       }
+
+      if (search_string_from_local_vars (BLOCK_SUBBLOCKS (block)))
+       {
+         found = TRUE;
+       }
+
+      block = BLOCK_CHAIN (block);
+    }
+    
+  return found;
+}
+
+
+/*
+ * search a character array from the specified type tree
+ */
+int
+search_string_def (type)
+     tree type;
+{
+  tree tem;
+    
+  if (! type)
+    return FALSE;
+
+  switch (TREE_CODE (type))
+    {
+    case ARRAY_TYPE:
+      /* Check if the array is a variable-sized array */
+      if (TYPE_DOMAIN (type) == 0
+         || (TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != 0
+             && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == NOP_EXPR))
+       current_function_defines_vsized_array = TRUE;
+
+      /* TREE_CODE( TREE_TYPE(type) ) == INTEGER_TYPE */
+      if (TYPE_MAIN_VARIANT (TREE_TYPE(type)) == char_type_node
+         || TYPE_MAIN_VARIANT (TREE_TYPE(type)) == signed_char_type_node
+         || TYPE_MAIN_VARIANT (TREE_TYPE(type)) == unsigned_char_type_node)
+       {
+         /* Check if the string is a variable string */
+         if (TYPE_DOMAIN (type) == 0
+             ||
+             (TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != 0
+              && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == NOP_EXPR))
+           return TRUE;
+
+#if SUSPICIOUS_BUF_SIZE > 0
+         /* Check if the string size is greater than SUSPICIOUS_BUF_SIZE */
+         if (TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != 0
+             &&
+             TREE_INT_CST_LOW(TYPE_MAX_VALUE(TYPE_DOMAIN(type)))+1
+             >= SUSPICIOUS_BUF_SIZE)
+           return TRUE;
+
+         current_function_defines_short_string = TRUE;
+#else
+         return TRUE;
+#endif
+       }
+      
+      /* to protect every functions, sweep any arrays to the frame top */
+      is_array = TRUE;
+
+      return search_string_def(TREE_TYPE(type));
+       
+    case UNION_TYPE:
+    case QUAL_UNION_TYPE:
+    case RECORD_TYPE:
+      /* Output the name, type, position (in bits), size (in bits) of each
+        field.  */
+      for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
+       {
+         /* Omit here local type decls until we know how to support them. */
+         if ((TREE_CODE (tem) == TYPE_DECL)
+             || (TREE_CODE (tem) == VAR_DECL && TREE_STATIC (tem)))
+           continue;
+
+         if (search_string_def(TREE_TYPE(tem))) return TRUE;
+       }
+      break;
+       
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
+      /* I'm not sure whether OFFSET_TYPE needs this treatment,
+        so I'll play safe and return 1.  */
+    case OFFSET_TYPE:
+    default:
+      break;
+    }
+
+  return FALSE;
+}
+
+/*
+ * examine whether the input contains frame pointer addressing
+ */
+int
+contains_fp (op)
+     rtx op;
+{
+  register enum rtx_code code;
+  rtx x;
+  int i, j;
+  const char *fmt;
+
+  x = op;
+  if (x == 0)
+    return FALSE;
+
+  code = GET_CODE (x);
+
+  switch (code)
+    {
+    case CONST_INT:
+    case CONST_DOUBLE:
+    case CONST:
+    case SYMBOL_REF:
+    case CODE_LABEL:
+    case REG:
+    case ADDRESSOF:
+      return FALSE;
+
+    case PLUS:
+      if (XEXP (x, 0) == virtual_stack_vars_rtx
+         && CONSTANT_P (XEXP (x, 1)))
+       return TRUE;
+
+    default:
+      break;
+    }
+
+  /* Scan all subexpressions.  */
+  fmt = GET_RTX_FORMAT (code);
+  for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
+    if (*fmt == 'e')
+      {
+       if (contains_fp (XEXP (x, i))) return TRUE;
+      }
+    else if (*fmt == 'E')
+      for (j = 0; j < XVECLEN (x, i); j++)
+       if (contains_fp (XVECEXP (x, i, j))) return TRUE;
+
+  return FALSE;
+}
+
+
+static int
+search_pointer_def (type)
+     tree type;
+{
+  tree tem;
+    
+  if (! type)
+    return FALSE;
+
+  switch (TREE_CODE (type))
+    {
+    case UNION_TYPE:
+    case QUAL_UNION_TYPE:
+    case RECORD_TYPE:
+      /* Output the name, type, position (in bits), size (in bits) of each
+        field.  */
+      for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
+       {
+         /* Omit here local type decls until we know how to support them. */
+         if ((TREE_CODE (tem) == TYPE_DECL)
+             || (TREE_CODE (tem) == VAR_DECL && TREE_STATIC (tem)))
+           continue;
+
+         if (search_pointer_def (TREE_TYPE(tem))) return TRUE;
+       }
+      break;
+
+    case ARRAY_TYPE:
+      return search_pointer_def (TREE_TYPE(type));
+       
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
+    case OFFSET_TYPE:
+      if (TYPE_READONLY (TREE_TYPE (type)))
+       {
+         /* unless this pointer contains function pointer,
+            it should be protected */
+         return search_func_pointer (TREE_TYPE (type));
+       }
+      return TRUE;
+       
+    default:
+      break;
+    }
+
+  return FALSE;
+}
+
+
+static int
+search_func_pointer (type)
+     tree type;
+{
+  tree tem;
+    
+  if (! type)
+    return FALSE;
+
+  switch (TREE_CODE (type))
+    {
+    case UNION_TYPE:
+    case QUAL_UNION_TYPE:
+    case RECORD_TYPE:
+       if (! TREE_VISITED (type))
+         {
+           /* mark the type as having been visited already */
+           TREE_VISITED (type) = 1;
+
+           /* Output the name, type, position (in bits), size (in bits) of
+              each field.  */
+           for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
+             {
+               if (TREE_CODE (tem) == FIELD_DECL
+                   && search_func_pointer (TREE_TYPE(tem))) {
+                 TREE_VISITED (type) = 0;
+                 return TRUE;
+               }
+             }
+           
+           TREE_VISITED (type) = 0;
+         }
+       break;
+
+    case ARRAY_TYPE:
+      return search_func_pointer (TREE_TYPE(type));
+       
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
+      /* I'm not sure whether OFFSET_TYPE needs this treatment,
+        so I'll play safe and return 1.  */
+    case OFFSET_TYPE:
+      if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
+       return TRUE;
+      return search_func_pointer (TREE_TYPE(type));
+       
+    default:
+      break;
+    }
+
+  return FALSE;
+}
+
+
+static void
+reset_used_flags_for_insns (insn)
+     rtx insn;
+{
+  register int i, j;
+  register enum rtx_code code;
+  register const char *format_ptr;
+
+  for (; insn; insn = NEXT_INSN (insn))
+    if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
+       || GET_CODE (insn) == CALL_INSN)
+      {
+       code = GET_CODE (insn);
+       insn->used = 0;
+       format_ptr = GET_RTX_FORMAT (code);
+
+       for (i = 0; i < GET_RTX_LENGTH (code); i++)
+         {
+           switch (*format_ptr++) {
+           case 'e':
+             reset_used_flags_of_plus (XEXP (insn, i));
+             break;
+                       
+           case 'E':
+             for (j = 0; j < XVECLEN (insn, i); j++)
+               reset_used_flags_of_plus (XVECEXP (insn, i, j));
+             break;
+           }
+         }
+      }
+}
+
+static void
+reset_used_flags_for_decls (block)
+     tree block;
+{
+  tree types;
+  rtx home;
+
+  while (block && TREE_CODE(block)==BLOCK)
+    {
+      types = BLOCK_VARS(block);
+       
+      while (types)
+       {
+         /* skip the declaration that refers an external variable and
+            also skip an global variable */
+         if (! DECL_EXTERNAL (types))
+           {
+             if (!DECL_RTL_SET_P (types)) goto next;
+             home = DECL_RTL (types);
+
+             if (GET_CODE (home) == MEM
+                 && GET_CODE (XEXP (home, 0)) == PLUS
+                 && GET_CODE (XEXP (XEXP (home, 0), 1)) == CONST_INT)
+               {
+                 XEXP (home, 0)->used = 0;
+               }
+           }
+       next:
+         types = TREE_CHAIN(types);
+       }
+
+      reset_used_flags_for_decls (BLOCK_SUBBLOCKS (block));
+
+      block = BLOCK_CHAIN (block);
+    }
+}
+
+/* Clear the USED bits only of type PLUS in X */
+
+static void
+reset_used_flags_of_plus (x)
+     rtx x;
+{
+  register int i, j;
+  register enum rtx_code code;
+  register const char *format_ptr;
+
+  if (x == 0)
+    return;
+
+  code = GET_CODE (x);
+
+  /* These types may be freely shared so we needn't do any resetting
+     for them.  */
+
+  switch (code)
+    {
+    case REG:
+    case QUEUED:
+    case CONST_INT:
+    case CONST_DOUBLE:
+    case SYMBOL_REF:
+    case CODE_LABEL:
+    case PC:
+    case CC0:
+      return;
+
+    case INSN:
+    case JUMP_INSN:
+    case CALL_INSN:
+    case NOTE:
+    case LABEL_REF:
+    case BARRIER:
+      /* The chain of insns is not being copied.  */
+      return;
+      
+    case PLUS:
+      x->used = 0;
+      break;
+
+    case CALL_PLACEHOLDER:
+      reset_used_flags_for_insns (XEXP (x, 0));
+      reset_used_flags_for_insns (XEXP (x, 1));
+      reset_used_flags_for_insns (XEXP (x, 2));
+      break;
+
+    default:
+      break;
+    }
+
+  format_ptr = GET_RTX_FORMAT (code);
+  for (i = 0; i < GET_RTX_LENGTH (code); i++)
+    {
+      switch (*format_ptr++)
+       {
+       case 'e':
+         reset_used_flags_of_plus (XEXP (x, i));
+         break;
+
+       case 'E':
+         for (j = 0; j < XVECLEN (x, i); j++)
+           reset_used_flags_of_plus (XVECEXP (x, i, j));
+         break;
+       }
+    }
+}
+
+
+static void
+rtl_prologue (insn)
+     rtx insn;
+{
+#if defined(INIT_SECTION_ASM_OP) && !defined(INVOKE__main)
+#undef HAS_INIT_SECTION
+#define HAS_INIT_SECTION
+#endif
+
+  rtx _val;
+
+  for (; insn; insn = NEXT_INSN (insn))
+    if (GET_CODE (insn) == NOTE
+       && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)
+      break;
+  
+#if !defined (HAS_INIT_SECTION)
+  /* If this function is `main', skip a call to `__main'
+     to run guard instruments after global initializers, etc.  */
+  if (DECL_NAME (current_function_decl)
+      && MAIN_NAME_P (DECL_NAME (current_function_decl))
+      && DECL_CONTEXT (current_function_decl) == NULL_TREE)
+    {
+      rtx fbinsn = insn;
+      for (; insn; insn = NEXT_INSN (insn))
+       if (GET_CODE (insn) == NOTE
+           && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG)
+         break;
+      if (insn == 0) insn = fbinsn;
+    }
+#endif
+
+  /* mark the next insn of FUNCTION_BEG insn */
+  prologue_insert_point = NEXT_INSN (insn);
+               
+  start_sequence ();
+
+  _guard = gen_rtx_MEM (GUARD_m, gen_rtx_SYMBOL_REF (Pmode, "__guard"));
+  emit_move_insn ( guard_area, _guard);
+
+  _val = get_insns ();
+  end_sequence ();
+
+  emit_insn_before (_val, prologue_insert_point);
+}
+
+static void
+rtl_epilogue (insn)
+     rtx insn;
+{
+  rtx if_false_label;
+  rtx _val;
+  rtx funcname;
+  tree funcstr;
+  int  flag_have_return = FALSE;
+               
+  start_sequence ();
+
+#ifdef HAVE_return
+  if (HAVE_return)
+    {
+      rtx insn;
+      return_label = gen_label_rtx ();
+      
+      for (insn = prologue_insert_point; insn; insn = NEXT_INSN (insn))
+       if (GET_CODE (insn) == JUMP_INSN
+           && GET_CODE (PATTERN (insn)) == RETURN
+           && GET_MODE (PATTERN (insn)) == VOIDmode)
+         {
+           rtx pat = gen_rtx_SET (VOIDmode,
+                                  pc_rtx,
+                                  gen_rtx_LABEL_REF (VOIDmode,
+                                                     return_label));
+           PATTERN (insn) = pat;
+           flag_have_return = TRUE;
+         }
+
+
+      emit_label (return_label);
+    }
+#endif
+
+  /*                                          if (guard_area != _guard) */
+  compare_from_rtx (guard_area, _guard, NE, 0, GUARD_m, NULL_RTX);
+
+  if_false_label = gen_label_rtx ();           /* { */
+  emit_jump_insn ( gen_beq(if_false_label));
+
+  /* generate string for the current function name */
+  funcstr = build_string (strlen(current_function_name)+1,
+                         current_function_name);
+  TREE_TYPE (funcstr) = build_array_type (char_type_node, 0);
+  funcname = output_constant_def (funcstr, 1);
+
+  emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__stack_smash_handler"),
+                    0, VOIDmode, 2,
+                     XEXP (funcname, 0), Pmode, guard_area, GUARD_m);
+
+  /* generate RTL to return from the current function */
+               
+  emit_barrier ();                             /* } */
+  emit_label (if_false_label);
+
+  /* generate RTL to return from the current function */
+  if (DECL_RTL_SET_P (DECL_RESULT (current_function_decl)))
+    use_return_register ();
+
+#ifdef HAVE_return
+  if (HAVE_return && flag_have_return)
+    {
+      emit_jump_insn (gen_return ());
+      emit_barrier ();
+    }
+#endif
+  
+  _val = get_insns ();
+  end_sequence ();
+
+  emit_insn_after (_val, insn);
+}
+
+
+static void
+arrange_var_order (block)
+     tree block;
+{
+  tree types;
+  HOST_WIDE_INT offset;
+    
+  while (block && TREE_CODE(block)==BLOCK)
+    {
+      types = BLOCK_VARS (block);
+
+      while (types)
+       {
+         /* skip the declaration that refers an external variable */
+         /* name: types.decl.assembler_name.id                    */
+         if (! DECL_EXTERNAL (types) && ! TREE_STATIC (types)
+             && TREE_CODE (types) == VAR_DECL
+             && ! DECL_ARTIFICIAL (types)
+             && ! DECL_INLINE (types)  /* don't sweep inlined string */
+             && DECL_RTL_SET_P (types)
+             && GET_CODE (DECL_RTL (types)) == MEM
+
+             && (is_array=0, search_string_def (TREE_TYPE (types))
+                 || (! current_function_defines_vulnerable_string
+                     && is_array)))
+           {
+             rtx home = DECL_RTL (types);
+
+             if (!(GET_CODE (home) == MEM
+                   && (GET_CODE (XEXP (home, 0)) == MEM
+                       ||
+                       (GET_CODE (XEXP (home, 0)) == REG
+                        && XEXP (home, 0) != virtual_stack_vars_rtx
+                        && REGNO (XEXP (home, 0)) != HARD_FRAME_POINTER_REGNUM
+                        && REGNO (XEXP (home, 0)) != STACK_POINTER_REGNUM
+#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+                        && REGNO (XEXP (home, 0)) != ARG_POINTER_REGNUM
+#endif
+                        ))))
+               {
+                 /* found a string variable */
+                 HOST_WIDE_INT var_size =
+                   ((TREE_INT_CST_LOW (DECL_SIZE (types)) + BITS_PER_UNIT - 1)
+                    / BITS_PER_UNIT);
+
+                 if (GET_MODE (DECL_RTL (types)) == BLKmode)
+                   {
+                     int alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
+                     var_size = CEIL_ROUND (var_size, alignment);
+                   }
+
+                 /* skip the variable if it is top of the region
+                    specified by sweep_frame_offset */
+                 offset = AUTO_OFFSET (XEXP (DECL_RTL (types), 0));
+                 if (offset == sweep_frame_offset - var_size)
+                   sweep_frame_offset -= var_size;
+                     
+                 else if (offset < sweep_frame_offset - var_size)
+                   sweep_string_variable (DECL_RTL (types), var_size);
+               }
+           }
+
+         types = TREE_CHAIN(types);
+       }
+
+      arrange_var_order (BLOCK_SUBBLOCKS (block));
+
+      block = BLOCK_CHAIN (block);
+    }
+}
+
+
+static void
+copy_args_for_protection ()
+{
+  tree parms = DECL_ARGUMENTS (current_function_decl);
+  rtx temp_rtx;
+
+  parms = DECL_ARGUMENTS (current_function_decl);
+  for (; parms; parms = TREE_CHAIN (parms))
+    if (DECL_NAME (parms) && TREE_TYPE (parms) != error_mark_node)
+      {
+       if (PARM_PASSED_IN_MEMORY (parms) && DECL_NAME (parms))
+         {
+           int string_p;
+
+           /*
+             skip arguemnt protection if the last argument is used
+             for the variable argument
+           */
+           /*
+             tree fntype;
+             if (TREE_CHAIN (parms) == 0)
+             {
+               fntype = TREE_TYPE (current_function_decl);
+
+               if ((TYPE_ARG_TYPES (fntype) != 0
+                    && TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) 
+                         != void_type_node)
+                    || current_function_varargs)
+                 continue;
+             }
+           */
+
+           string_p = search_string_def (TREE_TYPE(parms));
+
+           /* check if it is a candidate to move */
+           if (string_p || search_pointer_def (TREE_TYPE (parms)))
+             {
+               int arg_size
+                 = ((TREE_INT_CST_LOW (DECL_SIZE (parms)) + BITS_PER_UNIT - 1)
+                    / BITS_PER_UNIT);
+               tree passed_type = DECL_ARG_TYPE (parms);
+               tree nominal_type = TREE_TYPE (parms);
+               
+               start_sequence ();
+
+               if (GET_CODE (DECL_RTL (parms)) == REG)
+                 {
+                   rtx safe = 0;
+                   
+                   change_arg_use_of_insns (prologue_insert_point,
+                                            DECL_RTL (parms), &safe, 0);
+                   if (safe)
+                     {
+                       /* generate codes for copying the content */
+                       rtx movinsn = emit_move_insn (safe, DECL_RTL (parms));
+                   
+                       /* avoid register elimination in gcse.c (COPY-PROP)*/
+                       PATTERN (movinsn)->volatil = 1;
+                       
+                       /* save debugger info */
+                       DECL_INCOMING_RTL (parms) = safe;
+                     }
+                 }
+               else if (GET_CODE (DECL_RTL (parms)) == MEM
+                        && GET_CODE (XEXP (DECL_RTL (parms), 0)) == ADDRESSOF)
+                 {
+                   rtx movinsn;
+                   rtx safe = gen_reg_rtx (GET_MODE (DECL_RTL (parms)));
+
+                   /* generate codes for copying the content */
+                   movinsn = emit_move_insn (safe, DECL_INCOMING_RTL (parms));
+                   /* avoid register elimination in gcse.c (COPY-PROP)*/
+                   PATTERN (movinsn)->volatil = 1;
+
+                   /* change the addressof information to the newly
+                      allocated pseudo register */
+                   emit_move_insn (DECL_RTL (parms), safe);
+
+                   /* save debugger info */
+                   DECL_INCOMING_RTL (parms) = safe;
+                 }
+                       
+               /* See if the frontend wants to pass this by invisible
+                  reference.  */
+               else if (passed_type != nominal_type
+                        && POINTER_TYPE_P (passed_type)
+                        && TREE_TYPE (passed_type) == nominal_type)
+                 {
+                   rtx safe = 0, orig = XEXP (DECL_RTL (parms), 0);
+
+                   change_arg_use_of_insns (prologue_insert_point,
+                                            orig, &safe, 0);
+                   if (safe)
+                     {
+                       /* generate codes for copying the content */
+                       rtx movinsn = emit_move_insn (safe, orig);
+                   
+                       /* avoid register elimination in gcse.c (COPY-PROP)*/
+                       PATTERN (movinsn)->volatil = 1;
+                       
+                       /* save debugger info */
+                       DECL_INCOMING_RTL (parms) = safe;
+                     }
+                 }
+
+               else
+                 {
+                   /* declare temporary local variable DECL_NAME (parms) */
+                   temp_rtx
+                     = assign_stack_local (DECL_MODE (parms), arg_size,
+                                           DECL_MODE (parms) == BLKmode ?
+                                           -1 : 0);
+                   
+                   MEM_IN_STRUCT_P (temp_rtx)
+                     = AGGREGATE_TYPE_P (TREE_TYPE (parms));
+                   set_mem_alias_set (temp_rtx, get_alias_set (parms));
+
+                   /* move_arg_location may change the contents of
+                      DECL_RTL (parms). to avoid this, copies the contents */
+                   /* SET_DECL_RTL (parms, copy_rtx (DECL_RTL (parms))); */
+
+                   /* generate codes for copying the content */
+                   store_expr (parms, temp_rtx, 0);
+
+                   /* change the reference for each instructions */
+                   move_arg_location (prologue_insert_point, DECL_RTL (parms),
+                                      temp_rtx, arg_size);
+
+                   /* change the location of parms variable */
+                   SET_DECL_RTL (parms, temp_rtx);
+
+                   /* change debugger info */
+                   DECL_INCOMING_RTL (parms) = temp_rtx;
+                 }
+
+               emit_insn_before (get_insns (), prologue_insert_point);
+               end_sequence ();
+
+#ifdef FRAME_GROWS_DOWNWARD
+               /* process the string argument */
+               if (string_p && DECL_MODE (parms) == BLKmode)
+                 {
+                   int alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
+                   arg_size = CEIL_ROUND (arg_size, alignment);
+                       
+                   /* change the reference for each instructions */
+                   sweep_string_variable (DECL_RTL (parms), arg_size);
+                 }
+#endif
+             }
+         }
+      }
+}
+
+
+/*
+  sweep a string variable to the local variable addressed
+  by sweep_frame_offset, that is a last position of string variables.
+*/
+static void
+sweep_string_variable (sweep_var, var_size)
+     rtx sweep_var;
+     HOST_WIDE_INT var_size;
+{
+  HOST_WIDE_INT sweep_offset;
+
+  switch (GET_CODE (sweep_var))
+    {
+    case MEM:
+      if (GET_CODE (XEXP (sweep_var, 0)) == ADDRESSOF
+         && GET_CODE (XEXP (XEXP (sweep_var, 0), 0)) == REG)
+       return;
+      sweep_offset = AUTO_OFFSET(XEXP (sweep_var, 0));
+      break;
+    case CONST_INT:
+      sweep_offset = INTVAL (sweep_var);
+      break;
+    default:
+      abort ();
+    }
+
+  /* scan all declarations of variables and fix the offset address of
+     the variable based on the frame pointer */
+  sweep_string_in_decls (DECL_INITIAL (current_function_decl),
+                        sweep_offset, var_size);
+
+  /* scan all argument variable and fix the offset address based on
+     the frame pointer */
+  sweep_string_in_args (DECL_ARGUMENTS (current_function_decl),
+                       sweep_offset, var_size);
+
+  /* For making room for sweep variable, scan all insns and
+     fix the offset address of the variable that is based on frame pointer */
+  sweep_string_use_of_insns (function_first_insn, sweep_offset, var_size);
+
+
+  /* Clear all the USED bits in operands of all insns and declarations of
+     local vars */
+  reset_used_flags_for_decls (DECL_INITIAL (current_function_decl));
+  reset_used_flags_for_insns (function_first_insn);
+
+  sweep_frame_offset -= var_size;
+}
+
+
+
+/*
+  move an argument to the local variable addressed by frame_offset
+*/
+static void
+move_arg_location (insn, orig, new, var_size)
+     rtx  insn, orig, new;
+     HOST_WIDE_INT var_size;
+{
+  /* For making room for sweep variable, scan all insns and
+     fix the offset address of the variable that is based on frame pointer */
+  change_arg_use_of_insns (insn, orig, &new, var_size);
+
+
+  /* Clear all the USED bits in operands of all insns and declarations
+     of local vars */
+  reset_used_flags_for_insns (insn);
+}
+
+
+static void
+sweep_string_in_decls (block, sweep_offset, sweep_size)
+     tree block;
+     HOST_WIDE_INT sweep_offset, sweep_size;
+{
+  tree types;
+  HOST_WIDE_INT offset;
+  rtx home;
+
+  while (block && TREE_CODE(block)==BLOCK)
+    {
+      types = BLOCK_VARS(block);
+       
+      while (types)
+       {
+         /* skip the declaration that refers an external variable and
+            also skip an global variable */
+         if (! DECL_EXTERNAL (types) && ! TREE_STATIC (types)) {
+           
+           if (!DECL_RTL_SET_P (types)) goto next;
+           home = DECL_RTL (types);
+
+           /* process for static local variable */
+           if (GET_CODE (home) == MEM
+               && GET_CODE (XEXP (home, 0)) == SYMBOL_REF)
+             goto next;
+
+           if (GET_CODE (home) == MEM
+               && XEXP (home, 0) == virtual_stack_vars_rtx)
+             {
+               offset = 0;
+               
+               /* the operand related to the sweep variable */
+               if (sweep_offset <= offset
+                   && offset < sweep_offset + sweep_size)
+                 {
+                   offset = sweep_frame_offset - sweep_size - sweep_offset;
+
+                   XEXP (home, 0) = plus_constant (virtual_stack_vars_rtx,
+                                                   offset);
+                   XEXP (home, 0)->used = 1;
+                 }
+               else if (sweep_offset <= offset
+                        && offset < sweep_frame_offset)
+                 {
+                   /* the rest of variables under sweep_frame_offset,
+                      shift the location */
+                   XEXP (home, 0) = plus_constant (virtual_stack_vars_rtx,
+                                                   -sweep_size);
+                   XEXP (home, 0)->used = 1;
+                 }
+             }
+               
+           if (GET_CODE (home) == MEM
+               && GET_CODE (XEXP (home, 0)) == MEM)
+             {
+               /* process for dynamically allocated aray */
+               home = XEXP (home, 0);
+             }
+               
+           if (GET_CODE (home) == MEM
+               && GET_CODE (XEXP (home, 0)) == PLUS
+               && XEXP (XEXP (home, 0), 0) == virtual_stack_vars_rtx
+               && GET_CODE (XEXP (XEXP (home, 0), 1)) == CONST_INT)
+             {
+               if (! XEXP (home, 0)->used)
+                 {
+                   offset = AUTO_OFFSET(XEXP (home, 0));
+
+                   /* the operand related to the sweep variable */
+                   if (sweep_offset <= offset
+                       && offset < sweep_offset + sweep_size)
+                     {
+
+                       offset
+                         += sweep_frame_offset - sweep_size - sweep_offset;
+                       XEXP (XEXP (home, 0), 1) = gen_rtx_CONST_INT (VOIDmode,
+                                                                     offset);
+
+                       /* mark */
+                       XEXP (home, 0)->used = 1;
+                     }
+                   else if (sweep_offset <= offset
+                            && offset < sweep_frame_offset)
+                     { /* the rest of variables under sweep_frame_offset,
+                          so shift the location */
+
+                       XEXP (XEXP (home, 0), 1)
+                         = gen_rtx_CONST_INT (VOIDmode, offset - sweep_size);
+
+                       /* mark */
+                       XEXP (home, 0)->used = 1;
+                     }
+                 }
+             }
+
+         }
+       next:
+         types = TREE_CHAIN(types);
+       }
+
+      sweep_string_in_decls (BLOCK_SUBBLOCKS (block),
+                            sweep_offset, sweep_size);
+      block = BLOCK_CHAIN (block);
+    }
+}
+
+
+static void
+sweep_string_in_args (parms, sweep_offset, sweep_size)
+     tree parms;
+     HOST_WIDE_INT sweep_offset, sweep_size;
+{
+  rtx home;
+  HOST_WIDE_INT offset;
+    
+  for (; parms; parms = TREE_CHAIN (parms))
+    if (DECL_NAME (parms) && TREE_TYPE (parms) != error_mark_node)
+      {
+       if (PARM_PASSED_IN_MEMORY (parms) && DECL_NAME (parms))
+         {
+           home = DECL_INCOMING_RTL (parms);
+
+           if (XEXP (home, 0)->used) continue;
+
+           offset = AUTO_OFFSET(XEXP (home, 0));
+
+           /* the operand related to the sweep variable */
+           if (AUTO_BASEPTR (XEXP (home, 0)) == virtual_stack_vars_rtx)
+             {
+               if (sweep_offset <= offset
+                   && offset < sweep_offset + sweep_size)
+                 {
+                   offset += sweep_frame_offset - sweep_size - sweep_offset;
+                   XEXP (XEXP (home, 0), 1) = gen_rtx_CONST_INT (VOIDmode,
+                                                                 offset);
+
+                   /* mark */
+                   XEXP (home, 0)->used = 1;
+                 }
+               else if (sweep_offset <= offset
+                        && offset < sweep_frame_offset)
+                 {
+                   /* the rest of variables under sweep_frame_offset,
+                      shift the location */
+                   XEXP (XEXP (home, 0), 1)
+                     = gen_rtx_CONST_INT (VOIDmode, offset - sweep_size);
+
+                   /* mark */
+                   XEXP (home, 0)->used = 1;
+                 }
+             }
+         }
+      }
+}
+
+
+static int has_virtual_reg;
+
+static void
+sweep_string_use_of_insns (insn, sweep_offset, sweep_size)
+     rtx insn;
+     HOST_WIDE_INT sweep_offset, sweep_size;
+{
+  for (; insn; insn = NEXT_INSN (insn))
+    if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
+       || GET_CODE (insn) == CALL_INSN)
+      {
+       has_virtual_reg = FALSE;
+       sweep_string_in_operand (insn, &PATTERN (insn),
+                                sweep_offset, sweep_size);
+       sweep_string_in_operand (insn, &REG_NOTES (insn),
+                                sweep_offset, sweep_size);
+      }
+}
+
+
+static void
+sweep_string_in_operand (insn, loc, sweep_offset, sweep_size)
+     rtx insn, *loc;
+     HOST_WIDE_INT sweep_offset, sweep_size;
+{
+  register rtx x = *loc;
+  register enum rtx_code code;
+  int i, j, k = 0;
+  HOST_WIDE_INT offset;
+  const char *fmt;
+
+  if (x == 0)
+    return;
+
+  code = GET_CODE (x);
+
+  switch (code)
+    {
+    case CONST_INT:
+    case CONST_DOUBLE:
+    case CONST:
+    case SYMBOL_REF:
+    case CODE_LABEL:
+    case PC:
+    case CC0:
+    case ASM_INPUT:
+    case ADDR_VEC:
+    case ADDR_DIFF_VEC:
+    case RETURN:
+    case ADDRESSOF:
+      return;
+           
+    case REG:
+      if (x == virtual_incoming_args_rtx
+         || x == virtual_stack_vars_rtx
+         || x == virtual_stack_dynamic_rtx
+         || x == virtual_outgoing_args_rtx
+         || x == virtual_cfa_rtx)
+       has_virtual_reg = TRUE;
+      return;
+      
+    case SET:
+      /*
+       skip setjmp setup insn and setjmp restore insn
+       Example:
+       (set (MEM (reg:SI xx)) (virtual_stack_vars_rtx)))
+       (set (virtual_stack_vars_rtx) (REG))
+      */
+      if (GET_CODE (XEXP (x, 0)) == MEM
+         && XEXP (x, 1) == virtual_stack_vars_rtx)
+       return;
+      if (XEXP (x, 0) == virtual_stack_vars_rtx
+         && GET_CODE (XEXP (x, 1)) == REG)
+       return;
+      break;
+           
+    case PLUS:
+      /* Handle typical case of frame register plus constant.  */
+      if (XEXP (x, 0) == virtual_stack_vars_rtx
+         && CONSTANT_P (XEXP (x, 1)))
+       {
+         if (x->used) goto single_use_of_virtual_reg;
+         
+         offset = AUTO_OFFSET(x);
+         if (RTX_INTEGRATED_P (x)) k = -1; /* for inline base ptr */
+
+         /* the operand related to the sweep variable */
+         if (sweep_offset <= offset + k
+             && offset + k < sweep_offset + sweep_size)
+           {
+             offset += sweep_frame_offset - sweep_size - sweep_offset;
+
+             XEXP (x, 0) = virtual_stack_vars_rtx;
+             XEXP (x, 1) = gen_rtx_CONST_INT (VOIDmode, offset);
+             x->used = 1;
+           }
+         else if (sweep_offset <= offset + k
+                  && offset + k < sweep_frame_offset)
+           {
+             /* the rest of variables under sweep_frame_offset,
+                shift the location */
+             XEXP (x, 1) = gen_rtx_CONST_INT (VOIDmode, offset - sweep_size);
+             x->used = 1;
+           }
+         
+       single_use_of_virtual_reg:
+         if (has_virtual_reg) {
+           /* excerpt from insn_invalid_p in recog.c */
+           int icode = recog_memoized (insn);
+
+           if (icode < 0 && asm_noperands (PATTERN (insn)) < 0)
+             {
+               rtx temp, seq;
+               
+               start_sequence ();
+               temp = force_operand (x, NULL_RTX);
+               seq = get_insns ();
+               end_sequence ();
+               
+               emit_insn_before (seq, insn);
+               if (! validate_change (insn, loc, temp, 0)
+                   && ! validate_replace_rtx (x, temp, insn))
+                 fatal_insn ("sweep_string_in_operand", insn);
+             }
+         }
+
+         has_virtual_reg = TRUE;
+         return;
+       }
+
+#ifdef FRAME_GROWS_DOWNWARD
+      /*
+       alert the case of frame register plus constant given by reg.
+       */
+      else if (XEXP (x, 0) == virtual_stack_vars_rtx
+              && GET_CODE (XEXP (x, 1)) == REG)
+       fatal_insn ("sweep_string_in_operand: unknown addressing", insn);
+#endif
+
+      /*
+       process further subtree:
+       Example:  (plus:SI (mem/s:SI (plus:SI (reg:SI 17) (const_int 8)))
+       (const_int 5))
+      */
+      break;
+
+    case CALL_PLACEHOLDER:
+      for (i = 0; i < 3; i++)
+       {
+         rtx seq = XEXP (x, i);
+         if (seq)
+           {
+             push_to_sequence (seq);
+             sweep_string_use_of_insns (XEXP (x, i),
+                                        sweep_offset, sweep_size);
+             XEXP (x, i) = get_insns ();
+             end_sequence ();
+           }
+       }
+      break;
+
+    default:
+      break;
+    }
+
+  /* Scan all subexpressions.  */
+  fmt = GET_RTX_FORMAT (code);
+  for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
+    if (*fmt == 'e')
+      {
+       /*
+         virtual_stack_vars_rtx without offset
+         Example:
+           (set (reg:SI xx) (reg:SI 78))
+           (set (reg:SI xx) (MEM (reg:SI 78)))
+       */
+       if (XEXP (x, i) == virtual_stack_vars_rtx)
+         fatal_insn ("sweep_string_in_operand: unknown fp usage", insn);
+       sweep_string_in_operand (insn, &XEXP (x, i), sweep_offset, sweep_size);
+      }
+    else if (*fmt == 'E')
+      for (j = 0; j < XVECLEN (x, i); j++)
+       sweep_string_in_operand (insn, &XVECEXP (x, i, j), sweep_offset, sweep_size);
+}   
+
+
+/*
+  change a argument variable to the local variable addressed
+  by the "new" variable.
+*/
+static void
+change_arg_use_of_insns (insn, orig, new, size)
+     rtx insn, orig, *new;
+     HOST_WIDE_INT size;
+{
+  change_arg_use_of_insns_2 (insn, orig, new, size);
+}
+
+static void
+change_arg_use_of_insns_2 (insn, orig, new, size)
+     rtx insn, orig, *new;
+     HOST_WIDE_INT size;
+{
+  for (; insn; insn = NEXT_INSN (insn))
+    if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
+       || GET_CODE (insn) == CALL_INSN)
+      {
+       rtx seq;
+       
+       start_sequence ();
+       change_arg_use_in_operand (PATTERN (insn), orig, new, size);
+
+       seq = get_insns ();
+       end_sequence ();
+       emit_insn_before (seq, insn);
+      }
+}
+
+
+
+static void
+change_arg_use_in_operand (x, orig, new, size)
+     rtx x, orig, *new;
+     HOST_WIDE_INT size;
+{
+  register enum rtx_code code;
+  int i, j;
+  HOST_WIDE_INT offset;
+  const char *fmt;
+
+  if (x == 0)
+    return;
+
+  code = GET_CODE (x);
+
+  switch (code)
+    {
+    case CONST_INT:
+    case CONST_DOUBLE:
+    case CONST:
+    case SYMBOL_REF:
+    case CODE_LABEL:
+    case PC:
+    case CC0:
+    case ASM_INPUT:
+    case ADDR_VEC:
+    case ADDR_DIFF_VEC:
+    case RETURN:
+    case REG:
+    case ADDRESSOF:
+      return;
+
+    case MEM:
+      /* Handle special case of MEM (incoming_args)  */
+      if (GET_CODE (orig) == MEM
+         && XEXP (x, 0) == virtual_incoming_args_rtx)
+       {
+         offset = 0;
+
+         /* the operand related to the sweep variable */
+         if (AUTO_OFFSET(XEXP (orig, 0)) <= offset &&
+             offset < AUTO_OFFSET(XEXP (orig, 0)) + size) {
+
+           offset = AUTO_OFFSET(XEXP (*new, 0))
+             + (offset - AUTO_OFFSET(XEXP (orig, 0)));
+
+           XEXP (x, 0) = plus_constant (virtual_stack_vars_rtx, offset);
+           XEXP (x, 0)->used = 1;
+
+           return;
+         }
+       }
+      break;
+      
+    case PLUS:
+      /* Handle special case of frame register plus constant.  */
+      if (GET_CODE (orig) == MEM
+         && XEXP (x, 0) == virtual_incoming_args_rtx
+         && CONSTANT_P (XEXP (x, 1))
+         && ! x->used)
+       {
+         offset = AUTO_OFFSET(x);
+
+         /* the operand related to the sweep variable */
+         if (AUTO_OFFSET(XEXP (orig, 0)) <= offset &&
+             offset < AUTO_OFFSET(XEXP (orig, 0)) + size) {
+
+           offset = AUTO_OFFSET(XEXP (*new, 0))
+             + (offset - AUTO_OFFSET(XEXP (orig, 0)));
+
+           XEXP (x, 0) = virtual_stack_vars_rtx;
+           XEXP (x, 1) = gen_rtx_CONST_INT (VOIDmode, offset);
+           x->used = 1;
+
+           return;
+         }
+
+         /*
+           process further subtree:
+           Example:  (plus:SI (mem/s:SI (plus:SI (reg:SI 17) (const_int 8)))
+           (const_int 5))
+         */
+       }
+      break;
+
+    case SET:
+      /* Handle special case of "set (REG or MEM) (incoming_args)".
+        It means that the the address of the 1st argument is stored. */
+      if (GET_CODE (orig) == MEM
+         && XEXP (x, 1) == virtual_incoming_args_rtx)
+       {
+         offset = 0;
+
+         /* the operand related to the sweep variable */
+         if (AUTO_OFFSET(XEXP (orig, 0)) <= offset &&
+             offset < AUTO_OFFSET(XEXP (orig, 0)) + size) {
+
+           offset = AUTO_OFFSET(XEXP (*new, 0))
+             + (offset - AUTO_OFFSET(XEXP (orig, 0)));
+
+           XEXP (x, 1) = force_operand (plus_constant (virtual_stack_vars_rtx,
+                                                       offset), NULL_RTX);
+           XEXP (x, 1)->used = 1;
+
+           return;
+         }
+       }
+      break;
+
+    case CALL_PLACEHOLDER:
+      for (i = 0; i < 3; i++)
+       {
+         rtx seq = XEXP (x, i);
+         if (seq)
+           {
+             push_to_sequence (seq);
+             change_arg_use_of_insns_2 (XEXP (x, i), orig, new, size);
+             XEXP (x, i) = get_insns ();
+             end_sequence ();
+           }
+       }
+      break;
+
+    default:
+      break;
+    }
+
+  /* Scan all subexpressions.  */
+  fmt = GET_RTX_FORMAT (code);
+  for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
+    if (*fmt == 'e')
+      {
+       if (XEXP (x, i) == orig)
+         {
+           if (*new == 0) *new = gen_reg_rtx (GET_MODE (orig));
+           XEXP (x, i) = *new;
+           continue;
+         }
+       change_arg_use_in_operand (XEXP (x, i), orig, new, size);
+      }
+    else if (*fmt == 'E')
+      for (j = 0; j < XVECLEN (x, i); j++)
+       {
+
+         if (XVECEXP (x, i, j) == orig)
+           {
+             if (*new == 0) *new = gen_reg_rtx (GET_MODE (orig));
+             XVECEXP (x, i, j) = *new;
+             continue;
+           }
+         change_arg_use_in_operand (XVECEXP (x, i, j), orig, new, size);
+       }
+}   
+
+
+static void
+validate_insns_of_varrefs (insn)
+     rtx insn;
+{
+  rtx next;
+
+  /* Initialize recognition, indicating that volatile is OK.  */
+  init_recog ();
+
+  for (; insn; insn = next)
+    {
+      next = NEXT_INSN (insn);
+      if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
+         || GET_CODE (insn) == CALL_INSN)
+       {
+         /* excerpt from insn_invalid_p in recog.c */
+         int icode = recog_memoized (insn);
+
+         if (icode < 0 && asm_noperands (PATTERN (insn)) < 0)
+           validate_operand_of_varrefs (insn, &PATTERN (insn));
+       }
+    }
+
+  init_recog_no_volatile ();
+}
+
+
+static void
+validate_operand_of_varrefs (insn, loc)
+     rtx insn, *loc;
+{
+  register enum rtx_code code;
+  rtx x, temp, seq;
+  int i, j;
+  const char *fmt;
+
+  x = *loc;
+  if (x == 0)
+    return;
+
+  code = GET_CODE (x);
+
+  switch (code)
+    {
+    case USE:
+    case CONST_INT:
+    case CONST_DOUBLE:
+    case CONST:
+    case SYMBOL_REF:
+    case CODE_LABEL:
+    case PC:
+    case CC0:
+    case ASM_INPUT:
+    case ADDR_VEC:
+    case ADDR_DIFF_VEC:
+    case RETURN:
+    case REG:
+    case ADDRESSOF:
+      return;
+
+    case PLUS:
+      /* validate insn of frame register plus constant.  */
+      if (GET_CODE (x) == PLUS
+         && XEXP (x, 0) == virtual_stack_vars_rtx
+         && CONSTANT_P (XEXP (x, 1)))
+       {
+         start_sequence ();
+
+         { /* excerpt from expand_binop in optabs.c */
+           optab binoptab = add_optab;
+           enum machine_mode mode = GET_MODE (x);
+           int icode = (int) binoptab->handlers[(int) mode].insn_code;
+           enum machine_mode mode1 = insn_data[icode].operand[2].mode;
+           rtx pat;
+           rtx xop0 = XEXP (x, 0), xop1 = XEXP (x, 1);
+           temp = gen_reg_rtx (mode);
+
+           /* Now, if insn's predicates don't allow offset operands,
+              put them into pseudo regs.  */
+
+           if (! (*insn_data[icode].operand[2].predicate) (xop1, mode1)
+               && mode1 != VOIDmode)
+             xop1 = copy_to_mode_reg (mode1, xop1);
+
+           pat = GEN_FCN (icode) (temp, xop0, xop1);
+           if (pat)
+             emit_insn (pat);
+         }           
+         seq = get_insns ();
+         end_sequence ();
+         
+         emit_insn_before (seq, insn);
+         if (! validate_change (insn, loc, temp, 0))
+           abort ();
+         return;
+       }
+       break;
+      
+
+    case CALL_PLACEHOLDER:
+      for (i = 0; i < 3; i++)
+       {
+         rtx seq = XEXP (x, i);
+         if (seq)
+           {
+             push_to_sequence (seq);
+             validate_insns_of_varrefs (XEXP (x, i));
+             XEXP (x, i) = get_insns ();
+             end_sequence ();
+           }
+       }
+      break;
+
+    default:
+      break;
+    }
+
+  /* Scan all subexpressions.  */
+  fmt = GET_RTX_FORMAT (code);
+  for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
+    if (*fmt == 'e')
+      validate_operand_of_varrefs (insn, &XEXP (x, i));
+    else if (*fmt == 'E')
+      for (j = 0; j < XVECLEN (x, i); j++)
+       validate_operand_of_varrefs (insn, &XVECEXP (x, i, j));
+}
+
+
+
+
+/*
+  The following codes are invoked after the instantiation of pseuso registers.
+
+  Reorder local variables to place a peudo register after buffers to avoid
+  the corruption of local variables that could be used to further corrupt
+  arbitrary memory locations.
+*/
+#if !defined(FRAME_GROWS_DOWNWARD) && defined(STACK_GROWS_DOWNWARD)
+static void push_frame
+       PARAMS ((HOST_WIDE_INT var_size, HOST_WIDE_INT boundary));
+static void push_frame_in_decls
+       PARAMS ((tree block, HOST_WIDE_INT push_size, HOST_WIDE_INT boundary));
+static void push_frame_in_args
+       PARAMS ((tree parms, HOST_WIDE_INT push_size, HOST_WIDE_INT boundary));
+static void push_frame_of_insns
+       PARAMS ((rtx insn, HOST_WIDE_INT push_size, HOST_WIDE_INT boundary));
+static void push_frame_in_operand
+       PARAMS ((rtx insn, rtx orig,
+                HOST_WIDE_INT push_size, HOST_WIDE_INT boundary));
+static void push_frame_of_reg_equiv_memory_loc
+       PARAMS ((HOST_WIDE_INT push_size, HOST_WIDE_INT boundary));
+static void push_frame_of_reg_equiv_constant
+       PARAMS ((HOST_WIDE_INT push_size, HOST_WIDE_INT boundary));
+static void reset_used_flags_for_push_frame PARAMS ((void));
+static int check_out_of_frame_access
+       PARAMS ((rtx insn, HOST_WIDE_INT boundary));
+static int check_out_of_frame_access_in_operand
+       PARAMS ((rtx, HOST_WIDE_INT boundary));
+#endif
+
+rtx
+assign_stack_local_for_pseudo_reg (mode, size, align)
+     enum machine_mode mode;
+     HOST_WIDE_INT size;
+     int align;
+{
+#if defined(FRAME_GROWS_DOWNWARD) || !defined(STACK_GROWS_DOWNWARD)
+  return assign_stack_local (mode, size, align);
+#else
+  tree blocks = DECL_INITIAL (current_function_decl);
+  rtx new;
+  HOST_WIDE_INT saved_frame_offset, units_per_push, starting_frame;
+  int first_call_from_purge_addressof, first_call_from_global_alloc;
+
+  if (! flag_propolice_protection
+      || size == 0
+      || ! blocks
+      || current_function_is_inlinable
+      || ! search_string_from_argsandvars (1)
+      || current_function_contains_functions)
+    return assign_stack_local (mode, size, align);
+
+  first_call_from_purge_addressof = !push_frame_offset && !cse_not_expected;
+  first_call_from_global_alloc = !saved_cse_not_expected && cse_not_expected;
+  saved_cse_not_expected = cse_not_expected;
+
+  starting_frame = (STARTING_FRAME_OFFSET)?
+    STARTING_FRAME_OFFSET:BIGGEST_ALIGNMENT / BITS_PER_UNIT;
+  units_per_push = MAX(BIGGEST_ALIGNMENT / BITS_PER_UNIT,
+                      GET_MODE_SIZE (mode));
+    
+  if (first_call_from_purge_addressof)
+    {
+      push_frame_offset = push_allocated_offset;
+      if (check_out_of_frame_access (get_insns (), starting_frame))
+       {
+         /* if there is an access beyond frame, push dummy region to seperate
+            the address of instantiated variables */
+         push_frame (GET_MODE_SIZE (DImode), 0);
+         assign_stack_local (BLKmode, GET_MODE_SIZE (DImode), -1);
+       }
+    }
+
+  if (first_call_from_global_alloc)
+    {
+      push_frame_offset = push_allocated_offset = 0;
+      if (check_out_of_frame_access (get_insns (), starting_frame))
+       {
+         if (STARTING_FRAME_OFFSET)
+           {
+             /* if there is an access beyond frame, push dummy region 
+                to seperate the address of instantiated variables */
+             push_frame (GET_MODE_SIZE (DImode), 0);
+             assign_stack_local (BLKmode, GET_MODE_SIZE (DImode), -1);
+           }
+         else
+           push_allocated_offset = starting_frame;
+       }
+    }
+
+  saved_frame_offset = frame_offset;
+  frame_offset = push_frame_offset;
+
+  new = assign_stack_local (mode, size, align);
+
+  push_frame_offset = frame_offset;
+  frame_offset = saved_frame_offset;
+  
+  if (push_frame_offset > push_allocated_offset)
+    {
+      push_frame (units_per_push,
+                 push_allocated_offset + STARTING_FRAME_OFFSET);
+
+      assign_stack_local (BLKmode, units_per_push, -1);
+      push_allocated_offset += units_per_push;
+    }
+
+  /* At the second call from global alloc, alpha push frame and assign
+     a local variable to the top of the stack */
+  if (first_call_from_global_alloc && STARTING_FRAME_OFFSET == 0)
+    push_frame_offset = push_allocated_offset = 0;
+
+  return new;
+#endif
+}
+
+
+#if !defined(FRAME_GROWS_DOWNWARD) && defined(STACK_GROWS_DOWNWARD)
+/*
+  push frame infomation for instantiating pseudo register at the top of stack.
+  This is only for the "frame grows upward", it means FRAME_GROWS_DOWNWARD is 
+  not defined.
+
+  It is called by purge_addressof function and global_alloc (or reload)
+  function.
+*/
+static void
+push_frame (var_size, boundary)
+     HOST_WIDE_INT var_size, boundary;
+{
+  reset_used_flags_for_push_frame();
+
+  /* scan all declarations of variables and fix the offset address of
+     the variable based on the frame pointer */
+  push_frame_in_decls (DECL_INITIAL (current_function_decl),
+                      var_size, boundary);
+
+  /* scan all argument variable and fix the offset address based on
+     the frame pointer */
+  push_frame_in_args (DECL_ARGUMENTS (current_function_decl),
+                     var_size, boundary);
+
+  /* scan all operands of all insns and fix the offset address
+     based on the frame pointer */
+  push_frame_of_insns (get_insns (), var_size, boundary);
+
+  /* scan all reg_equiv_memory_loc and reg_equiv_constant*/
+  push_frame_of_reg_equiv_memory_loc (var_size, boundary);
+  push_frame_of_reg_equiv_constant (var_size, boundary);
+
+  reset_used_flags_for_push_frame();
+}
+
+static void
+reset_used_flags_for_push_frame()
+{
+  int i;
+  extern rtx *reg_equiv_memory_loc;
+  extern rtx *reg_equiv_constant;
+
+  /* Clear all the USED bits in operands of all insns and declarations of
+     local vars */
+  reset_used_flags_for_decls (DECL_INITIAL (current_function_decl));
+  reset_used_flags_for_insns (get_insns ());
+
+
+  /* The following codes are processed if the push_frame is called from 
+     global_alloc (or reload) function */
+  if (reg_equiv_memory_loc == 0) return;
+
+  for (i=LAST_VIRTUAL_REGISTER+1; i < max_regno; i++)
+    if (reg_equiv_memory_loc[i])
+      {
+       rtx x = reg_equiv_memory_loc[i];
+
+       if (GET_CODE (x) == MEM
+           && GET_CODE (XEXP (x, 0)) == PLUS
+           && AUTO_BASEPTR (XEXP (x, 0)) == frame_pointer_rtx)
+         {
+           /* reset */
+           XEXP (x, 0)->used = 0;
+         }
+      }
+
+  
+  if (reg_equiv_constant == 0) return;
+
+  for (i=LAST_VIRTUAL_REGISTER+1; i < max_regno; i++)
+    if (reg_equiv_constant[i])
+      {
+       rtx x = reg_equiv_constant[i];
+
+       if (GET_CODE (x) == PLUS
+           && AUTO_BASEPTR (x) == frame_pointer_rtx)
+         {
+           /* reset */
+           x->used = 0;
+         }
+      }
+}
+
+static void
+push_frame_in_decls (block, push_size, boundary)
+     tree block;
+     HOST_WIDE_INT push_size, boundary;
+{
+  tree types;
+  HOST_WIDE_INT offset;
+  rtx home;
+
+  while (block && TREE_CODE(block)==BLOCK)
+    {
+      types = BLOCK_VARS(block);
+       
+      while (types)
+       {
+         /* skip the declaration that refers an external variable and
+            also skip an global variable */
+         if (! DECL_EXTERNAL (types) && ! TREE_STATIC (types))
+           {
+           
+             if (!DECL_RTL_SET_P (types)) goto next;
+             home = DECL_RTL (types);
+
+             /* process for static local variable */
+             if (GET_CODE (home) == MEM
+                 && GET_CODE (XEXP (home, 0)) == SYMBOL_REF)
+               goto next;
+
+             if (GET_CODE (home) == MEM
+                 && GET_CODE (XEXP (home, 0)) == REG)
+               {
+                 if (XEXP (home, 0) != frame_pointer_rtx
+                     || boundary != 0)
+                   goto next;
+
+                 XEXP (home, 0) = plus_constant (frame_pointer_rtx,
+                                                 push_size);
+
+                 /* mark */
+                 XEXP (home, 0)->used = 1;
+               }
+               
+             if (GET_CODE (home) == MEM
+                 && GET_CODE (XEXP (home, 0)) == MEM)
+               {
+
+                 /* process for dynamically allocated aray */
+                 home = XEXP (home, 0);
+               }
+               
+             if (GET_CODE (home) == MEM
+                 && GET_CODE (XEXP (home, 0)) == PLUS
+                 && GET_CODE (XEXP (XEXP (home, 0), 1)) == CONST_INT)
+               {
+                 offset = AUTO_OFFSET(XEXP (home, 0));
+
+                 if (! XEXP (home, 0)->used
+                     && offset >= boundary)
+                   {
+                     offset += push_size;
+                     XEXP (XEXP (home, 0), 1)
+                       = gen_rtx_CONST_INT (VOIDmode, offset);
+                     
+                     /* mark */
+                     XEXP (home, 0)->used = 1;
+                   }
+               }
+
+           }
+       next:
+         types = TREE_CHAIN(types);
+       }
+
+      push_frame_in_decls (BLOCK_SUBBLOCKS (block), push_size, boundary);
+      block = BLOCK_CHAIN (block);
+    }
+}
+
+
+static void
+push_frame_in_args (parms, push_size, boundary)
+     tree parms;
+     HOST_WIDE_INT push_size, boundary;
+{
+  rtx home;
+  HOST_WIDE_INT offset;
+    
+  for (; parms; parms = TREE_CHAIN (parms))
+    if (DECL_NAME (parms) && TREE_TYPE (parms) != error_mark_node)
+      {
+       if (PARM_PASSED_IN_MEMORY (parms) && DECL_NAME (parms))
+         {
+           home = DECL_INCOMING_RTL (parms);
+           offset = AUTO_OFFSET(XEXP (home, 0));
+
+           if (XEXP (home, 0)->used || offset < boundary) continue;
+
+           /* the operand related to the sweep variable */
+           if (AUTO_BASEPTR (XEXP (home, 0)) == frame_pointer_rtx)
+             {
+               if (XEXP (home, 0) == frame_pointer_rtx)
+                 XEXP (home, 0) = plus_constant (frame_pointer_rtx,
+                                                 push_size);
+               else {
+                 offset += push_size;
+                 XEXP (XEXP (home, 0), 1) = gen_rtx_CONST_INT (VOIDmode,
+                                                               offset);
+               }
+
+               /* mark */
+               XEXP (home, 0)->used = 1;
+             }
+         }
+      }
+}
+
+
+static int insn_pushed;
+static int *fp_equiv = 0;
+
+static void
+push_frame_of_insns (insn, push_size, boundary)
+     rtx insn;
+     HOST_WIDE_INT push_size, boundary;
+{
+  /* init fp_equiv */
+  fp_equiv = (int *) xcalloc (max_reg_num (), sizeof (int));
+               
+  for (; insn; insn = NEXT_INSN (insn))
+    if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
+       || GET_CODE (insn) == CALL_INSN)
+      {
+       rtx last;
+       
+       insn_pushed = FALSE;
+
+       /* push frame in INSN operation */
+       push_frame_in_operand (insn, PATTERN (insn), push_size, boundary);
+
+       /* push frame in NOTE */
+       push_frame_in_operand (insn, REG_NOTES (insn), push_size, boundary);
+
+       /* push frame in CALL EXPR_LIST */
+       if (GET_CODE (insn) == CALL_INSN)
+         push_frame_in_operand (insn, CALL_INSN_FUNCTION_USAGE (insn),
+                                push_size, boundary);
+
+       if (insn_pushed
+           && (last = try_split (PATTERN (insn), insn, 1)) != insn)
+         {
+           rtx first = NEXT_INSN (insn);
+           rtx trial = NEXT_INSN (first);
+           rtx pattern = PATTERN (trial);
+           rtx set;
+
+           /* update insn_chain with splitted insns
+              when it is called from global_alloc. */
+           if (cse_not_expected)
+             {
+               struct insn_chain *chain = reload_insn_chain;
+               for (; chain; chain = chain->next)
+                 if (chain->insn == insn)
+                   {
+                     chain->insn = first;
+                     break;
+                   }
+             }
+
+           /* update REG_EQUIV info to the first splitted insn */
+           if ((set = single_set (insn))
+               && find_reg_note (insn, REG_EQUIV, SET_SRC (set))
+               && GET_CODE (PATTERN (first)) == SET)
+             {
+               REG_NOTES (first)
+                 = gen_rtx_EXPR_LIST (REG_EQUIV,
+                                      SET_SRC (PATTERN (first)),
+                                      REG_NOTES (first));
+             }
+
+           if (GET_CODE (pattern) == SET
+               && GET_CODE (XEXP (pattern, 0)) == REG
+               && GET_CODE (XEXP (pattern, 1)) == PLUS
+               && XEXP (pattern, 0) == XEXP (XEXP (pattern, 1), 0)
+               && CONSTANT_P (XEXP (XEXP (pattern, 1), 1)))
+             {
+               rtx offset = XEXP (XEXP (pattern, 1), 1);
+               fp_equiv[REGNO (XEXP (pattern, 0))] = INTVAL (offset);
+
+               delete_insn (trial);
+             }
+
+           insn = last;
+         }
+      }
+
+  /* Clean up.  */
+  free (fp_equiv);
+}
+
+
+static void
+push_frame_in_operand (insn, orig, push_size, boundary)
+     rtx insn, orig;
+     HOST_WIDE_INT push_size, boundary;
+{
+  register rtx x = orig;
+  register enum rtx_code code;
+  int i, j;
+  HOST_WIDE_INT offset;
+  const char *fmt;
+
+  if (x == 0)
+    return;
+
+  code = GET_CODE (x);
+
+  switch (code)
+    {
+    case CONST_INT:
+    case CONST_DOUBLE:
+    case CONST:
+    case SYMBOL_REF:
+    case CODE_LABEL:
+    case PC:
+    case CC0:
+    case ASM_INPUT:
+    case ADDR_VEC:
+    case ADDR_DIFF_VEC:
+    case RETURN:
+    case REG:
+    case ADDRESSOF:
+    case USE:
+      return;
+           
+    case SET:
+      /*
+       skip setjmp setup insn and setjmp restore insn
+       alpha case:
+       (set (MEM (reg:SI xx)) (frame_pointer_rtx)))
+       (set (frame_pointer_rtx) (REG))
+      */
+      if (GET_CODE (XEXP (x, 0)) == MEM
+         && XEXP (x, 1) == frame_pointer_rtx)
+       return;
+      if (XEXP (x, 0) == frame_pointer_rtx
+         && GET_CODE (XEXP (x, 1)) == REG)
+       return;
+
+      /*
+       powerpc case: restores setjmp address
+       (set (frame_pointer_rtx) (plus frame_pointer_rtx const_int -n))
+       or
+       (set (reg) (plus frame_pointer_rtx const_int -n))
+       (set (frame_pointer_rtx) (reg))
+      */
+      if (GET_CODE (XEXP (x, 0)) == REG
+         && GET_CODE (XEXP (x, 1)) == PLUS
+         && XEXP (XEXP (x, 1), 0) == frame_pointer_rtx
+         && CONSTANT_P (XEXP (XEXP (x, 1), 1))
+         && INTVAL (XEXP (XEXP (x, 1), 1)) < 0)
+       {
+         x = XEXP (x, 1);
+         offset = AUTO_OFFSET(x);
+         if (x->used || abs (offset) < boundary)
+           return;
+
+         XEXP (x, 1) = gen_rtx_CONST_INT (VOIDmode, offset - push_size);
+         x->used = 1; insn_pushed = TRUE;
+         return;
+       }
+
+      /* reset fp_equiv register */
+      else if (GET_CODE (XEXP (x, 0)) == REG
+         && fp_equiv[REGNO (XEXP (x, 0))])
+       fp_equiv[REGNO (XEXP (x, 0))] = 0;
+
+      /* propagete fp_equiv register */
+      else if (GET_CODE (XEXP (x, 0)) == REG
+              && GET_CODE (XEXP (x, 1)) == REG
+              && fp_equiv[REGNO (XEXP (x, 1))])
+       if (REGNO (XEXP (x, 0)) <= LAST_VIRTUAL_REGISTER
+           || reg_renumber[REGNO (XEXP (x, 0))] > 0)
+         fp_equiv[REGNO (XEXP (x, 0))] = fp_equiv[REGNO (XEXP (x, 1))];
+      break;
+
+    case MEM:
+      if (XEXP (x, 0) == frame_pointer_rtx
+         && boundary == 0)
+       {
+         XEXP (x, 0) = plus_constant (frame_pointer_rtx, push_size);
+         XEXP (x, 0)->used = 1; insn_pushed = TRUE;
+         return;
+       }
+      break;
+      
+    case PLUS:
+      offset = AUTO_OFFSET(x);
+
+      /* Handle special case of frame register plus constant.  */
+      if (CONSTANT_P (XEXP (x, 1))
+         && XEXP (x, 0) == frame_pointer_rtx)
+       {
+         if (x->used || offset < boundary)
+           return;
+
+         XEXP (x, 1) = gen_rtx_CONST_INT (VOIDmode, offset + push_size);
+         x->used = 1; insn_pushed = TRUE;
+
+         return;
+       }
+      /*
+       Handle alpha case:
+        (plus:SI (subreg:SI (reg:DI 63 FP) 0) (const_int 64 [0x40]))
+      */
+      if (CONSTANT_P (XEXP (x, 1))
+         && GET_CODE (XEXP (x, 0)) == SUBREG
+         && SUBREG_REG (XEXP (x, 0)) == frame_pointer_rtx)
+       {
+         if (x->used || offset < boundary)
+           return;
+
+         XEXP (x, 1) = gen_rtx_CONST_INT (VOIDmode, offset + push_size);
+         x->used = 1; insn_pushed = TRUE;
+
+         return;
+       }
+      /*
+       Handle powerpc case:
+        (set (reg x) (plus fp const))
+        (set (.....) (... (plus (reg x) (const B))))
+      */
+      else if (CONSTANT_P (XEXP (x, 1))
+              && GET_CODE (XEXP (x, 0)) == REG
+              && fp_equiv[REGNO (XEXP (x, 0))])
+       {
+         if (x->used) return;
+
+         offset += fp_equiv[REGNO (XEXP (x, 0))];
+
+         XEXP (x, 1) = gen_rtx_CONST_INT (VOIDmode, offset);
+         x->used = 1; insn_pushed = TRUE;
+
+         return;
+       }
+      /*
+       Handle special case of frame register plus reg (constant).
+        (set (reg x) (const B))
+        (set (....) (...(plus fp (reg x))))
+      */
+      else if (XEXP (x, 0) == frame_pointer_rtx
+              && GET_CODE (XEXP (x, 1)) == REG
+              && PREV_INSN (insn)
+              && PATTERN (PREV_INSN (insn))
+              && SET_DEST (PATTERN (PREV_INSN (insn))) == XEXP (x, 1)
+              && CONSTANT_P (SET_SRC (PATTERN (PREV_INSN (insn)))))
+       {
+         HOST_WIDE_INT offset = INTVAL (SET_SRC (PATTERN (PREV_INSN (insn))));
+
+         if (x->used || offset < boundary)
+           return;
+         
+         SET_SRC (PATTERN (PREV_INSN (insn)))
+           = gen_rtx_CONST_INT (VOIDmode, offset + push_size);
+         x->used = 1;
+         XEXP (x, 1)->used = 1;
+
+         return;
+       }
+      /* Handle special case of frame register plus reg (used).  */
+      else if (XEXP (x, 0) == frame_pointer_rtx
+              && XEXP (x, 1)->used)
+       {
+         x->used = 1;
+         return;
+       }
+      /*
+       process further subtree:
+       Example:  (plus:SI (mem/s:SI (plus:SI (reg:SI 17) (const_int 8)))
+       (const_int 5))
+      */
+      break;
+
+    case CALL_PLACEHOLDER:
+      push_frame_of_insns (XEXP (x, 0), push_size, boundary);
+      push_frame_of_insns (XEXP (x, 1), push_size, boundary);
+      push_frame_of_insns (XEXP (x, 2), push_size, boundary);
+      break;
+
+    default:
+      break;
+    }
+
+  /* Scan all subexpressions.  */
+  fmt = GET_RTX_FORMAT (code);
+  for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
+    if (*fmt == 'e')
+      {
+       if (XEXP (x, i) == frame_pointer_rtx && boundary == 0)
+         fatal_insn ("push_frame_in_operand", insn);
+       push_frame_in_operand (insn, XEXP (x, i), push_size, boundary);
+      }
+    else if (*fmt == 'E')
+      for (j = 0; j < XVECLEN (x, i); j++)
+       push_frame_in_operand (insn, XVECEXP (x, i, j), push_size, boundary);
+}   
+
+static void
+push_frame_of_reg_equiv_memory_loc (push_size, boundary)
+     HOST_WIDE_INT push_size, boundary;
+{
+  int i;
+  extern rtx *reg_equiv_memory_loc;
+
+  /* This function is processed if the push_frame is called from 
+     global_alloc (or reload) function */
+  if (reg_equiv_memory_loc == 0) return;
+
+  for (i=LAST_VIRTUAL_REGISTER+1; i < max_regno; i++)
+    if (reg_equiv_memory_loc[i])
+      {
+       rtx x = reg_equiv_memory_loc[i];
+       int offset;
+
+       if (GET_CODE (x) == MEM
+           && GET_CODE (XEXP (x, 0)) == PLUS
+           && XEXP (XEXP (x, 0), 0) == frame_pointer_rtx)
+         {
+           offset = AUTO_OFFSET(XEXP (x, 0));
+           
+           if (! XEXP (x, 0)->used
+               && offset >= boundary)
+             {
+               offset += push_size;
+               XEXP (XEXP (x, 0), 1) = gen_rtx_CONST_INT (VOIDmode, offset);
+
+               /* mark */
+               XEXP (x, 0)->used = 1;
+             }
+         }
+       else if (GET_CODE (x) == MEM
+                && XEXP (x, 0) == frame_pointer_rtx
+                && boundary == 0)
+         {
+           XEXP (x, 0) = plus_constant (frame_pointer_rtx, push_size);
+           XEXP (x, 0)->used = 1; insn_pushed = TRUE;
+         }
+      }
+}
+
+static void
+push_frame_of_reg_equiv_constant (push_size, boundary)
+     HOST_WIDE_INT push_size, boundary;
+{
+  int i;
+  extern rtx *reg_equiv_constant;
+
+  /* This function is processed if the push_frame is called from 
+     global_alloc (or reload) function */
+  if (reg_equiv_constant == 0) return;
+
+  for (i=LAST_VIRTUAL_REGISTER+1; i < max_regno; i++)
+    if (reg_equiv_constant[i])
+      {
+       rtx x = reg_equiv_constant[i];
+       int offset;
+
+       if (GET_CODE (x) == PLUS
+           && XEXP (x, 0) == frame_pointer_rtx)
+         {
+           offset = AUTO_OFFSET(x);
+           
+           if (! x->used
+               && offset >= boundary)
+             {
+               offset += push_size;
+               XEXP (x, 1) = gen_rtx_CONST_INT (VOIDmode, offset);
+
+               /* mark */
+               x->used = 1;
+             }
+         }
+       else if (x == frame_pointer_rtx
+                && boundary == 0)
+         {
+           reg_equiv_constant[i]
+             = plus_constant (frame_pointer_rtx, push_size);
+           reg_equiv_constant[i]->used = 1; insn_pushed = TRUE;
+         }
+      }
+}
+
+static int
+check_out_of_frame_access (insn, boundary)
+     rtx insn;
+     HOST_WIDE_INT boundary;
+{
+  for (; insn; insn = NEXT_INSN (insn))
+    if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
+       || GET_CODE (insn) == CALL_INSN)
+      {
+       if (check_out_of_frame_access_in_operand (PATTERN (insn), boundary))
+         return TRUE;
+      }
+  return FALSE;
+}
+
+
+static int
+check_out_of_frame_access_in_operand (orig, boundary)
+     rtx orig;
+     HOST_WIDE_INT boundary;
+{
+  register rtx x = orig;
+  register enum rtx_code code;
+  int i, j;
+  const char *fmt;
+
+  if (x == 0)
+    return FALSE;
+
+  code = GET_CODE (x);
+
+  switch (code)
+    {
+    case CONST_INT:
+    case CONST_DOUBLE:
+    case CONST:
+    case SYMBOL_REF:
+    case CODE_LABEL:
+    case PC:
+    case CC0:
+    case ASM_INPUT:
+    case ADDR_VEC:
+    case ADDR_DIFF_VEC:
+    case RETURN:
+    case REG:
+    case ADDRESSOF:
+      return FALSE;
+           
+    case MEM:
+      if (XEXP (x, 0) == frame_pointer_rtx)
+       if (0 < boundary) return TRUE;
+      break;
+      
+    case PLUS:
+      /* Handle special case of frame register plus constant.  */
+      if (CONSTANT_P (XEXP (x, 1))
+         && XEXP (x, 0) == frame_pointer_rtx)
+       {
+         if (0 <= AUTO_OFFSET(x)
+             && AUTO_OFFSET(x) < boundary) return TRUE;
+         return FALSE;
+       }
+      /*
+       process further subtree:
+       Example:  (plus:SI (mem/s:SI (plus:SI (reg:SI 17) (const_int 8)))
+       (const_int 5))
+      */
+      break;
+
+    case CALL_PLACEHOLDER:
+      if (check_out_of_frame_access (XEXP (x, 0), boundary)) return TRUE;
+      if (check_out_of_frame_access (XEXP (x, 1), boundary)) return TRUE;
+      if (check_out_of_frame_access (XEXP (x, 2), boundary)) return TRUE;
+      break;
+
+    default:
+      break;
+    }
+
+  /* Scan all subexpressions.  */
+  fmt = GET_RTX_FORMAT (code);
+  for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
+    if (*fmt == 'e')
+      {
+       if (check_out_of_frame_access_in_operand (XEXP (x, i), boundary))
+         return TRUE;
+      }
+    else if (*fmt == 'E')
+      for (j = 0; j < XVECLEN (x, i); j++)
+       if (check_out_of_frame_access_in_operand (XVECEXP (x, i, j), boundary))
+         return TRUE;
+
+  return FALSE;
+}
+#endif
diff --git a/gnu/usr.bin/cc3/cc_int/protector.h b/gnu/usr.bin/cc3/cc_int/protector.h
new file mode 100644 (file)
index 0000000..6e9a91a
--- /dev/null
@@ -0,0 +1,50 @@
+/* $DragonFly: src/gnu/usr.bin/cc3/cc_int/Attic/protector.h,v 1.1 2004/03/05 21:38:44 joerg Exp $ */
+
+/* RTL buffer overflow protection function for GNU C compiler
+   Copyright (C) 1987, 88, 89, 92-7, 1998 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+
+/* declaration of GUARD variable */
+#define GUARD_m                Pmode
+#define UNITS_PER_GUARD MAX(BIGGEST_ALIGNMENT / BITS_PER_UNIT, GET_MODE_SIZE (GUARD_m))
+
+#ifndef L_stack_smash_handler
+
+/* insert a guard variable before a character buffer and change the order
+ of pointer variables, character buffers and pointer arguments */
+
+extern void prepare_stack_protection  PARAMS ((int inlinable));
+
+#ifdef TREE_CODE
+/* search a character array from the specified type tree */
+
+extern int search_string_def PARAMS ((tree names));
+#endif
+
+/* examine whether the input contains frame pointer addressing */
+
+extern int contains_fp PARAMS ((rtx op));
+
+/* allocate a local variable in the stack area before character buffers
+   to avoid the corruption of it */
+
+extern rtx assign_stack_local_for_pseudo_reg PARAMS ((enum machine_mode, HOST_WIDE_INT, int));
+
+#endif
index ee24595..c3013a3 100644 (file)
@@ -1,5 +1,5 @@
 # $FreeBSD: src/sys/boot/ficl/Makefile,v 1.35 2003/06/30 19:08:49 ru Exp $
-# $DragonFly: src/sys/boot/ficl/Makefile,v 1.3 2003/11/10 06:08:33 dillon Exp $
+# $DragonFly: src/sys/boot/ficl/Makefile,v 1.4 2004/03/05 21:38:44 joerg Exp $
 #
 .if ${MACHINE_ARCH} == "amd64"
 .MAKEFLAGS:  MACHINE_ARCH=i386 MACHINE=i386 REALLY_AMD64=true
@@ -10,6 +10,10 @@ BASE_SRCS=   dict.c ficl.c fileaccess.c float.c loader.c math64.c \
                prefix.c search.c stack.c tools.c vm.c words.c
 
 SRCS=          ${BASE_SRCS} sysdep.c softcore.c
+OBJS+=         stack_protector.o
+
+stack_protector.o: ../../libkern/stack_protector.c
+
 CLEANFILES=    softcore.c testmain testmain.o
 CFLAGS+=       -ffreestanding
 .if ${MACHINE_ARCH} == "alpha"