170 lines
5.7 KiB
C++
170 lines
5.7 KiB
C++
|
//===----------- JITSymbol.cpp - JITSymbol class implementation -----------===//
|
||
|
//
|
||
|
// 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
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
//
|
||
|
// JITSymbol class implementation plus helper functions.
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
#include "llvm/ExecutionEngine/JITSymbol.h"
|
||
|
#include "llvm/IR/Function.h"
|
||
|
#include "llvm/IR/GlobalAlias.h"
|
||
|
#include "llvm/IR/GlobalValue.h"
|
||
|
#include "llvm/IR/ModuleSummaryIndex.h"
|
||
|
#include "llvm/Object/ObjectFile.h"
|
||
|
|
||
|
using namespace llvm;
|
||
|
|
||
|
JITSymbolFlags llvm::JITSymbolFlags::fromGlobalValue(const GlobalValue &GV) {
|
||
|
assert(GV.hasName() && "Can't get flags for anonymous symbol");
|
||
|
|
||
|
JITSymbolFlags Flags = JITSymbolFlags::None;
|
||
|
if (GV.hasWeakLinkage() || GV.hasLinkOnceLinkage())
|
||
|
Flags |= JITSymbolFlags::Weak;
|
||
|
if (GV.hasCommonLinkage())
|
||
|
Flags |= JITSymbolFlags::Common;
|
||
|
if (!GV.hasLocalLinkage() && !GV.hasHiddenVisibility())
|
||
|
Flags |= JITSymbolFlags::Exported;
|
||
|
|
||
|
if (isa<Function>(GV))
|
||
|
Flags |= JITSymbolFlags::Callable;
|
||
|
else if (isa<GlobalAlias>(GV) &&
|
||
|
isa<Function>(cast<GlobalAlias>(GV).getAliasee()))
|
||
|
Flags |= JITSymbolFlags::Callable;
|
||
|
|
||
|
// Check for a linker-private-global-prefix on the symbol name, in which
|
||
|
// case it must be marked as non-exported.
|
||
|
if (auto *M = GV.getParent()) {
|
||
|
const auto &DL = M->getDataLayout();
|
||
|
StringRef LPGP = DL.getLinkerPrivateGlobalPrefix();
|
||
|
if (!LPGP.empty() && GV.getName().front() == '\01' &&
|
||
|
GV.getName().substr(1).startswith(LPGP))
|
||
|
Flags &= ~JITSymbolFlags::Exported;
|
||
|
}
|
||
|
|
||
|
return Flags;
|
||
|
}
|
||
|
|
||
|
JITSymbolFlags llvm::JITSymbolFlags::fromSummary(GlobalValueSummary *S) {
|
||
|
JITSymbolFlags Flags = JITSymbolFlags::None;
|
||
|
auto L = S->linkage();
|
||
|
if (GlobalValue::isWeakLinkage(L) || GlobalValue::isLinkOnceLinkage(L))
|
||
|
Flags |= JITSymbolFlags::Weak;
|
||
|
if (GlobalValue::isCommonLinkage(L))
|
||
|
Flags |= JITSymbolFlags::Common;
|
||
|
if (GlobalValue::isExternalLinkage(L) || GlobalValue::isExternalWeakLinkage(L))
|
||
|
Flags |= JITSymbolFlags::Exported;
|
||
|
|
||
|
if (isa<FunctionSummary>(S))
|
||
|
Flags |= JITSymbolFlags::Callable;
|
||
|
|
||
|
return Flags;
|
||
|
}
|
||
|
|
||
|
Expected<JITSymbolFlags>
|
||
|
llvm::JITSymbolFlags::fromObjectSymbol(const object::SymbolRef &Symbol) {
|
||
|
Expected<uint32_t> SymbolFlagsOrErr = Symbol.getFlags();
|
||
|
if (!SymbolFlagsOrErr)
|
||
|
// TODO: Test this error.
|
||
|
return SymbolFlagsOrErr.takeError();
|
||
|
|
||
|
JITSymbolFlags Flags = JITSymbolFlags::None;
|
||
|
if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Weak)
|
||
|
Flags |= JITSymbolFlags::Weak;
|
||
|
if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Common)
|
||
|
Flags |= JITSymbolFlags::Common;
|
||
|
if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Exported)
|
||
|
Flags |= JITSymbolFlags::Exported;
|
||
|
|
||
|
auto SymbolType = Symbol.getType();
|
||
|
if (!SymbolType)
|
||
|
return SymbolType.takeError();
|
||
|
|
||
|
if (*SymbolType & object::SymbolRef::ST_Function)
|
||
|
Flags |= JITSymbolFlags::Callable;
|
||
|
|
||
|
return Flags;
|
||
|
}
|
||
|
|
||
|
ARMJITSymbolFlags
|
||
|
llvm::ARMJITSymbolFlags::fromObjectSymbol(const object::SymbolRef &Symbol) {
|
||
|
Expected<uint32_t> SymbolFlagsOrErr = Symbol.getFlags();
|
||
|
if (!SymbolFlagsOrErr)
|
||
|
// TODO: Actually report errors helpfully.
|
||
|
report_fatal_error(SymbolFlagsOrErr.takeError());
|
||
|
ARMJITSymbolFlags Flags;
|
||
|
if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Thumb)
|
||
|
Flags |= ARMJITSymbolFlags::Thumb;
|
||
|
return Flags;
|
||
|
}
|
||
|
|
||
|
/// Performs lookup by, for each symbol, first calling
|
||
|
/// findSymbolInLogicalDylib and if that fails calling
|
||
|
/// findSymbol.
|
||
|
void LegacyJITSymbolResolver::lookup(const LookupSet &Symbols,
|
||
|
OnResolvedFunction OnResolved) {
|
||
|
JITSymbolResolver::LookupResult Result;
|
||
|
for (auto &Symbol : Symbols) {
|
||
|
std::string SymName = Symbol.str();
|
||
|
if (auto Sym = findSymbolInLogicalDylib(SymName)) {
|
||
|
if (auto AddrOrErr = Sym.getAddress())
|
||
|
Result[Symbol] = JITEvaluatedSymbol(*AddrOrErr, Sym.getFlags());
|
||
|
else {
|
||
|
OnResolved(AddrOrErr.takeError());
|
||
|
return;
|
||
|
}
|
||
|
} else if (auto Err = Sym.takeError()) {
|
||
|
OnResolved(std::move(Err));
|
||
|
return;
|
||
|
} else {
|
||
|
// findSymbolInLogicalDylib failed. Lets try findSymbol.
|
||
|
if (auto Sym = findSymbol(SymName)) {
|
||
|
if (auto AddrOrErr = Sym.getAddress())
|
||
|
Result[Symbol] = JITEvaluatedSymbol(*AddrOrErr, Sym.getFlags());
|
||
|
else {
|
||
|
OnResolved(AddrOrErr.takeError());
|
||
|
return;
|
||
|
}
|
||
|
} else if (auto Err = Sym.takeError()) {
|
||
|
OnResolved(std::move(Err));
|
||
|
return;
|
||
|
} else {
|
||
|
OnResolved(make_error<StringError>("Symbol not found: " + Symbol,
|
||
|
inconvertibleErrorCode()));
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
OnResolved(std::move(Result));
|
||
|
}
|
||
|
|
||
|
/// Performs flags lookup by calling findSymbolInLogicalDylib and
|
||
|
/// returning the flags value for that symbol.
|
||
|
Expected<JITSymbolResolver::LookupSet>
|
||
|
LegacyJITSymbolResolver::getResponsibilitySet(const LookupSet &Symbols) {
|
||
|
JITSymbolResolver::LookupSet Result;
|
||
|
|
||
|
for (auto &Symbol : Symbols) {
|
||
|
std::string SymName = Symbol.str();
|
||
|
if (auto Sym = findSymbolInLogicalDylib(SymName)) {
|
||
|
// If there's an existing def but it is not strong, then the caller is
|
||
|
// responsible for it.
|
||
|
if (!Sym.getFlags().isStrong())
|
||
|
Result.insert(Symbol);
|
||
|
} else if (auto Err = Sym.takeError())
|
||
|
return std::move(Err);
|
||
|
else {
|
||
|
// If there is no existing definition then the caller is responsible for
|
||
|
// it.
|
||
|
Result.insert(Symbol);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return std::move(Result);
|
||
|
}
|