Skip site navigation (1)Skip section navigation (2)
Date:      14 Nov 2001 21:28:37 +0500
From:      Kerberus <kerberus@microbsd.net>
To:        Kris Kennaway <kris@obsecurity.org>
Cc:        Andrew Johns <johnsa@kpi.com.au>, freebsd-questions@FreeBSD.ORG
Subject:   Re: GCC stack smashing protection for 4.4-STABLE?
Message-ID:  <1005755318.13317.2.camel@devel.netwolves.com>
In-Reply-To: <20011113213920.A46774@xor.obsecurity.org>
References:  <3BF1EE29.49275AED@kpi.com.au>  <20011113213920.A46774@xor.obsecurity.org>

next in thread | previous in thread | raw e-mail | index | archive | help

--=-u0LHuhZj3rcXxj9M/geN
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

try this it worked for me, just patch from /usr/src and follow the
directions

On Wed, 2001-11-14 at 00:39, Kris Kennaway wrote:


--=-u0LHuhZj3rcXxj9M/geN
Content-Disposition: attachment; filename=gcc-propolice.patch
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=ISO-8859-1

Index: contrib/gcc/Makefile.in
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /mnt/ncvs/src/contrib/gcc/Makefile.in,v
retrieving revision 1.4
diff -u -r1.4 Makefile.in
--- contrib/gcc/Makefile.in	1999/10/16 08:21:54	1.4
+++ contrib/gcc/Makefile.in	2000/11/17 22:06:11
@@ -684,7 +684,7 @@
  insn-peep.o reorg.o $(SCHED_PREFIX)sched.o final.o recog.o reg-stack.o \
  insn-opinit.o insn-recog.o insn-extract.o insn-output.o insn-emit.o lcm.o=
 \
  profile.o insn-attrtab.o $(out_object_file) getpwd.o $(EXTRA_OBJS) conver=
t.o \
- mbchar.o dyn-string.o splay-tree.o graph.o sbitmap.o resource.o hash.o
+ mbchar.o dyn-string.o splay-tree.o graph.o sbitmap.o resource.o hash.o pr=
otector.o
=20
 # GEN files are listed separately, so they can be built before doing paral=
lel
 #  makes for cc1 or cc1plus.  Otherwise sequent parallel make attempts to =
load
@@ -735,7 +735,7 @@
     _fixtfdi _fixunstfdi _floatditf \
     __gcc_bcmp _varargs __dummy _eprintf \
     _bb _shtab _clear_cache _trampoline __main _exit \
-    _ctors _pure
+    _ctors _pure _stack_smash_handler
=20
 LIB2FUNCS_EH =3D _eh
=20
Index: contrib/gcc/choose-temp.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /mnt/ncvs/src/contrib/gcc/choose-temp.c,v
retrieving revision 1.3
diff -u -r1.3 choose-temp.c
--- contrib/gcc/choose-temp.c	1999/11/04 10:23:25	1.3
+++ contrib/gcc/choose-temp.c	2000/11/03 19:17:33
@@ -73,7 +73,7 @@
=20
 /* Name of temporary file.
    mktemp requires 6 trailing X's.  */
-#define TEMP_FILE "ccXXXXXX"
+#define TEMP_FILE "ccXXXXXXXXXX"
=20
 /* Subroutine of choose_temp_base.
    If BASE is non-NULL, return it.
Index: contrib/gcc/cse.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /mnt/ncvs/src/contrib/gcc/cse.c,v
retrieving revision 1.1.1.6
diff -u -r1.1.1.6 cse.c
--- contrib/gcc/cse.c	2000/01/22 02:59:02	1.1.1.6
+++ contrib/gcc/cse.c	2000/11/17 22:06:11
@@ -6482,6 +6482,10 @@
       if (SET_DEST (x) =3D=3D pc_rtx
 	  && GET_CODE (SET_SRC (x)) =3D=3D LABEL_REF)
 	;
+      else if (x->volatil) {
+	make_new_qty (REGNO (SET_DEST (x)));
+	qty_mode[REG_QTY (REGNO (SET_DEST (x)))] =3D GET_MODE (SET_DEST (x));
+      }
=20
       /* Don't count call-insns, (set (reg 0) (call ...)), as a set.
 	 The hard function value register is used only once, to copy to
Index: contrib/gcc/dbxout.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /mnt/ncvs/src/contrib/gcc/dbxout.c,v
retrieving revision 1.4
diff -u -r1.4 dbxout.c
--- contrib/gcc/dbxout.c	1999/10/26 08:47:58	1.4
+++ contrib/gcc/dbxout.c	2000/11/17 22:05:36
@@ -2253,6 +2253,9 @@
   for (; parms; parms =3D TREE_CHAIN (parms))
     if (DECL_NAME (parms) && TREE_TYPE (parms) !=3D error_mark_node)
       {
+	/* change the debug info of escaped argument for stack protection */
+	update_debuginfo_using_escaped_arg_list (parms);
+
 	dbxout_prepare_symbol (parms);
=20
 	/* Perform any necessary register eliminations on the parameter's rtl,
Index: contrib/gcc/expr.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /mnt/ncvs/src/contrib/gcc/expr.c,v
retrieving revision 1.1.1.4
diff -u -r1.1.1.4 expr.c
--- contrib/gcc/expr.c	1999/10/16 06:04:52	1.1.1.4
+++ contrib/gcc/expr.c	2000/11/17 22:05:36
@@ -40,6 +40,7 @@
 #include "typeclass.h"
 #include "defaults.h"
 #include "toplev.h"
+#include "protector.h"
=20
 #define CEIL(x,y) (((x) + (y) - 1) / (y))
=20
@@ -6240,7 +6241,7 @@
 	    && modifier !=3D EXPAND_MEMORY_USE_WO)
  	  return GEN_INT (TREE_STRING_POINTER (string)[i]);
=20
-	op0 =3D expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM);
+	op0 =3D expand_expr (exp1, NULL_RTX, VOIDmode, ro_modifier);
 	op0 =3D memory_address (mode, op0);
=20
 	if (current_function_check_memory_usage && !AGGREGATE_TYPE_P (TREE_TYPE (=
exp)))
@@ -8681,7 +8682,7 @@
   mem =3D gen_rtx_MEM (BLKmode,
 		     memory_address (BLKmode,
 				     expand_expr (exp, NULL_RTX,
-						  ptr_mode, EXPAND_SUM)));
+						  ptr_mode, flag_propolice_protection?EXPAND_NORMAL:EXPAND_SUM)));
=20
   RTX_UNCHANGING_P (mem) =3D TREE_READONLY (exp);
=20
Index: contrib/gcc/function.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /mnt/ncvs/src/contrib/gcc/function.c,v
retrieving revision 1.6
diff -u -r1.6 function.c
--- contrib/gcc/function.c	1999/11/01 18:56:02	1.6
+++ contrib/gcc/function.c	2000/11/17 22:05:36
@@ -59,6 +59,7 @@
 #include "obstack.h"
 #include "toplev.h"
 #include "hash.h"
+#include "protector.h"
=20
 #ifndef TRAMPOLINE_ALIGNMENT
 #define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY
@@ -431,6 +432,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 P=
roPolice */
+  int boundary_mark;
 };
=20
 /* List of all temporaries allocated, both available and in use.  */
@@ -450,6 +453,11 @@
    until no longer needed.  CLEANUP_POINT_EXPRs define the lifetime
    of TARGET_EXPRs.  */
 int target_temp_slot_level;
+
+/* Current boundary mark for character arrays.  */
+
+int temp_boundary_mark;
+
 =0C
 /* This structure is used to record MEMs or pseudos used to replace VAR, a=
ny
    SUBREGs of VAR, and any MEMs containing VAR as an address.  We need to
@@ -932,6 +940,7 @@
   int align;
   int alias_set;
   struct temp_slot *p, *best_p =3D 0;
+  int char_array =3D type && (TREE_TYPE (type)=3D=3Dchar_type_node);
=20
   /* If SIZE is -1 it means that somebody tried to allocate a temporary
      of a variable size.  */
