On Tue, Feb 8, 2022 at 7:05 PM H.J. Lu via Gcc-patches <[email protected]> wrote: > > On Tue, Feb 8, 2022 at 6:38 PM Hongtao Liu <[email protected]> wrote: > > > > On Fri, Jan 28, 2022 at 5:53 AM H.J. Lu via Gcc-patches > > <[email protected]> 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 >
