xref: /llvm-project/llvm/lib/ExecutionEngine/Orc/Debugging/DebugInfoSupport.cpp (revision fef144cebb378f550ef098d370316554d647f625)
17ddf7d87SPrem Chintalapudi //===--- DebugInfoSupport.cpp -- Utils for debug info support ---*- C++ -*-===//
27ddf7d87SPrem Chintalapudi //
37ddf7d87SPrem Chintalapudi // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47ddf7d87SPrem Chintalapudi // See https://llvm.org/LICENSE.txt for license information.
57ddf7d87SPrem Chintalapudi // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67ddf7d87SPrem Chintalapudi //
77ddf7d87SPrem Chintalapudi //===----------------------------------------------------------------------===//
87ddf7d87SPrem Chintalapudi //
97ddf7d87SPrem Chintalapudi // Utilities to preserve and parse debug info from LinkGraphs.
107ddf7d87SPrem Chintalapudi //
117ddf7d87SPrem Chintalapudi //===----------------------------------------------------------------------===//
127ddf7d87SPrem Chintalapudi 
137ddf7d87SPrem Chintalapudi #include "llvm/ExecutionEngine/Orc/Debugging/DebugInfoSupport.h"
147ddf7d87SPrem Chintalapudi 
157ddf7d87SPrem Chintalapudi #include "llvm/Support/SmallVectorMemoryBuffer.h"
167ddf7d87SPrem Chintalapudi 
177ddf7d87SPrem Chintalapudi #define DEBUG_TYPE "orc"
187ddf7d87SPrem Chintalapudi 
197ddf7d87SPrem Chintalapudi using namespace llvm;
207ddf7d87SPrem Chintalapudi using namespace llvm::orc;
217ddf7d87SPrem Chintalapudi using namespace llvm::jitlink;
227ddf7d87SPrem Chintalapudi 
237ddf7d87SPrem Chintalapudi namespace {
247ddf7d87SPrem Chintalapudi static DenseSet<StringRef> DWARFSectionNames = {
257ddf7d87SPrem Chintalapudi #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION)        \
267ddf7d87SPrem Chintalapudi   StringRef(ELF_NAME),
277ddf7d87SPrem Chintalapudi #include "llvm/BinaryFormat/Dwarf.def"
287ddf7d87SPrem Chintalapudi #undef HANDLE_DWARF_SECTION
297ddf7d87SPrem Chintalapudi };
307ddf7d87SPrem Chintalapudi 
317ddf7d87SPrem Chintalapudi // We might be able to drop relocations to symbols that do end up
327ddf7d87SPrem Chintalapudi // being pruned by the linker, but for now we just preserve all
preserveDWARFSection(LinkGraph & G,Section & Sec)337ddf7d87SPrem Chintalapudi static void preserveDWARFSection(LinkGraph &G, Section &Sec) {
347ddf7d87SPrem Chintalapudi   DenseMap<Block *, Symbol *> Preserved;
357ddf7d87SPrem Chintalapudi   for (auto Sym : Sec.symbols()) {
367ddf7d87SPrem Chintalapudi     if (Sym->isLive())
377ddf7d87SPrem Chintalapudi       Preserved[&Sym->getBlock()] = Sym;
387ddf7d87SPrem Chintalapudi     else if (!Preserved.count(&Sym->getBlock()))
397ddf7d87SPrem Chintalapudi       Preserved[&Sym->getBlock()] = Sym;
407ddf7d87SPrem Chintalapudi   }
417ddf7d87SPrem Chintalapudi   for (auto Block : Sec.blocks()) {
427ddf7d87SPrem Chintalapudi     auto &PSym = Preserved[Block];
437ddf7d87SPrem Chintalapudi     if (!PSym)
447ddf7d87SPrem Chintalapudi       PSym = &G.addAnonymousSymbol(*Block, 0, 0, false, true);
457ddf7d87SPrem Chintalapudi     else if (!PSym->isLive())
467ddf7d87SPrem Chintalapudi       PSym->setLive(true);
477ddf7d87SPrem Chintalapudi   }
487ddf7d87SPrem Chintalapudi }
497ddf7d87SPrem Chintalapudi 
getSectionData(Section & Sec)507ddf7d87SPrem Chintalapudi static SmallVector<char, 0> getSectionData(Section &Sec) {
517ddf7d87SPrem Chintalapudi   SmallVector<char, 0> SecData;
527ddf7d87SPrem Chintalapudi   SmallVector<Block *, 8> SecBlocks(Sec.blocks().begin(), Sec.blocks().end());
53*fef144ceSKazu Hirata   std::sort(SecBlocks.begin(), SecBlocks.end(), [](Block *LHS, Block *RHS) {
547ddf7d87SPrem Chintalapudi     return LHS->getAddress() < RHS->getAddress();
557ddf7d87SPrem Chintalapudi   });
567ddf7d87SPrem Chintalapudi   // Convert back to what object file would have, one blob of section content
577ddf7d87SPrem Chintalapudi   // Assumes all zerofill
587ddf7d87SPrem Chintalapudi   // TODO handle alignment?
597ddf7d87SPrem Chintalapudi   // TODO handle alignment offset?
607ddf7d87SPrem Chintalapudi   for (auto *Block : SecBlocks) {
617ddf7d87SPrem Chintalapudi     if (Block->isZeroFill())
627ddf7d87SPrem Chintalapudi       SecData.resize(SecData.size() + Block->getSize(), 0);
637ddf7d87SPrem Chintalapudi     else
647ddf7d87SPrem Chintalapudi       SecData.append(Block->getContent().begin(), Block->getContent().end());
657ddf7d87SPrem Chintalapudi   }
667ddf7d87SPrem Chintalapudi   return SecData;
677ddf7d87SPrem Chintalapudi }
687ddf7d87SPrem Chintalapudi 
dumpDWARFContext(DWARFContext & DC)697ddf7d87SPrem Chintalapudi static void dumpDWARFContext(DWARFContext &DC) {
707ddf7d87SPrem Chintalapudi   auto options = llvm::DIDumpOptions();
717ddf7d87SPrem Chintalapudi   options.DumpType &= ~DIDT_UUID;
727ddf7d87SPrem Chintalapudi   options.DumpType &= ~(1 << DIDT_ID_DebugFrame);
737ddf7d87SPrem Chintalapudi   LLVM_DEBUG(DC.dump(dbgs(), options));
747ddf7d87SPrem Chintalapudi }
757ddf7d87SPrem Chintalapudi 
767ddf7d87SPrem Chintalapudi } // namespace
777ddf7d87SPrem Chintalapudi 
preserveDebugSections(LinkGraph & G)787ddf7d87SPrem Chintalapudi Error llvm::orc::preserveDebugSections(LinkGraph &G) {
797ddf7d87SPrem Chintalapudi   if (!G.getTargetTriple().isOSBinFormatELF()) {
807ddf7d87SPrem Chintalapudi     return make_error<StringError>(
817ddf7d87SPrem Chintalapudi         "preserveDebugSections only supports ELF LinkGraphs!",
827ddf7d87SPrem Chintalapudi         inconvertibleErrorCode());
837ddf7d87SPrem Chintalapudi   }
847ddf7d87SPrem Chintalapudi   for (auto &Sec : G.sections()) {
857ddf7d87SPrem Chintalapudi     if (DWARFSectionNames.count(Sec.getName())) {
867ddf7d87SPrem Chintalapudi       LLVM_DEBUG(dbgs() << "Preserving DWARF section " << Sec.getName()
877ddf7d87SPrem Chintalapudi                         << "\n");
887ddf7d87SPrem Chintalapudi       preserveDWARFSection(G, Sec);
897ddf7d87SPrem Chintalapudi     }
907ddf7d87SPrem Chintalapudi   }
917ddf7d87SPrem Chintalapudi   return Error::success();
927ddf7d87SPrem Chintalapudi }
937ddf7d87SPrem Chintalapudi 
947ddf7d87SPrem Chintalapudi Expected<std::pair<std::unique_ptr<DWARFContext>,
957ddf7d87SPrem Chintalapudi                    StringMap<std::unique_ptr<MemoryBuffer>>>>
createDWARFContext(LinkGraph & G)967ddf7d87SPrem Chintalapudi llvm::orc::createDWARFContext(LinkGraph &G) {
977ddf7d87SPrem Chintalapudi   if (!G.getTargetTriple().isOSBinFormatELF()) {
987ddf7d87SPrem Chintalapudi     return make_error<StringError>(
997ddf7d87SPrem Chintalapudi         "createDWARFContext only supports ELF LinkGraphs!",
1007ddf7d87SPrem Chintalapudi         inconvertibleErrorCode());
1017ddf7d87SPrem Chintalapudi   }
1027ddf7d87SPrem Chintalapudi   StringMap<std::unique_ptr<MemoryBuffer>> DWARFSectionData;
1037ddf7d87SPrem Chintalapudi   for (auto &Sec : G.sections()) {
1047ddf7d87SPrem Chintalapudi     if (DWARFSectionNames.count(Sec.getName())) {
1057ddf7d87SPrem Chintalapudi       auto SecData = getSectionData(Sec);
1067ddf7d87SPrem Chintalapudi       auto Name = Sec.getName();
1077ddf7d87SPrem Chintalapudi       // DWARFContext expects the section name to not start with a dot
108f5f2c313SKazu Hirata       Name.consume_front(".");
1097ddf7d87SPrem Chintalapudi       LLVM_DEBUG(dbgs() << "Creating DWARFContext section " << Name
1107ddf7d87SPrem Chintalapudi                         << " with size " << SecData.size() << "\n");
1117ddf7d87SPrem Chintalapudi       DWARFSectionData[Name] =
1127ddf7d87SPrem Chintalapudi           std::make_unique<SmallVectorMemoryBuffer>(std::move(SecData));
1137ddf7d87SPrem Chintalapudi     }
1147ddf7d87SPrem Chintalapudi   }
1154a0ccfa8SKazu Hirata   auto Ctx =
1164a0ccfa8SKazu Hirata       DWARFContext::create(DWARFSectionData, G.getPointerSize(),
1174a0ccfa8SKazu Hirata                            G.getEndianness() == llvm::endianness::little);
1187ddf7d87SPrem Chintalapudi   dumpDWARFContext(*Ctx);
1197ddf7d87SPrem Chintalapudi   return std::make_pair(std::move(Ctx), std::move(DWARFSectionData));
1207ddf7d87SPrem Chintalapudi }
121