[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / lib / ExecutionEngine / JITLink / ELFLinkGraphBuilder.h
blob20738b0c9c83d45772158ad6d49c8be016ebd400
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.
11 //===----------------------------------------------------------------------===//
13 #ifndef LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H
14 #define LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H
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"
22 #define DEBUG_TYPE "jitlink"
24 namespace llvm {
25 namespace jitlink {
27 /// Common link-graph building code shared between all ELFFiles.
28 class ELFLinkGraphBuilderBase {
29 public:
30 ELFLinkGraphBuilderBase(std::unique_ptr<LinkGraph> G) : G(std::move(G)) {}
31 virtual ~ELFLinkGraphBuilderBase();
33 protected:
34 static bool isDwarfSection(StringRef SectionName) {
35 return llvm::is_contained(DwarfSectionNames, SectionName);
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);
44 return *CommonSection;
47 std::unique_ptr<LinkGraph> G;
49 private:
50 static StringRef CommonSectionName;
51 static ArrayRef<const char *> DwarfSectionNames;
53 Section *CommonSection = nullptr;
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>;
62 public:
63 ELFLinkGraphBuilder(const object::ELFFile<ELFT> &Obj, Triple TT,
64 StringRef FileName,
65 LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);
67 /// Attempt to construct and return the LinkGraph.
68 Expected<std::unique_ptr<LinkGraph>> buildGraph();
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;
74 protected:
75 using ELFSectionIndex = unsigned;
76 using ELFSymbolIndex = unsigned;
78 bool isRelocatable() const {
79 return Obj.getHeader().e_type == llvm::ELF::ET_REL;
82 void setGraphSection(ELFSectionIndex SecIndex, Section &Sec) {
83 assert(!GraphSections.count(SecIndex) && "Duplicate section at index");
84 GraphSections[SecIndex] = &Sec;
87 Section *getGraphSection(ELFSectionIndex SecIndex) {
88 auto I = GraphSections.find(SecIndex);
89 if (I == GraphSections.end())
90 return nullptr;
91 return I->second;
94 void setGraphSymbol(ELFSymbolIndex SymIndex, Symbol &Sym) {
95 assert(!GraphSymbols.count(SymIndex) && "Duplicate symbol at index");
96 GraphSymbols[SymIndex] = &Sym;
99 Symbol *getGraphSymbol(ELFSymbolIndex SymIndex) {
100 auto I = GraphSymbols.find(SymIndex);
101 if (I == GraphSymbols.end())
102 return nullptr;
103 return I->second;
106 Expected<std::pair<Linkage, Scope>>
107 getSymbolLinkageAndScope(const typename ELFT::Sym &Sym, StringRef Name);
109 Error prepare();
110 Error graphifySections();
111 Error graphifySymbols();
113 const ELFFile &Obj;
115 typename ELFFile::Elf_Shdr_Range Sections;
116 const typename ELFFile::Elf_Shdr *SymTabSec = nullptr;
117 StringRef SectionStringTab;
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;
125 template <typename ELFT>
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 << "\""; });
138 template <typename ELFT>
139 Expected<std::unique_ptr<LinkGraph>> ELFLinkGraphBuilder<ELFT>::buildGraph() {
140 if (!isRelocatable())
141 return make_error<JITLinkError>("Object is not a relocatable ELF file");
143 if (auto Err = prepare())
144 return std::move(Err);
146 if (auto Err = graphifySections())
147 return std::move(Err);
149 if (auto Err = graphifySymbols())
150 return std::move(Err);
152 if (auto Err = addRelocations())
153 return std::move(Err);
155 return std::move(G);
158 template <typename ELFT>
159 Expected<std::pair<Linkage, Scope>>
160 ELFLinkGraphBuilder<ELFT>::getSymbolLinkageAndScope(
161 const typename ELFT::Sym &Sym, StringRef Name) {
162 Linkage L = Linkage::Strong;
163 Scope S = Scope::Default;
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>(
177 "Unrecognized symbol binding " +
178 Twine(static_cast<int>(Sym.getBinding())) + " for " + Name,
179 inconvertibleErrorCode());
182 switch (Sym.getVisibility()) {
183 case ELF::STV_DEFAULT:
184 case ELF::STV_PROTECTED:
185 // FIXME: Make STV_DEFAULT symbols pre-emptible? This probably needs
186 // Orc support.
187 // Otherwise nothing to do here.
188 break;
189 case ELF::STV_HIDDEN:
190 // Default scope -> Hidden scope. No effect on local scope.
191 if (S == Scope::Default)
192 S = Scope::Hidden;
193 break;
194 case ELF::STV_INTERNAL:
195 return make_error<StringError>(
196 "Unrecognized symbol visibility " +
197 Twine(static_cast<int>(Sym.getVisibility())) + " for " + Name,
198 inconvertibleErrorCode());
201 return std::make_pair(L, S);
204 template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::prepare() {
205 LLVM_DEBUG(dbgs() << " Preparing to build...\n");
207 // Get the sections array.
208 if (auto SectionsOrErr = Obj.sections())
209 Sections = *SectionsOrErr;
210 else
211 return SectionsOrErr.takeError();
213 // Get the section string table.
214 if (auto SectionStringTabOrErr = Obj.getSectionStringTable(Sections))
215 SectionStringTab = *SectionStringTabOrErr;
216 else
217 return SectionStringTabOrErr.takeError();
219 // Get the SHT_SYMTAB section.
220 for (auto &Sec : Sections)
221 if (Sec.sh_type == ELF::SHT_SYMTAB) {
222 if (!SymTabSec)
223 SymTabSec = &Sec;
224 else
225 return make_error<JITLinkError>("Multiple SHT_SYMTAB sections in " +
226 G->getName());
229 return Error::success();
232 template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySections() {
233 LLVM_DEBUG(dbgs() << " Creating graph sections...\n");
235 // For each section...
236 for (ELFSectionIndex SecIndex = 0; SecIndex != Sections.size(); ++SecIndex) {
238 auto &Sec = Sections[SecIndex];
240 // Start by getting the section name.
241 auto Name = Obj.getSectionName(Sec, SectionStringTab);
242 if (!Name)
243 return Name.takeError();
245 // If the name indicates that it's a debug section then skip it: We don't
246 // support those yet.
247 if (isDwarfSection(*Name)) {
248 LLVM_DEBUG({
249 dbgs() << " " << SecIndex << ": \"" << *Name
250 << "\" is a debug section: "
251 "No graph section will be created.\n";
253 continue;
256 // Skip non-SHF_ALLOC sections
257 if (!(Sec.sh_flags & ELF::SHF_ALLOC)) {
258 LLVM_DEBUG({
259 dbgs() << " " << SecIndex << ": \"" << *Name
260 << "\" is not an SHF_ALLOC section: "
261 "No graph section will be created.\n";
263 continue;
266 LLVM_DEBUG({
267 dbgs() << " " << SecIndex << ": Creating section for \"" << *Name
268 << "\"\n";
271 // Get the section's memory protection flags.
272 sys::Memory::ProtectionFlags Prot;
273 if (Sec.sh_flags & ELF::SHF_EXECINSTR)
274 Prot = static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
275 sys::Memory::MF_EXEC);
276 else
277 Prot = static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
278 sys::Memory::MF_WRITE);
280 // For now we just use this to skip the "undefined" section, probably need
281 // to revist.
282 if (Sec.sh_size == 0)
283 continue;
285 auto &GraphSec = G->createSection(*Name, Prot);
286 if (Sec.sh_type != ELF::SHT_NOBITS) {
287 auto Data = Obj.template getSectionContentsAsArray<char>(Sec);
288 if (!Data)
289 return Data.takeError();
291 G->createContentBlock(GraphSec, *Data, Sec.sh_addr, Sec.sh_addralign, 0);
292 } else
293 G->createZeroFillBlock(GraphSec, Sec.sh_size, Sec.sh_addr,
294 Sec.sh_addralign, 0);
296 setGraphSection(SecIndex, GraphSec);
299 return Error::success();
302 template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySymbols() {
303 LLVM_DEBUG(dbgs() << " Creating graph symbols...\n");
305 // No SYMTAB -- Bail out early.
306 if (!SymTabSec)
307 return Error::success();
309 // Get the section content as a Symbols array.
310 auto Symbols = Obj.symbols(SymTabSec);
311 if (!Symbols)
312 return Symbols.takeError();
314 // Get the string table for this section.
315 auto StringTab = Obj.getStringTableForSymtab(*SymTabSec, Sections);
316 if (!StringTab)
317 return StringTab.takeError();
319 LLVM_DEBUG({
320 StringRef SymTabName;
322 if (auto SymTabNameOrErr = Obj.getSectionName(*SymTabSec, SectionStringTab))
323 SymTabName = *SymTabNameOrErr;
324 else {
325 dbgs() << "Could not get ELF SHT_SYMTAB section name for logging: "
326 << toString(SymTabNameOrErr.takeError()) << "\n";
327 SymTabName = "<SHT_SYMTAB section with invalid name>";
330 dbgs() << " Adding symbols from symtab section \"" << SymTabName
331 << "\"\n";
334 for (ELFSymbolIndex SymIndex = 0; SymIndex != Symbols->size(); ++SymIndex) {
335 auto &Sym = (*Symbols)[SymIndex];
337 // Check symbol type.
338 switch (Sym.getType()) {
339 case ELF::STT_FILE:
340 LLVM_DEBUG({
341 if (auto Name = Sym.getName(*StringTab))
342 dbgs() << " " << SymIndex << ": Skipping STT_FILE symbol \""
343 << *Name << "\"\n";
344 else {
345 dbgs() << "Could not get STT_FILE symbol name: "
346 << toString(Name.takeError()) << "\n";
347 dbgs() << " " << SymIndex
348 << ": Skipping STT_FILE symbol with invalid name\n";
351 continue;
352 break;
355 // Get the symbol name.
356 auto Name = Sym.getName(*StringTab);
357 if (!Name)
358 return Name.takeError();
360 // Handle common symbols specially.
361 if (Sym.isCommon()) {
362 Symbol &GSym =
363 G->addCommonSymbol(*Name, Scope::Default, getCommonSection(), 0,
364 Sym.st_size, Sym.getValue(), false);
365 setGraphSymbol(SymIndex, GSym);
366 continue;
369 // Map Visibility and Binding to Scope and Linkage:
370 Linkage L;
371 Scope S;
373 if (auto LSOrErr = getSymbolLinkageAndScope(Sym, *Name))
374 std::tie(L, S) = *LSOrErr;
375 else
376 return LSOrErr.takeError();
378 if (Sym.isDefined() &&
379 (Sym.getType() == ELF::STT_NOTYPE || Sym.getType() == ELF::STT_FUNC ||
380 Sym.getType() == ELF::STT_OBJECT ||
381 Sym.getType() == ELF::STT_SECTION)) {
383 // FIXME: Handle extended tables.
384 if (auto *GraphSec = getGraphSection(Sym.st_shndx)) {
385 Block *B = nullptr;
387 auto Blocks = GraphSec->blocks();
388 assert(Blocks.begin() != Blocks.end() && "No blocks for section");
389 assert(std::next(Blocks.begin()) == Blocks.end() &&
390 "Multiple blocks for section");
391 B = *Blocks.begin();
394 LLVM_DEBUG({
395 dbgs() << " " << SymIndex
396 << ": Creating defined graph symbol for ELF symbol \"" << *Name
397 << "\"\n";
400 if (Sym.getType() == ELF::STT_SECTION)
401 *Name = GraphSec->getName();
403 auto &GSym =
404 G->addDefinedSymbol(*B, Sym.getValue(), *Name, Sym.st_size, L, S,
405 Sym.getType() == ELF::STT_FUNC, false);
406 setGraphSymbol(SymIndex, GSym);
408 } else if (Sym.isUndefined() && Sym.isExternal()) {
409 LLVM_DEBUG({
410 dbgs() << " " << SymIndex
411 << ": Creating external graph symbol for ELF symbol \"" << *Name
412 << "\"\n";
414 auto &GSym = G->addExternalSymbol(*Name, Sym.st_size, L);
415 setGraphSymbol(SymIndex, GSym);
416 } else {
417 LLVM_DEBUG({
418 dbgs() << " " << SymIndex
419 << ": Not creating graph symbol for ELF symbol \"" << *Name
420 << "\" with unrecognized type\n";
425 return Error::success();
428 } // end namespace jitlink
429 } // end namespace llvm
431 #undef DEBUG_TYPE
433 #endif // LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H