Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 19 May 2001 09:32:27 +0900
From:      Hiroaki Etoh <etoh@trl.ibm.co.jp>
To:        security@FreeBSD.ORG
Subject:   Base system with gcc stack-smashing protector
Message-ID:  <20010519093227T.etoh@trl.ibm.com>

next in thread | raw e-mail | index | archive | help
----Next_Part(Sat_May_19_09:32:24_2001_518)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

At last, I have completed GCC extension for protectiong applications
against stack smashing attack. It works on Intel x86 processor and IBM
powerpc.   

I also updated the patch for protecting FreeBSD 4.3 system from stack
smashing attack. 

- support FreeBSD 4.3
- syslog output at the detection of stack smashing attack
- kernel protection

The attached file is a patch against the system 4.3-RELEASE.

See http://www.trl.ibm.com/projects/security/ssp/buildfreebsd.html for
details. (to be appered in the next week)

Hiroaki Etoh,
Tokyo Research Laboratory, IBM Japan

----Next_Part(Sat_May_19_09:32:24_2001_518)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="protector43.patch"

? contrib/gcc/protector.h
? contrib/gcc/protector.c
? lib/libc/.depend
? sys/libkern/stack_smash_handler.c
Index: contrib/gcc/Makefile.in
===================================================================
RCS file: /home/ncvs/src/contrib/gcc/Makefile.in,v
retrieving revision 1.4.2.1
diff -c -r1.4.2.1 Makefile.in
*** contrib/gcc/Makefile.in	2001/04/10 19:22:57	1.4.2.1
--- contrib/gcc/Makefile.in	2001/05/18 23:54:35
***************
*** 685,691 ****
   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) convert.o \
!  mbchar.o dyn-string.o splay-tree.o graph.o sbitmap.o resource.o hash.o
  
  # GEN files are listed separately, so they can be built before doing parallel
  #  makes for cc1 or cc1plus.  Otherwise sequent parallel make attempts to load
--- 685,691 ----
   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) convert.o \
!  mbchar.o dyn-string.o splay-tree.o graph.o sbitmap.o resource.o hash.o protector.o
  
  # GEN files are listed separately, so they can be built before doing parallel
  #  makes for cc1 or cc1plus.  Otherwise sequent parallel make attempts to load
***************
*** 736,742 ****
      _fixtfdi _fixunstfdi _floatditf \
      __gcc_bcmp _varargs __dummy _eprintf \
      _bb _shtab _clear_cache _trampoline __main _exit \
!     _ctors _pure
  
  LIB2FUNCS_EH = _eh
  
--- 736,742 ----
      _fixtfdi _fixunstfdi _floatditf \
      __gcc_bcmp _varargs __dummy _eprintf \
      _bb _shtab _clear_cache _trampoline __main _exit \
!     _ctors _pure _stack_smash_handler
  
  LIB2FUNCS_EH = _eh
  
***************
*** 1138,1144 ****
  	    if [ $${name}.asm = $${file} ]; then \
  	      cp $${file} $${name}.s || exit 1; file=$${name}.s; \
  	    else true; fi; \
! 	    $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) -c $${file}; \
  	    if [ $$? -eq 0 ] ; then true; else exit 1; fi; \
  	    $(AR_FOR_TARGET) $(AR_FLAGS_FOR_TARGET) tmplibgcc2.a $${oname}$(objext); \
  	    rm -f $${name}.s $${oname}$(objext); \
--- 1138,1144 ----
  	    if [ $${name}.asm = $${file} ]; then \
  	      cp $${file} $${name}.s || exit 1; file=$${name}.s; \
  	    else true; fi; \
! 	    $(GCC_FOR_TARGET) -fno-stack-protector $(LIBGCC2_CFLAGS) $(INCLUDES) -c $${file}; \
  	    if [ $$? -eq 0 ] ; then true; else exit 1; fi; \
  	    $(AR_FOR_TARGET) $(AR_FLAGS_FOR_TARGET) tmplibgcc2.a $${oname}$(objext); \
  	    rm -f $${name}.s $${oname}$(objext); \
***************
*** 1465,1471 ****
     dwarf2out.h sdbout.h dbxout.h $(EXPR_H) $(BASIC_BLOCK_H) \
     $(lang_options_files)
  	$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(MAYBE_USE_COLLECT2) \
! 	  -DTARGET_NAME=\"$(target_alias)\" \
  	  -c `echo $(srcdir)/toplev.c | sed 's,^\./,,'`
  
  rtl.o : rtl.c $(CONFIG_H) system.h $(RTL_H) bitmap.h
--- 1465,1471 ----
     dwarf2out.h sdbout.h dbxout.h $(EXPR_H) $(BASIC_BLOCK_H) \
     $(lang_options_files)
  	$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(MAYBE_USE_COLLECT2) \
! 	  -DSTACK_PROTECTOR -DTARGET_NAME=\"$(target_alias)\" \
  	  -c `echo $(srcdir)/toplev.c | sed 's,^\./,,'`
  
  rtl.o : rtl.c $(CONFIG_H) system.h $(RTL_H) bitmap.h
Index: contrib/gcc/cse.c
===================================================================
RCS file: /home/ncvs/src/contrib/gcc/cse.c,v
retrieving revision 1.1.1.6.2.1
diff -c -r1.1.1.6.2.1 cse.c
*** contrib/gcc/cse.c	2001/04/10 19:23:04	1.1.1.6.2.1
--- contrib/gcc/cse.c	2001/05/18 23:54:39
***************
*** 6483,6488 ****
--- 6483,6492 ----
        if (SET_DEST (x) == pc_rtx
  	  && GET_CODE (SET_SRC (x)) == LABEL_REF)
  	;
