diff options
author | Lang Hames <lhames@gmail.com> | 2023-09-22 10:38:07 -0700 |
---|---|---|
committer | Lang Hames <lhames@gmail.com> | 2023-09-22 10:56:40 -0700 |
commit | db51e572893e9e4403d65920dc5e87a8885b059c (patch) | |
tree | 1b96274b97885b33d5ec4ce41e59e962b31153d5 | |
parent | a12c2977debb640d2e694c72ed74344d366d89ae (diff) | |
download | llvm-db51e572893e9e4403d65920dc5e87a8885b059c.zip llvm-db51e572893e9e4403d65920dc5e87a8885b059c.tar.gz llvm-db51e572893e9e4403d65920dc5e87a8885b059c.tar.bz2 |
[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.
-rw-r--r-- | llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp | 52 |
1 files changed, 49 insertions, 3 deletions
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 <chrono> #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<std::unique_ptr<MemoryBuffer>> 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<StringError>(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::seconds>( + 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); |