15f757f3fSDimitry Andric //===--- DebugInfoSupport.cpp -- Utils for debug info support ---*- C++ -*-===// 25f757f3fSDimitry Andric // 35f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65f757f3fSDimitry Andric // 75f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 85f757f3fSDimitry Andric // 95f757f3fSDimitry Andric // Utilities to preserve and parse debug info from LinkGraphs. 105f757f3fSDimitry Andric // 115f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 125f757f3fSDimitry Andric 135f757f3fSDimitry Andric #include "llvm/ExecutionEngine/Orc/Debugging/DebugInfoSupport.h" 145f757f3fSDimitry Andric 155f757f3fSDimitry Andric #include "llvm/Support/SmallVectorMemoryBuffer.h" 165f757f3fSDimitry Andric 175f757f3fSDimitry Andric #define DEBUG_TYPE "orc" 185f757f3fSDimitry Andric 195f757f3fSDimitry Andric using namespace llvm; 205f757f3fSDimitry Andric using namespace llvm::orc; 215f757f3fSDimitry Andric using namespace llvm::jitlink; 225f757f3fSDimitry Andric 235f757f3fSDimitry Andric namespace { 245f757f3fSDimitry Andric static DenseSet<StringRef> DWARFSectionNames = { 255f757f3fSDimitry Andric #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION) \ 265f757f3fSDimitry Andric StringRef(ELF_NAME), 275f757f3fSDimitry Andric #include "llvm/BinaryFormat/Dwarf.def" 285f757f3fSDimitry Andric #undef HANDLE_DWARF_SECTION 295f757f3fSDimitry Andric }; 305f757f3fSDimitry Andric 315f757f3fSDimitry Andric // We might be able to drop relocations to symbols that do end up 325f757f3fSDimitry Andric // being pruned by the linker, but for now we just preserve all 335f757f3fSDimitry Andric static void preserveDWARFSection(LinkGraph &G, Section &Sec) { 345f757f3fSDimitry Andric DenseMap<Block *, Symbol *> Preserved; 355f757f3fSDimitry Andric for (auto Sym : Sec.symbols()) { 365f757f3fSDimitry Andric if (Sym->isLive()) 375f757f3fSDimitry Andric Preserved[&Sym->getBlock()] = Sym; 385f757f3fSDimitry Andric else if (!Preserved.count(&Sym->getBlock())) 395f757f3fSDimitry Andric Preserved[&Sym->getBlock()] = Sym; 405f757f3fSDimitry Andric } 415f757f3fSDimitry Andric for (auto Block : Sec.blocks()) { 425f757f3fSDimitry Andric auto &PSym = Preserved[Block]; 435f757f3fSDimitry Andric if (!PSym) 445f757f3fSDimitry Andric PSym = &G.addAnonymousSymbol(*Block, 0, 0, false, true); 455f757f3fSDimitry Andric else if (!PSym->isLive()) 465f757f3fSDimitry Andric PSym->setLive(true); 475f757f3fSDimitry Andric } 485f757f3fSDimitry Andric } 495f757f3fSDimitry Andric 505f757f3fSDimitry Andric static SmallVector<char, 0> getSectionData(Section &Sec) { 515f757f3fSDimitry Andric SmallVector<char, 0> SecData; 525f757f3fSDimitry Andric SmallVector<Block *, 8> SecBlocks(Sec.blocks().begin(), Sec.blocks().end()); 535f757f3fSDimitry Andric std::sort(SecBlocks.begin(), SecBlocks.end(), [](Block *LHS, Block *RHS) { 545f757f3fSDimitry Andric return LHS->getAddress() < RHS->getAddress(); 555f757f3fSDimitry Andric }); 565f757f3fSDimitry Andric // Convert back to what object file would have, one blob of section content 575f757f3fSDimitry Andric // Assumes all zerofill 585f757f3fSDimitry Andric // TODO handle alignment? 595f757f3fSDimitry Andric // TODO handle alignment offset? 605f757f3fSDimitry Andric for (auto *Block : SecBlocks) { 615f757f3fSDimitry Andric if (Block->isZeroFill()) 625f757f3fSDimitry Andric SecData.resize(SecData.size() + Block->getSize(), 0); 635f757f3fSDimitry Andric else 645f757f3fSDimitry Andric SecData.append(Block->getContent().begin(), Block->getContent().end()); 655f757f3fSDimitry Andric } 665f757f3fSDimitry Andric return SecData; 675f757f3fSDimitry Andric } 685f757f3fSDimitry Andric 695f757f3fSDimitry Andric static void dumpDWARFContext(DWARFContext &DC) { 705f757f3fSDimitry Andric auto options = llvm::DIDumpOptions(); 715f757f3fSDimitry Andric options.DumpType &= ~DIDT_UUID; 725f757f3fSDimitry Andric options.DumpType &= ~(1 << DIDT_ID_DebugFrame); 735f757f3fSDimitry Andric LLVM_DEBUG(DC.dump(dbgs(), options)); 745f757f3fSDimitry Andric } 755f757f3fSDimitry Andric 765f757f3fSDimitry Andric } // namespace 775f757f3fSDimitry Andric 785f757f3fSDimitry Andric Error llvm::orc::preserveDebugSections(LinkGraph &G) { 795f757f3fSDimitry Andric if (!G.getTargetTriple().isOSBinFormatELF()) { 805f757f3fSDimitry Andric return make_error<StringError>( 815f757f3fSDimitry Andric "preserveDebugSections only supports ELF LinkGraphs!", 825f757f3fSDimitry Andric inconvertibleErrorCode()); 835f757f3fSDimitry Andric } 845f757f3fSDimitry Andric for (auto &Sec : G.sections()) { 855f757f3fSDimitry Andric if (DWARFSectionNames.count(Sec.getName())) { 865f757f3fSDimitry Andric LLVM_DEBUG(dbgs() << "Preserving DWARF section " << Sec.getName() 875f757f3fSDimitry Andric << "\n"); 885f757f3fSDimitry Andric preserveDWARFSection(G, Sec); 895f757f3fSDimitry Andric } 905f757f3fSDimitry Andric } 915f757f3fSDimitry Andric return Error::success(); 925f757f3fSDimitry Andric } 935f757f3fSDimitry Andric 945f757f3fSDimitry Andric Expected<std::pair<std::unique_ptr<DWARFContext>, 955f757f3fSDimitry Andric StringMap<std::unique_ptr<MemoryBuffer>>>> 965f757f3fSDimitry Andric llvm::orc::createDWARFContext(LinkGraph &G) { 975f757f3fSDimitry Andric if (!G.getTargetTriple().isOSBinFormatELF()) { 985f757f3fSDimitry Andric return make_error<StringError>( 995f757f3fSDimitry Andric "createDWARFContext only supports ELF LinkGraphs!", 1005f757f3fSDimitry Andric inconvertibleErrorCode()); 1015f757f3fSDimitry Andric } 1025f757f3fSDimitry Andric StringMap<std::unique_ptr<MemoryBuffer>> DWARFSectionData; 1035f757f3fSDimitry Andric for (auto &Sec : G.sections()) { 1045f757f3fSDimitry Andric if (DWARFSectionNames.count(Sec.getName())) { 1055f757f3fSDimitry Andric auto SecData = getSectionData(Sec); 1065f757f3fSDimitry Andric auto Name = Sec.getName(); 1075f757f3fSDimitry Andric // DWARFContext expects the section name to not start with a dot 108*647cbc5dSDimitry Andric Name.consume_front("."); 1095f757f3fSDimitry Andric LLVM_DEBUG(dbgs() << "Creating DWARFContext section " << Name 1105f757f3fSDimitry Andric << " with size " << SecData.size() << "\n"); 1115f757f3fSDimitry Andric DWARFSectionData[Name] = 1125f757f3fSDimitry Andric std::make_unique<SmallVectorMemoryBuffer>(std::move(SecData)); 1135f757f3fSDimitry Andric } 1145f757f3fSDimitry Andric } 1155f757f3fSDimitry Andric auto Ctx = 1165f757f3fSDimitry Andric DWARFContext::create(DWARFSectionData, G.getPointerSize(), 1175f757f3fSDimitry Andric G.getEndianness() == llvm::endianness::little); 1185f757f3fSDimitry Andric dumpDWARFContext(*Ctx); 1195f757f3fSDimitry Andric return std::make_pair(std::move(Ctx), std::move(DWARFSectionData)); 1205f757f3fSDimitry Andric } 121