On Tue, Feb 8, 2022 at 7:05 PM H.J. Lu via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> On Tue, Feb 8, 2022 at 6:38 PM Hongtao Liu <crazy...@gmail.com> wrote:
> >
> > On Fri, Jan 28, 2022 at 5:53 AM H.J. Lu via Gcc-patches
> > <gcc-patches@gcc.gnu.org> wrote:
> > >
> > > The v3 patch was posted at
> > >
> > > https://gcc.gnu.org/pipermail/gcc-patches/2021-July/574847.html
> > >
> > > There is no progress with repeated pings since then.  Glibc 2.35 and
> > > binutils 2.38 will support GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS.
> > > I'd like to remove copy relocation to improve security and performance
> > > on x86 in GCC 12.  Here is the v4 patch
> >   This patch won't change default behavior for copy relocation(to
> > avoid conflict with existing .so files),
> > just give users an option under which copy relocation can be removed.
> >   The removal of copy relocation is an optimization of the linker(Also
> > improves security), whose
> > patches have been approved and committed to glibc2.35[1], binutils2.38[2].
> >   The compiler part is the final step in completing this optimization.
>
> Thanks for looking into it.  Since the new behavior is off by default and
> none of the maintainers feel comfortable to review my patch,  which is
> related to linker and glibc, for the last 6 months,  now is the good time
> to check it in as any other time.  I will check it in tomorrow.

