[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.
This commit is contained in:
Lang Hames
2023-09-22 10:38:07 -07:00
parent a12c2977de
commit db51e57289

View File

@@ -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,16 +137,52 @@ 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(',');
NDSP.BuilderSec = &Seg->addSection(SecName, SegName);
@@ -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);