Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 6370edb

Browse files
committed
[Driver] Darwin: Link in the profile runtime archive first
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 Differential Revision: https://reviews.llvm.org/D35385 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@313065 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent efd1952 commit 6370edb

File tree

3 files changed

+57
-20
lines changed

3 files changed

+57
-20
lines changed

lib/Driver/ToolChains/Darwin.cpp

+26-18
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
494494
if (getToolChain().getSanitizerArgs().needsSafeStackRt()) {
495495
getMachOToolChain().AddLinkRuntimeLib(Args, CmdArgs,
496496
"libclang_rt.safestack_osx.a",
497-
/*AlwaysLink=*/true);
497+
toolchains::Darwin::RLO_AlwaysLink);
498498
}
499499

500500
Args.AddAllArgs(CmdArgs, options::OPT_L);
@@ -897,25 +897,31 @@ unsigned DarwinClang::GetDefaultDwarfVersion() const {
897897
}
898898

899899
void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
900-
StringRef DarwinLibName, bool AlwaysLink,
901-
bool IsEmbedded, bool AddRPath) const {
900+
StringRef DarwinLibName,
901+
RuntimeLinkOptions Opts) const {
902902
SmallString<128> Dir(getDriver().ResourceDir);
903-
llvm::sys::path::append(Dir, "lib", IsEmbedded ? "macho_embedded" : "darwin");
903+
llvm::sys::path::append(
904+
Dir, "lib", (Opts & RLO_IsEmbedded) ? "macho_embedded" : "darwin");
904905

905906
SmallString<128> P(Dir);
906907
llvm::sys::path::append(P, DarwinLibName);
907908

908909
// For now, allow missing resource libraries to support developers who may
909910
// not have compiler-rt checked out or integrated into their build (unless
910911
// we explicitly force linking with this library).
911-
if (AlwaysLink || getVFS().exists(P))
912-
CmdArgs.push_back(Args.MakeArgString(P));
912+
if ((Opts & RLO_AlwaysLink) || getVFS().exists(P)) {
913+
const char *LibArg = Args.MakeArgString(P);
914+
if (Opts & RLO_FirstLink)
915+
CmdArgs.insert(CmdArgs.begin(), LibArg);
916+
else
917+
CmdArgs.push_back(LibArg);
918+
}
913919

914920
// Adding the rpaths might negatively interact when other rpaths are involved,
915921
// so we should make sure we add the rpaths last, after all user-specified
916922
// rpaths. This is currently true from this place, but we need to be
917923
// careful if this function is ever called before user's rpaths are emitted.
918-
if (AddRPath) {
924+
if (Opts & RLO_AddRPath) {
919925
assert(DarwinLibName.endswith(".dylib") && "must be a dynamic library");
920926

921927
// Add @executable_path to rpath to support having the dylib copied with
@@ -984,21 +990,23 @@ void Darwin::addProfileRTLibs(const ArgList &Args,
984990
ArgStringList &CmdArgs) const {
985991
if (!needsProfileRT(Args)) return;
986992

987-
AddLinkRuntimeLib(Args, CmdArgs, (Twine("libclang_rt.profile_") +
988-
getOSLibraryNameSuffix() + ".a").str(),
989-
/*AlwaysLink*/ true);
993+
AddLinkRuntimeLib(
994+
Args, CmdArgs,
995+
(Twine("libclang_rt.profile_") + getOSLibraryNameSuffix() + ".a").str(),
996+
RuntimeLinkOptions(RLO_AlwaysLink | RLO_FirstLink));
990997
}
991998

992999
void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args,
9931000
ArgStringList &CmdArgs,
9941001
StringRef Sanitizer,
9951002
bool Shared) const {
996-
AddLinkRuntimeLib(
997-
Args, CmdArgs,
998-
(Twine("libclang_rt.") + Sanitizer + "_" +
999-
getOSLibraryNameSuffix() + (Shared ? "_dynamic.dylib" : ".a")).str(),
1000-
/*AlwaysLink*/ true, /*IsEmbedded*/ false,
1001-
/*AddRPath*/ Shared);
1003+
auto RLO = RuntimeLinkOptions(RLO_AlwaysLink | (Shared ? RLO_AddRPath : 0U));
1004+
AddLinkRuntimeLib(Args, CmdArgs,
1005+
(Twine("libclang_rt.") + Sanitizer + "_" +
1006+
getOSLibraryNameSuffix() +
1007+
(Shared ? "_dynamic.dylib" : ".a"))
1008+
.str(),
1009+
RLO);
10021010
}
10031011

10041012
ToolChain::RuntimeLibType DarwinClang::GetRuntimeLibType(
@@ -1054,7 +1062,7 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
10541062
StringRef OS = isTargetMacOS() ? "osx" : "iossim";
10551063
AddLinkRuntimeLib(Args, CmdArgs,
10561064
(Twine("libclang_rt.stats_client_") + OS + ".a").str(),
1057-
/*AlwaysLink=*/true);
1065+
RLO_AlwaysLink);
10581066
AddLinkSanitizerLibArgs(Args, CmdArgs, "stats");
10591067
}
10601068
if (Sanitize.needsEsanRt())
@@ -1736,7 +1744,7 @@ void MachO::AddLinkRuntimeLibArgs(const ArgList &Args,
17361744
: "soft";
17371745
CompilerRT += Args.hasArg(options::OPT_fPIC) ? "_pic.a" : "_static.a";
17381746

1739-
AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, false, true);
1747+
AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, RLO_IsEmbedded);
17401748
}
17411749

