[lld] fffd05d - [ELF] Add -z start-stop-visibility= to set __start_/__stop_ symbol visibility

Petr Hosek via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 23 16:00:19 PDT 2020


Author: Petr Hosek
Date: 2020-06-23T15:59:59-07:00
New Revision: fffd05d52526e0718acf23b4dd34f200e2c79f67

URL: https://github.com/llvm/llvm-project/commit/fffd05d52526e0718acf23b4dd34f200e2c79f67
DIFF: https://github.com/llvm/llvm-project/commit/fffd05d52526e0718acf23b4dd34f200e2c79f67.diff

LOG: [ELF] Add -z start-stop-visibility= to set __start_/__stop_ symbol visibility

This matches the equivalent flag implemented in GNU linkers, see
https://sourceware.org/pipermail/binutils/2020-June/111685.html for
the associated discussion.

Differential Revision: https://reviews.llvm.org/D55682

Added: 
    lld/test/ELF/startstop-visibility.s

Modified: 
    lld/ELF/Config.h
    lld/ELF/Driver.cpp
    lld/ELF/Writer.cpp

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index cfdd1ebf0b03..9486ef233037 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -230,6 +230,7 @@ struct Configuration {
   bool zRelro;
   bool zRodynamic;
   bool zShstk;
+  uint8_t zStartStopVisibility;
   bool zText;
   bool zRetpolineplt;
   bool zWxneeded;

diff  --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 7430e0d1099d..28942b9475c5 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -411,6 +411,24 @@ static GnuStackKind getZGnuStack(opt::InputArgList &args) {
   return GnuStackKind::NoExec;
 }
 
+static uint8_t getZStartStopVisibility(opt::InputArgList &args) {
+  for (auto *arg : args.filtered_reverse(OPT_z)) {
+    std::pair<StringRef, StringRef> kv = StringRef(arg->getValue()).split('=');
+    if (kv.first == "start-stop-visibility") {
+      if (kv.second == "default")
+        return STV_DEFAULT;
+      else if (kv.second == "internal")
+        return STV_INTERNAL;
+      else if (kv.second == "hidden")
+        return STV_HIDDEN;
+      else if (kv.second == "protected")
+        return STV_PROTECTED;
+      error("unknown -z start-stop-visibility= value: " + StringRef(kv.second));
+    }
+  }
+  return STV_PROTECTED;
+}
+
 static bool isKnownZFlag(StringRef s) {
   return s == "combreloc" || s == "copyreloc" || s == "defs" ||
          s == "execstack" || s == "force-bti" || s == "force-ibt" ||
@@ -426,7 +444,8 @@ static bool isKnownZFlag(StringRef s) {
          s == "rela" || s == "relro" || s == "retpolineplt" ||
          s == "rodynamic" || s == "shstk" || s == "text" || s == "undefs" ||
          s == "wxneeded" || s.startswith("common-page-size=") ||
-         s.startswith("max-page-size=") || s.startswith("stack-size=");
+         s.startswith("max-page-size=") || s.startswith("stack-size=") ||
+         s.startswith("start-stop-visibility=");
 }
 
 // Report an error for an unknown -z option.
@@ -1046,6 +1065,7 @@ static void readConfigs(opt::InputArgList &args) {
   config->zSeparate = getZSeparate(args);
   config->zShstk = hasZOption(args, "shstk");
   config->zStackSize = args::getZOptionValue(args, OPT_z, "stack-size", 0);
+  config->zStartStopVisibility = getZStartStopVisibility(args);
   config->zText = getZFlag(args, "text", "notext", true);
   config->zWxneeded = hasZOption(args, "wxneeded");
 

diff  --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 57e006689252..b9fd03bc2eda 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -2229,8 +2229,10 @@ void Writer<ELFT>::addStartStopSymbols(OutputSection *sec) {
   StringRef s = sec->name;
   if (!isValidCIdentifier(s))
     return;
-  addOptionalRegular(saver.save("__start_" + s), sec, 0, STV_PROTECTED);
-  addOptionalRegular(saver.save("__stop_" + s), sec, -1, STV_PROTECTED);
+  addOptionalRegular(saver.save("__start_" + s), sec, 0,
+                     config->zStartStopVisibility);
+  addOptionalRegular(saver.save("__stop_" + s), sec, -1,
+                     config->zStartStopVisibility);
 }
 
 static bool needsPtLoad(OutputSection *sec) {

diff  --git a/lld/test/ELF/startstop-visibility.s b/lld/test/ELF/startstop-visibility.s
new file mode 100644
index 000000000000..e6c5b1b707c0
--- /dev/null
+++ b/lld/test/ELF/startstop-visibility.s
@@ -0,0 +1,45 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
+
+# RUN: ld.lld %t.o -o %t
+# RUN: llvm-readelf -s %t | FileCheck %s
+
+# CHECK: 0 NOTYPE GLOBAL PROTECTED 2 __start_aaa
+# CHECK: 0 NOTYPE GLOBAL PROTECTED 2 __stop_aaa
+
+# RUN: ld.lld -z start-stop-visibility=default %t.o -o %t1
+# RUN: llvm-readelf -s %t1 | FileCheck --check-prefix=CHECK-DEFAULT %s
+
+# CHECK-DEFAULT: 0 NOTYPE GLOBAL DEFAULT 2 __start_aaa
+# CHECK-DEFAULT: 0 NOTYPE GLOBAL DEFAULT 2 __stop_aaa
+
+# RUN: ld.lld -z start-stop-visibility=internal %t.o -o %t2
+# RUN: llvm-readelf -s %t2 | FileCheck --check-prefix=CHECK-INTERNAL %s
+
+# CHECK-INTERNAL: 0 NOTYPE LOCAL INTERNAL 2 __start_aaa
+# CHECK-INTERNAL: 0 NOTYPE LOCAL INTERNAL 2 __stop_aaa
+
+# RUN: ld.lld -z start-stop-visibility=hidden %t.o -o %t3
+# RUN: llvm-readelf -s %t3 | FileCheck --check-prefix=CHECK-HIDDEN %s
+
+# CHECK-HIDDEN: 0 NOTYPE LOCAL HIDDEN 2 __start_aaa
+# CHECK-HIDDEN: 0 NOTYPE LOCAL HIDDEN 2 __stop_aaa
+
+# RUN: ld.lld -z start-stop-visibility=protected %t.o -o %t4
+# RUN: llvm-readelf -s %t4 | FileCheck --check-prefix=CHECK-PROTECTED %s
+
+# CHECK-PROTECTED: 0 NOTYPE GLOBAL PROTECTED 2 __start_aaa
+# CHECK-PROTECTED: 0 NOTYPE GLOBAL PROTECTED 2 __stop_aaa
+
+# RUN: not ld.lld -z start-stop-visibility=aaa %t.o -o /dev/null
+# CHECK-ERROR: error: unknown -z start-stop-visibility= value: aaa
+
+.quad __start_aaa
+.quad __stop_aaa
+.section aaa,"ax"
+
+.global _start
+.text
+_start:
+  nop


        


More information about the llvm-commits mailing list