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