17421750
bool Darwin::isAlignedAllocationUnavailable() const {

lib/Driver/ToolChains/Darwin.h

+21-2
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@ class LLVM_LIBRARY_VISIBILITY MachO : public ToolChain {
152152
llvm::opt::ArgStringList &CmdArgs) const {}
153153

154154
/// Add the linker arguments to link the compiler runtime library.
155+
///
156+
/// FIXME: This API is intended for use with embedded libraries only, and is
157+
/// misleadingly named.
155158
virtual void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
156159
llvm::opt::ArgStringList &CmdArgs) const;
157160

@@ -169,10 +172,26 @@ class LLVM_LIBRARY_VISIBILITY MachO : public ToolChain {
169172
/// Is the target either iOS or an iOS simulator?
170173
bool isTargetIOSBased() const { return false; }
171174

175+
/// Options to control how a runtime library is linked.
176+
enum RuntimeLinkOptions : unsigned {
177+
// Link the library in even if it can't be found in the VFS.
178+
RLO_AlwaysLink = 1 << 0,
179+
180+
// Use the embedded runtime from the macho_embedded directory.
181+
RLO_IsEmbedded = 1 << 1,
182+
183+
// Emit rpaths for @executable_path as well as the resource directory.
184+
RLO_AddRPath = 1 << 2,
185+
186+
//< Link the library in before any others.
187+
RLO_FirstLink = 1 << 3,
188+
};
189+
190+
/// Add a runtime library to the list of items to link.
172191
void AddLinkRuntimeLib(const llvm::opt::ArgList &Args,
173192
llvm::opt::ArgStringList &CmdArgs,
174-
StringRef DarwinLibName, bool AlwaysLink = false,
175-
bool IsEmbedded = false, bool AddRPath = false) const;
193+
StringRef DarwinLibName,
194+
RuntimeLinkOptions Opts = RuntimeLinkOptions()) const;
176195

177196
/// Add any profiling runtime libraries that are needed. This is essentially a
178197
/// MachO specific version of addProfileRT in Tools.cpp.

test/Driver/darwin-ld.c

+10
Original file line numberDiff line numberDiff line change
@@ -341,3 +341,13 @@
341341
// RUN: %clang -target x86_64-apple-darwin12 %t.o -fsave-optimization-record -fprofile-instr-use=blah -### -o foo/bar.out 2> %t.log
342342
// RUN: FileCheck -check-prefix=PASS_REMARKS_WITH_HOTNESS %s < %t.log
343343
// PASS_REMARKS_WITH_HOTNESS: "-mllvm" "-lto-pass-remarks-output" "-mllvm" "foo/bar.out.opt.yaml" "-mllvm" "-lto-pass-remarks-with-hotness"
344+
345+
// RUN: %clang -target x86_64-apple-ios6.0 -miphoneos-version-min=6.0 -fprofile-instr-generate -### %t.o 2> %t.log
346+
// RUN: FileCheck -check-prefix=LINK_PROFILE_FIRST %s < %t.log
347+
// RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate -### %t.o 2> %t.log
348+
// RUN: FileCheck -check-prefix=LINK_PROFILE_FIRST %s < %t.log
349+
// RUN: %clang -target i386-apple-darwin9 -fprofile-instr-generate -### %t.o 2> %t.log
350+
// RUN: FileCheck -check-prefix=LINK_PROFILE_FIRST %s < %t.log
351+
// RUN: %clang -target arm64-apple-ios5.0 -miphoneos-version-min=5.0 -fprofile-instr-generate -### %t.o 2> %t.log
352+
// RUN: FileCheck -check-prefix=LINK_PROFILE_FIRST %s < %t.log
353+
// LINK_PROFILE_FIRST: {{ld(.exe)?"}} "{{[^"]+}}libclang_rt.profile_{{[a-z]+}}.a"

0 commit comments

Comments
 (0)