+       else if (x->volatil) {
+ 	make_new_qty (REGNO (SET_DEST (x)));
+ 	qty_mode[REG_QTY (REGNO (SET_DEST (x)))] = GET_MODE (SET_DEST (x));
+       }
  
        /* 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
===================================================================
RCS file: /home/ncvs/src/contrib/gcc/dbxout.c,v
retrieving revision 1.4
diff -c -r1.4 dbxout.c
*** contrib/gcc/dbxout.c	1999/10/26 08:47:58	1.4
--- contrib/gcc/dbxout.c	2001/05/18 23:54:40
***************
*** 2253,2258 ****
--- 2253,2261 ----
    for (; parms; parms = TREE_CHAIN (parms))
      if (DECL_NAME (parms) && TREE_TYPE (parms) != error_mark_node)
        {
+ 	/* change the debug info of escaped argument for stack protection */
+ 	update_debuginfo_using_escaped_arg_list (parms);
+ 
  	dbxout_prepare_symbol (parms);
  
  	/* Perform any necessary register eliminations on the parameter's rtl,
Index: contrib/gcc/expr.c
===================================================================
RCS file: /home/ncvs/src/contrib/gcc/expr.c,v
retrieving revision 1.1.1.4.2.2
diff -c -r1.1.1.4.2.2 expr.c
*** contrib/gcc/expr.c	2001/04/10 19:23:06	1.1.1.4.2.2
--- contrib/gcc/expr.c	2001/05/18 23:54:45
***************
*** 41,46 ****
--- 41,47 ----
  #include "typeclass.h"
  #include "defaults.h"
  #include "toplev.h"
+ #include "protector.h"
  
  #define CEIL(x,y) (((x) + (y) - 1) / (y))
  
***************
*** 6316,6322 ****
  	    && modifier != EXPAND_MEMORY_USE_WO)
   	  return GEN_INT (TREE_STRING_POINTER (string)[i]);
  
! 	op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM);
  	op0 = memory_address (mode, op0);
  
  	if (current_function_check_memory_usage && !AGGREGATE_TYPE_P (TREE_TYPE (exp)))
--- 6317,6323 ----
  	    && modifier != EXPAND_MEMORY_USE_WO)
   	  return GEN_INT (TREE_STRING_POINTER (string)[i]);
  
! 	op0 = expand_expr (exp1, NULL_RTX, VOIDmode, flag_propolice_protection?ro_modifier:EXPAND_SUM);
  	op0 = memory_address (mode, op0);
  
  	if (current_function_check_memory_usage && !AGGREGATE_TYPE_P (TREE_TYPE (exp)))
***************
*** 8796,8802 ****
    mem = gen_rtx_MEM (BLKmode,
  		     memory_address (BLKmode,
  				     expand_expr (exp, NULL_RTX,
! 						  ptr_mode, EXPAND_SUM)));
  
    RTX_UNCHANGING_P (mem) = TREE_READONLY (exp);
  
--- 8797,8803 ----
    mem = gen_rtx_MEM (BLKmode,
  		     memory_address (BLKmode,
  				     expand_expr (exp, NULL_RTX,
! 						  ptr_mode, flag_propolice_protection?EXPAND_NORMAL:EXPAND_SUM)));
  
    RTX_UNCHANGING_P (mem) = TREE_READONLY (exp);
  
Index: contrib/gcc/function.c
===================================================================
RCS file: /home/ncvs/src/contrib/gcc/function.c,v
retrieving revision 1.6.2.2
diff -c -r1.6.2.2 function.c
*** contrib/gcc/function.c	2001/04/10 19:23:08	1.6.2.2
--- contrib/gcc/function.c	2001/05/18 23:54:47
***************
*** 60,65 ****
--- 60,66 ----
  #include "obstack.h"
  #include "toplev.h"
  #include "hash.h"
+ #include "protector.h"
  
  #ifndef TRAMPOLINE_ALIGNMENT
  #define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY
***************
*** 432,437 ****
--- 433,440 ----
    /* 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;
  };
  
  /* List of all temporaries allocated, both available and in use.  */
***************
*** 451,456 ****
--- 454,464 ----
     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;
+ 
  
  /* This structure is used to record MEMs or pseudos used to replace VAR, any
     SUBREGs of VAR, and any MEMs containing VAR as an address.  We need to
***************
*** 933,938 ****
--- 941,950 ----
    int align;
    int alias_set;
    struct temp_slot *p, *best_p = 0;
+   int char_array = type && (TREE_TYPE (type)==char_type_node
+ 			    || (TREE_TYPE (type)
+ 				&& TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
+ 				&& TYPE_PRECISION (TREE_TYPE (type)) == 8));
  
    /* If SIZE is -1 it means that somebody tried to allocate a temporary
       of a variable size.  */
***************
*** 965,971 ****
  	&& (!flag_strict_aliasing
  	    || (alias_set && p->alias_set == alias_set))
  	&& (best_p == 0 || best_p->size > p->size
! 	    || (best_p->size == p->size && best_p->align > p->align)))
        {
  	if (p->align == align && p->size == size)
  	  {
--- 977,984 ----
  	&& (!flag_strict_aliasing
  	    || (alias_set && p->alias_set == alias_set))
  	&& (best_p == 0 || best_p->size > p->size
! 	    || (best_p->size == p->size && best_p->align > p->align))
! 	&& (! char_array || p->boundary_mark != 0))
        {
  	if (p->align == align && p->size == size)
  	  {
***************
*** 1003,1008 ****
--- 1016,1022 ----
  	      p->align = best_p->align;
  	      p->address = 0;
  	      p->rtl_expr = 0;
+ 	      p->boundary_mark = best_p->boundary_mark;
  	      p->next = temp_slots;
  	      temp_slots = p;
  
***************
*** 1064,1069 ****
--- 1078,1084 ----
        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;
      }
***************
*** 1188,1201 ****
  	    int delete_q = 0;
  	    if (! q->in_use && GET_MODE (q->slot) == BLKmode)
  	      {
! 		if (p->base_offset + p->full_size == q->base_offset)
  		  {
  		    /* 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)
  		  {
  		    /* P comes after Q; combine P into Q.  */
  		    q->size += p->size;
--- 1203,1218 ----
  	    int delete_q = 0;
  	    if (! q->in_use && GET_MODE (q->slot) == BLKmode)
  	      {
! 		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 &&
! 			 p->boundary_mark == q->boundary_mark)
  		  {
  		    /* P comes after Q; combine P into Q.  */
  		    q->size += p->size;
***************
*** 1704,1710 ****
        if (regno < max_parm_reg)
  	new = parm_reg_stack_loc[regno];
        if (new == 0)
! 	new = assign_stack_local (decl_mode, GET_MODE_SIZE (decl_mode), 0);
      }
  
    PUT_MODE (reg, decl_mode);
--- 1721,1727 ----
        if (regno < max_parm_reg)
  	new = parm_reg_stack_loc[regno];
        if (new == 0)
! 	new = assign_stack_local_for_pseudo_reg (decl_mode, GET_MODE_SIZE (decl_mode), 0);
      }
  
    PUT_MODE (reg, decl_mode);
***************
*** 7035,7038 ****
--- 7052,7061 ----
  	}
      }
  #endif /* HAVE_prologue or HAVE_epilogue */
+ }
+ 
+ tree
+ query_trampoline_list()
+ {
+     return trampoline_list;
  }
Index: contrib/gcc/gcc.c
===================================================================
RCS file: /home/ncvs/src/contrib/gcc/gcc.c,v
retrieving revision 1.17.2.1
diff -c -r1.17.2.1 gcc.c
*** contrib/gcc/gcc.c	2001/04/10 19:23:09	1.17.2.1
--- contrib/gcc/gcc.c	2001/05/18 23:54:49
***************
*** 768,774 ****
  			%{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\
  			%{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
  			%{static:} %{L*} %D %o\
! 			%{!nostdlib:%{!nodefaultlibs:%G %L %G}}\
  			%{!A:%{!nostdlib:%{!nostartfiles:%E}}}\
  			%{T*}\
  			\n }}}}}}";
