1 //===------- ELFLinkGraphBuilder.h - ELF LinkGraph builder ------*- C++ -*-===//
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 // Generic ELF LinkGraph building code.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H
14 #define LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H
15
16 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
17 #include "llvm/Object/ELF.h"
18 #include "llvm/Support/Debug.h"
19 #include "llvm/Support/Error.h"
20 #include "llvm/Support/FormatVariadic.h"
21
22 #define DEBUG_TYPE "jitlink"
23
24 namespace llvm {
25 namespace jitlink {
26
27 /// Common link-graph building code shared between all ELFFiles.
28 class ELFLinkGraphBuilderBase {
29 public:
ELFLinkGraphBuilderBase(std::unique_ptr<LinkGraph> G)30 ELFLinkGraphBuilderBase(std::unique_ptr<LinkGraph> G) : G(std::move(G)) {}
31 virtual ~ELFLinkGraphBuilderBase();
32
33 protected:
isDwarfSection(StringRef SectionName)34 static bool isDwarfSection(StringRef SectionName) {
35 return llvm::is_contained(DwarfSectionNames, SectionName);
36 }
37
getCommonSection()38 Section &getCommonSection() {
39 if (!CommonSection) {
40 auto Prot = static_cast<sys::Memory::ProtectionFlags>(
41 sys::Memory::MF_READ | sys::Memory::MF_WRITE);
42 CommonSection = &G->createSection(CommonSectionName, Prot);
43 }
44 return *CommonSection;
45 }
46
47 std::unique_ptr<LinkGraph> G;
48
49 private:
50 static StringRef CommonSectionName;
51 static ArrayRef<const char *> DwarfSectionNames;
52
53 Section *CommonSection = nullptr;
54 };
55
56 /// Ling-graph building code that's specific to the given ELFT, but common
57 /// across all architectures.
58 template <typename ELFT>
59 class ELFLinkGraphBuilder : public ELFLinkGraphBuilderBase {
60 using ELFFile = object::ELFFile<ELFT>;
61
62 public:
63 ELFLinkGraphBuilder(const object::ELFFile<ELFT> &Obj, Triple TT,
64 StringRef FileName,
65 LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);
66
67 /// Attempt to construct and return the LinkGraph.
68 Expected<std::unique_ptr<LinkGraph>> buildGraph();
69
70 /// Call to derived class to handle relocations. These require
71 /// architecture specific knowledge to map to JITLink edge kinds.
72 virtual Error addRelocations() = 0;
73
74 protected:
75 using ELFSectionIndex = unsigned;
76 using ELFSymbolIndex = unsigned;
77
isRelocatable()78 bool isRelocatable() const {
79 return Obj.getHeader().e_type == llvm::ELF::ET_REL;
80 }
81
setGraphSection(ELFSectionIndex SecIndex,Section & Sec)82 void setGraphSection(ELFSectionIndex SecIndex, Section &Sec) {
83 assert(!GraphSections.count(SecIndex) && "Duplicate section at index");
84 GraphSections[SecIndex] = &Sec;
85 }
86
getGraphSection(ELFSectionIndex SecIndex)87 Section *getGraphSection(ELFSectionIndex SecIndex) {
88 auto I = GraphSections.find(SecIndex);
89 if (I == GraphSections.end())
90 return nullptr;
91 return I->second;
92 }
93
setGraphSymbol(ELFSymbolIndex SymIndex,Symbol & Sym)94 void setGraphSymbol(ELFSymbolIndex SymIndex, Symbol &Sym) {
95 assert(!GraphSymbols.count(SymIndex) && "Duplicate symbol at index");
96 GraphSymbols[SymIndex] = &Sym;
97 }
98
getGraphSymbol(ELFSymbolIndex SymIndex)99 Symbol *getGraphSymbol(ELFSymbolIndex SymIndex) {
100 auto I = GraphSymbols.find(SymIndex);
101 if (I == GraphSymbols.end())
102 return nullptr;
103 return I->second;
104 }
105
106 Expected<std::pair<Linkage, Scope>>
107 getSymbolLinkageAndScope(const typename ELFT::Sym &Sym, StringRef Name);
108
109 Error prepare();
110 Error graphifySections();
111 Error graphifySymbols();
112
113 const ELFFile &Obj;
114
115 typename ELFFile::Elf_Shdr_Range Sections;
116 const typename ELFFile::Elf_Shdr *SymTabSec = nullptr;
117 StringRef SectionStringTab;
118
119 // Maps ELF section indexes to LinkGraph Sections.
120 // Only SHF_ALLOC sections will have graph sections.
121 DenseMap<ELFSectionIndex, Section *> GraphSections;
122 DenseMap<ELFSymbolIndex, Symbol *> GraphSymbols;
123 };
124
125 template <typename ELFT>
ELFLinkGraphBuilder(const ELFFile & Obj,Triple TT,StringRef FileName,LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)126 ELFLinkGraphBuilder<ELFT>::ELFLinkGraphBuilder(
127 const ELFFile &Obj, Triple TT, StringRef FileName,
128 LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
129 : ELFLinkGraphBuilderBase(std::make_unique<LinkGraph>(
130 FileName.str(), Triple(std::move(TT)), ELFT::Is64Bits ? 8 : 4,
131 support::endianness(ELFT::TargetEndianness),
132 std::move(GetEdgeKindName))),
133 Obj(Obj) {
134 LLVM_DEBUG(
135 { dbgs() << "Created ELFLinkGraphBuilder for \"" << FileName << "\""; });
136 }
137
138 template <typename ELFT>
buildGraph()139 Expected<std::unique_ptr<LinkGraph>> ELFLinkGraphBuilder<ELFT>::buildGraph() {
140 if (!isRelocatable())
141 return make_error<JITLinkError>("Object is not a relocatable ELF file");
142
143 if (auto Err = prepare())
144 return std::move(Err);
145
146 if (auto Err = graphifySections())
147 return std::move(Err);
148
149 if (auto Err = graphifySymbols())
150 return std::move(Err);
151
152 if (auto Err = addRelocations())
153 return std::move(Err);
154
155 return std::move(G);
156 }
157
158 template <typename ELFT>
159 Expected<std::pair<Linkage, Scope>>
getSymbolLinkageAndScope(const typename ELFT::Sym & Sym,StringRef Name)160 ELFLinkGraphBuilder<ELFT>::getSymbolLinkageAndScope(
161 const typename ELFT::Sym &Sym, StringRef Name) {
162 Linkage L = Linkage::Strong;
163 Scope S = Scope::Default;
164
165 switch (Sym.getBinding()) {
166 case ELF::STB_LOCAL:
167 S = Scope::Local;
168 break;
169 case ELF::STB_GLOBAL:
170 // Nothing to do here.
171 break;
172 case ELF::STB_WEAK:
173 L = Linkage::Weak;
174 break;
175 default:
176 return make_error<StringError>("Unrecognized symbol binding for " + Name,
177 inconvertibleErrorCode());
178 }
179
180 switch (Sym.getVisibility()) {
181 case ELF::STV_DEFAULT:
182 case ELF::STV_PROTECTED:
183 // FIXME: Make STV_DEFAULT symbols pre-emptible? This probably needs
184 // Orc support.
185 // Otherwise nothing to do here.
186 break;
187 case ELF::STV_HIDDEN:
188 // Default scope -> Hidden scope. No effect on local scope.
189 if (S == Scope::Default)
190 S = Scope::Hidden;
191 break;
192 case ELF::STV_INTERNAL:
193 return make_error<StringError>("Unrecognized symbol visibility for " + Name,
194 inconvertibleErrorCode());
195 }
196
197 return std::make_pair(L, S);
198 }
199
prepare()200 template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::prepare() {
201 LLVM_DEBUG(dbgs() << " Preparing to build...\n");
202
203 // Get the sections array.
204 if (auto SectionsOrErr = Obj.sections())
205 Sections = *SectionsOrErr;
206 else
207 return SectionsOrErr.takeError();
208
209 // Get the section string table.
210 if (auto SectionStringTabOrErr = Obj.getSectionStringTable(Sections))
211 SectionStringTab = *SectionStringTabOrErr;
212 else
213 return SectionStringTabOrErr.takeError();
214
215 // Get the SHT_SYMTAB section.
216 for (auto &Sec : Sections)
217 if (Sec.sh_type == ELF::SHT_SYMTAB) {
218 if (!SymTabSec)
219 SymTabSec = &Sec;
220 else
221 return make_error<JITLinkError>("Multiple SHT_SYMTAB sections in " +
222 G->getName());
223 }
224
225 return Error::success();
226 }
227
graphifySections()228 template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySections() {
229 LLVM_DEBUG(dbgs() << " Creating graph sections...\n");
230
231 // For each section...
232 for (ELFSectionIndex SecIndex = 0; SecIndex != Sections.size(); ++SecIndex) {
233
234 auto &Sec = Sections[SecIndex];
235
236 // Start by getting the section name.
237 auto Name = Obj.getSectionName(Sec, SectionStringTab);
238 if (!Name)
239 return Name.takeError();
240
241 // If the name indicates that it's a debug section then skip it: We don't
242 // support those yet.
243 if (isDwarfSection(*Name)) {
244 LLVM_DEBUG({
245 dbgs() << " " << SecIndex << ": \"" << *Name
246 << "\" is a debug section: "
247 "No graph section will be created.\n";
248 });
249 continue;
250 }
251
252 // Skip non-SHF_ALLOC sections
253 if (!(Sec.sh_flags & ELF::SHF_ALLOC)) {
254 LLVM_DEBUG({
255 dbgs() << " " << SecIndex << ": \"" << *Name
256 << "\" is not an SHF_ALLOC section: "
257 "No graph section will be created.\n";
258 });
259 continue;
260 }
261
262 LLVM_DEBUG({
263 dbgs() << " " << SecIndex << ": Creating section for \"" << *Name
264 << "\"\n";
265 });
266
267 // Get the section's memory protection flags.
268 sys::Memory::ProtectionFlags Prot;
269 if (Sec.sh_flags & ELF::SHF_EXECINSTR)
270 Prot = static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
271 sys::Memory::MF_EXEC);
272 else
273 Prot = static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
274 sys::Memory::MF_WRITE);
275
276 // For now we just use this to skip the "undefined" section, probably need
277 // to revist.
278 if (Sec.sh_size == 0)
279 continue;
280
281 auto &GraphSec = G->createSection(*Name, Prot);
282 if (Sec.sh_type != ELF::SHT_NOBITS) {
283 auto Data = Obj.template getSectionContentsAsArray<char>(Sec);
284 if (!Data)
285 return Data.takeError();
286
287 G->createContentBlock(GraphSec, *Data, Sec.sh_addr, Sec.sh_addralign, 0);
288 } else
289 G->createZeroFillBlock(GraphSec, Sec.sh_size, Sec.sh_addr,
290 Sec.sh_addralign, 0);
291
292 setGraphSection(SecIndex, GraphSec);
293 }
294
295 return Error::success();
296 }
297
graphifySymbols()298 template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySymbols() {
299 LLVM_DEBUG(dbgs() << " Creating graph symbols...\n");
300
301 // No SYMTAB -- Bail out early.
302 if (!SymTabSec)
303 return Error::success();
304
305 // Get the section content as a Symbols array.
306 auto Symbols = Obj.symbols(SymTabSec);
307 if (!Symbols)
308 return Symbols.takeError();
309
310 // Get the string table for this section.
311 auto StringTab = Obj.getStringTableForSymtab(*SymTabSec, Sections);
312 if (!StringTab)
313 return StringTab.takeError();
314
315 LLVM_DEBUG({
316 StringRef SymTabName;
317
318 if (auto SymTabNameOrErr = Obj.getSectionName(*SymTabSec, SectionStringTab))
319 SymTabName = *SymTabNameOrErr;
320 else {
321 dbgs() << "Could not get ELF SHT_SYMTAB section name for logging: "
322 << toString(SymTabNameOrErr.takeError()) << "\n";
323 SymTabName = "<SHT_SYMTAB section with invalid name>";
324 }
325
326 dbgs() << " Adding symbols from symtab section \"" << SymTabName
327 << "\"\n";
328 });
329
330 for (ELFSymbolIndex SymIndex = 0; SymIndex != Symbols->size(); ++SymIndex) {
331 auto &Sym = (*Symbols)[SymIndex];
332
333 // Check symbol type.
334 switch (Sym.getType()) {
335 case ELF::STT_FILE:
336 LLVM_DEBUG({
337 if (auto Name = Sym.getName(*StringTab))
338 dbgs() << " " << SymIndex << ": Skipping STT_FILE symbol \""
339 << *Name << "\"\n";
340 else {
341 dbgs() << "Could not get STT_FILE symbol name: "
342 << toString(Name.takeError()) << "\n";
343 dbgs() << " " << SymIndex
344 << ": Skipping STT_FILE symbol with invalid name\n";
345 }
346 });
347 continue;
348 break;
349 }
350
351 // Get the symbol name.
352 auto Name = Sym.getName(*StringTab);
353 if (!Name)
354 return Name.takeError();
355
356 // Handle common symbols specially.
357 if (Sym.isCommon()) {
358 Symbol &GSym =
359 G->addCommonSymbol(*Name, Scope::Default, getCommonSection(), 0,
360 Sym.st_size, Sym.getValue(), false);
361 setGraphSymbol(SymIndex, GSym);
362 continue;
363 }
364
365 // Map Visibility and Binding to Scope and Linkage:
366 Linkage L;
367 Scope S;
368
369 if (auto LSOrErr = getSymbolLinkageAndScope(Sym, *Name))
370 std::tie(L, S) = *LSOrErr;
371 else
372 return LSOrErr.takeError();
373
374 if (Sym.isDefined() &&
375 (Sym.getType() == ELF::STT_NOTYPE || Sym.getType() == ELF::STT_FUNC ||
376 Sym.getType() == ELF::STT_OBJECT ||
377 Sym.getType() == ELF::STT_SECTION)) {
378
379 // FIXME: Handle extended tables.
380 if (auto *GraphSec = getGraphSection(Sym.st_shndx)) {
381 Block *B = nullptr;
382 {
383 auto Blocks = GraphSec->blocks();
384 assert(Blocks.begin() != Blocks.end() && "No blocks for section");
385 assert(std::next(Blocks.begin()) == Blocks.end() &&
386 "Multiple blocks for section");
387 B = *Blocks.begin();
388 }
389
390 LLVM_DEBUG({
391 dbgs() << " " << SymIndex
392 << ": Creating defined graph symbol for ELF symbol \"" << *Name
393 << "\"\n";
394 });
395
396 if (Sym.getType() == ELF::STT_SECTION)
397 *Name = GraphSec->getName();
398
399 auto &GSym =
400 G->addDefinedSymbol(*B, Sym.getValue(), *Name, Sym.st_size, L, S,
401 Sym.getType() == ELF::STT_FUNC, false);
402 setGraphSymbol(SymIndex, GSym);
403 }
404 } else if (Sym.isUndefined() && Sym.isExternal()) {
405 LLVM_DEBUG({
406 dbgs() << " " << SymIndex
407 << ": Creating external graph symbol for ELF symbol \"" << *Name
408 << "\"\n";
409 });
410 auto &GSym = G->addExternalSymbol(*Name, Sym.st_size, L);
411 setGraphSymbol(SymIndex, GSym);
412 } else {
413 LLVM_DEBUG({
414 dbgs() << " " << SymIndex
415 << ": Not creating graph symbol for ELF symbol \"" << *Name
416 << "\" with unrecognized type\n";
417 });
418 }
419 }
420
421 return Error::success();
422 }
423
424 } // end namespace jitlink
425 } // end namespace llvm
426
427 #undef DEBUG_TYPE
428
429 #endif // LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H
430