Skip to content

Commit 02fc8d5

Browse files
committed
[ORC] Add custom object interface support to StaticLibaryDefinitionGenerator.
This adds a GetObjectFileInterface callback member to StaticLibraryDefinitionGenerator, and adds an optional argument for initializing that member to StaticLibraryDefinitionGenerator's named constructors. If not supplied, it will default to getObjectFileInterface from ObjectFileInterface.h. To enable testing a `-hidden-l<x>` option is added to the llvm-jitlink tool. This allows archives to be loaded with all contained symbol visibilities demoted to hidden. The ObjectLinkingLayer::setOverrideObjectFlagsWithResponsibilityFlags method is (belatedly) hooked up, and enabled in llvm-jitlink when `-hidden-l<x>` is used so that the demotion is also applied at symbol resolution time (avoiding any "mismatched symbol flags" crashes).
1 parent 3eeeb6e commit 02fc8d5

File tree

7 files changed

+183
-27
lines changed

7 files changed

+183
-27
lines changed

llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -259,26 +259,34 @@ class DynamicLibrarySearchGenerator : public DefinitionGenerator {
259259
/// the containing object being added to the JITDylib.
260260
class StaticLibraryDefinitionGenerator : public DefinitionGenerator {
261261
public:
262+
// Interface builder function for objects loaded from this archive.
263+
using GetObjectFileInterface =
264+
unique_function<Expected<MaterializationUnit::Interface>(
265+
ExecutionSession &ES, MemoryBufferRef ObjBuffer)>;
266+
262267
/// Try to create a StaticLibraryDefinitionGenerator from the given path.
263268
///
264269
/// This call will succeed if the file at the given path is a static library
265270
/// is a valid archive, otherwise it will return an error.
266271
static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
267-
Load(ObjectLayer &L, const char *FileName);
272+
Load(ObjectLayer &L, const char *FileName,
273+
GetObjectFileInterface GetObjFileInterface = GetObjectFileInterface());
268274

269275
/// Try to create a StaticLibraryDefinitionGenerator from the given path.
270276
///
271277
/// This call will succeed if the file at the given path is a static library
272278
/// or a MachO universal binary containing a static library that is compatible
273279
/// with the given triple. Otherwise it will return an error.
274280
static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
275-
Load(ObjectLayer &L, const char *FileName, const Triple &TT);
281+
Load(ObjectLayer &L, const char *FileName, const Triple &TT,
282+
GetObjectFileInterface GetObjFileInterface = GetObjectFileInterface());
276283

277284
/// Try to create a StaticLibrarySearchGenerator from the given memory buffer.
278285
/// This call will succeed if the buffer contains a valid archive, otherwise
279286
/// it will return an error.
280287
static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
281-
Create(ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer);
288+
Create(ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
289+
GetObjectFileInterface GetObjFileInterface = GetObjectFileInterface());
282290

283291
Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
284292
JITDylibLookupFlags JDLookupFlags,
@@ -287,9 +295,11 @@ class StaticLibraryDefinitionGenerator : public DefinitionGenerator {
287295
private:
288296
StaticLibraryDefinitionGenerator(ObjectLayer &L,
289297
std::unique_ptr<MemoryBuffer> ArchiveBuffer,
298+
GetObjectFileInterface GetObjFileInterface,
290299
Error &Err);
291300

292301
ObjectLayer &L;
302+
GetObjectFileInterface GetObjFileInterface;
293303
std::unique_ptr<MemoryBuffer> ArchiveBuffer;
294304
std::unique_ptr<object::Archive> Archive;
295305
};

llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
1010
#include "llvm/ExecutionEngine/Orc/Layer.h"
11+
#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
1112
#include "llvm/IR/Constants.h"
1213
#include "llvm/IR/Function.h"
1314
#include "llvm/IR/GlobalVariable.h"
@@ -269,25 +270,30 @@ Error DynamicLibrarySearchGenerator::tryToGenerate(
269270
}
270271

271272
Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
272-
StaticLibraryDefinitionGenerator::Load(ObjectLayer &L, const char *FileName) {
273+
StaticLibraryDefinitionGenerator::Load(
274+
ObjectLayer &L, const char *FileName,
275+
GetObjectFileInterface GetObjFileInterface) {
273276
auto ArchiveBuffer = errorOrToExpected(MemoryBuffer::getFile(FileName));
274277

275278
if (!ArchiveBuffer)
276279
return ArchiveBuffer.takeError();
277280

278-
return Create(L, std::move(*ArchiveBuffer));
281+
return Create(L, std::move(*ArchiveBuffer), std::move(GetObjFileInterface));
279282
}
280283

281284
Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
282-
StaticLibraryDefinitionGenerator::Load(ObjectLayer &L, const char *FileName,
283-
const Triple &TT) {
285+
StaticLibraryDefinitionGenerator::Load(
286+
ObjectLayer &L, const char *FileName, const Triple &TT,
287+
GetObjectFileInterface GetObjFileInterface) {
288+
284289
auto B = object::createBinary(FileName);
285290
if (!B)
286291
return B.takeError();
287292

288293
// If this is a regular archive then create an instance from it.
289294
if (isa<object::Archive>(B->getBinary()))
290-
return Create(L, std::move(B->takeBinary().second));
295+
return Create(L, std::move(B->takeBinary().second),
296+
std::move(GetObjFileInterface));
291297

292298
// If this is a universal binary then search for a slice matching the given
293299
// Triple.
@@ -309,7 +315,8 @@ StaticLibraryDefinitionGenerator::Load(ObjectLayer &L, const char *FileName,
309315
" .. " + formatv("{0:x}", Obj.getOffset() + Obj.getSize()) +
310316
": " + SliceBuffer.getError().message(),
311317
SliceBuffer.getError());
312-
return Create(L, std::move(*SliceBuffer));
318+
return Create(L, std::move(*SliceBuffer),
319+
std::move(GetObjFileInterface));
313320
}
314321
}
315322

@@ -326,11 +333,13 @@ StaticLibraryDefinitionGenerator::Load(ObjectLayer &L, const char *FileName,
326333

327334
Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
328335
StaticLibraryDefinitionGenerator::Create(
329-
ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer) {
336+
ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
337+
GetObjectFileInterface GetObjFileInterface) {
330338
Error Err = Error::success();
331339

332340
std::unique_ptr<StaticLibraryDefinitionGenerator> ADG(
333-
new StaticLibraryDefinitionGenerator(L, std::move(ArchiveBuffer), Err));
341+
new StaticLibraryDefinitionGenerator(
342+
L, std::move(ArchiveBuffer), std::move(GetObjFileInterface), Err));
334343

335344
if (Err)
336345
return std::move(Err);
@@ -371,17 +380,28 @@ Error StaticLibraryDefinitionGenerator::tryToGenerate(
371380
MemoryBufferRef ChildBufferRef(ChildBufferInfo.first,
372381
ChildBufferInfo.second);
373382

374-
if (auto Err = L.add(JD, MemoryBuffer::getMemBuffer(ChildBufferRef, false)))
383+
auto I = GetObjFileInterface(L.getExecutionSession(), ChildBufferRef);
384+
if (!I)
385+
return I.takeError();
386+
387+
if (auto Err = L.add(JD, MemoryBuffer::getMemBuffer(ChildBufferRef, false),
388+
std::move(*I)))
375389
return Err;
376390
}
377391

378392
return Error::success();
379393
}
380394

381395
StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator(
382-
ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, Error &Err)
383-
: L(L), ArchiveBuffer(std::move(ArchiveBuffer)),
384-
Archive(std::make_unique<object::Archive>(*this->ArchiveBuffer, Err)) {}
396+
ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
397+
GetObjectFileInterface GetObjFileInterface, Error &Err)
398+
: L(L), GetObjFileInterface(std::move(GetObjFileInterface)),
399+
ArchiveBuffer(std::move(ArchiveBuffer)),
400+
Archive(std::make_unique<object::Archive>(*this->ArchiveBuffer, Err)) {
401+
402+
if (!this->GetObjFileInterface)
403+
this->GetObjFileInterface = getObjectFileInterface;
404+
}
385405

386406
} // End namespace orc.
387407
} // End namespace llvm.

llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,8 @@ class ObjectLinkingLayerJITLinkContext final : public JITLinkContext {
249249

250250
{
251251

252-
// Check that InternedResult matches up with MR->getSymbols().
252+
// Check that InternedResult matches up with MR->getSymbols(), overriding
253+
// flags if requested.
253254
// This guards against faulty transformations / compilers / object caches.
254255

255256
// First check that there aren't any missing symbols.
@@ -258,16 +259,20 @@ class ObjectLinkingLayerJITLinkContext final : public JITLinkContext {
258259
SymbolNameVector MissingSymbols;
259260
for (auto &KV : MR->getSymbols()) {
260261

262+
auto I = InternedResult.find(KV.first);
263+
261264
// If this is a materialization-side-effects only symbol then bump
262265
// the counter and make sure it's *not* defined, otherwise make
263266
// sure that it is defined.
264267
if (KV.second.hasMaterializationSideEffectsOnly()) {
265268
++NumMaterializationSideEffectsOnlySymbols;
266-
if (InternedResult.count(KV.first))
269+
if (I != InternedResult.end())
267270
ExtraSymbols.push_back(KV.first);
268271
continue;
269-
} else if (!InternedResult.count(KV.first))
272+
} else if (I == InternedResult.end())
270273
MissingSymbols.push_back(KV.first);
274+
else if (Layer.OverrideObjectFlags)
275+
I->second.setFlags(KV.second);
271276
}
272277

273278
// If there were missing symbols then report the error.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# RUN: rm -rf %t && mkdir -p %t
2+
# RUN: llvm-mc -triple x86_64-apple-macosx10.9 -filetype=obj \
3+
# RUN: -o %t/MachO_extra_def_strong.o %S/Inputs/MachO_extra_def_strong.s
4+
# RUN: llvm-ar crs %t/libExtraDef.a %t/MachO_extra_def_strong.o
5+
# RUN: llvm-mc -triple x86_64-apple-macosx10.9 -filetype=obj \
6+
# RUN: -o %t/MachO_archive_load_hidden_support.o %s
7+
# RUN: not llvm-jitlink -noexec %t/MachO_archive_load_hidden_support.o -lFoo \
8+
# RUN: -jd Foo -L%t -hidden-lExtraDef
9+
#
10+
# Expect this test to fail when we try to reference ExtraDef, which should have
11+
# be hidden in JITDylib Foo. This tests that we're correctly overriding the
12+
# object interface when we load the object.
13+
14+
.section __TEXT,__text,regular,pure_instructions
15+
16+
.globl _main
17+
.p2align 4, 0x90
18+
_main:
19+
retq
20+
21+
.section __DATA,__data
22+
.globl ExtraDefRef
23+
.p2align 3
24+
ExtraDefRef:
25+
.quad ExtraDef
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# RUN: rm -rf %t && mkdir -p %t
2+
# RUN: llvm-mc -triple x86_64-apple-macosx10.9 -filetype=obj \
3+
# RUN: -o %t/MachO_extra_def_strong.o %S/Inputs/MachO_extra_def_strong.s
4+
# RUN: llvm-ar crs %t/libExtraDef.a %t/MachO_extra_def_strong.o
5+
# RUN: llvm-mc -triple x86_64-apple-macosx10.9 -filetype=obj \
6+
# RUN: -o %t/MachO_archive_load_hidden_support.o %s
7+
# RUN: llvm-jitlink -noexec %t/MachO_archive_load_hidden_support.o \
8+
# RUN: -L%t -hidden-lExtraDef
9+
#
10+
# Expect this test to succeed -- ExtraDef should be hidden, but visible to
11+
# ExtraDefRef as they're linked in the same JITDylib. This tests that we're
12+
# correctly handling the change in object interface when linking ExtraDef.
13+
14+
.section __TEXT,__text,regular,pure_instructions
15+
16+
.globl _main
17+
.p2align 4, 0x90
18+
_main:
19+
retq
20+
21+
.section __DATA,__data
22+
.globl ExtraDefRef
23+
.p2align 3
24+
ExtraDefRef:
25+
.quad ExtraDef

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

Lines changed: 79 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ static cl::list<std::string>
8282
cl::desc("Link against library X in the library search paths"),
8383
cl::Prefix, cl::cat(JITLinkCategory));
8484

85+
static cl::list<std::string> LibrariesHidden(
86+
"hidden-l", cl::desc("Link against library X in the library search paths"),
87+
cl::Prefix, cl::cat(JITLinkCategory));
88+
8589
static cl::opt<bool> NoExec("noexec", cl::desc("Do not execute loaded code"),
8690
cl::init(false), cl::cat(JITLinkCategory));
8791

@@ -1413,9 +1417,20 @@ static Error addObjects(Session &S,
14131417
return Error::success();
14141418
}
14151419

1420+
static Expected<MaterializationUnit::Interface>
1421+
getObjectFileInterfaceHidden(ExecutionSession &ES, MemoryBufferRef ObjBuffer) {
1422+
auto I = getObjectFileInterface(ES, ObjBuffer);
1423+
if (I) {
1424+
for (auto &KV : I->SymbolFlags)
1425+
KV.second &= ~JITSymbolFlags::Exported;
1426+
}
1427+
return I;
1428+
}
1429+
14161430
static Error addLibraries(Session &S,
14171431
const std::map<unsigned, JITDylib *> &IdxToJD) {
14181432

1433+
// 1. Collect search paths for each JITDylib.
14191434
DenseMap<const JITDylib *, SmallVector<StringRef, 2>> JDSearchPaths;
14201435

14211436
for (auto LSPItr = LibrarySearchPaths.begin(),
@@ -1447,16 +1462,58 @@ static Error addLibraries(Session &S,
14471462
}
14481463
});
14491464

1465+
// 2. Collect library loads from -lx, -hidden-lx.
1466+
struct LibraryLoad {
1467+
StringRef LibName;
1468+
unsigned Position;
1469+
StringRef *CandidateExtensions;
1470+
enum { Standard, Hidden } Modifier;
1471+
};
1472+
std::vector<LibraryLoad> LibraryLoads;
1473+
StringRef StandardExtensions[] = {".so", ".dylib", ".a"};
1474+
StringRef ArchiveExtensionsOnly[] = {".a"};
1475+
1476+
// Add -lx arguments to LibraryLoads.
14501477
for (auto LibItr = Libraries.begin(), LibEnd = Libraries.end();
14511478
LibItr != LibEnd; ++LibItr) {
1479+
LibraryLoad LL;
1480+
LL.LibName = *LibItr;
1481+
LL.Position = Libraries.getPosition(LibItr - Libraries.begin());
1482+
LL.CandidateExtensions = StandardExtensions;
1483+
LL.Modifier = LibraryLoad::Standard;
1484+
LibraryLoads.push_back(std::move(LL));
1485+
}
1486+
1487+
// Add -hidden-lx arguments to LibraryLoads.
1488+
for (auto LibHiddenItr = LibrariesHidden.begin(),
1489+
LibHiddenEnd = LibrariesHidden.end();
1490+
LibHiddenItr != LibHiddenEnd; ++LibHiddenItr) {
1491+
LibraryLoad LL;
1492+
LL.LibName = *LibHiddenItr;
1493+
LL.Position =
1494+
LibrariesHidden.getPosition(LibHiddenItr - LibrariesHidden.begin());
1495+
LL.CandidateExtensions = ArchiveExtensionsOnly;
1496+
LL.Modifier = LibraryLoad::Hidden;
1497+
LibraryLoads.push_back(std::move(LL));
1498+
}
1499+
1500+
// If there are any load-<modified> options then turn on flag overrides
1501+
// to avoid flag mismatch errors.
1502+
if (!LibrariesHidden.empty())
1503+
S.ObjLayer.setOverrideObjectFlagsWithResponsibilityFlags(true);
1504+
1505+
// Sort library loads by position in the argument list.
1506+
llvm::sort(LibraryLoads, [](const LibraryLoad &LHS, const LibraryLoad &RHS) {
1507+
return LHS.Position < RHS.Position;
1508+
});
14521509

1510+
// 3. Process library loads.
1511+
for (auto &LL : LibraryLoads) {
14531512
bool LibFound = false;
1454-
StringRef LibName(*LibItr);
1455-
unsigned LibIdx = Libraries.getPosition(LibItr - Libraries.begin());
1456-
auto &JD = *std::prev(IdxToJD.lower_bound(LibIdx))->second;
1513+
auto &JD = *std::prev(IdxToJD.lower_bound(LL.Position))->second;
14571514

14581515
// If this is the name of a JITDylib then link against that.
1459-
if (auto *LJD = S.ES.getJITDylibByName(LibName)) {
1516+
if (auto *LJD = S.ES.getJITDylibByName(LL.LibName)) {
14601517
JD.addToLinkOrder(*LJD);
14611518
continue;
14621519
}
@@ -1467,10 +1524,11 @@ static Error addLibraries(Session &S,
14671524
for (StringRef SearchPath : JDSearchPathsItr->second) {
14681525
for (const char *LibExt : {".dylib", ".so", ".a"}) {
14691526
SmallVector<char, 256> LibPath;
1470-
LibPath.reserve(SearchPath.size() + strlen("lib") + LibName.size() +
1471-
strlen(LibExt) + 2); // +2 for pathsep, null term.
1527+
LibPath.reserve(SearchPath.size() + strlen("lib") +
1528+
LL.LibName.size() + strlen(LibExt) +
1529+
2); // +2 for pathsep, null term.
14721530
llvm::copy(SearchPath, std::back_inserter(LibPath));
1473-
sys::path::append(LibPath, "lib" + LibName + LibExt);
1531+
sys::path::append(LibPath, "lib" + LL.LibName + LibExt);
14741532
LibPath.push_back('\0');
14751533

14761534
// Skip missing or non-regular paths.
@@ -1513,9 +1571,21 @@ static Error addLibraries(Session &S,
15131571
}
15141572
case file_magic::archive:
15151573
case file_magic::macho_universal_binary: {
1574+
unique_function<Expected<MaterializationUnit::Interface>(
1575+
ExecutionSession & ES, MemoryBufferRef ObjBuffer)>
1576+
GetObjFileInterface;
1577+
switch (LL.Modifier) {
1578+
case LibraryLoad::Standard:
1579+
GetObjFileInterface = getObjectFileInterface;
1580+
break;
1581+
case LibraryLoad::Hidden:
1582+
GetObjFileInterface = getObjectFileInterfaceHidden;
1583+
break;
1584+
}
15161585
auto G = StaticLibraryDefinitionGenerator::Load(
15171586
S.ObjLayer, LibPath.data(),
1518-
S.ES.getExecutorProcessControl().getTargetTriple());
1587+
S.ES.getExecutorProcessControl().getTargetTriple(),
1588+
std::move(GetObjFileInterface));
15191589
if (!G)
15201590
return G.takeError();
15211591
JD.addGenerator(std::move(*G));
@@ -1545,7 +1615,7 @@ static Error addLibraries(Session &S,
15451615
if (!LibFound)
15461616
return make_error<StringError>("While linking " + JD.getName() +
15471617
", could not find library for -l" +
1548-
LibName,
1618+
LL.LibName,
15491619
inconvertibleErrorCode());
15501620
}
15511621

llvm/tools/llvm-jitlink/llvm-jitlink.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ namespace llvm {
3232
struct Session;
3333

3434
struct Session {
35+
3536
orc::ExecutionSession ES;
3637
orc::JITDylib *MainJD = nullptr;
3738
orc::ObjectLinkingLayer ObjLayer;

0 commit comments

Comments
 (0)