From db51e572893e9e4403d65920dc5e87a8885b059c Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Fri, 22 Sep 2023 10:38:07 -0700 Subject: [ORC] Add N_SO and N_OSO stabs entries to MachO debug objects. No testcase: This code generates an in-memory object file that is shared with the debugger. The object file is malformed in ways that don't matter to the debugger, but mean that it can't be inspected by most tools. --- .../ExecutionEngine/Orc/DebuggerSupportPlugin.cpp | 52 ++++++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) (limited to 'llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp') diff --git a/llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp b/llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp index 63c1886..0c973c3 100644 --- a/llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp +++ b/llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp @@ -16,6 +16,10 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringSet.h" #include "llvm/BinaryFormat/MachO.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" + +#include #define DEBUG_TYPE "orc" @@ -97,8 +101,6 @@ public: << "\n"; }); - auto &SDOSec = G.createSection(SynthDebugSectionName, MemProt::Read); - for (auto &Sec : G.sections()) { if (Sec.blocks().empty()) continue; @@ -114,6 +116,10 @@ public: NonDebugSections.push_back({&Sec, nullptr}); } + // Bail out early if no debug sections. + if (DebugSections.empty()) + return Error::success(); + // Write MachO header and debug section load commands. Builder.Header.filetype = MachO::MH_OBJECT; switch (G.getTargetTriple().getArch()) { @@ -131,15 +137,51 @@ public: Seg = &Builder.addSegment(""); + StringMap> DebugSectionMap; + StringRef DebugLineSectionData; for (auto &DSec : DebugSections) { auto [SegName, SecName] = DSec.GraphSec->getName().split(','); DSec.BuilderSec = &Seg->addSection(SecName, SegName); SectionRange SR(*DSec.GraphSec); DSec.BuilderSec->Content.Size = SR.getSize(); - if (!SR.empty()) + if (!SR.empty()) { DSec.BuilderSec->align = Log2_64(SR.getFirstBlock()->getAlignment()); + StringRef SectionData(SR.getFirstBlock()->getContent().data(), + SR.getFirstBlock()->getSize()); + DebugSectionMap[SecName] = + MemoryBuffer::getMemBuffer(SectionData, G.getName(), false); + if (SecName == "__debug_line") + DebugLineSectionData = SectionData; + } + } + + if (DebugLineSectionData.empty()) + return make_error(G.getName() + + " has debug info but no line table", + inconvertibleErrorCode()); + + // Add Stabs. + auto DWARFCtx = DWARFContext::create(DebugSectionMap, G.getPointerSize(), + G.getEndianness()); + DWARFDataExtractor DebugLineData( + DebugLineSectionData, G.getEndianness() == support::endianness::little, + G.getPointerSize()); + uint64_t Offset = 0; + DWARFDebugLine::LineTable LineTable; + if (auto Err = LineTable.parse(DebugLineData, &Offset, *DWARFCtx, nullptr, + consumeError)) + return Err; + + Builder.addSymbol("", MachO::N_SO, 0, 0, 0); + for (auto &FN : LineTable.Prologue.FileNames) { + if (auto Name = dwarf::toString(FN.Name)) + Builder.addSymbol(*Name, MachO::N_SO, 0, 0, 0); } + auto TimeStamp = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count(); + Builder.addSymbol("", MachO::N_OSO, 3, 1, TimeStamp); for (auto &NDSP : NonDebugSections) { auto [SegName, SecName] = NDSP.GraphSec->getName().split(','); @@ -164,8 +206,12 @@ public: } } + Builder.addSymbol("", MachO::N_SO, 1, 0, 0); + + // Lay out the debug object, create a section and block for it. size_t DebugObjectSize = Builder.layout(); + auto &SDOSec = G.createSection(SynthDebugSectionName, MemProt::Read); MachOContainerBlock = &G.createMutableContentBlock( SDOSec, G.allocateBuffer(DebugObjectSize), orc::ExecutorAddr(), 8, 0); -- cgit v1.1