10b57cec5SDimitry Andric //===----------- JITSymbol.cpp - JITSymbol class implementation -----------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // JITSymbol class implementation plus helper functions.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric #include "llvm/ExecutionEngine/JITSymbol.h"
140b57cec5SDimitry Andric #include "llvm/IR/Function.h"
150b57cec5SDimitry Andric #include "llvm/IR/GlobalAlias.h"
160b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
175ffd83dbSDimitry Andric #include "llvm/IR/ModuleSummaryIndex.h"
180b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h"
190b57cec5SDimitry Andric
200b57cec5SDimitry Andric using namespace llvm;
210b57cec5SDimitry Andric
fromGlobalValue(const GlobalValue & GV)220b57cec5SDimitry Andric JITSymbolFlags llvm::JITSymbolFlags::fromGlobalValue(const GlobalValue &GV) {
235ffd83dbSDimitry Andric assert(GV.hasName() && "Can't get flags for anonymous symbol");
245ffd83dbSDimitry Andric
250b57cec5SDimitry Andric JITSymbolFlags Flags = JITSymbolFlags::None;
260b57cec5SDimitry Andric if (GV.hasWeakLinkage() || GV.hasLinkOnceLinkage())
270b57cec5SDimitry Andric Flags |= JITSymbolFlags::Weak;
280b57cec5SDimitry Andric if (GV.hasCommonLinkage())
290b57cec5SDimitry Andric Flags |= JITSymbolFlags::Common;
300b57cec5SDimitry Andric if (!GV.hasLocalLinkage() && !GV.hasHiddenVisibility())
310b57cec5SDimitry Andric Flags |= JITSymbolFlags::Exported;
320b57cec5SDimitry Andric
330b57cec5SDimitry Andric if (isa<Function>(GV))
340b57cec5SDimitry Andric Flags |= JITSymbolFlags::Callable;
350b57cec5SDimitry Andric else if (isa<GlobalAlias>(GV) &&
360b57cec5SDimitry Andric isa<Function>(cast<GlobalAlias>(GV).getAliasee()))
370b57cec5SDimitry Andric Flags |= JITSymbolFlags::Callable;
380b57cec5SDimitry Andric
395ffd83dbSDimitry Andric // Check for a linker-private-global-prefix on the symbol name, in which
405ffd83dbSDimitry Andric // case it must be marked as non-exported.
415ffd83dbSDimitry Andric if (auto *M = GV.getParent()) {
425ffd83dbSDimitry Andric const auto &DL = M->getDataLayout();
435ffd83dbSDimitry Andric StringRef LPGP = DL.getLinkerPrivateGlobalPrefix();
445ffd83dbSDimitry Andric if (!LPGP.empty() && GV.getName().front() == '\01' &&
45*5f757f3fSDimitry Andric GV.getName().substr(1).starts_with(LPGP))
465ffd83dbSDimitry Andric Flags &= ~JITSymbolFlags::Exported;
475ffd83dbSDimitry Andric }
485ffd83dbSDimitry Andric
495ffd83dbSDimitry Andric return Flags;
505ffd83dbSDimitry Andric }
515ffd83dbSDimitry Andric
fromSummary(GlobalValueSummary * S)525ffd83dbSDimitry Andric JITSymbolFlags llvm::JITSymbolFlags::fromSummary(GlobalValueSummary *S) {
535ffd83dbSDimitry Andric JITSymbolFlags Flags = JITSymbolFlags::None;
545ffd83dbSDimitry Andric auto L = S->linkage();
555ffd83dbSDimitry Andric if (GlobalValue::isWeakLinkage(L) || GlobalValue::isLinkOnceLinkage(L))
565ffd83dbSDimitry Andric Flags |= JITSymbolFlags::Weak;
575ffd83dbSDimitry Andric if (GlobalValue::isCommonLinkage(L))
585ffd83dbSDimitry Andric Flags |= JITSymbolFlags::Common;
595ffd83dbSDimitry Andric if (GlobalValue::isExternalLinkage(L) || GlobalValue::isExternalWeakLinkage(L))
605ffd83dbSDimitry Andric Flags |= JITSymbolFlags::Exported;
615ffd83dbSDimitry Andric
625ffd83dbSDimitry Andric if (isa<FunctionSummary>(S))
635ffd83dbSDimitry Andric Flags |= JITSymbolFlags::Callable;
645ffd83dbSDimitry Andric
650b57cec5SDimitry Andric return Flags;
660b57cec5SDimitry Andric }
670b57cec5SDimitry Andric
680b57cec5SDimitry Andric Expected<JITSymbolFlags>
fromObjectSymbol(const object::SymbolRef & Symbol)690b57cec5SDimitry Andric llvm::JITSymbolFlags::fromObjectSymbol(const object::SymbolRef &Symbol) {
705ffd83dbSDimitry Andric Expected<uint32_t> SymbolFlagsOrErr = Symbol.getFlags();
715ffd83dbSDimitry Andric if (!SymbolFlagsOrErr)
725ffd83dbSDimitry Andric // TODO: Test this error.
735ffd83dbSDimitry Andric return SymbolFlagsOrErr.takeError();
745ffd83dbSDimitry Andric
750b57cec5SDimitry Andric JITSymbolFlags Flags = JITSymbolFlags::None;
765ffd83dbSDimitry Andric if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Weak)
770b57cec5SDimitry Andric Flags |= JITSymbolFlags::Weak;
785ffd83dbSDimitry Andric if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Common)
790b57cec5SDimitry Andric Flags |= JITSymbolFlags::Common;
805ffd83dbSDimitry Andric if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Exported)
810b57cec5SDimitry Andric Flags |= JITSymbolFlags::Exported;
820b57cec5SDimitry Andric
830b57cec5SDimitry Andric auto SymbolType = Symbol.getType();
840b57cec5SDimitry Andric if (!SymbolType)
850b57cec5SDimitry Andric return SymbolType.takeError();
860b57cec5SDimitry Andric
87349cc55cSDimitry Andric if (*SymbolType == object::SymbolRef::ST_Function)
880b57cec5SDimitry Andric Flags |= JITSymbolFlags::Callable;
890b57cec5SDimitry Andric
900b57cec5SDimitry Andric return Flags;
910b57cec5SDimitry Andric }
920b57cec5SDimitry Andric
930b57cec5SDimitry Andric ARMJITSymbolFlags
fromObjectSymbol(const object::SymbolRef & Symbol)940b57cec5SDimitry Andric llvm::ARMJITSymbolFlags::fromObjectSymbol(const object::SymbolRef &Symbol) {
955ffd83dbSDimitry Andric Expected<uint32_t> SymbolFlagsOrErr = Symbol.getFlags();
965ffd83dbSDimitry Andric if (!SymbolFlagsOrErr)
975ffd83dbSDimitry Andric // TODO: Actually report errors helpfully.
985ffd83dbSDimitry Andric report_fatal_error(SymbolFlagsOrErr.takeError());
990b57cec5SDimitry Andric ARMJITSymbolFlags Flags;
1005ffd83dbSDimitry Andric if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Thumb)
1010b57cec5SDimitry Andric Flags |= ARMJITSymbolFlags::Thumb;
1020b57cec5SDimitry Andric return Flags;
1030b57cec5SDimitry Andric }
1040b57cec5SDimitry Andric
1050b57cec5SDimitry Andric /// Performs lookup by, for each symbol, first calling
1060b57cec5SDimitry Andric /// findSymbolInLogicalDylib and if that fails calling
1070b57cec5SDimitry Andric /// findSymbol.
lookup(const LookupSet & Symbols,OnResolvedFunction OnResolved)1080b57cec5SDimitry Andric void LegacyJITSymbolResolver::lookup(const LookupSet &Symbols,
1090b57cec5SDimitry Andric OnResolvedFunction OnResolved) {
1100b57cec5SDimitry Andric JITSymbolResolver::LookupResult Result;
1110b57cec5SDimitry Andric for (auto &Symbol : Symbols) {
1120b57cec5SDimitry Andric std::string SymName = Symbol.str();
1130b57cec5SDimitry Andric if (auto Sym = findSymbolInLogicalDylib(SymName)) {
1140b57cec5SDimitry Andric if (auto AddrOrErr = Sym.getAddress())
1150b57cec5SDimitry Andric Result[Symbol] = JITEvaluatedSymbol(*AddrOrErr, Sym.getFlags());
1160b57cec5SDimitry Andric else {
1170b57cec5SDimitry Andric OnResolved(AddrOrErr.takeError());
1180b57cec5SDimitry Andric return;
1190b57cec5SDimitry Andric }
1200b57cec5SDimitry Andric } else if (auto Err = Sym.takeError()) {
1210b57cec5SDimitry Andric OnResolved(std::move(Err));
1220b57cec5SDimitry Andric return;
1230b57cec5SDimitry Andric } else {
1240b57cec5SDimitry Andric // findSymbolInLogicalDylib failed. Lets try findSymbol.
1250b57cec5SDimitry Andric if (auto Sym = findSymbol(SymName)) {
1260b57cec5SDimitry Andric if (auto AddrOrErr = Sym.getAddress())
1270b57cec5SDimitry Andric Result[Symbol] = JITEvaluatedSymbol(*AddrOrErr, Sym.getFlags());
1280b57cec5SDimitry Andric else {
1290b57cec5SDimitry Andric OnResolved(AddrOrErr.takeError());
1300b57cec5SDimitry Andric return;
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric } else if (auto Err = Sym.takeError()) {
1330b57cec5SDimitry Andric OnResolved(std::move(Err));
1340b57cec5SDimitry Andric return;
1350b57cec5SDimitry Andric } else {
1360b57cec5SDimitry Andric OnResolved(make_error<StringError>("Symbol not found: " + Symbol,
1370b57cec5SDimitry Andric inconvertibleErrorCode()));
1380b57cec5SDimitry Andric return;
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric }
1410b57cec5SDimitry Andric }
1420b57cec5SDimitry Andric
1430b57cec5SDimitry Andric OnResolved(std::move(Result));
1440b57cec5SDimitry Andric }
1450b57cec5SDimitry Andric
1460b57cec5SDimitry Andric /// Performs flags lookup by calling findSymbolInLogicalDylib and
1470b57cec5SDimitry Andric /// returning the flags value for that symbol.
1480b57cec5SDimitry Andric Expected<JITSymbolResolver::LookupSet>
getResponsibilitySet(const LookupSet & Symbols)1490b57cec5SDimitry Andric LegacyJITSymbolResolver::getResponsibilitySet(const LookupSet &Symbols) {
1500b57cec5SDimitry Andric JITSymbolResolver::LookupSet Result;
1510b57cec5SDimitry Andric
1520b57cec5SDimitry Andric for (auto &Symbol : Symbols) {
1530b57cec5SDimitry Andric std::string SymName = Symbol.str();
1540b57cec5SDimitry Andric if (auto Sym = findSymbolInLogicalDylib(SymName)) {
1550b57cec5SDimitry Andric // If there's an existing def but it is not strong, then the caller is
1560b57cec5SDimitry Andric // responsible for it.
1570b57cec5SDimitry Andric if (!Sym.getFlags().isStrong())
1580b57cec5SDimitry Andric Result.insert(Symbol);
1590b57cec5SDimitry Andric } else if (auto Err = Sym.takeError())
1600b57cec5SDimitry Andric return std::move(Err);
1610b57cec5SDimitry Andric else {
1620b57cec5SDimitry Andric // If there is no existing definition then the caller is responsible for
1630b57cec5SDimitry Andric // it.
1640b57cec5SDimitry Andric Result.insert(Symbol);
1650b57cec5SDimitry Andric }
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric
1680b57cec5SDimitry Andric return std::move(Result);
1690b57cec5SDimitry Andric }
170