1 //===------- ELFLinkGraphBuilder.h - ELF LinkGraph builder ------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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"
27 /// Common link-graph building code shared between all ELFFiles.
28 class ELFLinkGraphBuilderBase
{
30 ELFLinkGraphBuilderBase(std::unique_ptr
<LinkGraph
> G
) : G(std::move(G
)) {}
31 virtual ~ELFLinkGraphBuilderBase();
34 static bool isDwarfSection(StringRef SectionName
) {
35 return llvm::is_contained(DwarfSectionNames
, SectionName
);
38 Section
&getCommonSection() {
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
;
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
>;
63 ELFLinkGraphBuilder(const object::ELFFile
<ELFT
> &Obj
, Triple TT
,
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;
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())
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())
106 Expected
<std::pair
<Linkage
, Scope
>>
107 getSymbolLinkageAndScope(const typename
ELFT::Sym
&Sym
, StringRef Name
);
110 Error
graphifySections();
111 Error
graphifySymbols();
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
))),
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
);
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()) {
169 case ELF::STB_GLOBAL
:
170 // Nothing to do here.
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
187 // Otherwise nothing to do here.
189 case ELF::STV_HIDDEN
:
190 // Default scope -> Hidden scope. No effect on local scope.
191 if (S
== Scope::Default
)
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
;
211 return SectionsOrErr
.takeError();
213 // Get the section string table.
214 if (auto SectionStringTabOrErr
= Obj
.getSectionStringTable(Sections
))
215 SectionStringTab
= *SectionStringTabOrErr
;
217 return SectionStringTabOrErr
.takeError();
219 // Get the SHT_SYMTAB section.
220 for (auto &Sec
: Sections
)
221 if (Sec
.sh_type
== ELF::SHT_SYMTAB
) {
225 return make_error
<JITLinkError
>("Multiple SHT_SYMTAB sections in " +
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
);
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
)) {
249 dbgs() << " " << SecIndex
<< ": \"" << *Name
250 << "\" is a debug section: "
251 "No graph section will be created.\n";
256 // Skip non-SHF_ALLOC sections
257 if (!(Sec
.sh_flags
& ELF::SHF_ALLOC
)) {
259 dbgs() << " " << SecIndex
<< ": \"" << *Name
260 << "\" is not an SHF_ALLOC section: "
261 "No graph section will be created.\n";
267 dbgs() << " " << SecIndex
<< ": Creating section for \"" << *Name
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
);
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
282 if (Sec
.sh_size
== 0)
285 auto &GraphSec
= G
->createSection(*Name
, Prot
);
286 if (Sec
.sh_type
!= ELF::SHT_NOBITS
) {
287 auto Data
= Obj
.template getSectionContentsAsArray
<char>(Sec
);
289 return Data
.takeError();
291 G
->createContentBlock(GraphSec
, *Data
, Sec
.sh_addr
, Sec
.sh_addralign
, 0);
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.
307 return Error::success();
309 // Get the section content as a Symbols array.
310 auto Symbols
= Obj
.symbols(SymTabSec
);
312 return Symbols
.takeError();
314 // Get the string table for this section.
315 auto StringTab
= Obj
.getStringTableForSymtab(*SymTabSec
, Sections
);
317 return StringTab
.takeError();
320 StringRef SymTabName
;
322 if (auto SymTabNameOrErr
= Obj
.getSectionName(*SymTabSec
, SectionStringTab
))
323 SymTabName
= *SymTabNameOrErr
;
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
334 for (ELFSymbolIndex SymIndex
= 0; SymIndex
!= Symbols
->size(); ++SymIndex
) {
335 auto &Sym
= (*Symbols
)[SymIndex
];
337 // Check symbol type.
338 switch (Sym
.getType()) {
341 if (auto Name
= Sym
.getName(*StringTab
))
342 dbgs() << " " << SymIndex
<< ": Skipping STT_FILE symbol \""
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";
355 // Get the symbol name.
356 auto Name
= Sym
.getName(*StringTab
);
358 return Name
.takeError();
360 // Handle common symbols specially.
361 if (Sym
.isCommon()) {
363 G
->addCommonSymbol(*Name
, Scope::Default
, getCommonSection(), 0,
364 Sym
.st_size
, Sym
.getValue(), false);
365 setGraphSymbol(SymIndex
, GSym
);
369 // Map Visibility and Binding to Scope and Linkage:
373 if (auto LSOrErr
= getSymbolLinkageAndScope(Sym
, *Name
))
374 std::tie(L
, S
) = *LSOrErr
;
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
)) {
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");
395 dbgs() << " " << SymIndex
396 << ": Creating defined graph symbol for ELF symbol \"" << *Name
400 if (Sym
.getType() == ELF::STT_SECTION
)
401 *Name
= GraphSec
->getName();
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()) {
410 dbgs() << " " << SymIndex
411 << ": Creating external graph symbol for ELF symbol \"" << *Name
414 auto &GSym
= G
->addExternalSymbol(*Name
, Sym
.st_size
, L
);
415 setGraphSymbol(SymIndex
, GSym
);
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
433 #endif // LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H