diff -Naur gcc-3.3/gcc/calls.c gcc-3.3-new/gcc/calls.c --- gcc-3.3/gcc/calls.c 2003-05-14 17:17:48.000000000 +0200 +++ gcc-3.3-new/gcc/calls.c 2003-05-29 16:31:58.000000000 +0200 @@ -2324,7 +2324,7 @@ /* For variable-sized objects, we must be called with a target specified. If we were to allocate space on the stack here, we would have no way of knowing when to free it. */ - rtx d = assign_temp (TREE_TYPE (exp), 1, 1, 1); + rtx d = assign_temp (TREE_TYPE (exp), 5, 1, 1); mark_temp_addr_taken (d); structure_value_addr = XEXP (d, 0); diff -Naur gcc-3.3/gcc/combine.c gcc-3.3-new/gcc/combine.c --- gcc-3.3/gcc/combine.c 2003-05-14 17:17:49.000000000 +0200 +++ gcc-3.3-new/gcc/combine.c 2003-05-29 16:31:58.000000000 +0200 @@ -3859,7 +3859,17 @@ rtx inner_op0 = XEXP (XEXP (x, 0), 1); rtx inner_op1 = XEXP (x, 1); rtx inner; - + +#ifndef FRAME_GROWS_DOWNWARD + if (flag_propolice_protection + && code == PLUS + && other == frame_pointer_rtx + && GET_CODE (inner_op0) == CONST_INT + && GET_CODE (inner_op1) == CONST_INT + && INTVAL (inner_op0) > 0 + && INTVAL (inner_op0) + INTVAL (inner_op1) <= 0) + return x; +#endif /* Make sure we pass the constant operand if any as the second one if this is a commutative operation. */ if (CONSTANT_P (inner_op0) && GET_RTX_CLASS (code) == 'c') @@ -4272,6 +4282,11 @@ they are now checked elsewhere. */ if (GET_CODE (XEXP (x, 0)) == PLUS && CONSTANT_ADDRESS_P (XEXP (XEXP (x, 0), 1))) +#ifndef FRAME_GROWS_DOWNWARD + if (! (flag_propolice_protection + && XEXP (XEXP (x, 0), 0) == frame_pointer_rtx + && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)) +#endif return gen_binary (PLUS, mode, gen_binary (PLUS, mode, XEXP (XEXP (x, 0), 0), XEXP (x, 1)), diff -Naur gcc-3.3/gcc/config/t-linux gcc-3.3-new/gcc/config/t-linux --- gcc-3.3/gcc/config/t-linux 2003-05-14 17:17:57.000000000 +0200 +++ gcc-3.3-new/gcc/config/t-linux 2003-05-29 16:31:58.000000000 +0200 @@ -4,7 +4,7 @@ # Compile crtbeginS.o and crtendS.o with pic. CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC # Compile libgcc2.a with pic. -TARGET_LIBGCC2_CFLAGS = -fPIC +TARGET_LIBGCC2_CFLAGS = -fPIC -DHAVE_SYSLOG # Override t-slibgcc-elf-ver to export some libgcc symbols with # the symbol versions that glibc used. diff -Naur gcc-3.3/gcc/cse.c gcc-3.3-new/gcc/cse.c --- gcc-3.3/gcc/cse.c 2003-05-14 17:18:06.000000000 +0200 +++ gcc-3.3-new/gcc/cse.c 2003-05-29 16:31:58.000000000 +0200 @@ -4288,7 +4288,14 @@ if (new_const == 0) break; - +#ifndef FRAME_GROWS_DOWNWARD + if (flag_propolice_protection + && GET_CODE (y) == PLUS + && XEXP (y, 0) == frame_pointer_rtx + && INTVAL (inner_const) > 0 + && INTVAL (new_const) <= 0) + break; +#endif /* If we are associating shift operations, don't let this produce a shift of the size of the object or larger. This could occur when we follow a sign-extend by a right @@ -4823,6 +4830,13 @@ if (SET_DEST (x) == pc_rtx && GET_CODE (SET_SRC (x)) == LABEL_REF) ; + /* cut the reg propagation of stack-protected argument */ + else if (x->volatil) { + rtx x1 = SET_DEST (x); + if (GET_CODE (x1) == SUBREG && GET_CODE (SUBREG_REG (x1)) == REG) + x1 = SUBREG_REG (x1); + make_new_qty (REGNO (x1), GET_MODE (x1)); + } /* Don't count call-insns, (set (reg 0) (call ...)), as a set. The hard function value register is used only once, to copy to diff -Naur gcc-3.3/gcc/explow.c gcc-3.3-new/gcc/explow.c --- gcc-3.3/gcc/explow.c 2003-05-14 17:18:09.000000000 +0200 +++ gcc-3.3-new/gcc/explow.c 2003-05-29 16:31:58.000000000 +0200 @@ -86,7 +86,8 @@ rtx tem; int all_constant = 0; - if (c == 0) + if (c == 0 + && !(flag_propolice_protection && x == virtual_stack_vars_rtx)) return x; restart: @@ -187,7 +188,8 @@ break; } - if (c != 0) + if (c != 0 + || (flag_propolice_protection && x == virtual_stack_vars_rtx)) x = gen_rtx_PLUS (mode, x, GEN_INT (c)); if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF) @@ -531,6 +533,21 @@ in certain cases. This is not necessary since the code below can handle all possible cases, but machine-dependent transformations can make better code. */ + if (flag_propolice_protection) + { +#define FRAMEADDR_P(X) (GET_CODE (X) == PLUS \ + && XEXP (X, 0) == virtual_stack_vars_rtx \ + && GET_CODE (XEXP (X, 1)) == CONST_INT) + rtx y; + if (FRAMEADDR_P (x)) goto win; + for (y=x; y!=0 && GET_CODE (y)==PLUS; y = XEXP (y, 0)) + { + if (FRAMEADDR_P (XEXP (y, 0))) + XEXP (y, 0) = force_reg (GET_MODE (XEXP (y, 0)), XEXP (y, 0)); + if (FRAMEADDR_P (XEXP (y, 1))) + XEXP (y, 1) = force_reg (GET_MODE (XEXP (y, 1)), XEXP (y, 1)); + } + } LEGITIMIZE_ADDRESS (x, oldx, mode, win); /* PLUS and MULT can appear in special ways diff -Naur gcc-3.3/gcc/expr.c gcc-3.3-new/gcc/expr.c --- gcc-3.3/gcc/expr.c 2003-05-14 17:18:09.000000000 +0200 +++ gcc-3.3-new/gcc/expr.c 2003-05-29 16:31:58.000000000 +0200 @@ -45,6 +45,7 @@ #include "langhooks.h" #include "intl.h" #include "tm_p.h" +#include "protector.h" /* Decide whether a function's arguments should be processed from first to last or from last to first. @@ -1517,7 +1518,7 @@ if (USE_LOAD_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_from) { - data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len)); + data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len-GET_MODE_SIZE (mode))); data.autinc_from = 1; data.explicit_inc_from = -1; } @@ -1531,7 +1532,7 @@ data.from_addr = copy_addr_to_reg (from_addr); if (USE_STORE_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_to) { - data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len)); + data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len-GET_MODE_SIZE (mode))); data.autinc_to = 1; data.explicit_inc_to = -1; } @@ -1648,11 +1649,13 @@ from1 = adjust_address (data->from, mode, data->offset); if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0) - emit_insn (gen_add2_insn (data->to_addr, - GEN_INT (-(HOST_WIDE_INT)size))); + if (data->explicit_inc_to < -1) + emit_insn (gen_add2_insn (data->to_addr, + GEN_INT (-(HOST_WIDE_INT)size))); if (HAVE_PRE_DECREMENT && data->explicit_inc_from < 0) - emit_insn (gen_add2_insn (data->from_addr, - GEN_INT (-(HOST_WIDE_INT)size))); + if (data->explicit_inc_from < -1) + emit_insn (gen_add2_insn (data->from_addr, + GEN_INT (-(HOST_WIDE_INT)size))); if (data->to) emit_insn ((*genfun) (to1, from1)); @@ -2816,7 +2819,7 @@ if (USE_STORE_PRE_DECREMENT (mode) && data->reverse && ! data->autinc_to) { - data->to_addr = copy_addr_to_reg (plus_constant (to_addr, data->len)); + data->to_addr = copy_addr_to_reg (plus_constant (to_addr, data->len-GET_MODE_SIZE (mode))); data->autinc_to = 1; data->explicit_inc_to = -1; } @@ -2887,8 +2890,9 @@ to1 = adjust_address (data->to, mode, data->offset); if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0) - emit_insn (gen_add2_insn (data->to_addr, - GEN_INT (-(HOST_WIDE_INT) size))); + if (data->explicit_inc_to < -1) + emit_insn (gen_add2_insn (data->to_addr, + GEN_INT (-(HOST_WIDE_INT) size))); cst = (*data->constfun) (data->constfundata, data->offset, mode); emit_insn ((*genfun) (to1, cst)); @@ -8049,7 +8053,8 @@ /* If adding to a sum including a constant, associate it to put the constant outside. */ if (GET_CODE (op1) == PLUS - && CONSTANT_P (XEXP (op1, 1))) + && CONSTANT_P (XEXP (op1, 1)) + && !(flag_propolice_protection && (contains_fp (op0) || contains_fp (op1)))) { rtx constant_term = const0_rtx; diff -Naur gcc-3.3/gcc/flags.h gcc-3.3-new/gcc/flags.h --- gcc-3.3/gcc/flags.h 2003-05-14 17:18:10.000000000 +0200 +++ gcc-3.3-new/gcc/flags.h 2003-05-29 16:31:58.000000000 +0200 @@ -685,4 +685,12 @@ #define HONOR_SIGN_DEPENDENT_ROUNDING(MODE) \ (MODE_HAS_SIGN_DEPENDENT_ROUNDING (MODE) && !flag_unsafe_math_optimizations) +/* Nonzero means use propolice as a stack protection method */ + +extern int flag_propolice_protection; + +/* Warn when not issuing stack smashing protection for some reason */ + +extern int warn_stack_protector; + #endif /* ! GCC_FLAGS_H */ diff -Naur gcc-3.3/gcc/function.c gcc-3.3-new/gcc/function.c --- gcc-3.3/gcc/function.c 2003-05-14 17:18:10.000000000 +0200 +++ gcc-3.3-new/gcc/function.c 2003-05-29 16:34:36.000000000 +0200 @@ -59,6 +59,7 @@ #include "tm_p.h" #include "integrate.h" #include "langhooks.h" +#include "protector.h" #ifndef TRAMPOLINE_ALIGNMENT #define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY @@ -142,6 +143,10 @@ /* Array of INSN_UIDs to hold the INSN_UIDs for each sibcall epilogue in this function. */ static GTY(()) varray_type sibcall_epilogue; + +/* Current boundary mark for character arrays. */ +int temp_boundary_mark = 0; + /* In order to evaluate some expressions, such as function calls returning structures in memory, we need to temporarily allocate stack locations. @@ -195,6 +200,8 @@ /* The size of the slot, including extra space for alignment. This info is for combine_temp_slots. */ HOST_WIDE_INT full_size; + /* Boundary mark of a character array and the others. This info is for propolice */ + int boundary_mark; }; /* This structure is used to record MEMs or pseudos used to replace VAR, any @@ -629,6 +636,7 @@ whose lifetime is controlled by CLEANUP_POINT_EXPRs. KEEP is 3 if we are to allocate something at an inner level to be treated as a variable in the block (e.g., a SAVE_EXPR). + KEEP is 5 if we allocate a place to return structure. TYPE is the type that will be used for the stack slot. */ @@ -642,6 +650,8 @@ unsigned int align; struct temp_slot *p, *best_p = 0; rtx slot; + int char_array = (flag_propolice_protection + && keep == 1 && search_string_def (type)); /* If SIZE is -1 it means that somebody tried to allocate a temporary of a variable size. */ @@ -667,7 +677,8 @@ && ! p->in_use && objects_must_conflict_p (p->type, type) && (best_p == 0 || best_p->size > p->size - || (best_p->size == p->size && best_p->align > p->align))) + || (best_p->size == p->size && best_p->align > p->align)) + && (! char_array || p->boundary_mark != 0)) { if (p->align == align && p->size == size) { @@ -702,6 +713,7 @@ p->address = 0; p->rtl_expr = 0; p->type = best_p->type; + p->boundary_mark = best_p->boundary_mark; p->next = temp_slots; temp_slots = p; @@ -762,6 +774,7 @@ p->full_size = frame_offset - frame_offset_old; #endif p->address = 0; + p->boundary_mark = char_array?++temp_boundary_mark:0; p->next = temp_slots; temp_slots = p; } @@ -932,14 +945,16 @@ int delete_q = 0; if (! q->in_use && GET_MODE (q->slot) == BLKmode) { - if (p->base_offset + p->full_size == q->base_offset) + if (p->base_offset + p->full_size == q->base_offset && + p->boundary_mark == q->boundary_mark) { /* Q comes after P; combine Q into P. */ p->size += q->size; p->full_size += q->full_size; delete_q = 1; } - else if (q->base_offset + q->full_size == p->base_offset) + else if (q->base_offset + q->full_size == p->base_offset && + p->boundary_mark == q->boundary_mark) { /* P comes after Q; combine P into Q. */ q->size += p->size; @@ -1497,7 +1512,9 @@ new = func->x_parm_reg_stack_loc[regno]; if (new == 0) - new = assign_stack_local_1 (decl_mode, GET_MODE_SIZE (decl_mode), 0, func); + new = function ? + assign_stack_local_1 (decl_mode, GET_MODE_SIZE (decl_mode), 0, func): + assign_stack_local_for_pseudo_reg (decl_mode, GET_MODE_SIZE (decl_mode), 0); PUT_CODE (reg, MEM); PUT_MODE (reg, decl_mode); @@ -3961,7 +3978,8 @@ constant with that register. */ temp = gen_reg_rtx (Pmode); XEXP (x, 0) = new; - if (validate_change (object, &XEXP (x, 1), temp, 0)) + if (validate_change (object, &XEXP (x, 1), temp, 0) + && ! flag_propolice_protection) emit_insn_before (gen_move_insn (temp, new_offset), object); else { diff -Naur gcc-3.3/gcc/gcse.c gcc-3.3-new/gcc/gcse.c --- gcc-3.3/gcc/gcse.c 2003-05-14 17:18:10.000000000 +0200 +++ gcc-3.3-new/gcc/gcse.c 2003-05-29 16:31:58.000000000 +0200 @@ -4208,7 +4208,7 @@ /* Find an assignment that sets reg_used and is available at the start of the block. */ set = find_avail_set (regno, insn); - if (! set) + if (! set || set->expr->volatil) continue; pat = set->expr; diff -Naur gcc-3.3/gcc/integrate.c gcc-3.3-new/gcc/integrate.c --- gcc-3.3/gcc/integrate.c 2003-05-14 17:18:12.000000000 +0200 +++ gcc-3.3-new/gcc/integrate.c 2003-05-29 16:31:58.000000000 +0200 @@ -399,6 +399,10 @@ /* These args would always appear unused, if not for this. */ TREE_USED (copy) = 1; + /* The inlined variable is marked as INLINE not to sweep by propolice */ + if (flag_propolice_protection && TREE_CODE (copy) == VAR_DECL) + DECL_INLINE (copy) = 1; + /* Set the context for the new declaration. */ if (!DECL_CONTEXT (decl)) /* Globals stay global. */ @@ -1963,6 +1967,10 @@ seq = get_insns (); end_sequence (); +#ifdef FRAME_GROWS_DOWNWARD + if (flag_propolice_protection && GET_CODE (seq) == SET) + RTX_INTEGRATED_P (SET_SRC (seq)) = 1; +#endif emit_insn_after (seq, map->insns_at_start); return temp; } diff -Naur gcc-3.3/gcc/libgcc2.c gcc-3.3-new/gcc/libgcc2.c --- gcc-3.3/gcc/libgcc2.c 2003-05-14 17:18:14.000000000 +0200 +++ gcc-3.3-new/gcc/libgcc2.c 2003-05-29 16:31:58.000000000 +0200 @@ -1993,3 +1993,102 @@ #endif /* NEED_ATEXIT */ #endif /* L_exit */ + +#ifdef L_stack_smash_handler +#include +#include +#include +#include + +#ifdef _POSIX_SOURCE +#include +#endif + +#if defined(HAVE_SYSLOG) +#include +#include +#include + +#include +#ifndef _PATH_LOG +#define _PATH_LOG "/dev/log" +#endif +#endif + +long __guard[8] = {0,0,0,0,0,0,0,0}; +static void __guard_setup (void) __attribute__ ((constructor)) ; +static void __guard_setup (void) +{ + int fd; + if (__guard[0]!=0) return; + fd = open ("/dev/urandom", 0); + if (fd != -1) { + ssize_t size = read (fd, (char*)&__guard, sizeof(__guard)); + close (fd) ; + if (size == sizeof(__guard)) return; + } + /* If a random generator can't be used, the protector switches the guard + to the "terminator canary" */ + ((char*)__guard)[0] = 0; ((char*)__guard)[1] = 0; + ((char*)__guard)[2] = '\n'; ((char*)__guard)[3] = 255; +} +void __stack_smash_handler (char func[], int damaged ATTRIBUTE_UNUSED) +{ +#if defined (__GNU_LIBRARY__) + extern char * __progname; +#endif + const char message[] = ": stack smashing attack in function "; + int bufsz = 256, len; + char buf[bufsz]; +#if defined(HAVE_SYSLOG) + int LogFile; + struct sockaddr_un SyslogAddr; /* AF_UNIX address of local logger */ +#endif +#ifdef _POSIX_SOURCE + { + sigset_t mask; + sigfillset(&mask); + sigdelset(&mask, SIGABRT); /* Block all signal handlers */ + sigprocmask(SIG_BLOCK, &mask, NULL); /* except SIGABRT */ + } +#endif + + strcpy(buf, "<2>"); len=3; /* send LOG_CRIT */ +#if defined (__GNU_LIBRARY__) + strncat(buf, __progname, bufsz-len-1); len = strlen(buf); +#endif + if (bufsz>len) {strncat(buf, message, bufsz-len-1); len = strlen(buf);} + if (bufsz>len) strncat(buf, func, bufsz-len-1); + + /* print error message */ + write (STDERR_FILENO, buf+3, len-3); +#if defined(HAVE_SYSLOG) + if ((LogFile = socket(AF_UNIX, SOCK_DGRAM, 0)) != -1) { + + /* + * Send "found" message to the "/dev/log" path + */ + SyslogAddr.sun_family = AF_UNIX; + (void)strncpy(SyslogAddr.sun_path, _PATH_LOG, + sizeof(SyslogAddr.sun_path) - 1); + SyslogAddr.sun_path[sizeof(SyslogAddr.sun_path) - 1] = '\0'; + sendto(LogFile, buf, strlen(buf), 0, (struct sockaddr *)&SyslogAddr, + sizeof(SyslogAddr)); + } +#endif + +#ifdef _POSIX_SOURCE + { /* Make sure the default handler is associated with SIGABRT */ + struct sigaction sa; + + memset(&sa, 0, sizeof(struct sigaction)); + sigfillset(&sa.sa_mask); /* Block all signals */ + sa.sa_flags = 0; + sa.sa_handler = SIG_DFL; + sigaction(SIGABRT, &sa, NULL); + (void)kill(getpid(), SIGABRT); + } +#endif + _exit(127); +} +#endif diff -Naur gcc-3.3/gcc/libgcc-std.ver gcc-3.3-new/gcc/libgcc-std.ver --- gcc-3.3/gcc/libgcc-std.ver 2003-05-14 17:18:14.000000000 +0200 +++ gcc-3.3-new/gcc/libgcc-std.ver 2003-05-29 16:31:58.000000000 +0200 @@ -174,6 +174,10 @@ _Unwind_SjLj_RaiseException _Unwind_SjLj_ForcedUnwind _Unwind_SjLj_Resume + + # stack smash handler symbols + __guard + __stack_smash_handler } %inherit GCC_3.3 GCC_3.0 diff -Naur gcc-3.3/gcc/loop.c gcc-3.3-new/gcc/loop.c --- gcc-3.3/gcc/loop.c 2003-05-14 17:18:14.000000000 +0200 +++ gcc-3.3-new/gcc/loop.c 2003-05-29 16:31:58.000000000 +0200 @@ -6516,6 +6516,14 @@ if (GET_CODE (*mult_val) == USE) *mult_val = XEXP (*mult_val, 0); +#ifndef FRAME_GROWS_DOWNWARD + if (flag_propolice_protection + && GET_CODE (*add_val) == PLUS + && (XEXP (*add_val, 0) == frame_pointer_rtx + || XEXP (*add_val, 1) == frame_pointer_rtx)) + return 0; +#endif + if (is_addr) *pbenefit += address_cost (orig_x, addr_mode) - reg_address_cost; else diff -Naur gcc-3.3/gcc/Makefile.in gcc-3.3-new/gcc/Makefile.in --- gcc-3.3/gcc/Makefile.in 2003-05-14 17:18:14.000000000 +0200 +++ gcc-3.3-new/gcc/Makefile.in 2003-05-29 16:33:21.000000000 +0200 @@ -761,7 +761,7 @@ sibcall.o simplify-rtx.o ssa.o ssa-ccp.o ssa-dce.o stmt.o \ stor-layout.o stringpool.o timevar.o toplev.o tracer.o tree.o tree-dump.o \ tree-inline.o unroll.o varasm.o varray.o version.o vmsdbgout.o xcoffout.o \ - et-forest.o $(GGC) $(out_object_file) $(EXTRA_OBJS) + et-forest.o protector.o $(GGC) $(out_object_file) $(EXTRA_OBJS) BACKEND = main.o libbackend.a @@ -795,7 +795,7 @@ LIB2FUNCS_2 = _floatdixf _fixunsxfsi _fixtfdi _fixunstfdi _floatditf \ _clear_cache _trampoline __main _exit _absvsi2 _absvdi2 _addvsi3 \ - _addvdi3 _subvsi3 _subvdi3 _mulvsi3 _mulvdi3 _negvsi2 _negvdi2 _ctors + _addvdi3 _subvsi3 _subvdi3 _mulvsi3 _mulvdi3 _negvsi2 _negvdi2 _ctors _stack_smash_handler # Defined in libgcc2.c, included only in the static library. LIB2FUNCS_ST = _eprintf _bb __gcc_bcmp diff -Naur gcc-3.3/gcc/optabs.c gcc-3.3-new/gcc/optabs.c --- gcc-3.3/gcc/optabs.c 2003-05-14 17:18:15.000000000 +0200 +++ gcc-3.3-new/gcc/optabs.c 2003-05-29 16:31:58.000000000 +0200 @@ -696,6 +696,26 @@ if (target) target = protect_from_queue (target, 1); + if (flag_propolice_protection + && binoptab->code == PLUS + && op0 == virtual_stack_vars_rtx + && GET_CODE(op1) == CONST_INT) + { + int icode = (int) binoptab->handlers[(int) mode].insn_code; + if (target) + temp = target; + else + temp = gen_reg_rtx (mode); + + if (! (*insn_data[icode].operand[0].predicate) (temp, mode) + || GET_CODE (temp) != REG) + temp = gen_reg_rtx (mode); + + emit_insn (gen_rtx_SET (VOIDmode, temp, + gen_rtx_PLUS (GET_MODE (op0), op0, op1))); + return temp; + } + if (flag_force_mem) { op0 = force_not_mem (op0); diff -Naur gcc-3.3/gcc/reload1.c gcc-3.3-new/gcc/reload1.c --- gcc-3.3/gcc/reload1.c 2003-05-14 17:18:19.000000000 +0200 +++ gcc-3.3-new/gcc/reload1.c 2003-05-29 16:31:58.000000000 +0200 @@ -42,6 +42,7 @@ #include "toplev.h" #include "except.h" #include "tree.h" +#include "protector.h" /* This file contains the reload pass of the compiler, which is run after register allocation has been done. It checks that @@ -1992,7 +1993,7 @@ if (from_reg == -1) { /* No known place to spill from => no slot to reuse. */ - x = assign_stack_local (GET_MODE (regno_reg_rtx[i]), total_size, + x = assign_stack_local_for_pseudo_reg (GET_MODE (regno_reg_rtx[i]), total_size, inherent_size == total_size ? 0 : -1); if (BYTES_BIG_ENDIAN) /* Cancel the big-endian correction done in assign_stack_local. diff -Naur gcc-3.3/gcc/simplify-rtx.c gcc-3.3-new/gcc/simplify-rtx.c --- gcc-3.3/gcc/simplify-rtx.c 2003-05-14 17:18:20.000000000 +0200 +++ gcc-3.3-new/gcc/simplify-rtx.c 2003-05-29 16:31:58.000000000 +0200 @@ -1670,7 +1670,8 @@ int n_ops = 2, input_ops = 2, input_consts = 0, n_consts; int first, negate, changed; int i, j; - + HOST_WIDE_INT fp_offset = 0; + memset ((char *) ops, 0, sizeof ops); /* Set up the two operands and then expand them until nothing has been @@ -1695,6 +1696,10 @@ switch (this_code) { case PLUS: + if (flag_propolice_protection + && XEXP (this_op, 0) == virtual_stack_vars_rtx + && GET_CODE (XEXP (this_op, 1)) == CONST_INT) + fp_offset = INTVAL (XEXP (this_op, 1)); case MINUS: if (n_ops == 7) return NULL_RTX; @@ -1849,10 +1854,10 @@ && GET_CODE (ops[n_ops - 1].op) == CONST_INT && CONSTANT_P (ops[n_ops - 2].op)) { - rtx value = ops[n_ops - 1].op; + int value = INTVAL (ops[n_ops - 1].op); if (ops[n_ops - 1].neg ^ ops[n_ops - 2].neg) - value = neg_const_int (mode, value); - ops[n_ops - 2].op = plus_constant (ops[n_ops - 2].op, INTVAL (value)); + value = -value; + ops[n_ops - 2].op = plus_constant (ops[n_ops - 2].op, value); n_ops--; } @@ -1871,6 +1876,54 @@ || (n_ops + n_consts == input_ops && n_consts <= input_consts))) return NULL_RTX; + if (flag_propolice_protection) + { + /* keep the addressing style of local variables + as (plus (virtual_stack_vars_rtx) (CONST_int x)) + (1) inline function is expanded, (+ (+VFP c1) -c2)=>(+ VFP c1-c2) + (2) the case ary[r-1], (+ (+VFP c1) (+r -1))=>(+ R (+r -1)) + */ + for (i = 0; i < n_ops; i++) +#ifdef FRAME_GROWS_DOWNWARD + if (ops[i].op == virtual_stack_vars_rtx) +#else + if (ops[i].op == virtual_stack_vars_rtx + || ops[i].op == frame_pointer_rtx) +#endif + { + if (GET_CODE (ops[n_ops - 1].op) == CONST_INT) + { + HOST_WIDE_INT value = INTVAL (ops[n_ops - 1].op); + if (n_ops < 3 || value >= fp_offset) + { + ops[i].op = plus_constant (ops[i].op, value); + n_ops--; + } + else + { + if (!force + && (n_ops+1 + n_consts > input_ops + || (n_ops+1 + n_consts == input_ops && n_consts <= input_consts))) + return NULL_RTX; + ops[n_ops - 1].op = GEN_INT (value-fp_offset); + ops[i].op = plus_constant (ops[i].op, fp_offset); + } + } + /* buf[BUFSIZE]: buf is the first local variable (+ (+ fp -S) S) + or (+ (fp 0) r) ==> ((+ (+fp 1) r) -1) */ + else if (fp_offset != 0) + return NULL_RTX; +#ifndef FRAME_GROWS_DOWNWARD + /* + * For the case of buf[i], i: REG, buf: (plus fp 0), + */ + else if (fp_offset == 0) + return NULL_RTX; +#endif + break; + } + } + /* Put a non-negated operand first. If there aren't any, make all operands positive and negate the whole thing later. */ diff -Naur gcc-3.3/gcc/toplev.c gcc-3.3-new/gcc/toplev.c --- gcc-3.3/gcc/toplev.c 2003-05-14 17:18:22.000000000 +0200 +++ gcc-3.3-new/gcc/toplev.c 2003-05-29 16:36:43.000000000 +0200 @@ -904,6 +904,13 @@ minimum function alignment. Zero means no alignment is forced. */ int force_align_functions_log; +#if defined(STACK_PROTECTOR) && defined(STACK_GROWS_DOWNWARD) +/* Nonzero means use propolice as a stack protection method */ +int flag_propolice_protection = 1; +#else +int flag_propolice_protection = 0; +#endif + /* Table of supported debugging formats. */ static const struct { @@ -1188,6 +1195,10 @@ N_("Trap for signed overflow in addition / subtraction / multiplication") }, { "new-ra", &flag_new_regalloc, 1, N_("Use graph coloring register allocation.") }, + {"stack-protector", &flag_propolice_protection, 1, + N_("Enables stack protection") }, + {"no-stack-protector", &flag_propolice_protection, 0, + N_("Disables stack protection") }, }; /* Table of language-specific options. */ @@ -1547,7 +1558,9 @@ {"missing-noreturn", &warn_missing_noreturn, 1, N_("Warn about functions which might be candidates for attribute noreturn") }, {"strict-aliasing", &warn_strict_aliasing, 1, - N_ ("Warn about code which might break the strict aliasing rules") } + N_ ("Warn about code which might break the strict aliasing rules") }, + {"stack-protector", &warn_stack_protector, 1, + N_("Warn when disabling stack protector for some reason")} }; void @@ -2449,6 +2462,8 @@ insns = get_insns (); + if (flag_propolice_protection) prepare_stack_protection (inlinable); + /* Dump the rtl code if we are dumping rtl. */ if (open_dump_file (DFI_rtl, decl))