@@ -964,7 +973,8 @@
 	&& (!flag_strict_aliasing
 	    || (alias_set && p->alias_set =3D=3D alias_set))
 	&& (best_p =3D=3D 0 || best_p->size > p->size
-	    || (best_p->size =3D=3D p->size && best_p->align > p->align)))
+	    || (best_p->size =3D=3D p->size && best_p->align > p->align))
+	&& (! char_array || p->boundary_mark !=3D 0))
       {
 	if (p->align =3D=3D align && p->size =3D=3D size)
 	  {
@@ -1002,6 +1012,7 @@
 	      p->align =3D best_p->align;
 	      p->address =3D 0;
 	      p->rtl_expr =3D 0;
+	      p->boundary_mark =3D best_p->boundary_mark;
 	      p->next =3D temp_slots;
 	      temp_slots =3D p;
=20
@@ -1063,6 +1074,7 @@
       p->full_size =3D frame_offset - frame_offset_old;
 #endif
       p->address =3D 0;
+      p->boundary_mark =3D char_array?++temp_boundary_mark:0;
       p->next =3D temp_slots;
       temp_slots =3D p;
     }
@@ -1187,14 +1199,16 @@
 	    int delete_q =3D 0;
 	    if (! q->in_use && GET_MODE (q->slot) =3D=3D BLKmode)
 	      {
-		if (p->base_offset + p->full_size =3D=3D q->base_offset)
+		if (p->base_offset + p->full_size =3D=3D q->base_offset &&
+		    p->boundary_mark =3D=3D q->boundary_mark)
 		  {
 		    /* Q comes after P; combine Q into P.  */
 		    p->size +=3D q->size;
 		    p->full_size +=3D q->full_size;
 		    delete_q =3D 1;
 		  }
-		else if (q->base_offset + q->full_size =3D=3D p->base_offset)
+		else if (q->base_offset + q->full_size =3D=3D p->base_offset &&
+			 p->boundary_mark =3D=3D q->boundary_mark)
 		  {
 		    /* P comes after Q; combine P into Q.  */
 		    q->size +=3D p->size;
@@ -1694,7 +1708,7 @@
       if (regno < max_parm_reg)
 	new =3D parm_reg_stack_loc[regno];
       if (new =3D=3D 0)
-	new =3D assign_stack_local (decl_mode, GET_MODE_SIZE (decl_mode), 0);
+	new =3D assign_stack_local_for_pseudo_reg (decl_mode, GET_MODE_SIZE (decl=
_mode), 0);
     }
=20
   PUT_MODE (reg, decl_mode);
@@ -6966,4 +6980,10 @@
 	}
     }
 #endif /* HAVE_prologue or HAVE_epilogue */
+}
+
+tree
+query_trampoline_list()
+{
+    return trampoline_list;
 }
Index: contrib/gcc/gcse.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /mnt/ncvs/src/contrib/gcc/gcse.c,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 gcse.c
--- contrib/gcc/gcse.c	1999/11/01 08:26:03	1.1.1.3
+++ contrib/gcc/gcse.c	2000/11/17 22:05:36
@@ -3718,7 +3718,7 @@
       /* Find an assignment that sets reg_used and is available
 	 at the start of the block.  */
       set =3D find_avail_set (regno, insn);
-      if (! set)
+      if (! set || set->expr->volatil)
 	continue;
  =20
       pat =3D set->expr;
Index: contrib/gcc/integrate.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /mnt/ncvs/src/contrib/gcc/integrate.c,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 integrate.c
--- contrib/gcc/integrate.c	1999/10/16 06:05:22	1.1.1.3
+++ contrib/gcc/integrate.c	2000/11/17 22:05:37
@@ -38,6 +38,7 @@
 #include "function.h"
 #include "toplev.h"
 #include "intl.h"
+#include "protector.h"
=20
 #include "obstack.h"
 #define	obstack_chunk_alloc	xmalloc
@@ -1503,10 +1504,10 @@
 	    arg_vals[i] =3D convert_modes (GET_MODE (loc),
 					 TYPE_MODE (TREE_TYPE (arg)),
 					 expand_expr (arg, NULL_RTX, mode,
-						      EXPAND_SUM),
+						      flag_propolice_protection?EXPAND_NORMAL:EXPAND_SUM),
 					 TREE_UNSIGNED (TREE_TYPE (formal)));
 	  else
-	    arg_vals[i] =3D expand_expr (arg, NULL_RTX, mode, EXPAND_SUM);
+	    arg_vals[i] =3D expand_expr (arg, NULL_RTX, mode, flag_propolice_prot=
ection?EXPAND_NORMAL:EXPAND_SUM);
 	}
       else
 	arg_vals[i] =3D 0;
Index: contrib/gcc/libgcc2.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /mnt/ncvs/src/contrib/gcc/libgcc2.c,v
retrieving revision 1.4
diff -u -r1.4 libgcc2.c
--- contrib/gcc/libgcc2.c	1999/10/27 09:45:47	1.4
+++ contrib/gcc/libgcc2.c	2000/11/17 22:05:37
@@ -4014,3 +4014,32 @@
   __terminate ();
 }
 #endif
+=0C
+#ifdef L_stack_smash_handler
+#include <fcntl.h>
+char __guard[32] =3D "";
+static void __guard_setup (void) __attribute__ ((constructor)) ;
+static void __guard_setup (void)
+{
+  int fd;
+  if (((int*)__guard)[0]!=3D0) return;
+  fd =3D open ("/dev/urandom", 0);
+  if (fd !=3D -1) {
+    ssize_t size =3D read (fd, &__guard, sizeof(__guard));
+    close (fd) ;
+    if (size =3D=3D sizeof(__guard)) return;
+  }
+  /* If a random generator can't be used, the protector switches the guard
+     to the "terminator canary" */
+  __guard[0] =3D 0; __guard[1] =3D 0; __guard[2] =3D '\n'; __guard[3] =3D =
255;
+}
+void __stack_smash_handler (char func[], int damaged)
+{
+  char *message =3D ": stack smashing attack? " ;
+  volatile char *faultloc;
+  write (STDERR_FILENO, func, strlen(func));
+  write (STDERR_FILENO, message, strlen(message));
+  faultloc =3D 0; *faultloc =3D *faultloc;
+  exit (666) ;
+}
+#endif
Index: contrib/gcc/reload1.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /mnt/ncvs/src/contrib/gcc/reload1.c,v
retrieving revision 1.1.1.4
diff -u -r1.1.1.4 reload1.c
--- contrib/gcc/reload1.c	2000/03/09 09:21:40	1.1.1.4
+++ contrib/gcc/reload1.c	2000/11/17 22:05:37
@@ -38,6 +38,7 @@
 #include "output.h"
 #include "real.h"
 #include "toplev.h"
+#include "protector.h"
=20
 #if !defined PREFERRED_STACK_BOUNDARY && defined STACK_BOUNDARY
 #define PREFERRED_STACK_BOUNDARY STACK_BOUNDARY
@@ -2419,7 +2420,7 @@
       if (from_reg =3D=3D -1)
 	{
 	  /* No known place to spill from =3D> no slot to reuse.  */
-	  x =3D assign_stack_local (GET_MODE (regno_reg_rtx[i]), total_size,
+	  x =3D assign_stack_local_for_pseudo_reg (GET_MODE (regno_reg_rtx[i]), t=
otal_size,
 				  inherent_size =3D=3D total_size ? 0 : -1);
 	  if (BYTES_BIG_ENDIAN)
 	    /* Cancel the  big-endian correction done in assign_stack_local.
Index: contrib/gcc/toplev.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /mnt/ncvs/src/contrib/gcc/toplev.c,v
retrieving revision 1.7
diff -u -r1.7 toplev.c
--- contrib/gcc/toplev.c	2000/03/26 12:56:54	1.7
+++ contrib/gcc/toplev.c	2000/11/17 22:05:37
@@ -776,6 +776,13 @@
=20
 int flag_no_ident =3D 0;
=20
+#ifdef STACK_PROTECTOR
+/* Nonzero means use ProPolice as a stack protection method */
+int flag_propolice_protection =3D 1;
+#else
+int flag_propolice_protection =3D 0;
+#endif
+
 /* Table of supported debugging formats.  */
 static struct
 {
@@ -985,7 +992,11 @@
   {"leading-underscore", &flag_leading_underscore, 1,
    "External symbols have a leading underscore" },
   {"ident", &flag_no_ident, 0,
-   "Process #ident directives"}
+   "Process #ident directives"},
+  {"stack-protector", &flag_propolice_protection, 1,
+   "Enables stack protection" },
+  {"no-stack-protector", &flag_propolice_protection, 0,
+   "Disables stack protection" },
 };
=20
 #define NUM_ELEM(a)  (sizeof (a) / sizeof ((a)[0]))
@@ -3651,6 +3662,8 @@
=20
       insns =3D get_insns ();
=20
+      if (flag_propolice_protection) prepare_stack_protection ();
+ =20
       /* Dump the rtl code if we are dumping rtl.  */
=20
       if (rtl_dump)
--- /dev/null	Fri Nov 17 15:02:17 2000
+++ contrib/gcc/protector.h	Fri Nov 17 14:06:24 2000
@@ -0,0 +1,46 @@
+/* Top level of GNU C compiler
+   Copyright (C) 1987, 88, 89, 92-7, 1998 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC 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.
+
+GNU CC 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 GNU CC; 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		SImode
+#define UNITS_PER_GUARD 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 ((void));
+
+/* 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, H=
OST_WIDE_INT, int));
+
+/* Update the debug information of the function argument pointed by 'old' =
*/
+extern void set_debuginfo_of_escaped_arg PARAMS ((rtx new, rtx old));
+
+
+/* Nonzero means use propolice as a stack protection method */
+extern int flag_propolice_protection;
+
+#endif
--- /dev/null	Fri Nov 17 15:02:17 2000
+++ contrib/gcc/protector.c	Fri Nov 17 14:06:24 2000
@@ -0,0 +1,1866 @@
+/* Top level of GNU C compiler
+   Copyright (C) 1987, 88, 89, 92-7, 1998 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC 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.
+
+GNU CC 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 GNU CC; 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 "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 "protector.h"
+
+
+rtx assign_stack_local_for_pseudo_reg PARAMS ((enum machine_mode, HOST_WID=
E_INT, int));
+void set_debuginfo_of_escaped_arg PARAMS ((rtx old, rtx new));
+void update_debuginfo_using_escaped_arg_list PARAMS ((tree parms));
+
+
+/* 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;
+
+/* List of trampolines */
+extern tree query_trampoline_list PARAMS ((void));
+
+typedef struct { rtx original; rtx escaped; } arg_status;
+
+/* 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 b=
e
+   damaged by the stack-smash attack */
+static int current_function_defines_vulnerable_string;
+static int current_function_has_variable_string;
+
+static rtx guard_area, _guard;
+static rtx function_first_insn, prologue_insert_point;
+
+/*  */
+static HOST_WIDE_INT sweep_frame_offset;
+static arg_status* escaped_arg_list =3D 0;
+static int escaped_arg_list_size =3D 0;
+
+static int search_string_from_argsandvars PARAMS ((void));
+static int search_string_from_local_vars PARAMS ((tree block));
+static int search_string_def PARAMS ((tree names));
+static int search_pointer_def PARAMS ((tree names));
+static int search_func_pointer PARAMS ((tree type, int mark));
+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, int var_size));
+static void sweep_string_in_decls PARAMS ((tree block, int sweep_offset, i=
nt size));
+static void sweep_string_in_args PARAMS ((tree parms, int sweep_offset, in=
t size));
+static void sweep_string_use_of_insns PARAMS ((rtx insn, int sweep_offset,=
 int size));
