From 22703df0df76accb65607f28070a9771b5bb42de Mon Sep 17 00:00:00 2001 From: Miod Vallat Date: Mon, 2 Dec 2002 09:00:27 +0000 Subject: Import propolice (http://www.trl.ibm.com/projects/security/ssp), a stack attack protection scheme, into gcc. This protection is enabled by default. It can be turned off by using the -fno-stack-protector flag. Code by Hiroaki Etoh (etoh at jp dot ibm dot com); work on openbsd-specific integration by fgsch@, deraadt@ and myself; tests by fgsch@, naddy@ and myself; beer drinking by myself. Please note that system upgrades with this new code will require a new libc and ld.so to be build and installed before the propolice-enabled compiler can be installed. --- gnu/egcs/gcc/Makefile.in | 6 +- gnu/egcs/gcc/combine.c | 147 ++- gnu/egcs/gcc/cse.c | 50 +- gnu/egcs/gcc/explow.c | 15 + gnu/egcs/gcc/expr.c | 438 ++++-- gnu/egcs/gcc/flags.h | 14 + gnu/egcs/gcc/function.c | 28 +- gnu/egcs/gcc/gcse.c | 34 +- gnu/egcs/gcc/optabs.c | 534 ++++++-- gnu/egcs/gcc/protector.c | 2269 ++++++++++++++++++++++++++++++++ gnu/egcs/gcc/protector.h | 38 + gnu/egcs/gcc/reload1.c | 236 +++- gnu/egcs/gcc/toplev.c | 19 +- gnu/usr.bin/ld/rtld/rtld.c | 14 +- lib/libc/shlib_version | 2 +- lib/libc/sys/Makefile.inc | 5 +- lib/libc/sys/stack_protector.c | 87 ++ lib/libc_r/shlib_version | 2 +- libexec/ld.so/util.c | 14 +- sys/arch/alpha/conf/Makefile.alpha | 4 +- sys/arch/alpha/stand/Makefile.inc | 3 +- sys/arch/amiga/conf/Makefile.amiga | 4 +- sys/arch/amiga/stand/binpatch/Makefile | 3 +- sys/arch/amiga/stand/boot/Makefile | 3 +- sys/arch/amiga/stand/loadbsd/Makefile | 3 +- sys/arch/amiga/stand/loadkmap/Makefile | 3 +- sys/arch/hp300/conf/Makefile.hp300 | 4 +- sys/arch/hp300/stand/Makefile.inc | 4 +- sys/arch/hppa/conf/Makefile.hppa | 5 +- sys/arch/hppa/stand/Makefile.inc | 3 +- sys/arch/i386/conf/Makefile.i386 | 3 +- sys/arch/i386/stand/Makefile.inc | 3 +- sys/arch/mac68k/conf/Makefile.mac68k | 4 +- sys/arch/macppc/conf/Makefile.macppc | 4 +- sys/arch/macppc/stand/Makefile.inc | 3 +- sys/arch/mvme68k/conf/Makefile.mvme68k | 4 +- sys/arch/mvme68k/stand/Makefile.inc | 3 +- sys/arch/mvme88k/conf/Makefile.mvme88k | 4 +- sys/arch/mvme88k/stand/Makefile.inc | 3 +- sys/arch/mvmeppc/conf/Makefile.mvmeppc | 4 +- sys/arch/mvmeppc/stand/Makefile.inc | 3 +- sys/arch/sparc/conf/Makefile.sparc | 3 +- sys/arch/sparc/stand/Makefile.inc | 4 +- sys/arch/sparc64/conf/Makefile.sparc64 | 2 +- sys/arch/sparc64/stand/Makefile.inc | 3 +- sys/arch/sun3/conf/Makefile.sun3 | 4 +- sys/arch/sun3/stand/Makefile.inc | 3 +- sys/arch/vax/boot/Makefile.inc | 3 +- sys/arch/vax/conf/Makefile.vax | 5 +- sys/arch/vax/stand/Makefile.inc | 3 +- 50 files changed, 3621 insertions(+), 438 deletions(-) create mode 100644 gnu/egcs/gcc/protector.c create mode 100644 gnu/egcs/gcc/protector.h create mode 100644 lib/libc/sys/stack_protector.c diff --git a/gnu/egcs/gcc/Makefile.in b/gnu/egcs/gcc/Makefile.in index ac9959a3977..a5eeadfd0f5 100644 --- a/gnu/egcs/gcc/Makefile.in +++ b/gnu/egcs/gcc/Makefile.in @@ -685,7 +685,7 @@ OBJS = toplev.o version.o tree.o print-tree.o stor-layout.o fold-const.o \ 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 graph.o sbitmap.o resource.o hash.o + mbchar.o dyn-string.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 @@ -1138,7 +1138,7 @@ libgcc2.a: libgcc2.c libgcc2.ready $(CONFIG_H) $(FPBIT) $(DPBIT) $(LIB2ADD) \ 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}; \ + $(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,7 +1465,7 @@ toplev.o : toplev.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) \ 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)\" \ + -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 diff --git a/gnu/egcs/gcc/combine.c b/gnu/egcs/gcc/combine.c index 0b64a86a548..ad97d3a5b83 100644 --- a/gnu/egcs/gcc/combine.c +++ b/gnu/egcs/gcc/combine.c @@ -1,5 +1,6 @@ /* Optimize by combining instructions for GNU compiler. - Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc. + Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, + 1999, 2000 Free Software Foundation, Inc. This file is part of GNU CC. @@ -392,6 +393,7 @@ static int n_occurrences; static void init_reg_last_arrays PROTO((void)); static void setup_incoming_promotions PROTO((void)); static void set_nonzero_bits_and_sign_copies PROTO((rtx, rtx)); +static int cant_combine_insn_p PROTO((rtx)); static int can_combine_p PROTO((rtx, rtx, rtx, rtx, rtx *, rtx *)); static int sets_function_arg_p PROTO((rtx)); static int combinable_i3pat PROTO((rtx, rtx *, rtx, rtx, int, rtx *)); @@ -1312,6 +1314,54 @@ combinable_i3pat (i3, loc, i2dest, i1dest, i1_not_in_src, pi3dest_killed) return 1; } +/* Determine whether INSN can be used in a combination. Return nonzero if + not. This is used in try_combine to detect early some cases where we + can't perform combinations. */ + +static int +cant_combine_insn_p (insn) + rtx insn; +{ + rtx set; + rtx src, dest; + + /* If this isn't really an insn, we can't do anything. + This can occur when flow deletes an insn that it has merged into an + auto-increment address. */ + if (GET_RTX_CLASS (GET_CODE (insn)) != 'i') + return 1; + + /* For the 2.95.3 release, restrict this code to only handle the machines + where it's strictly needed. */ + if (! SMALL_REGISTER_CLASSES) + return 0; + + /* Never combine loads and stores involving hard regs. The register + allocator can usually handle such reg-reg moves by tying. If we allow + the combiner to make substitutions of hard regs, we risk aborting in + reload on machines that have SMALL_REGISTER_CLASSES. + As an exception, we allow combinations involving fixed regs; these are + not available to the register allocator so there's no risk involved. */ + + set = single_set (insn); + if (! set) + return 0; + src = SET_SRC (set); + dest = SET_DEST (set); + if (GET_CODE (src) == SUBREG) + src = SUBREG_REG (src); + if (GET_CODE (dest) == SUBREG) + dest = SUBREG_REG (dest); + if (REG_P (src) && REG_P (dest) + && ((REGNO (src) < FIRST_PSEUDO_REGISTER + && ! fixed_regs[REGNO (src)]) + || (REGNO (dest) < FIRST_PSEUDO_REGISTER + && ! fixed_regs[REGNO (dest)]))) + return 1; + + return 0; +} + /* Try to combine the insns I1 and I2 into I3. Here I1 and I2 appear earlier than I3. I1 can be zero; then we combine just I2 into I3. @@ -1362,21 +1412,20 @@ try_combine (i3, i2, i1) register rtx link; int i; - /* If any of I1, I2, and I3 isn't really an insn, we can't do anything. - This can occur when flow deletes an insn that it has merged into an - auto-increment address. We also can't do anything if I3 has a - REG_LIBCALL note since we don't want to disrupt the contiguity of a - libcall. */ - - if (GET_RTX_CLASS (GET_CODE (i3)) != 'i' - || GET_RTX_CLASS (GET_CODE (i2)) != 'i' - || (i1 && GET_RTX_CLASS (GET_CODE (i1)) != 'i') + /* Exit early if one of the insns involved can't be used for + combinations. */ + if (cant_combine_insn_p (i3) + || cant_combine_insn_p (i2) + || (i1 && cant_combine_insn_p (i1)) + /* We also can't do anything if I3 has a + REG_LIBCALL note since we don't want to disrupt the contiguity of a + libcall. */ #if 0 /* ??? This gives worse code, and appears to be unnecessary, since no pass after flow uses REG_LIBCALL/REG_RETVAL notes. */ || find_reg_note (i3, REG_LIBCALL, NULL_RTX) #endif -) + ) return 0; combine_attempts++; @@ -3904,6 +3953,11 @@ simplify_rtx (x, op0_mode, last, in_dest) 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)), @@ -4015,7 +4069,8 @@ simplify_rtx (x, op0_mode, last, in_dest) gen_binary (MULT, mode, XEXP (XEXP (x, 0), 0), XEXP (x, 1)), gen_binary (MULT, mode, - XEXP (XEXP (x, 0), 1), XEXP (x, 1)))); + XEXP (XEXP (x, 0), 1), + copy_rtx (XEXP (x, 1))))); if (GET_CODE (x) != MULT) return x; @@ -4954,7 +5009,8 @@ simplify_logical (x, last) x = apply_distributive_law (gen_binary (GET_CODE (op0), mode, gen_binary (AND, mode, XEXP (op0, 0), op1), - gen_binary (AND, mode, XEXP (op0, 1), op1))); + gen_binary (AND, mode, XEXP (op0, 1), + copy_rtx (op1)))); if (GET_CODE (x) != AND) return x; } @@ -4963,7 +5019,8 @@ simplify_logical (x, last) return apply_distributive_law (gen_binary (GET_CODE (op1), mode, gen_binary (AND, mode, XEXP (op1, 0), op0), - gen_binary (AND, mode, XEXP (op1, 1), op0))); + gen_binary (AND, mode, XEXP (op1, 1), + copy_rtx (op0)))); /* Similarly, taking advantage of the fact that (and (not A) (xor B C)) == (xor (ior A B) (ior A C)) */ @@ -4972,13 +5029,14 @@ simplify_logical (x, last) return apply_distributive_law (gen_binary (XOR, mode, gen_binary (IOR, mode, XEXP (op0, 0), XEXP (op1, 0)), - gen_binary (IOR, mode, XEXP (op0, 0), XEXP (op1, 1)))); + gen_binary (IOR, mode, copy_rtx (XEXP (op0, 0)), + XEXP (op1, 1)))); else if (GET_CODE (op1) == NOT && GET_CODE (op0) == XOR) return apply_distributive_law (gen_binary (XOR, mode, gen_binary (IOR, mode, XEXP (op1, 0), XEXP (op0, 0)), - gen_binary (IOR, mode, XEXP (op1, 0), XEXP (op0, 1)))); + gen_binary (IOR, mode, copy_rtx (XEXP (op1, 0)), XEXP (op0, 1)))); break; case IOR: @@ -5004,7 +5062,8 @@ simplify_logical (x, last) x = apply_distributive_law (gen_binary (AND, mode, gen_binary (IOR, mode, XEXP (op0, 0), op1), - gen_binary (IOR, mode, XEXP (op0, 1), op1))); + gen_binary (IOR, mode, XEXP (op0, 1), + copy_rtx (op1)))); if (GET_CODE (x) != IOR) return x; @@ -5015,7 +5074,8 @@ simplify_logical (x, last) x = apply_distributive_law (gen_binary (AND, mode, gen_binary (IOR, mode, XEXP (op1, 0), op0), - gen_binary (IOR, mode, XEXP (op1, 1), op0))); + gen_binary (IOR, mode, XEXP (op1, 1), + copy_rtx (op0)))); if (GET_CODE (x) != IOR) return x; @@ -10834,56 +10894,9 @@ get_last_value (x) return 0; /* If the value was set in a later insn than the ones we are processing, - we can't use it even if the register was only set once, but make a quick - check to see if the previous insn set it to something. This is commonly - the case when the same pseudo is used by repeated insns. - - This does not work if there exists an instruction which is temporarily - not on the insn chain. */ - + we can't use it even if the register was only set once. */ if (INSN_CUID (reg_last_set[regno]) >= subst_low_cuid) - { - rtx insn, set; - - /* We can not do anything useful in this case, because there is - an instruction which is not on the insn chain. */ - if (subst_prev_insn) - return 0; - - /* Skip over USE insns. They are not useful here, and they may have - been made by combine, in which case they do not have a INSN_CUID - value. We can't use prev_real_insn, because that would incorrectly - take us backwards across labels. Skip over BARRIERs also, since - they could have been made by combine. If we see one, we must be - optimizing dead code, so it doesn't matter what we do. */ - for (insn = prev_nonnote_insn (subst_insn); - insn && ((GET_CODE (insn) == INSN - && GET_CODE (PATTERN (insn)) == USE) - || GET_CODE (insn) == BARRIER - || INSN_CUID (insn) >= subst_low_cuid); - insn = prev_nonnote_insn (insn)) - ; - - if (insn - && (set = single_set (insn)) != 0 - && rtx_equal_p (SET_DEST (set), x)) - { - value = SET_SRC (set); - - /* Make sure that VALUE doesn't reference X. Replace any - explicit references with a CLOBBER. If there are any remaining - references (rare), don't use the value. */ - - if (reg_mentioned_p (x, value)) - value = replace_rtx (copy_rtx (value), x, - gen_rtx_CLOBBER (GET_MODE (x), const0_rtx)); - - if (reg_overlap_mentioned_p (x, value)) - return 0; - } - else - return 0; - } + return 0; /* If the value has all its registers valid, return it. */ if (get_last_value_validate (&value, reg_last_set[regno], diff --git a/gnu/egcs/gcc/cse.c b/gnu/egcs/gcc/cse.c index 2947d8ef6a6..8d2b72898ba 100644 --- a/gnu/egcs/gcc/cse.c +++ b/gnu/egcs/gcc/cse.c @@ -4532,6 +4532,7 @@ simplify_plus_minus (code, mode, op0, op1) int n_ops = 2, input_ops = 2, input_consts = 0, n_consts = 0; int first = 1, negate = 0, changed; int i, j; + HOST_WIDE_INT fp_offset = 0; bzero ((char *) ops, sizeof ops); @@ -4550,6 +4551,10 @@ simplify_plus_minus (code, mode, op0, op1) switch (GET_CODE (ops[i])) { case PLUS: + if (flag_propolice_protection + && XEXP (ops[i], 0) == virtual_stack_vars_rtx + && GET_CODE (XEXP (ops[i], 1)) == CONST_INT) + fp_offset = INTVAL (XEXP (ops[i], 1)); case MINUS: if (n_ops == 7) return 0; @@ -4665,7 +4670,43 @@ simplify_plus_minus (code, mode, op0, op1) j = negs[n_ops - 1], negs[n_ops - 1] = negs[i], negs[i] = j; } - /* Put a non-negated operand first. If there aren't any, make all + 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] == virtual_stack_vars_rtx) +#else + if (ops[i] == virtual_stack_vars_rtx + || ops[i] == frame_pointer_rtx) +#endif + { + if (GET_CODE (ops[n_ops - 1]) == CONST_INT) + { + HOST_WIDE_INT value = INTVAL (ops[n_ops - 1]); + if (n_ops < 3 || value >= fp_offset) + { + ops[i] = plus_constant (ops[i], value); + n_ops--; + } + else + { + if (n_ops+1 + n_consts > input_ops + || (n_ops+1 + n_consts == input_ops && n_consts <= input_consts)) + return 0; + ops[n_ops - 1] = GEN_INT (value-fp_offset); + ops[i] = plus_constant (ops[i], fp_offset); + } + } + break; + } + } + +/* Put a non-negated operand first. If there aren't any, make all operands positive and negate the whole thing later. */ for (i = 0; i < n_ops && negs[i]; i++) ; @@ -6511,6 +6552,13 @@ cse_insn (insn, libcall_insn) if (SET_DEST (x) == pc_rtx && GET_CODE (SET_SRC (x)) == LABEL_REF) ; + 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)); + qty_mode[REG_QTY (REGNO (x1))] = GET_MODE (x1); + } /* Don't count call-insns, (set (reg 0) (call ...)), as a set. The hard function value register is used only once, to copy to diff --git a/gnu/egcs/gcc/explow.c b/gnu/egcs/gcc/explow.c index f06d99214e1..603a8d7c594 100644 --- a/gnu/egcs/gcc/explow.c +++ b/gnu/egcs/gcc/explow.c @@ -473,6 +473,21 @@ memory_address (mode, x) in certain cases. This is not necessary since the code below can handle all possible cases, but machine-dependent transformations can make better code. */ + if (flag_propolice_protection) + { +#define FRAMEADDR_P(X) (GET_CODE (X) == PLUS \ + && XEXP (X, 0) == virtual_stack_vars_rtx \ + && GET_CODE (XEXP (X, 1)) == CONST_INT) + rtx y; + if (FRAMEADDR_P (x)) goto win; + for (y=x; y!=0 && GET_CODE (y)==PLUS; y = XEXP (y, 0)) + { + if (FRAMEADDR_P (XEXP (y, 0))) + XEXP (y, 0) = force_reg (GET_MODE (XEXP (y, 0)), XEXP (y, 0)); + if (FRAMEADDR_P (XEXP (y, 1))) + XEXP (y, 1) = force_reg (GET_MODE (XEXP (y, 1)), XEXP (y, 1)); + } + } LEGITIMIZE_ADDRESS (x, oldx, mode, win); /* PLUS and MULT can appear in special ways diff --git a/gnu/egcs/gcc/expr.c b/gnu/egcs/gcc/expr.c index 17fa1be1fdc..996c277a5cc 100644 --- a/gnu/egcs/gcc/expr.c +++ b/gnu/egcs/gcc/expr.c @@ -1,5 +1,6 @@ /* Convert tree expression to rtl instructions, for GNU compiler. - Copyright (C) 1988, 92-98, 1999 Free Software Foundation, Inc. + Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2001 Free Software Foundation, Inc. This file is part of GNU CC. @@ -191,6 +192,7 @@ static rtx expand_builtin PROTO((tree, rtx, rtx, static int apply_args_size PROTO((void)); static int apply_result_size PROTO((void)); static rtx result_vector PROTO((int, rtx)); +static rtx expand_builtin_setjmp PROTO((tree, rtx)); static rtx expand_builtin_apply_args PROTO((void)); static rtx expand_builtin_apply PROTO((rtx, rtx, rtx)); static void expand_builtin_return PROTO((rtx)); @@ -1467,7 +1469,7 @@ move_by_pieces (to, from, len, align) 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; } @@ -1481,7 +1483,7 @@ move_by_pieces (to, from, len, align) 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; } @@ -1599,9 +1601,9 @@ move_by_pieces_1 (genfun, mode, data) MEM_IN_STRUCT_P (from1) = data->from_struct; if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0) - emit_insn (gen_add2_insn (data->to_addr, GEN_INT (-size))); + if (data->explicit_inc_to-- < -1) emit_insn (gen_add2_insn (data->to_addr, GEN_INT (-size))); if (HAVE_PRE_DECREMENT && data->explicit_inc_from < 0) - emit_insn (gen_add2_insn (data->from_addr, GEN_INT (-size))); + if (data->explicit_inc_from-- < -1) emit_insn (gen_add2_insn (data->from_addr, GEN_INT (-size))); emit_insn ((*genfun) (to1, from1)); if (HAVE_POST_INCREMENT && data->explicit_inc_to > 0) @@ -1710,6 +1712,37 @@ emit_block_move (x, y, size, align) } } + /* X, Y, or SIZE may have been passed through protect_from_queue. + + It is unsafe to save the value generated by protect_from_queue + and reuse it later. Consider what happens if emit_queue is + called before the return value from protect_from_queue is used. + + Expansion of the CALL_EXPR below will call emit_queue before + we are finished emitting RTL for argument setup. So if we are + not careful we could get the wrong value for an argument. + + To avoid this problem we go ahead and emit code to copy X, Y & + SIZE into new pseudos. We can then place those new pseudos + into an RTL_EXPR and use them later, even after a call to + emit_queue. + + Note this is not strictly needed for library calls since they + do not call emit_queue before loading their arguments. However, + we may need to have library calls call emit_queue in the future + since failing to do so could cause problems for targets which + define SMALL_REGISTER_CLASSES and pass arguments in registers. */ + x = copy_to_mode_reg (Pmode, XEXP (x, 0)); + y = copy_to_mode_reg (Pmode, XEXP (y, 0)); + +#ifdef TARGET_MEM_FUNCTIONS + size = copy_to_mode_reg (TYPE_MODE (sizetype), size); +#else + size = convert_to_mode (TYPE_MODE (integer_type_node), size, + TREE_UNSIGNED (integer_type_node)); + size = copy_to_mode_reg (TYPE_MODE (integer_type_node), size); +#endif + #ifdef TARGET_MEM_FUNCTIONS /* It is incorrect to use the libcall calling conventions to call memcpy in this context. @@ -1748,12 +1781,10 @@ emit_block_move (x, y, size, align) the last is a size_t byte count for the copy. */ arg_list = build_tree_list (NULL_TREE, - make_tree (build_pointer_type (void_type_node), - XEXP (x, 0))); + make_tree (build_pointer_type (void_type_node), x)); TREE_CHAIN (arg_list) = build_tree_list (NULL_TREE, - make_tree (build_pointer_type (void_type_node), - XEXP (y, 0))); + make_tree (build_pointer_type (void_type_node), y)); TREE_CHAIN (TREE_CHAIN (arg_list)) = build_tree_list (NULL_TREE, make_tree (sizetype, size)); TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arg_list))) = NULL_TREE; @@ -1767,8 +1798,7 @@ emit_block_move (x, y, size, align) retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0); #else emit_library_call (bcopy_libfunc, 0, - VOIDmode, 3, XEXP (y, 0), Pmode, - XEXP (x, 0), Pmode, + VOIDmode, 3, y, Pmode, x, Pmode, convert_to_mode (TYPE_MODE (integer_type_node), size, TREE_UNSIGNED (integer_type_node)), TYPE_MODE (integer_type_node)); @@ -2284,7 +2314,7 @@ clear_by_pieces (to, len, align) 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; } @@ -2354,7 +2384,7 @@ clear_by_pieces_1 (genfun, mode, data) MEM_IN_STRUCT_P (to1) = data->to_struct; if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0) - emit_insn (gen_add2_insn (data->to_addr, GEN_INT (-size))); + if (data->explicit_inc_to-- < -1) emit_insn (gen_add2_insn (data->to_addr, GEN_INT (-size))); emit_insn ((*genfun) (to1, const0_rtx)); if (HAVE_POST_INCREMENT && data->explicit_inc_to > 0) @@ -2444,69 +2474,97 @@ clear_storage (object, size, align) } } + /* OBJECT or SIZE may have been passed through protect_from_queue. -#ifdef TARGET_MEM_FUNCTIONS - /* It is incorrect to use the libcall calling conventions to call - memset in this context. + It is unsafe to save the value generated by protect_from_queue + and reuse it later. Consider what happens if emit_queue is + called before the return value from protect_from_queue is used. - This could be a user call to memset and the user may wish to - examine the return value from memset. + Expansion of the CALL_EXPR below will call emit_queue before + we are finished emitting RTL for argument setup. So if we are + not careful we could get the wrong value for an argument. - For targets where libcalls and normal calls have different conventions - for returning pointers, we could end up generating incorrect code. + To avoid this problem we go ahead and emit code to copy OBJECT + and SIZE into new pseudos. We can then place those new pseudos + into an RTL_EXPR and use them later, even after a call to + emit_queue. - So instead of using a libcall sequence we build up a suitable - CALL_EXPR and expand the call in the normal fashion. */ - if (fn == NULL_TREE) - { - tree fntype; + Note this is not strictly needed for library calls since they + do not call emit_queue before loading their arguments. However, + we may need to have library calls call emit_queue in the future + since failing to do so could cause problems for targets which + define SMALL_REGISTER_CLASSES and pass arguments in registers. */ + object = copy_to_mode_reg (Pmode, XEXP (object, 0)); - /* This was copied from except.c, I don't know if all this is - necessary in this context or not. */ - fn = get_identifier ("memset"); - push_obstacks_nochange (); - end_temporary_allocation (); - fntype = build_pointer_type (void_type_node); - fntype = build_function_type (fntype, NULL_TREE); - fn = build_decl (FUNCTION_DECL, fn, fntype); - DECL_EXTERNAL (fn) = 1; - TREE_PUBLIC (fn) = 1; - DECL_ARTIFICIAL (fn) = 1; - make_decl_rtl (fn, NULL_PTR, 1); - assemble_external (fn); - pop_obstacks (); - } +#ifdef TARGET_MEM_FUNCTIONS + size = copy_to_mode_reg (TYPE_MODE (sizetype), size); +#else + size = convert_to_mode (TYPE_MODE (integer_type_node), size, + TREE_UNSIGNED (integer_type_node)); + size = copy_to_mode_reg (TYPE_MODE (integer_type_node), size); +#endif - /* We need to make an argument list for the function call. - memset has three arguments, the first is a void * addresses, the - second a integer with the initialization value, the last is a size_t - byte count for the copy. */ - arg_list - = build_tree_list (NULL_TREE, - make_tree (build_pointer_type (void_type_node), - XEXP (object, 0))); - TREE_CHAIN (arg_list) - = build_tree_list (NULL_TREE, - make_tree (integer_type_node, const0_rtx)); - TREE_CHAIN (TREE_CHAIN (arg_list)) - = build_tree_list (NULL_TREE, make_tree (sizetype, size)); - TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arg_list))) = NULL_TREE; +#ifdef TARGET_MEM_FUNCTIONS + /* It is incorrect to use the libcall calling conventions to call + memset in this context. - /* Now we have to build up the CALL_EXPR itself. */ - call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn); - call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)), - call_expr, arg_list, NULL_TREE); - TREE_SIDE_EFFECTS (call_expr) = 1; + This could be a user call to memset and the user may wish to + examine the return value from memset. - retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0); + For targets where libcalls and normal calls have different + conventions for returning pointers, we could end up generating + incorrect code. + + So instead of using a libcall sequence we build up a suitable + CALL_EXPR and expand the call in the normal fashion. */ + if (fn == NULL_TREE) + { + tree fntype; + + /* This was copied from except.c, I don't know if all this is + necessary in this context or not. */ + fn = get_identifier ("memset"); + push_obstacks_nochange (); + end_temporary_allocation (); + fntype = build_pointer_type (void_type_node); + fntype = build_function_type (fntype, NULL_TREE); + fn = build_decl (FUNCTION_DECL, fn, fntype); + DECL_EXTERNAL (fn) = 1; + TREE_PUBLIC (fn) = 1; + DECL_ARTIFICIAL (fn) = 1; + make_decl_rtl (fn, NULL_PTR, 1); + assemble_external (fn); + pop_obstacks (); + } + + /* We need to make an argument list for the function call. + + memset has three arguments, the first is a void * addresses, the + second a integer with the initialization value, the last is a + size_t byte count for the copy. */ + arg_list + = build_tree_list (NULL_TREE, + make_tree (build_pointer_type (void_type_node), + object)); + TREE_CHAIN (arg_list) + = build_tree_list (NULL_TREE, + make_tree (integer_type_node, const0_rtx)); + TREE_CHAIN (TREE_CHAIN (arg_list)) + = build_tree_list (NULL_TREE, make_tree (sizetype, size)); + TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arg_list))) = NULL_TREE; + + /* Now we have to build up the CALL_EXPR itself. */ + call_expr = build1 (ADDR_EXPR, + build_pointer_type (TREE_TYPE (fn)), fn); + call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)), + call_expr, arg_list, NULL_TREE); + TREE_SIDE_EFFECTS (call_expr) = 1; + + retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0); #else emit_library_call (bzero_libfunc, 0, - VOIDmode, 2, - XEXP (object, 0), Pmode, - convert_to_mode - (TYPE_MODE (integer_type_node), size, - TREE_UNSIGNED (integer_type_node)), + VOIDmode, 2, object, Pmode, size, TYPE_MODE (integer_type_node)); #endif } @@ -2623,19 +2681,79 @@ emit_move_insn_1 (x, y) } else { - /* Show the output dies here. This is necessary for pseudos; + rtx realpart_x, realpart_y; + rtx imagpart_x, imagpart_y; + + /* If this is a complex value with each part being smaller than a + word, the usual calling sequence will likely pack the pieces into + a single register. Unfortunately, SUBREG of hard registers only + deals in terms of words, so we have a problem converting input + arguments to the CONCAT of two registers that is used elsewhere + for complex values. If this is before reload, we can copy it into + memory and reload. FIXME, we should see about using extract and + insert on integer registers, but complex short and complex char + variables should be rarely used. */ + if (GET_MODE_BITSIZE (mode) < 2*BITS_PER_WORD + && (reload_in_progress | reload_completed) == 0) + { + int packed_dest_p = (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER); + int packed_src_p = (REG_P (y) && REGNO (y) < FIRST_PSEUDO_REGISTER); + + if (packed_dest_p || packed_src_p) + { + enum mode_class reg_class = ((class == MODE_COMPLEX_FLOAT) + ? MODE_FLOAT : MODE_INT); + + enum machine_mode reg_mode = + mode_for_size (GET_MODE_BITSIZE (mode), reg_class, 1); + + if (reg_mode != BLKmode) + { + rtx mem = assign_stack_temp (reg_mode, + GET_MODE_SIZE (mode), 0); + + rtx cmem = change_address (mem, mode, NULL_RTX); + + current_function_cannot_inline + = "function using short complex types cannot be inline"; + + if (packed_dest_p) + { + rtx sreg = gen_rtx_SUBREG (reg_mode, x, 0); + emit_move_insn_1 (cmem, y); + return emit_move_insn_1 (sreg, mem); + } + else + { + rtx sreg = gen_rtx_SUBREG (reg_mode, y, 0); + emit_move_insn_1 (mem, sreg); + return emit_move_insn_1 (x, cmem); + } + } + } + } + + realpart_x = gen_realpart (submode, x); + realpart_y = gen_realpart (submode, y); + imagpart_x = gen_imagpart (submode, x); + imagpart_y = gen_imagpart (submode, y); + + /* Show the output dies here. This is necessary for SUBREGs + of pseudos since we cannot track their lifetimes correctly; hard regs shouldn't appear here except as return values. We never want to emit such a clobber after reload. */ if (x != y - && ! (reload_in_progress || reload_completed)) + && ! (reload_in_progress || reload_completed) + && (GET_CODE (realpart_x) == SUBREG + || GET_CODE (imagpart_x) == SUBREG)) { emit_insn (gen_rtx_CLOBBER (VOIDmode, x)); } emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code) - (gen_realpart (submode, x), gen_realpart (submode, y))); + (realpart_x, realpart_y)); emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code) - (gen_imagpart (submode, x), gen_imagpart (submode, y))); + (imagpart_x, imagpart_y)); } return get_last_insn (); @@ -2647,6 +2765,8 @@ emit_move_insn_1 (x, y) else if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) { rtx last_insn = 0; + rtx seq; + int need_clobber; #ifdef PUSH_ROUNDING @@ -2659,15 +2779,9 @@ emit_move_insn_1 (x, y) } #endif - /* Show the output dies here. This is necessary for pseudos; - hard regs shouldn't appear here except as return values. - We never want to emit such a clobber after reload. */ - if (x != y - && ! (reload_in_progress || reload_completed)) - { - emit_insn (gen_rtx_CLOBBER (VOIDmode, x)); - } + start_sequence (); + need_clobber = 0; for (i = 0; i < (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD; i++) @@ -2689,9 +2803,27 @@ emit_move_insn_1 (x, y) if (xpart == 0 || ypart == 0) abort (); + need_clobber |= (GET_CODE (xpart) == SUBREG); + last_insn = emit_move_insn (xpart, ypart); } + seq = gen_sequence (); + end_sequence (); + + /* Show the output dies here. This is necessary for SUBREGs + of pseudos since we cannot track their lifetimes correctly; + hard regs shouldn't appear here except as return values. + We never want to emit such a clobber after reload. */ + if (x != y + && ! (reload_in_progress || reload_completed) + && need_clobber != 0) + { + emit_insn (gen_rtx_CLOBBER (VOIDmode, x)); + } + + emit_insn (seq); + return last_insn; } else @@ -5097,7 +5229,7 @@ init_noncopied_parts (lhs, list) for (tail = list; tail; tail = TREE_CHAIN (tail)) if (TREE_CODE (TREE_VALUE (tail)) == TREE_LIST) parts = chainon (parts, init_noncopied_parts (lhs, TREE_VALUE (tail))); - else + else if (TREE_PURPOSE (tail)) { tree part = TREE_VALUE (tail); tree part_type = TREE_TYPE (part); @@ -6206,12 +6338,8 @@ expand_expr (exp, target, tmode, modifier) } temp = gen_rtx_MEM (mode, op0); - /* If address was computed by addition, - mark this as an element of an aggregate. */ - if (TREE_CODE (exp1) == PLUS_EXPR - || (TREE_CODE (exp1) == SAVE_EXPR - && TREE_CODE (TREE_OPERAND (exp1, 0)) == PLUS_EXPR) - || AGGREGATE_TYPE_P (TREE_TYPE (exp)) + + if (AGGREGATE_TYPE_P (TREE_TYPE (exp)) || (TREE_CODE (exp1) == ADDR_EXPR && (exp2 = TREE_OPERAND (exp1, 0)) && AGGREGATE_TYPE_P (TREE_TYPE (exp2)))) @@ -6948,7 +7076,8 @@ expand_expr (exp, target, tmode, modifier) /* 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 && XEXP (op1, 0) == virtual_stack_vars_rtx)) { rtx constant_term = const0_rtx; @@ -8417,44 +8546,29 @@ expand_builtin_return_addr (fndecl_code, count, tem) return tem; } -/* __builtin_setjmp is passed a pointer to an array of five words (not - all will be used on all machines). It operates similarly to the C - library function of the same name, but is more efficient. Much of - the code below (and for longjmp) is copied from the handling of - non-local gotos. +/* Construct the leading half of a __builtin_setjmp call. Control will + return to RECEIVER_LABEL. This is used directly by sjlj exception + handling code. */ - NOTE: This is intended for use by GNAT and the exception handling - scheme in the compiler and will only work in the method used by - them. */ - -rtx -expand_builtin_setjmp (buf_addr, target, first_label, next_label) +void +expand_builtin_setjmp_setup (buf_addr, receiver_label) rtx buf_addr; - rtx target; - rtx first_label, next_label; + rtx receiver_label; { - rtx lab1 = gen_label_rtx (); enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL); - enum machine_mode value_mode; rtx stack_save; - value_mode = TYPE_MODE (integer_type_node); - #ifdef POINTERS_EXTEND_UNSIGNED buf_addr = convert_memory_address (Pmode, buf_addr); #endif buf_addr = force_reg (Pmode, buf_addr); - if (target == 0 || GET_CODE (target) != REG - || REGNO (target) < FIRST_PSEUDO_REGISTER) - target = gen_reg_rtx (value_mode); - emit_queue (); - /* We store the frame pointer and the address of lab1 in the buffer - and use the rest of it for the stack save area, which is - machine-dependent. */ + /* We store the frame pointer and the address of receiver_label in + the buffer and use the rest of it for the stack save area, which + is machine-dependent. */ #ifndef BUILTIN_SETJMP_FRAME_VALUE #define BUILTIN_SETJMP_FRAME_VALUE virtual_stack_vars_rtx @@ -8466,7 +8580,7 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label) (gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode)))), - force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, lab1))); + force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label))); stack_save = gen_rtx_MEM (sa_mode, plus_constant (buf_addr, @@ -8479,20 +8593,22 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label) emit_insn (gen_builtin_setjmp_setup (buf_addr)); #endif - /* Set TARGET to zero and branch to the first-time-through label. */ - emit_move_insn (target, const0_rtx); - emit_jump_insn (gen_jump (first_label)); - emit_barrier (); - emit_label (lab1); - - /* Tell flow about the strange goings on. Putting `lab1' on - `nonlocal_goto_handler_labels' to indicates that function - calls may traverse the arc back to this label. */ + /* Tell optimize_save_area_alloca that extra work is going to + need to go on during alloca. */ + current_function_calls_setjmp = 1; + /* Set this so all the registers get saved in our frame; we need to be + able to copy the saved values for any registers from frames we unwind. */ current_function_has_nonlocal_label = 1; - nonlocal_goto_handler_labels = - gen_rtx_EXPR_LIST (VOIDmode, lab1, nonlocal_goto_handler_labels); +} +/* Construct the trailing part of a __builtin_setjmp call. + This is used directly by sjlj exception handling code. */ + +void +expand_builtin_setjmp_receiver (receiver_label) + rtx receiver_label ATTRIBUTE_UNUSED; +{ /* Clobber the FP when we get here, so we have to make sure it's marked as used by this function. */ emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx)); @@ -8539,7 +8655,7 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label) #ifdef HAVE_builtin_setjmp_receiver if (HAVE_builtin_setjmp_receiver) - emit_insn (gen_builtin_setjmp_receiver (lab1)); + emit_insn (gen_builtin_setjmp_receiver (receiver_label)); else #endif #ifdef HAVE_nonlocal_goto_receiver @@ -8551,11 +8667,67 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label) ; /* Nothing */ } - /* Set TARGET, and branch to the next-time-through label. */ - emit_move_insn (target, const1_rtx); - emit_jump_insn (gen_jump (next_label)); + /* @@@ This is a kludge. Not all machine descriptions define a blockage + insn, but we must not allow the code we just generated to be reordered + by scheduling. Specifically, the update of the frame pointer must + happen immediately, not later. So emit an ASM_INPUT to act as blockage + insn. */ + emit_insn (gen_rtx_ASM_INPUT (VOIDmode, "")); +} + + +/* __builtin_setjmp is passed a pointer to an array of five words (not + all will be used on all machines). It operates similarly to the C + library function of the same name, but is more efficient. Much of + the code below (and for longjmp) is copied from the handling of + non-local gotos. + + NOTE: This is intended for use by GNAT and the exception handling + scheme in the compiler and will only work in the method used by + them. */ + +static rtx +expand_builtin_setjmp (arglist, target) + tree arglist; + rtx target; +{ + rtx buf_addr, next_lab, cont_lab; + + if (arglist == 0 + || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE) + return NULL_RTX; + + if (target == 0 || GET_CODE (target) != REG + || REGNO (target) < FIRST_PSEUDO_REGISTER) + target = gen_reg_rtx (TYPE_MODE (integer_type_node)); + + buf_addr = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0); + + next_lab = gen_label_rtx (); + cont_lab = gen_label_rtx (); + + expand_builtin_setjmp_setup (buf_addr, next_lab); + + /* Set TARGET to zero and branch to the continue label. */ + emit_move_insn (target, const0_rtx); + emit_jump_insn (gen_jump (cont_lab)); emit_barrier (); + emit_label (next_lab); + + expand_builtin_setjmp_receiver (next_lab); + + /* Set TARGET to one. */ + emit_move_insn (target, const1_rtx); + emit_label (cont_lab); + + /* Tell flow about the strange goings on. Putting `next_lab' on + `nonlocal_goto_handler_labels' to indicates that function + calls may traverse the arc back to this label. */ + current_function_has_nonlocal_label = 1; + nonlocal_goto_handler_labels + = gen_rtx_EXPR_LIST (VOIDmode, next_lab, nonlocal_goto_handler_labels); + return target; } @@ -9576,18 +9748,10 @@ expand_builtin (exp, target, subtarget, mode, ignore) #endif case BUILT_IN_SETJMP: - if (arglist == 0 - || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE) - break; - else - { - rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget, - VOIDmode, 0); - rtx lab = gen_label_rtx (); - rtx ret = expand_builtin_setjmp (buf_addr, target, lab, lab); - emit_label (lab); - return ret; - } + target = expand_builtin_setjmp (arglist, target); + if (target) + return target; + break; /* __builtin_longjmp is passed a pointer to an array of five words. It's similar to the C library longjmp function but works with diff --git a/gnu/egcs/gcc/flags.h b/gnu/egcs/gcc/flags.h index df736988cce..24ef2a1a80c 100644 --- a/gnu/egcs/gcc/flags.h +++ b/gnu/egcs/gcc/flags.h @@ -296,6 +296,12 @@ extern int flag_fast_math; extern int flag_errno_math; +/* 0 means straightforward implementation of complex divide acceptable. + 1 means wide ranges of inputs must work for complex divide. + 2 means C9X-like requirements for complex divide (not yet implemented). */ + +extern int flag_complex_divide_method; + /* Nonzero means to run loop optimizations twice. */ extern int flag_rerun_loop_opt; @@ -532,3 +538,11 @@ extern enum graph_dump_types graph_dump_format; string identifying the compiler. */ extern int flag_no_ident; + +/* 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; diff --git a/gnu/egcs/gcc/function.c b/gnu/egcs/gcc/function.c index edd0bca1216..88523dfcc79 100644 --- a/gnu/egcs/gcc/function.c +++ b/gnu/egcs/gcc/function.c @@ -58,6 +58,7 @@ Boston, MA 02111-1307, USA. */ #include "obstack.h" #include "toplev.h" #include "hash.h" +#include "protector.h" #ifndef TRAMPOLINE_ALIGNMENT #define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY @@ -430,6 +431,8 @@ struct temp_slot /* 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. */ @@ -449,6 +452,11 @@ int var_temp_slot_level; 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 @@ -931,6 +939,10 @@ assign_stack_temp_for_type (mode, size, keep, type) 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. */ @@ -963,7 +975,8 @@ assign_stack_temp_for_type (mode, size, keep, type) && (!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))) + || (best_p->size == p->size && best_p->align > p->align)) + && (! char_array || p->boundary_mark != 0)) { if (p->align == align && p->size == size) { @@ -1001,6 +1014,7 @@ assign_stack_temp_for_type (mode, size, keep, type) 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; @@ -1062,6 +1076,7 @@ assign_stack_temp_for_type (mode, size, keep, type) 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; } @@ -1186,14 +1201,16 @@ combine_temp_slots () 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; @@ -1702,7 +1719,7 @@ put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p, 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); + new = assign_stack_local_for_pseudo_reg (decl_mode, GET_MODE_SIZE (decl_mode), 0); } PUT_MODE (reg, decl_mode); @@ -3860,7 +3877,8 @@ instantiate_virtual_regs_1 (loc, object, extra_insns) constant with that register. */ temp = gen_reg_rtx (Pmode); XEXP (x, 0) = new; - if (validate_change (object, &XEXP (x, 1), temp, 0)) + if (validate_change (object, &XEXP (x, 1), temp, 0) + && ! flag_propolice_protection) emit_insn_before (gen_move_insn (temp, new_offset), object); else { diff --git a/gnu/egcs/gcc/gcse.c b/gnu/egcs/gcc/gcse.c index d7fde36ecd8..3dab465ee4b 100644 --- a/gnu/egcs/gcc/gcse.c +++ b/gnu/egcs/gcc/gcse.c @@ -1394,6 +1394,7 @@ hash_expr_1 (x, mode, do_not_record_p) return 0; } hash += (unsigned) MEM; + hash += MEM_ALIAS_SET (x); x = XEXP (x, 0); goto repeat; @@ -1526,6 +1527,14 @@ expr_equiv_p (x, y) case REG: return REGNO (x) == REGNO (y); + case MEM: + /* Can't merge two expressions in different alias sets, since we can + decide that the expression is transparent in a block when it isn't, + due to it being set with the different alias set. */ + if (MEM_ALIAS_SET (x) != MEM_ALIAS_SET (y)) + return 0; + break; + /* For commutative operations, check both orders. */ case PLUS: case MULT: @@ -3709,7 +3718,7 @@ cprop_insn (insn, alter_jumps) /* 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; @@ -4189,9 +4198,26 @@ insert_insn_end_bb (expr, bb, pre) } } - new_insn = emit_insn_before (pat, insn); - if (BLOCK_HEAD (bb) == insn) - BLOCK_HEAD (bb) = new_insn; + /* If we found all the parameter loads, then we want to insert + before the first parameter load. + + If we did not find all the parameter loads, then we might have + stopped on the head of the block, which could be a CODE_LABEL. + If we inserted before the CODE_LABEL, then we would be putting + the insn in the wrong basic block. In that case, put the insn + after the CODE_LABEL. + + ?!? Do we need to account for NOTE_INSN_BASIC_BLOCK here? */ + if (GET_CODE (insn) != CODE_LABEL) + { + new_insn = emit_insn_before (pat, insn); + if (BLOCK_HEAD (bb) == insn) + BLOCK_HEAD (bb) = new_insn; + } + else + { + new_insn = emit_insn_after (pat, insn); + } } else { diff --git a/gnu/egcs/gcc/optabs.c b/gnu/egcs/gcc/optabs.c index 75f224c4809..d195d692b45 100644 --- a/gnu/egcs/gcc/optabs.c +++ b/gnu/egcs/gcc/optabs.c @@ -1,5 +1,6 @@ /* Expand the basic unary and binary arithmetic operations, for GNU compiler. - Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc. + Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000 Free Software Foundation, Inc. This file is part of GNU CC. @@ -246,6 +247,14 @@ enum insn_code movcc_gen_code[NUM_MACHINE_MODES]; static int add_equal_note PROTO((rtx, rtx, enum rtx_code, rtx, rtx)); static rtx widen_operand PROTO((rtx, enum machine_mode, enum machine_mode, int, int)); +static int expand_cmplxdiv_straight PROTO((rtx, rtx, rtx, rtx, + rtx, rtx, enum machine_mode, + int, enum optab_methods, + enum mode_class, optab)); +static int expand_cmplxdiv_wide PROTO((rtx, rtx, rtx, rtx, + rtx, rtx, enum machine_mode, + int, enum optab_methods, + enum mode_class, optab)); static enum insn_code can_fix_p PROTO((enum machine_mode, enum machine_mode, int, int *)); static enum insn_code can_float_p PROTO((enum machine_mode, enum machine_mode, @@ -348,6 +357,379 @@ widen_operand (op, mode, oldmode, unsignedp, no_extend) return result; } +/* Generate code to perform a straightforward complex divide. */ + +static int +expand_cmplxdiv_straight (real0, real1, imag0, imag1, realr, imagr, submode, + unsignedp, methods, class, binoptab) + rtx real0, real1, imag0, imag1, realr, imagr; + enum machine_mode submode; + int unsignedp; + enum optab_methods methods; + enum mode_class class; + optab binoptab; +{ + rtx divisor; + rtx real_t, imag_t; + rtx temp1, temp2; + rtx res; + + /* Don't fetch these from memory more than once. */ + real0 = force_reg (submode, real0); + real1 = force_reg (submode, real1); + + if (imag0 != 0) + imag0 = force_reg (submode, imag0); + + imag1 = force_reg (submode, imag1); + + /* Divisor: c*c + d*d. */ + temp1 = expand_binop (submode, smul_optab, real1, real1, + NULL_RTX, unsignedp, methods); + + temp2 = expand_binop (submode, smul_optab, imag1, imag1, + NULL_RTX, unsignedp, methods); + + if (temp1 == 0 || temp2 == 0) + return 0; + + divisor = expand_binop (submode, add_optab, temp1, temp2, + NULL_RTX, unsignedp, methods); + if (divisor == 0) + return 0; + + if (imag0 == 0) + { + /* Mathematically, ((a)(c-id))/divisor. */ + /* Computationally, (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)). */ + + /* Calculate the dividend. */ + real_t = expand_binop (submode, smul_optab, real0, real1, + NULL_RTX, unsignedp, methods); + + imag_t = expand_binop (submode, smul_optab, real0, imag1, + NULL_RTX, unsignedp, methods); + + if (real_t == 0 || imag_t == 0) + return 0; + + imag_t = expand_unop (submode, neg_optab, imag_t, + NULL_RTX, unsignedp); + } + else + { + /* Mathematically, ((a+ib)(c-id))/divider. */ + /* Calculate the dividend. */ + temp1 = expand_binop (submode, smul_optab, real0, real1, + NULL_RTX, unsignedp, methods); + + temp2 = expand_binop (submode, smul_optab, imag0, imag1, + NULL_RTX, unsignedp, methods); + + if (temp1 == 0 || temp2 == 0) + return 0; + + real_t = expand_binop (submode, add_optab, temp1, temp2, + NULL_RTX, unsignedp, methods); + + temp1 = expand_binop (submode, smul_optab, imag0, real1, + NULL_RTX, unsignedp, methods); + + temp2 = expand_binop (submode, smul_optab, real0, imag1, + NULL_RTX, unsignedp, methods); + + if (temp1 == 0 || temp2 == 0) + return 0; + + imag_t = expand_binop (submode, sub_optab, temp1, temp2, + NULL_RTX, unsignedp, methods); + + if (real_t == 0 || imag_t == 0) + return 0; + } + + if (class == MODE_COMPLEX_FLOAT) + res = expand_binop (submode, binoptab, real_t, divisor, + realr, unsignedp, methods); + else + res = expand_divmod (0, TRUNC_DIV_EXPR, submode, + real_t, divisor, realr, unsignedp); + + if (res == 0) + return 0; + + if (res != realr) + emit_move_insn (realr, res); + + if (class == MODE_COMPLEX_FLOAT) + res = expand_binop (submode, binoptab, imag_t, divisor, + imagr, unsignedp, methods); + else + res = expand_divmod (0, TRUNC_DIV_EXPR, submode, + imag_t, divisor, imagr, unsignedp); + + if (res == 0) + return 0; + + if (res != imagr) + emit_move_insn (imagr, res); + + return 1; +} + +/* Generate code to perform a wide-input-range-acceptable complex divide. */ + +static int +expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode, + unsignedp, methods, class, binoptab) + rtx real0, real1, imag0, imag1, realr, imagr; + enum machine_mode submode; + int unsignedp; + enum optab_methods methods; + enum mode_class class; + optab binoptab; +{ + rtx ratio, divisor; + rtx real_t, imag_t; + rtx temp1, temp2, lab1, lab2; + enum machine_mode mode; + int align; + rtx res; + + /* Don't fetch these from memory more than once. */ + real0 = force_reg (submode, real0); + real1 = force_reg (submode, real1); + + if (imag0 != 0) + imag0 = force_reg (submode, imag0); + + imag1 = force_reg (submode, imag1); + + /* XXX What's an "unsigned" complex number? */ + if (unsignedp) + { + temp1 = real1; + temp2 = imag1; + } + else + { + temp1 = expand_abs (submode, real1, NULL_RTX, 1); + temp2 = expand_abs (submode, imag1, NULL_RTX, 1); + } + + if (temp1 == 0 || temp2 == 0) + return 0; + + mode = GET_MODE (temp1); + align = GET_MODE_ALIGNMENT (mode); + lab1 = gen_label_rtx (); + emit_cmp_and_jump_insns (temp1, temp2, LT, NULL_RTX, + mode, unsignedp, align, lab1); + + /* |c| >= |d|; use ratio d/c to scale dividend and divisor. */ + + if (class == MODE_COMPLEX_FLOAT) + ratio = expand_binop (submode, binoptab, imag1, real1, + NULL_RTX, unsignedp, methods); + else + ratio = expand_divmod (0, TRUNC_DIV_EXPR, submode, + imag1, real1, NULL_RTX, unsignedp); + + if (ratio == 0) + return 0; + + /* Calculate divisor. */ + + temp1 = expand_binop (submode, smul_optab, imag1, ratio, + NULL_RTX, unsignedp, methods); + + if (temp1 == 0) + return 0; + + divisor = expand_binop (submode, add_optab, temp1, real1, + NULL_RTX, unsignedp, methods); + + if (divisor == 0) + return 0; + + /* Calculate dividend. */ + + if (imag0 == 0) + { + real_t = real0; + + /* Compute a / (c+id) as a / (c+d(d/c)) + i (-a(d/c)) / (c+d(d/c)). */ + + imag_t = expand_binop (submode, smul_optab, real0, ratio, + NULL_RTX, unsignedp, methods); + + if (imag_t == 0) + return 0; + + imag_t = expand_unop (submode, neg_optab, imag_t, + NULL_RTX, unsignedp); + + if (real_t == 0 || imag_t == 0) + return 0; + } + else + { + /* Compute (a+ib)/(c+id) as + (a+b(d/c))/(c+d(d/c) + i(b-a(d/c))/(c+d(d/c)). */ + + temp1 = expand_binop (submode, smul_optab, imag0, ratio, + NULL_RTX, unsignedp, methods); + + if (temp1 == 0) + return 0; + + real_t = expand_binop (submode, add_optab, temp1, real0, + NULL_RTX, unsignedp, methods); + + temp1 = expand_binop (submode, smul_optab, real0, ratio, + NULL_RTX, unsignedp, methods); + + if (temp1 == 0) + return 0; + + imag_t = expand_binop (submode, sub_optab, imag0, temp1, + NULL_RTX, unsignedp, methods); + + if (real_t == 0 || imag_t == 0) + return 0; + } + + if (class == MODE_COMPLEX_FLOAT) + res = expand_binop (submode, binoptab, real_t, divisor, + realr, unsignedp, methods); + else + res = expand_divmod (0, TRUNC_DIV_EXPR, submode, + real_t, divisor, realr, unsignedp); + + if (res == 0) + return 0; + + if (res != realr) + emit_move_insn (realr, res); + + if (class == MODE_COMPLEX_FLOAT) + res = expand_binop (submode, binoptab, imag_t, divisor, + imagr, unsignedp, methods); + else + res = expand_divmod (0, TRUNC_DIV_EXPR, submode, + imag_t, divisor, imagr, unsignedp); + + if (res == 0) + return 0; + + if (res != imagr) + emit_move_insn (imagr, res); + + lab2 = gen_label_rtx (); + emit_jump_insn (gen_jump (lab2)); + emit_barrier (); + + emit_label (lab1); + + /* |d| > |c|; use ratio c/d to scale dividend and divisor. */ + + if (class == MODE_COMPLEX_FLOAT) + ratio = expand_binop (submode, binoptab, real1, imag1, + NULL_RTX, unsignedp, methods); + else + ratio = expand_divmod (0, TRUNC_DIV_EXPR, submode, + real1, imag1, NULL_RTX, unsignedp); + + if (ratio == 0) + return 0; + + /* Calculate divisor. */ + + temp1 = expand_binop (submode, smul_optab, real1, ratio, + NULL_RTX, unsignedp, methods); + + if (temp1 == 0) + return 0; + + divisor = expand_binop (submode, add_optab, temp1, imag1, + NULL_RTX, unsignedp, methods); + + if (divisor == 0) + return 0; + + /* Calculate dividend. */ + + if (imag0 == 0) + { + /* Compute a / (c+id) as a(c/d) / (c(c/d)+d) + i (-a) / (c(c/d)+d). */ + + real_t = expand_binop (submode, smul_optab, real0, ratio, + NULL_RTX, unsignedp, methods); + + imag_t = expand_unop (submode, neg_optab, real0, + NULL_RTX, unsignedp); + + if (real_t == 0 || imag_t == 0) + return 0; + } + else + { + /* Compute (a+ib)/(c+id) as + (a(c/d)+b)/(c(c/d)+d) + i (b(c/d)-a)/(c(c/d)+d). */ + + temp1 = expand_binop (submode, smul_optab, real0, ratio, + NULL_RTX, unsignedp, methods); + + if (temp1 == 0) + return 0; + + real_t = expand_binop (submode, add_optab, temp1, imag0, + NULL_RTX, unsignedp, methods); + + temp1 = expand_binop (submode, smul_optab, imag0, ratio, + NULL_RTX, unsignedp, methods); + + if (temp1 == 0) + return 0; + + imag_t = expand_binop (submode, sub_optab, temp1, real0, + NULL_RTX, unsignedp, methods); + + if (real_t == 0 || imag_t == 0) + return 0; + } + + if (class == MODE_COMPLEX_FLOAT) + res = expand_binop (submode, binoptab, real_t, divisor, + realr, unsignedp, methods); + else + res = expand_divmod (0, TRUNC_DIV_EXPR, submode, + real_t, divisor, realr, unsignedp); + + if (res == 0) + return 0; + + if (res != realr) + emit_move_insn (realr, res); + + if (class == MODE_COMPLEX_FLOAT) + res = expand_binop (submode, binoptab, imag_t, divisor, + imagr, unsignedp, methods); + else + res = expand_divmod (0, TRUNC_DIV_EXPR, submode, + imag_t, divisor, imagr, unsignedp); + + if (res == 0) + return 0; + + if (res != imagr) + emit_move_insn (imagr, res); + + emit_label (lab2); + + return 1; +} + /* Generate code to perform an operation specified by BINOPTAB on operands OP0 and OP1, with result having machine-mode MODE. @@ -390,6 +772,25 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods) 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_operand_predicate[icode][0]) (temp, mode)) + 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); @@ -1219,12 +1620,12 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods) start_sequence (); - realr = gen_realpart (submode, target); + realr = gen_realpart (submode, target); imagr = gen_imagpart (submode, target); if (GET_MODE (op0) == mode) { - real0 = gen_realpart (submode, op0); + real0 = gen_realpart (submode, op0); imag0 = gen_imagpart (submode, op0); } else @@ -1232,7 +1633,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods) if (GET_MODE (op1) == mode) { - real1 = gen_realpart (submode, op1); + real1 = gen_realpart (submode, op1); imag1 = gen_imagpart (submode, op1); } else @@ -1390,111 +1791,25 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods) } else { - /* Divisor is of complex type: - X/(a+ib) */ - rtx divisor; - rtx real_t, imag_t; - rtx temp1, temp2; - - /* Don't fetch these from memory more than once. */ - real0 = force_reg (submode, real0); - real1 = force_reg (submode, real1); - - if (imag0 != 0) - imag0 = force_reg (submode, imag0); - - imag1 = force_reg (submode, imag1); - - /* Divisor: c*c + d*d */ - temp1 = expand_binop (submode, smul_optab, real1, real1, - NULL_RTX, unsignedp, methods); - - temp2 = expand_binop (submode, smul_optab, imag1, imag1, - NULL_RTX, unsignedp, methods); - - if (temp1 == 0 || temp2 == 0) - break; - - divisor = expand_binop (submode, add_optab, temp1, temp2, - NULL_RTX, unsignedp, methods); - if (divisor == 0) - break; - - if (imag0 == 0) + switch (flag_complex_divide_method) { - /* ((a)(c-id))/divisor */ - /* (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)) */ - - /* Calculate the dividend */ - real_t = expand_binop (submode, smul_optab, real0, real1, - NULL_RTX, unsignedp, methods); - - imag_t = expand_binop (submode, smul_optab, real0, imag1, - NULL_RTX, unsignedp, methods); - - if (real_t == 0 || imag_t == 0) - break; - - imag_t = expand_unop (submode, neg_optab, imag_t, - NULL_RTX, unsignedp); - } - else - { - /* ((a+ib)(c-id))/divider */ - /* Calculate the dividend */ - temp1 = expand_binop (submode, smul_optab, real0, real1, - NULL_RTX, unsignedp, methods); - - temp2 = expand_binop (submode, smul_optab, imag0, imag1, - NULL_RTX, unsignedp, methods); - - if (temp1 == 0 || temp2 == 0) - break; - - real_t = expand_binop (submode, add_optab, temp1, temp2, - NULL_RTX, unsignedp, methods); - - temp1 = expand_binop (submode, smul_optab, imag0, real1, - NULL_RTX, unsignedp, methods); - - temp2 = expand_binop (submode, smul_optab, real0, imag1, - NULL_RTX, unsignedp, methods); - - if (temp1 == 0 || temp2 == 0) - break; + case 0: + ok = expand_cmplxdiv_straight (real0, real1, imag0, imag1, + realr, imagr, submode, + unsignedp, methods, + class, binoptab); + break; - imag_t = expand_binop (submode, sub_optab, temp1, temp2, - NULL_RTX, unsignedp, methods); + case 1: + ok = expand_cmplxdiv_wide (real0, real1, imag0, imag1, + realr, imagr, submode, + unsignedp, methods, + class, binoptab); + break; - if (real_t == 0 || imag_t == 0) - break; + default: + abort (); } - - if (class == MODE_COMPLEX_FLOAT) - res = expand_binop (submode, binoptab, real_t, divisor, - realr, unsignedp, methods); - else - res = expand_divmod (0, TRUNC_DIV_EXPR, submode, - real_t, divisor, realr, unsignedp); - - if (res == 0) - break; - else if (res != realr) - emit_move_insn (realr, res); - - if (class == MODE_COMPLEX_FLOAT) - res = expand_binop (submode, binoptab, imag_t, divisor, - imagr, unsignedp, methods); - else - res = expand_divmod (0, TRUNC_DIV_EXPR, submode, - imag_t, divisor, imagr, unsignedp); - - if (res == 0) - break; - else if (res != imagr) - emit_move_insn (imagr, res); - - ok = 1; } break; @@ -2592,8 +2907,14 @@ emit_libcall_block (insns, target, result, equiv) rtx result; rtx equiv; { + rtx final_dest = target; rtx prev, next, first, last, insn; + /* If this is a reg with REG_USERVAR_P set, then it could possibly turn + into a MEM later. Protect the libcall block from this change. */ + if (! REG_P (target) || REG_USERVAR_P (target)) + target = gen_reg_rtx (GET_MODE (target)); + /* look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION reg note to indicate that this call cannot throw. (Unless there is already a REG_EH_REGION note.) */ @@ -2657,6 +2978,9 @@ emit_libcall_block (insns, target, result, equiv) != CODE_FOR_nothing) set_unique_reg_note (last, REG_EQUAL, copy_rtx (equiv)); + if (final_dest != target) + emit_move_insn (final_dest, target); + if (prev == 0) first = get_insns (); else diff --git a/gnu/egcs/gcc/protector.c b/gnu/egcs/gcc/protector.c new file mode 100644 index 00000000000..efbe22dba71 --- /dev/null +++ b/gnu/egcs/gcc/protector.c @@ -0,0 +1,2269 @@ +/* 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 "machmode.h" + +#include "rtl.h" +#include "tree.h" +#include "regs.h" +#include "flags.h" +#include "insn-config.h" +#include "insn-flags.h" +#include "expr.h" +#include "output.h" +#include "recog.h" +#include "hard-reg-set.h" +#include "real.h" +#include "except.h" +#include "function.h" +#include "toplev.h" +#include "conditions.h" +#include "insn-attr.h" +#include "c-tree.h" +#include "protector.h" + + +rtx assign_stack_local_for_pseudo_reg PARAMS ((enum machine_mode, HOST_WIDE_INT, int)); + + +/* Warn when not issuing stack smashing protection for some reason */ +int warn_stack_protector; + +/* Round a value to the lowest integer less than it that is a multiple of + the required alignment. Avoid using division in case the value is + negative. Assume the alignment is a power of two. */ +#define FLOOR_ROUND(VALUE,ALIGN) ((VALUE) & ~((ALIGN) - 1)) + +/* Similar, but round to the next highest integer that meets the + alignment. */ +#define CEIL_ROUND(VALUE,ALIGN) (((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1)) + + +/* Nonzero means use propolice as a stack protection method */ +extern int flag_propolice_protection; + +/* This file contains several memory arrangement functions to protect + the return address and the frame pointer of the stack + from a stack-smashing attack. It also + provides the function that protects pointer variables. */ + +/* Nonzero if function being compiled can define string buffers that may be + damaged by the stack-smash attack */ +static int current_function_defines_vulnerable_string; +static int current_function_defines_short_string; +static int current_function_has_variable_string; +static int current_function_defines_vsized_array; +static int saved_optimize_size = -1; + +static rtx guard_area, _guard; +static rtx function_first_insn, prologue_insert_point; +static rtx debuginsn; + +/* */ +static HOST_WIDE_INT sweep_frame_offset; +static HOST_WIDE_INT push_allocated_offset = 0; +static HOST_WIDE_INT push_frame_offset = 0; + +static int search_string_from_argsandvars PARAMS ((int caller)); +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, HOST_WIDE_INT var_size)); +static void sweep_string_in_decls PARAMS ((tree block, HOST_WIDE_INT sweep_offset, HOST_WIDE_INT size)); +static void sweep_string_in_args PARAMS ((tree parms, HOST_WIDE_INT sweep_offset, HOST_WIDE_INT size)); +static void sweep_string_use_of_insns PARAMS ((rtx insn, HOST_WIDE_INT sweep_offset, HOST_WIDE_INT size)); +static void sweep_string_in_operand PARAMS ((rtx insn, rtx orig, HOST_WIDE_INT sweep_offset, HOST_WIDE_INT size)); +static void move_arg_location PARAMS ((rtx insn, rtx orig, rtx new, HOST_WIDE_INT var_size)); +static void change_arg_use_of_insns PARAMS ((rtx insn, rtx orig, rtx new, HOST_WIDE_INT size)); +static void change_arg_use_in_operand PARAMS ((rtx x, rtx orig, rtx new, HOST_WIDE_INT size)); +static void expand_value_return PARAMS ((rtx val)); +static int replace_return_reg PARAMS ((rtx insn, rtx return_save)); +static void propagate_virtual_stack_vars_in_insns PARAMS ((rtx insn)); +static void propagate_virtual_stack_vars_in_operand PARAMS ((rtx x, rtx orig)); + + +#define SUSPICIOUS_BUF_SIZE 8 + +#define AUTO_BASEPTR(X) \ + (GET_CODE (X) == PLUS ? XEXP (X, 0) : X) +#define AUTO_OFFSET(X) \ + (GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0) +#undef PARM_PASSED_IN_MEMORY +#define PARM_PASSED_IN_MEMORY(PARM) \ + (GET_CODE (DECL_INCOMING_RTL (PARM)) == MEM) +#define VIRTUAL_STACK_VARS_P(X) \ + ((X) == virtual_stack_vars_rtx || (GET_CODE (X) == REG && (X)->used)) + + + +void +prepare_stack_protection (void) +{ + tree blocks = DECL_INITIAL (current_function_decl); + current_function_defines_short_string = FALSE; + current_function_has_variable_string = FALSE; + current_function_defines_vsized_array = FALSE; + push_frame_offset = push_allocated_offset = 0; + + /* solve for ssp-ppc-20021125 */ + if (saved_optimize_size < 0) saved_optimize_size = optimize_size; + optimize_size = saved_optimize_size; + + /* + 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 (0); + + if (current_function_defines_vulnerable_string) + { + HOST_WIDE_INT offset; + function_first_insn = get_insns (); + + if (current_function_contains_functions) { + if (warn_stack_protector) + warning ("not protecting function: it contains functions"); + return; + } + + /* propagate virtual_stack_vars_rtx to access arg_pointer_save_area */ + if (arg_pointer_save_area) + propagate_virtual_stack_vars_in_insns (function_first_insn); + + sweep_frame_offset = 0; + +#ifdef STACK_GROWS_DOWNWARD + /* + frame_offset: offset to end of allocated area of stack frame. + It is defined in the function.c + */ + + /* the location must be before buffers */ + guard_area = assign_stack_local (BLKmode, UNITS_PER_GUARD, -1); + PUT_MODE (guard_area, GUARD_m); + MEM_VOLATILE_P (guard_area) = 1; + +#ifndef FRAME_GROWS_DOWNWARD + sweep_frame_offset = frame_offset; +#endif + + /* For making room for guard value, scan all insns and fix the offset address + of the variable that is based on frame pointer. + Scan all declarations of variables and fix the offset address of the variable that + is based on the frame pointer */ + sweep_string_variable (guard_area, UNITS_PER_GUARD); + + + /* the location of guard area moves to the beginning of stack frame */ + if ((offset = AUTO_OFFSET(XEXP (guard_area, 0)))) + XEXP (XEXP (guard_area, 0), 1) = gen_rtx_CONST_INT (VOIDmode, sweep_frame_offset); + + + /* Insert prologue rtl instructions */ + rtl_prologue (function_first_insn); + + if (! current_function_has_variable_string) + { + /* Generate argument saving instruction */ + copy_args_for_protection (); + +#ifndef FRAME_GROWS_DOWNWARD + /* If frame grows upward, character string copied from an arg stays top of + the guard variable. So sweep the guard variable again */ + sweep_frame_offset = CEIL_ROUND (frame_offset, BIGGEST_ALIGNMENT / BITS_PER_UNIT); + sweep_string_variable (guard_area, UNITS_PER_GUARD); +#endif + } + else if (warn_stack_protector) + warning ("not protecting variables: it has a variable length buffer"); +#endif +#ifndef FRAME_GROWS_DOWNWARD + if (STARTING_FRAME_OFFSET == 0) + { + /* this may be only for alpha */ + push_allocated_offset = BIGGEST_ALIGNMENT / BITS_PER_UNIT; + assign_stack_local (BLKmode, push_allocated_offset, -1); + sweep_frame_offset = frame_offset; + sweep_string_variable (const0_rtx, -push_allocated_offset); + sweep_frame_offset = AUTO_OFFSET (XEXP (guard_area, 0)); + } +#endif + + /* Arrange the order of local variables */ + arrange_var_order (blocks); + +#ifdef STACK_GROWS_DOWNWARD + /* Insert epilogue rtl instructions */ + rtl_epilogue (get_last_insn ()); +#endif + } + else if (current_function_defines_short_string + && warn_stack_protector) + warning ("not protecting function: buffer is less than %d bytes long", + SUSPICIOUS_BUF_SIZE); +} + +/* + search string from arguments and local variables + caller: 0 means call from protector_stack_protection + 1 means call from push_frame +*/ +static int +search_string_from_argsandvars (caller) + int caller; +{ + tree blocks, parms; + int string_p; + + /* saves a latest search result as a cached infomation */ + static tree __latest_search_decl = 0; + static int __latest_search_result = FALSE; + + if (__latest_search_decl == current_function_decl) + return __latest_search_result; + else if (caller) return FALSE; + __latest_search_decl = current_function_decl; + __latest_search_result = TRUE; + + /* + search a string variable from local variables + */ + blocks = DECL_INITIAL (current_function_decl); + string_p = search_string_from_local_vars (blocks); + + if (!current_function_defines_vsized_array && current_function_calls_alloca) + { + current_function_has_variable_string = TRUE; + return TRUE; + } + + if (string_p) return TRUE; + +#ifdef STACK_GROWS_DOWNWARD + /* + search a string variable from arguments + */ + parms = DECL_ARGUMENTS (current_function_decl); + + for (; parms; parms = TREE_CHAIN (parms)) + if (DECL_NAME (parms) && TREE_TYPE (parms) != error_mark_node) + { + if (PARM_PASSED_IN_MEMORY (parms) && DECL_NAME (parms)) + { + string_p = search_string_def (TREE_TYPE(parms)); + if (string_p) return TRUE; + } + } +#endif + + __latest_search_result = FALSE; + return FALSE; +} + + +static int +search_string_from_local_vars (block) + tree block; +{ + tree types; + int found = FALSE; + + while (block) + { + types = BLOCK_VARS(block); + + while (types) + { + /* skip the declaration that refers an external variable */ + /* name: types.decl.name.identifier.id */ + if (! DECL_EXTERNAL (types) && ! TREE_STATIC (types) + && TREE_CODE (types) == VAR_DECL + && ! DECL_ARTIFICIAL (types) + && DECL_RTL (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 + && XEXP (home, 0) != virtual_stack_vars_rtx + && REGNO (XEXP (home, 0)) != HARD_FRAME_POINTER_REGNUM + && REGNO (XEXP (home, 0)) != STACK_POINTER_REGNUM +#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM + && REGNO (XEXP (home, 0)) != ARG_POINTER_REGNUM +#endif + ))) + /* If the value is indirect by memory or by a register + that isn't the frame pointer + then it means the object is variable-sized and address through + that register or stack slot. The protection has no way to hide pointer variables + behind the array, so all we can do is staying arguments. */ + { + current_function_has_variable_string = TRUE; + } + /* found character array */ + found = TRUE; + } + } + + types = TREE_CHAIN(types); + } + + if (search_string_from_local_vars (BLOCK_SUBBLOCKS (block))) + { + found = TRUE; + } + + block = BLOCK_CHAIN (block); + } + + return found; +} + +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: + /* Check if the array is a variable-sized array */ + if (TYPE_DOMAIN (type) == 0 || + TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == NOP_EXPR) + current_function_defines_vsized_array = TRUE; + + 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; + + current_function_defines_short_string = 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; +{ +#if defined(INIT_SECTION_ASM_OP) && !defined(INVOKE__main) +#undef HAS_INIT_SECTION +#define HAS_INIT_SECTION +#endif + rtx _val; + + + for (; insn; insn = NEXT_INSN (insn)) + if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG) + break; + +#if !defined (HAS_INIT_SECTION) + /* If this function is `main', skip a call to `__main' + to run guard instruments after global initializers, etc. */ + if (DECL_NAME (current_function_decl) + && strcmp (IDENTIFIER_POINTER (DECL_NAME (current_function_decl)), "main") == 0 + && DECL_CONTEXT (current_function_decl) == NULL_TREE) + { + rtx fbinsn = insn; + for (; insn; insn = NEXT_INSN (insn)) + if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG) + break; + if (insn == 0) insn = fbinsn; + } +#endif + + 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")); + _guard = force_reg (GUARD_m, _guard); + emit_move_insn ( guard_area, _guard); + + _val = gen_sequence (); + end_sequence (); + + emit_insn_before (_val, prologue_insert_point); +} + +static void +rtl_epilogue (insn) + rtx insn; +{ + rtx if_false_label; + rtx _val; + rtx funcname; + tree funcstr; + rtx return_reg = DECL_RTL (DECL_RESULT (current_function_decl)), return_save; + int flag_have_return = FALSE; + + start_sequence (); + +#ifdef HAVE_return + if (HAVE_return) + { + rtx insn; + return_label = gen_label_rtx (); + + for (insn = prologue_insert_point; insn; insn = NEXT_INSN (insn)) + if (GET_CODE (insn) == JUMP_INSN + && GET_CODE (PATTERN (insn)) == RETURN + && GET_MODE (PATTERN (insn)) == VOIDmode) + { + rtx pat = gen_rtx_SET (VOIDmode, + pc_rtx, + gen_rtx_LABEL_REF (VOIDmode, + return_label)); + PATTERN (insn) = pat; + flag_have_return = TRUE; + } + + + emit_label (return_label); + } +#endif + + if (return_reg + && ! (current_function_returns_struct + || current_function_returns_pcc_struct)) + { + return_save = GET_CODE (return_reg)==REG? + gen_reg_rtx (GET_MODE (return_reg)):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); + + emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__stack_smash_handler"), + 0, VOIDmode, 2, + XEXP (funcname, 0), Pmode, guard_area, GUARD_m); + + /* generate RTL to return from the current function */ + + emit_barrier (); /* } */ + emit_label (if_false_label); + + /* generate RTL to return from the current function */ + if (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); + } + } + +#ifdef HAVE_return + if (HAVE_return && flag_have_return) + { + emit_jump_insn (gen_return ()); + emit_barrier (); + } +#endif + + _val = gen_sequence (); + end_sequence (); + + emit_insn_after (_val, insn); +} + + +static void +arrange_var_order (block) + tree block; +{ + tree types; + HOST_WIDE_INT offset; + + while (block) + { + types = BLOCK_VARS (block); + + while (types) + { + /* skip the declaration that refers an external variable */ + /* name: types.decl.assembler_name.id */ + if (! DECL_EXTERNAL (types) && ! TREE_STATIC (types) + && TREE_CODE (types) == VAR_DECL + && ! DECL_ARTIFICIAL (types) + && DECL_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 + && XEXP (home, 0) != virtual_stack_vars_rtx + && REGNO (XEXP (home, 0)) != HARD_FRAME_POINTER_REGNUM + && REGNO (XEXP (home, 0)) != STACK_POINTER_REGNUM +#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM + && REGNO (XEXP (home, 0)) != ARG_POINTER_REGNUM +#endif + )))) + { + /* found a string variable */ + HOST_WIDE_INT var_size = + ((TREE_INT_CST_LOW (DECL_SIZE (types)) + BITS_PER_UNIT - 1) + / BITS_PER_UNIT); + + if (GET_MODE (DECL_RTL (types)) == BLKmode) + { + int alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT; + var_size = CEIL_ROUND (var_size, alignment); + } + + /* skip the variable if it is top of the region + specified by sweep_frame_offset */ + offset = AUTO_OFFSET (XEXP (DECL_RTL (types), 0)); + if (offset >= sweep_frame_offset - var_size) + sweep_frame_offset -= var_size; + + else + 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; + + parms = DECL_ARGUMENTS (current_function_decl); + for (idx = 0; parms; parms = TREE_CHAIN (parms)) + if (DECL_NAME (parms) && TREE_TYPE (parms) != error_mark_node) + { + if (PARM_PASSED_IN_MEMORY (parms) && DECL_NAME (parms)) + { + int string_p; + + /* + skip arguemnt protection if the last argument is used + for the variable argument + */ + /* + tree fntype; + if (TREE_CHAIN (parms) == 0) + { + fntype = TREE_TYPE (current_function_decl); + + if ((TYPE_ARG_TYPES (fntype) != 0 && + TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) != void_type_node) + || current_function_varargs) + continue; + } + */ + + string_p = search_string_def (TREE_TYPE(parms)); + + /* check if it is a candidate to move */ + if (string_p || search_pointer_def (TREE_TYPE (parms))) + { + int arg_size + = ((TREE_INT_CST_LOW (DECL_SIZE (parms)) + BITS_PER_UNIT - 1) + / BITS_PER_UNIT); + + 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 */ + DECL_INCOMING_RTL (parms) = safe; + } + + else if (GET_CODE (DECL_RTL (parms)) == MEM + && GET_CODE (XEXP (DECL_RTL (parms), 0)) == ADDRESSOF) + { + rtx movinsn; + rtx safe = gen_reg_rtx (GET_MODE (DECL_RTL (parms))); + + /* generate codes for copying the content */ + movinsn = emit_move_insn (safe, DECL_INCOMING_RTL (parms)); + 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 */ + DECL_INCOMING_RTL (parms) = 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 (); + +#ifdef FRAME_GROWS_DOWNWARD + /* process the string argument */ + if (string_p && DECL_MODE (parms) == BLKmode) + { + int alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT; + arg_size = CEIL_ROUND (arg_size, alignment); + + /* change the reference for each instructions */ + sweep_string_variable (DECL_RTL (parms), arg_size); + } +#endif + } + } + } +} + + +/* + sweep a string variable to the local variable addressed by sweep_frame_offset, that is + a last position of string variables. +*/ +static void +sweep_string_variable (sweep_var, var_size) + rtx sweep_var; + HOST_WIDE_INT var_size; +{ + HOST_WIDE_INT sweep_offset; + + switch (GET_CODE (sweep_var)) + { + case MEM: + sweep_offset = AUTO_OFFSET(XEXP (sweep_var, 0)); + break; + case CONST_INT: + sweep_offset = INTVAL (sweep_var); + break; + default: + abort (); + } + + /* scan all declarations of variables and fix the offset address of + the variable based on the frame pointer */ + sweep_string_in_decls (DECL_INITIAL (current_function_decl), sweep_offset, var_size); + + /* scan all argument variable and fix the offset address based on the frame pointer */ + sweep_string_in_args (DECL_ARGUMENTS (current_function_decl), sweep_offset, var_size); + + /* For making room for sweep variable, scan all insns and fix the offset address + of the variable that is based on frame pointer*/ + sweep_string_use_of_insns (function_first_insn, sweep_offset, var_size); + + + /* Clear all the USED bits in operands of all insns and declarations of local vars */ + reset_used_flags_for_decls (DECL_INITIAL (current_function_decl)); + reset_used_flags_for_insns (function_first_insn); + + sweep_frame_offset -= var_size; +} + + + +/* + move an argument to the local variable addressed by frame_offset +*/ +static void +move_arg_location (insn, orig, new, var_size) + rtx insn, orig, new; + HOST_WIDE_INT var_size; +{ + /* For making room for sweep variable, scan all insns and fix the offset address + of the variable that is based on frame pointer*/ + change_arg_use_of_insns (insn, orig, new, var_size); + + + /* Clear all the USED bits in operands of all insns and declarations of local vars */ + reset_used_flags_for_insns (insn); +} + + +static void +sweep_string_in_decls (block, sweep_offset, sweep_size) + tree block; + HOST_WIDE_INT sweep_offset, sweep_size; +{ + tree types; + HOST_WIDE_INT offset; + rtx home; + + while (block) + { + 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 + && XEXP (home, 0) == virtual_stack_vars_rtx) + { + offset = 0; + + /* the operand related to the sweep variable */ + if (sweep_offset <= offset + && offset < sweep_offset + sweep_size) + { + offset = sweep_frame_offset - sweep_size - sweep_offset; + + XEXP (home, 0) = plus_constant (virtual_stack_vars_rtx, offset); + XEXP (home, 0)->used = 1; + } + else if (sweep_offset <= offset + && offset < sweep_frame_offset) + { /* the rest of variables under sweep_frame_offset, so shift the location */ + XEXP (home, 0) = plus_constant (virtual_stack_vars_rtx, -sweep_size); + XEXP (home, 0)->used = 1; + } + } + + if (GET_CODE (home) == MEM + && GET_CODE (XEXP (home, 0)) == MEM) + { + /* process for dynamically allocated aray */ + home = XEXP (home, 0); + } + + if (GET_CODE (home) == MEM + && GET_CODE (XEXP (home, 0)) == PLUS + && XEXP (XEXP (home, 0), 0) == virtual_stack_vars_rtx + && GET_CODE (XEXP (XEXP (home, 0), 1)) == CONST_INT) + { + if (! XEXP (home, 0)->used) + { + offset = AUTO_OFFSET(XEXP (home, 0)); + + /* the operand related to the sweep variable */ + if (sweep_offset <= offset + && offset < sweep_offset + sweep_size) + { + + offset += sweep_frame_offset - sweep_size - sweep_offset; + XEXP (XEXP (home, 0), 1) = gen_rtx_CONST_INT (VOIDmode, offset); + + /* mark */ + XEXP (home, 0)->used = 1; + } + else if (sweep_offset <= offset + && offset < sweep_frame_offset) + { /* the rest of variables under sweep_frame_offset, + so shift the location */ + + XEXP (XEXP (home, 0), 1) + = gen_rtx_CONST_INT (VOIDmode, offset - sweep_size); + + /* mark */ + XEXP (home, 0)->used = 1; + } + } + } + + } + next: + types = TREE_CHAIN(types); + } + + sweep_string_in_decls (BLOCK_SUBBLOCKS (block), sweep_offset, sweep_size); + block = BLOCK_CHAIN (block); + } +} + + +static void +sweep_string_in_args (parms, sweep_offset, sweep_size) + tree parms; + HOST_WIDE_INT sweep_offset, sweep_size; +{ + rtx home; + HOST_WIDE_INT offset; + + for (; parms; parms = TREE_CHAIN (parms)) + if (DECL_NAME (parms) && TREE_TYPE (parms) != error_mark_node) + { + if (PARM_PASSED_IN_MEMORY (parms) && DECL_NAME (parms)) + { + home = DECL_INCOMING_RTL (parms); + + if (XEXP (home, 0)->used) continue; + + offset = AUTO_OFFSET(XEXP (home, 0)); + + /* the operand related to the sweep variable */ + if (AUTO_BASEPTR (XEXP (home, 0)) == virtual_stack_vars_rtx) + { + if (sweep_offset <= offset + && offset < sweep_offset + sweep_size) + { + offset += sweep_frame_offset - sweep_size - sweep_offset; + XEXP (XEXP (home, 0), 1) = gen_rtx_CONST_INT (VOIDmode, offset); + + /* mark */ + XEXP (home, 0)->used = 1; + } + else if (sweep_offset <= offset + && offset < sweep_frame_offset) + { /* the rest of variables under sweep_frame_offset, 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; + HOST_WIDE_INT sweep_offset, sweep_size; +{ + for (; insn; insn = NEXT_INSN (insn)) + if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN + || GET_CODE (insn) == CALL_INSN) + { + sweep_string_in_operand (insn, PATTERN (insn), sweep_offset, sweep_size); + } +} + + +static void +sweep_string_in_operand (insn, orig, sweep_offset, sweep_size) + rtx insn, orig; + HOST_WIDE_INT sweep_offset, sweep_size; +{ + register rtx x = orig; + register enum rtx_code code; + int i, j; + HOST_WIDE_INT offset; + const char *fmt; + + if (x == 0) + return; + + code = GET_CODE (x); + + switch (code) + { + case CONST_INT: + case CONST_DOUBLE: + case CONST: + case SYMBOL_REF: + case CODE_LABEL: + case PC: + case CC0: + case ASM_INPUT: + case ADDR_VEC: + case ADDR_DIFF_VEC: + case RETURN: + case REG: + case ADDRESSOF: + return; + + case SET: + break; + + case PLUS: + /* Handle typical case of frame register plus constant. */ + if (XEXP (x, 0) == virtual_stack_vars_rtx + && CONSTANT_P (XEXP (x, 1))) + { + if (x->used) return; + + offset = 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; + } + 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; + } + +#ifdef FRAME_GROWS_DOWNWARD + /* + Handle special case of frame register plus constant given by reg. + This is happen when the mem is refered by legitimized address. + + CAUTION: + This is only used at the case of guard sweep, not arrange_var_order. + + Example: + (plus:SI (reg:SI 78) (reg:SI 109)) + */ + else if (XEXP (x, 0) == virtual_stack_vars_rtx + && GET_CODE (XEXP (x, 1)) == REG) + { + rtx temp, *loc, seq; + + temp = plus_constant (virtual_stack_vars_rtx, -sweep_size); + temp->used = 1; + + loc = &XEXP (x, 0); + if (! validate_change (insn, loc, temp, 0)) { + start_sequence (); + temp = force_operand (temp, NULL_RTX); + seq = get_insns (); + end_sequence (); + + emit_insns_before (seq, insn); + if (! validate_change (insn, loc, temp, 0) + && ! validate_replace_rtx (XEXP (x, 0), temp, insn)) + *loc = temp; /* abort (); */ + } + return; + } +#endif + + /* + process further subtree: + Example: (plus:SI (mem/s:SI (plus:SI (reg:SI 17) (const_int 8))) + (const_int 5)) + */ + break; + + case CALL_PLACEHOLDER: + 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') + { + /* + virtual_stack_vars_rtx without offset + Example: + (set (reg:SI xx) (reg:SI 78)) + (set (reg:SI xx) (MEM (reg:SI 78))) + */ + if (XEXP (x, i) == virtual_stack_vars_rtx) + { + rtx temp = 0, *loc, seq; + offset = 0; + + /* the operand related to the sweep variable */ + if (sweep_offset <= offset + && offset < sweep_offset + sweep_size) + { + offset = sweep_frame_offset - sweep_size - sweep_offset; + + temp = plus_constant (virtual_stack_vars_rtx, offset); + temp->used = 1; + } + else if (sweep_offset <= offset + && offset < sweep_frame_offset) + { /* the rest of variables under sweep_frame_offset, so shift the location */ + temp = plus_constant (virtual_stack_vars_rtx, -sweep_size); + temp->used = 1; + } + + if (temp) { + loc = &XEXP (x, i); + if (! validate_change (insn, loc, temp, 0)) { + start_sequence (); + temp = force_operand (temp, NULL_RTX); + seq = get_insns (); + end_sequence (); + + emit_insns_before (seq, insn); + if (! validate_change (insn, loc, temp, 0) + && ! validate_replace_rtx (XEXP (x, i), temp, insn)) + *loc = temp; /* abort (); */ + } + } + return; + } + + sweep_string_in_operand (insn, XEXP (x, i), sweep_offset, sweep_size); + } + else if (*fmt == 'E') + for (j = 0; j < XVECLEN (x, i); j++) + sweep_string_in_operand (insn, XVECEXP (x, i, j), sweep_offset, sweep_size); +} + + +/* + change a argument variable to the local variable addressed by the "new" variable. +*/ +static void +change_arg_use_of_insns (insn, orig, new, size) + rtx insn, orig, new; + HOST_WIDE_INT size; +{ + 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; + HOST_WIDE_INT size; +{ + register enum rtx_code code; + int i, j; + HOST_WIDE_INT offset; + const char *fmt; + + if (x == 0) + return; + + code = GET_CODE (x); + + switch (code) + { + case CONST_INT: + case CONST_DOUBLE: + case CONST: + case SYMBOL_REF: + case CODE_LABEL: + case PC: + case CC0: + case ASM_INPUT: + case ADDR_VEC: + case ADDR_DIFF_VEC: + case RETURN: + case REG: + case ADDRESSOF: + return; + + case 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 = AUTO_OFFSET(x); + + /* the operand related to the sweep variable */ + if (AUTO_OFFSET(XEXP (orig, 0)) <= offset && + offset < AUTO_OFFSET(XEXP (orig, 0)) + size) { + + offset = AUTO_OFFSET(XEXP (new, 0)) + + (offset - AUTO_OFFSET(XEXP (orig, 0))); + + XEXP (x, 0) = virtual_stack_vars_rtx; + XEXP (x, 1) = gen_rtx_CONST_INT (VOIDmode, offset); + x->used = 1; + + return; + } + + /* + process further subtree: + Example: (plus:SI (mem/s:SI (plus:SI (reg:SI 17) (const_int 8))) + (const_int 5)) + */ + } + break; + + case 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)); + } + } +} + + +static void +propagate_virtual_stack_vars_in_insns (insn) + rtx insn; +{ + for (; insn; insn = NEXT_INSN (insn)) + if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN + || GET_CODE (insn) == CALL_INSN) + { + propagate_virtual_stack_vars_in_operand (insn, PATTERN (insn)); + } +} + + +static void +propagate_virtual_stack_vars_in_operand (insn, orig) + rtx insn, orig; +{ + register rtx x = orig; + register enum rtx_code code; + int 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: + if (RTX_INTEGRATED_P (insn) + && (GET_CODE (SET_SRC (x)) == REG && GET_CODE (SET_DEST (x)) == REG) + && VIRTUAL_STACK_VARS_P (SET_SRC (x))) + { + SET_DEST (x)->used = 1; debug_rtx (insn); + return; + } + break; + + case PLUS: + /* Handle typical case of frame register plus constant. */ + if (VIRTUAL_STACK_VARS_P (XEXP (x, 0)) + && (CONSTANT_P (XEXP (x, 1)) + || GET_CODE (XEXP (x, 1)) == REG)) + { + XEXP (x, 0) = virtual_stack_vars_rtx; + 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: + propagate_virtual_stack_vars_in_insns (XEXP (x, 0)); + propagate_virtual_stack_vars_in_insns (XEXP (x, 1)); + propagate_virtual_stack_vars_in_insns (XEXP (x, 2)); + break; + + default: + break; + } + + /* Scan all subexpressions. */ + fmt = GET_RTX_FORMAT (code); + for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++) + if (*fmt == 'e') + propagate_virtual_stack_vars_in_operand (insn, XEXP (x, i)); + else if (*fmt == 'E') + for (j = 0; j < XVECLEN (x, i); j++) + propagate_virtual_stack_vars_in_operand (insn, XVECEXP (x, i, j)); +} + + + + +/* + The following codes are invoked after the instantiation of pseuso registers. + + Reorder local variables to place a peudo register after buffers to avoid + the corruption of local variables that could be used to further corrupt + arbitrary memory locations. +*/ +#ifndef FRAME_GROWS_DOWNWARD +static void push_frame PARAMS ((HOST_WIDE_INT var_size, HOST_WIDE_INT boundary)); +static void push_frame_in_decls PARAMS ((tree block, HOST_WIDE_INT push_size, HOST_WIDE_INT boundary)); +static void push_frame_in_args PARAMS ((tree parms, HOST_WIDE_INT push_size, HOST_WIDE_INT boundary)); +static void push_frame_of_insns PARAMS ((rtx insn, HOST_WIDE_INT push_size, HOST_WIDE_INT boundary)); +static void push_frame_in_operand PARAMS ((rtx orig, HOST_WIDE_INT push_size, HOST_WIDE_INT boundary)); +static void push_frame_of_reg_equiv_memory_loc PARAMS ((HOST_WIDE_INT push_size, HOST_WIDE_INT boundary)); +static void push_frame_of_reg_equiv_constant PARAMS ((HOST_WIDE_INT push_size, HOST_WIDE_INT boundary)); +static void reset_used_flags_for_push_frame PARAMS ((void)); +static int check_out_of_frame_access PARAMS ((rtx insn, HOST_WIDE_INT boundary)); +static int check_out_of_frame_access_in_operand PARAMS ((rtx, HOST_WIDE_INT boundary)); +#endif + +rtx +assign_stack_local_for_pseudo_reg (mode, size, align) + enum machine_mode mode; + HOST_WIDE_INT size; + int align; +{ +#ifdef FRAME_GROWS_DOWNWARD + return assign_stack_local (mode, size, align); +#else + tree blocks = DECL_INITIAL (current_function_decl); + rtx new; + HOST_WIDE_INT saved_frame_offset, units_per_push; + + if (! flag_propolice_protection + || size == 0 + || ! blocks || TREE_CODE (blocks) != BLOCK + || DECL_INLINE (current_function_decl) + || ! search_string_from_argsandvars (1) + || current_function_contains_functions) + return assign_stack_local (mode, size, align); + + optimize_size = 1; /* solve for ssp-ppc-20021125 */ + units_per_push = MAX(BIGGEST_ALIGNMENT / BITS_PER_UNIT, + GET_MODE_SIZE (mode)); + + if (push_frame_offset == 0 + && check_out_of_frame_access (get_insns (), STARTING_FRAME_OFFSET)) + { + /* if there is an access beyond frame, push dummy region to seperate + the address of instantiated variables */ + push_frame (GET_MODE_SIZE (DImode), 0); + assign_stack_local (BLKmode, GET_MODE_SIZE (DImode), -1); + } + + saved_frame_offset = frame_offset; + frame_offset = push_frame_offset; + + new = assign_stack_local (mode, size, align); + + push_frame_offset = frame_offset; + frame_offset = saved_frame_offset; + + if (push_frame_offset > push_allocated_offset) { + push_frame (units_per_push, AUTO_OFFSET(XEXP (new, 0))); + + assign_stack_local (BLKmode, units_per_push, -1); + push_allocated_offset += units_per_push; + } + + 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, boundary) + HOST_WIDE_INT var_size, boundary; +{ + reset_used_flags_for_push_frame(); + + /* scan all declarations of variables and fix the offset address of the variable based on the frame pointer */ + push_frame_in_decls (DECL_INITIAL (current_function_decl), var_size, boundary); + + /* scan all argument variable and fix the offset address based on the frame pointer */ + push_frame_in_args (DECL_ARGUMENTS (current_function_decl), var_size, boundary); + + /* scan all operands of all insns and fix the offset address based on the frame pointer */ + push_frame_of_insns (get_insns (), var_size, boundary); + + /* scan all reg_equiv_memory_loc and reg_equiv_constant*/ + push_frame_of_reg_equiv_memory_loc (var_size, boundary); + push_frame_of_reg_equiv_constant (var_size, boundary); + + reset_used_flags_for_push_frame(); +} + +static void +reset_used_flags_for_push_frame() +{ + int i; + extern rtx *reg_equiv_memory_loc; + extern rtx *reg_equiv_constant; + + /* Clear all the USED bits in operands of all insns and declarations of local vars */ + reset_used_flags_for_decls (DECL_INITIAL (current_function_decl)); + reset_used_flags_for_insns (get_insns ()); + + + /* The following codes are processed if the push_frame is called from + global_alloc (or reload) function */ + if (reg_equiv_memory_loc == 0) return; + + for (i=LAST_VIRTUAL_REGISTER+1; i < max_regno; i++) + if (reg_equiv_memory_loc[i]) + { + rtx x = reg_equiv_memory_loc[i]; + + if (GET_CODE (x) == MEM + && GET_CODE (XEXP (x, 0)) == PLUS + && AUTO_BASEPTR (XEXP (x, 0)) == frame_pointer_rtx) + { + /* reset */ + XEXP (x, 0)->used = 0; + } + } + + + if (reg_equiv_constant == 0) return; + + for (i=LAST_VIRTUAL_REGISTER+1; i < max_regno; i++) + if (reg_equiv_constant[i]) + { + rtx x = reg_equiv_constant[i]; + + if (GET_CODE (x) == PLUS + && AUTO_BASEPTR (x) == frame_pointer_rtx) + { + /* reset */ + x->used = 0; + } + } +} + +static void +push_frame_in_decls (block, push_size, boundary) + tree block; + HOST_WIDE_INT push_size, boundary; +{ + tree types; + HOST_WIDE_INT offset; + rtx home; + + while (block) + { + 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) + { + if (XEXP (home, 0) != frame_pointer_rtx + || boundary != 0) + goto next; + + XEXP (home, 0) = plus_constant (frame_pointer_rtx, + push_size); + + /* mark */ + XEXP (home, 0)->used = 1; + } + + if (GET_CODE (home) == MEM + && GET_CODE (XEXP (home, 0)) == MEM) + { + + /* process for dynamically allocated aray */ + home = XEXP (home, 0); + } + + if (GET_CODE (home) == MEM + && GET_CODE (XEXP (home, 0)) == PLUS + && GET_CODE (XEXP (XEXP (home, 0), 1)) == CONST_INT) + { + offset = AUTO_OFFSET(XEXP (home, 0)); + + if (! XEXP (home, 0)->used + && offset >= boundary) + { + offset += push_size; + XEXP (XEXP (home, 0), 1) = gen_rtx_CONST_INT (VOIDmode, offset); + + /* mark */ + XEXP (home, 0)->used = 1; + } + } + + } + next: + types = TREE_CHAIN(types); + } + + push_frame_in_decls (BLOCK_SUBBLOCKS (block), push_size, boundary); + block = BLOCK_CHAIN (block); + } +} + + +static void +push_frame_in_args (parms, push_size, boundary) + tree parms; + HOST_WIDE_INT push_size, boundary; +{ + rtx home; + HOST_WIDE_INT offset; + + for (; parms; parms = TREE_CHAIN (parms)) + if (DECL_NAME (parms) && TREE_TYPE (parms) != error_mark_node) + { + if (PARM_PASSED_IN_MEMORY (parms) && DECL_NAME (parms)) + { + home = DECL_INCOMING_RTL (parms); + offset = AUTO_OFFSET(XEXP (home, 0)); + + if (XEXP (home, 0)->used || offset < boundary) continue; + + /* the operand related to the sweep variable */ + if (AUTO_BASEPTR (XEXP (home, 0)) == frame_pointer_rtx) + { + 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, boundary) + rtx insn; + HOST_WIDE_INT push_size, boundary; +{ + for (; insn; insn = NEXT_INSN (insn)) + if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN + || GET_CODE (insn) == CALL_INSN) + { + debuginsn = insn; + push_frame_in_operand (PATTERN (insn), push_size, boundary); + + /* push frame in NOTE */ + push_frame_in_operand (REG_NOTES (insn), push_size, boundary); + + /* push frame in CALL EXPR_LIST */ + if (GET_CODE (insn) == CALL_INSN) + push_frame_in_operand (CALL_INSN_FUNCTION_USAGE (insn), push_size, boundary); + } +} + + +static void +push_frame_in_operand (orig, push_size, boundary) + rtx orig; + HOST_WIDE_INT push_size, boundary; +{ + register rtx x = orig; + register enum rtx_code code; + int i, j; + HOST_WIDE_INT offset; + const char *fmt; + + if (x == 0) + return; + + code = GET_CODE (x); + + switch (code) + { + case CONST_INT: + case CONST_DOUBLE: + case CONST: + case SYMBOL_REF: + case CODE_LABEL: + case PC: + case CC0: + case ASM_INPUT: + case ADDR_VEC: + case ADDR_DIFF_VEC: + case RETURN: + case REG: + case ADDRESSOF: + return; + + case SET: + break; + + case MEM: + if (XEXP (x, 0) == frame_pointer_rtx + && boundary == 0) + { + XEXP (x, 0) = plus_constant (frame_pointer_rtx, push_size); + XEXP (x, 0)->used = 1; + return; + } + break; + + case PLUS: + offset = AUTO_OFFSET(x); + + /* Handle special case of frame register plus constant. */ + if (CONSTANT_P (XEXP (x, 1)) + && XEXP (x, 0) == frame_pointer_rtx) + { + if (x->used || abs (offset) < boundary) + return; + + if (offset > 0) + offset += push_size; + else + 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, boundary); + push_frame_of_insns (XEXP (x, 1), push_size, boundary); + push_frame_of_insns (XEXP (x, 2), push_size, boundary); + break; + + default: + break; + } + + /* Scan all subexpressions. */ + fmt = GET_RTX_FORMAT (code); + for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++) + if (*fmt == 'e') + { + if (XEXP (x, i) == frame_pointer_rtx && boundary == 0) + fatal_insn ("push_frame_in_operand", debuginsn); + push_frame_in_operand (XEXP (x, i), push_size, boundary); + } + else if (*fmt == 'E') + for (j = 0; j < XVECLEN (x, i); j++) + push_frame_in_operand (XVECEXP (x, i, j), push_size, boundary); +} + +static void +push_frame_of_reg_equiv_memory_loc (push_size, boundary) + HOST_WIDE_INT push_size, boundary; +{ + int i; + extern rtx *reg_equiv_memory_loc; + + /* This function is processed if the push_frame is called from + global_alloc (or reload) function */ + if (reg_equiv_memory_loc == 0) return; + + for (i=LAST_VIRTUAL_REGISTER+1; i < max_regno; i++) + if (reg_equiv_memory_loc[i]) + { + rtx x = reg_equiv_memory_loc[i]; + int offset; + + if (GET_CODE (x) == MEM + && GET_CODE (XEXP (x, 0)) == PLUS + && XEXP (XEXP (x, 0), 0) == frame_pointer_rtx) + { + offset = AUTO_OFFSET(XEXP (x, 0)); + + if (! XEXP (x, 0)->used + && offset >= boundary) + { + offset += push_size; + XEXP (XEXP (x, 0), 1) = gen_rtx_CONST_INT (VOIDmode, offset); + + /* mark */ + XEXP (x, 0)->used = 1; + } + } + } +} + +static void +push_frame_of_reg_equiv_constant (push_size, boundary) + HOST_WIDE_INT push_size, boundary; +{ + int i; + extern rtx *reg_equiv_constant; + + /* This function is processed if the push_frame is called from + global_alloc (or reload) function */ + if (reg_equiv_constant == 0) return; + + for (i=LAST_VIRTUAL_REGISTER+1; i < max_regno; i++) + if (reg_equiv_constant[i]) + { + rtx x = reg_equiv_constant[i]; + int offset; + + if (GET_CODE (x) == PLUS + && XEXP (x, 0) == frame_pointer_rtx) + { + offset = AUTO_OFFSET(x); + + if (! x->used + && offset >= boundary) + { + offset += push_size; + XEXP (x, 1) = gen_rtx_CONST_INT (VOIDmode, offset); + + /* mark */ + x->used = 1; + } + } + } +} + +static int +check_out_of_frame_access (insn, boundary) + rtx insn; + HOST_WIDE_INT boundary; +{ + for (; insn; insn = NEXT_INSN (insn)) + if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN + || GET_CODE (insn) == CALL_INSN) + { + if (check_out_of_frame_access_in_operand (PATTERN (insn), boundary)) + return TRUE; + } + return FALSE; +} + + +static int +check_out_of_frame_access_in_operand (orig, boundary) + rtx orig; + HOST_WIDE_INT boundary; +{ + register rtx x = orig; + register enum rtx_code code; + int i, j; + const char *fmt; + + if (x == 0) + return FALSE; + + code = GET_CODE (x); + + switch (code) + { + case CONST_INT: + case CONST_DOUBLE: + case CONST: + case SYMBOL_REF: + case CODE_LABEL: + case PC: + case CC0: + case ASM_INPUT: + case ADDR_VEC: + case ADDR_DIFF_VEC: + case RETURN: + case REG: + case ADDRESSOF: + return FALSE; + + case MEM: + if (XEXP (x, 0) == frame_pointer_rtx) + if (0 < boundary) return TRUE; + break; + + case PLUS: + /* Handle special case of frame register plus constant. */ + if (CONSTANT_P (XEXP (x, 1)) + && XEXP (x, 0) == frame_pointer_rtx) + { + if (0 <= AUTO_OFFSET(x) + && AUTO_OFFSET(x) < boundary) return TRUE; + return FALSE; + } + /* + process further subtree: + Example: (plus:SI (mem/s:SI (plus:SI (reg:SI 17) (const_int 8))) + (const_int 5)) + */ + break; + + case CALL_PLACEHOLDER: + if (check_out_of_frame_access (XEXP (x, 0), boundary)) return TRUE; + if (check_out_of_frame_access (XEXP (x, 1), boundary)) return TRUE; + if (check_out_of_frame_access (XEXP (x, 2), boundary)) return TRUE; + break; + + default: + break; + } + + /* Scan all subexpressions. */ + fmt = GET_RTX_FORMAT (code); + for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++) + if (*fmt == 'e') + { + if (check_out_of_frame_access_in_operand (XEXP (x, i), boundary)) + return TRUE; + } + else if (*fmt == 'E') + for (j = 0; j < XVECLEN (x, i); j++) + if (check_out_of_frame_access_in_operand (XVECEXP (x, i, j), boundary)) + return TRUE; + + return FALSE; +} +#endif diff --git a/gnu/egcs/gcc/protector.h b/gnu/egcs/gcc/protector.h new file mode 100644 index 00000000000..8e7061a955f --- /dev/null +++ b/gnu/egcs/gcc/protector.h @@ -0,0 +1,38 @@ +/* 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 Pmode +#define UNITS_PER_GUARD MAX(BIGGEST_ALIGNMENT / BITS_PER_UNIT, GET_MODE_SIZE (GUARD_m)) + +#ifndef L_stack_smash_handler + +/* insert a guard variable before a character buffer and change the order + of pointer variables, character buffers and pointer arguments */ + +extern void prepare_stack_protection PARAMS ((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)); + +#endif diff --git a/gnu/egcs/gcc/reload1.c b/gnu/egcs/gcc/reload1.c index f16ed109875..ac64db8eaf4 100644 --- a/gnu/egcs/gcc/reload1.c +++ b/gnu/egcs/gcc/reload1.c @@ -1,5 +1,6 @@ /* Reload pseudo regs into hard regs for insns that require hard regs. - Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc. + Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, + 1998, 1999, 2000 Free Software Foundation, Inc. This file is part of GNU CC. @@ -38,6 +39,7 @@ Boston, MA 02111-1307, USA. */ #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 @@ -420,9 +422,13 @@ static void clear_reload_reg_in_use PROTO((int, int, enum reload_type, enum machine_mode)); static int reload_reg_free_p PROTO((int, int, enum reload_type)); static int reload_reg_free_for_value_p PROTO((int, int, enum reload_type, rtx, rtx, int, int)); +static int free_for_value_p PROTO((int, enum machine_mode, int, + enum reload_type, rtx, rtx, + int, int)); static int reload_reg_reaches_end_p PROTO((int, int, enum reload_type)); static int allocate_reload_reg PROTO((struct insn_chain *, int, int, int)); +static int conflicts_with_override PROTO((rtx)); static void choose_reload_regs PROTO((struct insn_chain *)); static void merge_assigned_reloads PROTO((rtx)); static void emit_reload_insns PROTO((struct insn_chain *)); @@ -2419,7 +2425,7 @@ alter_reg (i, from_reg) 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. @@ -4518,7 +4524,10 @@ forget_old_reloads_1 (x, ignored) reload reg in the current instruction. */ if (n_reloads == 0 || ! TEST_HARD_REG_BIT (reg_is_output_reload, regno + i)) - CLEAR_HARD_REG_BIT (reg_reloaded_valid, regno + i); + { + CLEAR_HARD_REG_BIT (reg_reloaded_valid, regno + i); + spill_reg_store[regno + i] = 0; + } } /* Since value of X has changed, @@ -4577,6 +4586,8 @@ reload_reg_class_lower (r1p, r2p) /* The following HARD_REG_SETs indicate when each hard register is used for a reload of various parts of the current insn. */ +/* If reg is unavailable for all reloads. */ +static HARD_REG_SET reload_reg_unavailable; /* If reg is in use as a reload reg for a RELOAD_OTHER reload. */ static HARD_REG_SET reload_reg_used; /* If reg is in use for a RELOAD_FOR_INPUT_ADDRESS reload for operand I. */ @@ -4799,8 +4810,8 @@ reload_reg_free_p (regno, opnum, type) { int i; - /* In use for a RELOAD_OTHER means it's not available for anything. */ - if (TEST_HARD_REG_BIT (reload_reg_used, regno)) + if (TEST_HARD_REG_BIT (reload_reg_used, regno) + || TEST_HARD_REG_BIT (reload_reg_unavailable, regno)) return 0; switch (type) @@ -5133,7 +5144,7 @@ reloads_conflict (r1, r2) return (r2_type == RELOAD_FOR_INSN || r2_type == RELOAD_FOR_OUTPUT || ((r2_type == RELOAD_FOR_OUTPUT_ADDRESS || r2_type == RELOAD_FOR_OUTADDR_ADDRESS) - && r2_opnum >= r1_opnum)); + && r2_opnum <= r1_opnum)); case RELOAD_FOR_INSN: return (r2_type == RELOAD_FOR_INPUT || r2_type == RELOAD_FOR_OUTPUT @@ -5171,25 +5182,8 @@ rtx reload_override_in[MAX_RELOADS]; or -1 if we did not need a register for this reload. */ int reload_spill_index[MAX_RELOADS]; -/* Return 1 if the value in reload reg REGNO, as used by a reload - needed for the part of the insn specified by OPNUM and TYPE, - may be used to load VALUE into it. - - Other read-only reloads with the same value do not conflict - unless OUT is non-zero and these other reloads have to live while - output reloads live. - If OUT is CONST0_RTX, this is a special case: it means that the - test should not be for using register REGNO as reload register, but - for copying from register REGNO into the reload register. +/* Subroutine of free_for_value_p, used to check a single register. */ - RELOADNUM is the number of the reload we want to load this value for; - a reload does not conflict with itself. - - When IGNORE_ADDRESS_RELOADS is set, we can not have conflicts with - reloads that load an address for the very reload we are considering. - - The caller has to make sure that there is no conflict with the return - register. */ static int reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum, ignore_address_reloads) @@ -5201,9 +5195,20 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum, int ignore_address_reloads; { int time1; + /* Set if we see an input reload that must not share its reload register + with any new earlyclobber, but might otherwise share the reload + register with an output or input-output reload. */ + int check_earlyclobber = 0; int i; int copy = 0; + /* ??? reload_reg_used is abused to hold the registers that are not + available as spill registers, including hard registers that are + earlyclobbered in asms. As a temporary measure, reject anything + in reload_reg_used. */ + if (TEST_HARD_REG_BIT (reload_reg_unavailable, regno)) + return 0; + if (out == const0_rtx) { copy = 1; @@ -5228,7 +5233,8 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum, switch (type) { case RELOAD_FOR_OTHER_ADDRESS: - time1 = 0; + /* RELOAD_FOR_OTHER_ADDRESS conflicts with RELOAD_OTHER reloads. */ + time1 = copy ? 0 : 1; break; case RELOAD_OTHER: time1 = copy ? 1 : MAX_RECOG_OPERANDS * 5 + 5; @@ -5320,6 +5326,7 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum, break; case RELOAD_FOR_INPUT: time2 = reload_opnum[i] * 4 + 4; + check_earlyclobber = 1; break; /* reload_opnum[i] * 4 + 4 <= (MAX_RECOG_OPERAND - 1) * 4 + 4 == MAX_RECOG_OPERAND * 4 */ @@ -5332,6 +5339,7 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum, break; case RELOAD_FOR_OPERAND_ADDRESS: time2 = MAX_RECOG_OPERANDS * 4 + 2; + check_earlyclobber = 1; break; case RELOAD_FOR_INSN: time2 = MAX_RECOG_OPERANDS * 4 + 3; @@ -5360,6 +5368,9 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum, if (! reload_in[i] || rtx_equal_p (reload_in[i], value)) { time2 = MAX_RECOG_OPERANDS * 4 + 4; + /* Earlyclobbered outputs must conflict with inputs. */ + if (earlyclobber_operand_p (reload_out[i])) + time2 = MAX_RECOG_OPERANDS * 4 + 3; break; } time2 = 1; @@ -5382,9 +5393,71 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum, } } } + + /* Earlyclobbered outputs must conflict with inputs. */ + if (check_earlyclobber && out && earlyclobber_operand_p (out)) + return 0; + + return 1; +} + +/* Return 1 if the value in reload reg REGNO, as used by a reload + needed for the part of the insn specified by OPNUM and TYPE, + may be used to load VALUE into it. + + MODE is the mode in which the register is used, this is needed to + determine how many hard regs to test. + + Other read-only reloads with the same value do not conflict + unless OUT is non-zero and these other reloads have to live while + output reloads live. + If OUT is CONST0_RTX, this is a special case: it means that the + test should not be for using register REGNO as reload register, but + for copying from register REGNO into the reload register. + + RELOADNUM is the number of the reload we want to load this value for; + a reload does not conflict with itself. + + When IGNORE_ADDRESS_RELOADS is set, we can not have conflicts with + reloads that load an address for the very reload we are considering. + + The caller has to make sure that there is no conflict with the return + register. */ + +static int +free_for_value_p (regno, mode, opnum, type, value, out, reloadnum, + ignore_address_reloads) + int regno; + enum machine_mode mode; + int opnum; + enum reload_type type; + rtx value, out; + int reloadnum; + int ignore_address_reloads; +{ + int nregs = HARD_REGNO_NREGS (regno, mode); + while (nregs-- > 0) + if (! reload_reg_free_for_value_p (regno + nregs, opnum, type, value, out, + reloadnum, ignore_address_reloads)) + return 0; return 1; } +/* Determine whether the reload reg X overlaps any rtx'es used for + overriding inheritance. Return nonzero if so. */ + +static int +conflicts_with_override (x) + rtx x; +{ + int i; + for (i = 0; i < n_reloads; i++) + if (reload_override_in[i] + && reg_overlap_mentioned_p (x, reload_override_in[i])) + return 1; + return 0; +} + /* Find a spill register to use as a reload register for reload R. LAST_RELOAD is non-zero if this is the last reload for the insn being processed. @@ -5465,11 +5538,10 @@ allocate_reload_reg (chain, r, last_reload, noerror) /* We check reload_reg_used to make sure we don't clobber the return register. */ && ! TEST_HARD_REG_BIT (reload_reg_used, regnum) - && reload_reg_free_for_value_p (regnum, - reload_opnum[r], - reload_when_needed[r], - reload_in[r], - reload_out[r], r, 1))) + && free_for_value_p (regnum, reload_mode[r], + reload_opnum[r], + reload_when_needed[r], + reload_in[r], reload_out[r], r, 1))) && TEST_HARD_REG_BIT (reg_class_contents[class], regnum) && HARD_REGNO_MODE_OK (regnum, reload_mode[r]) /* Look first for regs to share, then for unshared. But @@ -5662,7 +5734,7 @@ choose_reload_regs (chain) CLEAR_HARD_REG_SET (reload_reg_used_in_outaddr_addr[i]); } - IOR_COMPL_HARD_REG_SET (reload_reg_used, chain->used_spill_regs); + COMPL_HARD_REG_SET (reload_reg_unavailable, chain->used_spill_regs); #if 0 /* Not needed, now that we can always retry without inheritance. */ /* See if we have more mandatory reloads than spill regs. @@ -5924,10 +5996,9 @@ choose_reload_regs (chain) && (reload_nregs[r] == max_group_size || ! TEST_HARD_REG_BIT (reg_class_contents[(int) group_class], i)) - && reload_reg_free_for_value_p (i, reload_opnum[r], - reload_when_needed[r], - reload_in[r], - const0_rtx, r, 1)) + && free_for_value_p (i, reload_mode[r], reload_opnum[r], + reload_when_needed[r], reload_in[r], + const0_rtx, r, 1)) { /* If a group is needed, verify that all the subsequent registers still have their values intact. */ @@ -5961,9 +6032,11 @@ choose_reload_regs (chain) break; if (i1 != n_earlyclobbers - || ! (reload_reg_free_for_value_p - (i, reload_opnum[r], reload_when_needed[r], - reload_in[r], reload_out[r], r, 1)) + || ! (free_for_value_p (i, reload_mode[r], + reload_opnum[r], + reload_when_needed[r], + reload_in[r], + reload_out[r], r, 1)) /* Don't use it if we'd clobber a pseudo reg. */ || (TEST_HARD_REG_BIT (reg_used_in_insn, i) && reload_out[r] @@ -5985,9 +6058,12 @@ choose_reload_regs (chain) && rtx_equal_p (reload_out[r], reload_reg_rtx[r]))) { - reload_override_in[r] = last_reg; - reload_inheritance_insn[r] - = reg_reloaded_insn[i]; + if (! reload_optional[r]) + { + reload_override_in[r] = last_reg; + reload_inheritance_insn[r] + = reg_reloaded_insn[i]; + } } else { @@ -6065,10 +6141,11 @@ choose_reload_regs (chain) and of the desired class. */ if (equiv != 0 && ((TEST_HARD_REG_BIT (reload_reg_used_at_all, regno) - && ! reload_reg_free_for_value_p (regno, reload_opnum[r], - reload_when_needed[r], - reload_in[r], - reload_out[r], r, 1)) + && ! free_for_value_p (regno, reload_mode[r], + reload_opnum[r], + reload_when_needed[r], + reload_in[r], reload_out[r], r, + 1)) || ! TEST_HARD_REG_BIT (reg_class_contents[(int) reload_reg_class[r]], regno))) equiv = 0; @@ -6086,7 +6163,8 @@ choose_reload_regs (chain) if (reg_overlap_mentioned_for_reload_p (equiv, reload_earlyclobbers[i])) { - reload_override_in[r] = equiv; + if (! reload_optional[r]) + reload_override_in[r] = equiv; equiv = 0; break; } @@ -6097,7 +6175,8 @@ choose_reload_regs (chain) In particular, we then can't use EQUIV for a RELOAD_FOR_OUTPUT_ADDRESS reload. */ - if (equiv != 0 && regno_clobbered_p (regno, insn)) + if (equiv != 0 && regno_clobbered_p (regno, insn, + reload_mode[r], 0)) { switch (reload_when_needed[r]) { @@ -6109,13 +6188,32 @@ choose_reload_regs (chain) case RELOAD_OTHER: case RELOAD_FOR_INPUT: case RELOAD_FOR_OPERAND_ADDRESS: - reload_override_in[r] = equiv; + if (! reload_optional[r]) + reload_override_in[r] = equiv; /* Fall through. */ default: equiv = 0; break; } } + else if (regno_clobbered_p (regno, insn, reload_mode[r], 1)) + switch (reload_when_needed[r]) + { + case RELOAD_FOR_OTHER_ADDRESS: + case RELOAD_FOR_INPADDR_ADDRESS: + case RELOAD_FOR_INPUT_ADDRESS: + case RELOAD_FOR_OPADDR_ADDR: + case RELOAD_FOR_OPERAND_ADDRESS: + case RELOAD_FOR_INPUT: + break; + case RELOAD_OTHER: + if (! reload_optional[r]) + reload_override_in[r] = equiv; + /* Fall through. */ + default: + equiv = 0; + break; + } /* If we found an equivalent reg, say no code need be generated to load it, and use it as our reload reg. */ @@ -6276,13 +6374,12 @@ choose_reload_regs (chain) check_reg = reload_override_in[r]; else continue; - if (! reload_reg_free_for_value_p (true_regnum (check_reg), - reload_opnum[r], - reload_when_needed[r], - reload_in[r], - (reload_inherited[r] - ? reload_out[r] : const0_rtx), - r, 1)) + if (! free_for_value_p (true_regnum (check_reg), reload_mode[r], + reload_opnum[r], reload_when_needed[r], + reload_in[r], + (reload_inherited[r] + ? reload_out[r] : const0_rtx), + r, 1)) { if (pass) continue; @@ -6330,6 +6427,7 @@ choose_reload_regs (chain) clear_reload_reg_in_use (regno, reload_opnum[j], reload_when_needed[j], reload_mode[j]); reload_reg_rtx[j] = 0; + reload_spill_index[j] = -1; } /* Record which pseudos and which spill regs have output reloads. */ @@ -6638,10 +6736,10 @@ emit_reload_insns (chain) /* Don't use OLDEQUIV if any other reload changes it at an earlier stage of this insn or at this stage. */ - if (! reload_reg_free_for_value_p (regno, reload_opnum[j], - reload_when_needed[j], - reload_in[j], const0_rtx, j, - 0)) + if (! free_for_value_p (regno, reload_mode[j], + reload_opnum[j], + reload_when_needed[j], + reload_in[j], const0_rtx, j, 0)) oldequiv = 0; /* If it is no cheaper to copy from OLDEQUIV into the @@ -6791,11 +6889,10 @@ emit_reload_insns (chain) && dead_or_set_p (insn, old) /* This is unsafe if some other reload uses the same reg first. */ - && reload_reg_free_for_value_p (REGNO (reloadreg), - reload_opnum[j], - reload_when_needed[j], - old, reload_out[j], - j, 0)) + && ! conflicts_with_override (reloadreg) + && free_for_value_p (REGNO (reloadreg), reload_mode[j], + reload_opnum[j], reload_when_needed[j], + old, reload_out[j], j, 0)) { rtx temp = PREV_INSN (insn); while (temp && GET_CODE (temp) == NOTE) @@ -7104,7 +7201,8 @@ emit_reload_insns (chain) /* We don't need to test full validity of last_regno for inherit here; we only want to know if the store actually matches the pseudo. */ - if (reg_reloaded_contents[last_regno] == pseudo_no + if (TEST_HARD_REG_BIT (reg_reloaded_valid, last_regno) + && reg_reloaded_contents[last_regno] == pseudo_no && spill_reg_store[last_regno] && rtx_equal_p (pseudo, spill_reg_stored_to[last_regno])) delete_output_reload (insn, j, last_regno); @@ -7280,7 +7378,7 @@ emit_reload_insns (chain) || !(set = single_set (insn)) || rtx_equal_p (old, SET_DEST (set)) || !reg_mentioned_p (old, SET_SRC (set)) - || !regno_clobbered_p (REGNO (old), insn)) + || !regno_clobbered_p (REGNO (old), insn, reload_mode[j], 0)) gen_reload (old, reloadreg, reload_opnum[j], reload_when_needed[j]); } @@ -7819,9 +7917,13 @@ gen_reload (out, in, opnum, type) DEFINE_PEEPHOLE should be specified that recognizes the sequence we emit below. */ + code = (int) add_optab->handlers[(int) GET_MODE (out)].insn_code; + if (CONSTANT_P (op1) || GET_CODE (op1) == MEM || GET_CODE (op1) == SUBREG || (GET_CODE (op1) == REG - && REGNO (op1) >= FIRST_PSEUDO_REGISTER)) + && REGNO (op1) >= FIRST_PSEUDO_REGISTER) + || (code != CODE_FOR_nothing + && ! (*insn_operand_predicate[code][2]) (op1, insn_operand_mode[code][2]))) tem = op0, op0 = op1, op1 = tem; gen_reload (out, op0, opnum, type); diff --git a/gnu/egcs/gcc/toplev.c b/gnu/egcs/gcc/toplev.c index 7b7f6a87fcb..56e9ab0a44f 100644 --- a/gnu/egcs/gcc/toplev.c +++ b/gnu/egcs/gcc/toplev.c @@ -772,6 +772,13 @@ int flag_instrument_function_entry_exit = 0; 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 { @@ -979,7 +986,11 @@ lang_independent_options f_options[] = {"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" }, }; #define NUM_ELEM(a) (sizeof (a) / sizeof ((a)[0])) @@ -1258,7 +1269,9 @@ lang_independent_options W_options[] = {"uninitialized", &warn_uninitialized, 1, "Warn about unitialized automatic variables"}, {"inline", &warn_inline, 1, - "Warn when an inlined function cannot be inlined"} + "Warn when an inlined function cannot be inlined"}, + {"stack-protector", &warn_stack_protector, 1, + "Warn when disabling stack protector for some reason"} }; /* Output files for assembler code (real compiler output) @@ -3646,6 +3659,8 @@ rest_of_compilation (decl) insns = get_insns (); + if (flag_propolice_protection) prepare_stack_protection (); + /* Dump the rtl code if we are dumping rtl. */ if (rtl_dump) diff --git a/gnu/usr.bin/ld/rtld/rtld.c b/gnu/usr.bin/ld/rtld/rtld.c index 0fb7e6184b8..f100fb1ae25 100644 --- a/gnu/usr.bin/ld/rtld/rtld.c +++ b/gnu/usr.bin/ld/rtld/rtld.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtld.c,v 1.29 2002/09/07 01:25:34 marc Exp $ */ +/* $OpenBSD: rtld.c,v 1.30 2002/12/02 09:00:11 miod Exp $ */ /* $NetBSD: rtld.c,v 1.43 1996/01/14 00:35:17 pk Exp $ */ /* * Copyright (c) 1993 Paul Kranenburg @@ -59,6 +59,18 @@ #include "ld.h" +/* + * Stack protector dummies. + * Ideally, a scheme to compile these stubs from libc should be used, but + * this would end up dragging too much code from libc here. + */ +long __guard[8] = {0,0,0,0,0,0,0,0}; +void +__stack_smash_handler(char func[], int damaged) +{ + _exit(127); +} + #ifndef MAP_ANON #define MAP_ANON 0 #define anon_open() do { \ diff --git a/lib/libc/shlib_version b/lib/libc/shlib_version index 59ded4be242..05b2c1e70b5 100644 --- a/lib/libc/shlib_version +++ b/lib/libc/shlib_version @@ -1,2 +1,2 @@ major=28 -minor=8 # note: remember to update minor in ../libc_r/shlib_version +minor=9 # note: remember to update minor in ../libc_r/shlib_version diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc index 90862148b46..26ac85b48ff 100644 --- a/lib/libc/sys/Makefile.inc +++ b/lib/libc/sys/Makefile.inc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.inc,v 1.61 2002/11/10 03:21:02 fgsch Exp $ +# $OpenBSD: Makefile.inc,v 1.62 2002/12/02 09:00:14 miod Exp $ # $NetBSD: Makefile.inc,v 1.35 1995/10/16 23:49:07 jtc Exp $ # @(#)Makefile.inc 8.1 (Berkeley) 6/17/93 @@ -25,6 +25,9 @@ SRCS+= ftruncate.c lseek.c mmap.c ptrace.c semctl.c truncate.c \ timer_create.c timer_delete.c timer_getoverrun.c timer_gettime.c \ timer_settime.c pread.c preadv.c pwrite.c pwritev.c +# stack protector helper functions +SRCS+= stack_protector.c + # modules with default implementations on all architectures: ASM= accept.o access.o acct.o adjtime.o bind.o chdir.o chflags.o chmod.o \ chown.o chroot.o clock_gettime.o clock_settime.o clock_getres.o \ diff --git a/lib/libc/sys/stack_protector.c b/lib/libc/sys/stack_protector.c new file mode 100644 index 00000000000..a51fe1e463f --- /dev/null +++ b/lib/libc/sys/stack_protector.c @@ -0,0 +1,87 @@ +/* $OpenBSD: stack_protector.c,v 1.1 2002/12/02 09:00:15 miod Exp $ */ + +/* + * Copyright (c) 2002 Hiroaki Etoh, Federico G. Schwindt, and Miodrag Vallat. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#if defined(LIBC_SCCS) && !defined(list) +static char rcsid[] = "$OpenBSD: stack_protector.c,v 1.1 2002/12/02 09:00:15 miod Exp $"; +#endif + +#include +#include +#include + +long __guard[8] = {0,0,0,0,0,0,0,0}; +static void __guard_setup(void) __attribute__ ((constructor)); +void __stack_smash_handler(char func[], int damaged __attribute__((unused))); + +static void +__guard_setup(void) +{ + int i, mib[2]; + size_t len; + + if (__guard[0] != 0) + return; + + mib[0] = CTL_KERN; + mib[1] = KERN_ARND; + + len = 4; + for (i = 0; i < sizeof(__guard) / 4; i++) { + if (sysctl(mib, 2, (char*)&((int*)__guard)[i], + &len, NULL, 0) == -1) + break; + } + + if (i < sizeof(__guard) / 4) { + /* If sysctl was unsuccessful, use 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) +{ + struct syslog_data sdata = SYSLOG_DATA_INIT; + const char message[] = "stack overflow in function %s"; + struct sigaction sa; + + /* this may fail on a chroot jail, though luck */ + syslog_r(LOG_CRIT, &sdata, message, func); + + bzero(sa, sizeof(struct sigaction)); + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = SIG_DFL; + sigaction(SIGABRT, &sa, NULL); + + kill(getpid(), SIGABRT); + + _exit(127); +} diff --git a/lib/libc_r/shlib_version b/lib/libc_r/shlib_version index e29c46e3713..e941ec1f045 100644 --- a/lib/libc_r/shlib_version +++ b/lib/libc_r/shlib_version @@ -1,2 +1,2 @@ major=6 -minor=8 +minor=9 diff --git a/libexec/ld.so/util.c b/libexec/ld.so/util.c index 62790011ce8..a6f1447f676 100644 --- a/libexec/ld.so/util.c +++ b/libexec/ld.so/util.c @@ -1,4 +1,4 @@ -/* $OpenBSD: util.c,v 1.9 2002/07/24 04:11:10 deraadt Exp $ */ +/* $OpenBSD: util.c,v 1.10 2002/12/02 09:00:18 miod Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -37,6 +37,18 @@ #include #include "archdep.h" +/* + * Stack protector dummies. + * Ideally, a scheme to compile these stubs from libc should be used, but + * this would end up dragging too much code from libc here. + */ +long __guard[8] = {0,0,0,0,0,0,0,0}; +void +stack_smash_handler(char func[], int damaged) +{ + _dl_exit(127); +} + /* * Static vars usable after bootstrapping. */ diff --git a/sys/arch/alpha/conf/Makefile.alpha b/sys/arch/alpha/conf/Makefile.alpha index 47f2425d94e..930fa5d9e18 100644 --- a/sys/arch/alpha/conf/Makefile.alpha +++ b/sys/arch/alpha/conf/Makefile.alpha @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.alpha,v 1.25 2002/08/09 20:24:41 miod Exp $ +# $OpenBSD: Makefile.alpha,v 1.26 2002/12/02 09:00:21 miod Exp $ # $NetBSD: Makefile.alpha,v 1.27 1996/12/01 06:12:25 jonathan Exp $ # Makefile for OpenBSD @@ -38,7 +38,7 @@ CPPFLAGS= ${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL -Dalpha CDIAGFLAGS?= -Werror -Wall -Wstrict-prototypes -Wmissing-prototypes \ -Wno-uninitialized -Wno-format -Wno-main -CMACHFLAGS= -mno-fp-regs +CMACHFLAGS= -mno-fp-regs -fno-stack-protector COPTS?= -O2 CFLAGS= ${DEBUG} ${CDIAGFLAGS} ${CMACHFLAGS} ${COPTS} ${PIPE} AFLAGS= -traditional -D_LOCORE diff --git a/sys/arch/alpha/stand/Makefile.inc b/sys/arch/alpha/stand/Makefile.inc index 1264f2a431d..d71f2ca141c 100644 --- a/sys/arch/alpha/stand/Makefile.inc +++ b/sys/arch/alpha/stand/Makefile.inc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.inc,v 1.6 2001/02/03 03:22:47 art Exp $ +# $OpenBSD: Makefile.inc,v 1.7 2002/12/02 09:00:22 miod Exp $ # $NetBSD: Makefile.inc,v 1.8 1997/04/06 08:39:38 cgd Exp $ .include # for ELF_TOOLCHAIN definition @@ -20,3 +20,4 @@ CPPFLAGS+= -D_STANDALONE XCPPFLAGS+= -DHEAP_LIMIT="0x${HEAP_LIMIT}" +CFLAGS+= -fno-stack-protector diff --git a/sys/arch/amiga/conf/Makefile.amiga b/sys/arch/amiga/conf/Makefile.amiga index fc3b2875945..2043585b546 100644 --- a/sys/arch/amiga/conf/Makefile.amiga +++ b/sys/arch/amiga/conf/Makefile.amiga @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.amiga,v 1.32 2002/08/09 20:24:43 miod Exp $ +# $OpenBSD: Makefile.amiga,v 1.33 2002/12/02 09:00:22 miod Exp $ # $NetBSD: Makefile.amiga,v 1.60 1997/07/23 10:19:42 is Exp $ # Makefile for OpenBSD @@ -50,7 +50,7 @@ CMACHFLAGS= -m68020 .else CMACHFLAGS= -m68060 -Wa,-m68030 .endif -CMACHFLAGS+= -msoft-float +CMACHFLAGS+= -msoft-float -fno-stack-protector COPTS?= -O2 CFLAGS= ${DEBUG} ${COPTS} ${CWARNFLAGS} ${CMACHFLAGS} ${PIPE} diff --git a/sys/arch/amiga/stand/binpatch/Makefile b/sys/arch/amiga/stand/binpatch/Makefile index 71c609261ba..7377c0aa588 100644 --- a/sys/arch/amiga/stand/binpatch/Makefile +++ b/sys/arch/amiga/stand/binpatch/Makefile @@ -1,10 +1,11 @@ -# $OpenBSD: Makefile,v 1.5 2000/02/12 15:29:05 espie Exp $ +# $OpenBSD: Makefile,v 1.6 2002/12/02 09:00:22 miod Exp $ # $NetBSD: Makefile,v 1.6 1996/09/27 03:23:12 chopps Exp $ .if ${MACHINE} == "amiga" PROG=binpatch BINDIR=/sbin LDFLAGS+=-static +CFLAGS+= -fno-stack-protector .else NOPROG=Yes .endif diff --git a/sys/arch/amiga/stand/boot/Makefile b/sys/arch/amiga/stand/boot/Makefile index f101ec86bad..16e33064893 100644 --- a/sys/arch/amiga/stand/boot/Makefile +++ b/sys/arch/amiga/stand/boot/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.6 2000/02/12 15:29:06 espie Exp $ +# $OpenBSD: Makefile,v 1.7 2002/12/02 09:00:22 miod Exp $ NOPROG= installboot MAN=installboot.8 @@ -39,6 +39,7 @@ INCPATH= -I${.CURDIR} -I${.CURDIR}/../.. -I${S} -I${S}/lib/libsa COPTIM= -O -fomit-frame-pointer -fno-function-cse -Wa,-l -m68060 \ -Wa,-m68030 CFLAGS= ${COPTIM} ${INCPATH} ${DEFS} +CFLAGS+= -fno-stack-protector COPTS+= -Wall -Wstrict-prototypes BOOTBLOCKS= xxboot # XXX fdboot is too large at the moment. diff --git a/sys/arch/amiga/stand/loadbsd/Makefile b/sys/arch/amiga/stand/loadbsd/Makefile index bf93cb95b8c..e81d493d99b 100644 --- a/sys/arch/amiga/stand/loadbsd/Makefile +++ b/sys/arch/amiga/stand/loadbsd/Makefile @@ -1,7 +1,8 @@ -# $OpenBSD: Makefile,v 1.4 1999/09/09 21:25:13 espie Exp $ +# $OpenBSD: Makefile,v 1.5 2002/12/02 09:00:22 miod Exp $ CC = gcc CFLAGS = -m68030 -Wall -O3 -fomit-frame-pointer -D__progname=program_name -msmall-code -resident +CFLAGS+= -fno-stack-protector OBJS1 = loadbsd.o poolmem.o getopt.o sleep.o vers.o openlibs_stub.o OBJS2 = loadbsd.o poolmem.o vers_ixemul.o openlibs_ixemul.o diff --git a/sys/arch/amiga/stand/loadkmap/Makefile b/sys/arch/amiga/stand/loadkmap/Makefile index daf487ccae0..3a6858b3454 100644 --- a/sys/arch/amiga/stand/loadkmap/Makefile +++ b/sys/arch/amiga/stand/loadkmap/Makefile @@ -1,10 +1,11 @@ -# $OpenBSD: Makefile,v 1.8 2000/02/13 13:15:23 espie Exp $ +# $OpenBSD: Makefile,v 1.9 2002/12/02 09:00:22 miod Exp $ # $NetBSD: Makefile,v 1.5 1996/09/27 03:23:13 chopps Exp $ .if ${MACHINE}=="amiga" PROG=loadkmap BINDIR=/usr/sbin SUBDIR=din es fr sw us +CFLAGS+= -fno-stack-protector .else NOPROG=Yes .endif diff --git a/sys/arch/hp300/conf/Makefile.hp300 b/sys/arch/hp300/conf/Makefile.hp300 index 5cbe14603fe..e4aff570362 100644 --- a/sys/arch/hp300/conf/Makefile.hp300 +++ b/sys/arch/hp300/conf/Makefile.hp300 @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.hp300,v 1.28 2002/08/09 20:24:43 miod Exp $ +# $OpenBSD: Makefile.hp300,v 1.29 2002/12/02 09:00:22 miod Exp $ # $NetBSD: Makefile.hp300,v 1.54 1997/04/01 23:16:41 scottr Exp $ # Makefile for OpenBSD @@ -44,7 +44,7 @@ CPPFLAGS= ${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL \ -Dmc68020 -Dhp300 CWARNFLAGS= -Werror -Wall -Wstrict-prototypes -Wmissing-prototypes \ -Wno-uninitialized -Wno-format -Wno-main -CMACHFLAGS= -msoft-float +CMACHFLAGS= -msoft-float -fno-stack-protector COPTS?= -O2 CFLAGS= ${DEBUG} ${COPTS} ${CWARNFLAGS} ${CMACHFLAGS} ${PIPE} AFLAGS= -x assembler-with-cpp -traditional-cpp -D_LOCORE diff --git a/sys/arch/hp300/stand/Makefile.inc b/sys/arch/hp300/stand/Makefile.inc index b1b016609d6..524af1b2d99 100644 --- a/sys/arch/hp300/stand/Makefile.inc +++ b/sys/arch/hp300/stand/Makefile.inc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.inc,v 1.3 1999/08/16 09:43:07 downsj Exp $ +# $OpenBSD: Makefile.inc,v 1.4 2002/12/02 09:00:23 miod Exp $ # $NetBSD: Makefile.inc,v 1.7 1997/05/12 07:43:18 thorpej Exp $ BINDIR= /usr/mdec @@ -6,6 +6,8 @@ BINDIR= /usr/mdec # RELOC=FFF00000 allows for boot prog up to FF000 (1044480) bytes long RELOC= FFF00000 +CFLAGS+= -fno-stack-protector + CPPFLAGS+= -DDCACONSOLE -DAPCICONSOLE -DITECONSOLE -DDCMCONSOLE CPPFLAGS+= -DHIL_KEYBOARD -DUK_KEYBOARD CPPFLAGS+= -DDOMAIN_KEYBOARD diff --git a/sys/arch/hppa/conf/Makefile.hppa b/sys/arch/hppa/conf/Makefile.hppa index f15c89fb047..7f3a469df63 100644 --- a/sys/arch/hppa/conf/Makefile.hppa +++ b/sys/arch/hppa/conf/Makefile.hppa @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.hppa,v 1.16 2002/08/09 20:24:43 miod Exp $ +# $OpenBSD: Makefile.hppa,v 1.17 2002/12/02 09:00:23 miod Exp $ # Makefile for OpenBSD # @@ -42,7 +42,8 @@ CPPFLAGS= ${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL \ -Dhppa CWARNFLAGS= -Werror -Wall -Wstrict-prototypes -Wno-uninitialized \ -Wno-format -Wno-main -CMACHFLAGS= -mfast-indirect-calls -mportable-runtime -mno-space-regs +CMACHFLAGS= -mfast-indirect-calls -mportable-runtime -mno-space-regs \ + -fno-stack-protector COPTS?= -Os CFLAGS= ${DEBUG} ${COPTS} ${CWARNFLAGS} ${CMACHFLAGS} ${PIPE} AFLAGS= -x assembler-with-cpp -traditional-cpp -D_LOCORE diff --git a/sys/arch/hppa/stand/Makefile.inc b/sys/arch/hppa/stand/Makefile.inc index 93652e1ea78..5893f128ea9 100644 --- a/sys/arch/hppa/stand/Makefile.inc +++ b/sys/arch/hppa/stand/Makefile.inc @@ -1,6 +1,7 @@ -# $OpenBSD: Makefile.inc,v 1.8 2002/03/15 21:22:50 mickey Exp $ +# $OpenBSD: Makefile.inc,v 1.9 2002/12/02 09:00:23 miod Exp $ CFLAGS=${DEBUG} -Os -Wall -Werror +CFLAGS+= -fno-stack-protector CPPFLAGS+=-I${S} -I. -I${.CURDIR} SACFLAGS=-nostdinc -fno-builtin -D_STANDALONE -I${SADIR}/libsa SACFLAGS+=-mdisable-fpregs -mfast-indirect-calls -mpa-risc-1-0 diff --git a/sys/arch/i386/conf/Makefile.i386 b/sys/arch/i386/conf/Makefile.i386 index 23f19662ce8..f1791a9e38d 100644 --- a/sys/arch/i386/conf/Makefile.i386 +++ b/sys/arch/i386/conf/Makefile.i386 @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.i386,v 1.31 2002/08/09 20:24:43 miod Exp $ +# $OpenBSD: Makefile.i386,v 1.32 2002/12/02 09:00:23 miod Exp $ # $NetBSD: Makefile.i386,v 1.67 1996/05/11 16:12:11 mycroft Exp $ # Makefile for OpenBSD @@ -48,6 +48,7 @@ CMACHFLAGS= -march=i486 .else CMACHFLAGS= .endif +CMACHFLAGS+= -fno-stack-protector COPTS?= -O2 CFLAGS= ${DEBUG} ${CDIAGFLAGS} ${CMACHFLAGS} ${COPTS} ${PIPE} diff --git a/sys/arch/i386/stand/Makefile.inc b/sys/arch/i386/stand/Makefile.inc index adebaa94ec6..7b6147b3e42 100644 --- a/sys/arch/i386/stand/Makefile.inc +++ b/sys/arch/i386/stand/Makefile.inc @@ -1,6 +1,7 @@ -# $OpenBSD: Makefile.inc,v 1.29 2000/10/09 20:25:10 mickey Exp $ +# $OpenBSD: Makefile.inc,v 1.30 2002/12/02 09:00:23 miod Exp $ CFLAGS=${DEBUG} -Os -Wall -Werror +CFLAGS+= -fno-stack-protector CPPFLAGS+=-I${S} -I${SADIR}/libsa -I. -I${.CURDIR} SACFLAGS=-D_STANDALONE DEBUGLIBS=no diff --git a/sys/arch/mac68k/conf/Makefile.mac68k b/sys/arch/mac68k/conf/Makefile.mac68k index 7911e0935e0..a44dada32e3 100644 --- a/sys/arch/mac68k/conf/Makefile.mac68k +++ b/sys/arch/mac68k/conf/Makefile.mac68k @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.mac68k,v 1.27 2002/08/09 20:24:43 miod Exp $ +# $OpenBSD: Makefile.mac68k,v 1.28 2002/12/02 09:00:24 miod Exp $ # $NetBSD: Makefile.mac68k,v 1.53 1997/04/15 06:11:38 scottr Exp $ # Makefile for OpenBSD @@ -44,7 +44,7 @@ CPPFLAGS= ${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL \ -Dmc68020 -Dmac68k CWARNFLAGS= -Werror -Wall -Wstrict-prototypes -Wmissing-prototypes \ -Wno-uninitialized -Wno-format -Wno-main -CMACHFLAGS= -msoft-float +CMACHFLAGS= -msoft-float -fno-stack-protector COPTS?= -O2 CFLAGS= ${DEBUG} ${COPTS} ${CWARNFLAGS} ${CMACHFLAGS} ${PIPE} AFLAGS= -x assembler-with-cpp -traditional-cpp -D_LOCORE diff --git a/sys/arch/macppc/conf/Makefile.macppc b/sys/arch/macppc/conf/Makefile.macppc index a10be37b0f5..2ccb0bf9075 100644 --- a/sys/arch/macppc/conf/Makefile.macppc +++ b/sys/arch/macppc/conf/Makefile.macppc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.macppc,v 1.8 2002/08/09 20:24:43 miod Exp $ +# $OpenBSD: Makefile.macppc,v 1.9 2002/12/02 09:00:24 miod Exp $ # # Makefile for OpenBSD PowerPC # @@ -44,7 +44,7 @@ CPPFLAGS= ${INCLUDES} ${IDENT} -D_KERNEL \ -Dmacppc CWARNFLAGS= -Werror -Wall -Wstrict-prototypes -Wmissing-prototypes \ -Wno-uninitialized -Wno-format -Wno-main -CMACHFLAGS= -msoft-float -Wa,-m7400 +CMACHFLAGS= -msoft-float -Wa,-m7400 -fno-stack-protector COPTS?= -O2 CFLAGS= ${DEBUG} ${CWARNFLAGS} ${CMACHFLAGS} ${COPTS} ${PIPE} AFLAGS= -D_LOCORE diff --git a/sys/arch/macppc/stand/Makefile.inc b/sys/arch/macppc/stand/Makefile.inc index 00a156e277b..df2635a710d 100644 --- a/sys/arch/macppc/stand/Makefile.inc +++ b/sys/arch/macppc/stand/Makefile.inc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.inc,v 1.2 2001/10/03 17:10:06 drahn Exp $ +# $OpenBSD: Makefile.inc,v 1.3 2002/12/02 09:00:24 miod Exp $ # $NetBSD: Makefile.inc,v 1.1 1996/09/30 16:34:59 ws Exp $ .if !defined(__stand_makefile_inc) @@ -22,6 +22,7 @@ INCLUDES+= -I. -I$(.OBJDIR) -I$(.CURDIR)/.. -I$(S)/arch -I$(S) INCLUDES+= -I$(S)/lib/libsa DEFS+= -DSTANDALONE -DFIREPOWERBUGS CFLAGS+= $(INCLUDES) $(DEFS) $(EXTRACFLAGS) +CFLAGS+= -fno-stack-protector LDFLAGS?= -X -N -Ttext $(RELOC) -e $(ENTRY) cleandir: diff --git a/sys/arch/mvme68k/conf/Makefile.mvme68k b/sys/arch/mvme68k/conf/Makefile.mvme68k index 0baa9ba4309..26dd4ab3205 100644 --- a/sys/arch/mvme68k/conf/Makefile.mvme68k +++ b/sys/arch/mvme68k/conf/Makefile.mvme68k @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.mvme68k,v 1.17 2002/08/09 20:24:43 miod Exp $ +# $OpenBSD: Makefile.mvme68k,v 1.18 2002/12/02 09:00:24 miod Exp $ # This makefile is constructed from a machine description: # config machineid @@ -47,7 +47,7 @@ CMACHFLAGS= -m68020 .else CMACHFLAGS= -m68060 -Wa,-m68030 .endif -CMACHFLAGS+= -msoft-float +CMACHFLAGS+= -msoft-float -fno-stack-protector COPTS?= -O2 CFLAGS= ${DEBUG} ${COPTS} ${CWARNFLAGS} ${CMACHFLAGS} ${PIPE} diff --git a/sys/arch/mvme68k/stand/Makefile.inc b/sys/arch/mvme68k/stand/Makefile.inc index a3f02f3f7c9..e622ccccb11 100644 --- a/sys/arch/mvme68k/stand/Makefile.inc +++ b/sys/arch/mvme68k/stand/Makefile.inc @@ -1,3 +1,4 @@ -# $OpenBSD: Makefile.inc,v 1.3 2000/03/03 00:54:52 todd Exp $ +# $OpenBSD: Makefile.inc,v 1.4 2002/12/02 09:00:24 miod Exp $ MDEC_DIR?=/usr/mdec +CFLAGS+= -fno-stack-protector diff --git a/sys/arch/mvme88k/conf/Makefile.mvme88k b/sys/arch/mvme88k/conf/Makefile.mvme88k index f3926027d93..ceb32a9e28c 100644 --- a/sys/arch/mvme88k/conf/Makefile.mvme88k +++ b/sys/arch/mvme88k/conf/Makefile.mvme88k @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.mvme88k,v 1.21 2002/08/09 20:24:43 miod Exp $ +# $OpenBSD: Makefile.mvme88k,v 1.22 2002/12/02 09:00:24 miod Exp $ # # Makefile for OpenBSD # @@ -41,7 +41,7 @@ INCLUDES= -nostdinc -I. -I$S/arch -I$S CPPFLAGS= ${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL -Dmvme88k -Dm88k CWARNFLAGS= -Wall -Werror -Wmissing-prototypes \ -Wno-uninitialized -Wno-format -Wno-main -Wstrict-prototypes -CMACHFLAGS= +CMACHFLAGS= -fno-stack-protector COPTS?= -O CFLAGS= ${DEBUG} ${CWARNFLAGS} ${CMACHFLAGS} ${COPTS} ${PIPE} AFLAGS= -x assembler-with-cpp -traditional-cpp -D_LOCORE ${CMACHFLAGS} diff --git a/sys/arch/mvme88k/stand/Makefile.inc b/sys/arch/mvme88k/stand/Makefile.inc index 5a0216193f1..8955102edea 100644 --- a/sys/arch/mvme88k/stand/Makefile.inc +++ b/sys/arch/mvme88k/stand/Makefile.inc @@ -1,6 +1,7 @@ -# $OpenBSD: Makefile.inc,v 1.4 2001/03/27 21:13:51 miod Exp $ +# $OpenBSD: Makefile.inc,v 1.5 2002/12/02 09:00:25 miod Exp $ MDEC_DIR?=/usr/mdec +CFLAGS+= -fno-stack-protector # Load addresses for first and second stage bootstraps STAGE1_RELOC=0x009F0000 diff --git a/sys/arch/mvmeppc/conf/Makefile.mvmeppc b/sys/arch/mvmeppc/conf/Makefile.mvmeppc index e215c41ee48..0e217bf98b1 100644 --- a/sys/arch/mvmeppc/conf/Makefile.mvmeppc +++ b/sys/arch/mvmeppc/conf/Makefile.mvmeppc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.mvmeppc,v 1.9 2002/08/09 20:24:43 miod Exp $ +# $OpenBSD: Makefile.mvmeppc,v 1.10 2002/12/02 09:00:25 miod Exp $ # # Makefile for OpenBSD PowerPC # @@ -44,7 +44,7 @@ CPPFLAGS= ${INCLUDES} ${IDENT} -D_KERNEL \ -Dpowerpc -D__mvmeppc__ CWARNFLAGS= -Werror -Wall -Wstrict-prototypes -Wmissing-prototypes \ -Wno-uninitialized -Wno-format -Wno-main -CMACHFLAGS= -msoft-float -Wa,-m7400 +CMACHFLAGS= -msoft-float -Wa,-m7400 -fno-stack-protector COPTS?= -O2 CFLAGS= ${DEBUG} ${CWARNFLAGS} ${CMACHFLAGS} ${COPTS} ${PIPE} AFLAGS= -D_LOCORE diff --git a/sys/arch/mvmeppc/stand/Makefile.inc b/sys/arch/mvmeppc/stand/Makefile.inc index 5404d746abb..e14f6de44eb 100644 --- a/sys/arch/mvmeppc/stand/Makefile.inc +++ b/sys/arch/mvmeppc/stand/Makefile.inc @@ -1,6 +1,7 @@ -# $OpenBSD: Makefile.inc,v 1.1 2001/06/26 21:57:58 smurph Exp $ +# $OpenBSD: Makefile.inc,v 1.2 2002/12/02 09:00:25 miod Exp $ MDEC_DIR?=/usr/mdec +CFLAGS+= -fno-stack-protector # Load addresses for first and second stage bootstraps STAGE1_RELOC=4000 diff --git a/sys/arch/sparc/conf/Makefile.sparc b/sys/arch/sparc/conf/Makefile.sparc index 7aaad1f1522..60f2fa9160d 100644 --- a/sys/arch/sparc/conf/Makefile.sparc +++ b/sys/arch/sparc/conf/Makefile.sparc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.sparc,v 1.26 2002/09/23 01:43:14 art Exp $ +# $OpenBSD: Makefile.sparc,v 1.27 2002/12/02 09:00:25 miod Exp $ # $NetBSD: Makefile.sparc,v 1.32.4.1 1996/06/12 20:26:32 pk Exp $ # Makefile for OpenBSD @@ -49,6 +49,7 @@ CMACHFLAGS= -mcpu=supersparc .else CMACHFLAGS= .endif +CMACHFLAGS+= -fno-stack-protector CFLAGS= ${DEBUG} -O2 ${CDIAGFLAGS} ${CMACHFLAGS} ${COPTS} ${PIPE} # add `-mno-fpu' to work around gcc (last noticed in v2.7.2) bug diff --git a/sys/arch/sparc/stand/Makefile.inc b/sys/arch/sparc/stand/Makefile.inc index b261d414d95..1c1d5e4417d 100644 --- a/sys/arch/sparc/stand/Makefile.inc +++ b/sys/arch/sparc/stand/Makefile.inc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.inc,v 1.10 2000/07/18 01:28:48 deraadt Exp $ +# $OpenBSD: Makefile.inc,v 1.11 2002/12/02 09:00:25 miod Exp $ # $NetBSD: Makefile.inc,v 1.5 1996/02/01 22:33:01 mycroft Exp $ BINDIR= /usr/mdec @@ -12,6 +12,8 @@ RELOC_SUN4M= 0x440000 RELOC?= ${RELOC_TEST} RELOC2!= perl -e 'printf "0x%x", ${RELOC_TEST} + 0x40000' +CFLAGS+= -fno-stack-protector + DEFS= -DSTANDALONE -DRELOC=${RELOC} -DSUN4 -DSUN4C -DSUN_BOOTPARAMS ### Figure out what to use for libkern diff --git a/sys/arch/sparc64/conf/Makefile.sparc64 b/sys/arch/sparc64/conf/Makefile.sparc64 index b20c4628ed4..bdb41113bfb 100644 --- a/sys/arch/sparc64/conf/Makefile.sparc64 +++ b/sys/arch/sparc64/conf/Makefile.sparc64 @@ -22,7 +22,7 @@ CPPFLAGS= ${INCLUDES} ${IDENT} -D_KERNEL CDIAGFLAGS= -Werror -Wall -Wstrict-prototypes -Wmissing-prototypes \ -Wno-uninitialized -Wno-format -Wno-main -CMACHFLAGS= -Wa,-Av9a, -mno-fpu +CMACHFLAGS= -Wa,-Av9a, -mno-fpu -fno-stack-protector CFLAGS= ${DEBUG} -O2 ${CDIAGFLAGS} ${CMACHFLAGS} ${COPTS} ${PIPE} AFLAGS= -x assembler-with-cpp -traditional-cpp -D_LOCORE -Wa,-Av9a diff --git a/sys/arch/sparc64/stand/Makefile.inc b/sys/arch/sparc64/stand/Makefile.inc index 2b8f6616321..ecb8d086a2d 100644 --- a/sys/arch/sparc64/stand/Makefile.inc +++ b/sys/arch/sparc64/stand/Makefile.inc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.inc,v 1.2 2001/08/20 19:55:33 jason Exp $ +# $OpenBSD: Makefile.inc,v 1.3 2002/12/02 09:00:25 miod Exp $ # $NetBSD: Makefile.inc,v 1.7 2000/08/20 14:57:16 mrg Exp $ .ifndef __INCLUDED_STAND_MAKEFILE_INC @@ -13,6 +13,7 @@ BINDIR= /usr/mdec CPPFLAGS+= -D_STANDALONE -DSUN4U CPPFLAGS+= -I. +CFLAGS+= -fno-stack-protector CFLAGS+= -msoft-float .endif diff --git a/sys/arch/sun3/conf/Makefile.sun3 b/sys/arch/sun3/conf/Makefile.sun3 index dff3e30ec28..c3410ec93c7 100644 --- a/sys/arch/sun3/conf/Makefile.sun3 +++ b/sys/arch/sun3/conf/Makefile.sun3 @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.sun3,v 1.32 2002/08/09 20:24:43 miod Exp $ +# $OpenBSD: Makefile.sun3,v 1.33 2002/12/02 09:00:26 miod Exp $ # $NetBSD: Makefile.sun3,v 1.51 1996/09/09 21:07:08 mycroft Exp $ # Makefile for OpenBSD @@ -44,7 +44,7 @@ CPPFLAGS= ${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL \ -Dmc68020 -Dsun3 CWARNFLAGS= -Werror -Wall -Wstrict-prototypes -Wmissing-prototypes \ -Wno-uninitialized -Wno-format -Wno-main -CMACHFLAGS= -m68020 -msoft-float +CMACHFLAGS= -m68020 -msoft-float -fno-stack-protector COPTS?= -O2 CFLAGS= ${DEBUG} ${COPTS} ${CWARNFLAGS} ${CMACHFLAGS} ${PIPE} AFLAGS= -x assembler-with-cpp -traditional-cpp -D_LOCORE ${CMACHFLAGS} diff --git a/sys/arch/sun3/stand/Makefile.inc b/sys/arch/sun3/stand/Makefile.inc index 55a5079c590..719bd9aeb0c 100644 --- a/sys/arch/sun3/stand/Makefile.inc +++ b/sys/arch/sun3/stand/Makefile.inc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.inc,v 1.5 2001/07/04 08:33:43 niklas Exp $ +# $OpenBSD: Makefile.inc,v 1.6 2002/12/02 09:00:26 miod Exp $ # $NetBSD: Makefile.inc,v 1.6 1995/11/17 23:23:44 gwr Exp $ .if defined(SA_PROG) @@ -10,6 +10,7 @@ S= ${.CURDIR}/../../../.. RELOC?= 240000 DEFS?= -DSTANDALONE INCL?= -I${.CURDIR} -I${.CURDIR}/../libsa -I${S}/lib/libsa -I${S} +CFLAGS+=-fno-stack-protector COPTS?= -msoft-float ${DEFS} ${DBG} ${INCL} LIBSA?= ../libsa diff --git a/sys/arch/vax/boot/Makefile.inc b/sys/arch/vax/boot/Makefile.inc index bbe032e06d2..068de9c7b4d 100644 --- a/sys/arch/vax/boot/Makefile.inc +++ b/sys/arch/vax/boot/Makefile.inc @@ -1,9 +1,10 @@ -# $OpenBSD: Makefile.inc,v 1.3 2002/06/11 09:36:23 hugh Exp $ +# $OpenBSD: Makefile.inc,v 1.4 2002/12/02 09:00:26 miod Exp $ # $NetBSD: Makefile.inc,v 1.6 2002/02/24 01:04:23 matt Exp $ RELOC=0x39F000 .PATH: ${.CURDIR}/../../vax ${.CURDIR}/../common +CFLAGS+= -fno-stack-protector CPPFLAGS+=-I. -I${.CURDIR}/../../../../ -I${.CURDIR}/../../ -I${.CURDIR}/../common -I${.CURDIR}/../../include CPPFLAGS+=-DRELOC=${RELOC} diff --git a/sys/arch/vax/conf/Makefile.vax b/sys/arch/vax/conf/Makefile.vax index 56bdc81a8ef..452c8a84407 100644 --- a/sys/arch/vax/conf/Makefile.vax +++ b/sys/arch/vax/conf/Makefile.vax @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.vax,v 1.19 2002/08/09 20:24:43 miod Exp $ +# $OpenBSD: Makefile.vax,v 1.20 2002/12/02 09:00:26 miod Exp $ # $NetBSD: Makefile.vax,v 1.49 1999/07/26 05:20:49 cgd Exp $ # Makefile for OpenBSD/vax @@ -78,7 +78,8 @@ INCLUDES= -I. -I$S/arch -I$S -nostdinc CPPFLAGS= ${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL \ -D_VAX_INLINE_ CWARNFLAGS?= -Werror -Wall -Wno-main -Wno-format -Wno-uninitialized -CFLAGS= ${DEBUG} ${COPTS} ${CWARNFLAGS} ${PIPE} +CMACHFLAGS= -fno-stack-protector +CFLAGS= ${DEBUG} ${COPTS} ${CWARNFLAGS} ${CMACHFLAGS} ${PIPE} AFLAGS= -x assembler-with-cpp -traditional-cpp -D_LOCORE LINKFLAGS= -N -Ttext 80000000 -e start STRIPFLAGS= -d diff --git a/sys/arch/vax/stand/Makefile.inc b/sys/arch/vax/stand/Makefile.inc index bbe032e06d2..068de9c7b4d 100644 --- a/sys/arch/vax/stand/Makefile.inc +++ b/sys/arch/vax/stand/Makefile.inc @@ -1,9 +1,10 @@ -# $OpenBSD: Makefile.inc,v 1.3 2002/06/11 09:36:23 hugh Exp $ +# $OpenBSD: Makefile.inc,v 1.4 2002/12/02 09:00:26 miod Exp $ # $NetBSD: Makefile.inc,v 1.6 2002/02/24 01:04:23 matt Exp $ RELOC=0x39F000 .PATH: ${.CURDIR}/../../vax ${.CURDIR}/../common +CFLAGS+= -fno-stack-protector CPPFLAGS+=-I. -I${.CURDIR}/../../../../ -I${.CURDIR}/../../ -I${.CURDIR}/../common -I${.CURDIR}/../../include CPPFLAGS+=-DRELOC=${RELOC} -- cgit v1.2.3