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