vsk created this revision.

While building a project with code coverage enabled, we can link in
dependencies which export a weak definition of __llvm_profile_filename.

After r306710, linking in the profiling runtime could pull in a weak
definition of this symbol from a dependency, instead of from within the
runtime's archive.

This inconsistency causes issues during API verification, and is also a
practical problem (the symbol would go missing were the dependent dylib
to be switched out). Introduce a LinkFirst runtime link option to make
sure we always search the profiling runtime for this symbol first.

rdar://problem/33271080


https://reviews.llvm.org/D35385

Files:
  lib/Driver/ToolChains/Darwin.cpp
  lib/Driver/ToolChains/Darwin.h
  test/Driver/darwin-ld.c

Index: test/Driver/darwin-ld.c
===================================================================
--- test/Driver/darwin-ld.c
+++ test/Driver/darwin-ld.c
@@ -341,3 +341,13 @@
 // RUN: %clang -target x86_64-apple-darwin12 %t.o -fsave-optimization-record -fprofile-instr-use=blah -### -o foo/bar.out 2> %t.log
 // RUN: FileCheck -check-prefix=PASS_REMARKS_WITH_HOTNESS %s < %t.log
 // PASS_REMARKS_WITH_HOTNESS: "-mllvm" "-lto-pass-remarks-output" "-mllvm" "foo/bar.out.opt.yaml" "-mllvm" "-lto-pass-remarks-with-hotness"
+
+// RUN: %clang -target x86_64-apple-ios6.0 -miphoneos-version-min=6.0 -fprofile-instr-generate -### %t.o 2> %t.log
+// RUN: FileCheck -check-prefix=LINK_PROFILE_FIRST %s < %t.log
+// RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate -### %t.o 2> %t.log
+// RUN: FileCheck -check-prefix=LINK_PROFILE_FIRST %s < %t.log
+// RUN: %clang -target i386-apple-darwin9 -fprofile-instr-generate -### %t.o 2> %t.log
+// RUN: FileCheck -check-prefix=LINK_PROFILE_FIRST %s < %t.log
+// RUN: %clang -target arm64-apple-ios5.0 -miphoneos-version-min=5.0 -fprofile-instr-generate -### %t.o 2> %t.log
+// RUN: FileCheck -check-prefix=LINK_PROFILE_FIRST %s < %t.log
+// LINK_PROFILE_FIRST: {{ld(.exe)?"}} "{{[^"]+}}libclang_rt.profile_{{[a-z]+}}.a"
Index: lib/Driver/ToolChains/Darwin.h
===================================================================
--- lib/Driver/ToolChains/Darwin.h
+++ lib/Driver/ToolChains/Darwin.h
@@ -152,8 +152,12 @@
                               llvm::opt::ArgStringList &CmdArgs) const {}
 
   /// Add the linker arguments to link the compiler runtime library.
+  ///
+  /// FIXME: This API is intended for use with embedded libraries only, and is
+  /// misleadingly named.
   virtual void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
                                      llvm::opt::ArgStringList &CmdArgs) const;
+
   virtual void AddFuzzerLinkArgs(const llvm::opt::ArgList &Args,
                                llvm::opt::ArgStringList &CmdArgs) const;
 
@@ -171,10 +175,26 @@
   /// Is the target either iOS or an iOS simulator?
   bool isTargetIOSBased() const { return false; }
 
+  /// Options to control how a runtime library is linked.
+  enum RuntimeLinkOptions : unsigned {
+    // Link the library in even if it can't be found in the VFS.
+    RLO_AlwaysLink = 1 << 0,
+
+    // Use the embedded runtime from the macho_embedded directory.
+    RLO_IsEmbedded = 1 << 1,
+
+    // Emit rpaths for @executable_path as well as the resource directory.
+    RLO_AddRPath = 1 << 2,
+
+    //< Link the library in before any others.
+    RLO_FirstLink = 1 << 3,
+  };
+
+  /// Add a runtime library to the list of items to link.
   void AddLinkRuntimeLib(const llvm::opt::ArgList &Args,
                          llvm::opt::ArgStringList &CmdArgs,
-                         StringRef DarwinLibName, bool AlwaysLink = false,
-                         bool IsEmbedded = false, bool AddRPath = false) const;
+                         StringRef DarwinLibName,
+                         RuntimeLinkOptions Opts = RuntimeLinkOptions()) const;
 
   /// Add any profiling runtime libraries that are needed. This is essentially a
   /// MachO specific version of addProfileRT in Tools.cpp.
