xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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