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>(Val: GV)) |
34 | Flags |= JITSymbolFlags::Callable; |
35 | else if (isa<GlobalAlias>(Val: GV) && |
36 | isa<Function>(Val: cast<GlobalAlias>(Val: 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(Start: 1).starts_with(Prefix: 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(Linkage: L) || GlobalValue::isLinkOnceLinkage(Linkage: L)) |
56 | Flags |= JITSymbolFlags::Weak; |
57 | if (GlobalValue::isCommonLinkage(Linkage: L)) |
58 | Flags |= JITSymbolFlags::Common; |
59 | if (GlobalValue::isExternalLinkage(Linkage: L) || GlobalValue::isExternalWeakLinkage(Linkage: L)) |
60 | Flags |= JITSymbolFlags::Exported; |
61 | |
62 | if (isa<FunctionSummary>(Val: 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(Err: 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(Name: 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(Name: 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>(Args: "Symbol not found: "+ Symbol, |
137 | Args: 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(Name: 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(x: 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(x: Symbol); |
165 | } |
166 | } |
167 | |
168 | return std::move(Result); |
169 | } |
170 |