gold, ld: Implement -z start-stop-visibility=... option.
authorRoland McGrath <mcgrathr@google.com>
Mon, 15 Jun 2020 18:45:02 +0000 (11:45 -0700)
committerRoland McGrath <mcgrathr@google.com>
Mon, 15 Jun 2020 18:45:02 +0000 (11:45 -0700)
gold/
Implement -z start-stop-visibility=... option.
* options.h (class General_options): Handle -z start-stop-visibility=.
(General_options::start_stop_visibility_enum): New public method.
(General_options::set_start_stop_visibility_enum): New private method.
(General_options::start_stop_visibility_enum_): New private member.
* options.cc (General_options::General_options): Add initializer.
(General_options::finalize): Set this->start_stop_visibility_enum_
from string value.
* layout.cc (Layout::define_section_symbols): Use option setting.

bfd/
* elflink.c (bfd_elf_define_start_stop): Use start_stop_visibility
field of bfd_link_info.

include/
* bfdlink.h (struct bfd_link_info): New field start_stop_visibility.

ld/
* NEWS: Mention -z start-stop-visibility=... option for ELF.
* ld.texi (Options): Document -z start-stop-visibility=... option.
* ldmain.c (main): Initialize link_info.start_stop_visibility.
* emultempl/elf.em (gld${EMULATION_NAME}_handle_option):
Parse -z start-stop-visibility=... option.

13 files changed:
bfd/ChangeLog
bfd/elflink.c
gold/ChangeLog
gold/layout.cc
gold/options.cc
gold/options.h
include/ChangeLog
include/bfdlink.h
ld/ChangeLog
ld/NEWS
ld/emultempl/elf.em
ld/ld.texi
ld/ldmain.c

index 6543260b2986363b0ba7d81e8580fcf9d7c0d941..741e96962b1df7a94f33404da53375920b76d1b8 100644 (file)
@@ -1,3 +1,8 @@
+2020-06-15  Roland McGrath  <mcgrathr@google.com>
+
+       * elflink.c (bfd_elf_define_start_stop): Use start_stop_visibility
+       field of bfd_link_info.
+
 2020-06-15  Alan Modra  <amodra@gmail.com>
 
        * config.bfd: Obsolete powerpcle-*-pe targets.
        (aout_link_add_symbols): e517df3dbf7 PR 19629 - Check for out of
        range string table offsets.
        531336e3a0b PR 20909 - Fix off-by-one error in check for an
-       illegal string offset. 
+       illegal string offset.
        (aout_link_includes_newfunc): Add comment.
        (pdp11_aout_link_input_section): ad756e3f9e6 - Return with an error
        on unexpected relocation type rather than ASSERT.
index ac00f2984e91c5e384acf0f044861e3b711fc053..14d8d159da7404748efafb8be9041878effb2bcd 100644 (file)
@@ -14837,7 +14837,8 @@ bfd_elf_define_start_stop (struct bfd_link_info *info,
       else
        {
          if (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
-           h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_PROTECTED;
+           h->other = ((h->other & ~ELF_ST_VISIBILITY (-1))
+                       | info->start_stop_visibility);
          if (was_dynamic)
            bfd_elf_link_record_dynamic_symbol (info, h);
        }
index f3d3715936278bbffde883a4dfacdbda2968708c..1f9c52334b3e02f651833d2e1cecc477b534e83c 100644 (file)
@@ -1,3 +1,15 @@
+2020-06-15  Roland McGrath  <mcgrathr@google.com>
+
+       Implement -z start-stop-visibility=... option.
+       * options.h (class General_options): Handle -z start-stop-visibility=.
+       (General_options::start_stop_visibility_enum): New public method.
+       (General_options::set_start_stop_visibility_enum): New private method.
+       (General_options::start_stop_visibility_enum_): New private member.
+       * options.cc (General_options::General_options): Add initializer.
+       (General_options::finalize): Set this->start_stop_visibility_enum_
+       from string value.
+       * layout.cc (Layout::define_section_symbols): Use option setting.
+
 2020-06-06  Alan Modra  <amodra@gmail.com>
 
        * powerpc.cc: Update throughout for reloc renaming.
index be437f3900e43484be96b20ef859b58c0b4feb5f..b3b0c5701d3c92e6debae0d35e504dabffbea804 100644 (file)
@@ -2474,6 +2474,7 @@ Layout::create_initial_dynamic_sections(Symbol_table* symtab)
 void
 Layout::define_section_symbols(Symbol_table* symtab)
 {
+  const elfcpp::STV visibility = parameters->options().start_stop_visibility_enum();
   for (Section_list::const_iterator p = this->section_list_.begin();
        p != this->section_list_.end();
        ++p)
@@ -2495,7 +2496,7 @@ Layout::define_section_symbols(Symbol_table* symtab)
                                        0, // symsize
                                        elfcpp::STT_NOTYPE,
                                        elfcpp::STB_GLOBAL,
-                                       elfcpp::STV_PROTECTED,
+                                       visibility,
                                        0, // nonvis
                                        false, // offset_is_from_end
                                        true); // only_if_ref
@@ -2508,7 +2509,7 @@ Layout::define_section_symbols(Symbol_table* symtab)
                                        0, // symsize
                                        elfcpp::STT_NOTYPE,
                                        elfcpp::STB_GLOBAL,
-                                       elfcpp::STV_PROTECTED,
+                                       visibility,
                                        0, // nonvis
                                        true, // offset_is_from_end
                                        true); // only_if_ref
index 94867b361a2479dc4bfd752f7e20d1d50dd041ec..b13ae71ce14b9ebfbf240a3007d76c936ddf0b28 100644 (file)
@@ -997,7 +997,8 @@ General_options::General_options()
     fix_v4bx_(FIX_V4BX_NONE),
     endianness_(ENDIANNESS_NOT_SET),
     discard_locals_(DISCARD_SEC_MERGE),
-    orphan_handling_enum_(ORPHAN_PLACE)
+    orphan_handling_enum_(ORPHAN_PLACE),
+    start_stop_visibility_enum_(elfcpp::STV_PROTECTED)
 {
   // Turn off option registration once construction is complete.
   gold::options::ready_to_register = false;
@@ -1169,6 +1170,19 @@ General_options::finalize()
         this->set_orphan_handling_enum(ORPHAN_ERROR);
     }
 
+  // Parse the -z start-stop-visibility argument.
+  if (this->user_set_start_stop_visibility())
+    {
+      if (strcmp(this->start_stop_visibility(), "default") == 0)
+        this->set_start_stop_visibility_enum(elfcpp::STV_DEFAULT);
+      else if (strcmp(this->start_stop_visibility(), "internal") == 0)
+        this->set_start_stop_visibility_enum(elfcpp::STV_INTERNAL);
+      else if (strcmp(this->start_stop_visibility(), "hidden") == 0)
+        this->set_start_stop_visibility_enum(elfcpp::STV_HIDDEN);
+      else if (strcmp(this->start_stop_visibility(), "protected") == 0)
+        this->set_start_stop_visibility_enum(elfcpp::STV_PROTECTED);
+    }
+
   // -M is equivalent to "-Map -".
   if (this->print_map() && !this->user_set_Map())
     {
index b2059d984cdc461491bee1394ba5d4afc9cb1282..f0e9fbddcd5f77d6a78a405dcc5ecdbe4f786f17 100644 (file)
@@ -1500,6 +1500,11 @@ class General_options
              N_("Don't mark variables read-only after relocation"));
   DEFINE_uint64(stack_size, options::DASH_Z, '\0', 0,
                N_("Set PT_GNU_STACK segment p_memsz to SIZE"), N_("SIZE"));
+  DEFINE_enum(start_stop_visibility, options::DASH_Z, '\0', "protected",
+              N_("ELF symbol visibility for synthesized "
+                 "__start_* and __stop_* symbols"),
+              ("[default,internal,hidden,protected]"),
+              {"default", "internal", "hidden", "protected"});
   DEFINE_bool(text, options::DASH_Z, '\0', false,
              N_("Do not permit relocations in read-only segments"),
              N_("Permit relocations in read-only segments"));
@@ -1750,6 +1755,10 @@ class General_options
   orphan_handling_enum() const
   { return this->orphan_handling_enum_; }
 
+  elfcpp::STV
+  start_stop_visibility_enum() const
+  { return this->start_stop_visibility_enum_; }
+
  private:
   // Don't copy this structure.
   General_options(const General_options&);
@@ -1809,6 +1818,10 @@ class General_options
   set_orphan_handling_enum(Orphan_handling value)
   { this->orphan_handling_enum_ = value; }
 
+  void
+  set_start_stop_visibility_enum(elfcpp::STV value)
+  { this->start_stop_visibility_enum_ = value; }
+
   // These are called by finalize() to set up the search-path correctly.
   void
   add_to_library_path_with_sysroot(const std::string& arg)
@@ -1876,6 +1889,8 @@ class General_options
   std::vector<Position_dependent_options*> options_stack_;
   // Orphan handling option, decoded to an enum value.
   Orphan_handling orphan_handling_enum_;
+  // Symbol visibility for __start_* / __stop_* magic symbols.
+  elfcpp::STV start_stop_visibility_enum_;
 };
 
 // The position-dependent options.  We use this to store the state of
index 248866cbc94b82d2e368b0f716899f6eec1eb242..f30e5e2a24a0c17192c33aacae26dc3d5bb89acc 100644 (file)
@@ -1,3 +1,7 @@
+2020-06-12  Roland McGrath  <mcgrathr@google.com>
+
+       * bfdlink.h (struct bfd_link_info): New field start_stop_visibility.
+
 2020-06-12  Nelson Chu  <nelson.chu@sifive.com>
 
        * opcode/riscv-opc.h: Update the defined versions of CSR from
index 34a0d2ec4efaec3334af336e729be2d1cb1a6e93..716343338302708f0331289fe526fe9aef67a32c 100644 (file)
@@ -542,10 +542,10 @@ struct bfd_link_info
      Normally these optimizations are disabled by default but some targets
      prefer to enable them by default.  So this field is a tri-state variable.
      The values are:
