170 lines · cpp
1//===----------- JITSymbol.cpp - JITSymbol class implementation -----------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// JITSymbol class implementation plus helper functions.10//11//===----------------------------------------------------------------------===//12 13#include "llvm/ExecutionEngine/JITSymbol.h"14#include "llvm/IR/Function.h"15#include "llvm/IR/GlobalAlias.h"16#include "llvm/IR/GlobalValue.h"17#include "llvm/IR/ModuleSummaryIndex.h"18#include "llvm/Object/ObjectFile.h"19 20using namespace llvm;21 22JITSymbolFlags llvm::JITSymbolFlags::fromGlobalValue(const GlobalValue &GV) {23 assert(GV.hasName() && "Can't get flags for anonymous symbol");24 25 JITSymbolFlags Flags = JITSymbolFlags::None;26 if (GV.hasWeakLinkage() || GV.hasLinkOnceLinkage())27 Flags |= JITSymbolFlags::Weak;28 if (GV.hasCommonLinkage())29 Flags |= JITSymbolFlags::Common;30 if (!GV.hasLocalLinkage() && !GV.hasHiddenVisibility())31 Flags |= JITSymbolFlags::Exported;32 33 if (isa<Function>(GV))34 Flags |= JITSymbolFlags::Callable;35 else if (isa<GlobalAlias>(GV) &&36 isa<Function>(cast<GlobalAlias>(GV).getAliasee()))37 Flags |= JITSymbolFlags::Callable;38 39 // Check for a linker-private-global-prefix on the symbol name, in which40 // case it must be marked as non-exported.41 if (auto *M = GV.getParent()) {42 const auto &DL = M->getDataLayout();43 StringRef LPGP = DL.getLinkerPrivateGlobalPrefix();44 if (!LPGP.empty() && GV.getName().front() == '\01' &&45 GV.getName().substr(1).starts_with(LPGP))46 Flags &= ~JITSymbolFlags::Exported;47 }48 49 return Flags;50}51 52JITSymbolFlags llvm::JITSymbolFlags::fromSummary(GlobalValueSummary *S) {53 JITSymbolFlags Flags = JITSymbolFlags::None;54 auto L = S->linkage();55 if (GlobalValue::isWeakLinkage(L) || GlobalValue::isLinkOnceLinkage(L))56 Flags |= JITSymbolFlags::Weak;57 if (GlobalValue::isCommonLinkage(L))58 Flags |= JITSymbolFlags::Common;59 if (GlobalValue::isExternalLinkage(L) || GlobalValue::isExternalWeakLinkage(L))60 Flags |= JITSymbolFlags::Exported;61 62 if (isa<FunctionSummary>(S))63 Flags |= JITSymbolFlags::Callable;64 65 return Flags;66}67 68Expected<JITSymbolFlags>69llvm::JITSymbolFlags::fromObjectSymbol(const object::SymbolRef &Symbol) {70 Expected<uint32_t> SymbolFlagsOrErr = Symbol.getFlags();71 if (!SymbolFlagsOrErr)72 // TODO: Test this error.73 return SymbolFlagsOrErr.takeError();74 75 JITSymbolFlags Flags = JITSymbolFlags::None;76 if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Weak)77 Flags |= JITSymbolFlags::Weak;78 if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Common)79 Flags |= JITSymbolFlags::Common;80 if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Exported)81 Flags |= JITSymbolFlags::Exported;82 83 auto SymbolType = Symbol.getType();84 if (!SymbolType)85 return SymbolType.takeError();86 87 if (*SymbolType == object::SymbolRef::ST_Function)88 Flags |= JITSymbolFlags::Callable;89 90 return Flags;91}92 93ARMJITSymbolFlags94llvm::ARMJITSymbolFlags::fromObjectSymbol(const object::SymbolRef &Symbol) {95 Expected<uint32_t> SymbolFlagsOrErr = Symbol.getFlags();96 if (!SymbolFlagsOrErr)97 // TODO: Actually report errors helpfully.98 report_fatal_error(SymbolFlagsOrErr.takeError());99 ARMJITSymbolFlags Flags;100 if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Thumb)101 Flags |= ARMJITSymbolFlags::Thumb;102 return Flags;103}104 105/// Performs lookup by, for each symbol, first calling106/// findSymbolInLogicalDylib and if that fails calling107/// findSymbol.108void LegacyJITSymbolResolver::lookup(const LookupSet &Symbols,109 OnResolvedFunction OnResolved) {110 JITSymbolResolver::LookupResult Result;111 for (auto &Symbol : Symbols) {112 std::string SymName = Symbol.str();113 if (auto Sym = findSymbolInLogicalDylib(SymName)) {114 if (auto AddrOrErr = Sym.getAddress())115 Result[Symbol] = JITEvaluatedSymbol(*AddrOrErr, Sym.getFlags());116 else {117 OnResolved(AddrOrErr.takeError());118 return;119 }120 } else if (auto Err = Sym.takeError()) {121 OnResolved(std::move(Err));122 return;123 } else {124 // findSymbolInLogicalDylib failed. Lets try findSymbol.125 if (auto Sym = findSymbol(SymName)) {126 if (auto AddrOrErr = Sym.getAddress())127 Result[Symbol] = JITEvaluatedSymbol(*AddrOrErr, Sym.getFlags());128 else {129 OnResolved(AddrOrErr.takeError());130 return;131 }132 } else if (auto Err = Sym.takeError()) {133 OnResolved(std::move(Err));134 return;135 } else {136 OnResolved(make_error<StringError>("Symbol not found: " + Symbol,137 inconvertibleErrorCode()));138 return;139 }140 }141 }142 143 OnResolved(std::move(Result));144}145 146/// Performs flags lookup by calling findSymbolInLogicalDylib and147/// returning the flags value for that symbol.148Expected<JITSymbolResolver::LookupSet>149LegacyJITSymbolResolver::getResponsibilitySet(const LookupSet &Symbols) {150 JITSymbolResolver::LookupSet Result;151 152 for (auto &Symbol : Symbols) {153 std::string SymName = Symbol.str();154 if (auto Sym = findSymbolInLogicalDylib(SymName)) {155 // If there's an existing def but it is not strong, then the caller is156 // responsible for it.157 if (!Sym.getFlags().isStrong())158 Result.insert(Symbol);159 } else if (auto Err = Sym.takeError())160 return std::move(Err);161 else {162 // If there is no existing definition then the caller is responsible for163 // it.164 Result.insert(Symbol);165 }166 }167 168 return std::move(Result);169}170