From patchwork Thu Sep 23 02:02:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 45326 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id F3A7B3858425 for ; Thu, 23 Sep 2021 02:05:25 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org F3A7B3858425 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1632362726; bh=j/wqwDwRJ3sG3GvQSAvoZ+Xz7xI6XVpamay559KvlVg=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=mxzNjft6BxvUX+mmp6PuFH5pAqA4dXerFxOc51SmahF7WHL/ayMXQTpwMllIXVD8t vD8B0rhNUKaONKAZJvMmk3ilgI6xtw7fobg2u5VQ222vviNlB5yZzAzaZaPxiQoRd8 Qgi4YIk4A4FFtn9A3oWzlGtkuBIcSjGFv+xb8Fk0= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-pg1-x52d.google.com (mail-pg1-x52d.google.com [IPv6:2607:f8b0:4864:20::52d]) by sourceware.org (Postfix) with ESMTPS id 61D0E385803C for ; Thu, 23 Sep 2021 02:02:19 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 61D0E385803C Received: by mail-pg1-x52d.google.com with SMTP id t1so4777297pgv.3 for ; Wed, 22 Sep 2021 19:02:19 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=j/wqwDwRJ3sG3GvQSAvoZ+Xz7xI6XVpamay559KvlVg=; b=iVUhVRWO52FLhUS53xwA5/kmokRGfVvMxJqZ+jgiq5lJi8H6RAjMKoRZZVu4SvgBcg BzZzHPkVQiKBV2/vNbYXrEv09zjlMiLU8+A5JhHweljT7crvUZ5vTQy9QOxXFcCLwVlJ HVSyBVkltpmlqqmWZONJTmFLkgXvKoHCepCRFlEi4r2/uL9Qz6C5+pqmak1yxFVcnmlk JlnFcafj+3uGVok62rbtkphqXloDuPcUHhpND4WJ/9n8Asw4svbRavJR43gKmi6HWPz8 0kCc6mIvtGuGHnDdsv5gx3d6ugJpCwRk7fGe9gOWddbw0L20igOKS6uX1uUBpZ79VGvs aXyQ== X-Gm-Message-State: AOAM531ppXHP9GVppnExnWvoHqWHBGexpX/nU3NxDpBEvxcnWcjZgJ+f RVDHxVtV1bZgc2kSNLKgmxHhpdd2dRw= X-Google-Smtp-Source: ABdhPJxZGrq9Ua+JFui09X56Twkk9V38jeTDoO1SKKPAbXxXCaF3hTgbJC2lD9s07HnIj7neUojFTw== X-Received: by 2002:a62:9242:0:b0:446:5771:7901 with SMTP id o63-20020a629242000000b0044657717901mr1728924pfd.81.1632362537491; Wed, 22 Sep 2021 19:02:17 -0700 (PDT) Received: from gnu-gram-1.localdomain (cpe-76-173-15-247.hawaii.res.rr.com. [76.173.15.247]) by smtp.gmail.com with ESMTPSA id o12sm4256839pgn.33.2021.09.22.19.02.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 22 Sep 2021 19:02:16 -0700 (PDT) Received: from gnu-gram-1.localdomain (localhost [IPv6:::1]) by gnu-gram-1.localdomain (Postfix) with ESMTP id 21EEEE0073; Wed, 22 Sep 2021 19:02:15 -0700 (PDT) To: gcc-patches@gcc.gnu.org Subject: [PATCH v4 1/2] Add -f[no-]direct-extern-access Date: Wed, 22 Sep 2021 19:02:06 -0700 Message-Id: <20210923020207.1414230-2-hjl.tools@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210923020207.1414230-1-hjl.tools@gmail.com> References: <20210923020207.1414230-1-hjl.tools@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3031.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_SHORT, KAM_STOCKGEN, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: "H.J. Lu via Gcc-patches" From: "H.J. Lu" Reply-To: "H.J. Lu" Cc: Florian Weimer , Jakub Jelinek Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Add -f[no-]direct-extern-access and nodirect_extern_access attribute. -fdirect-extern-access is the default and always use GOT to access undefined data and function symbols with nodirect_extern_access attribute, including in PIE and non-PIE. With -fno-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 -fno-direct-extern-access to avoid copy relocation. 4. Add ix86_reloc_rw_mask for TARGET_ASM_RELOC_RW_MASK to avoid copy relocation with -fno-direct-extern-access. gcc/ PR target/35513 PR target/100593 * common.opt: Add -fdirect-extern-access. * config/i386/i386-protos.h (ix86_force_load_from_GOT_p): Add a bool argument. * config/i386/i386.c (ix86_force_load_from_GOT_p): Add a bool argument to indicate call operand. Force non-call load from GOT for -fno-direct-extern-access or nodirect_extern_access attribute. (legitimate_pic_address_disp_p): Avoid copy relocation in PIE for -fno-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 -fno-direct-extern-access to avoid copy relocation. Check ptr_mode instead of TARGET_64BIT when selecting DW_EH_PE_sdata4. (ix86_binds_local_p): Don't treat protected data as extern and avoid copy relocation on common symbol with -fno-direct-extern-access or nodirect_extern_access attribute. (ix86_reloc_rw_mask): New to avoid copy relocation for -fno-direct-extern-access. (TARGET_ASM_RELOC_RW_MASK): New. * doc/extend.texi: Document nodirect_extern_access attribute. * doc/invoke.texi: Document -f[no-]direct-extern-access. gcc/c-family/ PR target/35513 PR target/100593 * c-attribs.c (handle_nodirect_extern_access_attribute): New. (c_common_attribute_table): Add nodirect_extern_access. gcc/testsuite/ PR target/35513 PR target/100593 * g++.dg/pr35513-1.C: New file. * g++.dg/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/c-family/c-attribs.c | 34 +++++++++++ gcc/common.opt | 4 ++ gcc/config/i386/i386-protos.h | 2 +- gcc/config/i386/i386.c | 62 ++++++++++++++++----- gcc/doc/extend.texi | 6 ++ gcc/doc/invoke.texi | 13 +++++ gcc/testsuite/g++.dg/pr35513-1.C | 25 +++++++++ gcc/testsuite/g++.dg/pr35513-2.C | 53 ++++++++++++++++++ gcc/testsuite/gcc.target/i386/pr35513-10a.c | 17 ++++++ gcc/testsuite/gcc.target/i386/pr35513-10b.c | 17 ++++++ gcc/testsuite/gcc.target/i386/pr35513-11a.c | 17 ++++++ gcc/testsuite/gcc.target/i386/pr35513-11b.c | 17 ++++++ gcc/testsuite/gcc.target/i386/pr35513-12a.c | 17 ++++++ gcc/testsuite/gcc.target/i386/pr35513-12b.c | 17 ++++++ gcc/testsuite/gcc.target/i386/pr35513-1a.c | 16 ++++++ gcc/testsuite/gcc.target/i386/pr35513-1b.c | 16 ++++++ gcc/testsuite/gcc.target/i386/pr35513-2a.c | 15 +++++ gcc/testsuite/gcc.target/i386/pr35513-2b.c | 15 +++++ gcc/testsuite/gcc.target/i386/pr35513-3a.c | 15 +++++ gcc/testsuite/gcc.target/i386/pr35513-3b.c | 15 +++++ gcc/testsuite/gcc.target/i386/pr35513-4a.c | 15 +++++ gcc/testsuite/gcc.target/i386/pr35513-4b.c | 15 +++++ gcc/testsuite/gcc.target/i386/pr35513-5a.c | 15 +++++ gcc/testsuite/gcc.target/i386/pr35513-5b.c | 15 +++++ gcc/testsuite/gcc.target/i386/pr35513-6a.c | 14 +++++ gcc/testsuite/gcc.target/i386/pr35513-6b.c | 14 +++++ gcc/testsuite/gcc.target/i386/pr35513-7a.c | 15 +++++ gcc/testsuite/gcc.target/i386/pr35513-7b.c | 15 +++++ gcc/testsuite/gcc.target/i386/pr35513-8.c | 41 ++++++++++++++ gcc/testsuite/gcc.target/i386/pr35513-9a.c | 17 ++++++ gcc/testsuite/gcc.target/i386/pr35513-9b.c | 17 ++++++ 31 files changed, 571 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/g++.dg/pr35513-1.C create mode 100644 gcc/testsuite/g++.dg/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/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index 007b928c54b..4f3bb72796d 100644 --- a/gcc/c-family/c-attribs.c +++ b/gcc/c-family/c-attribs.c @@ -86,6 +86,8 @@ static tree handle_used_attribute (tree *, tree, tree, int, bool *); static tree handle_uninitialized_attribute (tree *, tree, tree, int, bool *); static tree handle_externally_visible_attribute (tree *, tree, tree, int, bool *); +static tree handle_nodirect_extern_access_attribute (tree *, tree, tree, + int, bool *) ; static tree handle_no_reorder_attribute (tree *, tree, tree, int, bool *); static tree handle_const_attribute (tree *, tree, tree, int, bool *); @@ -340,6 +342,8 @@ const struct attribute_spec c_common_attribute_table[] = handle_retain_attribute, NULL }, { "externally_visible", 0, 0, true, false, false, false, handle_externally_visible_attribute, NULL }, + { "nodirect_extern_access", 0, 0, true, false, false, false, + handle_nodirect_extern_access_attribute, NULL }, { "no_reorder", 0, 0, true, false, false, false, handle_no_reorder_attribute, NULL }, /* The same comments as for noreturn attributes apply to const ones. */ @@ -1674,6 +1678,36 @@ handle_externally_visible_attribute (tree *pnode, tree name, 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; +} + /* Handle the "no_reorder" attribute. Arguments as in struct attribute_spec.handler. */ diff --git a/gcc/common.opt b/gcc/common.opt index b921f5e3b25..0d053f4a4dd 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1432,6 +1432,10 @@ fdiagnostics-minimum-margin-width= Common Joined UInteger Var(diagnostics_minimum_margin_width) Init(6) Set minimum width of left margin of source code when showing source. +fdirect-extern-access +Common Var(flag_direct_extern_access) Init(1) Optimization +Do not use GOT to access external symbols. + fdisable- Common Joined RejectNegative Var(common_deferred_options) Defer -fdisable-[tree|rtl|ipa]-=range1+range2 Disable an optimization pass. diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 708834ae832..bcd8dba4e12 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); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index ba89e111d28..9ca1ef512a4 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -10434,13 +10434,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: -fno-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 @@ -10448,11 +10452,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 + && (!flag_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)); } @@ -10724,7 +10733,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 + || ((flag_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))) @@ -13640,7 +13653,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. */ @@ -22350,10 +22363,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 || !flag_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; @@ -23468,10 +23481,26 @@ 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 + = (flag_direct_extern_access + && !(VAR_OR_FUNCTION_DECL_P (exp) + && lookup_attribute ("nodirect_extern_access", + DECL_ATTRIBUTES (exp)))); + 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 flag_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 || !flag_direct_extern_access) ? 3 : 0; } #endif @@ -24537,6 +24566,11 @@ ix86_libgcc_floating_mode_supported_p #define TARGET_GET_MULTILIB_ABI_NAME \ ix86_get_multilib_abi_name +#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/doc/extend.texi b/gcc/doc/extend.texi index 9501a60f20e..fa1d00820e7 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -2934,6 +2934,12 @@ produced by @command{gold}. For other linkers that cannot generate resolution file, explicit @code{externally_visible} attributes are still necessary. +@item nodirect_extern_access +@cindex @code{nodirect_extern_access} function attribute +@opindex fno-direct-extern-access +This attribute, attached to a global variable or function, is the +counterpart to option @option{-fno-direct-extern-access}. + @item flatten @cindex @code{flatten} function attribute Generally, inlining into a function is limited. For a function marked with diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 4acb94181d2..d747fad1589 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -659,6 +659,7 @@ Objective-C and Objective-C++ Dialects}. -fnon-call-exceptions -fdelete-dead-exceptions -funwind-tables @gol -fasynchronous-unwind-tables @gol -fno-gnu-unique @gol +-fno-direct-extern-access @gol -finhibit-size-directive -fcommon -fno-ident @gol -fpcc-struct-return -fpic -fPIC -fpie -fPIE -fno-plt @gol -fno-jump-tables -fno-bit-tests @gol @@ -16841,6 +16842,18 @@ through the PLT for specific external functions. In position-dependent code, a few targets also convert calls to functions that are marked to not use the PLT to use the GOT instead. +@item -fno-direct-extern-access +@opindex fno-direct-extern-access +@opindex fdirect-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. + +@strong{Warning:} shared libraries compiled with +@option{-fno-direct-extern-access} and executable compiled with +@option{-fdirect-extern-access} may not be binary compatible if +protected symbols are used in shared libraries and executable. + @item -fno-jump-tables @opindex fno-jump-tables @opindex fjump-tables diff --git a/gcc/testsuite/g++.dg/pr35513-1.C b/gcc/testsuite/g++.dg/pr35513-1.C new file mode 100644 index 00000000000..8423e826da8 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr35513-1.C @@ -0,0 +1,25 @@ +// { dg-do run } +// { dg-options "-O2 -fno-direct-extern-access" } + +#include + +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++.dg/pr35513-2.C b/gcc/testsuite/g++.dg/pr35513-2.C new file mode 100644 index 00000000000..56ed19ae1eb --- /dev/null +++ b/gcc/testsuite/g++.dg/pr35513-2.C @@ -0,0 +1,53 @@ +// { dg-do run } +// { dg-options "-O2 -fno-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..b61ea5c4e77 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr35513-10a.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpic -fno-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 } } } */ 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..3bb5fc8831f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr35513-10b.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpic -fdirect-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 } } } */ 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..8cb3d7f8482 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr35513-11a.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpic -fno-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 } } } */ 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..68e2e270769 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr35513-11b.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpic -fdirect-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 } } } */ 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..b2e64f97d54 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr35513-12a.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpic -fno-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 } } } */ 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..32031660154 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr35513-12b.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpic -fdirect-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 } } } */ 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..c5dbabc3704 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr35513-1a.c @@ -0,0 +1,16 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fno-pic -fno-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 } } } } */ 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..17bd7d127b4 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr35513-1b.c @@ -0,0 +1,16 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fno-pic -fdirect-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 } } } } */ 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..8bb7cb4c13d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr35513-2a.c @@ -0,0 +1,15 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fno-pic -fno-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 } } } } */ 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..81d1913de89 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr35513-2b.c @@ -0,0 +1,15 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fno-pic -fdirect-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 } } } } */ 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..98dc54e3bf4 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr35513-3a.c @@ -0,0 +1,15 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpie -fno-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 } } } } */ 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..e37c59efa9c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr35513-3b.c @@ -0,0 +1,15 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpie -fdirect-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 } } } } */ 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..467081dad65 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr35513-4a.c @@ -0,0 +1,15 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fplt -fno-pic -fno-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 } } } */ 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..273ee544803 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr35513-4b.c @@ -0,0 +1,15 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fplt -fno-pic -fdirect-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 } } } */ 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..b0e61b08ba9 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr35513-5a.c @@ -0,0 +1,15 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fplt -fpic -fno-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 } } } */ 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..6d2876823af --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr35513-5b.c @@ -0,0 +1,15 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fplt -fpic -fdirect-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 } } } */ 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..270504b8d0e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr35513-6a.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fplt -fno-pic -fno-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 } } } */ 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..4cc9e2be186 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr35513-6b.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fplt -fno-pic -fdirect-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 } } } */ 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..2c5a83ddef8 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr35513-7a.c @@ -0,0 +1,15 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fplt -fpic -fno-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 } } } */ 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..9211d339809 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr35513-7b.c @@ -0,0 +1,15 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fplt -fpic -fdirect-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 } } } */ 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..545979e99c2 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr35513-8.c @@ -0,0 +1,41 @@ +/* { dg-do assemble { target { *-*-linux* && { ! ia32 } } } } */ +/* { dg-require-effective-target maybe_x32 } */ +/* { dg-options "-mx32 -O2 -fno-pic -fexceptions -fasynchronous-unwind-tables -fno-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); +} 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..10b2c24ac87 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr35513-9a.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpic -fno-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 } } } */ 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..860c2e36034 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr35513-9b.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpic -fdirect-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 } } } */