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>