-     
+
      zero: Enable the optimizations (either from --relax being specified on
        the command line or the backend's before_allocation emulation function.
-       
+
      positive: The user has requested that these optimizations be disabled.
        (Via the --no-relax command line option).
 
@@ -649,6 +649,9 @@ struct bfd_link_info
   /* May be used to set DT_FLAGS_1 for ELF. */
   bfd_vma flags_1;
 
+  /* May be used to set ELF visibility for __start_* / __stop_.  */
+  unsigned int start_stop_visibility;
+
   /* Start and end of RELRO region.  */
   bfd_vma relro_start, relro_end;
 
index c6de0441d96d6d2846f728fa44df35d7af5d26a9..6700e727d83299ba18bd4b09e616995ed22c68ac 100644 (file)
@@ -1,3 +1,11 @@
+2020-06-15  Roland McGrath  <mcgrathr@google.com>
+
+       * NEWS: Mention -z start-stop-visibility=... option for ELF.
+       * ld.texi (Options): Document -z start-stop-visibility=... option.
+       * ldmain.c (main): Initialize link_info.start_stop_visibility.
+       * emultempl/elf.em (gld${EMULATION_NAME}_handle_option):
+       Parse -z start-stop-visibility=... option.
+
 2020-06-15  Alan Modra  <amodra@gmail.com>
 
        * testsuite/ld-scripts/include.exp: Don't load ld-lib.exp.
diff --git a/ld/NEWS b/ld/NEWS
index 485e1cf5b9a3ffcbb36e4d0d084a814a5e88e4c5..6955937429ba76a09a43be8fe202863d4518f07e 100644 (file)
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -25,6 +25,9 @@
   searched relative to the directory of the linker script before other search
   paths.
 
+* Add ELF linker command-line option `-z start-stop-visibility=...' to control
+  the visibility of synthetic `__start_SECNAME` and `__stop_SECNAME` symbols.
+
 Changes in 2.34:
 
 * The ld check for "PHDR segment not covered by LOAD segment" is more
index c4979eb9538234f9629bc32a5272ad07c2d358cd..c577e8b2e61b8c128fc309636cc9b443141a354b 100644 (file)
@@ -749,6 +749,21 @@ fragment <<EOF
        {
          link_info.flags_1 |= DF_1_GLOBAUDIT;
        }
+      else if (CONST_STRNEQ (optarg, "start-stop-visibility="))
+       {
+         if (strcmp (optarg, "start-stop-visibility=default") == 0)
+           link_info.start_stop_visibility = STV_DEFAULT;
+         else if (strcmp (optarg, "start-stop-visibility=internal") == 0)
+           link_info.start_stop_visibility = STV_INTERNAL;
+         else if (strcmp (optarg, "start-stop-visibility=hidden") == 0)
+           link_info.start_stop_visibility = STV_HIDDEN;
+         else if (strcmp (optarg, "start-stop-visibility=protected") == 0)
+           link_info.start_stop_visibility = STV_PROTECTED;
+         else
+           einfo (_("%F%P: invalid visibility in \`-z %s'; "
+                    "must be default, internal, hidden, or protected"),
+                  optarg);
+       }
 EOF
 
 if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
index bf474d4c62b04f7d1de3016f6dec8b1f8ca0cfac..b89c1a57c0b4e6476a003cec46e278bc8c29a2d5 100644 (file)
@@ -1373,6 +1373,19 @@ Specify a stack size for an ELF @code{PT_GNU_STACK} segment.
 Specifying zero will override any default non-zero sized
 @code{PT_GNU_STACK} segment creation.
 
+@item start-stop-visibility=@var{value}
+@cindex visibility
+@cindex ELF symbol visibility
+Specify the ELF symbol visibility for synthesized
+@code{__start_SECNAME} and @code{__stop_SECNAME} symbols (@pxref{Input
+Section Example}).  @var{value} must be exactly @samp{default},
+@samp{internal}, @samp{hidden}, or @samp{protected}.  If no @samp{-z
+start-stop-visibility} option is given, @samp{protected} is used for
+compatibility with historical practice.  However, it's highly
+recommended to use @samp{-z start-stop-visibility=hidden} in new
+programs and shared libraries so that these symbols are not exported
+between shared objects, which is not usually what's intended.
+
 @item text
 @itemx notext
 @itemx textoff
index e2c559ea3e03fc7d8250ba2327f70d293c788455..b0ce69f11860b89c501fe1dc36f0e5e9b16281cb 100644 (file)
@@ -27,6 +27,7 @@
 #include "bfdlink.h"
 #include "ctf-api.h"
 #include "filenames.h"
+#include "elf/common.h"
 
 #include "ld.h"
 #include "ldmain.h"
@@ -307,6 +308,7 @@ main (int argc, char **argv)
 #ifdef DEFAULT_NEW_DTAGS
   link_info.new_dtags = DEFAULT_NEW_DTAGS;
 #endif
+  link_info.start_stop_visibility = STV_PROTECTED;
 
   ldfile_add_arch ("");
   emulation = get_emulation (argc, argv);