summaryrefslogtreecommitdiff
path: root/gcc/config/rs6000
diff options
context:
space:
mode:
authoramodra <amodra@138bc75d-0d04-0410-961f-82ee72b054a4>2005-06-01 00:30:26 +0000
committeramodra <amodra@138bc75d-0d04-0410-961f-82ee72b054a4>2005-06-01 00:30:26 +0000
commit197f58fac938c5c4478231d8003942e89c1a439e (patch)
treea43884596f7b3725ff1193f949aede640e008d89 /gcc/config/rs6000
parent0663398065295b8b03266c3f4a1df130d6bdf712 (diff)
downloadgcc-197f58fac938c5c4478231d8003942e89c1a439e.tar.gz
* configure.ac: Add --enable-secureplt.
(HAVE_AS_REL16): Test for R_PPC_REL16 relocs. * config.in: Regenerate. * configure: Regenerate. * config.gcc (powerpc64-*-linux*, powerpc-*-linux*): Add rs6000/secureplt.h to tm_file when enable_secureplt. * doc/invoke.texi (msecure-plt, mbss-plt): Document. * doc/install.texi: Document --enable-targets and --enable-secureplt. Correct xrefs to "Using the GNU Compiler Collection (GCC)". * config/rs6000/secureplt.h: New file. * config/rs6000/sysv4.h (TARGET_SECURE_PLT): Define. (SUBTARGET_OVERRIDE_OPTIONS): Error if -msecure-plt given without assembler support. (CC1_SECURE_PLT_DEFAULT_SPEC): Define. (CC1_SPEC): Delete duplicate mno-sdata. Invoke cc1_secure_plt_default. (SUBTARGET_EXTRA_SPECS): Add cc1_secure_plt_default. * config/rs6000/sysv4.opt (msecure-plt, bss-plt): Add options. * config/rs6000/rs6000.h (TARGET_SECURE_PLT): Define. * config/rs6000/rs6000.c (rs6000_emit_load_toc_table): Handle TARGET_SECURE_PLT got register load sequence. (rs6000_emit_prologue): Call rs6000_emit_load_toc_table when TARGET_SECURE_PLT. (rs6000_elf_declare_function_name): Don't emit toc address offset word when TARGET_SECURE_PLT. * config/rs6000/rs6000.md (elf_high, elf_low): Move past load_toc_*. (load_toc_v4_PIC_1) Enable for TARGET_SECURE_PLT. (load_toc_v4_PIC_3b, load_toc_v4_PIC_3c): New insns. (call, call_value): Mark pic_offset_table_rtx used for sysv pic and TARGET_SECURE_PLT. (call_nonlocal_sysv, call_value_nonlocal_sysv, sibcall_nonlocal_sysv, sibcall_value_nonlocal_sysv): Add 32768 offset when TARGET_SECURE_PLT and -fPIC. * config/rs6000/tramp.asm (trampoline_initial): Use "bcl 20,31". (__trampoline_setup): Likewise. Init r30 before plt call. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@100415 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/rs6000')
-rw-r--r--gcc/config/rs6000/rs6000.c50
-rw-r--r--gcc/config/rs6000/rs6000.h4
-rw-r--r--gcc/config/rs6000/rs6000.md142
-rw-r--r--gcc/config/rs6000/secureplt.h21
-rw-r--r--gcc/config/rs6000/sysv4.h17
-rw-r--r--gcc/config/rs6000/sysv4.opt8
-rw-r--r--gcc/config/rs6000/tramp.asm10
7 files changed, 217 insertions, 35 deletions
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index b50ab946771..265a9ef402f 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -12572,15 +12572,49 @@ rs6000_emit_load_toc_table (int fromprolog)
rtx dest, insn;
dest = gen_rtx_REG (Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM);
- if (TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 1)
+ if (TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI != ABI_AIX && flag_pic)
{
- rtx temp = (fromprolog
- ? gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)
- : gen_reg_rtx (Pmode));
- insn = emit_insn (gen_load_toc_v4_pic_si (temp));
+ char buf[30];
+ rtx lab, tmp1, tmp2, got, tempLR;
+
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
+ lab = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
+ if (flag_pic == 2)
+ got = gen_rtx_SYMBOL_REF (Pmode, toc_label_name);
+ else
+ got = rs6000_got_sym ();
+ tmp1 = tmp2 = dest;
+ if (!fromprolog)
+ {
+ tmp1 = gen_reg_rtx (Pmode);
+ tmp2 = gen_reg_rtx (Pmode);
+ }
+ tempLR = (fromprolog
+ ? gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)
+ : gen_reg_rtx (Pmode));
+ insn = emit_insn (gen_load_toc_v4_PIC_1 (tempLR, lab));
+ if (fromprolog)
+ rs6000_maybe_dead (insn);
+ insn = emit_move_insn (tmp1, tempLR);
+ if (fromprolog)
+ rs6000_maybe_dead (insn);
+ insn = emit_insn (gen_load_toc_v4_PIC_3b (tmp2, tmp1, got, lab));
+ if (fromprolog)
+ rs6000_maybe_dead (insn);
+ insn = emit_insn (gen_load_toc_v4_PIC_3c (dest, tmp2, got, lab));
+ if (fromprolog)
+ rs6000_maybe_dead (insn);
+ }
+ else if (TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 1)
+ {
+ rtx tempLR = (fromprolog
+ ? gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)
+ : gen_reg_rtx (Pmode));
+
+ insn = emit_insn (gen_load_toc_v4_pic_si (tempLR));
if (fromprolog)
rs6000_maybe_dead (insn);
- insn = emit_move_insn (dest, temp);
+ insn = emit_move_insn (dest, tempLR);
if (fromprolog)
rs6000_maybe_dead (insn);
}
@@ -13674,7 +13708,8 @@ rs6000_emit_prologue (void)
/* If we are using RS6000_PIC_OFFSET_TABLE_REGNUM, we need to set it up. */
if ((TARGET_TOC && TARGET_MINIMAL_TOC && get_pool_size () != 0)
- || (DEFAULT_ABI == ABI_V4 && flag_pic == 1
+ || (DEFAULT_ABI == ABI_V4
+ && (flag_pic == 1 || (flag_pic && TARGET_SECURE_PLT))
&& regs_ever_live[RS6000_PIC_OFFSET_TABLE_REGNUM]))
{
/* If emit_load_toc_table will use the link register, we need to save
@@ -17204,6 +17239,7 @@ rs6000_elf_declare_function_name (FILE *file, const char *name, tree decl)
}
if (TARGET_RELOCATABLE
+ && !TARGET_SECURE_PLT
&& (get_pool_size () != 0 || current_function_profile)
&& uses_TOC ())
{
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 79fcc68c3cb..2710dad4dae 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -144,6 +144,10 @@
#define TARGET_POPCNTB 0
#endif
+#ifndef TARGET_SECURE_PLT
+#define TARGET_SECURE_PLT 0
+#endif
+
#define TARGET_32BIT (! TARGET_64BIT)
/* Emit a dtp-relative reference to a TLS variable. */
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index d46f97db899..02847df7c2f 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -7360,26 +7360,6 @@
;; Now define ways of moving data around.
-;; Elf specific ways of loading addresses for non-PIC code.
-;; The output of this could be r0, but we make a very strong
-;; preference for a base register because it will usually
-;; be needed there.
-(define_insn "elf_high"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=b*r")
- (high:SI (match_operand 1 "" "")))]
- "TARGET_ELF && ! TARGET_64BIT"
- "{liu|lis} %0,%1@ha")
-
-(define_insn "elf_low"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
- (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,!*r")
- (match_operand 2 "" "")))]
- "TARGET_ELF && ! TARGET_64BIT"
- "@
- {cal|la} %0,%2@l(%1)
- {ai|addic} %0,%1,%K2")
-
-
;; Set up a register with a value from the GOT table
(define_expand "movsi_got"
@@ -9810,7 +9790,8 @@
[(set (match_operand:SI 0 "register_operand" "=l")
(match_operand:SI 1 "immediate_operand" "s"))
(use (unspec [(match_dup 1)] UNSPEC_TOC))]
- "TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2"
+ "TARGET_ELF && DEFAULT_ABI != ABI_AIX
+ && (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))"
"bcl 20,31,%1\\n%1:"
[(set_attr "type" "branch")
(set_attr "length" "4")])
@@ -9833,6 +9814,22 @@
"{l|lwz} %0,%2-%3(%1)"
[(set_attr "type" "load")])
+(define_insn "load_toc_v4_PIC_3b"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=b")
+ (plus:SI (match_operand:SI 1 "gpc_reg_operand" "r")
+ (high:SI
+ (minus:SI (match_operand:SI 2 "symbol_ref_operand" "s")
+ (match_operand:SI 3 "symbol_ref_operand" "s")))))]
+ "TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI != ABI_AIX && flag_pic"
+ "{cau|addis} %0,%1,%2-%3@ha")
+
+(define_insn "load_toc_v4_PIC_3c"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (minus:SI (match_operand:SI 2 "symbol_ref_operand" "s")
+ (match_operand:SI 3 "symbol_ref_operand" "s"))))]
+ "TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI != ABI_AIX && flag_pic"
+ "{cal|addi} %0,%1,%2-%3@l")
;; If the TOC is shared over a translation unit, as happens with all
;; the kinds of PIC that we support, we need to restore the TOC
@@ -9867,6 +9864,25 @@
rs6000_emit_load_toc_table (FALSE);
DONE;
}")
+
+;; Elf specific ways of loading addresses for non-PIC code.
+;; The output of this could be r0, but we make a very strong
+;; preference for a base register because it will usually
+;; be needed there.
+(define_insn "elf_high"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=b*r")
+ (high:SI (match_operand 1 "" "")))]
+ "TARGET_ELF && ! TARGET_64BIT"
+ "{liu|lis} %0,%1@ha")
+
+(define_insn "elf_low"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
+ (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,!*r")
+ (match_operand 2 "" "")))]
+ "TARGET_ELF && ! TARGET_64BIT"
+ "@
+ {cal|la} %0,%2@l(%1)
+ {ai|addic} %0,%1,%K2")
;; A function pointer under AIX is a pointer to a data area whose first word
;; contains the actual address of the function, whose second word contains a
@@ -9983,6 +9999,25 @@
operands[0] = XEXP (operands[0], 0);
+ if (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT
+ && flag_pic
+ && GET_CODE (operands[0]) == SYMBOL_REF
+ && !SYMBOL_REF_LOCAL_P (operands[0]))
+ {
+ rtx call;
+ rtvec tmp;
+
+ tmp = gen_rtvec (3,
+ gen_rtx_CALL (VOIDmode,
+ gen_rtx_MEM (SImode, operands[0]),
+ operands[1]),
+ gen_rtx_USE (VOIDmode, operands[2]),
+ gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (SImode)));
+ call = emit_call_insn (gen_rtx_PARALLEL (VOIDmode, tmp));
+ use_reg (&CALL_INSN_FUNCTION_USAGE (call), pic_offset_table_rtx);
+ DONE;
+ }
+
if (GET_CODE (operands[0]) != SYMBOL_REF
|| (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (operands[0]))
|| (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[2]) & CALL_LONG) != 0))
@@ -10034,6 +10069,28 @@
operands[1] = XEXP (operands[1], 0);
+ if (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT
+ && flag_pic
+ && GET_CODE (operands[1]) == SYMBOL_REF
+ && !SYMBOL_REF_LOCAL_P (operands[1]))
+ {
+ rtx call;
+ rtvec tmp;
+
+ tmp = gen_rtvec (3,
+ gen_rtx_SET (VOIDmode,
+ operands[0],
+ gen_rtx_CALL (VOIDmode,
+ gen_rtx_MEM (SImode,
+ operands[1]),
+ operands[2])),
+ gen_rtx_USE (VOIDmode, operands[3]),
+ gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (SImode)));
+ call = emit_call_insn (gen_rtx_PARALLEL (VOIDmode, tmp));
+ use_reg (&CALL_INSN_FUNCTION_USAGE (call), pic_offset_table_rtx);
+ DONE;
+ }
+
if (GET_CODE (operands[1]) != SYMBOL_REF
|| (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (operands[1]))
|| (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[3]) & CALL_LONG) != 0))
@@ -10307,7 +10364,18 @@
#if TARGET_MACHO
return output_call(insn, operands, 0, 2);
#else
- return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "bl %z0@plt" : "bl %z0";
+ if (DEFAULT_ABI == ABI_V4 && flag_pic)
+ {
+ if (TARGET_SECURE_PLT && flag_pic == 2)
+ /* The magic 32768 offset here and in the other sysv call insns
+ corresponds to the offset of r30 in .got2, as given by LCTOC1.
+ See sysv4.h:toc_section. */
+ return "bl %z0+32768@plt";
+ else
+ return "bl %z0@plt";
+ }
+ else
+ return "bl %z0";
#endif
}
[(set_attr "type" "branch,branch")
@@ -10352,7 +10420,15 @@
#if TARGET_MACHO
return output_call(insn, operands, 1, 3);
#else
- return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "bl %z1@plt" : "bl %z1";
+ if (DEFAULT_ABI == ABI_V4 && flag_pic)
+ {
+ if (TARGET_SECURE_PLT && flag_pic == 2)
+ return "bl %z1+32768@plt";
+ else
+ return "bl %z1@plt";
+ }
+ else
+ return "bl %z1";
#endif
}
[(set_attr "type" "branch,branch")
@@ -10567,7 +10643,15 @@
else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn (\"creqv 6,6,6\", operands);
- return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z0@plt\" : \"b %z0\";
+ if (DEFAULT_ABI == ABI_V4 && flag_pic)
+ {
+ if (TARGET_SECURE_PLT && flag_pic == 2)
+ return \"b %z0+32768@plt\";
+ else
+ return \"b %z0@plt\";
+ }
+ else
+ return \"b %z0\";
}"
[(set_attr "type" "branch,branch")
(set_attr "length" "4,8")])
@@ -10613,7 +10697,15 @@
else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn (\"creqv 6,6,6\", operands);
- return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z1@plt\" : \"b %z1\";
+ if (DEFAULT_ABI == ABI_V4 && flag_pic)
+ {
+ if (TARGET_SECURE_PLT && flag_pic == 2)
+ return \"b %z1+32768@plt\";
+ else
+ return \"b %z1@plt\";
+ }
+ else
+ return \"b %z1\";
}"
[(set_attr "type" "branch,branch")
(set_attr "length" "4,8")])
diff --git a/gcc/config/rs6000/secureplt.h b/gcc/config/rs6000/secureplt.h
new file mode 100644
index 00000000000..91aea5634bb
--- /dev/null
+++ b/gcc/config/rs6000/secureplt.h
@@ -0,0 +1,21 @@
+/* Default to -msecure-plt.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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.
+
+GCC 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 GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define CC1_SECURE_PLT_DEFAULT_SPEC "-msecure-plt"
diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h
index a8b06aedb16..ed5deb1a55e 100644
--- a/gcc/config/rs6000/sysv4.h
+++ b/gcc/config/rs6000/sysv4.h
@@ -59,6 +59,11 @@ extern enum rs6000_sdata_type rs6000_sdata;
#define TARGET_NO_TOC (! TARGET_TOC)
#define TARGET_NO_EABI (! TARGET_EABI)
+#ifdef HAVE_AS_REL16
+#undef TARGET_SECURE_PLT
+#define TARGET_SECURE_PLT secure_plt
+#endif
+
extern const char *rs6000_abi_name;
extern const char *rs6000_sdata_name;
extern const char *rs6000_tls_size_string; /* For -mtls-size= */
@@ -205,6 +210,11 @@ do { \
error ("-mcall-aixdesc must be big endian"); \
} \
\
+ if (TARGET_SECURE_PLT != secure_plt) \
+ { \
+ error ("-msecure-plt not supported by your assembler"); \
+ } \
+ \
/* Treat -fPIC the same as -mrelocatable. */ \
if (flag_pic > 1 && DEFAULT_ABI != ABI_AIX) \
target_flags |= MASK_RELOCATABLE | MASK_MINIMAL_TOC | MASK_NO_FP_IN_TOC; \
@@ -750,6 +760,10 @@ extern int fixuplabelno;
#define CC1_ENDIAN_DEFAULT_SPEC "%(cc1_endian_big)"
+#ifndef CC1_SECURE_PLT_DEFAULT_SPEC
+#define CC1_SECURE_PLT_DEFAULT_SPEC ""
+#endif
+
/* Pass -G xxx to the compiler and set correct endian mode. */
#define CC1_SPEC "%{G*} \
%{mlittle|mlittle-endian: %(cc1_endian_little); \
@@ -762,7 +776,6 @@ extern int fixuplabelno;
mcall-gnu : -mbig %(cc1_endian_big); \
mcall-i960-old : -mlittle %(cc1_endian_little); \
: %(cc1_endian_default)} \
-%{mno-sdata: -msdata=none } \
%{meabi: %{!mcall-*: -mcall-sysv }} \
%{!meabi: %{!mno-eabi: \
%{mrelocatable: -meabi } \
@@ -774,6 +787,7 @@ extern int fixuplabelno;
%{mcall-openbsd: -mno-eabi }}} \
%{msdata: -msdata=default} \
%{mno-sdata: -msdata=none} \
+%{!mbss-plt: %{!msecure-plt: %(cc1_secure_plt_default)}} \
%{profile: -p}"
/* Don't put -Y P,<path> for cross compilers. */
@@ -1214,6 +1228,7 @@ ncrtn.o%s"
{ "cc1_endian_big", CC1_ENDIAN_BIG_SPEC }, \
{ "cc1_endian_little", CC1_ENDIAN_LITTLE_SPEC }, \
{ "cc1_endian_default", CC1_ENDIAN_DEFAULT_SPEC }, \
+ { "cc1_secure_plt_default", CC1_SECURE_PLT_DEFAULT_SPEC }, \
{ "cpp_os_ads", CPP_OS_ADS_SPEC }, \
{ "cpp_os_yellowknife", CPP_OS_YELLOWKNIFE_SPEC }, \
{ "cpp_os_mvme", CPP_OS_MVME_SPEC }, \
diff --git a/gcc/config/rs6000/sysv4.opt b/gcc/config/rs6000/sysv4.opt
index d826c55dd72..289c6e19e21 100644
--- a/gcc/config/rs6000/sysv4.opt
+++ b/gcc/config/rs6000/sysv4.opt
@@ -139,3 +139,11 @@ Generate 32-bit code
mnewlib
Target RejectNegative
no description yet
+
+msecure-plt
+Target Report RejectNegative Var(secure_plt, 1)
+Generate code to use a non-exec PLT and GOT
+
+mbss-plt
+Target Report RejectNegative Var(secure_plt, 0)
+Generate code for old exec BSS PLT
diff --git a/gcc/config/rs6000/tramp.asm b/gcc/config/rs6000/tramp.asm
index 284f9386074..0c6127d567b 100644
--- a/gcc/config/rs6000/tramp.asm
+++ b/gcc/config/rs6000/tramp.asm
@@ -44,7 +44,7 @@
.align 2
trampoline_initial:
mflr r0
- bl 1f
+ bcl 20,31,1f
.Lfunc = .-trampoline_initial
.long 0 /* will be replaced with function address */
.Lchain = .-trampoline_initial
@@ -67,7 +67,7 @@ trampoline_size = .-trampoline_initial
FUNC_START(__trampoline_setup)
mflr r0 /* save return address */
- bl .LCF0 /* load up __trampoline_initial into r7 */
+ bcl 20,31,.LCF0 /* load up __trampoline_initial into r7 */
.LCF0:
mflr r11
addi r7,r11,trampoline_initial-4-.LCF0 /* trampoline address -4 */
@@ -105,6 +105,12 @@ FUNC_START(__trampoline_setup)
blr
.Labort:
+#if defined SHARED && defined HAVE_AS_REL16
+ bcl 20,31,1f
+1: mflr r30
+ addis r30,r30,_GLOBAL_OFFSET_TABLE_-1b@ha
+ addi r30,r30,_GLOBAL_OFFSET_TABLE_-1b@l
+#endif
bl JUMP_TARGET(abort)
FUNC_END(__trampoline_setup)