aboutsummaryrefslogtreecommitdiff
path: root/lld
diff options
context:
space:
mode:
authorJez Ng <jezng@fb.com>2020-09-18 11:38:15 -0700
committerJez Ng <jezng@fb.com>2020-09-23 19:26:41 -0700
commit98f03908d07d06c74be5547cc0436bd89186cae2 (patch)
treec8e3f89d5a492e83477e30ed3c5e01182d5f34bf /lld
parent79412d6ca772c1c3913030cfef4b17f4afac110d (diff)
downloadllvm-98f03908d07d06c74be5547cc0436bd89186cae2.zip
llvm-98f03908d07d06c74be5547cc0436bd89186cae2.tar.gz
llvm-98f03908d07d06c74be5547cc0436bd89186cae2.tar.bz2
[lld-macho] Support -weak_lx, -weak_library, -weak_framework
They cause their corresponding libraries / frameworks to be loaded via `LC_LOAD_WEAK_DYLIB` instead of `LC_LOAD_DYLIB`. Reviewed By: #lld-macho, gkm Differential Revision: https://reviews.llvm.org/D87929
Diffstat (limited to 'lld')
-rw-r--r--lld/MachO/Driver.cpp39
-rw-r--r--lld/MachO/InputFiles.h1
-rw-r--r--lld/MachO/Options.td3
-rw-r--r--lld/MachO/Writer.cpp7
-rw-r--r--lld/test/MachO/weak-import.s31
5 files changed, 64 insertions, 17 deletions
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index cc0211a..0f1551a 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -237,11 +237,12 @@ static std::vector<MemoryBufferRef> getArchiveMembers(MemoryBufferRef mb) {
return v;
}
-static void addFile(StringRef path) {
+static InputFile *addFile(StringRef path) {
Optional<MemoryBufferRef> buffer = readFile(path);
if (!buffer)
- return;
+ return nullptr;
MemoryBufferRef mbref = *buffer;
+ InputFile *newFile = nullptr;
switch (identify_magic(mbref.getBuffer())) {
case file_magic::archive: {
@@ -270,25 +271,27 @@ static void addFile(StringRef path) {
inputFiles.push_back(make<ObjFile>(member));
}
- inputFiles.push_back(make<ArchiveFile>(std::move(file)));
+ newFile = make<ArchiveFile>(std::move(file));
break;
}
case file_magic::macho_object:
- inputFiles.push_back(make<ObjFile>(mbref));
+ newFile = make<ObjFile>(mbref);
break;
case file_magic::macho_dynamically_linked_shared_lib:
- inputFiles.push_back(make<DylibFile>(mbref));
+ newFile = make<DylibFile>(mbref);
break;
case file_magic::tapi_file: {
Optional<DylibFile *> dylibFile = makeDylibFromTAPI(mbref);
if (!dylibFile)
- return;
- inputFiles.push_back(*dylibFile);
+ return nullptr;
+ newFile = *dylibFile;
break;
}
default:
error(path + ": unhandled file type");
}
+ inputFiles.push_back(newFile);
+ return newFile;
}
static void addFileList(StringRef path) {
@@ -596,29 +599,41 @@ bool macho::link(llvm::ArrayRef<const char *> argsArr, bool canExitEarly,
warnIfDeprecatedOption(opt);
warnIfUnimplementedOption(opt);
// TODO: are any of these better handled via filtered() or getLastArg()?
- switch (arg->getOption().getID()) {
+ switch (opt.getID()) {
case OPT_INPUT:
addFile(arg->getValue());
break;
+ case OPT_weak_library: {
+ auto *dylibFile = dyn_cast_or_null<DylibFile>(addFile(arg->getValue()));
+ if (dylibFile != nullptr)
+ dylibFile->forceWeakImport = true;
+ break;
+ }
case OPT_filelist:
addFileList(arg->getValue());
break;
case OPT_force_load:
forceLoadArchive(arg->getValue());
break;
- case OPT_l: {
+ case OPT_l:
+ case OPT_weak_l: {
StringRef name = arg->getValue();
if (Optional<std::string> path = findLibrary(name)) {
- addFile(*path);
+ auto *dylibFile = dyn_cast_or_null<DylibFile>(addFile(*path));
+ if (opt.getID() == OPT_weak_l && dylibFile != nullptr)
+ dylibFile->forceWeakImport = true;
break;
}
error("library not found for -l" + name);
break;
}
- case OPT_framework: {
+ case OPT_framework:
+ case OPT_weak_framework: {
StringRef name = arg->getValue();
if (Optional<std::string> path = findFramework(name)) {
- addFile(*path);
+ auto *dylibFile = dyn_cast_or_null<DylibFile>(addFile(*path));
+ if (opt.getID() == OPT_weak_framework && dylibFile != nullptr)
+ dylibFile->forceWeakImport = true;
break;
}
error("framework not found for -framework " + name);
diff --git a/lld/MachO/InputFiles.h b/lld/MachO/InputFiles.h
index 194de0e..bb83c20 100644
--- a/lld/MachO/InputFiles.h
+++ b/lld/MachO/InputFiles.h
@@ -107,6 +107,7 @@ public:
StringRef dylibName;
uint64_t ordinal = 0; // Ordinal numbering starts from 1, so 0 is a sentinel
bool reexport = false;
+ bool forceWeakImport = false;
std::vector<DylibFile *> reexported;
};
diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td
index 2a05ddf..ddcf8aa 100644
--- a/lld/MachO/Options.td
+++ b/lld/MachO/Options.td
@@ -64,12 +64,10 @@ def l : Joined<["-"], "l">,
def weak_l : Joined<["-"], "weak-l">,
MetaVarName<"<name>">,
HelpText<"Like -l<name>, but mark library and its references as weak imports">,
- Flags<[HelpHidden]>,
Group<grp_libs>;
def weak_library : Separate<["-"], "weak_library">,
MetaVarName<"<path>">,
HelpText<"Like bare <path>, but mark library and its references as weak imports">,
- Flags<[HelpHidden]>,
Group<grp_libs>;
def reexport_l : Joined<["-"], "reexport-l">,
MetaVarName<"<name>">,
@@ -115,7 +113,6 @@ def framework : Separate<["-"], "framework">,
def weak_framework : Separate<["-"], "weak_framework">,
MetaVarName<"<name>">,
HelpText<"Like -framework <name>, but mark framework and its references as weak imports">,
- Flags<[HelpHidden]>,
Group<grp_libs>;
def reexport_framework : Separate<["-"], "reexport_framework">,
MetaVarName<"<name>">,
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
index 1f1c34ca..aabe6a9 100644
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -376,8 +376,11 @@ void Writer::createLoadCommands() {
uint64_t dylibOrdinal = 1;
for (InputFile *file : inputFiles) {
if (auto *dylibFile = dyn_cast<DylibFile>(file)) {
- in.header->addLoadCommand(
- make<LCDylib>(LC_LOAD_DYLIB, dylibFile->dylibName));
+ // TODO: dylibs that are only referenced by weak refs should also be
+ // loaded via LC_LOAD_WEAK_DYLIB.
+ LoadCommandType lcType =
+ dylibFile->forceWeakImport ? LC_LOAD_WEAK_DYLIB : LC_LOAD_DYLIB;
+ in.header->addLoadCommand(make<LCDylib>(lcType, dylibFile->dylibName));
dylibFile->ordinal = dylibOrdinal++;
if (dylibFile->reexport)
diff --git a/lld/test/MachO/weak-import.s b/lld/test/MachO/weak-import.s
new file mode 100644
index 0000000..a203375
--- /dev/null
+++ b/lld/test/MachO/weak-import.s
@@ -0,0 +1,31 @@
+# REQUIRES: x86
+# RUN: split-file %s %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/test.s -o %t/test.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/foo.s -o %t/foo.o
+# RUN: lld -flavor darwinnew -syslibroot %S/Inputs/MacOSX.sdk -lSystem -dylib %t/foo.o -o %t/libfoo.dylib
+
+# RUN: lld -flavor darwinnew -syslibroot %S/Inputs/MacOSX.sdk -weak-lSystem %t/test.o -weak_framework CoreFoundation -weak_library %t/libfoo.dylib -o %t/test
+# RUN: llvm-objdump --macho --all-headers %t/test | FileCheck %s -DDIR=%t
+
+# CHECK: cmd LC_LOAD_WEAK_DYLIB
+# CHECK-NEXT: cmdsize
+# CHECK-NEXT: name /usr/lib/libSystem.B.dylib
+
+# CHECK: cmd LC_LOAD_WEAK_DYLIB
+# CHECK-NEXT: cmdsize
+# CHECK-NEXT: name /System/Library/Frameworks/CoreFoundation.framework/CoreFoundation
+
+# CHECK: cmd LC_LOAD_WEAK_DYLIB
+# CHECK-NEXT: cmdsize
+# CHECK-NEXT: name [[DIR]]/libfoo.dylib
+
+#--- foo.s
+.globl _foo
+_foo:
+ ret
+
+#--- test.s
+.globl _main
+.text
+_main:
+ ret