diff options
author | Jez Ng <jezng@fb.com> | 2020-09-18 11:38:15 -0700 |
---|---|---|
committer | Jez Ng <jezng@fb.com> | 2020-09-23 19:26:41 -0700 |
commit | 98f03908d07d06c74be5547cc0436bd89186cae2 (patch) | |
tree | c8e3f89d5a492e83477e30ed3c5e01182d5f34bf /lld | |
parent | 79412d6ca772c1c3913030cfef4b17f4afac110d (diff) | |
download | llvm-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.cpp | 39 | ||||
-rw-r--r-- | lld/MachO/InputFiles.h | 1 | ||||
-rw-r--r-- | lld/MachO/Options.td | 3 | ||||
-rw-r--r-- | lld/MachO/Writer.cpp | 7 | ||||
-rw-r--r-- | lld/test/MachO/weak-import.s | 31 |
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 |