forked from OSchip/llvm-project
Teach llvm-jitlink to support archives in inputs files and -load_hidden
Similar to the ld64 command-line options. These use the same underlying mechanisms as -l and -hidden-l, but allow specifying an absolute path to the archive. This is often more convenient for a one-off, or when adding a new search path could change how existing -l options are resolved. Differential Revision: https://reviews.llvm.org/D117360
This commit is contained in:
parent
258cd02c6a
commit
ca2353ce5a
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -82,9 +82,16 @@ static cl::list<std::string>
|
|||
cl::desc("Link against library X in the library search paths"),
|
||||
cl::Prefix, cl::cat(JITLinkCategory));
|
||||
|
||||
static cl::list<std::string> LibrariesHidden(
|
||||
"hidden-l", cl::desc("Link against library X in the library search paths"),
|
||||
cl::Prefix, cl::cat(JITLinkCategory));
|
||||
static cl::list<std::string>
|
||||
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<std::string>
|
||||
LoadHidden("load_hidden",
|
||||
cl::desc("Link against library X with hidden visibility"),
|
||||
cl::cat(JITLinkCategory));
|
||||
|
||||
static cl::opt<bool> 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<LibraryLoad> 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-<modified> 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<std::unique_ptr<StaticLibraryDefinitionGenerator>> {
|
||||
unique_function<Expected<MaterializationUnit::Interface>(
|
||||
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<Expected<MaterializationUnit::Interface>(
|
||||
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));
|
||||
|
|
Loading…
Reference in New Issue