Skip to content

Commit 5114b9b

Browse files
committed
[ORC][llvm-jitlink] Extend weak-linking emulation to real dylibs.
Commit 253e116 added support for emulating weak-linking against dylibs that are (under the emulation) absent at runtime. This commit extends emulated weak linking support to allow a real dylib to supply the interface (i.e. -weak-lx / -weak_library can be pointed at a dylib, in which case they should be read as "weak-link against this dylib, behavining as if it weren't actually present at runtime").
1 parent d254fa8 commit 5114b9b

File tree

6 files changed

+182
-84
lines changed

6 files changed

+182
-84
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//===---- GetDylibInterface.h - Get interface for real dylib ----*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Get symbol interface from a real dynamic library or TAPI file. These
10+
// interfaces can be used to simulate weak linking (ld64 -weak-lx /
11+
// -weak_library) against a library that is absent at runtime.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef LLVM_EXECUTIONENGINE_ORC_GETDYLIBINTERFACE_H
16+
#define LLVM_EXECUTIONENGINE_ORC_GETDYLIBINTERFACE_H
17+
18+
#include "llvm/ExecutionEngine/Orc/Core.h"
19+
#include "llvm/Object/TapiUniversal.h"
20+
21+
namespace llvm::orc {
22+
23+
/// Returns a SymbolNameSet containing the exported symbols defined in the
24+
/// given dylib.
25+
Expected<SymbolNameSet> getDylibInterfaceFromDylib(ExecutionSession &ES,
26+
Twine Path);
27+
28+
/// Returns a SymbolNameSet containing the exported symbols defined in the
29+
/// relevant slice of the TapiUniversal file.
30+
Expected<SymbolNameSet> getDylibInterfaceFromTapiFile(ExecutionSession &ES,
31+
Twine Path);
32+
33+
/// Returns a SymbolNameSet containing the exported symbols defined in the
34+
/// relevant slice of the given file, which may be either a dylib or a tapi
35+
/// file.
36+
Expected<SymbolNameSet> getDylibInterface(ExecutionSession &ES, Twine Path);
37+
38+
} // namespace llvm::orc
39+
40+
#endif // LLVM_EXECUTIONENGINE_ORC_GETDYLIBINTERFACE_H

llvm/include/llvm/ExecutionEngine/Orc/GetTapiInterface.h

Lines changed: 0 additions & 28 deletions
This file was deleted.

