diff --git a/llvm/test/ExecutionEngine/JITLink/X86/MachO_archive_load_hidden_expect_success.s b/llvm/test/ExecutionEngine/JITLink/X86/MachO_archive_load_hidden_expect_success.s index 249519356f8cb8..e52f905628a356 100644 --- a/llvm/test/ExecutionEngine/JITLink/X86/MachO_archive_load_hidden_expect_success.s +++ b/llvm/test/ExecutionEngine/JITLink/X86/MachO_archive_load_hidden_expect_success.s @@ -6,6 +6,8 @@ # RUN: -o %t/MachO_archive_load_hidden_support.o %s # RUN: llvm-jitlink -noexec %t/MachO_archive_load_hidden_support.o \ # RUN: -L%t -hidden-lExtraDef +# RUN: llvm-jitlink -noexec %t/MachO_archive_load_hidden_support.o \ +# RUN: -load_hidden %t/libExtraDef.a # # Expect this test to succeed -- ExtraDef should be hidden, but visible to # ExtraDefRef as they're linked in the same JITDylib. This tests that we're diff --git a/llvm/test/ExecutionEngine/JITLink/X86/MachO_archive_support.s b/llvm/test/ExecutionEngine/JITLink/X86/MachO_archive_support.s index e3fea53e397b93..77f396075c4eb7 100644 --- a/llvm/test/ExecutionEngine/JITLink/X86/MachO_archive_support.s +++ b/llvm/test/ExecutionEngine/JITLink/X86/MachO_archive_support.s @@ -5,6 +5,7 @@ # RUN: llvm-mc -triple x86_64-apple-macosx10.9 -filetype=obj \ # RUN: -o %t/MachO_archive_support.o %s # RUN: llvm-jitlink -noexec %t/MachO_archive_support.o -lFoo -jd Foo -L%t -lExtraDef +# RUN: llvm-jitlink -noexec %t/MachO_archive_support.o -lFoo -jd Foo %t/libExtraDef.a # # Test that archives can be loaded and referenced from other JITDylibs. diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp index 8d0fd0403d4db5..f581ea131f1334 100644 --- a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp +++ b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp @@ -82,9 +82,16 @@ static cl::list cl::desc("Link against library X in the library search paths"), cl::Prefix, cl::cat(JITLinkCategory)); -static cl::list LibrariesHidden( - "hidden-l", cl::desc("Link against library X in the library search paths"), - cl::Prefix, cl::cat(JITLinkCategory)); +static cl::list + LibrariesHidden("hidden-l", + cl::desc("Link against library X in the library search " + "paths with hidden visibility"), + cl::Prefix, cl::cat(JITLinkCategory)); + +static cl::list + LoadHidden("load_hidden", + cl::desc("Link against library X with hidden visibility"), + cl::cat(JITLinkCategory)); static cl::opt NoExec("noexec", cl::desc("Do not execute loaded code"), cl::init(false), cl::cat(JITLinkCategory)); @@ -1403,6 +1410,8 @@ static Error addObjects(Session &S, unsigned InputFileArgIdx = InputFiles.getPosition(InputFileItr - InputFiles.begin()); const std::string &InputFile = *InputFileItr; + if (StringRef(InputFile).endswith(".a")) + continue; auto &JD = *std::prev(IdxToJD.lower_bound(InputFileArgIdx))->second; LLVM_DEBUG(dbgs() << " " << InputFileArgIdx << ": \"" << InputFile << "\" to " << JD.getName() << "\n";); @@ -1474,14 +1483,41 @@ static Error addLibraries(Session &S, } }); - // 2. Collect library loads from -lx, -hidden-lx. + // 2. Collect library loads struct LibraryLoad { StringRef LibName; + bool IsPath = false; unsigned Position; StringRef *CandidateExtensions; enum { Standard, Hidden } Modifier; }; std::vector LibraryLoads; + // Add archive files from the inputs to LibraryLoads. + for (auto InputFileItr = InputFiles.begin(), InputFileEnd = InputFiles.end(); + InputFileItr != InputFileEnd; ++InputFileItr) { + StringRef InputFile = *InputFileItr; + if (!InputFile.endswith(".a")) + continue; + LibraryLoad LL; + LL.LibName = InputFile; + LL.IsPath = true; + LL.Position = InputFiles.getPosition(InputFileItr - InputFiles.begin()); + LL.CandidateExtensions = nullptr; + LL.Modifier = LibraryLoad::Standard; + LibraryLoads.push_back(std::move(LL)); + } + + // Add -load_hidden arguments to LibraryLoads. + for (auto LibItr = LoadHidden.begin(), LibEnd = LoadHidden.end(); + LibItr != LibEnd; ++LibItr) { + LibraryLoad LL; + LL.LibName = *LibItr; + LL.IsPath = true; + LL.Position = LoadHidden.getPosition(LibItr - LoadHidden.begin()); + LL.CandidateExtensions = nullptr; + LL.Modifier = LibraryLoad::Hidden; + LibraryLoads.push_back(std::move(LL)); + } StringRef StandardExtensions[] = {".so", ".dylib", ".a"}; StringRef ArchiveExtensionsOnly[] = {".a"}; @@ -1511,7 +1547,7 @@ static Error addLibraries(Session &S, // If there are any load- options then turn on flag overrides // to avoid flag mismatch errors. - if (!LibrariesHidden.empty()) + if (!LibrariesHidden.empty() || !LoadHidden.empty()) S.ObjLayer.setOverrideObjectFlagsWithResponsibilityFlags(true); // Sort library loads by position in the argument list. @@ -1520,6 +1556,24 @@ static Error addLibraries(Session &S, }); // 3. Process library loads. + auto AddArchive = [&](const char *Path, const LibraryLoad &LL) + -> Expected> { + unique_function( + ExecutionSession & ES, MemoryBufferRef ObjBuffer)> + GetObjFileInterface; + switch (LL.Modifier) { + case LibraryLoad::Standard: + GetObjFileInterface = getObjectFileInterface; + break; + case LibraryLoad::Hidden: + GetObjFileInterface = getObjectFileInterfaceHidden; + break; + } + return StaticLibraryDefinitionGenerator::Load( + S.ObjLayer, Path, S.ES.getExecutorProcessControl().getTargetTriple(), + std::move(GetObjFileInterface)); + }; + for (auto &LL : LibraryLoads) { bool LibFound = false; auto &JD = *std::prev(IdxToJD.lower_bound(LL.Position))->second; @@ -1530,6 +1584,18 @@ static Error addLibraries(Session &S, continue; } + if (LL.IsPath) { + auto G = AddArchive(LL.LibName.str().c_str(), LL); + if (!G) + return createFileError(LL.LibName, G.takeError()); + JD.addGenerator(std::move(*G)); + LLVM_DEBUG({ + dbgs() << "Adding generator for static library " << LL.LibName << " to " + << JD.getName() << "\n"; + }); + continue; + } + // Otherwise look through the search paths. auto JDSearchPathsItr = JDSearchPaths.find(&JD); if (JDSearchPathsItr != JDSearchPaths.end()) { @@ -1583,21 +1649,7 @@ static Error addLibraries(Session &S, } case file_magic::archive: case file_magic::macho_universal_binary: { - unique_function( - ExecutionSession & ES, MemoryBufferRef ObjBuffer)> - GetObjFileInterface; - switch (LL.Modifier) { - case LibraryLoad::Standard: - GetObjFileInterface = getObjectFileInterface; - break; - case LibraryLoad::Hidden: - GetObjFileInterface = getObjectFileInterfaceHidden; - break; - } - auto G = StaticLibraryDefinitionGenerator::Load( - S.ObjLayer, LibPath.data(), - S.ES.getExecutorProcessControl().getTargetTriple(), - std::move(GetObjFileInterface)); + auto G = AddArchive(LibPath.data(), LL); if (!G) return G.takeError(); JD.addGenerator(std::move(*G));