xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Debugging/DebugInfoSupport.cpp (revision 647cbc5de815c5651677bf8582797f716ec7b48d)
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
preserveDWARFSection(LinkGraph & G,Section & Sec)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 
getSectionData(Section & Sec)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 
dumpDWARFContext(DWARFContext & DC)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 
preserveDebugSections(LinkGraph & G)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>>>>
createDWARFContext(LinkGraph & G)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