//===--- 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 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 Preserved; for (auto Sym : Sec.symbols()) { if (Sym->isLive()) Preserved[&Sym->getBlock()] = Sym; else if (!Preserved.count(&Sym->getBlock())) Preserved[&Sym->getBlock()] = 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 getSectionData(Section &Sec) { SmallVector SecData; SmallVector SecBlocks(Sec.blocks().begin(), Sec.blocks().end()); std::sort(SecBlocks.begin(), SecBlocks.end(), [](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( "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, StringMap>>> llvm::orc::createDWARFContext(LinkGraph &G) { if (!G.getTargetTriple().isOSBinFormatELF()) { return make_error( "createDWARFContext only supports ELF LinkGraphs!", inconvertibleErrorCode()); } StringMap> 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(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)); }