Index: lib/Driver/ToolChains/Darwin.cpp
===================================================================
--- lib/Driver/ToolChains/Darwin.cpp
+++ lib/Driver/ToolChains/Darwin.cpp
@@ -493,7 +493,7 @@
   if (getToolChain().getSanitizerArgs().needsSafeStackRt()) {
     getMachOToolChain().AddLinkRuntimeLib(Args, CmdArgs,
                                           "libclang_rt.safestack_osx.a",
-                                          /*AlwaysLink=*/true);
+                                          toolchains::Darwin::RLO_AlwaysLink);
   }
 
   Args.AddAllArgs(CmdArgs, options::OPT_L);
@@ -897,25 +897,31 @@
 }
 
 void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
-                              StringRef DarwinLibName, bool AlwaysLink,
-                              bool IsEmbedded, bool AddRPath) const {
+                              StringRef DarwinLibName,
+                              RuntimeLinkOptions Opts) const {
   SmallString<128> Dir(getDriver().ResourceDir);
-  llvm::sys::path::append(Dir, "lib", IsEmbedded ? "macho_embedded" : "darwin");
+  llvm::sys::path::append(
+      Dir, "lib", (Opts & RLO_IsEmbedded) ? "macho_embedded" : "darwin");
 
   SmallString<128> P(Dir);
   llvm::sys::path::append(P, DarwinLibName);
 
   // For now, allow missing resource libraries to support developers who may
   // not have compiler-rt checked out or integrated into their build (unless
   // we explicitly force linking with this library).
-  if (AlwaysLink || getVFS().exists(P))
-    CmdArgs.push_back(Args.MakeArgString(P));
+  if ((Opts & RLO_AlwaysLink) || getVFS().exists(P)) {
+    const char *LibArg = Args.MakeArgString(P);
+    if (Opts & RLO_FirstLink)
+      CmdArgs.insert(CmdArgs.begin(), LibArg);
+    else
+      CmdArgs.push_back(LibArg);
+  }
 
   // Adding the rpaths might negatively interact when other rpaths are involved,
   // so we should make sure we add the rpaths last, after all user-specified
   // rpaths. This is currently true from this place, but we need to be
   // careful if this function is ever called before user's rpaths are emitted.
-  if (AddRPath) {
+  if (Opts & RLO_AddRPath) {
     assert(DarwinLibName.endswith(".dylib") && "must be a dynamic library");
 
     // Add @executable_path to rpath to support having the dylib copied with
@@ -996,20 +1002,20 @@
                               ArgStringList &CmdArgs) const {
   if (!needsProfileRT(Args)) return;
 
-  AddLinkRuntimeLib(Args, CmdArgs, (Twine("libclang_rt.profile_") +
-       getOSLibraryNameSuffix() + ".a").str(),
-                    /*AlwaysLink*/ true);
+  AddLinkRuntimeLib(
+      Args, CmdArgs,
+      (Twine("libclang_rt.profile_") + getOSLibraryNameSuffix() + ".a").str(),
+      RuntimeLinkOptions(RLO_AlwaysLink | RLO_FirstLink));
 }
 
 void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args,
                                           ArgStringList &CmdArgs,
                                           StringRef Sanitizer) const {
-  AddLinkRuntimeLib(
-      Args, CmdArgs,
-      (Twine("libclang_rt.") + Sanitizer + "_" +
-       getOSLibraryNameSuffix() + "_dynamic.dylib").str(),
-      /*AlwaysLink*/ true, /*IsEmbedded*/ false,
-      /*AddRPath*/ true);
+  AddLinkRuntimeLib(Args, CmdArgs,
+                    (Twine("libclang_rt.") + Sanitizer + "_" +
+                     getOSLibraryNameSuffix() + "_dynamic.dylib")
+                        .str(),
+                    RuntimeLinkOptions(RLO_AlwaysLink | RLO_AddRPath));
 }
 
 ToolChain::RuntimeLibType DarwinClang::GetRuntimeLibType(
@@ -1059,7 +1065,7 @@
     StringRef OS = isTargetMacOS() ? "osx" : "iossim";
     AddLinkRuntimeLib(Args, CmdArgs,
                       (Twine("libclang_rt.stats_client_") + OS + ".a").str(),
-                      /*AlwaysLink=*/true);
+                      RLO_AlwaysLink);
     AddLinkSanitizerLibArgs(Args, CmdArgs, "stats");
   }
   if (Sanitize.needsEsanRt())
@@ -1709,7 +1715,7 @@
           : "soft";
   CompilerRT += Args.hasArg(options::OPT_fPIC) ? "_pic.a" : "_static.a";
 
-  AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, false, true);
+  AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, RLO_IsEmbedded);
 }
 
 bool Darwin::isAlignedAllocationUnavailable() const {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to