1 //===--- DebugInfoSupport.cpp -- Utils for debug info support ---*- 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 // Utilities to preserve and parse debug info from LinkGraphs. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/ExecutionEngine/Orc/Debugging/DebugInfoSupport.h" 14 15 #include "llvm/Support/SmallVectorMemoryBuffer.h" 16 17 #define DEBUG_TYPE "orc" 18 19 using namespace llvm; 20 using namespace llvm::orc; 21 using namespace llvm::jitlink; 22 23 namespace { 24 static DenseSet<StringRef> DWARFSectionNames = { 25 #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION) \ 26 StringRef(ELF_NAME), 27 #include "llvm/BinaryFormat/Dwarf.def" 28 #undef HANDLE_DWARF_SECTION 29 }; 30 31 // We might be able to drop relocations to symbols that do end up 32 // being pruned by the linker, but for now we just preserve all 33 static void preserveDWARFSection(LinkGraph &G, Section &Sec) { 34 DenseMap<Block *, Symbol *> Preserved; 35 for (auto Sym : Sec.symbols()) { 36 if (Sym->isLive()) 37 Preserved[&Sym->getBlock()] = Sym; 38 else if (!Preserved.count(&Sym->getBlock())) 39 Preserved[&Sym->getBlock()] = Sym; 40 } 41 for (auto Block : Sec.blocks()) { 42 auto &PSym = Preserved[Block]; 43 if (!PSym) 44 PSym = &G.addAnonymousSymbol(*Block, 0, 0, false, true); 45 else if (!PSym->isLive()) 46 PSym->setLive(true); 47 } 48 } 49 50 static SmallVector<char, 0> getSectionData(Section &Sec) { 51 SmallVector<char, 0> SecData; 52 SmallVector<Block *, 8> SecBlocks(Sec.blocks().begin(), Sec.blocks().end()); 53 std::sort(SecBlocks.begin(), SecBlocks.end(), [](Block *LHS, Block *RHS) { 54 return LHS->getAddress() < RHS->getAddress(); 55 }); 56 // Convert back to what object file would have, one blob of section content 57 // Assumes all zerofill 58 // TODO handle alignment? 59 // TODO handle alignment offset? 60 for (auto *Block : SecBlocks) { 61 if (Block->isZeroFill()) 62 SecData.resize(SecData.size() + Block->getSize(), 0); 63 else 64 SecData.append(Block->getContent().begin(), Block->getContent().end()); 65 } 66 return SecData; 67 } 68 69 static void dumpDWARFContext(DWARFContext &DC) { 70 auto options = llvm::DIDumpOptions(); 71 options.DumpType &= ~DIDT_UUID; 72 options.DumpType &= ~(1 << DIDT_ID_DebugFrame); 73 LLVM_DEBUG(DC.dump(dbgs(), options)); 74 } 75 76 } // namespace 77 78 Error llvm::orc::preserveDebugSections(LinkGraph &G) { 79 if (!G.getTargetTriple().isOSBinFormatELF()) { 80 return make_error<StringError>( 81 "preserveDebugSections only supports ELF LinkGraphs!", 82 inconvertibleErrorCode()); 83 } 84 for (auto &Sec : G.sections()) { 85 if (DWARFSectionNames.count(Sec.getName())) { 86 LLVM_DEBUG(dbgs() << "Preserving DWARF section " << Sec.getName() 87 << "\n"); 88 preserveDWARFSection(G, Sec); 89 } 90 } 91 return Error::success(); 92 } 93 94 Expected<std::pair<std::unique_ptr<DWARFContext>, 95 StringMap<std::unique_ptr<MemoryBuffer>>>> 96 llvm::orc::createDWARFContext(LinkGraph &G) { 97 if (!G.getTargetTriple().isOSBinFormatELF()) { 98 return make_error<StringError>( 99 "createDWARFContext only supports ELF LinkGraphs!", 100 inconvertibleErrorCode()); 101 } 102 StringMap<std::unique_ptr<MemoryBuffer>> DWARFSectionData; 103 for (auto &Sec : G.sections()) { 104 if (DWARFSectionNames.count(Sec.getName())) { 105 auto SecData = getSectionData(Sec); 106 auto Name = Sec.getName(); 107 // DWARFContext expects the section name to not start with a dot 108 Name.consume_front("."); 109 LLVM_DEBUG(dbgs() << "Creating DWARFContext section " << Name 110 << " with size " << SecData.size() << "\n"); 111 DWARFSectionData[Name] = 112 std::make_unique<SmallVectorMemoryBuffer>(std::move(SecData)); 113 } 114 } 115 auto Ctx = 116 DWARFContext::create(DWARFSectionData, G.getPointerSize(), 117 G.getEndianness() == llvm::endianness::little); 118 dumpDWARFContext(*Ctx); 119 return std::make_pair(std::move(Ctx), std::move(DWARFSectionData)); 120 } 121