forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[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").
- Loading branch information
Showing
6 changed files
with
182 additions
and
84 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
//===---- GetDylibInterface.h - Get interface for real dylib ----*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Get symbol interface from a real dynamic library or TAPI file. These | ||
// interfaces can be used to simulate weak linking (ld64 -weak-lx / | ||
// -weak_library) against a library that is absent at runtime. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_EXECUTIONENGINE_ORC_GETDYLIBINTERFACE_H | ||
#define LLVM_EXECUTIONENGINE_ORC_GETDYLIBINTERFACE_H | ||
|
||
#include "llvm/ExecutionEngine/Orc/Core.h" | ||
#include "llvm/Object/TapiUniversal.h" | ||
|
||
namespace llvm::orc { | ||
|
||
/// Returns a SymbolNameSet containing the exported symbols defined in the | ||
/// given dylib. | ||
Expected<SymbolNameSet> getDylibInterfaceFromDylib(ExecutionSession &ES, | ||
Twine Path); | ||
|
||
/// Returns a SymbolNameSet containing the exported symbols defined in the | ||
/// relevant slice of the TapiUniversal file. | ||
Expected<SymbolNameSet> getDylibInterfaceFromTapiFile(ExecutionSession &ES, | ||
Twine Path); | ||
|
||
/// Returns a SymbolNameSet containing the exported symbols defined in the | ||
/// relevant slice of the given file, which may be either a dylib or a tapi | ||
/// file. | ||
Expected<SymbolNameSet> getDylibInterface(ExecutionSession &ES, Twine Path); | ||
|
||
} // namespace llvm::orc | ||
|
||
#endif // LLVM_EXECUTIONENGINE_ORC_GETDYLIBINTERFACE_H |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
//===-------- GetDylibInterface.cpp - Get interface for real dylib --------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "llvm/ExecutionEngine/Orc/GetDylibInterface.h" | ||
|
||
#include "llvm/BinaryFormat/Magic.h" | ||
#include "llvm/Object/MachO.h" | ||
#include "llvm/Object/MachOUniversal.h" | ||
|
||
#define DEBUG_TYPE "orc" | ||
|
||
namespace llvm::orc { | ||
|
||
Expected<SymbolNameSet> getDylibInterfaceFromDylib(ExecutionSession &ES, | ||
Twine Path) { | ||
auto CPUType = MachO::getCPUType(ES.getTargetTriple()); | ||
if (!CPUType) | ||
return CPUType.takeError(); | ||
|
||
auto CPUSubType = MachO::getCPUSubType(ES.getTargetTriple()); | ||
if (!CPUSubType) | ||
return CPUSubType.takeError(); | ||
|
||
auto Buf = MemoryBuffer::getFile(Path); | ||
if (!Buf) | ||
return createFileError(Path, Buf.getError()); | ||
|
||
auto SymFile = | ||
object::SymbolicFile::createSymbolicFile((*Buf)->getMemBufferRef()); | ||
if (!SymFile) | ||
return SymFile.takeError(); | ||
|
||
std::unique_ptr<object::MachOObjectFile> MachOFile; | ||
if (isa<object::MachOObjectFile>(**SymFile)) | ||
MachOFile.reset(dyn_cast<object::MachOObjectFile>(SymFile->release())); | ||
else if (auto *MachOUni = | ||
dyn_cast<object::MachOUniversalBinary>(SymFile->get())) { | ||
for (auto &O : MachOUni->objects()) { | ||
if (O.getCPUType() == *CPUType && O.getCPUSubType() == *CPUSubType) { | ||
if (auto Obj = O.getAsObjectFile()) | ||
MachOFile = std::move(*Obj); | ||
else | ||
return Obj.takeError(); | ||
break; | ||
} | ||
} | ||
if (!MachOFile) | ||
return make_error<StringError>("MachO universal binary at " + Path + | ||
" does not contain a slice for " + | ||
ES.getTargetTriple().str(), | ||
inconvertibleErrorCode()); | ||
} else | ||
return make_error<StringError>("File at " + Path + " is not a MachO", | ||
inconvertibleErrorCode()); | ||
|
||
if (MachOFile->getHeader().filetype != MachO::MH_DYLIB) | ||
return make_error<StringError>("MachO at " + Path + " is not a dylib", | ||
inconvertibleErrorCode()); | ||
|
||
SymbolNameSet Symbols; | ||
for (auto &Sym : MachOFile->symbols()) { | ||
if (auto Name = Sym.getName()) | ||
Symbols.insert(ES.intern(*Name)); | ||
else | ||
return Name.takeError(); | ||
} | ||
|
||
return std::move(Symbols); | ||
} | ||
|
||
Expected<SymbolNameSet> getDylibInterfaceFromTapiFile(ExecutionSession &ES, | ||
Twine Path) { | ||
SymbolNameSet Symbols; | ||
|
||
auto TapiFileBuffer = MemoryBuffer::getFile(Path); | ||
if (!TapiFileBuffer) | ||
return createFileError(Path, TapiFileBuffer.getError()); | ||
|
||
auto Tapi = | ||
object::TapiUniversal::create((*TapiFileBuffer)->getMemBufferRef()); | ||
if (!Tapi) | ||
return Tapi.takeError(); | ||
|
||
auto CPUType = MachO::getCPUType(ES.getTargetTriple()); | ||
if (!CPUType) | ||
return CPUType.takeError(); | ||
|
||
auto CPUSubType = MachO::getCPUSubType(ES.getTargetTriple()); | ||
if (!CPUSubType) | ||
return CPUSubType.takeError(); | ||
|
||
auto &IF = (*Tapi)->getInterfaceFile(); | ||
auto Interface = | ||
IF.extract(MachO::getArchitectureFromCpuType(*CPUType, *CPUSubType)); | ||
if (!Interface) | ||
return Interface.takeError(); | ||
|
||
for (auto *Sym : (*Interface)->exports()) | ||
Symbols.insert(ES.intern(Sym->getName())); | ||
|
||
return Symbols; | ||
} | ||
|
||
Expected<SymbolNameSet> getDylibInterface(ExecutionSession &ES, Twine Path) { | ||
file_magic Magic; | ||
if (auto EC = identify_magic(Path, Magic)) | ||
return createFileError(Path, EC); | ||
|
||
SymbolNameSet Symbols; | ||
switch (Magic) { | ||
case file_magic::macho_dynamically_linked_shared_lib: | ||
return getDylibInterfaceFromDylib(ES, Path); | ||
case file_magic::tapi_file: | ||
return getDylibInterfaceFromTapiFile(ES, Path); | ||
default: | ||
return make_error<StringError>("Cannot get interface for " + Path + | ||
" unrecognized file type", | ||
inconvertibleErrorCode()); | ||
} | ||
} | ||
|
||
} // namespace llvm::orc |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters