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   JITSymbolFlags Flags = JITSymbolFlags::None;
24   if (GV.hasWeakLinkage() || GV.hasLinkOnceLinkage())
25     Flags |= JITSymbolFlags::Weak;
26   if (GV.hasCommonLinkage())
27     Flags |= JITSymbolFlags::Common;
28   if (!GV.hasLocalLinkage() && !GV.hasHiddenVisibility())
29     Flags |= JITSymbolFlags::Exported;
30 
31   if (isa<Function>(GV))
32     Flags |= JITSymbolFlags::Callable;
33   else if (isa<GlobalAlias>(GV) &&
34            isa<Function>(cast<GlobalAlias>(GV).getAliasee()))
35     Flags |= JITSymbolFlags::Callable;
36 
37   return Flags;
38 }
39 
40 JITSymbolFlags llvm::JITSymbolFlags::fromSummary(GlobalValueSummary *S) {
41   JITSymbolFlags Flags = JITSymbolFlags::None;
42   auto L = S->linkage();
43   if (GlobalValue::isWeakLinkage(L) || GlobalValue::isLinkOnceLinkage(L))
44     Flags |= JITSymbolFlags::Weak;
45   if (GlobalValue::isCommonLinkage(L))
46     Flags |= JITSymbolFlags::Common;
47   if (GlobalValue::isExternalLinkage(L) || GlobalValue::isExternalWeakLinkage(L))
48     Flags |= JITSymbolFlags::Exported;
49 
50   if (isa<FunctionSummary>(S))
51     Flags |= JITSymbolFlags::Callable;
52 
53   return Flags;
54 }
55 
56 Expected<JITSymbolFlags>
57 llvm::JITSymbolFlags::fromObjectSymbol(const object::SymbolRef &Symbol) {
58   JITSymbolFlags Flags = JITSymbolFlags::None;
59   if (Symbol.getFlags() & object::BasicSymbolRef::SF_Weak)
60     Flags |= JITSymbolFlags::Weak;
61   if (Symbol.getFlags() & object::BasicSymbolRef::SF_Common)
62     Flags |= JITSymbolFlags::Common;
63   if (Symbol.getFlags() & object::BasicSymbolRef::SF_Exported)
64     Flags |= JITSymbolFlags::Exported;
65 
66   auto SymbolType = Symbol.getType();
67   if (!SymbolType)
68     return SymbolType.takeError();
69 
70   if (*SymbolType & object::SymbolRef::ST_Function)
71     Flags |= JITSymbolFlags::Callable;
72 
73   return Flags;
74 }
75 
76 ARMJITSymbolFlags
77 llvm::ARMJITSymbolFlags::fromObjectSymbol(const object::SymbolRef &Symbol) {
78   ARMJITSymbolFlags Flags;
79   if (Symbol.getFlags() & object::BasicSymbolRef::SF_Thumb)
80     Flags |= ARMJITSymbolFlags::Thumb;
81   return Flags;
82 }
83 
84 /// Performs lookup by, for each symbol, first calling
85 ///        findSymbolInLogicalDylib and if that fails calling
86 ///        findSymbol.
87 void LegacyJITSymbolResolver::lookup(const LookupSet &Symbols,
88                                      OnResolvedFunction OnResolved) {
89   JITSymbolResolver::LookupResult Result;
90   for (auto &Symbol : Symbols) {
91     std::string SymName = Symbol.str();
92     if (auto Sym = findSymbolInLogicalDylib(SymName)) {
93       if (auto AddrOrErr = Sym.getAddress())
94         Result[Symbol] = JITEvaluatedSymbol(*AddrOrErr, Sym.getFlags());
95       else {
96         OnResolved(AddrOrErr.takeError());
97         return;
98       }
99     } else if (auto Err = Sym.takeError()) {
100       OnResolved(std::move(Err));
101       return;
102     } else {
103       // findSymbolInLogicalDylib failed. Lets try findSymbol.
104       if (auto Sym = findSymbol(SymName)) {
105         if (auto AddrOrErr = Sym.getAddress())
106           Result[Symbol] = JITEvaluatedSymbol(*AddrOrErr, Sym.getFlags());
107         else {
108           OnResolved(AddrOrErr.takeError());
109           return;
110         }
111       } else if (auto Err = Sym.takeError()) {
112         OnResolved(std::move(Err));
113         return;
114       } else {
115         OnResolved(make_error<StringError>("Symbol not found: " + Symbol,
116                                            inconvertibleErrorCode()));
117         return;
118       }
119     }
120   }
121 
122   OnResolved(std::move(Result));
123 }
124 
125 /// Performs flags lookup by calling findSymbolInLogicalDylib and
126 ///        returning the flags value for that symbol.
127 Expected<JITSymbolResolver::LookupSet>
128 LegacyJITSymbolResolver::getResponsibilitySet(const LookupSet &Symbols) {
129   JITSymbolResolver::LookupSet Result;
130 
131   for (auto &Symbol : Symbols) {
132     std::string SymName = Symbol.str();
133     if (auto Sym = findSymbolInLogicalDylib(SymName)) {
134       // If there's an existing def but it is not strong, then the caller is
135       // responsible for it.
136       if (!Sym.getFlags().isStrong())
137         Result.insert(Symbol);
138     } else if (auto Err = Sym.takeError())
139       return std::move(Err);
140     else {
141       // If there is no existing definition then the caller is responsible for
142       // it.
143       Result.insert(Symbol);
144     }
145   }
146 
147   return std::move(Result);
148 }
149