+static void sweep_string_in_operand PARAMS ((rtx orig, int sweep_offset, i=
nt size));
+static void move_arg_location PARAMS ((rtx insn, rtx orig, rtx new, int va=
r_size));
+static void change_arg_use_of_insns PARAMS ((rtx insn, rtx orig, rtx new, =
int size));
+static void change_arg_use_in_operand PARAMS ((rtx x, rtx orig, rtx new, i=
nt size));
+static void expand_value_return PARAMS ((rtx val));
+static int  replace_return_reg PARAMS ((rtx insn, rtx return_save));
+
+
+#define SUSPICIOUS_BUF_SIZE 8
+
+#define DEBUGGER_AUTO_BASEPTR(X) \
+  (GET_CODE (X) =3D=3D PLUS ? XEXP (X, 0) : X)
+#define DEBUGGER_AUTO_OFFSET(X) \
+  (GET_CODE (X) =3D=3D PLUS ? INTVAL (XEXP (X, 1)) : 0)
+#define PARM_PASSED_IN_MEMORY(PARM) \
+ (GET_CODE (DECL_INCOMING_RTL (PARM)) =3D=3D MEM)
+
+
+
+void
+prepare_stack_protection (void)
+{
+  tree blocks =3D DECL_INITIAL (current_function_decl);
+  current_function_has_variable_string =3D FALSE;
+
+  /*
+    skip the protection if the function has no block or it is an inline fu=
nction
+  */
+  if (! blocks || DECL_INLINE (current_function_decl)) return;
+
+  current_function_defines_vulnerable_string =3D search_string_from_argsan=
dvars ();
+
+  if (current_function_defines_vulnerable_string)
+    {
+      HOST_WIDE_INT previous_frame_offset, offset;
+      function_first_insn =3D get_insns ();
+
+      if (query_trampoline_list ()) return;
+   =20
+      sweep_frame_offset =3D 0;
+=09
+#ifdef STACK_GROWS_DOWNWARD
+      /*
+	frame_offset: offset to end of allocated area of stack frame.
+	 It is defined in the function.c
+      */
+      previous_frame_offset =3D frame_offset;
+
+      /* the location must be before buffers */
+      guard_area =3D assign_stack_local (GUARD_m, UNITS_PER_GUARD, 0);
+      MEM_VOLATILE_P (guard_area) =3D 1;
+=09
+=09
+#ifndef FRAME_GROWS_DOWNWARD
+      sweep_frame_offset =3D frame_offset;
+#endif
+
+      /* For making room for guard value, scan all insns and fix the offse=
t address
+	 of the variable that is based on frame pointer.
+	 Scan all declarations of variables and fix the offset address of the var=
iable that
+	 is based on the frame pointer */
+      sweep_string_variable (guard_area, UNITS_PER_GUARD);
+
+=09
+      /* the location of guard area moves to the beginning of stack frame =
*/
+      offset =3D DEBUGGER_AUTO_OFFSET(XEXP (guard_area, 0));
+      XEXP (XEXP (guard_area, 0), 1) =3D gen_rtx_CONST_INT (VOIDmode, swee=
p_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 =3D frame_offset;
+	  sweep_string_variable (guard_area, UNITS_PER_GUARD);
+#endif
+	}
+#endif
+
+      if (! current_function_has_variable_string)
+	{
+	  /* Arrange the order of local variables */
+	  arrange_var_order (blocks);
+	}
+
+#ifdef STACK_GROWS_DOWNWARD
+      /* Insert epilogue rtl instructions */
+      rtl_epilogue (get_last_insn ());
+#endif
+    }
+}
+
+
+static int
+search_string_from_argsandvars (void)
+{
+  tree blocks, parms;
+  int string_p;
+
+  /*
+    search a string variable from local variables
+  */
+  blocks =3D DECL_INITIAL (current_function_decl);
+  string_p =3D search_string_from_local_vars (blocks);
+  if (string_p) return TRUE;
+
+
+#ifdef FRAME_GROWS_DOWNWARD
+  /*
+    search a string variable from arguments
+  */
+  parms =3D DECL_ARGUMENTS (current_function_decl);
+
+  for (; parms; parms =3D TREE_CHAIN (parms))
+    if (DECL_NAME (parms) && TREE_TYPE (parms) !=3D error_mark_node)
+      {
+	if (PARM_PASSED_IN_MEMORY (parms) && DECL_NAME (parms))
+	  {
+	    string_p =3D search_string_def (TREE_TYPE(parms));
+	    if (string_p) return TRUE;
+	  }
+      }
+#endif
+
+  return FALSE;
+}
+
+
+static int
+search_string_from_local_vars (block)
+     tree block;
+{
+  tree types;
+  int found =3D FALSE;
+
+  while (block)
+    {
+      types =3D BLOCK_VARS(block);
+
+      while (types)
+	{
+	  /* skip the declaration that refers an external variable */
+	  if (! DECL_EXTERNAL (types) && ! TREE_STATIC (types) &&
+	      (TREE_CODE (types) =3D=3D VAR_DECL))
+	    {
+
+	      if (search_string_def (TREE_TYPE (types)))
+		{
+		  rtx home =3D DECL_RTL (types);
+
+		  if (GET_CODE (home) =3D=3D MEM
+		      && (GET_CODE (XEXP (home, 0)) =3D=3D MEM
+			  || (GET_CODE (XEXP (home, 0)) =3D=3D REG
+			      && REGNO (XEXP (home, 0)) !=3D HARD_FRAME_POINTER_REGNUM
+			      && REGNO (XEXP (home, 0)) !=3D STACK_POINTER_REGNUM
+#if ARG_POINTER_REGNUM !=3D HARD_FRAME_POINTER_REGNUM
+			      && REGNO (XEXP (home, 0)) !=3D 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 p=
ointer variables
+		       behind the array, so all we can do is staying the order of variab=
les and arguments. */
+		    {
+		      current_function_has_variable_string =3D TRUE;
+		    }
+	   =20
+		  found =3D TRUE;
+		}
+	    }
+
+	  types =3D TREE_CHAIN(types);
+	}
+
+      if (search_string_from_local_vars (BLOCK_SUBBLOCKS (block)))
+	{
+	  found =3D TRUE;
+	}
+
+      block =3D BLOCK_CHAIN (block);
+    }
+   =20
+  return found;
+}
+
+static int
+search_string_def (type)
+     tree type;
+{
+  tree tem;
+   =20
+  /* Mark it as defined, so that if it is self-referent
+     we will not get into an infinite recursion of definitions.  */
+
+  switch (TREE_CODE (type))
+    {
+    case ARRAY_TYPE:
+      /* TREE_CODE( TREE_TYPE(type) ) =3D=3D INTEGER_TYPE */
+      if (TREE_TYPE(type) =3D=3D char_type_node)
+	{
+	  /* Check if the string is a variable string */
+	  if (TYPE_DOMAIN (type) =3D=3D 0 ||
+	      TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) =3D=3D NOP_EXPR)
+	    return TRUE;
+
+	  /* Check if the string size is greater than SUSPICIOUS_BUF_SIZE */
+	  if (TREE_INT_CST_LOW(TYPE_MAX_VALUE(TYPE_DOMAIN(type)))+1 >=3D SUSPICIO=
US_BUF_SIZE)
+	    return TRUE;
+	}
+      return search_string_def(TREE_TYPE(type));
+=09
+    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 =3D TYPE_FIELDS (type); tem; tem =3D TREE_CHAIN (tem))
+	{
+	  /* Omit here local type decls until we know how to support them. */
+	  if ((TREE_CODE (tem) =3D=3D TYPE_DECL)
+	      || (TREE_CODE (tem) =3D=3D VAR_DECL && TREE_STATIC (tem)))
+	    continue;
+
+	  if (search_string_def(TREE_TYPE(tem))) return TRUE;
+	}
+      break;
+=09
+    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;
+}
+
+
+static int
+search_pointer_def (type)
+     tree type;
+{
+  tree tem;
+   =20
+  /* Mark it as defined, so that if it is self-referent
+     we will not get into an infinite recursion of definitions.  */
+
+  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 =3D TYPE_FIELDS (type); tem; tem =3D TREE_CHAIN (tem))
+	{
+	  /* Omit here local type decls until we know how to support them. */
+	  if ((TREE_CODE (tem) =3D=3D TYPE_DECL)
+	      || (TREE_CODE (tem) =3D=3D 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));
+=09
+    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 (TYPE_READONLY (TREE_TYPE (type)))
+	{
+	  int funcp =3D search_func_pointer (TREE_TYPE (type), 1);
+	  /* Un-mark the type as having been visited already */
+	  search_func_pointer (TREE_TYPE (type), 0);
+	  return funcp;
+	}
+      return TRUE;
+=09
+    default:
+      break;
+    }
+
+  return FALSE;
+}
+
+
+static int
+search_func_pointer (type, mark)
+     tree type;
+     int mark;
+{
+  tree tem;
+   =20
+  /* Mark it as defined, so that if it is self-referent
+     we will not get into an infinite recursion of definitions.  */
+
+  switch (TREE_CODE (type))
+    {
+    case UNION_TYPE:
+    case QUAL_UNION_TYPE:
+    case RECORD_TYPE:
+	if (TREE_ASM_WRITTEN (type) !=3D mark)
+	  {
+	    /* mark the type as having been visited already */
+	    TREE_ASM_WRITTEN (type) =3D mark;
+
+	    /* Output the name, type, position (in bits), size (in bits) of
+	       each field.  */
+	    for (tem =3D TYPE_FIELDS (type); tem; tem =3D TREE_CHAIN (tem))
+	      {
+		/* Omit here local type decls until we know how to support them. */
+		if (TREE_CODE (tem) =3D=3D FIELD_DECL
+		    && search_func_pointer (TREE_TYPE(tem), mark)) return TRUE;
+	      }
+	  }
+	break;
+
+    case ARRAY_TYPE:
+      return search_func_pointer (TREE_TYPE(type), mark);
+=09
+    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:
+      return TREE_CODE (TREE_TYPE (type)) =3D=3D FUNCTION_TYPE;
+=09
+    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 =3D NEXT_INSN (insn))
+    if (GET_CODE (insn) =3D=3D INSN || GET_CODE (insn) =3D=3D JUMP_INSN
+	|| GET_CODE (insn) =3D=3D CALL_INSN)
+      {
+	code =3D GET_CODE (insn);
+	insn->used =3D 0;
+	format_ptr =3D GET_RTX_FORMAT (code);
+
+	for (i =3D 0; i < GET_RTX_LENGTH (code); i++)
+	  {
+	    switch (*format_ptr++) {
+	    case 'e':
+	      reset_used_flags_of_plus (XEXP (insn, i));
+	      break;
+		=09
+	    case 'E':
+	      for (j =3D 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)
+    {
+      types =3D BLOCK_VARS(block);
+=09
+      while (types)
+	{
+	  /* skip the declaration that refers an external variable and
+	     also skip an global variable */
+	  if (! DECL_EXTERNAL (types))
+	    {
+	      home =3D DECL_RTL (types);
+	      if (home =3D=3D 0) goto next;
+
+	      if (GET_CODE (home) =3D=3D MEM
+		  && GET_CODE (XEXP (home, 0)) =3D=3D PLUS
+		  && GET_CODE (XEXP (XEXP (home, 0), 1)) =3D=3D CONST_INT)
+		{
+		  XEXP (home, 0)->used =3D 0;
+		}
+	    }
+	next:
+	  types =3D TREE_CHAIN(types);
+	}
+
+      reset_used_flags_for_decls (BLOCK_SUBBLOCKS (block));
+
+      block =3D 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 =3D=3D 0)
+    return;
+
+  code =3D 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;
+     =20
+    case PLUS:
+      x->used =3D 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 =3D GET_RTX_FORMAT (code);
+  for (i =3D 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 =3D 0; j < XVECLEN (x, i); j++)
+	    reset_used_flags_of_plus (XVECEXP (x, i, j));
+	  break;
+	}
+    }
+}
+
+
+static void
+rtl_prologue (insn)
+     rtx insn;
+{
+  for (; insn; insn =3D NEXT_INSN (insn))
+    if (GET_CODE (insn) =3D=3D NOTE && NOTE_LINE_NUMBER (insn) =3D=3D NOTE=
_INSN_FUNCTION_BEG)
+      {
+	rtx _val;
+
+	prologue_insert_point =3D NEXT_INSN (insn);	/* mark the next insn of FUNC=
TION_BEG insn */
+	=09
+	start_sequence ();
+
+	_guard =3D gen_rtx_MEM (GUARD_m, gen_rtx_SYMBOL_REF (Pmode, "__guard"));
+	emit_move_insn ( guard_area, _guard);
+
+	_val =3D gen_sequence ();
+	end_sequence ();
+
+	emit_insn_before (_val, prologue_insert_point);
+	break;
+      }
+}
+
+static void
+rtl_epilogue (insn)
+     rtx insn;
+{
+  /* Like STACK_BOUNDARY but in units of bytes, not bits.  */
+#define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT)
+
+  rtx if_false_label;
+  rtx _val, handler, funcname, addr;
+  tree funcstr;
+  HOST_WIDE_INT args_size;
+  enum machine_mode arg1mode;
+  rtx return_reg =3D DECL_RTL (DECL_RESULT (current_function_decl)), retur=
n_save;
+	=09
+  handler =3D gen_rtx_MEM (FUNCTION_MODE, gen_rtx (SYMBOL_REF, Pmode, "__s=
tack_smash_handler"));
+
+  start_sequence ();
+
+  if (return_reg
+      && ! (current_function_returns_struct
+	    || current_function_returns_pcc_struct))
+    {
+      return_save =3D gen_reg_rtx (GET_MODE (return_reg));
+
+      if (! replace_return_reg (prologue_insert_point, return_save))
+	emit_move_insn (return_save, return_reg);
+    }
+
+  compare_from_rtx (guard_area, _guard, NE, 0, GUARD_m, 0, 0);	/* if (guar=
d_area !=3D _guard) */
+
+  if_false_label =3D gen_label_rtx ();				/* { */
+  emit_jump_insn ( gen_beq(if_false_label));
+
+  /*
+    In the function force_const_mem in varasm.c of egcs-1.1.2-30, there is=
 a=20
+    failure to assign the guard_area variable to eax register, which destr=
oys=20
+    the return value of the function.
+
+    The BUG preceding comment is an apropriate processes.
+    When the bug is fixed, removes the comment
+  */
+
+  /* generate string for the current function name */
+  funcstr =3D build_string (strlen(current_function_name)+1, current_funct=
ion_name);
+  TREE_TYPE (funcstr) =3D build_array_type (char_type_node, 0);/* =3D char=
_array_type_node;*/
+  funcname =3D output_constant_def (funcstr);
+
+  addr =3D gen_push_operand ();
+  emit_move_insn (gen_rtx_MEM (GUARD_m, addr), guard_area);		/* push the v=
alue of guard area */
+
+  arg1mode =3D GET_MODE (XEXP (funcname, 0));
+  addr =3D gen_push_operand ();
+  emit_move_insn (gen_rtx_MEM (arg1mode, addr), XEXP (funcname, 0));	/* pu=
sh current_function_name */
+
+  /* calculate the stack size of two arguments */
+  args_size =3D GET_MODE_SIZE (arg1mode) + GET_MODE_SIZE (GUARD_m);
+#ifdef PUSH_ROUNDING
+  args_size =3D PUSH_ROUNDING (GET_MODE_SIZE (arg1mode)) + PUSH_ROUNDING (=
GET_MODE_SIZE (GUARD_m));
+#endif
+#ifdef STACK_BOUNDARY
+  args_size =3D (((args_size + (STACK_BYTES - 1)) / STACK_BYTES) * STACK_B=
YTES);
+#endif
+
+  /* jump to the stack smash handler */
+  emit_call_insn (gen_call (handler, GEN_INT (args_size), const0_rtx));
+
+  /* generate RTL to return from the current function */
+	=09
+  emit_barrier ();						/* } */
+  emit_label (if_false_label);
+
+  /* generate RTL to return from the current function */
+  if (return_reg)
+    {
+      if (!current_function_returns_struct && !current_function_returns_pc=
c_struct)
+	expand_value_return (return_save);
+=09
+
+      /* If returning a structure, arrange to return the address of the va=
lue
+	 in a place where debuggers expect to find it.
+
+	 If returning a structure PCC style,
+	 the caller also depends on this value.
+	 And current_function_returns_pcc_struct is not necessarily set.  */
+      else
+	{
+	  rtx value_address =3D XEXP (DECL_RTL (DECL_RESULT (current_function_dec=
l)), 0);
+	  tree type =3D TREE_TYPE (DECL_RESULT (current_function_decl));
+#ifdef FUNCTION_OUTGOING_VALUE
+	  rtx outgoing
+	    =3D FUNCTION_OUTGOING_VALUE (build_pointer_type (type),
+				       current_function_decl);
+#else
+	  rtx outgoing
+	    =3D FUNCTION_VALUE (build_pointer_type (type),
+			      current_function_decl);
+#endif
+	 =20
+	  /* Mark this as a function return value so integrate will delete the
+	     assignment and USE below when inlining this function.  */
+	  REG_FUNCTION_VALUE_P (outgoing) =3D 1;
+
+	  emit_move_insn (outgoing, value_address);
+	  use_variable (outgoing);
+	}
+    }
+
+  _val =3D gen_sequence ();
+  end_sequence ();
+
+  emit_insn_after (_val, insn);
+}
+
+
+static void
+arrange_var_order (block)
+     tree block;
+{
+  tree types;
+  int offset;
+   =20
+  while (block)
+    {
+      types =3D BLOCK_VARS (block);
+
+      while (types)
+	{
+	  /* skip the declaration that refers an external variable */
+	  if (! DECL_EXTERNAL (types) && ! TREE_STATIC (types)
+	      && (TREE_CODE (types) =3D=3D VAR_DECL))
+	    {
+	      if (search_string_def (TREE_TYPE (types)))
+		{
+		  /* found a string variable */
+		  int var_size =3D
+		    ((TREE_INT_CST_LOW (DECL_SIZE (types)) + BITS_PER_UNIT - 1)
+		     / BITS_PER_UNIT);
+
+		  if (GET_MODE (DECL_RTL (types)) =3D=3D BLKmode)
+		    {
+		      int alignment =3D BIGGEST_ALIGNMENT / BITS_PER_UNIT;
+		      var_size =3D CEIL_ROUND (var_size, alignment);
+		    }
+
+		  /* skip the variable if it is top of the region
+		     specified by sweep_frame_offset */
+		  offset =3D DEBUGGER_AUTO_OFFSET (XEXP (DECL_RTL (types), 0));
+		  if (offset >=3D sweep_frame_offset - var_size)
+		    sweep_frame_offset -=3D var_size;
+
+		  else
+		    sweep_string_variable (DECL_RTL (types), var_size);
+		}
+	    }
+
+	  types =3D TREE_CHAIN(types);
+	}
+
+      arrange_var_order (BLOCK_SUBBLOCKS (block));
+
+      block =3D BLOCK_CHAIN (block);
+    }
+}
+
+
+static void
+copy_args_for_protection (void)
+{
+  tree parms =3D DECL_ARGUMENTS (current_function_decl);
+  rtx temp_rtx;
+  int idx;
+
+  escaped_arg_list_size =3D 0;
+
+  /* count the number of argument passed in memory */
+  for (; parms; parms =3D TREE_CHAIN (parms))
+    if (DECL_NAME (parms) && TREE_TYPE (parms) !=3D error_mark_node)
+      {
+	if (PARM_PASSED_IN_MEMORY (parms))
+	  escaped_arg_list_size ++;
+      }
+
+  if (escaped_arg_list) free (escaped_arg_list);
+  escaped_arg_list =3D xmalloc (sizeof (arg_status) * escaped_arg_list_siz=
e);
+ =20
+  parms =3D DECL_ARGUMENTS (current_function_decl);
+  for (idx =3D 0; parms; parms =3D TREE_CHAIN (parms), idx++)
+    if (DECL_NAME (parms) && TREE_TYPE (parms) !=3D 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) =3D=3D 0)
+	      {
+	        fntype =3D TREE_TYPE (current_function_decl);
+
+	        if ((TYPE_ARG_TYPES (fntype) !=3D 0 &&
+	             TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) !=3D void_t=
ype_node)
+	             || current_function_varargs)
+	          continue;
+	      }
+	    */
+
+	    escaped_arg_list[idx].original =3D 0;
+	    escaped_arg_list[idx].escaped =3D 0;
+	=09
+	    string_p =3D 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
+		  =3D ((TREE_INT_CST_LOW (DECL_SIZE (parms)) + BITS_PER_UNIT - 1)
+		     / BITS_PER_UNIT);
+	=09
+		start_sequence ();
+
+		if (GET_CODE (DECL_RTL (parms)) =3D=3D REG)
+		  {
+		    rtx movinsn;
+		    rtx safe =3D gen_reg_rtx (GET_MODE (DECL_RTL (parms)));
+
+		    /* generate codes for copying the content */
+		    movinsn =3D emit_move_insn (safe, DECL_RTL (parms));
+		    PATTERN (movinsn)->volatil =3D 1;	/* avoid register elimination in g=
cse.c (COPY-PROP)*/
+
+		    change_arg_use_of_insns (prologue_insert_point, DECL_RTL (parms), sa=
fe, 0);
+
+		    /* save debugger info */
+		    escaped_arg_list[idx].original =3D DECL_RTL (parms);
+		    escaped_arg_list[idx].escaped =3D safe;
+		  }
+
+		else if (GET_CODE (DECL_RTL (parms)) =3D=3D MEM
+			 && GET_CODE (XEXP (DECL_RTL (parms), 0)) =3D=3D ADDRESSOF)
+		  {
+		    rtx movinsn;
+		    rtx safe =3D gen_reg_rtx (GET_MODE (DECL_RTL (parms)));
+
+		    /* generate codes for copying the content */
+		    movinsn =3D emit_move_insn (safe, DECL_INCOMING_RTL (parms));
+		    PATTERN (movinsn)->volatil =3D 1;	/* avoid register elimination in g=
cse.c (COPY-PROP)*/
+
+		    /* change the addressof information to the newly allocated pseudo re=
gister */
+		    emit_move_insn (DECL_RTL (parms), safe);
+
+		    /* save debugger info */
+		    escaped_arg_list[idx].original =3D DECL_RTL (parms);
+		    escaped_arg_list[idx].escaped =3D safe;
+		  }
+		=09
+		else
+		  {
+		    /* declare temporary local variable DECL_NAME (parms) for it */
+		    temp_rtx
+		      =3D assign_stack_local (DECL_MODE (parms), arg_size,
+					    DECL_MODE (parms) =3D=3D BLKmode ? -1 : 0);
+		   =20
+		    MEM_IN_STRUCT_P (temp_rtx) =3D AGGREGATE_TYPE_P (TREE_TYPE (parms));
+		    MEM_ALIAS_SET (temp_rtx) =3D get_alias_set (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 */
+		    DECL_RTL (parms) =3D temp_rtx;
+
+		    /* change debugger info */
+		    DECL_INCOMING_RTL (parms) =3D temp_rtx;
+		  }
+
+		emit_insn_before (gen_sequence (), prologue_insert_point);
+		end_sequence ();
+
+#ifndef FRAME_GROWS_DOWNWARD
+		/* process the string argument */
+		if (string_p)
+		  {
+		    if (DECL_MODE (parms) =3D=3D BLKmode)
+		      {
+			int alignment =3D BIGGEST_ALIGNMENT / BITS_PER_UNIT;
+			arg_size =3D CEIL_ROUND (arg_size, alignment);
+		      }
+		=09
+		    /* 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_o=
ffset, that is
+  a last position of string variables.
+*/
+static void
+sweep_string_variable (sweep_var, var_size)
+     int var_size;
+     rtx sweep_var;
+{
+  int sweep_offset =3D DEBUGGER_AUTO_OFFSET(XEXP (sweep_var, 0));
+
+  /* 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_offse=
t, var_size);
+
+  /* scan all argument variable and fix the offset address based on the fr=
ame pointer */
+  sweep_string_in_args (DECL_ARGUMENTS (current_function_decl), sweep_offs=
et, 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 -=3D 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;
+     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;
+     int sweep_offset, sweep_size;
+{
+  tree types;
+  HOST_WIDE_INT offset;
+  rtx home;
+
+  while (block)
+    {
+      types =3D BLOCK_VARS(block);
+=09
+      while (types)
+	{
+	  /* skip the declaration that refers an external variable and
+	     also skip an global variable */
+	  if (! DECL_EXTERNAL (types) && ! TREE_STATIC (types)) {
+	   =20
+	    home =3D DECL_RTL (types);
+	    if (home =3D=3D 0) goto next;
+
+	    /* process for static local variable */
+	    if (GET_CODE (home) =3D=3D MEM
+		&& GET_CODE (XEXP (home, 0)) =3D=3D SYMBOL_REF)
+	      goto next;
+
+	    if (GET_CODE (home) =3D=3D MEM
+		&& GET_CODE (XEXP (home, 0)) =3D=3D REG)
+	      {
+		goto next;
+	      }
+	=09
+	    if (GET_CODE (home) =3D=3D MEM
+		&& GET_CODE (XEXP (home, 0)) =3D=3D MEM)
+	      {
+		/* process for dynamically allocated aray */
+		home =3D XEXP (home, 0);
+	      }
+	=09
+	    if (GET_CODE (home) =3D=3D MEM
+		&& GET_CODE (XEXP (home, 0)) =3D=3D PLUS
+		&& GET_CODE (XEXP (XEXP (home, 0), 1)) =3D=3D CONST_INT)
+	      {
+		if (! XEXP (home, 0)->used)
+		  {
+		    offset =3D DEBUGGER_AUTO_OFFSET(XEXP (home, 0));
+
+		    /* the operand related to the sweep variable */
+		    if (sweep_offset <=3D offset
+			&& offset < sweep_offset + sweep_size)
+		      {
+
+			offset +=3D sweep_frame_offset - sweep_size - sweep_offset;
+			XEXP (XEXP (home, 0), 1) =3D gen_rtx_CONST_INT (VOIDmode, offset);
+
+			/* mark */
+			XEXP (home, 0)->used =3D 1;
+		      }
+		    else if (sweep_offset <=3D offset
+			     && offset < sweep_frame_offset)
+		      {	/* the rest of variables under sweep_frame_offset,
+			   so shift the location */
+
+			XEXP (XEXP (home, 0), 1)
+			  =3D gen_rtx_CONST_INT (VOIDmode, offset - sweep_size);
+
+			/* mark */
+			XEXP (home, 0)->used =3D 1;
+		      }
+		  }
+	      }
+
+	  }
+	next:
+	  types =3D TREE_CHAIN(types);
+	}
+
+      sweep_string_in_decls (BLOCK_SUBBLOCKS (block), sweep_offset, sweep_=
size);
+      block =3D BLOCK_CHAIN (block);
+    }
+}
+
+
+static void
+sweep_string_in_args (parms, sweep_offset, sweep_size)
+     tree parms;
+     int sweep_offset, sweep_size;
+{
+  rtx home;
+  HOST_WIDE_INT offset;
+   =20
+  for (; parms; parms =3D TREE_CHAIN (parms))
+    if (DECL_NAME (parms) && TREE_TYPE (parms) !=3D error_mark_node)
+      {
+	if (PARM_PASSED_IN_MEMORY (parms) && DECL_NAME (parms))
+	  {
+	    home =3D DECL_INCOMING_RTL (parms);
+
+	    if (XEXP (home, 0)->used) continue;
+
+	    offset =3D DEBUGGER_AUTO_OFFSET(XEXP (home, 0));
+
+	    /* the operand related to the sweep variable */
+	    if (DEBUGGER_AUTO_BASEPTR (XEXP (home, 0)) =3D=3D virtual_stack_vars_=
rtx)
+	      {
+		if (sweep_offset <=3D offset
+		    && offset < sweep_offset + sweep_size)
+		  {
+		    offset +=3D sweep_frame_offset - sweep_size - sweep_offset;
+		    XEXP (XEXP (home, 0), 1) =3D gen_rtx_CONST_INT (VOIDmode, offset);
+
+		    /* mark */
+		    XEXP (home, 0)->used =3D 1;
+		  }
+		else if (sweep_offset <=3D offset
+			 && offset < sweep_frame_offset)
+		  {	/* the rest of variables under sweep_frame_offset, so shift the loca=
tion */
+		    XEXP (XEXP (home, 0), 1) =3D gen_rtx_CONST_INT (VOIDmode, offset - s=
weep_size);
+
+		    /* mark */
+		    XEXP (home, 0)->used =3D 1;
+		  }
+	      }
+	  }
+      }
+}
+
+
+static void
+sweep_string_use_of_insns (insn, sweep_offset, sweep_size)
+     rtx insn;
+     int sweep_offset, sweep_size;
+{
+  for (; insn; insn =3D NEXT_INSN (insn))
+    if (GET_CODE (insn) =3D=3D INSN || GET_CODE (insn) =3D=3D JUMP_INSN
+	|| GET_CODE (insn) =3D=3D CALL_INSN)
+      {
+	sweep_string_in_operand (PATTERN (insn), sweep_offset, sweep_size);
+      }
+}
+
+
+static void
+sweep_string_in_operand (orig, sweep_offset, sweep_size)
+     rtx orig;
+     int sweep_offset, sweep_size;
+{
+  register rtx x =3D orig;
+  register enum rtx_code code;
+  int offset, i, j;
+  const char *fmt;
+
+  if (x =3D=3D 0)
+    return;
+
+  code =3D 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;
+	   =20
+    case SET:
+      break;
+	   =20
+    case PLUS:
+      /* Handle special case of frame register plus constant.  */
+      if (CONSTANT_P (XEXP (x, 1))
+	  && XEXP (x, 0) =3D=3D virtual_stack_vars_rtx
+	  && ! x->used)
+	{
+	  offset =3D DEBUGGER_AUTO_OFFSET(x);
+
+	  /* the operand related to the sweep variable */
+	  if (sweep_offset <=3D offset
+	      && offset < sweep_offset + sweep_size)
+	    {
+	      offset +=3D sweep_frame_offset - sweep_size - sweep_offset;
+
+	      XEXP (x, 0) =3D virtual_stack_vars_rtx;
+	      XEXP (x, 1) =3D gen_rtx_CONST_INT (VOIDmode, offset);
+	      x->used =3D 1;
+
+	      return;
+	    }
+	  else if (sweep_offset <=3D offset
+		   && offset < sweep_frame_offset)
+	    {	/* the rest of variables under sweep_frame_offset, so shift the loc=
ation */
+	      XEXP (x, 1) =3D gen_rtx_CONST_INT (VOIDmode, offset - sweep_size);
+	      x->used =3D 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:
+      sweep_string_use_of_insns (XEXP (x, 0), sweep_offset, sweep_size);
+      sweep_string_use_of_insns (XEXP (x, 1), sweep_offset, sweep_size);
+      sweep_string_use_of_insns (XEXP (x, 2), sweep_offset, sweep_size);
+      break;
+
+    default:
+      break;
+    }
+
+  /* Scan all subexpressions.  */
+  fmt =3D GET_RTX_FORMAT (code);
+  for (i =3D 0; i < GET_RTX_LENGTH (code); i++, fmt++)
+    if (*fmt =3D=3D 'e')
+      {
+	sweep_string_in_operand (XEXP (x, i), sweep_offset, sweep_size);
+      }
+    else if (*fmt =3D=3D 'E')
+      for (j =3D 0; j < XVECLEN (x, i); j++)
+	sweep_string_in_operand (XVECEXP (x, i, j), sweep_offset, sweep_size);
+}  =20
+
+
+/*
+  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;
+     int size;
+{
+  for (; insn; insn =3D NEXT_INSN (insn))
+    if (GET_CODE (insn) =3D=3D INSN || GET_CODE (insn) =3D=3D JUMP_INSN
+	|| GET_CODE (insn) =3D=3D CALL_INSN)
+      {
+	change_arg_use_in_operand (PATTERN (insn), orig, new, size);
+      }
+}
+
+
+static void
+change_arg_use_in_operand (x, orig, new, size)
+     rtx x, orig, new;
+     int size;
+{
+  register enum rtx_code code;
+  int offset, i, j;
+  const char *fmt;
+
+  if (x =3D=3D 0)
+    return;
+
+  code =3D 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;
+	   =20
+    case PLUS:
+      /* Handle special case of frame register plus constant.  */
+      if (GET_CODE (orig) =3D=3D MEM /* skip if orig is register variable =
in the optimization */
+	  && XEXP (x, 0) =3D=3D virtual_incoming_args_rtx && CONSTANT_P (XEXP (x,=
 1))
+	  && ! x->used)
+	{
+	  offset =3D DEBUGGER_AUTO_OFFSET(x);
+
+	  /* the operand related to the sweep variable */
+	  if (DEBUGGER_AUTO_OFFSET(XEXP (orig, 0)) <=3D offset &&
+	      offset < DEBUGGER_AUTO_OFFSET(XEXP (orig, 0)) + size) {
+
+	    offset +=3D frame_offset - DEBUGGER_AUTO_OFFSET(XEXP (orig, 0));
+
+	    XEXP (x, 0) =3D virtual_stack_vars_rtx;
+	    XEXP (x, 1) =3D gen_rtx_CONST_INT (VOIDmode, offset);
+	    x->used =3D 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:
+      change_arg_use_of_insns (XEXP (x, 0), orig, new, size);
+      change_arg_use_of_insns (XEXP (x, 1), orig, new, size);
+      change_arg_use_of_insns (XEXP (x, 2), orig, new, size);
+      break;
+
+    default:
+      break;
+    }
+
+  /* Scan all subexpressions.  */
+  fmt =3D GET_RTX_FORMAT (code);
+  for (i =3D 0; i < GET_RTX_LENGTH (code); i++, fmt++)
+    if (*fmt =3D=3D 'e')
+      {
+	if (XEXP (x, i) =3D=3D orig)
+	  {
+	    XEXP (x, i) =3D new;
+	    continue;
+	  }
+	change_arg_use_in_operand (XEXP (x, i), orig, new, size);
+      }
+    else if (*fmt =3D=3D 'E')
+      for (j =3D 0; j < XVECLEN (x, i); j++)
+	{
+
+	  if (XVECEXP (x, i, j) =3D=3D orig)
+	    {
+	      XVECEXP (x, i, j) =3D new;
+	      continue;
+	    }
+	  change_arg_use_in_operand (XVECEXP (x, i, j), orig, new, size);
+	}
+}  =20
+
+static int
+replace_return_reg (first, return_save)
+     rtx first, return_save;
+{
+  rtx return_reg =3D DECL_RTL (DECL_RESULT (current_function_decl));
+  rtx insn;
+   =20
+  /* comfirm that insn patterns are the expected order */
+  for (insn =3D first; insn; insn =3D NEXT_INSN (insn))
+    {
+      if (GET_RTX_CLASS (GET_CODE (insn)) =3D=3D 'i')
+	{
+
+	  rtx prev;
+
+	  if (PREV_INSN (insn)) prev =3D PREV_INSN (insn);
+
+	  if (GET_CODE (PATTERN (insn)) =3D=3D USE && XEXP (PATTERN (insn), 0) =
=3D=3D return_reg)
+	    if (!(prev && GET_CODE (PATTERN (prev)) =3D=3D SET && XEXP (PATTERN (=
prev), 0) =3D=3D return_reg))
+	      return FALSE;
+	}
+    }
+
+  /* replace return register */
+  for (insn =3D first; insn; insn =3D NEXT_INSN (insn))
+    {
+      if (GET_RTX_CLASS (GET_CODE (insn)) =3D=3D 'i')
+	{
+	  rtx prev;
+
+	  if (PREV_INSN (insn)) prev =3D PREV_INSN (insn);
+	  if (GET_CODE (PATTERN (insn)) =3D=3D USE
+	      && XEXP (PATTERN (insn), 0) =3D=3D return_reg
+	      && prev
+	      && GET_CODE (PATTERN (prev)) =3D=3D SET
+	      && XEXP (PATTERN (prev), 0) =3D=3D return_reg)
+	    {
+	      XEXP (PATTERN (prev), 0) =3D return_save;
+	=09
+	      /* change use insn to NOTE_INSN_DELETED */
+	      PUT_CODE (insn, NOTE);
+	      NOTE_SOURCE_FILE (insn) =3D 0;
+	      NOTE_LINE_NUMBER (insn) =3D NOTE_INSN_DELETED;
+	    }
+	}
+    }
+
+  return TRUE;
+}
+
+
+/*
+  Generate RTL to return from the current function, with value VAL.
+  It is copied and modified based on expand_value_return function of stmt.=
c
+*/
+
+static void
+expand_value_return (val)
+     rtx val;
+{
+  rtx return_reg =3D DECL_RTL (DECL_RESULT (current_function_decl));
+
+  /* Copy the value to the return location
+     unless it's already there.  */
+
+  if (return_reg !=3D val)
+    {
+#ifdef PROMOTE_FUNCTION_RETURN
+      tree type =3D TREE_TYPE (DECL_RESULT (current_function_decl));
+      int unsignedp =3D TREE_UNSIGNED (type);
+      enum machine_mode mode
+	=3D promote_mode (type, DECL_MODE (DECL_RESULT (current_function_decl)),
+			&unsignedp, 1);
+
+      if (GET_MODE (val) !=3D VOIDmode && GET_MODE (val) !=3D mode)
+	convert_move (return_reg, val, unsignedp);
+      else
+#endif
+	emit_move_insn (return_reg, val);
+    }
+  if (GET_CODE (return_reg) =3D=3D REG
+      && REGNO (return_reg) < FIRST_PSEUDO_REGISTER)
+    emit_insn (gen_rtx_USE (VOIDmode, return_reg));
+  /* Handle calls that return values in multiple non-contiguous locations.
+     The Irix 6 ABI has examples of this.  */
+  else if (GET_CODE (return_reg) =3D=3D PARALLEL)
+    {
+      int i;
+
+      for (i =3D 0; i < XVECLEN (return_reg, 0); i++)
+	{
+	  rtx x =3D XEXP (XVECEXP (return_reg, 0, i), 0);
+
+	  if (GET_CODE (x) =3D=3D REG
+	      && REGNO (x) < FIRST_PSEUDO_REGISTER)
+	    emit_insn (gen_rtx_USE (VOIDmode, x));
+	}
+    }
+}
+
+
+
+
+/*
+  The following codes are invoked after the instantiation of pseuso regist=
ers.
+
+  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.
+*/
+#ifndef FRAME_GROWS_DOWNWARD
+static void push_frame PARAMS ((int var_size));
+static void push_frame_in_decls PARAMS ((tree block, int push_size));
+static void push_frame_in_args PARAMS ((tree parms, int push_size));
+static void push_frame_of_insns PARAMS ((rtx insn, int push_size));
+static void push_frame_in_operand PARAMS ((rtx orig, int push_size));
+static void push_frame_of_reg_equiv_memory_loc PARAMS ((int push_size));
+static void push_frame_of_reg_equiv_constant PARAMS ((int push_size));
+static void reset_used_flags_for_push_frame PARAMS ((void));
+#endif
+
+rtx
+assign_stack_local_for_pseudo_reg (mode, size, align)
+     enum machine_mode mode;
+     HOST_WIDE_INT size;
+     int align;
+{
+#ifdef FRAME_GROWS_DOWNWARD
+  return assign_stack_local (mode, size, align);
+#else
+  tree blocks =3D DECL_INITIAL (current_function_decl);
+  rtx new;
+  HOST_WIDE_INT previous_frame_offset, offset;
+
+  previous_frame_offset =3D frame_offset;
+  new =3D assign_stack_local (mode, size, align);
+  if (! flag_propolice_protection
+      || size =3D=3D 0
+      || ! blocks
+      || DECL_INLINE (current_function_decl)
+      || ! search_string_from_argsandvars ()
+      || query_trampoline_list())
+    return new;
+
+  push_frame (frame_offset - previous_frame_offset);
+
+  /* If we have already instantiated virtual registers, return the actual
+     address relative to the frame pointer.  */
+/*if (virtuals_instantiated) {*/
+    offset =3D DEBUGGER_AUTO_OFFSET(XEXP (new, 0));
+
+    offset -=3D previous_frame_offset;
+    XEXP (XEXP (new, 0), 1) =3D gen_rtx_CONST_INT (VOIDmode, offset);
+/*}*/
+   =20
+  return new;
+#endif
+}
+
+
+#ifndef FRAME_GROWS_DOWNWARD
+/*
+  push frame infomation for instantiating pseudo register at the top of st=
ack.
+  This is only for the "frame grows upward", it means FRAME_GROWS_DOWNWARD=
 is=20
+  not defined.
+
+  It is called by purge_addressof function and global_alloc (or reload)
+  function.
+*/
+static void
+push_frame (var_size)
+     int var_size;
+{
+  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);
+
+  /* scan all argument variable and fix the offset address based on the fr=
ame pointer */
+  push_frame_in_args (DECL_ARGUMENTS (current_function_decl), var_size);
+
+  /* scan all operands of all insns and fix the offset address based on th=
e frame pointer */
+  push_frame_of_insns (get_insns (), var_size);
+
+  /* scan all reg_equiv_memory_loc and reg_equiv_constant*/
+  push_frame_of_reg_equiv_memory_loc (var_size);
+  push_frame_of_reg_equiv_constant (var_size);
+
+  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=20
+     global_alloc (or reload) function */
+  if (reg_equiv_memory_loc =3D=3D 0) return;
+
+  for (i=3DLAST_VIRTUAL_REGISTER+1; i < max_regno; i++)
+    if (reg_equiv_memory_loc[i])
+      {
+	rtx x =3D reg_equiv_memory_loc[i];
+
+	if (GET_CODE (x) =3D=3D MEM
+	    && GET_CODE (XEXP (x, 0)) =3D=3D PLUS
+	    && DEBUGGER_AUTO_BASEPTR (XEXP (x, 0)) =3D=3D frame_pointer_rtx)
+	  {
+	    /* reset */
+	    XEXP (x, 0)->used =3D 0;
+	  }
+      }
+
+ =20
+  if (reg_equiv_constant =3D=3D 0) return;
+
+  for (i=3DLAST_VIRTUAL_REGISTER+1; i < max_regno; i++)
+    if (reg_equiv_constant[i])
+      {
+	rtx x =3D reg_equiv_constant[i];
+
+	if (GET_CODE (x) =3D=3D PLUS
+	    && DEBUGGER_AUTO_BASEPTR (x) =3D=3D frame_pointer_rtx)
+	  {
+	    /* reset */
+	    x->used =3D 0;
+	  }
+      }
+}
+
+static void
+push_frame_in_decls (block, push_size)
+     tree block;
+     int push_size;
+{
+  tree types;
+  HOST_WIDE_INT offset;
+  rtx home;
+
+  while (block)
+    {
+      types =3D BLOCK_VARS(block);
+=09
+      while (types)
+	{
+	  /* skip the declaration that refers an external variable and
+	     also skip an global variable */
+	  if (! DECL_EXTERNAL (types) && ! TREE_STATIC (types))
+	    {
+	   =20
+	      home =3D DECL_RTL (types);
+	      if (home =3D=3D 0) goto next;
+
+	      /* process for static local variable */
+	      if (GET_CODE (home) =3D=3D MEM
+		  && GET_CODE (XEXP (home, 0)) =3D=3D SYMBOL_REF)
+		goto next;
+
+	      if (GET_CODE (home) =3D=3D MEM
+		  && GET_CODE (XEXP (home, 0)) =3D=3D REG)
+		{
+		  goto next;
+		}
+	=09
+	      if (GET_CODE (home) =3D=3D MEM
+		  && GET_CODE (XEXP (home, 0)) =3D=3D MEM)
+		{
+
+		  /* process for dynamically allocated aray */
+		  home =3D XEXP (home, 0);
+		}
+	=09
+	      if (GET_CODE (home) =3D=3D MEM
+		  && GET_CODE (XEXP (home, 0)) =3D=3D PLUS
+		  && GET_CODE (XEXP (XEXP (home, 0), 1)) =3D=3D CONST_INT)
+		{
+		  if (! XEXP (home, 0)->used)
+		    {
+		      offset =3D DEBUGGER_AUTO_OFFSET(XEXP (home, 0));
+
+		      offset +=3D push_size;
+		      XEXP (XEXP (home, 0), 1) =3D gen_rtx_CONST_INT (VOIDmode, offset);
+
+		      /* mark */
+		      XEXP (home, 0)->used =3D 1;
+		    }
+		}
+
+	    }
+	next:
+	  types =3D TREE_CHAIN(types);
+	}
+
+      push_frame_in_decls (BLOCK_SUBBLOCKS (block), push_size);
+      block =3D BLOCK_CHAIN (block);
+    }
+}
+
+
+static void
+push_frame_in_args (parms, push_size)
+     tree parms;
+     int push_size;
+{
+  rtx home;
+  HOST_WIDE_INT offset;
+   =20
+  for (; parms; parms =3D TREE_CHAIN (parms))
+    if (DECL_NAME (parms) && TREE_TYPE (parms) !=3D error_mark_node)
+      {
+	if (PARM_PASSED_IN_MEMORY (parms) && DECL_NAME (parms))
+	  {
+	    home =3D DECL_INCOMING_RTL (parms);
+
+	    if (XEXP (home, 0)->used) continue;
+
+	    offset =3D DEBUGGER_AUTO_OFFSET(XEXP (home, 0));
+
+	    /* the operand related to the sweep variable */
+	    if (DEBUGGER_AUTO_BASEPTR (XEXP (home, 0)) =3D=3D frame_pointer_rtx)
+	      {
+		offset +=3D push_size;
+		XEXP (XEXP (home, 0), 1) =3D gen_rtx_CONST_INT (VOIDmode, offset);
+
+		/* mark */
+		XEXP (home, 0)->used =3D 1;
+	      }
+	  }
+      }
+}
+
+
+static void
+push_frame_of_insns (insn, push_size)
+     rtx insn;
+     int push_size;
+{
+  for (; insn; insn =3D NEXT_INSN (insn))
+    if (GET_CODE (insn) =3D=3D INSN || GET_CODE (insn) =3D=3D JUMP_INSN
+	|| GET_CODE (insn) =3D=3D CALL_INSN)
+      {
+	push_frame_in_operand (PATTERN (insn), push_size);
+
+	/* push frame in NOTE */
+	push_frame_in_operand (REG_NOTES (insn), push_size);
+
+	/* push frame in CALL EXPR_LIST */
+	if (GET_CODE (insn) =3D=3D CALL_INSN)
+	  push_frame_in_operand (CALL_INSN_FUNCTION_USAGE (insn), push_size);
+      }
+}
+
+
+static void
+push_frame_in_operand (orig, push_size)
+     rtx orig;
+     int push_size;
+{
+  register rtx x =3D orig;
+  register enum rtx_code code;
+  int offset, i, j;
+  const char *fmt;
+
+  if (x =3D=3D 0)
+    return;
+
+  code =3D 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;
+	   =20
+    case SET:
+      break;
+	   =20
+    case PLUS:
+      /* Handle special case of frame register plus constant.  */
+      if (CONSTANT_P (XEXP (x, 1))
+	  && XEXP (x, 0) =3D=3D frame_pointer_rtx
+	  && ! x->used)
+	{
+	  offset =3D DEBUGGER_AUTO_OFFSET(x);
+
+	  offset +=3D push_size;
+
+	  /* XEXP (x, 0) is frame_pointer_rtx */
+	  XEXP (x, 1) =3D gen_rtx_CONST_INT (VOIDmode, offset);
+	  x->used =3D 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);
+      push_frame_of_insns (XEXP (x, 1), push_size);
+      push_frame_of_insns (XEXP (x, 2), push_size);
+      break;
+
+    default:
+      break;
+    }
+
+  /* Scan all subexpressions.  */
+  fmt =3D GET_RTX_FORMAT (code);
+  for (i =3D 0; i < GET_RTX_LENGTH (code); i++, fmt++)
+    if (*fmt =3D=3D 'e')
+      {
+	push_frame_in_operand (XEXP (x, i), push_size);
+      }
+    else if (*fmt =3D=3D 'E')
+      for (j =3D 0; j < XVECLEN (x, i); j++)
+	push_frame_in_operand (XVECEXP (x, i, j), push_size);
+}  =20
+
+static void
+push_frame_of_reg_equiv_memory_loc (push_size)
+     int push_size;
+{
+  int i;
+  extern rtx *reg_equiv_memory_loc;
+
+  /* This function is processed if the push_frame is called from=20
+     global_alloc (or reload) function */
+  if (reg_equiv_memory_loc =3D=3D 0) return;
+
+  for (i=3DLAST_VIRTUAL_REGISTER+1; i < max_regno; i++)
+    if (reg_equiv_memory_loc[i])
+      {
+	rtx x =3D reg_equiv_memory_loc[i];
+	int offset;
+
+	if (GET_CODE (x) =3D=3D MEM
+	    && GET_CODE (XEXP (x, 0)) =3D=3D PLUS
+	    && XEXP (XEXP (x, 0), 0) =3D=3D frame_pointer_rtx)
+	  {
+	    if (! XEXP (x, 0)->used)
+	      {
+		offset =3D DEBUGGER_AUTO_OFFSET(XEXP (x, 0));
+
+		offset +=3D push_size;
+		XEXP (XEXP (x, 0), 1) =3D gen_rtx_CONST_INT (VOIDmode, offset);
+
+		/* mark */
+		XEXP (x, 0)->used =3D 1;
+	      }
+	  }
+      }
+}
+
+static void
+push_frame_of_reg_equiv_constant (push_size)
+     int push_size;
+{
+  int i;
+  extern rtx *reg_equiv_constant;
+
+  /* This function is processed if the push_frame is called from=20
+     global_alloc (or reload) function */
+  if (reg_equiv_constant =3D=3D 0) return;
+
+  for (i=3DLAST_VIRTUAL_REGISTER+1; i < max_regno; i++)
+    if (reg_equiv_constant[i])
+      {
+	rtx x =3D reg_equiv_constant[i];
+	int offset;
+
+	if (GET_CODE (x) =3D=3D PLUS
+	    && XEXP (x, 0) =3D=3D frame_pointer_rtx)
+	  {
+	    if (! x->used)
+	      {
+		offset =3D DEBUGGER_AUTO_OFFSET(x);
+
+		offset +=3D push_size;
+		XEXP (x, 1) =3D gen_rtx_CONST_INT (VOIDmode, offset);
+
+		/* mark */
+		x->used =3D 1;
+	      }
+	  }
+      }
+}
+#endif
+
+
+void
+set_debuginfo_of_escaped_arg (rtx new, rtx old)
+{
+  int idx;
+
+  if (flag_propolice_protection)
+    for (idx =3D 0; idx < escaped_arg_list_size; idx++)
+      if (escaped_arg_list[idx].original =3D=3D old)
+	{
+	  /* change debugger info */
+	  escaped_arg_list[idx].escaped =3D new;
+	}
+}
+
+
+void
+update_debuginfo_using_escaped_arg_list (tree parms)
+{
+  rtx orig =3D DECL_RTL (parms);
+  int idx;
+
+  if (flag_propolice_protection && PARM_PASSED_IN_MEMORY (parms))
+    for (idx =3D 0; idx < escaped_arg_list_size; idx++)
+      if (escaped_arg_list[idx].original =3D=3D orig)
+	{
+	  rtx escaped =3D escaped_arg_list[idx].escaped;
+
+	  /* skip in the case where the escaped register was deleted */
+	  if (GET_CODE (escaped) =3D=3D REG
+	      && REGNO (escaped) >=3D FIRST_PSEUDO_REGISTER)
+	    break;
+
+	  DECL_INCOMING_RTL (parms) =3D escaped;
+	  break;
+	}
+}
Index: gnu/lib/libgcc/Makefile
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /mnt/ncvs/src/gnu/lib/libgcc/Makefile,v
retrieving revision 1.33
diff -u -r1.33 Makefile
--- gnu/lib/libgcc/Makefile	2000/06/04 06:56:21	1.33
+++ gnu/lib/libgcc/Makefile	2000/11/17 22:09:12
@@ -46,7 +46,7 @@
 	   _fixtfdi _fixunstfdi _floatditf \
 	   __gcc_bcmp _varargs __dummy _eprintf \
 	   _bb _shtab _clear_cache _trampoline __main _exit _ctors \
-	   _eh _pure
+	   _eh _pure _stack_smash_handler
=20
 # Library members defined in new1.cc.
 NEW1FUNCS=3D _op_new _op_newnt=20
Index: gnu/usr.bin/cc/cc_int/Makefile
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /mnt/ncvs/src/gnu/usr.bin/cc/cc_int/Makefile,v
retrieving revision 1.26
diff -u -r1.26 Makefile
--- gnu/usr.bin/cc/cc_int/Makefile	2000/05/24 20:02:21	1.26
+++ gnu/usr.bin/cc/cc_int/Makefile	2000/11/17 22:08:27
@@ -22,7 +22,7 @@
 	toplev.c tree.c unroll.c varasm.c version.c xcoffout.c \
 	alias.c bitmap.c dwarf2out.c dyn-string.c except.c \
 	gcse.c genrtl.c profile.c regmove.c varray.c \
-	${OUT_FILE}
+	${OUT_FILE} protector.c
 .if defined(USE_EGCS_HAIFA) && ${USE_EGCS_HAIFA} =3D=3D 1
 SRCS+=3D	haifa-sched.c
 .else

--=-u0LHuhZj3rcXxj9M/geN--


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-questions" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1005755318.13317.2.camel>