Shall we move forward with "x86-64: Remove HAVE_LD_PIE_COPYRELOC"
(https://gcc.gnu.org/pipermail/gcc-patches/2021-November/582987.html)?
It's more about the correct behavior for -fpie.

The -mno-direct-extern-access transition will certainly take a long
time, but we should not let that block fixing the GCC 5 x86-64
regression.

> > [1] https://sourceware.org/pipermail/libc-alpha/2021-October/131742.html
> > [2] https://sourceware.org/pipermail/binutils/2021-July/117308.html
> > >
> > > 1. Rename the common option to x86 specific -mdirect-extern-access option.
> > > 2. Remove GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS linker check.
> > > 3. Use the existing GNU property function in x86 backend.
> > >
> > > This new behavior is off by default.  Are there any objections?
> > >
> > > Changes in the v3 patch.
> > >
> > > 1. GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS support has been added to
> > > GNU binutils 2.38.  But the -z indirect-extern-access linker option is
> > > only available for Linux/x86.  However, the --max-cache-size=SIZE linker
> > > option was also addded within a day.  --max-cache-size=SIZE is used to
> > > check for GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS support.
> > >
> > > Changes in the v2 patch.
> > >
> > > 1. Rename the option to -fdirect-extern-access.
> > >
> > > ---
> > > On systems with copy relocation:
> > > * A copy in executable is created for the definition in a shared library
> > > at run-time by ld.so.
> > > * The copy is referenced by executable and shared libraries.
> > > * Executable can access the copy directly.
> > >
> > > Issues are:
> > > * Overhead of a copy, time and space, may be visible at run-time.
> > > * Read-only data in the shared library becomes read-write copy in
> > > executable at run-time.
> > > * Local access to data with the STV_PROTECTED visibility in the shared
> > > library must use GOT.
> > >
> > > On systems without function descriptor, function pointers vary depending
> > > on where and how the functions are defined.
> > > * If the function is defined in executable, it can be the address of
> > > function body.
> > > * If the function, including the function with STV_PROTECTED visibility,
> > > is defined in the shared library, it can be the address of the PLT entry
> > > in executable or shared library.
> > >
> > > Issues are:
> > > * The address of function body may not be used as its function pointer.
> > > * ld.so needs to search loaded shared libraries for the function pointer
> > > of the function with STV_PROTECTED visibility.
> > >
> > > Here is a proposal to remove copy relocation and use canonical function
> > > pointer:
> > >
> > > 1. Accesses, including in PIE and non-PIE, to undefined symbols must
> > > use GOT.
> > >   a. Linker may optimize out GOT access if the data is defined in PIE or
> > >   non-PIE.
> > > 2. Read-only data in the shared library remain read-only at run-time
> > > 3. Address of global data with the STV_PROTECTED visibility in the shared
> > > library is the address of data body.
> > >   a. Can use IP-relative access.
> > >   b. May need GOT without IP-relative access.
> > > 4. For systems without function descriptor,
> > >   a. All global function pointers of undefined functions in PIE and
> > >   non-PIE must use GOT.  Linker may optimize out GOT access if the
> > >   function is defined in PIE or non-PIE.
> > >   b. Function pointer of functions with the STV_PROTECTED visibility in
> > >   executable and shared library is the address of function body.
> > >    i. Can use IP-relative access.
> > >    ii. May need GOT without IP-relative access.
> > >    iii. Branches to undefined functions may use PLT.
> > > 5. Single global definition marker:
> > >
> > > Add GNU_PROPERTY_1_NEEDED:
> > >
> > > #define GNU_PROPERTY_1_NEEDED GNU_PROPERTY_UINT32_OR_LO
> > >
> > > to indicate the needed properties by the object file.
> > >
> > > Add GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS:
> > >
> > > #define GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS (1U << 0)
> > >
> > > to indicate that the object file requires canonical function pointers and
> > > cannot be used with copy relocation.  This bit should be cleared in
> > > executable when there are non-GOT or non-PLT relocations in relocatable
> > > input files without this bit set.
> > >
> > >   a. Protected symbol access within the shared library can be treated as
> > >   local.
> > >   b. Copy relocation should be disallowed at link-time and run-time.
> > >   c. GOT function pointer reference is required at link-time and run-time.
> > >
> > > The indirect external access marker can be used in the following ways:
> > >
> > > 1. Linker can decide the best way to resolve a relocation against a
> > > protected symbol before seeing all relocations against the symbol.
> > > 2. Dynamic linker can decide if it is an error to have a copy relocation
> > > in executable against the protected symbol in a shared library by checking
> > > if the shared library is built with -mno-direct-extern-access.
> > >
> > > Add a compiler option, -mdirect-extern-access. -mdirect-extern-access is
> > > the default.  With -mno-direct-extern-access:
> > >
> > > 1. Always to use GOT to access undefined symbols, including in PIE and
> > > non-PIE.  This is safe to do and does not break the ABI.
> > > 2. In executable and shared library, for symbols with the STV_PROTECTED
> > > visibility:
> > >   a. The address of data symbol is the address of data body.
> > >   b. For systems without function descriptor, the function pointer is
> > >   the address of function body.
> > > These break the ABI and resulting shared libraries may not be compatible
> > > with executables which are not compiled with -mno-direct-extern-access.
> > > 3. Generate an indirect external access marker in relocatable objects if
> > > supported by linker.
> > >
> > > H.J.
> > > ---
> > > Add -m[no-]direct-extern-access and nodirect_extern_access attribute.
> > > -mdirect-extern-access is the default.  With nodirect_extern_access
> > > attribute, GOT is always used to access undefined data and function
> > > symbols with nodirect_extern_access attribute, including in PIE and
> > > non-PIE.  With -mno-direct-extern-access:
> > >
> > > 1. Always use GOT to access undefined data and function symbols,
> > >    including in PIE and non-PIE.  These will avoid copy relocations
> > >    in executables.  This is compatible with existing executables and
> > >    shared libraries.
> > > 2. In executable and shared library, bind symbols with the STV_PROTECTED
> > >    visibility locally:
> > >    a. The address of data symbol is the address of data body.
> > >    b. For systems without function descriptor, the function pointer is
> > >       the address of function body.
> > >    c. The resulting shared libraries may not be incompatible with
> > >       executables which have copy relocations on protected symbols or
> > >       use executable PLT entries as function addresses for protected
> > >       functions in shared libraries.
> > > 3. Update asm_preferred_eh_data_format to select PC relative EH encoding
> > > format with -mno-direct-extern-access to avoid copy relocation.
> > > 4. Add ix86_reloc_rw_mask for TARGET_ASM_RELOC_RW_MASK to avoid copy
> > > relocation with -mno-direct-extern-access.
> > >
> > > gcc/
> > >
> > >         PR target/35513
> > >         PR target/100593
> > >         * config/i386/gnu-property.cc: Include "i386-protos.h".
> > >         (file_end_indicate_exec_stack_and_gnu_property): Generate
> > >         a GNU_PROPERTY_1_NEEDED note for -mno-direct-extern-access or
> > >         nodirect_extern_access attribute.
> > >         * config/i386/i386-options.cc
> > >         (handle_nodirect_extern_access_attribute): New function.
> > >         (ix86_attribute_table): Add nodirect_extern_access attribute.
> > >         * config/i386/i386-protos.h (ix86_force_load_from_GOT_p): Add a
> > >         bool argument.
> > >         (ix86_has_no_direct_extern_access): New.
> > >         * config/i386/i386.cc (ix86_has_no_direct_extern_access): New.
> > >         (ix86_force_load_from_GOT_p): Add a bool argument to indicate
> > >         call operand.  Force non-call load from GOT for
> > >         -mno-direct-extern-access or nodirect_extern_access attribute.
> > >         (legitimate_pic_address_disp_p): Avoid copy relocation in PIE
> > >         for -mno-direct-extern-access or nodirect_extern_access attribute.
> > >         (ix86_print_operand): Pass true to ix86_force_load_from_GOT_p
> > >         for call operand.
> > >         (asm_preferred_eh_data_format): Use PC-relative format for
> > >         -mno-direct-extern-access to avoid copy relocation.  Check
> > >         ptr_mode instead of TARGET_64BIT when selecting DW_EH_PE_sdata4.
> > >         (ix86_binds_local_p): Set ix86_has_no_direct_extern_access to
> > >         true for -mno-direct-extern-access or nodirect_extern_access
> > >         attribute.  Don't treat protected data as extern and avoid copy
> > >         relocation on common symbol with -mno-direct-extern-access or
> > >         nodirect_extern_access attribute.
> > >         (ix86_reloc_rw_mask): New to avoid copy relocation for
> > >         -mno-direct-extern-access.
> > >         (TARGET_ASM_RELOC_RW_MASK): New.
> > >         * config/i386/i386.opt: Add -mdirect-extern-access.
> > >         * doc/extend.texi: Document nodirect_extern_access attribute.
> > >         * doc/invoke.texi: Document -m[no-]direct-extern-access.
> > >
> > > gcc/testsuite/
> > >
> > >         PR target/35513
> > >         PR target/100593
> > >         * g++.target/i386/pr35513-1.C: New file.
> > >         * g++.target/i386/pr35513-2.C: Likewise.
> > >         * gcc.target/i386/pr35513-1a.c: Likewise.
> > >         * gcc.target/i386/pr35513-1b.c: Likewise.
> > >         * gcc.target/i386/pr35513-2a.c: Likewise.
> > >         * gcc.target/i386/pr35513-2b.c: Likewise.
> > >         * gcc.target/i386/pr35513-3a.c: Likewise.
> > >         * gcc.target/i386/pr35513-3b.c: Likewise.
> > >         * gcc.target/i386/pr35513-4a.c: Likewise.
> > >         * gcc.target/i386/pr35513-4b.c: Likewise.
> > >         * gcc.target/i386/pr35513-5a.c: Likewise.
> > >         * gcc.target/i386/pr35513-5b.c: Likewise.
> > >         * gcc.target/i386/pr35513-6a.c: Likewise.
> > >         * gcc.target/i386/pr35513-6b.c: Likewise.
> > >         * gcc.target/i386/pr35513-7a.c: Likewise.
> > >         * gcc.target/i386/pr35513-7b.c: Likewise.
> > >         * gcc.target/i386/pr35513-8a.c: Likewise.
> > >         * gcc.target/i386/pr35513-8b.c: Likewise.
> > >         * gcc.target/i386/pr35513-9a.c: Likewise.
> > >         * gcc.target/i386/pr35513-9b.c: Likewise.
> > >         * gcc.target/i386/pr35513-10a.c: Likewise.
> > >         * gcc.target/i386/pr35513-10b.c: Likewise.
> > >         * gcc.target/i386/pr35513-11a.c: Likewise.
> > >         * gcc.target/i386/pr35513-11b.c: Likewise.
> > >         * gcc.target/i386/pr35513-12a.c: Likewise.
> > >         * gcc.target/i386/pr35513-12b.c: Likewise.
> > > ---
> > >  gcc/config/i386/gnu-property.cc             | 10 ++-
> > >  gcc/config/i386/i386-options.cc             | 32 ++++++++++
> > >  gcc/config/i386/i386-protos.h               |  4 +-
> > >  gcc/config/i386/i386.cc                     | 67 ++++++++++++++++-----
> > >  gcc/config/i386/i386.opt                    |  4 ++
> > >  gcc/doc/extend.texi                         |  6 ++
> > >  gcc/doc/invoke.texi                         | 15 ++++-
> > >  gcc/testsuite/g++.target/i386/pr35513-1.C   | 25 ++++++++
> > >  gcc/testsuite/g++.target/i386/pr35513-2.C   | 53 ++++++++++++++++
> > >  gcc/testsuite/gcc.target/i386/pr35513-10a.c | 20 ++++++
> > >  gcc/testsuite/gcc.target/i386/pr35513-10b.c | 20 ++++++
> > >  gcc/testsuite/gcc.target/i386/pr35513-11a.c | 20 ++++++
> > >  gcc/testsuite/gcc.target/i386/pr35513-11b.c | 20 ++++++
> > >  gcc/testsuite/gcc.target/i386/pr35513-12a.c | 20 ++++++
> > >  gcc/testsuite/gcc.target/i386/pr35513-12b.c | 20 ++++++
> > >  gcc/testsuite/gcc.target/i386/pr35513-1a.c  | 19 ++++++
> > >  gcc/testsuite/gcc.target/i386/pr35513-1b.c  | 19 ++++++
> > >  gcc/testsuite/gcc.target/i386/pr35513-2a.c  | 18 ++++++
> > >  gcc/testsuite/gcc.target/i386/pr35513-2b.c  | 18 ++++++
> > >  gcc/testsuite/gcc.target/i386/pr35513-3a.c  | 18 ++++++
> > >  gcc/testsuite/gcc.target/i386/pr35513-3b.c  | 18 ++++++
> > >  gcc/testsuite/gcc.target/i386/pr35513-4a.c  | 18 ++++++
> > >  gcc/testsuite/gcc.target/i386/pr35513-4b.c  | 18 ++++++
> > >  gcc/testsuite/gcc.target/i386/pr35513-5a.c  | 18 ++++++
> > >  gcc/testsuite/gcc.target/i386/pr35513-5b.c  | 18 ++++++
> > >  gcc/testsuite/gcc.target/i386/pr35513-6a.c  | 17 ++++++
> > >  gcc/testsuite/gcc.target/i386/pr35513-6b.c  | 17 ++++++
> > >  gcc/testsuite/gcc.target/i386/pr35513-7a.c  | 18 ++++++
> > >  gcc/testsuite/gcc.target/i386/pr35513-7b.c  | 18 ++++++
> > >  gcc/testsuite/gcc.target/i386/pr35513-8.c   | 44 ++++++++++++++
> > >  gcc/testsuite/gcc.target/i386/pr35513-9a.c  | 20 ++++++
> > >  gcc/testsuite/gcc.target/i386/pr35513-9b.c  | 20 ++++++
> > >  32 files changed, 655 insertions(+), 17 deletions(-)
> > >  create mode 100644 gcc/testsuite/g++.target/i386/pr35513-1.C
> > >  create mode 100644 gcc/testsuite/g++.target/i386/pr35513-2.C
> > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr35513-10a.c
> > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr35513-10b.c
> > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr35513-11a.c
> > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr35513-11b.c
> > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr35513-12a.c
> > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr35513-12b.c
> > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr35513-1a.c
> > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr35513-1b.c
> > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr35513-2a.c
> > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr35513-2b.c
> > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr35513-3a.c
> > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr35513-3b.c
> > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr35513-4a.c
> > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr35513-4b.c
> > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr35513-5a.c
> > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr35513-5b.c
> > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr35513-6a.c
> > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr35513-6b.c
> > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr35513-7a.c
> > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr35513-7b.c
> > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr35513-8.c
> > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr35513-9a.c
> > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr35513-9b.c
> > >
> > > diff --git a/gcc/config/i386/gnu-property.cc 
> > > b/gcc/config/i386/gnu-property.cc
> > > index f08984f32a1..ea63c1ec58c 100644
> > > --- a/gcc/config/i386/gnu-property.cc
> > > +++ b/gcc/config/i386/gnu-property.cc
> > > @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3.  If not see
> > >  #include "tm.h"
> > >  #include "output.h"
> > >  #include "linux-common.h"
> > > +#include "i386-protos.h"
> > >
> > >  static void
> > >  emit_gnu_property (unsigned int type, unsigned int data)
> > > @@ -60,7 +61,9 @@ file_end_indicate_exec_stack_and_gnu_property (void)
> > >  {
> > >    file_end_indicate_exec_stack ();
> > >
> > > -  if (flag_cf_protection == CF_NONE && !ix86_needed)
> > > +  if (flag_cf_protection == CF_NONE
> > > +      && !ix86_needed
> > > +      && !ix86_has_no_direct_extern_access)
> > >      return;
> > >
> > >    unsigned int feature_1 = 0;
> > > @@ -121,4 +124,9 @@ file_end_indicate_exec_stack_and_gnu_property (void)
> > >    /* Generate GNU_PROPERTY_X86_ISA_1_NEEDED.  */
> > >    if (isa_1)
> > >      emit_gnu_property (0xc0008002, isa_1);
> > > +
> > > +  if (ix86_has_no_direct_extern_access)
> > > +    /* Emite a GNU_PROPERTY_1_NEEDED note with
> > > +       GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS.  */
> > > +    emit_gnu_property (0xb0008000, (1U << 0));
> > >  }
> > > diff --git a/gcc/config/i386/i386-options.cc 
> > > b/gcc/config/i386/i386-options.cc
> > > index 715d9a15ff5..b82f7060007 100644
> > > --- a/gcc/config/i386/i386-options.cc
> > > +++ b/gcc/config/i386/i386-options.cc
> > > @@ -3775,6 +3775,36 @@ ix86_handle_fentry_name (tree *node, tree name, 
> > > tree args,
> > >    return NULL_TREE;
> > >  }
> > >
> > > +/* Handle a "nodirect_extern_access" attribute; arguments as in
> > > +   struct attribute_spec.handler.  */
> > > +
> > > +static tree
> > > +handle_nodirect_extern_access_attribute (tree *pnode, tree name,
> > > +                                        tree ARG_UNUSED (args),
> > > +                                        int ARG_UNUSED (flags),
> > > +                                        bool *no_add_attrs)
> > > +{
> > > +  tree node = *pnode;
> > > +
> > > +  if (VAR_OR_FUNCTION_DECL_P (node))
> > > +    {
> > > +      if ((!TREE_STATIC (node) && TREE_CODE (node) != FUNCTION_DECL
> > > +          && !DECL_EXTERNAL (node)) || !TREE_PUBLIC (node))
> > > +       {
> > > +         warning (OPT_Wattributes,
> > > +                  "%qE attribute have effect only on public objects", 
> > > name);
> > > +         *no_add_attrs = true;
> > > +       }
> > > +    }
> > > +  else
> > > +    {
> > > +      warning (OPT_Wattributes, "%qE attribute ignored", name);
> > > +      *no_add_attrs = true;
> > > +    }
> > > +
> > > +  return NULL_TREE;
> > > +}
> > > +
> > >  /* Table of valid machine attributes.  */
> > >  const struct attribute_spec ix86_attribute_table[] =
> > >  {
> > > @@ -3855,6 +3885,8 @@ const struct attribute_spec ix86_attribute_table[] =
> > >      ix86_handle_fentry_name, NULL },
> > >    { "cf_check", 0, 0, true, false, false, false,
> > >      ix86_handle_fndecl_attribute, NULL },
> > > +  { "nodirect_extern_access", 0, 0, true, false, false, false,
> > > +    handle_nodirect_extern_access_attribute, NULL },
> > >
> > >    /* End element.  */
> > >    { NULL, 0, 0, false, false, false, false, NULL, NULL }
> > > diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
> > > index 6b3c9516a7f..b7e9aa75d25 100644
> > > --- a/gcc/config/i386/i386-protos.h
> > > +++ b/gcc/config/i386/i386-protos.h
> > > @@ -79,7 +79,7 @@ extern bool ix86_expand_cmpstrn_or_cmpmem (rtx, rtx, 
> > > rtx, rtx, rtx, bool);
> > >  extern bool constant_address_p (rtx);
> > >  extern bool legitimate_pic_operand_p (rtx);
> > >  extern bool legitimate_pic_address_disp_p (rtx);
> > > -extern bool ix86_force_load_from_GOT_p (rtx);
> > > +extern bool ix86_force_load_from_GOT_p (rtx, bool = false);
> > >  extern void print_reg (rtx, int, FILE*);
> > >  extern void ix86_print_operand (FILE *, rtx, int);
> > >
> > > @@ -401,3 +401,5 @@ extern rtl_opt_pass 
> > > *make_pass_insert_endbr_and_patchable_area
> > >    (gcc::context *);
> > >  extern rtl_opt_pass *make_pass_remove_partial_avx_dependency
> > >    (gcc::context *);
> > > +
> > > +extern bool ix86_has_no_direct_extern_access;
> > > diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
> > > index ad5a5caa413..3f520c007bd 100644
> > > --- a/gcc/config/i386/i386.cc
> > > +++ b/gcc/config/i386/i386.cc
> > > @@ -363,6 +363,9 @@ unsigned int ix86_default_incoming_stack_boundary;
> > >  /* Alignment for incoming stack boundary in bits.  */
> > >  unsigned int ix86_incoming_stack_boundary;
> > >
> > > +/* True if there is no direct access to extern symbols.  */
> > > +bool ix86_has_no_direct_extern_access;
> > > +
> > >  /* Calling abi specific va_list type nodes.  */
> > >  tree sysv_va_list_type_node;
> > >  tree ms_va_list_type_node;
> > > @@ -10513,13 +10516,17 @@ darwin_local_data_pic (rtx disp)
> > >  }
> > >
> > >  /* True if the function symbol operand X should be loaded from GOT.
> > > +   If CALL_P is true, X is a call operand.
> > > +
> > > +   NB: -mno-direct-extern-access doesn't force load from GOT for
> > > +   call.
> > >
> > >     NB: In 32-bit mode, only non-PIC is allowed in inline assembly
> > >     statements, since a PIC register could not be available at the
> > >     call site.  */
> > >
> > >  bool
> > > -ix86_force_load_from_GOT_p (rtx x)
> > > +ix86_force_load_from_GOT_p (rtx x, bool call_p)
> > >  {
> > >    return ((TARGET_64BIT || (!flag_pic && HAVE_AS_IX86_GOT32X))
> > >           && !TARGET_PECOFF && !TARGET_MACHO
> > > @@ -10527,11 +10534,16 @@ ix86_force_load_from_GOT_p (rtx x)
> > >           && ix86_cmodel != CM_LARGE
> > >           && ix86_cmodel != CM_LARGE_PIC
> > >           && GET_CODE (x) == SYMBOL_REF
> > > -         && SYMBOL_REF_FUNCTION_P (x)
> > > -         && (!flag_plt
> > > -             || (SYMBOL_REF_DECL (x)
> > > -                 && lookup_attribute ("noplt",
> > > -                                      DECL_ATTRIBUTES (SYMBOL_REF_DECL 
> > > (x)))))
> > > +         && ((!call_p
> > > +              && (!ix86_direct_extern_access
> > > +                  || (SYMBOL_REF_DECL (x)
> > > +                      && lookup_attribute ("nodirect_extern_access",
> > > +                                           DECL_ATTRIBUTES 
> > > (SYMBOL_REF_DECL (x))))))
> > > +             || (SYMBOL_REF_FUNCTION_P (x)
> > > +                 && (!flag_plt
> > > +                     || (SYMBOL_REF_DECL (x)
> > > +                         && lookup_attribute ("noplt",
> > > +                                              DECL_ATTRIBUTES 
> > > (SYMBOL_REF_DECL (x)))))))
> > >           && !SYMBOL_REF_LOCAL_P (x));
> > >  }
> > >
> > > @@ -10798,7 +10810,11 @@ legitimate_pic_address_disp_p (rtx disp)
> > >             }
> > >           else if (!SYMBOL_REF_FAR_ADDR_P (op0)
> > >                    && (SYMBOL_REF_LOCAL_P (op0)
> > > -                      || (HAVE_LD_PIE_COPYRELOC
> > > +                      || ((ix86_direct_extern_access
> > > +                           && !(SYMBOL_REF_DECL (op0)
> > > +                                && lookup_attribute 
> > > ("nodirect_extern_access",
> > > +                                                     DECL_ATTRIBUTES 
> > > (SYMBOL_REF_DECL (op0)))))
> > > +                          && HAVE_LD_PIE_COPYRELOC
> > >                            && flag_pie
> > >                            && !SYMBOL_REF_WEAK (op0)
> > >                            && !SYMBOL_REF_FUNCTION_P (op0)))
> > > @@ -13754,7 +13770,7 @@ ix86_print_operand (FILE *file, rtx x, int code)
> > >
> > >        if (code == 'P')
> > >         {
> > > -         if (ix86_force_load_from_GOT_p (x))
> > > +         if (ix86_force_load_from_GOT_p (x, true))
> > >             {
> > >               /* For inline assembly statement, load function address
> > >                  from GOT with 'P' operand modifier to avoid PLT.  */
> > > @@ -22520,10 +22536,10 @@ int
> > >  asm_preferred_eh_data_format (int code, int global)
> > >  {
> > >    /* PE-COFF is effectively always -fPIC because of the .reloc section.  
> > > */
> > > -  if (flag_pic || TARGET_PECOFF)
> > > +  if (flag_pic || TARGET_PECOFF || !ix86_direct_extern_access)
> > >      {
> > >        int type = DW_EH_PE_sdata8;
> > > -      if (!TARGET_64BIT
> > > +      if (ptr_mode == SImode
> > >           || ix86_cmodel == CM_SMALL_PIC
> > >           || (ix86_cmodel == CM_MEDIUM_PIC && (global || code)))
> > >         type = DW_EH_PE_sdata4;
> > > @@ -23613,10 +23629,28 @@ ix86_atomic_assign_expand_fenv (tree *hold, 
> > > tree *clear, tree *update)
> > >  static bool
> > >  ix86_binds_local_p (const_tree exp)
> > >  {
> > > -  return default_binds_local_p_3 (exp, flag_shlib != 0, true, true,
> > > -                                 (!flag_pic
> > > -                                  || (TARGET_64BIT
> > > -                                      && HAVE_LD_PIE_COPYRELOC != 0)));
> > > +  bool direct_extern_access
> > > +    = (ix86_direct_extern_access
> > > +       && !(VAR_OR_FUNCTION_DECL_P (exp)
> > > +           && lookup_attribute ("nodirect_extern_access",
> > > +                                DECL_ATTRIBUTES (exp))));
> > > +  if (!direct_extern_access)
> > > +    ix86_has_no_direct_extern_access = true;
> > > +  return default_binds_local_p_3 (exp, flag_shlib != 0, true,
> > > +                                 direct_extern_access,
> > > +                                 (direct_extern_access
> > > +                                  && (!flag_pic
> > > +                                      || (TARGET_64BIT
> > > +                                          && HAVE_LD_PIE_COPYRELOC != 
> > > 0))));
> > > +}
> > > +
> > > +/* If flag_pic or ix86_direct_extern_access is false, then neither
> > > +   local nor global relocs should be placed in readonly memory.  */
> > > +
> > > +static int
> > > +ix86_reloc_rw_mask (void)
> > > +{
> > > +  return (flag_pic || !ix86_direct_extern_access) ? 3 : 0;
> > >  }
> > >  #endif
> > >
> > > @@ -24681,6 +24715,11 @@ ix86_libgcc_floating_mode_supported_p
> > >  #undef TARGET_IFUNC_REF_LOCAL_OK
> > >  #define TARGET_IFUNC_REF_LOCAL_OK hook_bool_void_true
> > >
> > > +#if !TARGET_MACHO && !TARGET_DLLIMPORT_DECL_ATTRIBUTES
> > > +# undef TARGET_ASM_RELOC_RW_MASK
> > > +# define TARGET_ASM_RELOC_RW_MASK ix86_reloc_rw_mask
> > > +#endif
> > > +
> > >  static bool ix86_libc_has_fast_function (int fcode ATTRIBUTE_UNUSED)
> > >  {
> > >  #ifdef OPTION_GLIBC
> > > diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
> > > index eb829d13d40..d8e8656a8ab 100644
> > > --- a/gcc/config/i386/i386.opt
> > > +++ b/gcc/config/i386/i386.opt
> > > @@ -1206,3 +1206,7 @@ Support MWAIT and MONITOR built-in functions and 
> > > code generation.
> > >  mavx512fp16
> > >  Target Mask(ISA2_AVX512FP16) Var(ix86_isa_flags2) Save
> > >  Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F 
> > > and AVX512FP16 built-in functions and code generation.
> > > +
> > > +mdirect-extern-access
> > > +Target Var(ix86_direct_extern_access) Init(1)
> > > +Do not use GOT to access external symbols.
> > > diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
> > > index a961fc4e0a2..dbc453c7108 100644
> > > --- a/gcc/doc/extend.texi
> > > +++ b/gcc/doc/extend.texi
> > > @@ -7220,6 +7220,12 @@ On x86 targets, the @code{fentry_section} 
> > > attribute sets the name
> > >  of the section to record function entry instrumentation calls in when
> > >  enabled with @option{-pg -mrecord-mcount}
> > >
> > > +@item nodirect_extern_access
> > > +@cindex @code{nodirect_extern_access} function attribute
> > > +@opindex mno-direct-extern-access
> > > +This attribute, attached to a global variable or function, is the
> > > +counterpart to option @option{-mno-direct-extern-access}.
> > > +
> > >  @end table
> > >
> > >  @node Xstormy16 Function Attributes
> > > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> > > index 9e588db4fce..7f2de745f48 100644
> > > --- a/gcc/doc/invoke.texi
> > > +++ b/gcc/doc/invoke.texi
> > > @@ -1436,7 +1436,7 @@ See RS/6000 and PowerPC Options.
> > >  -mgeneral-regs-only  -mcall-ms2sysv-xlogues -mrelax-cmpxchg-loop @gol
> > >  -mindirect-branch=@var{choice}  -mfunction-return=@var{choice} @gol
> > >  -mindirect-branch-register -mharden-sls=@var{choice} @gol
> > > --mindirect-branch-cs-prefix -mneeded}
> > > +-mindirect-branch-cs-prefix -mneeded -mno-direct-extern-access}
> > >
> > >  @emph{x86 Windows Options}
> > >  @gccoptlist{-mconsole  -mcygwin  -mno-cygwin  -mdll @gol
> > > @@ -32789,6 +32789,19 @@ x32 environments.
> > >  @opindex mneeded
> > >  Emit GNU_PROPERTY_X86_ISA_1_NEEDED GNU property for Linux target to
> > >  indicate the micro-architecture ISA level required to execute the binary.
> > > +
> > > +@item -mno-direct-extern-access
> > > +@opindex mno-direct-extern-access
> > > +@opindex mdirect-extern-access
> > > +Without @option{-fpic} nor @option{-fPIC}, always use the GOT pointer
> > > +to access external symbols.  With @option{-fpic} or @option{-fPIC},
> > > +treat access to protected symbols as local symbols.  The default is
> > > +@option{-mdirect-extern-access}.
> > > +
> > > +@strong{Warning:} shared libraries compiled with
> > > +@option{-mno-direct-extern-access} and executable compiled with
> > > +@option{-mdirect-extern-access} may not be binary compatible if
> > > +protected symbols are used in shared libraries and executable.
> > >  @end table
> > >
> > >  @node x86 Windows Options
> > > diff --git a/gcc/testsuite/g++.target/i386/pr35513-1.C 
> > > b/gcc/testsuite/g++.target/i386/pr35513-1.C
> > > new file mode 100644
> > > index 00000000000..6f8db37fb7c
> > > --- /dev/null
> > > +++ b/gcc/testsuite/g++.target/i386/pr35513-1.C
> > > @@ -0,0 +1,25 @@
> > > +// { dg-do run }
> > > +// { dg-options "-O2 -mno-direct-extern-access" }
> > > +
> > > +#include <iostream>
> > > +
> > > +class Bug
> > > +{
> > > +};
> > > +
> > > +int throw_bug()
> > > +{
> > > +  throw Bug();
> > > +
> > > +  return 0;
> > > +}
> > > +
> > > +int main()
> > > +{
> > > +  try {
> > > +      std::cout << throw_bug();
> > > +  } catch (Bug bug) {
> > > +  };
> > > +
> > > +  return 0;
> > > +}
> > > diff --git a/gcc/testsuite/g++.target/i386/pr35513-2.C 
> > > b/gcc/testsuite/g++.target/i386/pr35513-2.C
> > > new file mode 100644
> > > index 00000000000..9143ff3f0a5
> > > --- /dev/null
> > > +++ b/gcc/testsuite/g++.target/i386/pr35513-2.C
> > > @@ -0,0 +1,53 @@
> > > +// { dg-do run  }
> > > +// { dg-options "-O2 -mno-direct-extern-access" }
> > > +
> > > +class Foo
> > > +{
> > > +public:
> > > +  Foo(int n) : n_(n) { }
> > > +  int f() { return n_; }
> > > +
> > > +  int badTest();
> > > +  int goodTest();
> > > +
> > > +private:
> > > +
> > > +  int n_;
> > > +};
> > > +
> > > +int Foo::badTest()
> > > +{
> > > +  try {
> > > +      throw int(99);
> > > +  }
> > > +
> > > +  catch (int &i) {
> > > +      n_ = 16;
> > > +  }
> > > +
> > > +  return n_;
> > > +}
> > > +
> > > +
> > > +int Foo::goodTest()
> > > +{
> > > +  int  n;
> > > +
> > > +  try {
> > > +      throw int(99);
> > > +  }
> > > +
> > > +  catch (int &i) {
> > > +      n = 16;
> > > +  }
> > > +
> > > +  return n_;
> > > +}
> > > +
> > > +int main()
> > > +{
> > > +  Foo foo(5);
> > > +  foo.goodTest();
> > > +  foo.badTest();
> > > +  return 0;
> > > +}
> > > diff --git a/gcc/testsuite/gcc.target/i386/pr35513-10a.c 
> > > b/gcc/testsuite/gcc.target/i386/pr35513-10a.c
> > > new file mode 100644
> > > index 00000000000..d7b5c98fa8c
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/i386/pr35513-10a.c
> > > @@ -0,0 +1,20 @@
> > > +/* { dg-do compile { target *-*-linux* } } */
> > > +/* { dg-options "-O2 -fpic -mno-direct-extern-access" } */
> > > +
> > > +/* Weak common symbol with -fpic.  */
> > > +__attribute__((weak, visibility("protected")))
> > > +int xxx;
> > > +
> > > +int
> > > +foo ()
> > > +{
> > > +  return xxx;
> > > +}
> > > +
> > > +/* { dg-final { scan-assembler "xxx\\(%rip\\)" { target { ! ia32 } } } } 
> > > */
> > > +/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } 
> > > } } */
> > > +/* { dg-final { scan-assembler "xxx@GOTOFF" { target ia32 } } } */
> > > +/* { dg-final { scan-assembler-not "xxx@GOT\\(" { target ia32 } } } */
> > > +/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } 
> > > */
> > > +/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
> > > +
> > > diff --git a/gcc/testsuite/gcc.target/i386/pr35513-10b.c 
> > > b/gcc/testsuite/gcc.target/i386/pr35513-10b.c
> > > new file mode 100644
> > > index 00000000000..a40692e6e3d
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/i386/pr35513-10b.c
> > > @@ -0,0 +1,20 @@
> > > +/* { dg-do compile { target *-*-linux* } } */
> > > +/* { dg-options "-O2 -fpic -mdirect-extern-access" } */
> > > +
> > > +/* Weak common symbol with -fpic.  */
> > > +__attribute__((weak, visibility("protected"),nodirect_extern_access))
> > > +int xxx;
> > > +
> > > +int
> > > +foo ()
> > > +{
> > > +  return xxx;
> > > +}
> > > +
> > > +/* { dg-final { scan-assembler "xxx\\(%rip\\)" { target { ! ia32 } } } } 
> > > */
> > > +/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } 
> > > } } */
> > > +/* { dg-final { scan-assembler "xxx@GOTOFF" { target ia32 } } } */
> > > +/* { dg-final { scan-assembler-not "xxx@GOT\\(" { target ia32 } } } */
> > > +/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } 
> > > */
> > > +/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
> > > +
> > > diff --git a/gcc/testsuite/gcc.target/i386/pr35513-11a.c 
> > > b/gcc/testsuite/gcc.target/i386/pr35513-11a.c
> > > new file mode 100644
> > > index 00000000000..5489f1e5cee
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/i386/pr35513-11a.c
> > > @@ -0,0 +1,20 @@
> > > +/* { dg-do compile { target *-*-linux* } } */
> > > +/* { dg-options "-O2 -fpic -mno-direct-extern-access" } */
> > > +
> > > +/* Initialized symbol with -fpic.  */
> > > +__attribute__((visibility("protected")))
> > > +int xxx = -1;
> > > +
> > > +int
> > > +foo ()
> > > +{
> > > +  return xxx;
> > > +}
> > > +
> > > +/* { dg-final { scan-assembler "xxx\\(%rip\\)" { target { ! ia32 } } } } 
> > > */
> > > +/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } 
> > > } } */
> > > +/* { dg-final { scan-assembler "xxx@GOTOFF" { target ia32 } } } */
> > > +/* { dg-final { scan-assembler-not "xxx@GOT\\(" { target ia32 } } } */
> > > +/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } 
> > > */
> > > +/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
> > > +
> > > diff --git a/gcc/testsuite/gcc.target/i386/pr35513-11b.c 
> > > b/gcc/testsuite/gcc.target/i386/pr35513-11b.c
> > > new file mode 100644
> > > index 00000000000..2704900fed5
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/i386/pr35513-11b.c
> > > @@ -0,0 +1,20 @@
> > > +/* { dg-do compile { target *-*-linux* } } */
> > > +/* { dg-options "-O2 -fpic -mdirect-extern-access" } */
> > > +
> > > +/* Initialized symbol with -fpic.  */
> > > +__attribute__((visibility("protected"), nodirect_extern_access))
> > > +int xxx = -1;
> > > +
> > > +int
> > > +foo ()
> > > +{
> > > +  return xxx;
> > > +}
> > > +
> > > +/* { dg-final { scan-assembler "xxx\\(%rip\\)" { target { ! ia32 } } } } 
> > > */
> > > +/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } 
> > > } } */
> > > +/* { dg-final { scan-assembler "xxx@GOTOFF" { target ia32 } } } */
> > > +/* { dg-final { scan-assembler-not "xxx@GOT\\(" { target ia32 } } } */
> > > +/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } 
> > > */
> > > +/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
> > > +
> > > diff --git a/gcc/testsuite/gcc.target/i386/pr35513-12a.c 
> > > b/gcc/testsuite/gcc.target/i386/pr35513-12a.c
> > > new file mode 100644
> > > index 00000000000..8b3123f9042
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/i386/pr35513-12a.c
> > > @@ -0,0 +1,20 @@
> > > +/* { dg-do compile { target *-*-linux* } } */
> > > +/* { dg-options "-O2 -fpic -mno-direct-extern-access" } */
> > > +
> > > +/* Weak initialized symbol with -fpic.  */
> > > +__attribute__((weak, visibility("protected")))
> > > +int xxx = -1;
> > > +
> > > +int
> > > +foo ()
> > > +{
> > > +  return xxx;
> > > +}
> > > +
> > > +/* { dg-final { scan-assembler "xxx\\(%rip\\)" { target { ! ia32 } } } } 
> > > */
> > > +/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } 
> > > } } */
> > > +/* { dg-final { scan-assembler "xxx@GOTOFF" { target ia32 } } } */
> > > +/* { dg-final { scan-assembler-not "xxx@GOT\\(" { target ia32 } } } */
> > > +/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } 
> > > */
> > > +/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
> > > +
> > > diff --git a/gcc/testsuite/gcc.target/i386/pr35513-12b.c 
> > > b/gcc/testsuite/gcc.target/i386/pr35513-12b.c
> > > new file mode 100644
> > > index 00000000000..a1b6b9e92df
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/i386/pr35513-12b.c
> > > @@ -0,0 +1,20 @@
> > > +/* { dg-do compile { target *-*-linux* } } */
> > > +/* { dg-options "-O2 -fpic -mdirect-extern-access" } */
> > > +
> > > +/* Weak initialized symbol with -fpic.  */
> > > +__attribute__((weak, visibility("protected"), nodirect_extern_access))
> > > +int xxx = -1;
> > > +
> > > +int
> > > +foo ()
> > > +{
> > > +  return xxx;
> > > +}
> > > +
> > > +/* { dg-final { scan-assembler "xxx\\(%rip\\)" { target { ! ia32 } } } } 
> > > */
> > > +/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } 
> > > } } */
> > > +/* { dg-final { scan-assembler "xxx@GOTOFF" { target ia32 } } } */
> > > +/* { dg-final { scan-assembler-not "xxx@GOT\\(" { target ia32 } } } */
> > > +/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } 
> > > */
> > > +/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
> > > +
> > > diff --git a/gcc/testsuite/gcc.target/i386/pr35513-1a.c 
> > > b/gcc/testsuite/gcc.target/i386/pr35513-1a.c
> > > new file mode 100644
> > > index 00000000000..972542423cb
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/i386/pr35513-1a.c
> > > @@ -0,0 +1,19 @@
> > > +/* { dg-do compile { target *-*-linux* } } */
> > > +/* { dg-options "-O2 -fno-pic -mno-direct-extern-access" } */
> > > +
> > > +extern void bar (void);
> > > +extern void *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\(l|q\)\[ \t\]*\\\$bar," { target 
> > > { ! ia32 } } } } */
> > > +/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target 
> > > { ia32 && got32x_reloc } } } } */
> > > +/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } 
> > > */
> > > +/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
> > > +
> > > diff --git a/gcc/testsuite/gcc.target/i386/pr35513-1b.c 
> > > b/gcc/testsuite/gcc.target/i386/pr35513-1b.c
> > > new file mode 100644
> > > index 00000000000..54a579a9e37
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/i386/pr35513-1b.c
> > > @@ -0,0 +1,19 @@
> > > +/* { dg-do compile { target *-*-linux* } } */
> > > +/* { dg-options "-O2 -fno-pic -mdirect-extern-access" } */
> > > +
> > > +extern void bar (void) __attribute__ ((nodirect_extern_access));
> > > +extern void *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\(l|q\)\[ \t\]*\\\$bar," { target 
> > > { ! ia32 } } } } */
> > > +/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target 
> > > { ia32 && got32x_reloc } } } } */
> > > +/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } 
> > > */
> > > +/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
> > > +
> > > diff --git a/gcc/testsuite/gcc.target/i386/pr35513-2a.c 
> > > b/gcc/testsuite/gcc.target/i386/pr35513-2a.c
> > > new file mode 100644
> > > index 00000000000..74fa8fc9d97
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/i386/pr35513-2a.c
> > > @@ -0,0 +1,18 @@
> > > +/* { dg-do compile { target *-*-linux* } } */
> > > +/* { dg-options "-O2 -fno-pic -mno-direct-extern-access" } */
> > > +
> > > +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\(l|q\)\[ \t\]*\\\$bar," { target 
> > > { ! ia32 } } } } */
> > > +/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target 
> > > { ia32 && got32x_reloc } } } } */
> > > +/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } 
> > > */
> > > +/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
> > > +
> > > diff --git a/gcc/testsuite/gcc.target/i386/pr35513-2b.c 
> > > b/gcc/testsuite/gcc.target/i386/pr35513-2b.c
> > > new file mode 100644
> > > index 00000000000..ae2edff8d93
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/i386/pr35513-2b.c
> > > @@ -0,0 +1,18 @@
> > > +/* { dg-do compile { target *-*-linux* } } */
> > > +/* { dg-options "-O2 -fno-pic -mdirect-extern-access" } */
> > > +
> > > +extern int bar __attribute__ ((nodirect_extern_access));
> > > +
> > > +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\(l|q\)\[ \t\]*\\\$bar," { target 
> > > { ! ia32 } } } } */
> > > +/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target 
> > > { ia32 && got32x_reloc } } } } */
> > > +/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } 
> > > */
> > > +/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
> > > +
> > > diff --git a/gcc/testsuite/gcc.target/i386/pr35513-3a.c 
> > > b/gcc/testsuite/gcc.target/i386/pr35513-3a.c
> > > new file mode 100644
> > > index 00000000000..4ca4332c4ab
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/i386/pr35513-3a.c
> > > @@ -0,0 +1,18 @@
> > > +/* { dg-do compile { target *-*-linux* } } */
> > > +/* { dg-options "-O2 -fpie -mno-direct-extern-access" } */
> > > +
> > > +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\(l|q\)\[ \t\]*\\\$bar," { target 
> > > { ! ia32 } } } } */
> > > +/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target 
> > > { ia32 && got32x_reloc } } } } */
> > > +/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } 
> > > */
> > > +/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
> > > +
> > > diff --git a/gcc/testsuite/gcc.target/i386/pr35513-3b.c 
> > > b/gcc/testsuite/gcc.target/i386/pr35513-3b.c
> > > new file mode 100644
> > > index 00000000000..c3888039834
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/i386/pr35513-3b.c
> > > @@ -0,0 +1,18 @@
> > > +/* { dg-do compile { target *-*-linux* } } */
> > > +/* { dg-options "-O2 -fpie -mdirect-extern-access" } */
> > > +
> > > +extern int bar __attribute__ ((nodirect_extern_access));
> > > +
> > > +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\(l|q\)\[ \t\]*\\\$bar," { target 
> > > { ! ia32 } } } } */
> > > +/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target 
> > > { ia32 && got32x_reloc } } } } */
> > > +/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } 
> > > */
> > > +/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
> > > +
> > > diff --git a/gcc/testsuite/gcc.target/i386/pr35513-4a.c 
> > > b/gcc/testsuite/gcc.target/i386/pr35513-4a.c
> > > new file mode 100644
> > > index 00000000000..9c3a199404c
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/i386/pr35513-4a.c
> > > @@ -0,0 +1,18 @@
> > > +/* { dg-do compile { target *-*-linux* } } */
> > > +/* { dg-options "-O2 -fplt -fno-pic -mno-direct-extern-access" } */
> > > +
> > > +extern void foo (void);
> > > +
> > > +int
> > > +bar (void)
> > > +{
> > > +  foo ();
> > > +  return 0;
> > > +}
> > > +
> > > +/* { dg-final { scan-assembler "call\[ \t\]*foo" } } */
> > > +/* { dg-final { scan-assembler-not "foo@GOTPCREL" { target { ! ia32 } } 
> > > } } */
> > > +/* { dg-final { scan-assembler-not "foo@GOT" { target ia32 } } } */
> > > +/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } 
> > > */
> > > +/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
> > > +
> > > diff --git a/gcc/testsuite/gcc.target/i386/pr35513-4b.c 
> > > b/gcc/testsuite/gcc.target/i386/pr35513-4b.c
> > > new file mode 100644
> > > index 00000000000..e1a50784bf9
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/i386/pr35513-4b.c
> > > @@ -0,0 +1,18 @@
> > > +/* { dg-do compile { target *-*-linux* } } */
> > > +/* { dg-options "-O2 -fplt -fno-pic -mdirect-extern-access" } */
> > > +
> > > +extern void foo (void) __attribute__ ((nodirect_extern_access));
> > > +
> > > +int
> > > +bar (void)
> > > +{
> > > +  foo ();
> > > +  return 0;
> > > +}
> > > +
> > > +/* { dg-final { scan-assembler "call\[ \t\]*foo" } } */
> > > +/* { dg-final { scan-assembler-not "foo@GOTPCREL" { target { ! ia32 } } 
> > > } } */
> > > +/* { dg-final { scan-assembler-not "foo@GOT" { target ia32 } } } */
> > > +/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } 
> > > */
> > > +/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
> > > +
> > > diff --git a/gcc/testsuite/gcc.target/i386/pr35513-5a.c 
> > > b/gcc/testsuite/gcc.target/i386/pr35513-5a.c
> > > new file mode 100644
> > > index 00000000000..4d2e1732838
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/i386/pr35513-5a.c
> > > @@ -0,0 +1,18 @@
> > > +/* { dg-do compile { target *-*-linux* } } */
> > > +/* { dg-options "-O2 -fplt -fpic -mno-direct-extern-access" } */
> > > +
> > > +extern void foo (void);
> > > +
> > > +int
> > > +bar (void)
> > > +{
> > > +  foo ();
> > > +  return 0;
> > > +}
> > > +
> > > +/* { dg-final { scan-assembler "call\[ \t\]*foo@PLT" } } */
> > > +/* { dg-final { scan-assembler-not "foo@GOTPCREL" { target { ! ia32 } } 
> > > } } */
> > > +/* { dg-final { scan-assembler-not "foo@GOT" { target ia32 } } } */
> > > +/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } 
> > > */
> > > +/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
> > > +
> > > diff --git a/gcc/testsuite/gcc.target/i386/pr35513-5b.c 
> > > b/gcc/testsuite/gcc.target/i386/pr35513-5b.c
> > > new file mode 100644
> > > index 00000000000..81e98ed7836
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/i386/pr35513-5b.c
> > > @@ -0,0 +1,18 @@
> > > +/* { dg-do compile { target *-*-linux* } } */
> > > +/* { dg-options "-O2 -fplt -fpic -mdirect-extern-access" } */
> > > +
> > > +extern void foo (void) __attribute__ ((nodirect_extern_access));
> > > +
> > > +int
> > > +bar (void)
> > > +{
> > > +  foo ();
> > > +  return 0;
> > > +}
> > > +
> > > +/* { dg-final { scan-assembler "call\[ \t\]*foo@PLT" } } */
> > > +/* { dg-final { scan-assembler-not "foo@GOTPCREL" { target { ! ia32 } } 
> > > } } */
> > > +/* { dg-final { scan-assembler-not "foo@GOT" { target ia32 } } } */
> > > +/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } 
> > > */
> > > +/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
> > > +
> > > diff --git a/gcc/testsuite/gcc.target/i386/pr35513-6a.c 
> > > b/gcc/testsuite/gcc.target/i386/pr35513-6a.c
> > > new file mode 100644
> > > index 00000000000..ece878e3c3a
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/i386/pr35513-6a.c
> > > @@ -0,0 +1,17 @@
> > > +/* { dg-do compile { target *-*-linux* } } */
> > > +/* { dg-options "-O2 -fplt -fno-pic -mno-direct-extern-access" } */
> > > +
> > > +extern void foo (void);
> > > +
> > > +void
> > > +bar (void)
> > > +{
> > > +  foo ();
> > > +}
> > > +
> > > +/* { dg-final { scan-assembler "jmp\[ \t\]*foo" } } */
> > > +/* { dg-final { scan-assembler-not "foo@GOTPCREL" { target { ! ia32 } } 
> > > } } */
> > > +/* { dg-final { scan-assembler-not "foo@GOT" { target ia32 } } } */
> > > +/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } 
> > > */
> > > +/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
> > > +
> > > diff --git a/gcc/testsuite/gcc.target/i386/pr35513-6b.c 
> > > b/gcc/testsuite/gcc.target/i386/pr35513-6b.c
> > > new file mode 100644
> > > index 00000000000..3f679defdab
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/i386/pr35513-6b.c
> > > @@ -0,0 +1,17 @@
> > > +/* { dg-do compile { target *-*-linux* } } */
> > > +/* { dg-options "-O2 -fplt -fno-pic -mdirect-extern-access" } */
> > > +
> > > +extern void foo (void) __attribute__ ((nodirect_extern_access));
> > > +
> > > +void
> > > +bar (void)
> > > +{
> > > +  foo ();
> > > +}
> > > +
> > > +/* { dg-final { scan-assembler "jmp\[ \t\]*foo" } } */
> > > +/* { dg-final { scan-assembler-not "foo@GOTPCREL" { target { ! ia32 } } 
> > > } } */
> > > +/* { dg-final { scan-assembler-not "foo@GOT" { target ia32 } } } */
> > > +/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } 
> > > */
> > > +/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
> > > +
> > > diff --git a/gcc/testsuite/gcc.target/i386/pr35513-7a.c 
> > > b/gcc/testsuite/gcc.target/i386/pr35513-7a.c
> > > new file mode 100644
> > > index 00000000000..1de014d39c2
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/i386/pr35513-7a.c
> > > @@ -0,0 +1,18 @@
> > > +/* { dg-do compile { target *-*-linux* } } */
> > > +/* { dg-options "-O2 -fplt -fpic -mno-direct-extern-access" } */
> > > +
> > > +extern void foo (void);
> > > +
> > > +void
> > > +bar (void)
> > > +{
> > > +  foo ();
> > > +}
> > > +
> > > +/* { dg-final { scan-assembler "jmp\[ \t\]*foo@PLT" { target { ! ia32 } 
> > > } } } */
> > > +/* { dg-final { scan-assembler "call\[ \t\]*foo@PLT" { target ia32 } } } 
> > > */
> > > +/* { dg-final { scan-assembler-not "foo@GOTPCREL" { target { ! ia32 } } 
> > > } } */
> > > +/* { dg-final { scan-assembler-not "foo@GOT" { target ia32 } } } */
> > > +/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } 
> > > */
> > > +/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
> > > +
> > > diff --git a/gcc/testsuite/gcc.target/i386/pr35513-7b.c 
> > > b/gcc/testsuite/gcc.target/i386/pr35513-7b.c
> > > new file mode 100644
> > > index 00000000000..984e2dc2752
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/i386/pr35513-7b.c
> > > @@ -0,0 +1,18 @@
> > > +/* { dg-do compile { target *-*-linux* } } */
> > > +/* { dg-options "-O2 -fplt -fpic -mdirect-extern-access" } */
> > > +
> > > +extern void foo (void) __attribute__ ((nodirect_extern_access));
> > > +
> > > +void
> > > +bar (void)
> > > +{
> > > +  foo ();
> > > +}
> > > +
> > > +/* { dg-final { scan-assembler "jmp\[ \t\]*foo@PLT" { target { ! ia32 } 
> > > } } } */
> > > +/* { dg-final { scan-assembler "call\[ \t\]*foo@PLT" { target ia32 } } } 
> > > */
> > > +/* { dg-final { scan-assembler-not "foo@GOTPCREL" { target { ! ia32 } } 
> > > } } */
> > > +/* { dg-final { scan-assembler-not "foo@GOT" { target ia32 } } } */
> > > +/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } 
> > > */
> > > +/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
> > > +
> > > diff --git a/gcc/testsuite/gcc.target/i386/pr35513-8.c 
> > > b/gcc/testsuite/gcc.target/i386/pr35513-8.c
> > > new file mode 100644
> > > index 00000000000..7ba67de2156
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/i386/pr35513-8.c
> > > @@ -0,0 +1,44 @@
> > > +/* { dg-do assemble { target { *-*-linux* && { ! ia32 } } } } */
> > > +/* { dg-require-effective-target maybe_x32 } */
> > > +/* { dg-options "-mx32 -O2 -fno-pic -fexceptions 
> > > -fasynchronous-unwind-tables -mno-direct-extern-access" } */
> > > +
> > > +extern int foo (int);
> > > +extern void exit (int __status) __attribute__ ((__nothrow__ )) 
> > > __attribute__ ((__noreturn__));
> > > +struct __pthread_cleanup_frame
> > > +{
> > > +  void (*__cancel_routine) (void *);
> > > +  void *__cancel_arg;
> > > +  int __do_it;
> > > +  int __cancel_type;
> > > +};
> > > +extern __inline void
> > > +__pthread_cleanup_routine (struct __pthread_cleanup_frame *__frame)
> > > +{
> > > +  if (__frame->__do_it)
> > > +    __frame->__cancel_routine (__frame->__cancel_arg);
> > > +}
> > > +static int cl_called;
> > > +
> > > +static void
> > > +cl (void *arg)
> > > +{
> > > +  ++cl_called;
> > > +}
> > > +
> > > +
> > > +void *
> > > +tf_usleep (void *arg)
> > > +{
> > > +
> > > +  do { struct __pthread_cleanup_frame __clframe __attribute__ 
> > > ((__cleanup__ (__pthread_cleanup_routine))) = { .__cancel_routine = (cl), 
> > > .__cancel_arg = (
> > > +                                                                         
> > >                                                                           
> > >      ((void *)0)), .__do_it = 1 };;
> > > +
> > > +    foo (arg == ((void *)0) ? (0x7fffffffL * 2UL + 1UL) : 0);
> > > +
> > > +    __clframe.__do_it = (0); } while (0);
> > > +
> > > +  exit (1);
> > > +}
> > > +/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } 
> > > */
> > > +/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
> > > +
> > > diff --git a/gcc/testsuite/gcc.target/i386/pr35513-9a.c 
> > > b/gcc/testsuite/gcc.target/i386/pr35513-9a.c
> > > new file mode 100644
> > > index 00000000000..533f1d2ddb4
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/i386/pr35513-9a.c
> > > @@ -0,0 +1,20 @@
> > > +/* { dg-do compile { target *-*-linux* } } */
> > > +/* { dg-options "-O2 -fpic -mno-direct-extern-access" } */
> > > +
> > > +/* Common symbol with -fpic.  */
> > > +__attribute__((visibility("protected")))
> > > +int xxx;
> > > +
> > > +int
> > > +foo ()
> > > +{
> > > +  return xxx;
> > > +}
> > > +
> > > +/* { dg-final { scan-assembler "xxx\\(%rip\\)" { target { ! ia32 } } } } 
> > > */
> > > +/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } 
> > > } } */
> > > +/* { dg-final { scan-assembler "xxx@GOTOFF" { target ia32 } } } */
> > > +/* { dg-final { scan-assembler-not "xxx@GOT\\(" { target ia32 } } } */
> > > +/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } 
> > > */
> > > +/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
> > > +
> > > diff --git a/gcc/testsuite/gcc.target/i386/pr35513-9b.c 
> > > b/gcc/testsuite/gcc.target/i386/pr35513-9b.c
> > > new file mode 100644
> > > index 00000000000..b6c66f43b40
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/i386/pr35513-9b.c
> > > @@ -0,0 +1,20 @@
> > > +/* { dg-do compile { target *-*-linux* } } */
> > > +/* { dg-options "-O2 -fpic -mdirect-extern-access" } */
> > > +
> > > +/* Common symbol with -fpic.  */
> > > +__attribute__((visibility("protected"), nodirect_extern_access))
> > > +int xxx;
> > > +
> > > +int
> > > +foo ()
> > > +{
> > > +  return xxx;
> > > +}
> > > +
> > > +/* { dg-final { scan-assembler "xxx\\(%rip\\)" { target { ! ia32 } } } } 
> > > */
> > > +/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } 
> > > } } */
> > > +/* { dg-final { scan-assembler "xxx@GOTOFF" { target ia32 } } } */
> > > +/* { dg-final { scan-assembler-not "xxx@GOT\\(" { target ia32 } } } */
> > > +/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } 
> > > */
> > > +/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
> > > +
> > > --
> > > 2.34.1
> > >
> >
> >
> > --
> > BR,
> > Hongtao
>

Reply via email to