--- 768,774 ----
  			%{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\
  			%{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
  			%{static:} %{L*} %D %o\
! 			%{!nostdlib:%{!nodefaultlibs:%G %L %G %L}}\
  			%{!A:%{!nostdlib:%{!nostartfiles:%E}}}\
  			%{T*}\
  			\n }}}}}}";
Index: contrib/gcc/gcse.c
===================================================================
RCS file: /home/ncvs/src/contrib/gcc/gcse.c,v
retrieving revision 1.1.1.3
diff -c -r1.1.1.3 gcse.c
*** contrib/gcc/gcse.c	1999/11/01 08:26:03	1.1.1.3
--- contrib/gcc/gcse.c	2001/05/18 23:54:51
***************
*** 3718,3724 ****
        /* Find an assignment that sets reg_used and is available
  	 at the start of the block.  */
        set = find_avail_set (regno, insn);
!       if (! set)
  	continue;
    
        pat = set->expr;
--- 3718,3724 ----
        /* Find an assignment that sets reg_used and is available
  	 at the start of the block.  */
        set = find_avail_set (regno, insn);
!       if (! set || set->expr->volatil)
  	continue;
    
        pat = set->expr;
Index: contrib/gcc/integrate.c
===================================================================
RCS file: /home/ncvs/src/contrib/gcc/integrate.c,v
retrieving revision 1.1.1.3
diff -c -r1.1.1.3 integrate.c
*** contrib/gcc/integrate.c	1999/10/16 06:05:22	1.1.1.3
--- contrib/gcc/integrate.c	2001/05/18 23:54:53
***************
*** 38,43 ****
--- 38,44 ----
  #include "function.h"
  #include "toplev.h"
  #include "intl.h"
+ #include "protector.h"
  
  #include "obstack.h"
  #define	obstack_chunk_alloc	xmalloc
***************
*** 1503,1512 ****
  	    arg_vals[i] = convert_modes (GET_MODE (loc),
  					 TYPE_MODE (TREE_TYPE (arg)),
  					 expand_expr (arg, NULL_RTX, mode,
! 						      EXPAND_SUM),
  					 TREE_UNSIGNED (TREE_TYPE (formal)));
  	  else
! 	    arg_vals[i] = expand_expr (arg, NULL_RTX, mode, EXPAND_SUM);
  	}
        else
  	arg_vals[i] = 0;
--- 1504,1513 ----
  	    arg_vals[i] = convert_modes (GET_MODE (loc),
  					 TYPE_MODE (TREE_TYPE (arg)),
  					 expand_expr (arg, NULL_RTX, mode,
! 						      flag_propolice_protection?EXPAND_NORMAL:EXPAND_SUM),
  					 TREE_UNSIGNED (TREE_TYPE (formal)));
  	  else
! 	    arg_vals[i] = expand_expr (arg, NULL_RTX, mode, flag_propolice_protection?EXPAND_NORMAL:EXPAND_SUM);
  	}
        else
  	arg_vals[i] = 0;
Index: contrib/gcc/libgcc2.c
===================================================================
RCS file: /home/ncvs/src/contrib/gcc/libgcc2.c,v
retrieving revision 1.4
diff -c -r1.4 libgcc2.c
*** contrib/gcc/libgcc2.c	1999/10/27 09:45:47	1.4
--- contrib/gcc/libgcc2.c	2001/05/18 23:54:54
***************
*** 4014,4016 ****
--- 4014,4086 ----
    __terminate ();
  }
  #endif
+ 
+ #ifdef L_stack_smash_handler
+ #include <stdio.h>
+ #include <string.h>
+ #include <fcntl.h>
+ 
+ #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
+ 
+ char __guard[32] = {0,0,0,0,0,0,0,0};
+ static void __guard_setup (void) __attribute__ ((constructor)) ;
+ static void __guard_setup (void)
+ {
+   int fd;
+   if (((int*)__guard)[0]!=0) return;
+   fd = open ("/dev/urandom", 0);
+   if (fd != -1) {
+     ssize_t size = read (fd, &__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" */
+   __guard[0] = 0; __guard[1] = 0; __guard[2] = '\n'; __guard[3] = 255;
+ }
+ void __stack_smash_handler (char func[], int damaged)
+ {
+ #if defined (__GNU_LIBRARY__)
+   extern char * __progname;
+ #endif
+   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
+ 
+   strcpy(buf, "<2>"); len=3;	/* send LOG_CRIT */
+ #if defined (__GNU_LIBRARY__)
+   strncat(buf, __progname, bufsz-len); len = strlen(buf);
+ #endif
+   if (bufsz>len) strncat(buf, message, bufsz-len); len = strlen(buf);
+   if (bufsz>len) strncat(buf, func, bufsz-len); 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);
+     sendto(LogFile, buf, strlen(buf), 0, (struct sockaddr *)&SyslogAddr, sizeof(SyslogAddr));
+   }
+ #endif
+   abort();
+ }
+ #endif
Index: contrib/gcc/reload1.c
===================================================================
RCS file: /home/ncvs/src/contrib/gcc/reload1.c,v
retrieving revision 1.1.1.4.2.1
diff -c -r1.1.1.4.2.1 reload1.c
*** contrib/gcc/reload1.c	2001/04/10 19:23:13	1.1.1.4.2.1
--- contrib/gcc/reload1.c	2001/05/18 23:54:58
***************
*** 39,44 ****
--- 39,45 ----
  #include "output.h"
  #include "real.h"
  #include "toplev.h"
+ #include "protector.h"
  
  #if !defined PREFERRED_STACK_BOUNDARY && defined STACK_BOUNDARY
  #define PREFERRED_STACK_BOUNDARY STACK_BOUNDARY
***************
*** 2424,2430 ****
        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,
  				  inherent_size == total_size ? 0 : -1);
  	  if (BYTES_BIG_ENDIAN)
  	    /* Cancel the  big-endian correction done in assign_stack_local.
--- 2425,2431 ----
        if (from_reg == -1)
  	{
  	  /* No known place to spill from => no slot to reuse.  */
! 	  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.
Index: contrib/gcc/toplev.c
===================================================================
RCS file: /home/ncvs/src/contrib/gcc/toplev.c,v
retrieving revision 1.6.2.3
diff -c -r1.6.2.3 toplev.c
*** contrib/gcc/toplev.c	2001/04/10 19:23:16	1.6.2.3
--- contrib/gcc/toplev.c	2001/05/18 23:54:59
***************
*** 777,782 ****
--- 777,789 ----
  
  int flag_no_ident = 0;
  
