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   Expected<uint32_t> SymbolFlagsOrErr = Symbol.getFlags();
59   if (!SymbolFlagsOrErr)
60     // TODO: Test this error.
61     return SymbolFlagsOrErr.takeError();
62 
63   JITSymbolFlags Flags = JITSymbolFlags::None;
64   if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Weak)
65     Flags |= JITSymbolFlags::Weak;
66   if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Common)
67     Flags |= JITSymbolFlags::Common;
68   if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Exported)
69     Flags |= JITSymbolFlags::Exported;
70 
71   auto SymbolType = Symbol.getType();
72   if (!SymbolType)
73     return SymbolType.takeError();
74 
75   if (*SymbolType & object::SymbolRef::ST_Function)
76     Flags |= JITSymbolFlags::Callable;
77 
78   return Flags;
79 }
80 
81 ARMJITSymbolFlags
82 llvm::ARMJITSymbolFlags::fromObjectSymbol(const object::SymbolRef &Symbol) {
83   Expected<uint32_t> SymbolFlagsOrErr = Symbol.getFlags();
84   if (!SymbolFlagsOrErr)
85     // TODO: Actually report errors helpfully.
86     report_fatal_error(SymbolFlagsOrErr.takeError());
87   ARMJITSymbolFlags Flags;
88   if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Thumb)
89     Flags |= ARMJITSymbolFlags::Thumb;
90   return Flags;
91 }
92 
93 /// Performs lookup by, for each symbol, first calling
94 ///        findSymbolInLogicalDylib and if that fails calling
95 ///        findSymbol.
96 void LegacyJITSymbolResolver::lookup(const LookupSet &Symbols,
97                                      OnResolvedFunction OnResolved) {
98   JITSymbolResolver::LookupResult Result;
99   for (auto &Symbol : Symbols) {
100     std::string SymName = Symbol.str();
101     if (auto Sym = findSymbolInLogicalDylib(SymName)) {
102       if (auto AddrOrErr = Sym.getAddress())
103         Result[Symbol] = JITEvaluatedSymbol(*AddrOrErr, Sym.getFlags());
104       else {
105         OnResolved(AddrOrErr.takeError());
106         return;
107       }
108     } else if (auto Err = Sym.takeError()) {
109       OnResolved(std::move(Err));
110       return;
111     } else {
112       // findSymbolInLogicalDylib failed. Lets try findSymbol.
113       if (auto Sym = findSymbol(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         OnResolved(make_error<StringError>("Symbol not found: " + Symbol,
125                                            inconvertibleErrorCode()));
126         return;
127       }
128     }
129   }
130 
131   OnResolved(std::move(Result));
132 }
133 
134 /// Performs flags lookup by calling findSymbolInLogicalDylib and
135 ///        returning the flags value for that symbol.
136 Expected<JITSymbolResolver::LookupSet>
137 LegacyJITSymbolResolver::getResponsibilitySet(const LookupSet &Symbols) {
138   JITSymbolResolver::LookupSet Result;
139 
140   for (auto &Symbol : Symbols) {
141     std::string SymName = Symbol.str();
142     if (auto Sym = findSymbolInLogicalDylib(SymName)) {
143       // If there's an existing def but it is not strong, then the caller is
144       // responsible for it.
145       if (!Sym.getFlags().isStrong())
146         Result.insert(Symbol);
147     } else if (auto Err = Sym.takeError())
148       return std::move(Err);
149     else {
150       // If there is no existing definition then the caller is responsible for
151       // it.
152       Result.insert(Symbol);
153     }
154   }
155 
156   return std::move(Result);
157 }
158