xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===----------- JITSymbol.cpp - JITSymbol class implementation -----------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric // JITSymbol class implementation plus helper functions.
10*0b57cec5SDimitry Andric //
11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
12*0b57cec5SDimitry Andric 
13*0b57cec5SDimitry Andric #include "llvm/ExecutionEngine/JITSymbol.h"
14*0b57cec5SDimitry Andric #include "llvm/IR/Function.h"
15*0b57cec5SDimitry Andric #include "llvm/IR/GlobalAlias.h"
16*0b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
17*0b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h"
18*0b57cec5SDimitry Andric 
19*0b57cec5SDimitry Andric using namespace llvm;
20*0b57cec5SDimitry Andric 
21*0b57cec5SDimitry Andric JITSymbolFlags llvm::JITSymbolFlags::fromGlobalValue(const GlobalValue &GV) {
22*0b57cec5SDimitry Andric   JITSymbolFlags Flags = JITSymbolFlags::None;
23*0b57cec5SDimitry Andric   if (GV.hasWeakLinkage() || GV.hasLinkOnceLinkage())
24*0b57cec5SDimitry Andric     Flags |= JITSymbolFlags::Weak;
25*0b57cec5SDimitry Andric   if (GV.hasCommonLinkage())
26*0b57cec5SDimitry Andric     Flags |= JITSymbolFlags::Common;
27*0b57cec5SDimitry Andric   if (!GV.hasLocalLinkage() && !GV.hasHiddenVisibility())
28*0b57cec5SDimitry Andric     Flags |= JITSymbolFlags::Exported;
29*0b57cec5SDimitry Andric 
30*0b57cec5SDimitry Andric   if (isa<Function>(GV))
31*0b57cec5SDimitry Andric     Flags |= JITSymbolFlags::Callable;
32*0b57cec5SDimitry Andric   else if (isa<GlobalAlias>(GV) &&
33*0b57cec5SDimitry Andric            isa<Function>(cast<GlobalAlias>(GV).getAliasee()))
34*0b57cec5SDimitry Andric     Flags |= JITSymbolFlags::Callable;
35*0b57cec5SDimitry Andric 
36*0b57cec5SDimitry Andric   return Flags;
37*0b57cec5SDimitry Andric }
38*0b57cec5SDimitry Andric 
39*0b57cec5SDimitry Andric Expected<JITSymbolFlags>
40*0b57cec5SDimitry Andric llvm::JITSymbolFlags::fromObjectSymbol(const object::SymbolRef &Symbol) {
41*0b57cec5SDimitry Andric   JITSymbolFlags Flags = JITSymbolFlags::None;
42*0b57cec5SDimitry Andric   if (Symbol.getFlags() & object::BasicSymbolRef::SF_Weak)
43*0b57cec5SDimitry Andric     Flags |= JITSymbolFlags::Weak;
44*0b57cec5SDimitry Andric   if (Symbol.getFlags() & object::BasicSymbolRef::SF_Common)
45*0b57cec5SDimitry Andric     Flags |= JITSymbolFlags::Common;
46*0b57cec5SDimitry Andric   if (Symbol.getFlags() & object::BasicSymbolRef::SF_Exported)
47*0b57cec5SDimitry Andric     Flags |= JITSymbolFlags::Exported;
48*0b57cec5SDimitry Andric 
49*0b57cec5SDimitry Andric   auto SymbolType = Symbol.getType();
50*0b57cec5SDimitry Andric   if (!SymbolType)
51*0b57cec5SDimitry Andric     return SymbolType.takeError();
52*0b57cec5SDimitry Andric 
53*0b57cec5SDimitry Andric   if (*SymbolType & object::SymbolRef::ST_Function)
54*0b57cec5SDimitry Andric     Flags |= JITSymbolFlags::Callable;
55*0b57cec5SDimitry Andric 
56*0b57cec5SDimitry Andric   return Flags;
57*0b57cec5SDimitry Andric }
58*0b57cec5SDimitry Andric 
59*0b57cec5SDimitry Andric ARMJITSymbolFlags
60*0b57cec5SDimitry Andric llvm::ARMJITSymbolFlags::fromObjectSymbol(const object::SymbolRef &Symbol) {
61*0b57cec5SDimitry Andric   ARMJITSymbolFlags Flags;
62*0b57cec5SDimitry Andric   if (Symbol.getFlags() & object::BasicSymbolRef::SF_Thumb)
63*0b57cec5SDimitry Andric     Flags |= ARMJITSymbolFlags::Thumb;
64*0b57cec5SDimitry Andric   return Flags;
65*0b57cec5SDimitry Andric }
66*0b57cec5SDimitry Andric 
67*0b57cec5SDimitry Andric /// Performs lookup by, for each symbol, first calling
68*0b57cec5SDimitry Andric ///        findSymbolInLogicalDylib and if that fails calling
69*0b57cec5SDimitry Andric ///        findSymbol.
70*0b57cec5SDimitry Andric void LegacyJITSymbolResolver::lookup(const LookupSet &Symbols,
71*0b57cec5SDimitry Andric                                      OnResolvedFunction OnResolved) {
72*0b57cec5SDimitry Andric   JITSymbolResolver::LookupResult Result;
73*0b57cec5SDimitry Andric   for (auto &Symbol : Symbols) {
74*0b57cec5SDimitry Andric     std::string SymName = Symbol.str();
75*0b57cec5SDimitry Andric     if (auto Sym = findSymbolInLogicalDylib(SymName)) {
76*0b57cec5SDimitry Andric       if (auto AddrOrErr = Sym.getAddress())
77*0b57cec5SDimitry Andric         Result[Symbol] = JITEvaluatedSymbol(*AddrOrErr, Sym.getFlags());
78*0b57cec5SDimitry Andric       else {
79*0b57cec5SDimitry Andric         OnResolved(AddrOrErr.takeError());
80*0b57cec5SDimitry Andric         return;
81*0b57cec5SDimitry Andric       }
82*0b57cec5SDimitry Andric     } else if (auto Err = Sym.takeError()) {
83*0b57cec5SDimitry Andric       OnResolved(std::move(Err));
84*0b57cec5SDimitry Andric       return;
85*0b57cec5SDimitry Andric     } else {
86*0b57cec5SDimitry Andric       // findSymbolInLogicalDylib failed. Lets try findSymbol.
87*0b57cec5SDimitry Andric       if (auto Sym = findSymbol(SymName)) {
88*0b57cec5SDimitry Andric         if (auto AddrOrErr = Sym.getAddress())
89*0b57cec5SDimitry Andric           Result[Symbol] = JITEvaluatedSymbol(*AddrOrErr, Sym.getFlags());
90*0b57cec5SDimitry Andric         else {
91*0b57cec5SDimitry Andric           OnResolved(AddrOrErr.takeError());
92*0b57cec5SDimitry Andric           return;
93*0b57cec5SDimitry Andric         }
94*0b57cec5SDimitry Andric       } else if (auto Err = Sym.takeError()) {
95*0b57cec5SDimitry Andric         OnResolved(std::move(Err));
96*0b57cec5SDimitry Andric         return;
97*0b57cec5SDimitry Andric       } else {
98*0b57cec5SDimitry Andric         OnResolved(make_error<StringError>("Symbol not found: " + Symbol,
99*0b57cec5SDimitry Andric                                            inconvertibleErrorCode()));
100*0b57cec5SDimitry Andric         return;
101*0b57cec5SDimitry Andric       }
102*0b57cec5SDimitry Andric     }
103*0b57cec5SDimitry Andric   }
104*0b57cec5SDimitry Andric 
105*0b57cec5SDimitry Andric   OnResolved(std::move(Result));
106*0b57cec5SDimitry Andric }
107*0b57cec5SDimitry Andric 
108*0b57cec5SDimitry Andric /// Performs flags lookup by calling findSymbolInLogicalDylib and
109*0b57cec5SDimitry Andric ///        returning the flags value for that symbol.
110*0b57cec5SDimitry Andric Expected<JITSymbolResolver::LookupSet>
111*0b57cec5SDimitry Andric LegacyJITSymbolResolver::getResponsibilitySet(const LookupSet &Symbols) {
112*0b57cec5SDimitry Andric   JITSymbolResolver::LookupSet Result;
113*0b57cec5SDimitry Andric 
114*0b57cec5SDimitry Andric   for (auto &Symbol : Symbols) {
115*0b57cec5SDimitry Andric     std::string SymName = Symbol.str();
116*0b57cec5SDimitry Andric     if (auto Sym = findSymbolInLogicalDylib(SymName)) {
117*0b57cec5SDimitry Andric       // If there's an existing def but it is not strong, then the caller is
118*0b57cec5SDimitry Andric       // responsible for it.
119*0b57cec5SDimitry Andric       if (!Sym.getFlags().isStrong())
120*0b57cec5SDimitry Andric         Result.insert(Symbol);
121*0b57cec5SDimitry Andric     } else if (auto Err = Sym.takeError())
122*0b57cec5SDimitry Andric       return std::move(Err);
123*0b57cec5SDimitry Andric     else {
124*0b57cec5SDimitry Andric       // If there is no existing definition then the caller is responsible for
125*0b57cec5SDimitry Andric       // it.
126*0b57cec5SDimitry Andric       Result.insert(Symbol);
127*0b57cec5SDimitry Andric     }
128*0b57cec5SDimitry Andric   }
129*0b57cec5SDimitry Andric 
130*0b57cec5SDimitry Andric   return std::move(Result);
131*0b57cec5SDimitry Andric }
132