Skip to content

Commit

Permalink
[ORC] Add N_SO and N_OSO stabs entries to MachO debug objects.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
lhames committed Sep 22, 2023
1 parent a12c297 commit db51e57
Showing 1 changed file with 49 additions and 3 deletions.
52 changes: 49 additions & 3 deletions llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -97,8 +101,6 @@ class MachODebugObjectSynthesizer : public MachODebugObjectSynthesizerBase {
<< "\n";
});

auto &SDOSec = G.createSection(SynthDebugSectionName, MemProt::Read);

for (auto &Sec : G.sections()) {
if (Sec.blocks().empty())
continue;
Expand All @@ -114,6 +116,10 @@ class MachODebugObjectSynthesizer : public MachODebugObjectSynthesizerBase {
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()) {
Expand All @@ -131,15 +137,51 @@ class MachODebugObjectSynthesizer : public MachODebugObjectSynthesizerBase {

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(',');
Expand All @@ -164,8 +206,12 @@ class MachODebugObjectSynthesizer : public MachODebugObjectSynthesizerBase {
}
}

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);

Expand Down

0 comments on commit db51e57

Please sign in to comment.