+ #ifdef STACK_PROTECTOR
+ /* Nonzero means use ProPolice as a stack protection method */
+ int flag_propolice_protection = 1;
+ #else
+ int flag_propolice_protection = 0;
+ #endif
+ 
  /* Table of supported debugging formats.  */
  static struct
  {
***************
*** 986,992 ****
    {"leading-underscore", &flag_leading_underscore, 1,
     "External symbols have a leading underscore" },
    {"ident", &flag_no_ident, 0,
!    "Process #ident directives"}
  };
  
  #define NUM_ELEM(a)  (sizeof (a) / sizeof ((a)[0]))
--- 993,1003 ----
    {"leading-underscore", &flag_leading_underscore, 1,
     "External symbols have a leading underscore" },
    {"ident", &flag_no_ident, 0,
!    "Process #ident directives"},
!   {"stack-protector", &flag_propolice_protection, 1,
!    "Enables stack protection" },
!   {"no-stack-protector", &flag_propolice_protection, 0,
!    "Disables stack protection" },
  };
  
  #define NUM_ELEM(a)  (sizeof (a) / sizeof ((a)[0]))
***************
*** 3652,3657 ****
--- 3663,3670 ----
  
        insns = get_insns ();
  
+       if (flag_propolice_protection) prepare_stack_protection ();
+   
        /* Dump the rtl code if we are dumping rtl.  */
  
        if (rtl_dump)
Index: gnu/lib/libgcc/Makefile
===================================================================
RCS file: /home/ncvs/src/gnu/lib/libgcc/Makefile,v
retrieving revision 1.31.2.1
diff -c -r1.31.2.1 Makefile
*** gnu/lib/libgcc/Makefile	2001/01/06 23:16:54	1.31.2.1
--- gnu/lib/libgcc/Makefile	2001/05/18 23:55:23
***************
*** 49,55 ****
  	   _fixtfdi _fixunstfdi _floatditf \
  	   __gcc_bcmp _varargs __dummy _eprintf \
  	   _bb _shtab _clear_cache _trampoline __main _exit _ctors \
! 	   _eh _pure
  
  # Library members defined in new1.cc.
  NEW1FUNCS= _op_new _op_newnt 
--- 49,55 ----
  	   _fixtfdi _fixunstfdi _floatditf \
  	   __gcc_bcmp _varargs __dummy _eprintf \
  	   _bb _shtab _clear_cache _trampoline __main _exit _ctors \
! 	   _eh _pure _stack_smash_handler
  
  # Library members defined in new1.cc.
  NEW1FUNCS= _op_new _op_newnt 
***************
*** 65,70 ****
--- 65,71 ----
  .if ${OBJFORMAT} != aout
  CFLAGS+=	-D_PTHREADS -fPIC -DGTHREAD_USE_WEAK
  .endif
+ CFLAGS+=	-DHAVE_SYSLOG
  CXXFLAGS+=	-I${GCCDIR}/cp/inc
  CXXFLAGS+=	-nostdinc++
  
Index: gnu/usr.bin/cc/cc_int/Makefile
===================================================================
RCS file: /home/ncvs/src/gnu/usr.bin/cc/cc_int/Makefile,v
retrieving revision 1.25.2.1
diff -c -r1.25.2.1 Makefile
*** gnu/usr.bin/cc/cc_int/Makefile	2000/07/04 05:41:39	1.25.2.1
--- gnu/usr.bin/cc/cc_int/Makefile	2001/05/18 23:55:26
***************
*** 22,28 ****
  	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}
  .if defined(USE_EGCS_HAIFA) && ${USE_EGCS_HAIFA} == 1
  SRCS+=	haifa-sched.c
  .else
--- 22,28 ----
  	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} protector.c
  .if defined(USE_EGCS_HAIFA) && ${USE_EGCS_HAIFA} == 1
  SRCS+=	haifa-sched.c
  .else
Index: libexec/rtld-elf/Makefile
===================================================================
RCS file: /home/ncvs/src/libexec/rtld-elf/Makefile,v
retrieving revision 1.10.2.3
diff -c -r1.10.2.3 Makefile
*** libexec/rtld-elf/Makefile	2000/07/20 11:16:05	1.10.2.3
--- libexec/rtld-elf/Makefile	2001/05/18 23:55:37
***************
*** 30,35 ****
--- 30,49 ----
  DPADD=		${LIBC}
  LDADD=		-lc
  .else
+ 
+ OBJS+=		_stack_smash_handler.o
+ CLEANFILES+=	tconfig.h tm.h
+ _stack_smash_handler.o: ${.CURDIR}/../../contrib/gcc/libgcc2.c
+ 	echo '#include "gansidecl.h"'                           > tconfig.h
+ 	echo '#include "${MACHINE_ARCH}/xm-${MACHINE_ARCH}.h"'  >> tconfig.h
+ 	echo '#include "i386/i386.h"'	> tm.h
+ 	echo '#include "i386/att.h"'	>> tm.h
+ 	echo '#include "svr4.h"'	>> tm.h
+ 	echo '#include <freebsd.h>'	>> tm.h
+ 	echo '#include "i386/freebsd.h"'>> tm.h
+ 	echo '#include "i386/perform.h"'>> tm.h
+ 	$(CC) $(CFLAGS) -DIN_GCC -DL_stack_smash_handler -I${.CURDIR}/../../contrib/gcc -I${.CURDIR}/../../contrib/gcc/config -I. -fexceptions -c $> -o $@
+ 
  CFLAGS+=	-fpic -DPIC
  LDFLAGS+=	-shared -Wl,-Bsymbolic
  DPADD=		${LIBC_PIC}
Index: sys/boot/i386/loader/Makefile
===================================================================
RCS file: /home/ncvs/src/sys/boot/i386/loader/Makefile,v
retrieving revision 1.41.2.6
diff -c -r1.41.2.6 Makefile
*** sys/boot/i386/loader/Makefile	2000/12/19 01:18:34	1.41.2.6
--- sys/boot/i386/loader/Makefile	2001/05/18 23:55:47
***************
*** 125,131 ****
  
  ${BASE}.sym: ${OBJS} ${LIBI386} ${LIBSTAND} ${LIBFICL} vers.o
  	${CC} ${LDFLAGS} -o ${.TARGET} ${BTXCRT} ${OBJS} vers.o \
! 		${LIBFICL} ${LIBI386} ${LIBSTAND}
  
  # If it's not there, don't consider it a target
  .if exists(${.CURDIR}/../../../i386/include)