llvm/lib/ExecutionEngine/Orc/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ add_llvm_component_library(LLVMOrcJIT
2525
EPCIndirectionUtils.cpp
2626
ExecutionUtils.cpp
2727
ObjectFileInterface.cpp
28-
GetTapiInterface.cpp
28+
GetDylibInterface.cpp
2929
IndirectionUtils.cpp
3030
IRCompileLayer.cpp
3131
IRTransformLayer.cpp
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
//===-------- GetDylibInterface.cpp - Get interface for real dylib --------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/ExecutionEngine/Orc/GetDylibInterface.h"
10+
11+
#include "llvm/BinaryFormat/Magic.h"
12+
#include "llvm/Object/MachO.h"
13+
#include "llvm/Object/MachOUniversal.h"
14+
15+
#define DEBUG_TYPE "orc"
16+
17+
namespace llvm::orc {
18+
19+
Expected<SymbolNameSet> getDylibInterfaceFromDylib(ExecutionSession &ES,
20+
Twine Path) {
21+
auto CPUType = MachO::getCPUType(ES.getTargetTriple());
22+
if (!CPUType)
23+
return CPUType.takeError();
24+
25+
auto CPUSubType = MachO::getCPUSubType(ES.getTargetTriple());
26+
if (!CPUSubType)
27+
return CPUSubType.takeError();
28+
29+
auto Buf = MemoryBuffer::getFile(Path);
30+
if (!Buf)
31+
return createFileError(Path, Buf.getError());
32+
33+
auto SymFile =
34+
object::SymbolicFile::createSymbolicFile((*Buf)->getMemBufferRef());
35+
if (!SymFile)
36+
return SymFile.takeError();
37+
38+
std::unique_ptr<object::MachOObjectFile> MachOFile;
39+
if (isa<object::MachOObjectFile>(**SymFile))
40+
MachOFile.reset(dyn_cast<object::MachOObjectFile>(SymFile->release()));
41+
else if (auto *MachOUni =
42+
dyn_cast<object::MachOUniversalBinary>(SymFile->get())) {
43+
for (auto &O : MachOUni->objects()) {
44+
if (O.getCPUType() == *CPUType && O.getCPUSubType() == *CPUSubType) {
45+
if (auto Obj = O.getAsObjectFile())
46+
MachOFile = std::move(*Obj);
47+
else
48+
return Obj.takeError();
49+
break;
50+
}
51+
}
52+
if (!MachOFile)
53+
return make_error<StringError>("MachO universal binary at " + Path +
54+
" does not contain a slice for " +
55+
ES.getTargetTriple().str(),
56+
inconvertibleErrorCode());
57+
} else
58+
return make_error<StringError>("File at " + Path + " is not a MachO",
59+
inconvertibleErrorCode());
60+
61+
if (MachOFile->getHeader().filetype != MachO::MH_DYLIB)
62+
return make_error<StringError>("MachO at " + Path + " is not a dylib",
63+
inconvertibleErrorCode());
64+
65+
SymbolNameSet Symbols;
66+
for (auto &Sym : MachOFile->symbols()) {
67+
if (auto Name = Sym.getName())
68+
Symbols.insert(ES.intern(*Name));
69+
else
70+
return Name.takeError();
71+
}
72+
73+
return std::move(Symbols);
74+
}
75+
76+
Expected<SymbolNameSet> getDylibInterfaceFromTapiFile(ExecutionSession &ES,
77+
Twine Path) {
78+
SymbolNameSet Symbols;
79+
80+
auto TapiFileBuffer = MemoryBuffer::getFile(Path);
81+
if (!TapiFileBuffer)
82+
return createFileError(Path, TapiFileBuffer.getError());
83+
84+
auto Tapi =
85+
object::TapiUniversal::create((*TapiFileBuffer)->getMemBufferRef());
86+
if (!Tapi)
87+
return Tapi.takeError();
88+
89+
auto CPUType = MachO::getCPUType(ES.getTargetTriple());
90+
if (!CPUType)
91+
return CPUType.takeError();
92+
93+
auto CPUSubType = MachO::getCPUSubType(ES.getTargetTriple());
94+
if (!CPUSubType)
95+
return CPUSubType.takeError();
96+
97+
auto &IF = (*Tapi)->getInterfaceFile();
98+
auto Interface =
99+
IF.extract(MachO::getArchitectureFromCpuType(*CPUType, *CPUSubType));
100+
if (!Interface)
101+
return Interface.takeError();
102+
103+
for (auto *Sym : (*Interface)->exports())
104+
Symbols.insert(ES.intern(Sym->getName()));
105+
106+
return Symbols;
107+
}
108+
109+
Expected<SymbolNameSet> getDylibInterface(ExecutionSession &ES, Twine Path) {
110+
file_magic Magic;
111+
if (auto EC = identify_magic(Path, Magic))
112+
return createFileError(Path, EC);
113+
114+
SymbolNameSet Symbols;
115+
switch (Magic) {
116+
case file_magic::macho_dynamically_linked_shared_lib:
117+
return getDylibInterfaceFromDylib(ES, Path);
118+
case file_magic::tapi_file:
119+
return getDylibInterfaceFromTapiFile(ES, Path);
120+
default:
121+
return make_error<StringError>("Cannot get interface for " + Path +
122+
" unrecognized file type",
123+
inconvertibleErrorCode());
124+
}
125+
}
126+
127+
} // namespace llvm::orc

llvm/lib/ExecutionEngine/Orc/GetTapiInterface.cpp

Lines changed: 0 additions & 39 deletions
This file was deleted.

llvm/tools/llvm-jitlink/llvm-jitlink.cpp

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
3030
#include "llvm/ExecutionEngine/Orc/EPCEHFrameRegistrar.h"
3131
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
32-
#include "llvm/ExecutionEngine/Orc/GetTapiInterface.h"
32+
#include "llvm/ExecutionEngine/Orc/GetDylibInterface.h"
3333
#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
3434
#include "llvm/ExecutionEngine/Orc/JITLinkRedirectableSymbolManager.h"
3535
#include "llvm/ExecutionEngine/Orc/JITLinkReentryTrampolines.h"
@@ -2117,17 +2117,8 @@ static SmallVector<StringRef, 5> getSearchPathsFromEnvVar(Session &S) {
21172117
}
21182118

21192119
static Expected<std::unique_ptr<DefinitionGenerator>>
2120-
LoadLibraryWeak(Session &S, StringRef InterfacePath) {
2121-
auto TapiFileBuffer = getFile(InterfacePath);
2122-
if (!TapiFileBuffer)
2123-
return TapiFileBuffer.takeError();
2124-
2125-
auto Tapi =
2126-
object::TapiUniversal::create((*TapiFileBuffer)->getMemBufferRef());
2127-
if (!Tapi)
2128-
return Tapi.takeError();
2129-
2130-
auto Symbols = getInterfaceFromTapiFile(S.ES, **Tapi);
2120+
LoadLibraryWeak(Session &S, StringRef Path) {
2121+
auto Symbols = getDylibInterface(S.ES, Path);
21312122
if (!Symbols)
21322123
return Symbols.takeError();
21332124

@@ -2227,7 +2218,7 @@ static Error addLibraries(Session &S,
22272218
StringRef StandardExtensions[] = {".so", ".dylib", ".dll", ".a", ".lib"};
22282219
StringRef DynLibExtensionsOnly[] = {".so", ".dylib", ".dll"};
22292220
StringRef ArchiveExtensionsOnly[] = {".a", ".lib"};
2230-
StringRef InterfaceExtensionsOnly = {".tbd"};
2221+
StringRef WeakLinkExtensionsOnly[] = {".dylib", ".tbd"};
22312222

22322223
// Add -lx arguments to LibraryLoads.
22332224
for (auto LibItr = Libraries.begin(), LibEnd = Libraries.end();
@@ -2260,7 +2251,7 @@ static Error addLibraries(Session &S,
22602251
LibraryLoad LL;
22612252
LL.LibName = *LibWeakItr;
22622253
LL.Position = LibrariesWeak.getPosition(LibWeakItr - LibrariesWeak.begin());
2263-
LL.CandidateExtensions = InterfaceExtensionsOnly;
2254+
LL.CandidateExtensions = WeakLinkExtensionsOnly;
22642255
LL.Modifier = LibraryLoad::Weak;
22652256
LibraryLoadQueue.push_back(std::move(LL));
22662257
}
@@ -2403,8 +2394,15 @@ static Error addLibraries(Session &S,
24032394
case file_magic::pecoff_executable:
24042395
case file_magic::elf_shared_object:
24052396
case file_magic::macho_dynamically_linked_shared_lib: {
2406-
if (auto Err = S.loadAndLinkDynamicLibrary(JD, LibPath.data()))
2407-
return Err;
2397+
if (LL.Modifier == LibraryLoad::Weak) {
2398+
if (auto G = LoadLibraryWeak(S, LibPath.data()))
2399+
JD.addGenerator(std::move(*G));
2400+
else
2401+
return G.takeError();
2402+
} else {
2403+
if (auto Err = S.loadAndLinkDynamicLibrary(JD, LibPath.data()))
2404+
return Err;
2405+
}
24082406
break;
24092407
}
24102408
case file_magic::archive:

0 commit comments

Comments
 (0)