forked from OSchip/llvm-project
[ORC] Add MaterializationUnit::Interface parameter to ObjectLayer::add.
Also moves object interface building functions out of Mangling.h and in to the new ObjectFileInterfaces.h header, and updates the llvm-jitlink tool to use custom object interfaces rather than a custom link layer. ObjectLayer::add overloads are added to match the old signatures (which do not take a MaterializationUnit::Interface). These overloads use the standard getObjectFileInterface function to build an interface. Passing a MaterializationUnit::Interface explicitly makes it easier to alter the effective interface of the object file being added, e.g. by changing symbol visibility/linkage, or renaming symbols (in both cases the changes will need to be mirrored by a JITLink pass at link time to update the LinkGraph to match the explicit interface). Altering interfaces in this way can be useful when lazily compiling (e.g. for renaming function bodies) or emulating linker options (e.g. demoting all symbols to hidden visibility to emulate -load_hidden).
This commit is contained in:
parent
d4127c0d76
commit
4299d8d0ce
|
@ -140,14 +140,28 @@ public:
|
|||
/// Returns the execution session for this layer.
|
||||
ExecutionSession &getExecutionSession() { return ES; }
|
||||
|
||||
/// Adds a MaterializationUnit representing the given IR to the given
|
||||
/// JITDylib.
|
||||
virtual Error add(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> O);
|
||||
/// Adds a MaterializationUnit for the object file in the given memory buffer
|
||||
/// to the JITDylib for the given ResourceTracker.
|
||||
virtual Error add(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> O,
|
||||
MaterializationUnit::Interface I);
|
||||
|
||||
Error add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O) {
|
||||
return add(JD.getDefaultResourceTracker(), std::move(O));
|
||||
/// Adds a MaterializationUnit for the object file in the given memory buffer
|
||||
/// to the JITDylib for the given ResourceTracker. The interface for the
|
||||
/// object will be built using the default object interface builder.
|
||||
Error add(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> O);
|
||||
|
||||
/// Adds a MaterializationUnit for the object file in the given memory buffer
|
||||
/// to the given JITDylib.
|
||||
Error add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O,
|
||||
MaterializationUnit::Interface I) {
|
||||
return add(JD.getDefaultResourceTracker(), std::move(O), std::move(I));
|
||||
}
|
||||
|
||||
/// Adds a MaterializationUnit for the object file in the given memory buffer
|
||||
/// to the given JITDylib. The interface for the object will be built using
|
||||
/// the default object interface builder.
|
||||
Error add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O);
|
||||
|
||||
/// Emit should materialize the given IR.
|
||||
virtual void emit(std::unique_ptr<MaterializationResponsibility> R,
|
||||
std::unique_ptr<MemoryBuffer> O) = 0;
|
||||
|
@ -160,6 +174,7 @@ private:
|
|||
/// instance) by calling 'emit' on the given ObjectLayer.
|
||||
class BasicObjectLayerMaterializationUnit : public MaterializationUnit {
|
||||
public:
|
||||
/// Create using the default object interface builder function.
|
||||
static Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>>
|
||||
Create(ObjectLayer &L, std::unique_ptr<MemoryBuffer> O);
|
||||
|
||||
|
|
|
@ -55,11 +55,6 @@ public:
|
|||
SymbolNameToDefinitionMap *SymbolToDefinition = nullptr);
|
||||
};
|
||||
|
||||
/// Returns a SymbolFlagsMap for the object file represented by the given
|
||||
/// buffer, or an error if the buffer does not contain a valid object file.
|
||||
Expected<MaterializationUnit::Interface>
|
||||
getObjectInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer);
|
||||
|
||||
} // End namespace orc
|
||||
} // End namespace llvm
|
||||
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
//===-- ObjectFileInterface.h - MU interface utils for objects --*- 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Utilities for building MaterializationUnit::Interface objects from
|
||||
// object files.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_EXECUTIONENGINE_ORC_OBJECTFILEINTERFACE_H
|
||||
#define LLVM_EXECUTIONENGINE_ORC_OBJECTFILEINTERFACE_H
|
||||
|
||||
#include "llvm/ExecutionEngine/Orc/Core.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace orc {
|
||||
|
||||
/// Adds an initializer symbol to the given MU interface.
|
||||
/// The init symbol's name is guaranteed to be unique within I, and will be of
|
||||
/// the form $.<ObjFileName>.__inits.<N>, where N is some integer.
|
||||
void addInitSymbol(MaterializationUnit::Interface &I, ExecutionSession &ES,
|
||||
StringRef ObjFileName);
|
||||
|
||||
/// Returns a MaterializationUnit::Interface for the object file contained in
|
||||
/// the given buffer, or an error if the buffer does not contain a valid object
|
||||
/// file.
|
||||
Expected<MaterializationUnit::Interface>
|
||||
getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer);
|
||||
|
||||
} // End namespace orc
|
||||
} // End namespace llvm
|
||||
|
||||
#endif // LLVM_EXECUTIONENGINE_ORC_OBJECTFILEINTERFACE_H
|
|
@ -13,6 +13,7 @@ add_llvm_component_library(LLVMOrcJIT
|
|||
EPCGenericRTDyldMemoryManager.cpp
|
||||
EPCIndirectionUtils.cpp
|
||||
ExecutionUtils.cpp
|
||||
ObjectFileInterface.cpp
|
||||
IndirectionUtils.cpp
|
||||
IRCompileLayer.cpp
|
||||
IRTransformLayer.cpp
|
||||
|
|
|
@ -10,9 +10,8 @@
|
|||
|
||||
#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
|
||||
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
|
||||
#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/Object/MachO.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
|
||||
#define DEBUG_TYPE "orc"
|
||||
|
@ -161,20 +160,35 @@ ObjectLayer::ObjectLayer(ExecutionSession &ES) : ES(ES) {}
|
|||
|
||||
ObjectLayer::~ObjectLayer() {}
|
||||
|
||||
Error ObjectLayer::add(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> O) {
|
||||
Error ObjectLayer::add(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> O,
|
||||
MaterializationUnit::Interface I) {
|
||||
assert(RT && "RT can not be null");
|
||||
auto ObjMU = BasicObjectLayerMaterializationUnit::Create(*this, std::move(O));
|
||||
if (!ObjMU)
|
||||
return ObjMU.takeError();
|
||||
auto &JD = RT->getJITDylib();
|
||||
return JD.define(std::move(*ObjMU), std::move(RT));
|
||||
return JD.define(std::make_unique<BasicObjectLayerMaterializationUnit>(
|
||||
*this, std::move(O), std::move(I)),
|
||||
std::move(RT));
|
||||
}
|
||||
|
||||
Error ObjectLayer::add(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> O) {
|
||||
auto I = getObjectFileInterface(getExecutionSession(), O->getMemBufferRef());
|
||||
if (!I)
|
||||
return I.takeError();
|
||||
return add(std::move(RT), std::move(O), std::move(*I));
|
||||
}
|
||||
|
||||
Error ObjectLayer::add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O) {
|
||||
auto I = getObjectFileInterface(getExecutionSession(), O->getMemBufferRef());
|
||||
if (!I)
|
||||
return I.takeError();
|
||||
return add(JD, std::move(O), std::move(*I));
|
||||
}
|
||||
|
||||
Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>>
|
||||
BasicObjectLayerMaterializationUnit::Create(ObjectLayer &L,
|
||||
std::unique_ptr<MemoryBuffer> O) {
|
||||
|
||||
auto ObjInterface =
|
||||
getObjectInterface(L.getExecutionSession(), O->getMemBufferRef());
|
||||
getObjectFileInterface(L.getExecutionSession(), O->getMemBufferRef());
|
||||
|
||||
if (!ObjInterface)
|
||||
return ObjInterface.takeError();
|
||||
|
|
|
@ -7,13 +7,8 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ExecutionEngine/Orc/Mangling.h"
|
||||
#include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
|
||||
#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/Mangler.h"
|
||||
#include "llvm/Object/ELFObjectFile.h"
|
||||
#include "llvm/Object/MachO.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
|
||||
#define DEBUG_TYPE "orc"
|
||||
|
@ -85,190 +80,5 @@ void IRSymbolMapper::add(ExecutionSession &ES, const ManglingOptions &MO,
|
|||
}
|
||||
}
|
||||
|
||||
static SymbolStringPtr addInitSymbol(SymbolFlagsMap &SymbolFlags,
|
||||
ExecutionSession &ES,
|
||||
StringRef ObjFileName) {
|
||||
SymbolStringPtr InitSymbol;
|
||||
size_t Counter = 0;
|
||||
|
||||
do {
|
||||
std::string InitSymString;
|
||||
raw_string_ostream(InitSymString)
|
||||
<< "$." << ObjFileName << ".__inits." << Counter++;
|
||||
InitSymbol = ES.intern(InitSymString);
|
||||
} while (SymbolFlags.count(InitSymbol));
|
||||
|
||||
SymbolFlags[InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly;
|
||||
return InitSymbol;
|
||||
}
|
||||
|
||||
static Expected<MaterializationUnit::Interface>
|
||||
getMachOObjectFileSymbolInfo(ExecutionSession &ES,
|
||||
const object::MachOObjectFile &Obj) {
|
||||
SymbolFlagsMap SymbolFlags;
|
||||
|
||||
for (auto &Sym : Obj.symbols()) {
|
||||
Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
|
||||
if (!SymFlagsOrErr)
|
||||
// TODO: Test this error.
|
||||
return SymFlagsOrErr.takeError();
|
||||
|
||||
// Skip symbols not defined in this object file.
|
||||
if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
|
||||
continue;
|
||||
|
||||
// Skip symbols that are not global.
|
||||
if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
|
||||
continue;
|
||||
|
||||
// Skip symbols that have type SF_File.
|
||||
if (auto SymType = Sym.getType()) {
|
||||
if (*SymType == object::SymbolRef::ST_File)
|
||||
continue;
|
||||
} else
|
||||
return SymType.takeError();
|
||||
|
||||
auto Name = Sym.getName();
|
||||
if (!Name)
|
||||
return Name.takeError();
|
||||
auto InternedName = ES.intern(*Name);
|
||||
auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
|
||||
if (!SymFlags)
|
||||
return SymFlags.takeError();
|
||||
|
||||
// Strip the 'exported' flag from MachO linker-private symbols.
|
||||
if (Name->startswith("l"))
|
||||
*SymFlags &= ~JITSymbolFlags::Exported;
|
||||
|
||||
SymbolFlags[InternedName] = std::move(*SymFlags);
|
||||
}
|
||||
|
||||
SymbolStringPtr InitSymbol;
|
||||
for (auto &Sec : Obj.sections()) {
|
||||
auto SecType = Obj.getSectionType(Sec);
|
||||
if ((SecType & MachO::SECTION_TYPE) == MachO::S_MOD_INIT_FUNC_POINTERS) {
|
||||
InitSymbol = addInitSymbol(SymbolFlags, ES, Obj.getFileName());
|
||||
break;
|
||||
}
|
||||
auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl());
|
||||
auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl()));
|
||||
if (MachOPlatform::isInitializerSection(SegName, SecName)) {
|
||||
InitSymbol = addInitSymbol(SymbolFlags, ES, Obj.getFileName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return MaterializationUnit::Interface(std::move(SymbolFlags),
|
||||
std::move(InitSymbol));
|
||||
}
|
||||
|
||||
static Expected<MaterializationUnit::Interface>
|
||||
getELFObjectFileSymbolInfo(ExecutionSession &ES,
|
||||
const object::ELFObjectFileBase &Obj) {
|
||||
SymbolFlagsMap SymbolFlags;
|
||||
for (auto &Sym : Obj.symbols()) {
|
||||
Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
|
||||
if (!SymFlagsOrErr)
|
||||
// TODO: Test this error.
|
||||
return SymFlagsOrErr.takeError();
|
||||
|
||||
// Skip symbols not defined in this object file.
|
||||
if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
|
||||
continue;
|
||||
|
||||
// Skip symbols that are not global.
|
||||
if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
|
||||
continue;
|
||||
|
||||
// Skip symbols that have type SF_File.
|
||||
if (auto SymType = Sym.getType()) {
|
||||
if (*SymType == object::SymbolRef::ST_File)
|
||||
continue;
|
||||
} else
|
||||
return SymType.takeError();
|
||||
|
||||
auto Name = Sym.getName();
|
||||
if (!Name)
|
||||
return Name.takeError();
|
||||
auto InternedName = ES.intern(*Name);
|
||||
auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
|
||||
if (!SymFlags)
|
||||
return SymFlags.takeError();
|
||||
|
||||
// ELF STB_GNU_UNIQUE should map to Weak for ORC.
|
||||
if (Sym.getBinding() == ELF::STB_GNU_UNIQUE)
|
||||
*SymFlags |= JITSymbolFlags::Weak;
|
||||
|
||||
SymbolFlags[InternedName] = std::move(*SymFlags);
|
||||
}
|
||||
|
||||
SymbolStringPtr InitSymbol;
|
||||
for (auto &Sec : Obj.sections()) {
|
||||
if (auto SecName = Sec.getName()) {
|
||||
if (ELFNixPlatform::isInitializerSection(*SecName)) {
|
||||
InitSymbol = addInitSymbol(SymbolFlags, ES, Obj.getFileName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MaterializationUnit::Interface(std::move(SymbolFlags),
|
||||
std::move(InitSymbol));
|
||||
}
|
||||
|
||||
Expected<MaterializationUnit::Interface>
|
||||
getGenericObjectFileSymbolInfo(ExecutionSession &ES,
|
||||
const object::ObjectFile &Obj) {
|
||||
SymbolFlagsMap SymbolFlags;
|
||||
for (auto &Sym : Obj.symbols()) {
|
||||
Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
|
||||
if (!SymFlagsOrErr)
|
||||
// TODO: Test this error.
|
||||
return SymFlagsOrErr.takeError();
|
||||
|
||||
// Skip symbols not defined in this object file.
|
||||
if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
|
||||
continue;
|
||||
|
||||
// Skip symbols that are not global.
|
||||
if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
|
||||
continue;
|
||||
|
||||
// Skip symbols that have type SF_File.
|
||||
if (auto SymType = Sym.getType()) {
|
||||
if (*SymType == object::SymbolRef::ST_File)
|
||||
continue;
|
||||
} else
|
||||
return SymType.takeError();
|
||||
|
||||
auto Name = Sym.getName();
|
||||
if (!Name)
|
||||
return Name.takeError();
|
||||
auto InternedName = ES.intern(*Name);
|
||||
auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
|
||||
if (!SymFlags)
|
||||
return SymFlags.takeError();
|
||||
|
||||
SymbolFlags[InternedName] = std::move(*SymFlags);
|
||||
}
|
||||
|
||||
return MaterializationUnit::Interface(std::move(SymbolFlags), nullptr);
|
||||
}
|
||||
|
||||
Expected<MaterializationUnit::Interface>
|
||||
getObjectInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) {
|
||||
auto Obj = object::ObjectFile::createObjectFile(ObjBuffer);
|
||||
|
||||
if (!Obj)
|
||||
return Obj.takeError();
|
||||
|
||||
if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj->get()))
|
||||
return getMachOObjectFileSymbolInfo(ES, *MachOObj);
|
||||
else if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj->get()))
|
||||
return getELFObjectFileSymbolInfo(ES, *ELFObj);
|
||||
|
||||
return getGenericObjectFileSymbolInfo(ES, **Obj);
|
||||
}
|
||||
|
||||
} // End namespace orc.
|
||||
} // End namespace llvm.
|
||||
|
|
|
@ -0,0 +1,205 @@
|
|||
//===------ ObjectFileInterface.cpp - MU interface utils for objects ------===//
|
||||
//
|
||||
// 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/ObjectFileInterface.h"
|
||||
#include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
|
||||
#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
|
||||
#include "llvm/Object/ELFObjectFile.h"
|
||||
#include "llvm/Object/MachO.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
|
||||
#define DEBUG_TYPE "orc"
|
||||
|
||||
namespace llvm {
|
||||
namespace orc {
|
||||
|
||||
void addInitSymbol(MaterializationUnit::Interface &I, ExecutionSession &ES,
|
||||
StringRef ObjFileName) {
|
||||
assert(!I.InitSymbol && "I already has an init symbol");
|
||||
size_t Counter = 0;
|
||||
|
||||
do {
|
||||
std::string InitSymString;
|
||||
raw_string_ostream(InitSymString)
|
||||
<< "$." << ObjFileName << ".__inits." << Counter++;
|
||||
I.InitSymbol = ES.intern(InitSymString);
|
||||
} while (I.SymbolFlags.count(I.InitSymbol));
|
||||
|
||||
I.SymbolFlags[I.InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly;
|
||||
}
|
||||
|
||||
static Expected<MaterializationUnit::Interface>
|
||||
getMachOObjectFileSymbolInfo(ExecutionSession &ES,
|
||||
const object::MachOObjectFile &Obj) {
|
||||
MaterializationUnit::Interface I;
|
||||
|
||||
for (auto &Sym : Obj.symbols()) {
|
||||
Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
|
||||
if (!SymFlagsOrErr)
|
||||
// TODO: Test this error.
|
||||
return SymFlagsOrErr.takeError();
|
||||
|
||||
// Skip symbols not defined in this object file.
|
||||
if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
|
||||
continue;
|
||||
|
||||
// Skip symbols that are not global.
|
||||
if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
|
||||
continue;
|
||||
|
||||
// Skip symbols that have type SF_File.
|
||||
if (auto SymType = Sym.getType()) {
|
||||
if (*SymType == object::SymbolRef::ST_File)
|
||||
continue;
|
||||
} else
|
||||
return SymType.takeError();
|
||||
|
||||
auto Name = Sym.getName();
|
||||
if (!Name)
|
||||
return Name.takeError();
|
||||
auto InternedName = ES.intern(*Name);
|
||||
auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
|
||||
if (!SymFlags)
|
||||
return SymFlags.takeError();
|
||||
|
||||
// Strip the 'exported' flag from MachO linker-private symbols.
|
||||
if (Name->startswith("l"))
|
||||
*SymFlags &= ~JITSymbolFlags::Exported;
|
||||
|
||||
I.SymbolFlags[InternedName] = std::move(*SymFlags);
|
||||
}
|
||||
|
||||
for (auto &Sec : Obj.sections()) {
|
||||
auto SecType = Obj.getSectionType(Sec);
|
||||
if ((SecType & MachO::SECTION_TYPE) == MachO::S_MOD_INIT_FUNC_POINTERS) {
|
||||
addInitSymbol(I, ES, Obj.getFileName());
|
||||
break;
|
||||
}
|
||||
auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl());
|
||||
auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl()));
|
||||
if (MachOPlatform::isInitializerSection(SegName, SecName)) {
|
||||
addInitSymbol(I, ES, Obj.getFileName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return I;
|
||||
}
|
||||
|
||||
static Expected<MaterializationUnit::Interface>
|
||||
getELFObjectFileSymbolInfo(ExecutionSession &ES,
|
||||
const object::ELFObjectFileBase &Obj) {
|
||||
MaterializationUnit::Interface I;
|
||||
|
||||
for (auto &Sym : Obj.symbols()) {
|
||||
Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
|
||||
if (!SymFlagsOrErr)
|
||||
// TODO: Test this error.
|
||||
return SymFlagsOrErr.takeError();
|
||||
|
||||
// Skip symbols not defined in this object file.
|
||||
if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
|
||||
continue;
|
||||
|
||||
// Skip symbols that are not global.
|
||||
if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
|
||||
continue;
|
||||
|
||||
// Skip symbols that have type SF_File.
|
||||
if (auto SymType = Sym.getType()) {
|
||||
if (*SymType == object::SymbolRef::ST_File)
|
||||
continue;
|
||||
} else
|
||||
return SymType.takeError();
|
||||
|
||||
auto Name = Sym.getName();
|
||||
if (!Name)
|
||||
return Name.takeError();
|
||||
auto InternedName = ES.intern(*Name);
|
||||
auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
|
||||
if (!SymFlags)
|
||||
return SymFlags.takeError();
|
||||
|
||||
// ELF STB_GNU_UNIQUE should map to Weak for ORC.
|
||||
if (Sym.getBinding() == ELF::STB_GNU_UNIQUE)
|
||||
*SymFlags |= JITSymbolFlags::Weak;
|
||||
|
||||
I.SymbolFlags[InternedName] = std::move(*SymFlags);
|
||||
}
|
||||
|
||||
SymbolStringPtr InitSymbol;
|
||||
for (auto &Sec : Obj.sections()) {
|
||||
if (auto SecName = Sec.getName()) {
|
||||
if (ELFNixPlatform::isInitializerSection(*SecName)) {
|
||||
addInitSymbol(I, ES, Obj.getFileName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return I;
|
||||
}
|
||||
|
||||
Expected<MaterializationUnit::Interface>
|
||||
getGenericObjectFileSymbolInfo(ExecutionSession &ES,
|
||||
const object::ObjectFile &Obj) {
|
||||
MaterializationUnit::Interface I;
|
||||
|
||||
for (auto &Sym : Obj.symbols()) {
|
||||
Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
|
||||
if (!SymFlagsOrErr)
|
||||
// TODO: Test this error.
|
||||
return SymFlagsOrErr.takeError();
|
||||
|
||||
// Skip symbols not defined in this object file.
|
||||
if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
|
||||
continue;
|
||||
|
||||
// Skip symbols that are not global.
|
||||
if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
|
||||
continue;
|
||||
|
||||
// Skip symbols that have type SF_File.
|
||||
if (auto SymType = Sym.getType()) {
|
||||
if (*SymType == object::SymbolRef::ST_File)
|
||||
continue;
|
||||
} else
|
||||
return SymType.takeError();
|
||||
|
||||
auto Name = Sym.getName();
|
||||
if (!Name)
|
||||
return Name.takeError();
|
||||
auto InternedName = ES.intern(*Name);
|
||||
auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
|
||||
if (!SymFlags)
|
||||
return SymFlags.takeError();
|
||||
|
||||
I.SymbolFlags[InternedName] = std::move(*SymFlags);
|
||||
}
|
||||
|
||||
return I;
|
||||
}
|
||||
|
||||
Expected<MaterializationUnit::Interface>
|
||||
getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) {
|
||||
auto Obj = object::ObjectFile::createObjectFile(ObjBuffer);
|
||||
|
||||
if (!Obj)
|
||||
return Obj.takeError();
|
||||
|
||||
if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj->get()))
|
||||
return getMachOObjectFileSymbolInfo(ES, *MachOObj);
|
||||
else if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj->get()))
|
||||
return getELFObjectFileSymbolInfo(ES, *ELFObj);
|
||||
|
||||
return getGenericObjectFileSymbolInfo(ES, **Obj);
|
||||
}
|
||||
|
||||
} // End namespace orc.
|
||||
} // End namespace llvm.
|
|
@ -24,6 +24,7 @@
|
|||
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
|
||||
#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
|
||||
#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
|
||||
#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
|
||||
#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
|
||||
#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
|
@ -637,34 +638,23 @@ static std::unique_ptr<JITLinkMemoryManager> createMemoryManager() {
|
|||
return ExitOnErr(InProcessMemoryManager::Create());
|
||||
}
|
||||
|
||||
LLVMJITLinkObjectLinkingLayer::LLVMJITLinkObjectLinkingLayer(
|
||||
Session &S, JITLinkMemoryManager &MemMgr)
|
||||
: ObjectLinkingLayer(S.ES, MemMgr), S(S) {}
|
||||
static Expected<MaterializationUnit::Interface>
|
||||
getTestObjectFileInterface(Session &S, MemoryBufferRef O) {
|
||||
|
||||
Error LLVMJITLinkObjectLinkingLayer::add(ResourceTrackerSP RT,
|
||||
std::unique_ptr<MemoryBuffer> O) {
|
||||
|
||||
if (S.HarnessFiles.empty() || S.HarnessFiles.count(O->getBufferIdentifier()))
|
||||
return ObjectLinkingLayer::add(std::move(RT), std::move(O));
|
||||
|
||||
// Use getObjectSymbolInfo to compute the init symbol, but ignore
|
||||
// the symbols field. We'll handle that manually to include promotion.
|
||||
auto ObjInterface =
|
||||
getObjectInterface(getExecutionSession(), O->getMemBufferRef());
|
||||
|
||||
if (!ObjInterface)
|
||||
return ObjInterface.takeError();
|
||||
// Get the standard interface for this object, but ignore the symbols field.
|
||||
// We'll handle that manually to include promotion.
|
||||
auto I = getObjectFileInterface(S.ES, O);
|
||||
if (!I)
|
||||
return I.takeError();
|
||||
I->SymbolFlags.clear();
|
||||
|
||||
// If creating an object file was going to fail it would have happened above,
|
||||
// so we can 'cantFail' this.
|
||||
auto Obj =
|
||||
cantFail(object::ObjectFile::createObjectFile(O->getMemBufferRef()));
|
||||
|
||||
ObjInterface->SymbolFlags.clear();
|
||||
auto Obj = cantFail(object::ObjectFile::createObjectFile(O));
|
||||
|
||||
// The init symbol must be included in the SymbolFlags map if present.
|
||||
if (ObjInterface->InitSymbol)
|
||||
ObjInterface->SymbolFlags[ObjInterface->InitSymbol] =
|
||||
if (I->InitSymbol)
|
||||
I->SymbolFlags[I->InitSymbol] =
|
||||
JITSymbolFlags::MaterializationSideEffectsOnly;
|
||||
|
||||
for (auto &Sym : Obj->symbols()) {
|
||||
|
@ -698,7 +688,7 @@ Error LLVMJITLinkObjectLinkingLayer::add(ResourceTrackerSP RT,
|
|||
// that we've seen) or discard it.
|
||||
if (S.HarnessDefinitions.count(*Name) || S.CanonicalWeakDefs.count(*Name))
|
||||
continue;
|
||||
S.CanonicalWeakDefs[*Name] = O->getBufferIdentifier();
|
||||
S.CanonicalWeakDefs[*Name] = O.getBufferIdentifier();
|
||||
*SymFlags &= ~JITSymbolFlags::Weak;
|
||||
if (!S.HarnessExternals.count(*Name))
|
||||
*SymFlags &= ~JITSymbolFlags::Exported;
|
||||
|
@ -709,14 +699,10 @@ Error LLVMJITLinkObjectLinkingLayer::add(ResourceTrackerSP RT,
|
|||
continue;
|
||||
|
||||
auto InternedName = S.ES.intern(*Name);
|
||||
ObjInterface->SymbolFlags[InternedName] = std::move(*SymFlags);
|
||||
I->SymbolFlags[InternedName] = std::move(*SymFlags);
|
||||
}
|
||||
|
||||
auto MU = std::make_unique<BasicObjectLayerMaterializationUnit>(
|
||||
*this, std::move(O), std::move(*ObjInterface));
|
||||
|
||||
auto &JD = RT->getJITDylib();
|
||||
return JD.define(std::move(MU), std::move(RT));
|
||||
return I;
|
||||
}
|
||||
|
||||
static Error loadProcessSymbols(Session &S) {
|
||||
|
@ -954,7 +940,7 @@ Session::~Session() {
|
|||
|
||||
Session::Session(std::unique_ptr<ExecutorProcessControl> EPC, Error &Err)
|
||||
: ES(std::move(EPC)),
|
||||
ObjLayer(*this, ES.getExecutorProcessControl().getMemMgr()) {
|
||||
ObjLayer(ES, ES.getExecutorProcessControl().getMemMgr()) {
|
||||
|
||||
/// Local ObjectLinkingLayer::Plugin class to forward modifyPassConfig to the
|
||||
/// Session.
|
||||
|
@ -1034,7 +1020,7 @@ Session::Session(std::unique_ptr<ExecutorProcessControl> EPC, Error &Err)
|
|||
ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(HarnessFile)));
|
||||
|
||||
auto ObjInterface =
|
||||
ExitOnErr(getObjectInterface(ES, ObjBuffer->getMemBufferRef()));
|
||||
ExitOnErr(getObjectFileInterface(ES, ObjBuffer->getMemBufferRef()));
|
||||
|
||||
for (auto &KV : ObjInterface.SymbolFlags)
|
||||
HarnessDefinitions.insert(*KV.first);
|
||||
|
@ -1360,8 +1346,18 @@ static Error loadObjects(Session &S) {
|
|||
JD.addGenerator(ExitOnErr(StaticLibraryDefinitionGenerator::Load(
|
||||
S.ObjLayer, InputFile.c_str(),
|
||||
S.ES.getExecutorProcessControl().getTargetTriple())));
|
||||
else
|
||||
ExitOnErr(S.ObjLayer.add(JD, std::move(ObjBuffer)));
|
||||
else {
|
||||
if (S.HarnessFiles.empty())
|
||||
ExitOnErr(S.ObjLayer.add(JD, std::move(ObjBuffer)));
|
||||
else {
|
||||
// We're in -harness mode. Use a custom interface for this
|
||||
// test object.
|
||||
auto ObjInterface = ExitOnErr(
|
||||
getTestObjectFileInterface(S, ObjBuffer->getMemBufferRef()));
|
||||
ExitOnErr(
|
||||
S.ObjLayer.add(JD, std::move(ObjBuffer), std::move(ObjInterface)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Define absolute symbols.
|
||||
|
|
|
@ -31,25 +31,10 @@ namespace llvm {
|
|||
|
||||
struct Session;
|
||||
|
||||
/// ObjectLinkingLayer with additional support for symbol promotion.
|
||||
class LLVMJITLinkObjectLinkingLayer : public orc::ObjectLinkingLayer {
|
||||
public:
|
||||
using orc::ObjectLinkingLayer::add;
|
||||
|
||||
LLVMJITLinkObjectLinkingLayer(Session &S,
|
||||
jitlink::JITLinkMemoryManager &MemMgr);
|
||||
|
||||
Error add(orc::ResourceTrackerSP RT,
|
||||
std::unique_ptr<MemoryBuffer> O) override;
|
||||
|
||||
private:
|
||||
Session &S;
|
||||
};
|
||||
|
||||
struct Session {
|
||||
orc::ExecutionSession ES;
|
||||
orc::JITDylib *MainJD = nullptr;
|
||||
LLVMJITLinkObjectLinkingLayer ObjLayer;
|
||||
orc::ObjectLinkingLayer ObjLayer;
|
||||
orc::JITDylibSearchOrder JDSearchOrder;
|
||||
|
||||
~Session();
|
||||
|
|
Loading…
Reference in New Issue