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-exception 6 // 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 20 using namespace llvm; 21 22 JITSymbolFlags 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 which 40 // 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 52 JITSymbolFlags 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 68 Expected<JITSymbolFlags> 69 llvm::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 93 ARMJITSymbolFlags 94 llvm::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 calling 106 /// findSymbolInLogicalDylib and if that fails calling 107 /// findSymbol. 108 void 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 and 147 /// returning the flags value for that symbol. 148 Expected<JITSymbolResolver::LookupSet> 149 LegacyJITSymbolResolver::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 is 156 // 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 for 163 // it. 164 Result.insert(Symbol); 165 } 166 } 167 168 return std::move(Result); 169 } 170