From patchwork Wed Aug 31 20:18:07 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 664675 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3sPcCK0MXYz9ryQ for ; Thu, 1 Sep 2016 06:18:20 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=MAwij34t; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:reply-to:mime-version :content-type; q=dns; s=default; b=fT92LGMZF43ihxMHsd1teZrwrYkvn WBqvvfSe+VSJR6xWxfZXxAK4qPU8fAlscbEHaG5Y+YrBHzOkOdAXng4gBexuBPSE Jd9oIbxUQ8XmsaWC79KcMCypcSBiEGM/LtnqEZt0uF9PfmAS6NXioxDyEORJnoLh C7xKy+UKDUpeS4= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:reply-to:mime-version :content-type; s=default; bh=7rXisSbI3JFyJtZxf1yseoLz4Sg=; b=MAw ij34tAfr5riG3eAKGEwDhtLdOqD9gRp+D+WvurXVEdnaYyykSCaquv8mPgLr9qQG yizHSAg3JHdpyEWNpggC4z/unXdPSDfWCgZ1QFwGH0EgmtMhA/BukxNDEg3fyVSN 2OI5cQUVuj+YVFT1NBf8IDjTe8cyPoNtIgQaOq4M= Received: (qmail 52751 invoked by alias); 31 Aug 2016 20:18:11 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 52741 invoked by uid 89); 31 Aug 2016 20:18:11 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.9 required=5.0 tests=BAYES_00, KAM_LAZY_DOMAIN_SECURITY, KAM_STOCKGEN, NO_DNS_FOR_FROM, RP_MATCHES_RCVD autolearn=no version=3.3.2 spammy=indirectly, sk:general, sk:legitim, risk X-HELO: mga07.intel.com Received: from mga07.intel.com (HELO mga07.intel.com) (134.134.136.100) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 31 Aug 2016 20:18:09 +0000 Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga105.jf.intel.com with ESMTP; 31 Aug 2016 13:18:07 -0700 X-ExtLoop1: 1 Received: from gnu-6.sc.intel.com ([172.25.70.218]) by fmsmga002.fm.intel.com with ESMTP; 31 Aug 2016 13:18:07 -0700 Received: by gnu-6.sc.intel.com (Postfix, from userid 1000) id 32B9FC1AFF; Wed, 31 Aug 2016 13:18:07 -0700 (PDT) Date: Wed, 31 Aug 2016 13:18:07 -0700 From: "H.J. Lu" To: gcc-patches@gcc.gnu.org Cc: Uros Bizjak Subject: [PATCH] PR target/77408: Add -mcopy-reloc to avoid copy relocation Message-ID: <20160831201807.GA2113@intel.com> Reply-To: "H.J. Lu" MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.7.0 (2016-08-17) On x86, copy relocation is used in executable to access external data defined in shared object as if it is defined locally. At run-time, dynamic linker copies symbol data from shared object to executable and its references from shared objects are resolved by GLOB_DAT relocation. Since the copy of symbol data in executable is writable even if the original symbol in shared object is read-only, this is a potential security risk. We can avoid copy relocation by always using PIC model to access external data symbol. If the external symbol is defined locally in executable, linker can optimize instructions on memory operand with GOTPCRELX/GOT32X relocation against external symbol into a different form on immediate operand. Without copy relocation, external symbols in executable are accessed indirectly via the GOT slot. Even when the symbol is defined locally, it is still referenced indirectly through a register. However, there are a few side benefits: 1. Without copy relocation in executable for external symbol defined in shared object, symbol size can be increased while still providing backward binary compatibility. 2. Since protected symbols in shared objects are no longer copied to executable at run-time, references of protected symbols within shared objects can be resolved without GOT. Tested on i686 and x86-64. OK for master? H.J. --- gcc/ PR target/77408 * config/i386/i386.c (ix86_force_load_from_GOT_p): Return true on data symbols for -mno-copy-reloc. (legitimate_pic_address_disp_p): Allow copy relocation in 64-bit PIE only with -mcopy-reloc. * config/i386/i386.opt (mcopy-reloc): New. * doc/invoke.texi: Document -mcopy-reloc. gcc/testsuite/ PR target/77408 * gcc.target/i386/no-copy-reloc-1.c: New test. * gcc.target/i386/no-copy-reloc-2.c: Likewise. * gcc.target/i386/no-copy-reloc-3.c: Likewise. * gcc.target/i386/no-copy-reloc-4.c: Likewise. * gcc.target/i386/no-copy-reloc-5.c: Likewise. * gcc.target/i386/no-copy-reloc-6.c: Likewise. * gcc.target/i386/no-copy-reloc-7.c: Likewise. * gcc.target/i386/no-copy-reloc-8.c: Likewise. * gcc.target/i386/no-copy-reloc-9.c: Likewise. --- gcc/config/i386/i386.c | 22 +++++++++++++++------- gcc/config/i386/i386.opt | 4 ++++ gcc/doc/invoke.texi | 7 ++++++- gcc/testsuite/gcc.target/i386/no-copy-reloc-1.c | 15 +++++++++++++++ gcc/testsuite/gcc.target/i386/no-copy-reloc-2.c | 16 ++++++++++++++++ gcc/testsuite/gcc.target/i386/no-copy-reloc-3.c | 14 ++++++++++++++ gcc/testsuite/gcc.target/i386/no-copy-reloc-4.c | 14 ++++++++++++++ gcc/testsuite/gcc.target/i386/no-copy-reloc-5.c | 15 +++++++++++++++ gcc/testsuite/gcc.target/i386/no-copy-reloc-6.c | 14 ++++++++++++++ gcc/testsuite/gcc.target/i386/no-copy-reloc-7.c | 14 ++++++++++++++ gcc/testsuite/gcc.target/i386/no-copy-reloc-8.c | 12 ++++++++++++ gcc/testsuite/gcc.target/i386/no-copy-reloc-9.c | 12 ++++++++++++ 12 files changed, 151 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/no-copy-reloc-1.c create mode 100644 gcc/testsuite/gcc.target/i386/no-copy-reloc-2.c create mode 100644 gcc/testsuite/gcc.target/i386/no-copy-reloc-3.c create mode 100644 gcc/testsuite/gcc.target/i386/no-copy-reloc-4.c create mode 100644 gcc/testsuite/gcc.target/i386/no-copy-reloc-5.c create mode 100644 gcc/testsuite/gcc.target/i386/no-copy-reloc-6.c create mode 100644 gcc/testsuite/gcc.target/i386/no-copy-reloc-7.c create mode 100644 gcc/testsuite/gcc.target/i386/no-copy-reloc-8.c create mode 100644 gcc/testsuite/gcc.target/i386/no-copy-reloc-9.c diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index a229a73..c84a351 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -15172,13 +15172,20 @@ darwin_local_data_pic (rtx disp) bool ix86_force_load_from_GOT_p (rtx x) { - return ((TARGET_64BIT || HAVE_AS_IX86_GOT32X) - && !TARGET_PECOFF && !TARGET_MACHO - && !flag_plt && !flag_pic - && ix86_cmodel != CM_LARGE - && GET_CODE (x) == SYMBOL_REF - && SYMBOL_REF_FUNCTION_P (x) - && !SYMBOL_REF_LOCAL_P (x)); + if ((TARGET_64BIT || HAVE_AS_IX86_GOT32X) + && !TARGET_PECOFF + && !flag_pic + && !TARGET_MACHO + && ix86_cmodel != CM_LARGE + && GET_CODE (x) == SYMBOL_REF + && !SYMBOL_REF_LOCAL_P (x)) + { + if (SYMBOL_REF_FUNCTION_P (x)) + return !flag_plt; + else + return !flag_copy_reloc; + } + return false; } /* Determine if a given RTX is a valid constant. We already know this @@ -15439,6 +15446,7 @@ legitimate_pic_address_disp_p (rtx disp) else if (!SYMBOL_REF_FAR_ADDR_P (op0) && (SYMBOL_REF_LOCAL_P (op0) || (HAVE_LD_PIE_COPYRELOC + && flag_copy_reloc && flag_pie && !SYMBOL_REF_WEAK (op0) && !SYMBOL_REF_FUNCTION_P (op0))) diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt index 4b75ba8..aef23d9 100644 --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -897,3 +897,7 @@ Attempt to avoid generating instruction sequences containing ret bytes. mgeneral-regs-only Target Report RejectNegative Mask(GENERAL_REGS_ONLY) Var(ix86_target_flags) Save Generate code which uses only the general registers. + +mcopy-reloc +Target Report Var(flag_copy_reloc) Init(1) +Allow copy relocation when accessing external data. diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 87da1f1..71bec15 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1179,7 +1179,7 @@ See RS/6000 and PowerPC Options. -msse2avx -mfentry -mrecord-mcount -mnop-mcount -m8bit-idiv @gol -mavx256-split-unaligned-load -mavx256-split-unaligned-store @gol -malign-data=@var{type} -mstack-protector-guard=@var{guard} @gol --mmitigate-rop -mgeneral-regs-only} +-mmitigate-rop -mgeneral-regs-only -mcopy-reloc} @emph{x86 Windows Options} @gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol @@ -24653,6 +24653,11 @@ Generate code that uses only the general-purpose registers. This prevents the compiler from using floating-point, vector, mask and bound registers. +@item -mcopy-reloc +@opindex mcopy-reloc +Generate code that uses copy relocation in executable to access external +data defined in shared object. It is enabled by default. + @end table These @samp{-m} switches are supported in addition to the above diff --git a/gcc/testsuite/gcc.target/i386/no-copy-reloc-1.c b/gcc/testsuite/gcc.target/i386/no-copy-reloc-1.c new file mode 100644 index 0000000..94de223 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/no-copy-reloc-1.c @@ -0,0 +1,15 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fno-pic -mno-copy-reloc" } */ + +extern int bar; + +int * +foo (void) +{ + return &bar; +} + +/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT," { target { ia32 && got32x_reloc } } } } */ +/* { dg-final { scan-assembler-not "\(mov|lea\)\(l|q\)\[ \t\]*\(\\\$|\)bar\\(%rip\\)" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-not "\(mov|lea\)l\[ \t\]*\(\\\$|\)bar," { target { ia32 && got32x_reloc } } } } */ diff --git a/gcc/testsuite/gcc.target/i386/no-copy-reloc-2.c b/gcc/testsuite/gcc.target/i386/no-copy-reloc-2.c new file mode 100644 index 0000000..90205a4 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/no-copy-reloc-2.c @@ -0,0 +1,16 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fno-pic -mno-copy-reloc" } */ + +extern int bar; +extern int *p; + +void +foo (void) +{ + p = &bar; +} + +/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT," { target { ia32 && got32x_reloc } } } } */ +/* { dg-final { scan-assembler-not "\(mov|lea\)\(l|q\)\[ \t\]*\(\\\$|\)bar\\(%rip\\)" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target { ia32 && got32x_reloc } } } } */ diff --git a/gcc/testsuite/gcc.target/i386/no-copy-reloc-3.c b/gcc/testsuite/gcc.target/i386/no-copy-reloc-3.c new file mode 100644 index 0000000..c8c7cf1 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/no-copy-reloc-3.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fno-pic -mno-copy-reloc" } */ + +static int bar; + +int * +foo (void) +{ + return &bar; +} + +/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*\\\$bar," } } */ +/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-not "movl\[ \t\]*bar@GOT," { target { ia32 && got32x_reloc } } } } */ diff --git a/gcc/testsuite/gcc.target/i386/no-copy-reloc-4.c b/gcc/testsuite/gcc.target/i386/no-copy-reloc-4.c new file mode 100644 index 0000000..fbfa63a --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/no-copy-reloc-4.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fno-pic -mno-copy-reloc" } */ + +extern int bar __attribute__ ((visibility ("hidden"))); + +int * +foo (void) +{ + return &bar; +} + +/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*\\\$bar," } } */ +/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-not "movl\[ \t\]*bar@GOT," { target { ia32 && got32x_reloc } } } } */ diff --git a/gcc/testsuite/gcc.target/i386/no-copy-reloc-5.c b/gcc/testsuite/gcc.target/i386/no-copy-reloc-5.c new file mode 100644 index 0000000..d5ec6a7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/no-copy-reloc-5.c @@ -0,0 +1,15 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fno-pic -mno-copy-reloc" } */ + +extern int bar; + +int +foo (void) +{ + return bar; +} + +/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT," { target { ia32 && got32x_reloc } } } } */ +/* { dg-final { scan-assembler-not "\(mov|lea\)\(l|q\)\[ \t\]*\(\\\$|\)bar\\(%rip\\)" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-not "\(mov|lea\)l\[ \t\]*\(\\\$|\)bar," { target { ia32 && got32x_reloc } } } } */ diff --git a/gcc/testsuite/gcc.target/i386/no-copy-reloc-6.c b/gcc/testsuite/gcc.target/i386/no-copy-reloc-6.c new file mode 100644 index 0000000..9eff04f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/no-copy-reloc-6.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fno-pic -mno-copy-reloc" } */ + +extern int bar; + +int +check (int *p) +{ + return p != &bar; +} + +/* { dg-final { scan-assembler "cmp\(l|q\)\[ \t\]*.*bar@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT," { target { ia32 && got32x_reloc } } } } */ +/* { dg-final { scan-assembler-not "cmp\(l|q\)\[ \t\]*\\\$bar," } } */ diff --git a/gcc/testsuite/gcc.target/i386/no-copy-reloc-7.c b/gcc/testsuite/gcc.target/i386/no-copy-reloc-7.c new file mode 100644 index 0000000..9c1dec0 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/no-copy-reloc-7.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fno-pic -mno-copy-reloc" } */ + +extern int bar[]; + +int * +foo (void) +{ + return &bar[1]; +} + +/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT," { target { ia32 && got32x_reloc } } } } */ +/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar\\+4," } } */ diff --git a/gcc/testsuite/gcc.target/i386/no-copy-reloc-8.c b/gcc/testsuite/gcc.target/i386/no-copy-reloc-8.c new file mode 100644 index 0000000..5d490a7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/no-copy-reloc-8.c @@ -0,0 +1,12 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpie -mno-copy-reloc" } */ + +extern int glob_a; + +int foo () +{ + return glob_a; +} + +/* { dg-final { scan-assembler "glob_a@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler "glob_a@GOT\\(" { target { ia32 } } } } */ diff --git a/gcc/testsuite/gcc.target/i386/no-copy-reloc-9.c b/gcc/testsuite/gcc.target/i386/no-copy-reloc-9.c new file mode 100644 index 0000000..5d490a7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/no-copy-reloc-9.c @@ -0,0 +1,12 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpie -mno-copy-reloc" } */ + +extern int glob_a; + +int foo () +{ + return glob_a; +} + +/* { dg-final { scan-assembler "glob_a@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler "glob_a@GOT\\(" { target { ia32 } } } } */