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: |
30 | ELFLinkGraphBuilderBase(std::unique_ptr<LinkGraph> G) : G(std::move(G)) {} |
31 | virtual ~ELFLinkGraphBuilderBase(); |
32 | |
33 | protected: |
34 | static bool isDwarfSection(StringRef SectionName) { |
35 | return llvm::is_contained(Range&: DwarfSectionNames, Element: SectionName); |
36 | } |
37 | |
38 | Section &getCommonSection() { |
39 | if (!CommonSection) |
40 | CommonSection = &G->createSection( |
41 | Name: CommonSectionName, Prot: orc::MemProt::Read | orc::MemProt::Write); |
42 | return *CommonSection; |
43 | } |
44 | |
45 | std::unique_ptr<LinkGraph> G; |
46 | |
47 | private: |
48 | static StringRef CommonSectionName; |
49 | static ArrayRef<const char *> DwarfSectionNames; |
50 | |
51 | Section *CommonSection = nullptr; |
52 | }; |
53 | |
54 | /// LinkGraph building code that's specific to the given ELFT, but common |
55 | /// across all architectures. |
56 | template <typename ELFT> |
57 | class ELFLinkGraphBuilder : public ELFLinkGraphBuilderBase { |
58 | using ELFFile = object::ELFFile<ELFT>; |
59 | |
60 | public: |
61 | ELFLinkGraphBuilder(const object::ELFFile<ELFT> &Obj, Triple TT, |
62 | SubtargetFeatures Features, StringRef FileName, |
63 | LinkGraph::GetEdgeKindNameFunction GetEdgeKindName); |
64 | |
65 | /// Debug sections are included in the graph by default. Use |
66 | /// setProcessDebugSections(false) to ignore them if debug info is not |
67 | /// needed. |
68 | ELFLinkGraphBuilder &setProcessDebugSections(bool ProcessDebugSections) { |
69 | this->ProcessDebugSections = ProcessDebugSections; |
70 | return *this; |
71 | } |
72 | |
73 | /// Attempt to construct and return the LinkGraph. |
74 | Expected<std::unique_ptr<LinkGraph>> buildGraph(); |
75 | |
76 | /// Call to derived class to handle relocations. These require |
77 | /// architecture specific knowledge to map to JITLink edge kinds. |
78 | virtual Error addRelocations() = 0; |
79 | |
80 | protected: |
81 | using ELFSectionIndex = unsigned; |
82 | using ELFSymbolIndex = unsigned; |
83 | |
84 | bool isRelocatable() const { |
85 | return Obj.getHeader().e_type == llvm::ELF::ET_REL; |
86 | } |
87 | |
88 | void setGraphBlock(ELFSectionIndex SecIndex, Block *B) { |
89 | assert(!GraphBlocks.count(SecIndex) && "Duplicate section at index" ); |
90 | GraphBlocks[SecIndex] = B; |
91 | } |
92 | |
93 | Block *getGraphBlock(ELFSectionIndex SecIndex) { |
94 | return GraphBlocks.lookup(Val: SecIndex); |
95 | } |
96 | |
97 | void setGraphSymbol(ELFSymbolIndex SymIndex, Symbol &Sym) { |
98 | assert(!GraphSymbols.count(SymIndex) && "Duplicate symbol at index" ); |
99 | GraphSymbols[SymIndex] = &Sym; |
100 | } |
101 | |
102 | Symbol *getGraphSymbol(ELFSymbolIndex SymIndex) { |
103 | return GraphSymbols.lookup(Val: SymIndex); |
104 | } |
105 | |
106 | Expected<std::pair<Linkage, Scope>> |
107 | getSymbolLinkageAndScope(const typename ELFT::Sym &Sym, StringRef Name); |
108 | |
109 | /// Set the target flags on the given Symbol. |
110 | virtual TargetFlagsType makeTargetFlags(const typename ELFT::Sym &Sym) { |
111 | return TargetFlagsType{}; |
112 | } |
113 | |
114 | /// Get the physical offset of the symbol on the target platform. |
115 | virtual orc::ExecutorAddrDiff getRawOffset(const typename ELFT::Sym &Sym, |
116 | TargetFlagsType Flags) { |
117 | return Sym.getValue(); |
118 | } |
119 | |
120 | Error prepare(); |
121 | Error graphifySections(); |
122 | Error graphifySymbols(); |
123 | |
124 | /// Override in derived classes to suppress certain sections in the link |
125 | /// graph. |
126 | virtual bool excludeSection(const typename ELFT::Shdr &Sect) const { |
127 | return false; |
128 | } |
129 | |
130 | /// Traverse all matching ELFT::Rela relocation records in the given section. |
131 | /// The handler function Func should be callable with this signature: |
132 | /// Error(const typename ELFT::Rela &, |
133 | /// const typename ELFT::Shdr &, Section &) |
134 | /// |
135 | template <typename RelocHandlerMethod> |
136 | Error forEachRelaRelocation(const typename ELFT::Shdr &RelSect, |
137 | RelocHandlerMethod &&Func); |
138 | |
139 | /// Traverse all matching ELFT::Rel relocation records in the given section. |
140 | /// The handler function Func should be callable with this signature: |
141 | /// Error(const typename ELFT::Rel &, |
142 | /// const typename ELFT::Shdr &, Section &) |
143 | /// |
144 | template <typename RelocHandlerMethod> |
145 | Error forEachRelRelocation(const typename ELFT::Shdr &RelSect, |
146 | RelocHandlerMethod &&Func); |
147 | |
148 | /// Traverse all matching rela relocation records in the given section. |
149 | /// Convenience wrapper to allow passing a member function for the handler. |
150 | /// |
151 | template <typename ClassT, typename RelocHandlerMethod> |
152 | Error forEachRelaRelocation(const typename ELFT::Shdr &RelSect, |
153 | ClassT *Instance, RelocHandlerMethod &&Method) { |
154 | return forEachRelaRelocation( |
155 | RelSect, |
156 | [Instance, Method](const auto &Rel, const auto &Target, auto &GS) { |
157 | return (Instance->*Method)(Rel, Target, GS); |
158 | }); |
159 | } |
160 | |
161 | /// Traverse all matching rel relocation records in the given section. |
162 | /// Convenience wrapper to allow passing a member function for the handler. |
163 | /// |
164 | template <typename ClassT, typename RelocHandlerMethod> |
165 | Error forEachRelRelocation(const typename ELFT::Shdr &RelSect, |
166 | ClassT *Instance, RelocHandlerMethod &&Method) { |
167 | return forEachRelRelocation( |
168 | RelSect, |
169 | [Instance, Method](const auto &Rel, const auto &Target, auto &GS) { |
170 | return (Instance->*Method)(Rel, Target, GS); |
171 | }); |
172 | } |
173 | |
174 | const ELFFile &Obj; |
175 | |
176 | typename ELFFile::Elf_Shdr_Range Sections; |
177 | const typename ELFFile::Elf_Shdr *SymTabSec = nullptr; |
178 | StringRef SectionStringTab; |
179 | bool ProcessDebugSections = true; |
180 | |
181 | // Maps ELF section indexes to LinkGraph Blocks. |
182 | // Only SHF_ALLOC sections will have graph blocks. |
183 | DenseMap<ELFSectionIndex, Block *> GraphBlocks; |
184 | DenseMap<ELFSymbolIndex, Symbol *> GraphSymbols; |
185 | DenseMap<const typename ELFFile::Elf_Shdr *, |
186 | ArrayRef<typename ELFFile::Elf_Word>> |
187 | ShndxTables; |
188 | }; |
189 | |
190 | template <typename ELFT> |
191 | ELFLinkGraphBuilder<ELFT>::ELFLinkGraphBuilder( |
192 | const ELFFile &Obj, Triple TT, SubtargetFeatures Features, |
193 | StringRef FileName, LinkGraph::GetEdgeKindNameFunction GetEdgeKindName) |
194 | : ELFLinkGraphBuilderBase(std::make_unique<LinkGraph>( |
195 | FileName.str(), Triple(std::move(TT)), std::move(Features), |
196 | ELFT::Is64Bits ? 8 : 4, llvm::endianness(ELFT::Endianness), |
197 | std::move(GetEdgeKindName))), |
198 | Obj(Obj) { |
199 | LLVM_DEBUG( |
200 | { dbgs() << "Created ELFLinkGraphBuilder for \"" << FileName << "\"" ; }); |
201 | } |
202 | |
203 | template <typename ELFT> |
204 | Expected<std::unique_ptr<LinkGraph>> ELFLinkGraphBuilder<ELFT>::buildGraph() { |
205 | if (!isRelocatable()) |
206 | return make_error<JITLinkError>(Args: "Object is not a relocatable ELF file" ); |
207 | |
208 | if (auto Err = prepare()) |
209 | return std::move(Err); |
210 | |
211 | if (auto Err = graphifySections()) |
212 | return std::move(Err); |
213 | |
214 | if (auto Err = graphifySymbols()) |
215 | return std::move(Err); |
216 | |
217 | if (auto Err = addRelocations()) |
218 | return std::move(Err); |
219 | |
220 | return std::move(G); |
221 | } |
222 | |
223 | template <typename ELFT> |
224 | Expected<std::pair<Linkage, Scope>> |
225 | ELFLinkGraphBuilder<ELFT>::getSymbolLinkageAndScope( |
226 | const typename ELFT::Sym &Sym, StringRef Name) { |
227 | Linkage L = Linkage::Strong; |
228 | Scope S = Scope::Default; |
229 | |
230 | switch (Sym.getBinding()) { |
231 | case ELF::STB_LOCAL: |
232 | S = Scope::Local; |
233 | break; |
234 | case ELF::STB_GLOBAL: |
235 | // Nothing to do here. |
236 | break; |
237 | case ELF::STB_WEAK: |
238 | case ELF::STB_GNU_UNIQUE: |
239 | L = Linkage::Weak; |
240 | break; |
241 | default: |
242 | return make_error<StringError>( |
243 | Args: "Unrecognized symbol binding " + |
244 | Twine(static_cast<int>(Sym.getBinding())) + " for " + Name, |
245 | Args: inconvertibleErrorCode()); |
246 | } |
247 | |
248 | switch (Sym.getVisibility()) { |
249 | case ELF::STV_DEFAULT: |
250 | case ELF::STV_PROTECTED: |
251 | // FIXME: Make STV_DEFAULT symbols pre-emptible? This probably needs |
252 | // Orc support. |
253 | // Otherwise nothing to do here. |
254 | break; |
255 | case ELF::STV_HIDDEN: |
256 | // Default scope -> Hidden scope. No effect on local scope. |
257 | if (S == Scope::Default) |
258 | S = Scope::Hidden; |
259 | break; |
260 | case ELF::STV_INTERNAL: |
261 | return make_error<StringError>( |
262 | Args: "Unrecognized symbol visibility " + |
263 | Twine(static_cast<int>(Sym.getVisibility())) + " for " + Name, |
264 | Args: inconvertibleErrorCode()); |
265 | } |
266 | |
267 | return std::make_pair(x&: L, y&: S); |
268 | } |
269 | |
270 | template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::prepare() { |
271 | LLVM_DEBUG(dbgs() << " Preparing to build...\n" ); |
272 | |
273 | // Get the sections array. |
274 | if (auto SectionsOrErr = Obj.sections()) |
275 | Sections = *SectionsOrErr; |
276 | else |
277 | return SectionsOrErr.takeError(); |
278 | |
279 | // Get the section string table. |
280 | if (auto SectionStringTabOrErr = Obj.getSectionStringTable(Sections)) |
281 | SectionStringTab = *SectionStringTabOrErr; |
282 | else |
283 | return SectionStringTabOrErr.takeError(); |
284 | |
285 | // Get the SHT_SYMTAB section. |
286 | for (auto &Sec : Sections) { |
287 | if (Sec.sh_type == ELF::SHT_SYMTAB) { |
288 | if (!SymTabSec) |
289 | SymTabSec = &Sec; |
290 | else |
291 | return make_error<JITLinkError>(Args: "Multiple SHT_SYMTAB sections in " + |
292 | G->getName()); |
293 | } |
294 | |
295 | // Extended table. |
296 | if (Sec.sh_type == ELF::SHT_SYMTAB_SHNDX) { |
297 | uint32_t SymtabNdx = Sec.sh_link; |
298 | if (SymtabNdx >= Sections.size()) |
299 | return make_error<JITLinkError>(Args: "sh_link is out of bound" ); |
300 | |
301 | auto ShndxTable = Obj.getSHNDXTable(Sec); |
302 | if (!ShndxTable) |
303 | return ShndxTable.takeError(); |
304 | |
305 | ShndxTables.insert({&Sections[SymtabNdx], *ShndxTable}); |
306 | } |
307 | } |
308 | |
309 | return Error::success(); |
310 | } |
311 | |
312 | template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySections() { |
313 | LLVM_DEBUG(dbgs() << " Creating graph sections...\n" ); |
314 | |
315 | // For each section... |
316 | for (ELFSectionIndex SecIndex = 0; SecIndex != Sections.size(); ++SecIndex) { |
317 | |
318 | auto &Sec = Sections[SecIndex]; |
319 | |
320 | // Start by getting the section name. |
321 | auto Name = Obj.getSectionName(Sec, SectionStringTab); |
322 | if (!Name) |
323 | return Name.takeError(); |
324 | if (excludeSection(Sect: Sec)) { |
325 | LLVM_DEBUG({ |
326 | dbgs() << " " << SecIndex << ": Skipping section \"" << *Name |
327 | << "\" explicitly\n" ; |
328 | }); |
329 | continue; |
330 | } |
331 | |
332 | // Skip null sections. |
333 | if (Sec.sh_type == ELF::SHT_NULL) { |
334 | LLVM_DEBUG({ |
335 | dbgs() << " " << SecIndex << ": has type SHT_NULL. Skipping.\n" ; |
336 | }); |
337 | continue; |
338 | } |
339 | |
340 | // If the name indicates that it's a debug section then skip it: We don't |
341 | // support those yet. |
342 | if (!ProcessDebugSections && isDwarfSection(SectionName: *Name)) { |
343 | LLVM_DEBUG({ |
344 | dbgs() << " " << SecIndex << ": \"" << *Name |
345 | << "\" is a debug section: " |
346 | "No graph section will be created.\n" ; |
347 | }); |
348 | continue; |
349 | } |
350 | |
351 | LLVM_DEBUG({ |
352 | dbgs() << " " << SecIndex << ": Creating section for \"" << *Name |
353 | << "\"\n" ; |
354 | }); |
355 | |
356 | // Get the section's memory protection flags. |
357 | orc::MemProt Prot = orc::MemProt::Read; |
358 | if (Sec.sh_flags & ELF::SHF_EXECINSTR) |
359 | Prot |= orc::MemProt::Exec; |
360 | if (Sec.sh_flags & ELF::SHF_WRITE) |
361 | Prot |= orc::MemProt::Write; |
362 | |
363 | // Look for existing sections first. |
364 | auto *GraphSec = G->findSectionByName(Name: *Name); |
365 | if (!GraphSec) { |
366 | GraphSec = &G->createSection(Name: *Name, Prot); |
367 | // Non-SHF_ALLOC sections get NoAlloc memory lifetimes. |
368 | if (!(Sec.sh_flags & ELF::SHF_ALLOC)) { |
369 | GraphSec->setMemLifetime(orc::MemLifetime::NoAlloc); |
370 | LLVM_DEBUG({ |
371 | dbgs() << " " << SecIndex << ": \"" << *Name |
372 | << "\" is not a SHF_ALLOC section. Using NoAlloc lifetime.\n" ; |
373 | }); |
374 | } |
375 | } |
376 | |
377 | if (GraphSec->getMemProt() != Prot) { |
378 | std::string ErrMsg; |
379 | raw_string_ostream(ErrMsg) |
380 | << "In " << G->getName() << ", section " << *Name |
381 | << " is present more than once with different permissions: " |
382 | << GraphSec->getMemProt() << " vs " << Prot; |
383 | return make_error<JITLinkError>(Args: std::move(ErrMsg)); |
384 | } |
385 | |
386 | Block *B = nullptr; |
387 | if (Sec.sh_type != ELF::SHT_NOBITS) { |
388 | auto Data = Obj.template getSectionContentsAsArray<char>(Sec); |
389 | if (!Data) |
390 | return Data.takeError(); |
391 | |
392 | B = &G->createContentBlock(Parent&: *GraphSec, Content: *Data, |
393 | Address: orc::ExecutorAddr(Sec.sh_addr), |
394 | Alignment: Sec.sh_addralign, AlignmentOffset: 0); |
395 | } else |
396 | B = &G->createZeroFillBlock(Parent&: *GraphSec, Size: Sec.sh_size, |
397 | Address: orc::ExecutorAddr(Sec.sh_addr), |
398 | Alignment: Sec.sh_addralign, AlignmentOffset: 0); |
399 | |
400 | if (Sec.sh_type == ELF::SHT_ARM_EXIDX) { |
401 | // Add live symbol to avoid dead-stripping for .ARM.exidx sections |
402 | G->addAnonymousSymbol(Content&: *B, Offset: orc::ExecutorAddrDiff(), |
403 | Size: orc::ExecutorAddrDiff(), IsCallable: false, IsLive: true); |
404 | } |
405 | |
406 | setGraphBlock(SecIndex, B); |
407 | } |
408 | |
409 | return Error::success(); |
410 | } |
411 | |
412 | template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySymbols() { |
413 | LLVM_DEBUG(dbgs() << " Creating graph symbols...\n" ); |
414 | |
415 | // No SYMTAB -- Bail out early. |
416 | if (!SymTabSec) |
417 | return Error::success(); |
418 | |
419 | // Get the section content as a Symbols array. |
420 | auto Symbols = Obj.symbols(SymTabSec); |
421 | if (!Symbols) |
422 | return Symbols.takeError(); |
423 | |
424 | // Get the string table for this section. |
425 | auto StringTab = Obj.getStringTableForSymtab(*SymTabSec, Sections); |
426 | if (!StringTab) |
427 | return StringTab.takeError(); |
428 | |
429 | LLVM_DEBUG({ |
430 | StringRef SymTabName; |
431 | |
432 | if (auto SymTabNameOrErr = Obj.getSectionName(*SymTabSec, SectionStringTab)) |
433 | SymTabName = *SymTabNameOrErr; |
434 | else { |
435 | dbgs() << "Could not get ELF SHT_SYMTAB section name for logging: " |
436 | << toString(SymTabNameOrErr.takeError()) << "\n" ; |
437 | SymTabName = "<SHT_SYMTAB section with invalid name>" ; |
438 | } |
439 | |
440 | dbgs() << " Adding symbols from symtab section \"" << SymTabName |
441 | << "\"\n" ; |
442 | }); |
443 | |
444 | for (ELFSymbolIndex SymIndex = 0; SymIndex != Symbols->size(); ++SymIndex) { |
445 | auto &Sym = (*Symbols)[SymIndex]; |
446 | |
447 | // Check symbol type. |
448 | switch (Sym.getType()) { |
449 | case ELF::STT_FILE: |
450 | LLVM_DEBUG({ |
451 | if (auto Name = Sym.getName(*StringTab)) |
452 | dbgs() << " " << SymIndex << ": Skipping STT_FILE symbol \"" |
453 | << *Name << "\"\n" ; |
454 | else { |
455 | dbgs() << "Could not get STT_FILE symbol name: " |
456 | << toString(Name.takeError()) << "\n" ; |
457 | dbgs() << " " << SymIndex |
458 | << ": Skipping STT_FILE symbol with invalid name\n" ; |
459 | } |
460 | }); |
461 | continue; |
462 | break; |
463 | } |
464 | |
465 | // Get the symbol name. |
466 | auto Name = Sym.getName(*StringTab); |
467 | if (!Name) |
468 | return Name.takeError(); |
469 | |
470 | // Handle common symbols specially. |
471 | if (Sym.isCommon()) { |
472 | Symbol &GSym = G->addDefinedSymbol( |
473 | Content&: G->createZeroFillBlock(Parent&: getCommonSection(), Size: Sym.st_size, |
474 | Address: orc::ExecutorAddr(), Alignment: Sym.getValue(), AlignmentOffset: 0), |
475 | Offset: 0, Name: *Name, Size: Sym.st_size, L: Linkage::Strong, S: Scope::Default, IsCallable: false, IsLive: false); |
476 | setGraphSymbol(SymIndex, Sym&: GSym); |
477 | continue; |
478 | } |
479 | |
480 | if (Sym.isDefined() && |
481 | (Sym.getType() == ELF::STT_NOTYPE || Sym.getType() == ELF::STT_FUNC || |
482 | Sym.getType() == ELF::STT_OBJECT || |
483 | Sym.getType() == ELF::STT_SECTION || Sym.getType() == ELF::STT_TLS)) { |
484 | |
485 | // Map Visibility and Binding to Scope and Linkage: |
486 | Linkage L; |
487 | Scope S; |
488 | if (auto LSOrErr = getSymbolLinkageAndScope(Sym, Name: *Name)) |
489 | std::tie(args&: L, args&: S) = *LSOrErr; |
490 | else |
491 | return LSOrErr.takeError(); |
492 | |
493 | // Handle extended tables. |
494 | unsigned Shndx = Sym.st_shndx; |
495 | if (Shndx == ELF::SHN_XINDEX) { |
496 | auto ShndxTable = ShndxTables.find(SymTabSec); |
497 | if (ShndxTable == ShndxTables.end()) |
498 | continue; |
499 | auto NdxOrErr = object::getExtendedSymbolTableIndex<ELFT>( |
500 | Sym, SymIndex, ShndxTable->second); |
501 | if (!NdxOrErr) |
502 | return NdxOrErr.takeError(); |
503 | Shndx = *NdxOrErr; |
504 | } |
505 | if (auto *B = getGraphBlock(SecIndex: Shndx)) { |
506 | LLVM_DEBUG({ |
507 | dbgs() << " " << SymIndex |
508 | << ": Creating defined graph symbol for ELF symbol \"" << *Name |
509 | << "\"\n" ; |
510 | }); |
511 | |
512 | TargetFlagsType Flags = makeTargetFlags(Sym); |
513 | orc::ExecutorAddrDiff Offset = getRawOffset(Sym, Flags); |
514 | |
515 | if (Offset + Sym.st_size > B->getSize()) { |
516 | std::string ErrMsg; |
517 | raw_string_ostream ErrStream(ErrMsg); |
518 | ErrStream << "In " << G->getName() << ", symbol " ; |
519 | if (!Name->empty()) |
520 | ErrStream << *Name; |
521 | else |
522 | ErrStream << "<anon>" ; |
523 | ErrStream << " (" << (B->getAddress() + Offset) << " -- " |
524 | << (B->getAddress() + Offset + Sym.st_size) << ") extends " |
525 | << formatv("{0:x}" , Offset + Sym.st_size - B->getSize()) |
526 | << " bytes past the end of its containing block (" |
527 | << B->getRange() << ")" ; |
528 | return make_error<JITLinkError>(Args: std::move(ErrMsg)); |
529 | } |
530 | |
531 | // In RISCV, temporary symbols (Used to generate dwarf, eh_frame |
532 | // sections...) will appear in object code's symbol table, and LLVM does |
533 | // not use names on these temporary symbols (RISCV gnu toolchain uses |
534 | // names on these temporary symbols). If the symbol is unnamed, add an |
535 | // anonymous symbol. |
536 | auto &GSym = |
537 | Name->empty() |
538 | ? G->addAnonymousSymbol(Content&: *B, Offset, Size: Sym.st_size, |
539 | IsCallable: false, IsLive: false) |
540 | : G->addDefinedSymbol(Content&: *B, Offset, Name: *Name, Size: Sym.st_size, L, |
541 | S, IsCallable: Sym.getType() == ELF::STT_FUNC, |
542 | IsLive: false); |
543 | |
544 | GSym.setTargetFlags(Flags); |
545 | setGraphSymbol(SymIndex, Sym&: GSym); |
546 | } |
547 | } else if (Sym.isUndefined() && Sym.isExternal()) { |
548 | LLVM_DEBUG({ |
549 | dbgs() << " " << SymIndex |
550 | << ": Creating external graph symbol for ELF symbol \"" << *Name |
551 | << "\"\n" ; |
552 | }); |
553 | |
554 | if (Sym.getBinding() != ELF::STB_GLOBAL && |
555 | Sym.getBinding() != ELF::STB_WEAK) |
556 | return make_error<StringError>( |
557 | "Invalid symbol binding " + |
558 | Twine(static_cast<int>(Sym.getBinding())) + |
559 | " for external symbol " + *Name, |
560 | inconvertibleErrorCode()); |
561 | |
562 | // If L is Linkage::Weak that means this is a weakly referenced symbol. |
563 | auto &GSym = G->addExternalSymbol(Name: *Name, Size: Sym.st_size, |
564 | IsWeaklyReferenced: Sym.getBinding() == ELF::STB_WEAK); |
565 | setGraphSymbol(SymIndex, Sym&: GSym); |
566 | } else if (Sym.isUndefined() && Sym.st_value == 0 && Sym.st_size == 0 && |
567 | Sym.getType() == ELF::STT_NOTYPE && |
568 | Sym.getBinding() == ELF::STB_LOCAL && Name->empty()) { |
569 | // Some relocations (e.g., R_RISCV_ALIGN) don't have a target symbol and |
570 | // use this kind of null symbol as a placeholder. |
571 | LLVM_DEBUG({ |
572 | dbgs() << " " << SymIndex << ": Creating null graph symbol\n" ; |
573 | }); |
574 | |
575 | auto SymName = |
576 | G->allocateContent(Source: "__jitlink_ELF_SYM_UND_" + Twine(SymIndex)); |
577 | auto SymNameRef = StringRef(SymName.data(), SymName.size()); |
578 | auto &GSym = G->addAbsoluteSymbol(Name: SymNameRef, Address: orc::ExecutorAddr(0), Size: 0, |
579 | L: Linkage::Strong, S: Scope::Local, IsLive: false); |
580 | setGraphSymbol(SymIndex, Sym&: GSym); |
581 | } else { |
582 | LLVM_DEBUG({ |
583 | dbgs() << " " << SymIndex |
584 | << ": Not creating graph symbol for ELF symbol \"" << *Name |
585 | << "\" with unrecognized type\n" ; |
586 | }); |
587 | } |
588 | } |
589 | |
590 | return Error::success(); |
591 | } |
592 | |
593 | template <typename ELFT> |
594 | template <typename RelocHandlerFunction> |
595 | Error ELFLinkGraphBuilder<ELFT>::forEachRelaRelocation( |
596 | const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func) { |
597 | // Only look into sections that store relocation entries. |
598 | if (RelSect.sh_type != ELF::SHT_RELA) |
599 | return Error::success(); |
600 | |
601 | // sh_info contains the section header index of the target (FixupSection), |
602 | // which is the section to which all relocations in RelSect apply. |
603 | auto FixupSection = Obj.getSection(RelSect.sh_info); |
604 | if (!FixupSection) |
605 | return FixupSection.takeError(); |
606 | |
607 | // Target sections have names in valid ELF object files. |
608 | Expected<StringRef> Name = Obj.getSectionName(**FixupSection); |
609 | if (!Name) |
610 | return Name.takeError(); |
611 | LLVM_DEBUG(dbgs() << " " << *Name << ":\n" ); |
612 | |
613 | // Consider skipping these relocations. |
614 | if (!ProcessDebugSections && isDwarfSection(SectionName: *Name)) { |
615 | LLVM_DEBUG(dbgs() << " skipped (dwarf section)\n\n" ); |
616 | return Error::success(); |
617 | } |
618 | if (excludeSection(Sect: **FixupSection)) { |
619 | LLVM_DEBUG(dbgs() << " skipped (fixup section excluded explicitly)\n\n" ); |
620 | return Error::success(); |
621 | } |
622 | |
623 | // Lookup the link-graph node corresponding to the target section name. |
624 | auto *BlockToFix = getGraphBlock(SecIndex: RelSect.sh_info); |
625 | if (!BlockToFix) |
626 | return make_error<StringError>( |
627 | Args: "Refencing a section that wasn't added to the graph: " + *Name, |
628 | Args: inconvertibleErrorCode()); |
629 | |
630 | auto RelEntries = Obj.relas(RelSect); |
631 | if (!RelEntries) |
632 | return RelEntries.takeError(); |
633 | |
634 | // Let the callee process relocation entries one by one. |
635 | for (const typename ELFT::Rela &R : *RelEntries) |
636 | if (Error Err = Func(R, **FixupSection, *BlockToFix)) |
637 | return Err; |
638 | |
639 | LLVM_DEBUG(dbgs() << "\n" ); |
640 | return Error::success(); |
641 | } |
642 | |
643 | template <typename ELFT> |
644 | template <typename RelocHandlerFunction> |
645 | Error ELFLinkGraphBuilder<ELFT>::forEachRelRelocation( |
646 | const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func) { |
647 | // Only look into sections that store relocation entries. |
648 | if (RelSect.sh_type != ELF::SHT_REL) |
649 | return Error::success(); |
650 | |
651 | // sh_info contains the section header index of the target (FixupSection), |
652 | // which is the section to which all relocations in RelSect apply. |
653 | auto FixupSection = Obj.getSection(RelSect.sh_info); |
654 | if (!FixupSection) |
655 | return FixupSection.takeError(); |
656 | |
657 | // Target sections have names in valid ELF object files. |
658 | Expected<StringRef> Name = Obj.getSectionName(**FixupSection); |
659 | if (!Name) |
660 | return Name.takeError(); |
661 | LLVM_DEBUG(dbgs() << " " << *Name << ":\n" ); |
662 | |
663 | // Consider skipping these relocations. |
664 | if (!ProcessDebugSections && isDwarfSection(SectionName: *Name)) { |
665 | LLVM_DEBUG(dbgs() << " skipped (dwarf section)\n\n" ); |
666 | return Error::success(); |
667 | } |
668 | if (excludeSection(Sect: **FixupSection)) { |
669 | LLVM_DEBUG(dbgs() << " skipped (fixup section excluded explicitly)\n\n" ); |
670 | return Error::success(); |
671 | } |
672 | |
673 | // Lookup the link-graph node corresponding to the target section name. |
674 | auto *BlockToFix = getGraphBlock(SecIndex: RelSect.sh_info); |
675 | if (!BlockToFix) |
676 | return make_error<StringError>( |
677 | Args: "Refencing a section that wasn't added to the graph: " + *Name, |
678 | Args: inconvertibleErrorCode()); |
679 | |
680 | auto RelEntries = Obj.rels(RelSect); |
681 | if (!RelEntries) |
682 | return RelEntries.takeError(); |
683 | |
684 | // Let the callee process relocation entries one by one. |
685 | for (const typename ELFT::Rel &R : *RelEntries) |
686 | if (Error Err = Func(R, **FixupSection, *BlockToFix)) |
687 | return Err; |
688 | |
689 | LLVM_DEBUG(dbgs() << "\n" ); |
690 | return Error::success(); |
691 | } |
692 | |
693 | } // end namespace jitlink |
694 | } // end namespace llvm |
695 | |
696 | #undef DEBUG_TYPE |
697 | |
698 | #endif // LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H |
699 | |