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