--- 125,131 ----
  
  ${BASE}.sym: ${OBJS} ${LIBI386} ${LIBSTAND} ${LIBFICL} vers.o
  	${CC} ${LDFLAGS} -o ${.TARGET} ${BTXCRT} ${OBJS} vers.o \
! 		${LIBFICL} ${LIBI386} ${LIBSTAND} -lgcc -lc
  
  # If it's not there, don't consider it a target
  .if exists(${.CURDIR}/../../../i386/include)
Index: sys/conf/files
===================================================================
RCS file: /home/ncvs/src/sys/conf/files,v
retrieving revision 1.340.2.51
diff -c -r1.340.2.51 files
*** sys/conf/files	2001/03/05 05:33:20	1.340.2.51
--- sys/conf/files	2001/05/18 23:55:52
***************
*** 1223,1225 ****
--- 1223,1226 ----
  libkern/strtoq.c	standard
  libkern/strtoul.c	standard
  libkern/strtouq.c	standard
+ libkern/stack_smash_handler.c	standard
*** /dev/null	Sat May 19 03:36:36 2001
--- contrib/gcc/protector.h	Tue May 15 18:39:54 2001
***************
*** 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, HOST_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	Sat May 19 03:36:36 2001
--- contrib/gcc/protector.c	Tue May 15 18:39:54 2001
***************
*** 0 ****
--- 1,1877 ----
+ /* 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_WIDE_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 be
+    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 = 0;
+ static int escaped_arg_list_size = 0;
+ static int guard_has_legitimate_address;
+ 
+ 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, int size));
+ static void sweep_string_in_args PARAMS ((tree parms, int sweep_offset, int 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, int size));
+ static void move_arg_location PARAMS ((rtx insn, rtx orig, rtx new, int var_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, int 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) == PLUS ? XEXP (X, 0) : X)
+ #define DEBUGGER_AUTO_OFFSET(X) \
+   (GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0)
+ #define PARM_PASSED_IN_MEMORY(PARM) \
+  (GET_CODE (DECL_INCOMING_RTL (PARM)) == MEM)
+ 
+ 
+ 
+ void
+ prepare_stack_protection (void)
+ {
+   tree blocks = DECL_INITIAL (current_function_decl);
+   current_function_has_variable_string = FALSE;
+ 
+   /*
+     skip the protection if the function has no block or it is an inline function
+   */
+   if (! blocks || DECL_INLINE (current_function_decl)) return;
+ 
+   current_function_defines_vulnerable_string = search_string_from_argsandvars ();
+ 
+   if (current_function_defines_vulnerable_string)
+     {
+       HOST_WIDE_INT previous_frame_offset, offset;
+       function_first_insn = get_insns ();
+ 
+       if (query_trampoline_list ()) return;
+     
+       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
+       */
+       previous_frame_offset = frame_offset;
+ 
+       /* the location must be before buffers */
+       guard_area = assign_stack_local (GUARD_m, UNITS_PER_GUARD, 0);
+       MEM_VOLATILE_P (guard_area) = 1;
+ 	
+       /* check if the address of the guard has legitimate address */
+       guard_has_legitimate_address = 1;
+       GO_IF_LEGITIMATE_ADDRESS(GUARD_m, guard_area, has_legitimate_address);
+       guard_has_legitimate_address = 0;
+     has_legitimate_address:
+ 	
+ #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 */
+       offset = DEBUGGER_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 = frame_offset;
+ 	  sweep_string_variable (guard_area, UNITS_PER_GUARD);
+ #endif
+ 	}
+ #endif
+ 
+       if (! current_function_has_variable_string
+ 	  && guard_has_legitimate_address)
+ 	{
+ 	  /* 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 = DECL_INITIAL (current_function_decl);
+   string_p = search_string_from_local_vars (blocks);
+   if (string_p) return TRUE;
+ 
+ 
+ #ifdef FRAME_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
+ 
+   return FALSE;
+ }
+ 
+ 
+ static int
+ search_string_from_local_vars (block)
+      tree block;
+ {
+   tree types;
+   int found = FALSE;
+ 
+   while (block)
+     {
+       types = BLOCK_VARS(block);
+ 
+       while (types)
+ 	{
+ 	  /* skip the declaration that refers an external variable */
+ 	  if (! DECL_EXTERNAL (types) && ! TREE_STATIC (types)
+ 	      && TREE_CODE (types) == VAR_DECL
+ 	      && DECL_RTL (types) && GET_CODE (DECL_RTL (types)) == MEM)
+ 	    {
+ 
+ 	      if (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
+ 			      && 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 = TRUE;
+ 		}
+ 	    }
+ 
+ 	  types = TREE_CHAIN(types);
+ 	}
+ 
+       if (search_string_from_local_vars (BLOCK_SUBBLOCKS (block)))
+ 	{
+ 	  found = TRUE;
+ 	}
+ 
+       block = BLOCK_CHAIN (block);
+     }
+     
+   return found;
+ }
+ 
+ static int
+ search_string_def (type)
+      tree type;
+ {
+   tree tem;
+     
+   /* 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:
+       if (TREE_TYPE (type) == char_type_node
+ 	  || (TREE_TYPE (type)
+ 	      && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
+ 	      && TYPE_PRECISION (TREE_TYPE (type)) == 8))
+ 	{
+ 	  /* Check if the string is a variable string */
+ 	  if (TYPE_DOMAIN (type) == 0 ||
+ 	      TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == 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 >= SUSPICIOUS_BUF_SIZE)
+ 	    return 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;
+ }
+ 
+ 
+ static int
+ search_pointer_def (type)
+      tree type;
+ {
+   tree tem;
+     
+   /* 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 = 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:
+       /* 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 = 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;
+ 	
+     default:
+       break;
+     }
+ 
+   return FALSE;
+ }
+ 
+ 
+ static int
+ search_func_pointer (type, mark)
+      tree type;
+      int mark;
+ {
+   tree tem;
+     
+   /* 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) != mark)
+ 	  {
+ 	    /* mark the type as having been visited already */
+ 	    TREE_ASM_WRITTEN (type) = mark;
+ 
+ 	    /* 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) == FIELD_DECL
+ 		    && search_func_pointer (TREE_TYPE(tem), mark)) return TRUE;
+ 	      }
+ 	  }
+ 	break;
+ 
+     case ARRAY_TYPE:
+       return search_func_pointer (TREE_TYPE(type), mark);
+ 	
+     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)) == FUNCTION_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)
+     {
+       types = BLOCK_VARS(block);
+ 	
+       while (types)
+ 	{
+ 	  /* skip the declaration that refers an external variable and
+ 	     also skip an global variable */
+ 	  if (! DECL_EXTERNAL (types))
+ 	    {
+ 	      home = DECL_RTL (types);
+ 	      if (home == 0) goto next;
+ 
+ 	      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;
+ {
+   for (; insn; insn = NEXT_INSN (insn))
+     if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)
+       {
+ 	rtx _val;
+ 
+ 	prologue_insert_point = NEXT_INSN (insn);	/* mark the next insn of FUNCTION_BEG insn */
+ 		
+ 	start_sequence ();
+ 
+ 	_guard = gen_rtx_MEM (GUARD_m, gen_rtx_SYMBOL_REF (Pmode, "__guard"));
+ 	emit_move_insn ( guard_area, _guard);
+ 
+ 	_val = 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 = DECL_RTL (DECL_RESULT (current_function_decl)), return_save;
+ 		
+   handler = gen_rtx_MEM (FUNCTION_MODE, gen_rtx (SYMBOL_REF, Pmode, "__stack_smash_handler"));
+ 
+   start_sequence ();
+ 
+   if (return_reg
+       && ! (current_function_returns_struct
+ 	    || current_function_returns_pcc_struct))
+     {
+       return_save = 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 (guard_area != _guard) */
+ 
+   if_false_label = 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 
+     failure to assign the guard_area variable to eax register, which destroys 
+     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 = build_string (strlen(current_function_name)+1, current_function_name);
+   TREE_TYPE (funcstr) = build_array_type (char_type_node, 0);/* = char_array_type_node;*/
+   funcname = output_constant_def (funcstr);
+ 
+   addr = gen_push_operand ();
+   emit_move_insn (gen_rtx_MEM (GUARD_m, addr), guard_area);		/* push the value of guard area */
+ 
+   arg1mode = GET_MODE (XEXP (funcname, 0));
+   addr = gen_push_operand ();
+   emit_move_insn (gen_rtx_MEM (arg1mode, addr), XEXP (funcname, 0));	/* push current_function_name */
+ 
+   /* calculate the stack size of two arguments */
+   args_size = GET_MODE_SIZE (arg1mode) + GET_MODE_SIZE (GUARD_m);
+ #ifdef PUSH_ROUNDING
+   args_size = PUSH_ROUNDING (GET_MODE_SIZE (arg1mode)) + PUSH_ROUNDING (GET_MODE_SIZE (GUARD_m));
+ #endif
+ #ifdef STACK_BOUNDARY
+   args_size = (((args_size + (STACK_BYTES - 1)) / STACK_BYTES) * STACK_BYTES);
+ #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 */
+ 		
+   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_pcc_struct)
+ 	expand_value_return (return_save);
+ 	
+ 
+       /* If returning a structure, arrange to return the address of the value
+ 	 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 = XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
+ 	  tree type = TREE_TYPE (DECL_RESULT (current_function_decl));
+ #ifdef FUNCTION_OUTGOING_VALUE
+ 	  rtx outgoing
+ 	    = FUNCTION_OUTGOING_VALUE (build_pointer_type (type),
+ 				       current_function_decl);
+ #else
+ 	  rtx outgoing
+ 	    = FUNCTION_VALUE (build_pointer_type (type),
+ 			      current_function_decl);
+ #endif
+ 	  
+ 	  /* 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) = 1;
+ 
+ 	  emit_move_insn (outgoing, value_address);
+ 	  use_variable (outgoing);
+ 	}
+     }
+ 
+   _val = gen_sequence ();
+   end_sequence ();
+ 
+   emit_insn_after (_val, insn);
+ }
+ 
+ 
+ static void
+ arrange_var_order (block)
+      tree block;
+ {
+   tree types;
+   int offset;
+     
+   while (block)
+     {
+       types = BLOCK_VARS (block);
+ 
+       while (types)
+ 	{
+ 	  /* skip the declaration that refers an external variable */
+ 	  if (! DECL_EXTERNAL (types) && ! TREE_STATIC (types)
+ 	      && TREE_CODE (types) == VAR_DECL
+ 	      && GET_CODE (DECL_RTL (types)) == MEM)
+ 	    {
+ 	      if (search_string_def (TREE_TYPE (types)))
+ 		{
+ 		  /* found a string variable */
+ 		  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 = DEBUGGER_AUTO_OFFSET (XEXP (DECL_RTL (types), 0));
+ 		  if (offset >= sweep_frame_offset - var_size)
+ 		    sweep_frame_offset -= var_size;
+ 
+ 		  else
+ 		    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 (void)
+ {
+   tree parms = DECL_ARGUMENTS (current_function_decl);
+   rtx temp_rtx;
+   int idx;
+ 
+   escaped_arg_list_size = 0;
+ 
+   /* count the number of argument passed in memory */
+   for (; parms; parms = TREE_CHAIN (parms))
+     if (DECL_NAME (parms) && TREE_TYPE (parms) != error_mark_node)
+       {
+ 	if (PARM_PASSED_IN_MEMORY (parms))
+ 	  escaped_arg_list_size ++;
+       }
+ 
+   if (escaped_arg_list) free (escaped_arg_list);
+   escaped_arg_list = xmalloc (sizeof (arg_status) * escaped_arg_list_size);
+   
+   parms = DECL_ARGUMENTS (current_function_decl);
+   for (idx = 0; parms; parms = TREE_CHAIN (parms), idx++)
+     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;
+ 	      }
+ 	    */
+ 
+ 	    escaped_arg_list[idx].original = 0;
+ 	    escaped_arg_list[idx].escaped = 0;
+ 		
+ 	    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);
+ 		
+ 		start_sequence ();
+ 
+ 		if (GET_CODE (DECL_RTL (parms)) == REG)
+ 		  {
+ 		    rtx movinsn;
+ 		    rtx safe = gen_reg_rtx (GET_MODE (DECL_RTL (parms)));
+ 
+ 		    /* generate codes for copying the content */
+ 		    movinsn = emit_move_insn (safe, DECL_RTL (parms));
+ 		    PATTERN (movinsn)->volatil = 1;	/* avoid register elimination in gcse.c (COPY-PROP)*/
+ 
+ 		    change_arg_use_of_insns (prologue_insert_point, DECL_RTL (parms), safe, 0);
+ 
+ 		    /* save debugger info */
+ 		    escaped_arg_list[idx].original = DECL_RTL (parms);
+ 		    escaped_arg_list[idx].escaped = 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));
+ 		    PATTERN (movinsn)->volatil = 1;	/* avoid register elimination in gcse.c (COPY-PROP)*/
+ 
+ 		    /* change the addressof information to the newly allocated pseudo register */
+ 		    emit_move_insn (DECL_RTL (parms), safe);
+ 
+ 		    /* save debugger info */
+ 		    escaped_arg_list[idx].original = DECL_RTL (parms);
+ 		    escaped_arg_list[idx].escaped = safe;
+ 		  }
+ 			
+ 		else
+ 		  {
+ 		    /* declare temporary local variable DECL_NAME (parms) for it */
+ 		    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));
+ 		    MEM_ALIAS_SET (temp_rtx) = 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) = temp_rtx;
+ 
+ 		    /* change debugger info */
+ 		    DECL_INCOMING_RTL (parms) = 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) == 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)
+      int var_size;
+      rtx sweep_var;
+ {
+   int sweep_offset = 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_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;
+      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 = 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)) {
+ 	    
+ 	    home = DECL_RTL (types);
+ 	    if (home == 0) goto next;
+ 
+ 	    /* 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)
+ 	      {
+ 		goto next;
+ 	      }
+ 		
+ 	    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)
+ 	      {
+ 		if (! XEXP (home, 0)->used)
+ 		  {
+ 		    offset = DEBUGGER_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;
+      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 = DEBUGGER_AUTO_OFFSET(XEXP (home, 0));
+ 
+ 	    /* the operand related to the sweep variable */
+ 	    if (DEBUGGER_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, so shift the location */
+ 		    XEXP (XEXP (home, 0), 1) = gen_rtx_CONST_INT (VOIDmode, offset - sweep_size);
+ 
+ 		    /* mark */
+ 		    XEXP (home, 0)->used = 1;
+ 		  }
+ 	      }
+ 	  }
+       }
+ }
+ 
+ 
+ static void
+ sweep_string_use_of_insns (insn, sweep_offset, sweep_size)
+      rtx insn;
+      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)
+       {
+ 	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 = orig;
+   register enum rtx_code code;
+   int offset, i, j;
+   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 SET:
+       break;
+ 	    
+     case PLUS:
+       /* Handle special case of frame register plus constant.  */
+       if (CONSTANT_P (XEXP (x, 1))
+ 	  && XEXP (x, 0) == virtual_stack_vars_rtx
+ 	  && ! x->used)
+ 	{
+ 	  offset = DEBUGGER_AUTO_OFFSET(x);
+ 
+ 	  /* 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 (x, 0) = virtual_stack_vars_rtx;
+ 	      XEXP (x, 1) = gen_rtx_CONST_INT (VOIDmode, offset);
+ 	      x->used = 1;
+ 
+ 	      return;
+ 	    }
+ 	  else if (sweep_offset <= offset
+ 		   && offset < sweep_frame_offset)
+ 	    {	/* the rest of variables under sweep_frame_offset, so shift the location */
+ 	      XEXP (x, 1) = gen_rtx_CONST_INT (VOIDmode, offset - sweep_size);
+ 	      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:
+       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 = GET_RTX_FORMAT (code);
+   for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
+     if (*fmt == 'e')
+       {
+ 	sweep_string_in_operand (XEXP (x, i), sweep_offset, sweep_size);
+       }
+     else if (*fmt == 'E')
+       for (j = 0; j < XVECLEN (x, i); j++)
+ 	sweep_string_in_operand (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;
+      int size;
+ {
+   for (; insn; insn = NEXT_INSN (insn))
+     if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
+ 	|| GET_CODE (insn) == 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 == 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 PLUS:
+       /* Handle special case of frame register plus constant.  */
+       if (GET_CODE (orig) == MEM /* skip if orig is register variable in the optimization */
+ 	  && XEXP (x, 0) == virtual_incoming_args_rtx && CONSTANT_P (XEXP (x, 1))
+ 	  && ! x->used)
+ 	{
+ 	  offset = DEBUGGER_AUTO_OFFSET(x);
+ 
+ 	  /* the operand related to the sweep variable */
+ 	  if (DEBUGGER_AUTO_OFFSET(XEXP (orig, 0)) <= offset &&
+ 	      offset < DEBUGGER_AUTO_OFFSET(XEXP (orig, 0)) + size) {
+ 
+ 	    offset += frame_offset - DEBUGGER_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 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 = GET_RTX_FORMAT (code);
+   for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
+     if (*fmt == 'e')
+       {
+ 	if (XEXP (x, i) == 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)
+ 	    {
+ 	      XVECEXP (x, i, j) = new;
+ 	      continue;
+ 	    }
+ 	  change_arg_use_in_operand (XVECEXP (x, i, j), orig, new, size);
+ 	}
+ }   
+ 
+ static int
+ replace_return_reg (first, return_save)
+      rtx first, return_save;
+ {
+   rtx return_reg = DECL_RTL (DECL_RESULT (current_function_decl));
+   rtx insn;
+     
+   /* comfirm that insn patterns are the expected order */
+   for (insn = first; insn; insn = NEXT_INSN (insn))
+     {
+       if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ 	{
+ 
+ 	  rtx prev;
+ 
+ 	  if (PREV_INSN (insn)) prev = PREV_INSN (insn);
+ 
+ 	  if (GET_CODE (PATTERN (insn)) == USE && XEXP (PATTERN (insn), 0) == return_reg)
+ 	    if (!(prev && GET_CODE (PATTERN (prev)) == SET && XEXP (PATTERN (prev), 0) == return_reg))
+ 	      return FALSE;
+ 	}
+     }
+ 
+   /* replace return register */
+   for (insn = first; insn; insn = NEXT_INSN (insn))
+     {
+       if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ 	{
+ 	  rtx prev;
+ 
+ 	  if (PREV_INSN (insn)) prev = PREV_INSN (insn);
+ 	  if (GET_CODE (PATTERN (insn)) == USE
+ 	      && XEXP (PATTERN (insn), 0) == return_reg
+ 	      && prev
+ 	      && GET_CODE (PATTERN (prev)) == SET
+ 	      && XEXP (PATTERN (prev), 0) == return_reg)
+ 	    {
+ 	      XEXP (PATTERN (prev), 0) = return_save;
+ 		
+ 	      /* change use insn to NOTE_INSN_DELETED */
+ 	      PUT_CODE (insn, NOTE);
+ 	      NOTE_SOURCE_FILE (insn) = 0;
+ 	      NOTE_LINE_NUMBER (insn) = 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 = DECL_RTL (DECL_RESULT (current_function_decl));
+ 
+   /* Copy the value to the return location
+      unless it's already there.  */
+ 
+   if (return_reg != val)
+     {
+ #ifdef PROMOTE_FUNCTION_RETURN
+       tree type = TREE_TYPE (DECL_RESULT (current_function_decl));
+       int unsignedp = TREE_UNSIGNED (type);
+       enum machine_mode mode
+ 	= promote_mode (type, DECL_MODE (DECL_RESULT (current_function_decl)),
+ 			&unsignedp, 1);
+ 
+       if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
+ 	convert_move (return_reg, val, unsignedp);
+       else
+ #endif
+ 	emit_move_insn (return_reg, val);
+     }
+   if (GET_CODE (return_reg) == 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) == PARALLEL)
+     {
+       int i;
+ 
+       for (i = 0; i < XVECLEN (return_reg, 0); i++)
+ 	{
+ 	  rtx x = XEXP (XVECEXP (return_reg, 0, i), 0);
+ 
+ 	  if (GET_CODE (x) == REG
+ 	      && REGNO (x) < FIRST_PSEUDO_REGISTER)
+ 	    emit_insn (gen_rtx_USE (VOIDmode, x));
+ 	}
+     }
+ }
+ 
+ 
+ 
+ 
+ /*
+   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.
+ */
+ #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 = DECL_INITIAL (current_function_decl);
+   rtx new;
+   HOST_WIDE_INT previous_frame_offset, offset;
+ 
+   previous_frame_offset = frame_offset;
+   new = assign_stack_local (mode, size, align);
+   if (! flag_propolice_protection
+       || size == 0
+       || ! blocks || TREE_CODE (blocks) != BLOCK
+       || 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 = DEBUGGER_AUTO_OFFSET(XEXP (new, 0));
+ 
+     offset -= previous_frame_offset;
+     XEXP (XEXP (new, 0), 1) = gen_rtx_CONST_INT (VOIDmode, offset);
+ /*}*/
+     
+   return new;
+ #endif
+ }
+ 
+ 
+ #ifndef FRAME_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)
+      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 frame 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 the 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 
+      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
+ 	    && DEBUGGER_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
+ 	    && DEBUGGER_AUTO_BASEPTR (x) == frame_pointer_rtx)
+ 	  {
+ 	    /* reset */
+ 	    x->used = 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 = 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))
+ 	    {
+ 	    
+ 	      home = DECL_RTL (types);
+ 	      if (home == 0) goto next;
+ 
+ 	      /* 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)
+ 		{
+ 		  goto next;
+ 		}
+ 		
+ 	      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)
+ 		{
+ 		  if (! XEXP (home, 0)->used)
+ 		    {
+ 		      offset = DEBUGGER_AUTO_OFFSET(XEXP (home, 0));
+ 
+ 		      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);
+       block = BLOCK_CHAIN (block);
+     }
+ }
+ 
+ 
+ static void
+ push_frame_in_args (parms, push_size)
+      tree parms;
+      int push_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 = DEBUGGER_AUTO_OFFSET(XEXP (home, 0));
+ 
+ 	    /* the operand related to the sweep variable */
+ 	    if (DEBUGGER_AUTO_BASEPTR (XEXP (home, 0)) == frame_pointer_rtx)
+ 	      {
+ 		offset += push_size;
+ 		XEXP (XEXP (home, 0), 1) = gen_rtx_CONST_INT (VOIDmode, offset);
+ 
+ 		/* mark */
+ 		XEXP (home, 0)->used = 1;
+ 	      }
+ 	  }
+       }
+ }
+ 
+ 
+ static void
+ push_frame_of_insns (insn, push_size)
+      rtx insn;
+      int push_size;
+ {
+   for (; insn; insn = NEXT_INSN (insn))
+     if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
+ 	|| GET_CODE (insn) == 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) == 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 = orig;
+   register enum rtx_code code;
+   int offset, i, j;
+   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 SET:
+       break;
+ 	    
+     case PLUS:
+       /* Handle special case of frame register plus constant.  */
+       if (CONSTANT_P (XEXP (x, 1))
+ 	  && XEXP (x, 0) == frame_pointer_rtx
+ 	  && ! x->used)
+ 	{
+ 	  offset = DEBUGGER_AUTO_OFFSET(x);
+ 
+ 	  offset += push_size;
+ 
+ 	  /* XEXP (x, 0) is frame_pointer_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 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 = GET_RTX_FORMAT (code);
+   for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
+     if (*fmt == 'e')
+       {
+ 	push_frame_in_operand (XEXP (x, i), push_size);
+       }
+     else if (*fmt == 'E')
+       for (j = 0; j < XVECLEN (x, i); j++)
+ 	push_frame_in_operand (XVECEXP (x, i, j), push_size);
+ }   
+ 
+ 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 
+      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)
+ 	  {
+ 	    if (! XEXP (x, 0)->used)
+ 	      {
+ 		offset = DEBUGGER_AUTO_OFFSET(XEXP (x, 0));
+ 
+ 		offset += push_size;
+ 		XEXP (XEXP (x, 0), 1) = gen_rtx_CONST_INT (VOIDmode, offset);
+ 
+ 		/* mark */
+ 		XEXP (x, 0)->used = 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 
+      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)
+ 	  {
+ 	    if (! x->used)
+ 	      {
+ 		offset = DEBUGGER_AUTO_OFFSET(x);
+ 
+ 		offset += push_size;
+ 		XEXP (x, 1) = gen_rtx_CONST_INT (VOIDmode, offset);
+ 
+ 		/* mark */
+ 		x->used = 1;
+ 	      }
+ 	  }
+       }
+ }
+ #endif
+ 
+ 
+ void
+ set_debuginfo_of_escaped_arg (rtx new, rtx old)
+ {
+   int idx;
+ 
+   if (flag_propolice_protection)
+     for (idx = 0; idx < escaped_arg_list_size; idx++)
+       if (escaped_arg_list[idx].original == old)
+ 	{
+ 	  /* change debugger info */
+ 	  escaped_arg_list[idx].escaped = new;
+ 	}
+ }
+ 
+ 
+ void
+ update_debuginfo_using_escaped_arg_list (tree parms)
+ {
+   rtx orig = DECL_RTL (parms);
+   int idx;
+ 
+   if (flag_propolice_protection && PARM_PASSED_IN_MEMORY (parms))
+     for (idx = 0; idx < escaped_arg_list_size; idx++)
+       if (escaped_arg_list[idx].original == orig)
+ 	{
+ 	  rtx escaped = escaped_arg_list[idx].escaped;
+ 
+ 	  /* skip in the case where the escaped register was deleted */
+ 	  if (GET_CODE (escaped) == REG
+ 	      && REGNO (escaped) >= FIRST_PSEUDO_REGISTER)
+ 	    break;
+ 
+ 	  DECL_INCOMING_RTL (parms) = escaped;
+ 	  break;
+ 	}
+ }
*** /dev/null	Sat May 19 03:36:36 2001
--- sys/libkern/stack_smash_handler.c	Fri May 18 15:22:09 2001
***************
*** 0 ****
--- 1,7 ----
+ int __guard = '\0\0\n\777';
+ 
+ void __stack_smash_handler (int damaged, char func[])
+ {
+   static char *message = "propolice detects %x at function %s.\n" ;
+   panic (message, damaged, func);
+ }

----Next_Part(Sat_May_19_09:32:24_2001_518)----

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




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