| //===--- DebugInfoSupport.cpp -- Utils for debug info support ---*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // Utilities to preserve and parse debug info from LinkGraphs. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "llvm/ExecutionEngine/Orc/Debugging/DebugInfoSupport.h" |
| |
| #include "llvm/Support/SmallVectorMemoryBuffer.h" |
| |
| #define DEBUG_TYPE "orc" |
| |
| using namespace llvm; |
| using namespace llvm::orc; |
| using namespace llvm::jitlink; |
| |
| namespace { |
| static DenseSet<StringRef> DWARFSectionNames = { |
| #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION) \ |
| StringRef(ELF_NAME), |
| #include "llvm/BinaryFormat/Dwarf.def" |
| #undef HANDLE_DWARF_SECTION |
| }; |
| |
| // We might be able to drop relocations to symbols that do end up |
| // being pruned by the linker, but for now we just preserve all |
| static void preserveDWARFSection(LinkGraph &G, Section &Sec) { |
| DenseMap<Block *, Symbol *> Preserved; |
| for (auto Sym : Sec.symbols()) { |
| auto [It, Inserted] = Preserved.try_emplace(&Sym->getBlock()); |
| if (Inserted || Sym->isLive()) |
| It->second = Sym; |
| } |
| for (auto Block : Sec.blocks()) { |
| auto &PSym = Preserved[Block]; |
| if (!PSym) |
| PSym = &G.addAnonymousSymbol(*Block, 0, 0, false, true); |
| else if (!PSym->isLive()) |
| PSym->setLive(true); |
| } |
| } |
| |
| static SmallVector<char, 0> getSectionData(Section &Sec) { |
| SmallVector<char, 0> SecData; |
| SmallVector<Block *, 8> SecBlocks(Sec.blocks().begin(), Sec.blocks().end()); |
| llvm::sort(SecBlocks, [](Block *LHS, Block *RHS) { |
| return LHS->getAddress() < RHS->getAddress(); |
| }); |
| // Convert back to what object file would have, one blob of section content |
| // Assumes all zerofill |
| // TODO handle alignment? |
| // TODO handle alignment offset? |
| for (auto *Block : SecBlocks) { |
| if (Block->isZeroFill()) |
| SecData.resize(SecData.size() + Block->getSize(), 0); |
| else |
| SecData.append(Block->getContent().begin(), Block->getContent().end()); |
| } |
| return SecData; |
| } |
| |
| static void dumpDWARFContext(DWARFContext &DC) { |
| auto options = llvm::DIDumpOptions(); |
| options.DumpType &= ~DIDT_UUID; |
| options.DumpType &= ~(1 << DIDT_ID_DebugFrame); |
| LLVM_DEBUG(DC.dump(dbgs(), options)); |
| } |
| |
| } // namespace |
| |
| Error llvm::orc::preserveDebugSections(LinkGraph &G) { |
| if (!G.getTargetTriple().isOSBinFormatELF()) { |
| return make_error<StringError>( |
| "preserveDebugSections only supports ELF LinkGraphs!", |
| inconvertibleErrorCode()); |
| } |
| for (auto &Sec : G.sections()) { |
| if (DWARFSectionNames.count(Sec.getName())) { |
| LLVM_DEBUG(dbgs() << "Preserving DWARF section " << Sec.getName() |
| << "\n"); |
| preserveDWARFSection(G, Sec); |
| } |
| } |
| return Error::success(); |
| } |
| |
| Expected<std::pair<std::unique_ptr<DWARFContext>, |
| StringMap<std::unique_ptr<MemoryBuffer>>>> |
| llvm::orc::createDWARFContext(LinkGraph &G) { |
| if (!G.getTargetTriple().isOSBinFormatELF()) { |
| return make_error<StringError>( |
| "createDWARFContext only supports ELF LinkGraphs!", |
| inconvertibleErrorCode()); |
| } |
| StringMap<std::unique_ptr<MemoryBuffer>> DWARFSectionData; |
| for (auto &Sec : G.sections()) { |
| if (DWARFSectionNames.count(Sec.getName())) { |
| auto SecData = getSectionData(Sec); |
| auto Name = Sec.getName(); |
| // DWARFContext expects the section name to not start with a dot |
| Name.consume_front("."); |
| LLVM_DEBUG(dbgs() << "Creating DWARFContext section " << Name |
| << " with size " << SecData.size() << "\n"); |
| DWARFSectionData[Name] = |
| std::make_unique<SmallVectorMemoryBuffer>(std::move(SecData)); |
| } |
| } |
| auto Ctx = |
| DWARFContext::create(DWARFSectionData, G.getPointerSize(), |
| G.getEndianness() == llvm::endianness::little); |
| dumpDWARFContext(*Ctx); |
| return std::make_pair(std::move(Ctx), std::move(DWARFSectionData)); |
| } |