Skip to content

Commit db51e57

Browse files
committed
[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.
1 parent a12c297 commit db51e57

File tree

1 file changed

+49
-3
lines changed

1 file changed

+49
-3
lines changed

llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
#include "llvm/ADT/SmallVector.h"
1717
#include "llvm/ADT/StringSet.h"
1818
#include "llvm/BinaryFormat/MachO.h"
19+
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
20+
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
21+
22+
#include <chrono>
1923

2024
#define DEBUG_TYPE "orc"
2125

@@ -97,8 +101,6 @@ class MachODebugObjectSynthesizer : public MachODebugObjectSynthesizerBase {
97101
<< "\n";
98102
});
99103

100-
auto &SDOSec = G.createSection(SynthDebugSectionName, MemProt::Read);
101-
102104
for (auto &Sec : G.sections()) {
103105
if (Sec.blocks().empty())
104106
continue;
@@ -114,6 +116,10 @@ class MachODebugObjectSynthesizer : public MachODebugObjectSynthesizerBase {
114116
NonDebugSections.push_back({&Sec, nullptr});
115117
}
116118

119+
// Bail out early if no debug sections.
120+
if (DebugSections.empty())
121+
return Error::success();
122+
117123
// Write MachO header and debug section load commands.
118124
Builder.Header.filetype = MachO::MH_OBJECT;
119125
switch (G.getTargetTriple().getArch()) {
@@ -131,15 +137,51 @@ class MachODebugObjectSynthesizer : public MachODebugObjectSynthesizerBase {
131137

132138
Seg = &Builder.addSegment("");
133139

140+
StringMap<std::unique_ptr<MemoryBuffer>> DebugSectionMap;
141+
StringRef DebugLineSectionData;
134142
for (auto &DSec : DebugSections) {
135143
auto [SegName, SecName] = DSec.GraphSec->getName().split(',');
136144
DSec.BuilderSec = &Seg->addSection(SecName, SegName);
137145

138146
SectionRange SR(*DSec.GraphSec);
139147
DSec.BuilderSec->Content.Size = SR.getSize();
140-
if (!SR.empty())
148+
if (!SR.empty()) {
141149
DSec.BuilderSec->align = Log2_64(SR.getFirstBlock()->getAlignment());
150+
StringRef SectionData(SR.getFirstBlock()->getContent().data(),
151+
SR.getFirstBlock()->getSize());
152+
DebugSectionMap[SecName] =
153+
MemoryBuffer::getMemBuffer(SectionData, G.getName(), false);
154+
if (SecName == "__debug_line")
155+
DebugLineSectionData = SectionData;
156+
}
157+
}
158+
159+
if (DebugLineSectionData.empty())
160+
return make_error<StringError>(G.getName() +
161+
" has debug info but no line table",
162+
inconvertibleErrorCode());
163+
164+
// Add Stabs.
165+
auto DWARFCtx = DWARFContext::create(DebugSectionMap, G.getPointerSize(),
166+
G.getEndianness());
167+
DWARFDataExtractor DebugLineData(
168+
DebugLineSectionData, G.getEndianness() == support::endianness::little,
169+
G.getPointerSize());
170+
uint64_t Offset = 0;
171+
DWARFDebugLine::LineTable LineTable;
172+
if (auto Err = LineTable.parse(DebugLineData, &Offset, *DWARFCtx, nullptr,
173+
consumeError))
174+
return Err;
175+
176+
Builder.addSymbol("", MachO::N_SO, 0, 0, 0);
177+
for (auto &FN : LineTable.Prologue.FileNames) {
178+
if (auto Name = dwarf::toString(FN.Name))
179+
Builder.addSymbol(*Name, MachO::N_SO, 0, 0, 0);
142180
}
181+
auto TimeStamp = std::chrono::duration_cast<std::chrono::seconds>(
182+
std::chrono::system_clock::now().time_since_epoch())
183+
.count();
184+
Builder.addSymbol("", MachO::N_OSO, 3, 1, TimeStamp);
143185

144186
for (auto &NDSP : NonDebugSections) {
145187
auto [SegName, SecName] = NDSP.GraphSec->getName().split(',');
@@ -164,8 +206,12 @@ class MachODebugObjectSynthesizer : public MachODebugObjectSynthesizerBase {
164206
}
165207
}
166208

209+
Builder.addSymbol("", MachO::N_SO, 1, 0, 0);
210+
211+
// Lay out the debug object, create a section and block for it.
167212
size_t DebugObjectSize = Builder.layout();
168213

214+
auto &SDOSec = G.createSection(SynthDebugSectionName, MemProt::Read);
169215
MachOContainerBlock = &G.createMutableContentBlock(
170216
SDOSec, G.allocateBuffer(DebugObjectSize), orc::ExecutorAddr(), 8, 0);
171217

0 commit comments

Comments
 (0)