Message ID | 20150228164223.GA22402@gmail.com |
---|---|
State | New |
Headers | show |
On 02/28/2015 09:42 AM, H.J. Lu wrote: > @@ -22704,6 +22705,13 @@ For systems that use the GNU C Library, the default is on. > Specify that the assembler should encode SSE instructions with VEX > prefix. The option @option{-mavx} turns this on by default. > > +@item -mcopyreloc-in-pie > +@itemx -mno-copyreloc-in-pie > +@opindex mcopyreloc-in-pie > +Use copy relocations in Position Independent Executable (PIE). It > +requires linker support. This option is turned on by default if linker > +used to build GCC supports it. > + How about: "...if GCC is configured to use a linker that supports these relocations." I assume this is a property of the target linker, and not literally the host linker used to build GCC? -Sandra
On Sat, Feb 28, 2015 at 5:42 PM, H.J. Lu <hjl.tools@gmail.com> wrote: > Ue copy relocation in PIE improves performance. But copy relocation > can't be used to access protected symbols defined in shared libaries > and linker in binutils 2.26 enforces doesn't allow it. GCC doesn't > know if an external definition is protected or not. This option adds > -mcopyreloc-in-pie to give user an option to turn it off to avoid problem > at link-time. OK for trunk? If the option does not work universally for all cases, then the default should be off. Uros.
On Sat, Feb 28, 2015 at 5:42 PM, H.J. Lu <hjl.tools@gmail.com> wrote: > Ue copy relocation in PIE improves performance. But copy relocation > can't be used to access protected symbols defined in shared libaries > and linker in binutils 2.26 enforces doesn't allow it. GCC doesn't > know if an external definition is protected or not. This option adds > -mcopyreloc-in-pie to give user an option to turn it off to avoid problem > at link-time. OK for trunk? I wonder if the linker can fix this up? That is, turn the relocation into a valid one? Richard. > Thanks. > > > H.J. > --- > gcc/ > > PR target/65248 > * config/i386/i386.c (ix86_option_override_internal): Set > flag_copyreloc_in_pie to HAVE_LD_PIE_COPYRELOC if not set. > (legitimate_pic_address_disp_p): Replace HAVE_LD_PIE_COPYRELOC > with flag_copyreloc_in_pie. > * config/i386/i386.opt (mcopyreloc-in-pie): New. > * doc/invoke.texi: Document -mcopyreloc-in-pie. > > gcc/testsuite/ > > PR target/65248 > * gcc.target/i386/pr65248-1.c: New. > * gcc.target/i386/pr65248-2.c: Likewise. > * gcc.target/i386/pr65248-3.c: Likewise. > * gcc.target/i386/pr65248-4.c: Likewise. > --- > gcc/config/i386/i386.c | 6 +++++- > gcc/config/i386/i386.opt | 4 ++++ > gcc/doc/invoke.texi | 10 +++++++++- > gcc/testsuite/gcc.target/i386/pr65248-1.c | 13 +++++++++++++ > gcc/testsuite/gcc.target/i386/pr65248-2.c | 13 +++++++++++++ > gcc/testsuite/gcc.target/i386/pr65248-3.c | 16 ++++++++++++++++ > gcc/testsuite/gcc.target/i386/pr65248-4.c | 16 ++++++++++++++++ > 7 files changed, 76 insertions(+), 2 deletions(-) > create mode 100644 gcc/testsuite/gcc.target/i386/pr65248-1.c > create mode 100644 gcc/testsuite/gcc.target/i386/pr65248-2.c > create mode 100644 gcc/testsuite/gcc.target/i386/pr65248-3.c > create mode 100644 gcc/testsuite/gcc.target/i386/pr65248-4.c > > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c > index bec1324..6768ee8 100644 > --- a/gcc/config/i386/i386.c > +++ b/gcc/config/i386/i386.c > @@ -4248,6 +4248,10 @@ ix86_option_override_internal (bool main_args_p, > #endif > } > > + /* Set the default value for -mcopyreloc-in-pie. */ > + if (opts->x_flag_copyreloc_in_pie == -1) > + opts->x_flag_copyreloc_in_pie = HAVE_LD_PIE_COPYRELOC; > + > if (!(opts_set->x_target_flags & MASK_VZEROUPPER)) > opts->x_target_flags |= MASK_VZEROUPPER; > if (!ix86_tune_features[X86_TUNE_AVX256_UNALIGNED_LOAD_OPTIMAL] > @@ -13230,7 +13234,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_copyreloc_in_pie > && 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 301430c..55c712c 100644 > --- a/gcc/config/i386/i386.opt > +++ b/gcc/config/i386/i386.opt > @@ -826,6 +826,10 @@ mfentry > Target Report Var(flag_fentry) Init(-1) > Emit profiling counter call at function entry before prologue. > > +mcopyreloc-in-pie > +Target Report Var(flag_copyreloc_in_pie) Init(-1) > +Use copy relocations in Position Independent Executable (PIE) > + > mrecord-mcount > Target Report Var(flag_record_mcount) Init(0) > Generate __mcount_loc section with all mcount or __fentry__ calls. > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi > index a87376e..7fd4e77 100644 > --- a/gcc/doc/invoke.texi > +++ b/gcc/doc/invoke.texi > @@ -1078,7 +1078,8 @@ See RS/6000 and PowerPC Options. > -m32 -m64 -mx32 -m16 -mlarge-data-threshold=@var{num} @gol > -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}} > +-malign-data=@var{type} -mstack-protector-guard=@var{guard}} @gol > +-mcopyreloc-in-pie > > @emph{x86 Windows Options} > @gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol > @@ -22704,6 +22705,13 @@ For systems that use the GNU C Library, the default is on. > Specify that the assembler should encode SSE instructions with VEX > prefix. The option @option{-mavx} turns this on by default. > > +@item -mcopyreloc-in-pie > +@itemx -mno-copyreloc-in-pie > +@opindex mcopyreloc-in-pie > +Use copy relocations in Position Independent Executable (PIE). It > +requires linker support. This option is turned on by default if linker > +used to build GCC supports it. > + > @item -mfentry > @itemx -mno-fentry > @opindex mfentry > diff --git a/gcc/testsuite/gcc.target/i386/pr65248-1.c b/gcc/testsuite/gcc.target/i386/pr65248-1.c > new file mode 100644 > index 0000000..91aa6be > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/pr65248-1.c > @@ -0,0 +1,13 @@ > +/* Check that GOTPCREL isn't used to access glob_a. */ > +/* { dg-do compile { target *-*-linux* } } */ > +/* { dg-options "-O2 -fpie -mcopyreloc-in-pie" } */ > + > +extern int glob_a; > + > +int foo () > +{ > + return glob_a; > +} > + > +/* glob_a should never be accessed with a GOTPCREL. */ > +/* { dg-final { scan-assembler-not "glob_a@GOTPCREL" { target { ! ia32 } } } } */ > diff --git a/gcc/testsuite/gcc.target/i386/pr65248-2.c b/gcc/testsuite/gcc.target/i386/pr65248-2.c > new file mode 100644 > index 0000000..dc8445c > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/pr65248-2.c > @@ -0,0 +1,13 @@ > +/* Check that GOTPCREL isn't used to access glob_a. */ > +/* { dg-do compile { target *-*-linux* } } */ > +/* { dg-options "-O2 -fpie -mno-copyreloc-in-pie" } */ > + > +int glob_a; > + > +int foo () > +{ > + return glob_a; > +} > + > +/* glob_a should never be accessed with a GOTPCREL. */ > +/* { dg-final { scan-assembler-not "glob_a@GOTPCREL" { target { ! ia32 } } } } */ > diff --git a/gcc/testsuite/gcc.target/i386/pr65248-3.c b/gcc/testsuite/gcc.target/i386/pr65248-3.c > new file mode 100644 > index 0000000..9398fd2 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/pr65248-3.c > @@ -0,0 +1,16 @@ > +/* Check that GOTPCREL is used to access glob_a. */ > +/* { dg-do compile { target *-*-linux* } } */ > +/* { dg-options "-O2 -fpie -mno-copyreloc-in-pie" } */ > + > +extern int glob_a; > + > +int foo () > +{ > + if (&glob_a != 0) > + return glob_a; > + else > + return 0; > +} > + > +/* weak glob_a should be accessed with a GOTPCREL. */ > +/* { dg-final { scan-assembler "glob_a@GOTPCREL" { target { ! ia32 } } } } */ > diff --git a/gcc/testsuite/gcc.target/i386/pr65248-4.c b/gcc/testsuite/gcc.target/i386/pr65248-4.c > new file mode 100644 > index 0000000..6d7cc86 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/pr65248-4.c > @@ -0,0 +1,16 @@ > +/* Check that GOTPCREL is used to access glob_a. */ > +/* { dg-do compile { target *-*-linux* } } */ > +/* { dg-options "-O2 -fpie -mno-copyreloc-in-pie" } */ > + > +extern int glob_a __attribute__((weak)); > + > +int foo () > +{ > + if (&glob_a != 0) > + return glob_a; > + else > + return 0; > +} > + > +/* weak glob_a should be accessed with a GOTPCREL. */ > +/* { dg-final { scan-assembler "glob_a@GOTPCREL" { target { ! ia32 } } } } */ > -- > 2.1.0 > > Reply-To: >
On Mon, Mar 02, 2015 at 09:40:01AM +0100, Richard Biener wrote: > On Sat, Feb 28, 2015 at 5:42 PM, H.J. Lu <hjl.tools@gmail.com> wrote: > > Ue copy relocation in PIE improves performance. But copy relocation > > can't be used to access protected symbols defined in shared libaries > > and linker in binutils 2.26 enforces doesn't allow it. GCC doesn't > > know if an external definition is protected or not. This option adds > > -mcopyreloc-in-pie to give user an option to turn it off to avoid problem > > at link-time. OK for trunk? > > I wonder if the linker can fix this up? That is, turn the relocation into > a valid one? No it can't (*), nor can the dynamic linker. Copy relocs aren't really the issue. They are just a means of initializing a linker generated variable to be used in place of a variable in a shared library. The issue is the linker generated .dynbss variable itself. Consider an ELF executable linked against a shared library, with the executable referencing (but not defining) a variable defined in the shared library. You'd expect that the executable and shared library would both use the same location for the variable. Indeed, that is true. Both executable and shared library use the shared library's variable. Except there is a wrinkle. If the executable is non-PIC, code in the executable will require dynamic text relocations as the variable's address isn't known until run time. To avoid that, some clever person thought: "Why not have the linker define the variable in the executable? ELF run time linking semantics mean the shared library will now use the linker defined copy, so we'll still just be using one copy of the variable". Any everyone was happy. At least until ELF visibility was invented. When ELF visibility comes into play, a variable defined in a shared library with non-default visibility is *not* overridden by another definition in the executable, be it an actual definition or a linker generated one. There is no problem of course if there is an actual definition in the executable. In that case the programmer would expect to see two different variables used. However, if the shared library contains a protected visibility variable, and the linker introduces a copy, then it has changed the meaning of the program. At the source level we only had one definition of the variable, but at run time we'd end up using two different locations. *) Except by avoiding .dynbss copies and hence requiring dynamic text relocations.
On Mon, Mar 2, 2015 at 11:09 AM, Alan Modra <amodra@gmail.com> wrote: > On Mon, Mar 02, 2015 at 09:40:01AM +0100, Richard Biener wrote: >> On Sat, Feb 28, 2015 at 5:42 PM, H.J. Lu <hjl.tools@gmail.com> wrote: >> > Ue copy relocation in PIE improves performance. But copy relocation >> > can't be used to access protected symbols defined in shared libaries >> > and linker in binutils 2.26 enforces doesn't allow it. GCC doesn't >> > know if an external definition is protected or not. This option adds >> > -mcopyreloc-in-pie to give user an option to turn it off to avoid problem >> > at link-time. OK for trunk? >> >> I wonder if the linker can fix this up? That is, turn the relocation into >> a valid one? > > No it can't (*), nor can the dynamic linker. Copy relocs aren't > really the issue. They are just a means of initializing a linker > generated variable to be used in place of a variable in a shared > library. The issue is the linker generated .dynbss variable itself. > > Consider an ELF executable linked against a shared library, with the > executable referencing (but not defining) a variable defined in the > shared library. You'd expect that the executable and shared library > would both use the same location for the variable. Indeed, that is > true. Both executable and shared library use the shared library's > variable. Except there is a wrinkle. If the executable is non-PIC, > code in the executable will require dynamic text relocations as the > variable's address isn't known until run time. To avoid that, some > clever person thought: "Why not have the linker define the variable in > the executable? ELF run time linking semantics mean the shared > library will now use the linker defined copy, so we'll still just be > using one copy of the variable". Any everyone was happy. At least > until ELF visibility was invented. > > When ELF visibility comes into play, a variable defined in a shared > library with non-default visibility is *not* overridden by another > definition in the executable, be it an actual definition or a linker > generated one. There is no problem of course if there is an actual > definition in the executable. In that case the programmer would > expect to see two different variables used. However, if the shared > library contains a protected visibility variable, and the linker > introduces a copy, then it has changed the meaning of the program. At > the source level we only had one definition of the variable, but at > run time we'd end up using two different locations. > > *) Except by avoiding .dynbss copies and hence requiring dynamic text > relocations. Ah, I see (protected visibility has haunted us in the past...). So I think we need to turn the new option off by default. Richard. > -- > Alan Modra > Australia Development Lab, IBM
On Sun, Mar 1, 2015 at 11:48 PM, Uros Bizjak <ubizjak@gmail.com> wrote: > On Sat, Feb 28, 2015 at 5:42 PM, H.J. Lu <hjl.tools@gmail.com> wrote: >> Ue copy relocation in PIE improves performance. But copy relocation >> can't be used to access protected symbols defined in shared libaries >> and linker in binutils 2.26 enforces doesn't allow it. GCC doesn't >> know if an external definition is protected or not. This option adds >> -mcopyreloc-in-pie to give user an option to turn it off to avoid problem >> at link-time. OK for trunk? > > If the option does not work universally for all cases, then the > default should be off. This optimization isn't the real issue. The issue here is protected symbol in shared library. It can never be referenced from a normal executable and works correctly, as Alan explained. It doesn't matter if this option is off or not since it only applies to PIE. You can try the testcase in PR 65248 without -fPIE -pie.
On Mon, Mar 2, 2015 at 4:05 AM, Richard Biener <richard.guenther@gmail.com> wrote: > On Mon, Mar 2, 2015 at 11:09 AM, Alan Modra <amodra@gmail.com> wrote: >> On Mon, Mar 02, 2015 at 09:40:01AM +0100, Richard Biener wrote: >>> On Sat, Feb 28, 2015 at 5:42 PM, H.J. Lu <hjl.tools@gmail.com> wrote: >>> > Ue copy relocation in PIE improves performance. But copy relocation >>> > can't be used to access protected symbols defined in shared libaries >>> > and linker in binutils 2.26 enforces doesn't allow it. GCC doesn't >>> > know if an external definition is protected or not. This option adds >>> > -mcopyreloc-in-pie to give user an option to turn it off to avoid problem >>> > at link-time. OK for trunk? >>> >>> I wonder if the linker can fix this up? That is, turn the relocation into >>> a valid one? >> >> No it can't (*), nor can the dynamic linker. Copy relocs aren't >> really the issue. They are just a means of initializing a linker >> generated variable to be used in place of a variable in a shared >> library. The issue is the linker generated .dynbss variable itself. >> >> Consider an ELF executable linked against a shared library, with the >> executable referencing (but not defining) a variable defined in the >> shared library. You'd expect that the executable and shared library >> would both use the same location for the variable. Indeed, that is >> true. Both executable and shared library use the shared library's >> variable. Except there is a wrinkle. If the executable is non-PIC, ^^^^^^^^^^^^ This is the key here. This optimization makes PIE behave like normal executable. Is it good or bad? >> code in the executable will require dynamic text relocations as the >> variable's address isn't known until run time. To avoid that, some >> clever person thought: "Why not have the linker define the variable in >> the executable? ELF run time linking semantics mean the shared >> library will now use the linker defined copy, so we'll still just be >> using one copy of the variable". Any everyone was happy. At least >> until ELF visibility was invented. >> >> When ELF visibility comes into play, a variable defined in a shared >> library with non-default visibility is *not* overridden by another >> definition in the executable, be it an actual definition or a linker >> generated one. There is no problem of course if there is an actual >> definition in the executable. In that case the programmer would >> expect to see two different variables used. However, if the shared >> library contains a protected visibility variable, and the linker >> introduces a copy, then it has changed the meaning of the program. At >> the source level we only had one definition of the variable, but at >> run time we'd end up using two different locations. >> >> *) Except by avoiding .dynbss copies and hence requiring dynamic text >> relocations. > > Ah, I see (protected visibility has haunted us in the past...). > > So I think we need to turn the new option off by default. >
On Mon, Mar 2, 2015 at 5:39 AM, H.J. Lu <hjl.tools@gmail.com> wrote: > On Mon, Mar 2, 2015 at 4:05 AM, Richard Biener > <richard.guenther@gmail.com> wrote: >> On Mon, Mar 2, 2015 at 11:09 AM, Alan Modra <amodra@gmail.com> wrote: >>> On Mon, Mar 02, 2015 at 09:40:01AM +0100, Richard Biener wrote: >>>> On Sat, Feb 28, 2015 at 5:42 PM, H.J. Lu <hjl.tools@gmail.com> wrote: >>>> > Ue copy relocation in PIE improves performance. But copy relocation >>>> > can't be used to access protected symbols defined in shared libaries >>>> > and linker in binutils 2.26 enforces doesn't allow it. GCC doesn't >>>> > know if an external definition is protected or not. This option adds >>>> > -mcopyreloc-in-pie to give user an option to turn it off to avoid problem >>>> > at link-time. OK for trunk? >>>> >>>> I wonder if the linker can fix this up? That is, turn the relocation into >>>> a valid one? >>> >>> No it can't (*), nor can the dynamic linker. Copy relocs aren't >>> really the issue. They are just a means of initializing a linker >>> generated variable to be used in place of a variable in a shared >>> library. The issue is the linker generated .dynbss variable itself. >>> >>> Consider an ELF executable linked against a shared library, with the >>> executable referencing (but not defining) a variable defined in the >>> shared library. You'd expect that the executable and shared library >>> would both use the same location for the variable. Indeed, that is >>> true. Both executable and shared library use the shared library's >>> variable. Except there is a wrinkle. If the executable is non-PIC, > > ^^^^^^^^^^^^ > This is the key here. This optimization makes PIE behave like normal > executable. Is it good or bad? > >>> code in the executable will require dynamic text relocations as the >>> variable's address isn't known until run time. To avoid that, some >>> clever person thought: "Why not have the linker define the variable in >>> the executable? ELF run time linking semantics mean the shared >>> library will now use the linker defined copy, so we'll still just be >>> using one copy of the variable". Any everyone was happy. At least >>> until ELF visibility was invented. >>> >>> When ELF visibility comes into play, a variable defined in a shared >>> library with non-default visibility is *not* overridden by another >>> definition in the executable, be it an actual definition or a linker >>> generated one. There is no problem of course if there is an actual >>> definition in the executable. In that case the programmer would >>> expect to see two different variables used. However, if the shared >>> library contains a protected visibility variable, and the linker >>> introduces a copy, then it has changed the meaning of the program. At >>> the source level we only had one definition of the variable, but at >>> run time we'd end up using two different locations. >>> >>> *) Except by avoiding .dynbss copies and hence requiring dynamic text >>> relocations. >> >> Ah, I see (protected visibility has haunted us in the past...). >> >> So I think we need to turn the new option off by default. >> By turning this optimization on by default, we make PIE behave the same as normal executable and provide a way to change PIE behavior. This is more consistent to users.
On Mon, Mar 02, 2015 at 05:36:24AM -0800, H.J. Lu wrote: > On Sun, Mar 1, 2015 at 11:48 PM, Uros Bizjak <ubizjak@gmail.com> wrote: > > On Sat, Feb 28, 2015 at 5:42 PM, H.J. Lu <hjl.tools@gmail.com> wrote: > >> Ue copy relocation in PIE improves performance. But copy relocation > >> can't be used to access protected symbols defined in shared libaries > >> and linker in binutils 2.26 enforces doesn't allow it. GCC doesn't > >> know if an external definition is protected or not. This option adds > >> -mcopyreloc-in-pie to give user an option to turn it off to avoid problem > >> at link-time. OK for trunk? > > > > If the option does not work universally for all cases, then the > > default should be off. > > This optimization isn't the real issue. The issue here is protected > symbol in shared library. It can never be referenced from a normal > executable and works correctly, as Alan explained. It doesn't matter > if this option is off or not since it only applies to PIE. You can try > the testcase in PR 65248 without -fPIE -pie. I see things differently. We have an old linker hack to avoid dynamic text relocations in non-PIC executables. This hack doesn't work properly with protected visibility variables in shared libraries. Rather than blaming protected visibility variables, I say the hack is broken. Since you rely on the linker hack for your optimization, you've extended the problem from non-PIC executables to PIEs.. If you want the optimization enabled by default then it probably would have been better to do the optimization entirely in the linker, similar to the way we optimize TLS sequences. Certainly a switch that enables the optimization in the compiler is reasonable if that gives better code, but I can see distros turning it off if you manage to convince Uros and others that the default should be on.
On Tue, Mar 3, 2015 at 12:12 AM, Alan Modra <amodra@gmail.com> wrote: > On Mon, Mar 02, 2015 at 05:36:24AM -0800, H.J. Lu wrote: >> On Sun, Mar 1, 2015 at 11:48 PM, Uros Bizjak <ubizjak@gmail.com> wrote: >> > On Sat, Feb 28, 2015 at 5:42 PM, H.J. Lu <hjl.tools@gmail.com> wrote: >> >> Ue copy relocation in PIE improves performance. But copy relocation >> >> can't be used to access protected symbols defined in shared libaries >> >> and linker in binutils 2.26 enforces doesn't allow it. GCC doesn't >> >> know if an external definition is protected or not. This option adds >> >> -mcopyreloc-in-pie to give user an option to turn it off to avoid problem >> >> at link-time. OK for trunk? >> > >> > If the option does not work universally for all cases, then the >> > default should be off. >> >> This optimization isn't the real issue. The issue here is protected >> symbol in shared library. It can never be referenced from a normal >> executable and works correctly, as Alan explained. It doesn't matter >> if this option is off or not since it only applies to PIE. You can try >> the testcase in PR 65248 without -fPIE -pie. > > I see things differently. We have an old linker hack to avoid dynamic > text relocations in non-PIC executables. This hack doesn't work > properly with protected visibility variables in shared libraries. > Rather than blaming protected visibility variables, I say the hack is > broken. > > Since you rely on the linker hack for your optimization, you've > extended the problem from non-PIC executables to PIEs.. > To make it clear, protected data symbols defined in shared library can never be accessed from normal executables on x86-64 since R_X86_64_PC32 relocation is used to reach externally defined symbols in small and medium models and it will overflow at run-time. On x86-64, R_X86_64_COPY relocation is required to access externally defined data symbols in normal executables unless small and medium models are removed from x86-64 psABI. For x86-64, protected data symbols are impossible.
On Tue, Mar 03, 2015 at 06:20:05AM -0800, H.J. Lu wrote:
> For x86-64, protected data symbols are impossible.
Impossible? This is not even true currently since -fPIC emits code
that looks like it would fully support protected visibiliy variables
in shared libraries.
If you meant to say it is impossible with non-PIC, then even that
statement is going too far. All you'd need to do is have GNU ld emit
dynamic text relocations and possibly add some reloc support to ld.so,
and you'd have support so long as shared libraries loaded within 2G of
the executable. A little horrible, but quite possible.
With some more work, GNU ld could edit the current code sequences
emitted by gcc for non-PIC, to a branch to a patch area where you use
a PIC code sequence.
See also Cary's suggestion at
https://groups.google.com/forum/#!msg/generic-abi/9JX9vdstoVA/g4UGTmRdXJcJ
Or you could just acknowledge that non-PIC has limitations. Another
similar one (same root cause of no GOT indirection) is with weak
symbols, where
extern int foo () __attribute__ ((weak));
if (foo)
foo ();
just doesn't work for foo in a shared library. The non-PIC "if (foo)"
effectively becomes either "if (0)" or "if (1)" at link time, unless
you emit dynamic text relocations or edit the code.
On Tue, Mar 3, 2015 at 7:13 PM, Alan Modra <amodra@gmail.com> wrote: > On Tue, Mar 03, 2015 at 06:20:05AM -0800, H.J. Lu wrote: >> For x86-64, protected data symbols are impossible. > > Impossible? This is not even true currently since -fPIC emits code > that looks like it would fully support protected visibiliy variables > in shared libraries. > > If you meant to say it is impossible with non-PIC, then even that > statement is going too far. All you'd need to do is have GNU ld emit > dynamic text relocations and possibly add some reloc support to ld.so, > and you'd have support so long as shared libraries loaded within 2G of > the executable. A little horrible, but quite possible. > > With some more work, GNU ld could edit the current code sequences > emitted by gcc for non-PIC, to a branch to a patch area where you use > a PIC code sequence. > > See also Cary's suggestion at > https://groups.google.com/forum/#!msg/generic-abi/9JX9vdstoVA/g4UGTmRdXJcJ > > Or you could just acknowledge that non-PIC has limitations. Another > similar one (same root cause of no GOT indirection) is with weak > symbols, where > extern int foo () __attribute__ ((weak)); > if (foo) > foo (); > just doesn't work for foo in a shared library. The non-PIC "if (foo)" > effectively becomes either "if (0)" or "if (1)" at link time, unless > you emit dynamic text relocations or edit the code. > I withdrew my patch. I am working on a new approach for PIE and normal executable.
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index bec1324..6768ee8 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -4248,6 +4248,10 @@ ix86_option_override_internal (bool main_args_p, #endif } + /* Set the default value for -mcopyreloc-in-pie. */ + if (opts->x_flag_copyreloc_in_pie == -1) + opts->x_flag_copyreloc_in_pie = HAVE_LD_PIE_COPYRELOC; + if (!(opts_set->x_target_flags & MASK_VZEROUPPER)) opts->x_target_flags |= MASK_VZEROUPPER; if (!ix86_tune_features[X86_TUNE_AVX256_UNALIGNED_LOAD_OPTIMAL] @@ -13230,7 +13234,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_copyreloc_in_pie && 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 301430c..55c712c 100644 --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -826,6 +826,10 @@ mfentry Target Report Var(flag_fentry) Init(-1) Emit profiling counter call at function entry before prologue. +mcopyreloc-in-pie +Target Report Var(flag_copyreloc_in_pie) Init(-1) +Use copy relocations in Position Independent Executable (PIE) + mrecord-mcount Target Report Var(flag_record_mcount) Init(0) Generate __mcount_loc section with all mcount or __fentry__ calls. diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index a87376e..7fd4e77 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1078,7 +1078,8 @@ See RS/6000 and PowerPC Options. -m32 -m64 -mx32 -m16 -mlarge-data-threshold=@var{num} @gol -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}} +-malign-data=@var{type} -mstack-protector-guard=@var{guard}} @gol +-mcopyreloc-in-pie @emph{x86 Windows Options} @gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol @@ -22704,6 +22705,13 @@ For systems that use the GNU C Library, the default is on. Specify that the assembler should encode SSE instructions with VEX prefix. The option @option{-mavx} turns this on by default. +@item -mcopyreloc-in-pie +@itemx -mno-copyreloc-in-pie +@opindex mcopyreloc-in-pie +Use copy relocations in Position Independent Executable (PIE). It +requires linker support. This option is turned on by default if linker +used to build GCC supports it. + @item -mfentry @itemx -mno-fentry @opindex mfentry diff --git a/gcc/testsuite/gcc.target/i386/pr65248-1.c b/gcc/testsuite/gcc.target/i386/pr65248-1.c new file mode 100644 index 0000000..91aa6be --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr65248-1.c @@ -0,0 +1,13 @@ +/* Check that GOTPCREL isn't used to access glob_a. */ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpie -mcopyreloc-in-pie" } */ + +extern int glob_a; + +int foo () +{ + return glob_a; +} + +/* glob_a should never be accessed with a GOTPCREL. */ +/* { dg-final { scan-assembler-not "glob_a@GOTPCREL" { target { ! ia32 } } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr65248-2.c b/gcc/testsuite/gcc.target/i386/pr65248-2.c new file mode 100644 index 0000000..dc8445c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr65248-2.c @@ -0,0 +1,13 @@ +/* Check that GOTPCREL isn't used to access glob_a. */ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpie -mno-copyreloc-in-pie" } */ + +int glob_a; + +int foo () +{ + return glob_a; +} + +/* glob_a should never be accessed with a GOTPCREL. */ +/* { dg-final { scan-assembler-not "glob_a@GOTPCREL" { target { ! ia32 } } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr65248-3.c b/gcc/testsuite/gcc.target/i386/pr65248-3.c new file mode 100644 index 0000000..9398fd2 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr65248-3.c @@ -0,0 +1,16 @@ +/* Check that GOTPCREL is used to access glob_a. */ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpie -mno-copyreloc-in-pie" } */ + +extern int glob_a; + +int foo () +{ + if (&glob_a != 0) + return glob_a; + else + return 0; +} + +/* weak glob_a should be accessed with a GOTPCREL. */ +/* { dg-final { scan-assembler "glob_a@GOTPCREL" { target { ! ia32 } } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr65248-4.c b/gcc/testsuite/gcc.target/i386/pr65248-4.c new file mode 100644 index 0000000..6d7cc86 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr65248-4.c @@ -0,0 +1,16 @@ +/* Check that GOTPCREL is used to access glob_a. */ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpie -mno-copyreloc-in-pie" } */ + +extern int glob_a __attribute__((weak)); + +int foo () +{ + if (&glob_a != 0) + return glob_a; + else + return 0; +} + +/* weak glob_a should be accessed with a GOTPCREL. */ +/* { dg-final { scan-assembler "glob_a@GOTPCREL" { target { ! ia32 } } } } */