1097a140dSpatrick //===- DwarfStreamer.cpp --------------------------------------------------===//
2097a140dSpatrick //
3097a140dSpatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4097a140dSpatrick // See https://llvm.org/LICENSE.txt for license information.
5097a140dSpatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6097a140dSpatrick //
7097a140dSpatrick //===----------------------------------------------------------------------===//
8097a140dSpatrick
9097a140dSpatrick #include "llvm/DWARFLinker/DWARFStreamer.h"
10097a140dSpatrick #include "llvm/ADT/Triple.h"
11097a140dSpatrick #include "llvm/CodeGen/NonRelocatableStringpool.h"
12097a140dSpatrick #include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
13097a140dSpatrick #include "llvm/DebugInfo/DWARF/DWARFContext.h"
14*d415bd75Srobert #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
15097a140dSpatrick #include "llvm/MC/MCAsmBackend.h"
16097a140dSpatrick #include "llvm/MC/MCCodeEmitter.h"
17097a140dSpatrick #include "llvm/MC/MCDwarf.h"
18097a140dSpatrick #include "llvm/MC/MCObjectWriter.h"
19097a140dSpatrick #include "llvm/MC/MCSection.h"
20097a140dSpatrick #include "llvm/MC/MCStreamer.h"
21097a140dSpatrick #include "llvm/MC/MCSubtargetInfo.h"
22097a140dSpatrick #include "llvm/MC/MCTargetOptions.h"
23097a140dSpatrick #include "llvm/MC/MCTargetOptionsCommandFlags.h"
24*d415bd75Srobert #include "llvm/MC/TargetRegistry.h"
25*d415bd75Srobert #include "llvm/Support/FormatVariadic.h"
26097a140dSpatrick #include "llvm/Support/LEB128.h"
27097a140dSpatrick #include "llvm/Target/TargetOptions.h"
28097a140dSpatrick
29097a140dSpatrick namespace llvm {
30097a140dSpatrick
init(Triple TheTriple,StringRef Swift5ReflectionSegmentName)31*d415bd75Srobert bool DwarfStreamer::init(Triple TheTriple,
32*d415bd75Srobert StringRef Swift5ReflectionSegmentName) {
33097a140dSpatrick std::string ErrorStr;
34097a140dSpatrick std::string TripleName;
35097a140dSpatrick StringRef Context = "dwarf streamer init";
36097a140dSpatrick
37097a140dSpatrick // Get the target.
38097a140dSpatrick const Target *TheTarget =
39097a140dSpatrick TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);
40097a140dSpatrick if (!TheTarget)
41097a140dSpatrick return error(ErrorStr, Context), false;
42097a140dSpatrick TripleName = TheTriple.getTriple();
43097a140dSpatrick
44097a140dSpatrick // Create all the MC Objects.
45097a140dSpatrick MRI.reset(TheTarget->createMCRegInfo(TripleName));
46097a140dSpatrick if (!MRI)
47097a140dSpatrick return error(Twine("no register info for target ") + TripleName, Context),
48097a140dSpatrick false;
49097a140dSpatrick
50097a140dSpatrick MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();
51097a140dSpatrick MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
52097a140dSpatrick if (!MAI)
53097a140dSpatrick return error("no asm info for target " + TripleName, Context), false;
54097a140dSpatrick
55097a140dSpatrick MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
56097a140dSpatrick if (!MSTI)
57097a140dSpatrick return error("no subtarget info for target " + TripleName, Context), false;
58097a140dSpatrick
59*d415bd75Srobert MC.reset(new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get(), nullptr,
60*d415bd75Srobert nullptr, true, Swift5ReflectionSegmentName));
61*d415bd75Srobert MOFI.reset(TheTarget->createMCObjectFileInfo(*MC, /*PIC=*/false, false));
6273471bf0Spatrick MC->setObjectFileInfo(MOFI.get());
6373471bf0Spatrick
64097a140dSpatrick MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, MCOptions);
65097a140dSpatrick if (!MAB)
66097a140dSpatrick return error("no asm backend for target " + TripleName, Context), false;
67097a140dSpatrick
68097a140dSpatrick MII.reset(TheTarget->createMCInstrInfo());
69097a140dSpatrick if (!MII)
70097a140dSpatrick return error("no instr info info for target " + TripleName, Context), false;
71097a140dSpatrick
72*d415bd75Srobert MCE = TheTarget->createMCCodeEmitter(*MII, *MC);
73097a140dSpatrick if (!MCE)
74097a140dSpatrick return error("no code emitter for target " + TripleName, Context), false;
75097a140dSpatrick
76097a140dSpatrick switch (OutFileType) {
77097a140dSpatrick case OutputFileType::Assembly: {
78097a140dSpatrick MIP = TheTarget->createMCInstPrinter(TheTriple, MAI->getAssemblerDialect(),
79097a140dSpatrick *MAI, *MII, *MRI);
80097a140dSpatrick MS = TheTarget->createAsmStreamer(
81097a140dSpatrick *MC, std::make_unique<formatted_raw_ostream>(OutFile), true, true, MIP,
82097a140dSpatrick std::unique_ptr<MCCodeEmitter>(MCE), std::unique_ptr<MCAsmBackend>(MAB),
83097a140dSpatrick true);
84097a140dSpatrick break;
85097a140dSpatrick }
86097a140dSpatrick case OutputFileType::Object: {
87097a140dSpatrick MS = TheTarget->createMCObjectStreamer(
88097a140dSpatrick TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB),
89097a140dSpatrick MAB->createObjectWriter(OutFile), std::unique_ptr<MCCodeEmitter>(MCE),
90097a140dSpatrick *MSTI, MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible,
91097a140dSpatrick /*DWARFMustBeAtTheEnd*/ false);
92097a140dSpatrick break;
93097a140dSpatrick }
94097a140dSpatrick }
95097a140dSpatrick
96097a140dSpatrick if (!MS)
97097a140dSpatrick return error("no object streamer for target " + TripleName, Context), false;
98097a140dSpatrick
99097a140dSpatrick // Finally create the AsmPrinter we'll use to emit the DIEs.
100097a140dSpatrick TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(),
101*d415bd75Srobert std::nullopt));
102097a140dSpatrick if (!TM)
103097a140dSpatrick return error("no target machine for target " + TripleName, Context), false;
104097a140dSpatrick
105097a140dSpatrick Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS)));
106097a140dSpatrick if (!Asm)
107097a140dSpatrick return error("no asm printer for target " + TripleName, Context), false;
108*d415bd75Srobert Asm->setDwarfUsesRelocationsAcrossSections(false);
109097a140dSpatrick
110097a140dSpatrick RangesSectionSize = 0;
111097a140dSpatrick LocSectionSize = 0;
112097a140dSpatrick LineSectionSize = 0;
113097a140dSpatrick FrameSectionSize = 0;
114097a140dSpatrick DebugInfoSectionSize = 0;
115*d415bd75Srobert MacInfoSectionSize = 0;
116*d415bd75Srobert MacroSectionSize = 0;
117097a140dSpatrick
118097a140dSpatrick return true;
119097a140dSpatrick }
120097a140dSpatrick
finish()121*d415bd75Srobert void DwarfStreamer::finish() { MS->finish(); }
122097a140dSpatrick
switchToDebugInfoSection(unsigned DwarfVersion)123097a140dSpatrick void DwarfStreamer::switchToDebugInfoSection(unsigned DwarfVersion) {
124*d415bd75Srobert MS->switchSection(MOFI->getDwarfInfoSection());
125097a140dSpatrick MC->setDwarfVersion(DwarfVersion);
126097a140dSpatrick }
127097a140dSpatrick
128097a140dSpatrick /// Emit the compilation unit header for \p Unit in the debug_info section.
129097a140dSpatrick ///
13073471bf0Spatrick /// A Dwarf 4 section header is encoded as:
131097a140dSpatrick /// uint32_t Unit length (omitting this field)
132097a140dSpatrick /// uint16_t Version
133097a140dSpatrick /// uint32_t Abbreviation table offset
134097a140dSpatrick /// uint8_t Address size
135097a140dSpatrick /// Leading to a total of 11 bytes.
13673471bf0Spatrick ///
13773471bf0Spatrick /// A Dwarf 5 section header is encoded as:
13873471bf0Spatrick /// uint32_t Unit length (omitting this field)
13973471bf0Spatrick /// uint16_t Version
14073471bf0Spatrick /// uint8_t Unit type
14173471bf0Spatrick /// uint8_t Address size
14273471bf0Spatrick /// uint32_t Abbreviation table offset
14373471bf0Spatrick /// Leading to a total of 12 bytes.
emitCompileUnitHeader(CompileUnit & Unit,unsigned DwarfVersion)14473471bf0Spatrick void DwarfStreamer::emitCompileUnitHeader(CompileUnit &Unit,
14573471bf0Spatrick unsigned DwarfVersion) {
14673471bf0Spatrick switchToDebugInfoSection(DwarfVersion);
147097a140dSpatrick
148097a140dSpatrick /// The start of the unit within its section.
149097a140dSpatrick Unit.setLabelBegin(Asm->createTempSymbol("cu_begin"));
150097a140dSpatrick Asm->OutStreamer->emitLabel(Unit.getLabelBegin());
151097a140dSpatrick
152097a140dSpatrick // Emit size of content not including length itself. The size has already
153097a140dSpatrick // been computed in CompileUnit::computeOffsets(). Subtract 4 to that size to
154097a140dSpatrick // account for the length field.
155097a140dSpatrick Asm->emitInt32(Unit.getNextUnitOffset() - Unit.getStartOffset() - 4);
15673471bf0Spatrick Asm->emitInt16(DwarfVersion);
157097a140dSpatrick
15873471bf0Spatrick if (DwarfVersion >= 5) {
15973471bf0Spatrick Asm->emitInt8(dwarf::DW_UT_compile);
16073471bf0Spatrick Asm->emitInt8(Unit.getOrigUnit().getAddressByteSize());
16173471bf0Spatrick // We share one abbreviations table across all units so it's always at the
16273471bf0Spatrick // start of the section.
16373471bf0Spatrick Asm->emitInt32(0);
16473471bf0Spatrick DebugInfoSectionSize += 12;
16573471bf0Spatrick } else {
166097a140dSpatrick // We share one abbreviations table across all units so it's always at the
167097a140dSpatrick // start of the section.
168097a140dSpatrick Asm->emitInt32(0);
169097a140dSpatrick Asm->emitInt8(Unit.getOrigUnit().getAddressByteSize());
170097a140dSpatrick DebugInfoSectionSize += 11;
17173471bf0Spatrick }
172097a140dSpatrick
173097a140dSpatrick // Remember this CU.
174097a140dSpatrick EmittedUnits.push_back({Unit.getUniqueID(), Unit.getLabelBegin()});
175097a140dSpatrick }
176097a140dSpatrick
177097a140dSpatrick /// Emit the \p Abbrevs array as the shared abbreviation table
178097a140dSpatrick /// for the linked Dwarf file.
emitAbbrevs(const std::vector<std::unique_ptr<DIEAbbrev>> & Abbrevs,unsigned DwarfVersion)179097a140dSpatrick void DwarfStreamer::emitAbbrevs(
180097a140dSpatrick const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs,
181097a140dSpatrick unsigned DwarfVersion) {
182*d415bd75Srobert MS->switchSection(MOFI->getDwarfAbbrevSection());
183097a140dSpatrick MC->setDwarfVersion(DwarfVersion);
184097a140dSpatrick Asm->emitDwarfAbbrevs(Abbrevs);
185097a140dSpatrick }
186097a140dSpatrick
187097a140dSpatrick /// Recursively emit the DIE tree rooted at \p Die.
emitDIE(DIE & Die)188097a140dSpatrick void DwarfStreamer::emitDIE(DIE &Die) {
189*d415bd75Srobert MS->switchSection(MOFI->getDwarfInfoSection());
190097a140dSpatrick Asm->emitDwarfDIE(Die);
191097a140dSpatrick DebugInfoSectionSize += Die.getSize();
192097a140dSpatrick }
193097a140dSpatrick
194097a140dSpatrick /// Emit contents of section SecName From Obj.
emitSectionContents(StringRef SecData,StringRef SecName)195097a140dSpatrick void DwarfStreamer::emitSectionContents(StringRef SecData, StringRef SecName) {
196097a140dSpatrick MCSection *Section =
197097a140dSpatrick StringSwitch<MCSection *>(SecName)
198097a140dSpatrick .Case("debug_line", MC->getObjectFileInfo()->getDwarfLineSection())
199097a140dSpatrick .Case("debug_loc", MC->getObjectFileInfo()->getDwarfLocSection())
200097a140dSpatrick .Case("debug_ranges",
201097a140dSpatrick MC->getObjectFileInfo()->getDwarfRangesSection())
202097a140dSpatrick .Case("debug_frame", MC->getObjectFileInfo()->getDwarfFrameSection())
203097a140dSpatrick .Case("debug_aranges",
204097a140dSpatrick MC->getObjectFileInfo()->getDwarfARangesSection())
205097a140dSpatrick .Default(nullptr);
206097a140dSpatrick
207097a140dSpatrick if (Section) {
208*d415bd75Srobert MS->switchSection(Section);
209097a140dSpatrick
210097a140dSpatrick MS->emitBytes(SecData);
211097a140dSpatrick }
212097a140dSpatrick }
213097a140dSpatrick
214097a140dSpatrick /// Emit DIE containing warnings.
emitPaperTrailWarningsDie(DIE & Die)215097a140dSpatrick void DwarfStreamer::emitPaperTrailWarningsDie(DIE &Die) {
216097a140dSpatrick switchToDebugInfoSection(/* Version */ 2);
217097a140dSpatrick auto &Asm = getAsmPrinter();
218097a140dSpatrick Asm.emitInt32(11 + Die.getSize() - 4);
219097a140dSpatrick Asm.emitInt16(2);
220097a140dSpatrick Asm.emitInt32(0);
22173471bf0Spatrick Asm.emitInt8(MC->getTargetTriple().isArch64Bit() ? 8 : 4);
222097a140dSpatrick DebugInfoSectionSize += 11;
223097a140dSpatrick emitDIE(Die);
224097a140dSpatrick }
225097a140dSpatrick
226097a140dSpatrick /// Emit the debug_str section stored in \p Pool.
emitStrings(const NonRelocatableStringpool & Pool)227097a140dSpatrick void DwarfStreamer::emitStrings(const NonRelocatableStringpool &Pool) {
228*d415bd75Srobert Asm->OutStreamer->switchSection(MOFI->getDwarfStrSection());
229097a140dSpatrick std::vector<DwarfStringPoolEntryRef> Entries = Pool.getEntriesForEmission();
230097a140dSpatrick for (auto Entry : Entries) {
231097a140dSpatrick // Emit the string itself.
232097a140dSpatrick Asm->OutStreamer->emitBytes(Entry.getString());
233097a140dSpatrick // Emit a null terminator.
234097a140dSpatrick Asm->emitInt8(0);
235097a140dSpatrick }
23673471bf0Spatrick
23773471bf0Spatrick #if 0
23873471bf0Spatrick if (DwarfVersion >= 5) {
23973471bf0Spatrick // Emit an empty string offset section.
240*d415bd75Srobert Asm->OutStreamer->switchSection(MOFI->getDwarfStrOffSection());
24173471bf0Spatrick Asm->emitDwarfUnitLength(4, "Length of String Offsets Set");
24273471bf0Spatrick Asm->emitInt16(DwarfVersion);
24373471bf0Spatrick Asm->emitInt16(0);
24473471bf0Spatrick }
24573471bf0Spatrick #endif
246097a140dSpatrick }
247097a140dSpatrick
emitDebugNames(AccelTable<DWARF5AccelTableStaticData> & Table)248097a140dSpatrick void DwarfStreamer::emitDebugNames(
249097a140dSpatrick AccelTable<DWARF5AccelTableStaticData> &Table) {
250097a140dSpatrick if (EmittedUnits.empty())
251097a140dSpatrick return;
252097a140dSpatrick
253097a140dSpatrick // Build up data structures needed to emit this section.
254097a140dSpatrick std::vector<MCSymbol *> CompUnits;
255097a140dSpatrick DenseMap<unsigned, size_t> UniqueIdToCuMap;
256097a140dSpatrick unsigned Id = 0;
257097a140dSpatrick for (auto &CU : EmittedUnits) {
258097a140dSpatrick CompUnits.push_back(CU.LabelBegin);
259097a140dSpatrick // We might be omitting CUs, so we need to remap them.
260097a140dSpatrick UniqueIdToCuMap[CU.ID] = Id++;
261097a140dSpatrick }
262097a140dSpatrick
263*d415bd75Srobert Asm->OutStreamer->switchSection(MOFI->getDwarfDebugNamesSection());
264097a140dSpatrick emitDWARF5AccelTable(
265097a140dSpatrick Asm.get(), Table, CompUnits,
266097a140dSpatrick [&UniqueIdToCuMap](const DWARF5AccelTableStaticData &Entry) {
267097a140dSpatrick return UniqueIdToCuMap[Entry.getCUIndex()];
268097a140dSpatrick });
269097a140dSpatrick }
270097a140dSpatrick
emitAppleNamespaces(AccelTable<AppleAccelTableStaticOffsetData> & Table)271097a140dSpatrick void DwarfStreamer::emitAppleNamespaces(
272097a140dSpatrick AccelTable<AppleAccelTableStaticOffsetData> &Table) {
273*d415bd75Srobert Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamespaceSection());
274097a140dSpatrick auto *SectionBegin = Asm->createTempSymbol("namespac_begin");
275097a140dSpatrick Asm->OutStreamer->emitLabel(SectionBegin);
276097a140dSpatrick emitAppleAccelTable(Asm.get(), Table, "namespac", SectionBegin);
277097a140dSpatrick }
278097a140dSpatrick
emitAppleNames(AccelTable<AppleAccelTableStaticOffsetData> & Table)279097a140dSpatrick void DwarfStreamer::emitAppleNames(
280097a140dSpatrick AccelTable<AppleAccelTableStaticOffsetData> &Table) {
281*d415bd75Srobert Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamesSection());
282097a140dSpatrick auto *SectionBegin = Asm->createTempSymbol("names_begin");
283097a140dSpatrick Asm->OutStreamer->emitLabel(SectionBegin);
284097a140dSpatrick emitAppleAccelTable(Asm.get(), Table, "names", SectionBegin);
285097a140dSpatrick }
286097a140dSpatrick
emitAppleObjc(AccelTable<AppleAccelTableStaticOffsetData> & Table)287097a140dSpatrick void DwarfStreamer::emitAppleObjc(
288097a140dSpatrick AccelTable<AppleAccelTableStaticOffsetData> &Table) {
289*d415bd75Srobert Asm->OutStreamer->switchSection(MOFI->getDwarfAccelObjCSection());
290097a140dSpatrick auto *SectionBegin = Asm->createTempSymbol("objc_begin");
291097a140dSpatrick Asm->OutStreamer->emitLabel(SectionBegin);
292097a140dSpatrick emitAppleAccelTable(Asm.get(), Table, "objc", SectionBegin);
293097a140dSpatrick }
294097a140dSpatrick
emitAppleTypes(AccelTable<AppleAccelTableStaticTypeData> & Table)295097a140dSpatrick void DwarfStreamer::emitAppleTypes(
296097a140dSpatrick AccelTable<AppleAccelTableStaticTypeData> &Table) {
297*d415bd75Srobert Asm->OutStreamer->switchSection(MOFI->getDwarfAccelTypesSection());
298097a140dSpatrick auto *SectionBegin = Asm->createTempSymbol("types_begin");
299097a140dSpatrick Asm->OutStreamer->emitLabel(SectionBegin);
300097a140dSpatrick emitAppleAccelTable(Asm.get(), Table, "types", SectionBegin);
301097a140dSpatrick }
302097a140dSpatrick
303097a140dSpatrick /// Emit the swift_ast section stored in \p Buffers.
emitSwiftAST(StringRef Buffer)304097a140dSpatrick void DwarfStreamer::emitSwiftAST(StringRef Buffer) {
305097a140dSpatrick MCSection *SwiftASTSection = MOFI->getDwarfSwiftASTSection();
306097a140dSpatrick SwiftASTSection->setAlignment(Align(32));
307*d415bd75Srobert MS->switchSection(SwiftASTSection);
308097a140dSpatrick MS->emitBytes(Buffer);
309097a140dSpatrick }
310097a140dSpatrick
emitSwiftReflectionSection(llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind,StringRef Buffer,uint32_t Alignment,uint32_t Size)311*d415bd75Srobert void DwarfStreamer::emitSwiftReflectionSection(
312*d415bd75Srobert llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind,
313*d415bd75Srobert StringRef Buffer, uint32_t Alignment, uint32_t Size) {
314*d415bd75Srobert MCSection *ReflectionSection =
315*d415bd75Srobert MOFI->getSwift5ReflectionSection(ReflSectionKind);
316*d415bd75Srobert if (ReflectionSection == nullptr)
317*d415bd75Srobert return;
318*d415bd75Srobert ReflectionSection->setAlignment(Align(Alignment));
319*d415bd75Srobert MS->switchSection(ReflectionSection);
320*d415bd75Srobert MS->emitBytes(Buffer);
321097a140dSpatrick }
322097a140dSpatrick
emitDwarfDebugArangesTable(const CompileUnit & Unit,const AddressRanges & LinkedRanges)323*d415bd75Srobert void DwarfStreamer::emitDwarfDebugArangesTable(
324*d415bd75Srobert const CompileUnit &Unit, const AddressRanges &LinkedRanges) {
325097a140dSpatrick unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
326097a140dSpatrick
327*d415bd75Srobert // Make .debug_aranges to be current section.
328*d415bd75Srobert MS->switchSection(MC->getObjectFileInfo()->getDwarfARangesSection());
329097a140dSpatrick
330*d415bd75Srobert // Emit Header.
331097a140dSpatrick MCSymbol *BeginLabel = Asm->createTempSymbol("Barange");
332097a140dSpatrick MCSymbol *EndLabel = Asm->createTempSymbol("Earange");
333097a140dSpatrick
334097a140dSpatrick unsigned HeaderSize =
335097a140dSpatrick sizeof(int32_t) + // Size of contents (w/o this field
336097a140dSpatrick sizeof(int16_t) + // DWARF ARange version number
337097a140dSpatrick sizeof(int32_t) + // Offset of CU in the .debug_info section
338097a140dSpatrick sizeof(int8_t) + // Pointer Size (in bytes)
339097a140dSpatrick sizeof(int8_t); // Segment Size (in bytes)
340097a140dSpatrick
341097a140dSpatrick unsigned TupleSize = AddressSize * 2;
342097a140dSpatrick unsigned Padding = offsetToAlignment(HeaderSize, Align(TupleSize));
343097a140dSpatrick
344097a140dSpatrick Asm->emitLabelDifference(EndLabel, BeginLabel, 4); // Arange length
345097a140dSpatrick Asm->OutStreamer->emitLabel(BeginLabel);
346097a140dSpatrick Asm->emitInt16(dwarf::DW_ARANGES_VERSION); // Version number
347097a140dSpatrick Asm->emitInt32(Unit.getStartOffset()); // Corresponding unit's offset
348097a140dSpatrick Asm->emitInt8(AddressSize); // Address size
349097a140dSpatrick Asm->emitInt8(0); // Segment size
350097a140dSpatrick
351097a140dSpatrick Asm->OutStreamer->emitFill(Padding, 0x0);
352097a140dSpatrick
353*d415bd75Srobert // Emit linked ranges.
354*d415bd75Srobert for (const AddressRange &Range : LinkedRanges) {
355*d415bd75Srobert MS->emitIntValue(Range.start(), AddressSize);
356*d415bd75Srobert MS->emitIntValue(Range.end() - Range.start(), AddressSize);
357097a140dSpatrick }
358097a140dSpatrick
359*d415bd75Srobert // Emit terminator.
360097a140dSpatrick Asm->OutStreamer->emitIntValue(0, AddressSize);
361097a140dSpatrick Asm->OutStreamer->emitIntValue(0, AddressSize);
362097a140dSpatrick Asm->OutStreamer->emitLabel(EndLabel);
363097a140dSpatrick }
364097a140dSpatrick
emitDwarfDebugRangesTableFragment(const CompileUnit & Unit,const AddressRanges & LinkedRanges)365*d415bd75Srobert void DwarfStreamer::emitDwarfDebugRangesTableFragment(
366*d415bd75Srobert const CompileUnit &Unit, const AddressRanges &LinkedRanges) {
367*d415bd75Srobert unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
368097a140dSpatrick
369*d415bd75Srobert // Make .debug_ranges to be current section.
370*d415bd75Srobert MS->switchSection(MC->getObjectFileInfo()->getDwarfRangesSection());
371*d415bd75Srobert
372*d415bd75Srobert // Emit ranges.
373*d415bd75Srobert uint64_t BaseAddress = 0;
374*d415bd75Srobert if (std::optional<uint64_t> LowPC = Unit.getLowPc())
375*d415bd75Srobert BaseAddress = *LowPC;
376*d415bd75Srobert
377*d415bd75Srobert for (const AddressRange &Range : LinkedRanges) {
378*d415bd75Srobert MS->emitIntValue(Range.start() - BaseAddress, AddressSize);
379*d415bd75Srobert MS->emitIntValue(Range.end() - BaseAddress, AddressSize);
380*d415bd75Srobert
381*d415bd75Srobert RangesSectionSize += AddressSize;
382*d415bd75Srobert RangesSectionSize += AddressSize;
383097a140dSpatrick }
384097a140dSpatrick
385097a140dSpatrick // Add the terminator entry.
386097a140dSpatrick MS->emitIntValue(0, AddressSize);
387097a140dSpatrick MS->emitIntValue(0, AddressSize);
388*d415bd75Srobert
389*d415bd75Srobert RangesSectionSize += AddressSize;
390*d415bd75Srobert RangesSectionSize += AddressSize;
391*d415bd75Srobert }
392*d415bd75Srobert
393*d415bd75Srobert /// Emit the debug_aranges contribution of a unit and
394*d415bd75Srobert /// if \p DoDebugRanges is true the debug_range contents for a
395*d415bd75Srobert /// compile_unit level DW_AT_ranges attribute (Which are basically the
396*d415bd75Srobert /// same thing with a different base address).
397*d415bd75Srobert /// Just aggregate all the ranges gathered inside that unit.
emitUnitRangesEntries(CompileUnit & Unit,bool DoDebugRanges)398*d415bd75Srobert void DwarfStreamer::emitUnitRangesEntries(CompileUnit &Unit,
399*d415bd75Srobert bool DoDebugRanges) {
400*d415bd75Srobert const RangesTy &FunctionRanges = Unit.getFunctionRanges();
401*d415bd75Srobert
402*d415bd75Srobert // Linked addresses might end up in a different order.
403*d415bd75Srobert // Build linked address ranges.
404*d415bd75Srobert AddressRanges LinkedRanges;
405*d415bd75Srobert for (size_t Idx = 0; Idx < FunctionRanges.size(); Idx++)
406*d415bd75Srobert LinkedRanges.insert(
407*d415bd75Srobert {FunctionRanges[Idx].first.start() + FunctionRanges[Idx].second,
408*d415bd75Srobert FunctionRanges[Idx].first.end() + FunctionRanges[Idx].second});
409*d415bd75Srobert
410*d415bd75Srobert if (!FunctionRanges.empty())
411*d415bd75Srobert emitDwarfDebugArangesTable(Unit, LinkedRanges);
412*d415bd75Srobert
413*d415bd75Srobert if (DoDebugRanges)
414*d415bd75Srobert emitDwarfDebugRangesTableFragment(Unit, LinkedRanges);
415097a140dSpatrick }
416097a140dSpatrick
417097a140dSpatrick /// Emit location lists for \p Unit and update attributes to point to the new
418097a140dSpatrick /// entries.
emitLocationsForUnit(const CompileUnit & Unit,DWARFContext & Dwarf,std::function<void (StringRef,SmallVectorImpl<uint8_t> &)> ProcessExpr)419097a140dSpatrick void DwarfStreamer::emitLocationsForUnit(
420097a140dSpatrick const CompileUnit &Unit, DWARFContext &Dwarf,
421097a140dSpatrick std::function<void(StringRef, SmallVectorImpl<uint8_t> &)> ProcessExpr) {
422097a140dSpatrick const auto &Attributes = Unit.getLocationAttributes();
423097a140dSpatrick
424097a140dSpatrick if (Attributes.empty())
425097a140dSpatrick return;
426097a140dSpatrick
427*d415bd75Srobert MS->switchSection(MC->getObjectFileInfo()->getDwarfLocSection());
428097a140dSpatrick
429097a140dSpatrick unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
430097a140dSpatrick uint64_t BaseAddressMarker = (AddressSize == 8)
431097a140dSpatrick ? std::numeric_limits<uint64_t>::max()
432097a140dSpatrick : std::numeric_limits<uint32_t>::max();
433097a140dSpatrick const DWARFSection &InputSec = Dwarf.getDWARFObj().getLocSection();
434097a140dSpatrick DataExtractor Data(InputSec.Data, Dwarf.isLittleEndian(), AddressSize);
435097a140dSpatrick DWARFUnit &OrigUnit = Unit.getOrigUnit();
436097a140dSpatrick auto OrigUnitDie = OrigUnit.getUnitDIE(false);
437097a140dSpatrick int64_t UnitPcOffset = 0;
438*d415bd75Srobert if (auto OrigLowPc =
439*d415bd75Srobert dwarf::toAddress(OrigUnitDie.find(dwarf::DW_AT_low_pc))) {
440*d415bd75Srobert assert(Unit.getLowPc());
441*d415bd75Srobert UnitPcOffset = int64_t(*OrigLowPc) - *Unit.getLowPc();
442*d415bd75Srobert }
443097a140dSpatrick
444097a140dSpatrick SmallVector<uint8_t, 32> Buffer;
445097a140dSpatrick for (const auto &Attr : Attributes) {
446097a140dSpatrick uint64_t Offset = Attr.first.get();
447097a140dSpatrick Attr.first.set(LocSectionSize);
448097a140dSpatrick // This is the quantity to add to the old location address to get
449097a140dSpatrick // the correct address for the new one.
450097a140dSpatrick int64_t LocPcOffset = Attr.second + UnitPcOffset;
451097a140dSpatrick while (Data.isValidOffset(Offset)) {
452097a140dSpatrick uint64_t Low = Data.getUnsigned(&Offset, AddressSize);
453097a140dSpatrick uint64_t High = Data.getUnsigned(&Offset, AddressSize);
454097a140dSpatrick LocSectionSize += 2 * AddressSize;
455097a140dSpatrick // End of list entry.
456097a140dSpatrick if (Low == 0 && High == 0) {
457097a140dSpatrick Asm->OutStreamer->emitIntValue(0, AddressSize);
458097a140dSpatrick Asm->OutStreamer->emitIntValue(0, AddressSize);
459097a140dSpatrick break;
460097a140dSpatrick }
461097a140dSpatrick // Base address selection entry.
462097a140dSpatrick if (Low == BaseAddressMarker) {
463097a140dSpatrick Asm->OutStreamer->emitIntValue(BaseAddressMarker, AddressSize);
464097a140dSpatrick Asm->OutStreamer->emitIntValue(High + Attr.second, AddressSize);
465097a140dSpatrick LocPcOffset = 0;
466097a140dSpatrick continue;
467097a140dSpatrick }
468097a140dSpatrick // Location list entry.
469097a140dSpatrick Asm->OutStreamer->emitIntValue(Low + LocPcOffset, AddressSize);
470097a140dSpatrick Asm->OutStreamer->emitIntValue(High + LocPcOffset, AddressSize);
471097a140dSpatrick uint64_t Length = Data.getU16(&Offset);
472097a140dSpatrick Asm->OutStreamer->emitIntValue(Length, 2);
473097a140dSpatrick // Copy the bytes into to the buffer, process them, emit them.
474097a140dSpatrick Buffer.reserve(Length);
475097a140dSpatrick Buffer.resize(0);
476097a140dSpatrick StringRef Input = InputSec.Data.substr(Offset, Length);
477097a140dSpatrick ProcessExpr(Input, Buffer);
478097a140dSpatrick Asm->OutStreamer->emitBytes(
479097a140dSpatrick StringRef((const char *)Buffer.data(), Length));
480097a140dSpatrick Offset += Length;
481097a140dSpatrick LocSectionSize += Length + 2;
482097a140dSpatrick }
483097a140dSpatrick }
484097a140dSpatrick }
485097a140dSpatrick
emitLineTableForUnit(MCDwarfLineTableParams Params,StringRef PrologueBytes,unsigned MinInstLength,std::vector<DWARFDebugLine::Row> & Rows,unsigned PointerSize)486097a140dSpatrick void DwarfStreamer::emitLineTableForUnit(MCDwarfLineTableParams Params,
487097a140dSpatrick StringRef PrologueBytes,
488097a140dSpatrick unsigned MinInstLength,
489097a140dSpatrick std::vector<DWARFDebugLine::Row> &Rows,
490097a140dSpatrick unsigned PointerSize) {
491097a140dSpatrick // Switch to the section where the table will be emitted into.
492*d415bd75Srobert MS->switchSection(MC->getObjectFileInfo()->getDwarfLineSection());
493097a140dSpatrick MCSymbol *LineStartSym = MC->createTempSymbol();
494097a140dSpatrick MCSymbol *LineEndSym = MC->createTempSymbol();
495097a140dSpatrick
496097a140dSpatrick // The first 4 bytes is the total length of the information for this
497097a140dSpatrick // compilation unit (not including these 4 bytes for the length).
498097a140dSpatrick Asm->emitLabelDifference(LineEndSym, LineStartSym, 4);
499097a140dSpatrick Asm->OutStreamer->emitLabel(LineStartSym);
500097a140dSpatrick // Copy Prologue.
501097a140dSpatrick MS->emitBytes(PrologueBytes);
502097a140dSpatrick LineSectionSize += PrologueBytes.size() + 4;
503097a140dSpatrick
504097a140dSpatrick SmallString<128> EncodingBuffer;
505097a140dSpatrick raw_svector_ostream EncodingOS(EncodingBuffer);
506097a140dSpatrick
507097a140dSpatrick if (Rows.empty()) {
508097a140dSpatrick // We only have the dummy entry, dsymutil emits an entry with a 0
509097a140dSpatrick // address in that case.
510097a140dSpatrick MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0,
511097a140dSpatrick EncodingOS);
512097a140dSpatrick MS->emitBytes(EncodingOS.str());
513097a140dSpatrick LineSectionSize += EncodingBuffer.size();
514097a140dSpatrick MS->emitLabel(LineEndSym);
515097a140dSpatrick return;
516097a140dSpatrick }
517097a140dSpatrick
518097a140dSpatrick // Line table state machine fields
519097a140dSpatrick unsigned FileNum = 1;
520097a140dSpatrick unsigned LastLine = 1;
521097a140dSpatrick unsigned Column = 0;
522097a140dSpatrick unsigned IsStatement = 1;
523097a140dSpatrick unsigned Isa = 0;
524097a140dSpatrick uint64_t Address = -1ULL;
525097a140dSpatrick
526097a140dSpatrick unsigned RowsSinceLastSequence = 0;
527097a140dSpatrick
528*d415bd75Srobert for (DWARFDebugLine::Row &Row : Rows) {
529097a140dSpatrick int64_t AddressDelta;
530097a140dSpatrick if (Address == -1ULL) {
531097a140dSpatrick MS->emitIntValue(dwarf::DW_LNS_extended_op, 1);
532097a140dSpatrick MS->emitULEB128IntValue(PointerSize + 1);
533097a140dSpatrick MS->emitIntValue(dwarf::DW_LNE_set_address, 1);
534097a140dSpatrick MS->emitIntValue(Row.Address.Address, PointerSize);
535097a140dSpatrick LineSectionSize += 2 + PointerSize + getULEB128Size(PointerSize + 1);
536097a140dSpatrick AddressDelta = 0;
537097a140dSpatrick } else {
538097a140dSpatrick AddressDelta = (Row.Address.Address - Address) / MinInstLength;
539097a140dSpatrick }
540097a140dSpatrick
541097a140dSpatrick // FIXME: code copied and transformed from MCDwarf.cpp::EmitDwarfLineTable.
542097a140dSpatrick // We should find a way to share this code, but the current compatibility
543097a140dSpatrick // requirement with classic dsymutil makes it hard. Revisit that once this
544097a140dSpatrick // requirement is dropped.
545097a140dSpatrick
546097a140dSpatrick if (FileNum != Row.File) {
547097a140dSpatrick FileNum = Row.File;
548097a140dSpatrick MS->emitIntValue(dwarf::DW_LNS_set_file, 1);
549097a140dSpatrick MS->emitULEB128IntValue(FileNum);
550097a140dSpatrick LineSectionSize += 1 + getULEB128Size(FileNum);
551097a140dSpatrick }
552097a140dSpatrick if (Column != Row.Column) {
553097a140dSpatrick Column = Row.Column;
554097a140dSpatrick MS->emitIntValue(dwarf::DW_LNS_set_column, 1);
555097a140dSpatrick MS->emitULEB128IntValue(Column);
556097a140dSpatrick LineSectionSize += 1 + getULEB128Size(Column);
557097a140dSpatrick }
558097a140dSpatrick
559097a140dSpatrick // FIXME: We should handle the discriminator here, but dsymutil doesn't
560097a140dSpatrick // consider it, thus ignore it for now.
561097a140dSpatrick
562097a140dSpatrick if (Isa != Row.Isa) {
563097a140dSpatrick Isa = Row.Isa;
564097a140dSpatrick MS->emitIntValue(dwarf::DW_LNS_set_isa, 1);
565097a140dSpatrick MS->emitULEB128IntValue(Isa);
566097a140dSpatrick LineSectionSize += 1 + getULEB128Size(Isa);
567097a140dSpatrick }
568097a140dSpatrick if (IsStatement != Row.IsStmt) {
569097a140dSpatrick IsStatement = Row.IsStmt;
570097a140dSpatrick MS->emitIntValue(dwarf::DW_LNS_negate_stmt, 1);
571097a140dSpatrick LineSectionSize += 1;
572097a140dSpatrick }
573097a140dSpatrick if (Row.BasicBlock) {
574097a140dSpatrick MS->emitIntValue(dwarf::DW_LNS_set_basic_block, 1);
575097a140dSpatrick LineSectionSize += 1;
576097a140dSpatrick }
577097a140dSpatrick
578097a140dSpatrick if (Row.PrologueEnd) {
579097a140dSpatrick MS->emitIntValue(dwarf::DW_LNS_set_prologue_end, 1);
580097a140dSpatrick LineSectionSize += 1;
581097a140dSpatrick }
582097a140dSpatrick
583097a140dSpatrick if (Row.EpilogueBegin) {
584097a140dSpatrick MS->emitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1);
585097a140dSpatrick LineSectionSize += 1;
586097a140dSpatrick }
587097a140dSpatrick
588097a140dSpatrick int64_t LineDelta = int64_t(Row.Line) - LastLine;
589097a140dSpatrick if (!Row.EndSequence) {
590097a140dSpatrick MCDwarfLineAddr::Encode(*MC, Params, LineDelta, AddressDelta, EncodingOS);
591097a140dSpatrick MS->emitBytes(EncodingOS.str());
592097a140dSpatrick LineSectionSize += EncodingBuffer.size();
593097a140dSpatrick EncodingBuffer.resize(0);
594097a140dSpatrick Address = Row.Address.Address;
595097a140dSpatrick LastLine = Row.Line;
596097a140dSpatrick RowsSinceLastSequence++;
597097a140dSpatrick } else {
598097a140dSpatrick if (LineDelta) {
599097a140dSpatrick MS->emitIntValue(dwarf::DW_LNS_advance_line, 1);
600097a140dSpatrick MS->emitSLEB128IntValue(LineDelta);
601097a140dSpatrick LineSectionSize += 1 + getSLEB128Size(LineDelta);
602097a140dSpatrick }
603097a140dSpatrick if (AddressDelta) {
604097a140dSpatrick MS->emitIntValue(dwarf::DW_LNS_advance_pc, 1);
605097a140dSpatrick MS->emitULEB128IntValue(AddressDelta);
606097a140dSpatrick LineSectionSize += 1 + getULEB128Size(AddressDelta);
607097a140dSpatrick }
608097a140dSpatrick MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(),
609097a140dSpatrick 0, EncodingOS);
610097a140dSpatrick MS->emitBytes(EncodingOS.str());
611097a140dSpatrick LineSectionSize += EncodingBuffer.size();
612097a140dSpatrick EncodingBuffer.resize(0);
613097a140dSpatrick Address = -1ULL;
614097a140dSpatrick LastLine = FileNum = IsStatement = 1;
615097a140dSpatrick RowsSinceLastSequence = Column = Isa = 0;
616097a140dSpatrick }
617097a140dSpatrick }
618097a140dSpatrick
619097a140dSpatrick if (RowsSinceLastSequence) {
620097a140dSpatrick MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0,
621097a140dSpatrick EncodingOS);
622097a140dSpatrick MS->emitBytes(EncodingOS.str());
623097a140dSpatrick LineSectionSize += EncodingBuffer.size();
624097a140dSpatrick EncodingBuffer.resize(0);
625097a140dSpatrick }
626097a140dSpatrick
627097a140dSpatrick MS->emitLabel(LineEndSym);
628097a140dSpatrick }
629097a140dSpatrick
630097a140dSpatrick /// Copy the debug_line over to the updated binary while unobfuscating the file
631097a140dSpatrick /// names and directories.
translateLineTable(DataExtractor Data,uint64_t Offset)632097a140dSpatrick void DwarfStreamer::translateLineTable(DataExtractor Data, uint64_t Offset) {
633*d415bd75Srobert MS->switchSection(MC->getObjectFileInfo()->getDwarfLineSection());
634097a140dSpatrick StringRef Contents = Data.getData();
635097a140dSpatrick
636097a140dSpatrick // We have to deconstruct the line table header, because it contains to
637097a140dSpatrick // length fields that will need to be updated when we change the length of
638097a140dSpatrick // the files and directories in there.
639097a140dSpatrick unsigned UnitLength = Data.getU32(&Offset);
640097a140dSpatrick uint64_t UnitEnd = Offset + UnitLength;
641097a140dSpatrick MCSymbol *BeginLabel = MC->createTempSymbol();
642097a140dSpatrick MCSymbol *EndLabel = MC->createTempSymbol();
643097a140dSpatrick unsigned Version = Data.getU16(&Offset);
644097a140dSpatrick
645097a140dSpatrick if (Version > 5) {
646097a140dSpatrick warn("Unsupported line table version: dropping contents and not "
647097a140dSpatrick "unobfsucating line table.");
648097a140dSpatrick return;
649097a140dSpatrick }
650097a140dSpatrick
651097a140dSpatrick Asm->emitLabelDifference(EndLabel, BeginLabel, 4);
652097a140dSpatrick Asm->OutStreamer->emitLabel(BeginLabel);
653097a140dSpatrick Asm->emitInt16(Version);
654097a140dSpatrick LineSectionSize += 6;
655097a140dSpatrick
656097a140dSpatrick MCSymbol *HeaderBeginLabel = MC->createTempSymbol();
657097a140dSpatrick MCSymbol *HeaderEndLabel = MC->createTempSymbol();
658097a140dSpatrick Asm->emitLabelDifference(HeaderEndLabel, HeaderBeginLabel, 4);
659097a140dSpatrick Asm->OutStreamer->emitLabel(HeaderBeginLabel);
660097a140dSpatrick Offset += 4;
661097a140dSpatrick LineSectionSize += 4;
662097a140dSpatrick
663097a140dSpatrick uint64_t AfterHeaderLengthOffset = Offset;
664097a140dSpatrick // Skip to the directories.
665097a140dSpatrick Offset += (Version >= 4) ? 5 : 4;
666097a140dSpatrick unsigned OpcodeBase = Data.getU8(&Offset);
667097a140dSpatrick Offset += OpcodeBase - 1;
668097a140dSpatrick Asm->OutStreamer->emitBytes(Contents.slice(AfterHeaderLengthOffset, Offset));
669097a140dSpatrick LineSectionSize += Offset - AfterHeaderLengthOffset;
670097a140dSpatrick
671097a140dSpatrick // Offset points to the first directory.
672097a140dSpatrick while (const char *Dir = Data.getCStr(&Offset)) {
673097a140dSpatrick if (Dir[0] == 0)
674097a140dSpatrick break;
675097a140dSpatrick
676097a140dSpatrick StringRef Translated = Translator(Dir);
677097a140dSpatrick Asm->OutStreamer->emitBytes(Translated);
678097a140dSpatrick Asm->emitInt8(0);
679097a140dSpatrick LineSectionSize += Translated.size() + 1;
680097a140dSpatrick }
681097a140dSpatrick Asm->emitInt8(0);
682097a140dSpatrick LineSectionSize += 1;
683097a140dSpatrick
684097a140dSpatrick while (const char *File = Data.getCStr(&Offset)) {
685097a140dSpatrick if (File[0] == 0)
686097a140dSpatrick break;
687097a140dSpatrick
688097a140dSpatrick StringRef Translated = Translator(File);
689097a140dSpatrick Asm->OutStreamer->emitBytes(Translated);
690097a140dSpatrick Asm->emitInt8(0);
691097a140dSpatrick LineSectionSize += Translated.size() + 1;
692097a140dSpatrick
693097a140dSpatrick uint64_t OffsetBeforeLEBs = Offset;
694097a140dSpatrick Asm->emitULEB128(Data.getULEB128(&Offset));
695097a140dSpatrick Asm->emitULEB128(Data.getULEB128(&Offset));
696097a140dSpatrick Asm->emitULEB128(Data.getULEB128(&Offset));
697097a140dSpatrick LineSectionSize += Offset - OffsetBeforeLEBs;
698097a140dSpatrick }
699097a140dSpatrick Asm->emitInt8(0);
700097a140dSpatrick LineSectionSize += 1;
701097a140dSpatrick
702097a140dSpatrick Asm->OutStreamer->emitLabel(HeaderEndLabel);
703097a140dSpatrick
704097a140dSpatrick // Copy the actual line table program over.
705097a140dSpatrick Asm->OutStreamer->emitBytes(Contents.slice(Offset, UnitEnd));
706097a140dSpatrick LineSectionSize += UnitEnd - Offset;
707097a140dSpatrick
708097a140dSpatrick Asm->OutStreamer->emitLabel(EndLabel);
709097a140dSpatrick Offset = UnitEnd;
710097a140dSpatrick }
711097a140dSpatrick
712097a140dSpatrick /// Emit the pubnames or pubtypes section contribution for \p
713097a140dSpatrick /// Unit into \p Sec. The data is provided in \p Names.
emitPubSectionForUnit(MCSection * Sec,StringRef SecName,const CompileUnit & Unit,const std::vector<CompileUnit::AccelInfo> & Names)714097a140dSpatrick void DwarfStreamer::emitPubSectionForUnit(
715097a140dSpatrick MCSection *Sec, StringRef SecName, const CompileUnit &Unit,
716097a140dSpatrick const std::vector<CompileUnit::AccelInfo> &Names) {
717097a140dSpatrick if (Names.empty())
718097a140dSpatrick return;
719097a140dSpatrick
720097a140dSpatrick // Start the dwarf pubnames section.
721*d415bd75Srobert Asm->OutStreamer->switchSection(Sec);
722097a140dSpatrick MCSymbol *BeginLabel = Asm->createTempSymbol("pub" + SecName + "_begin");
723097a140dSpatrick MCSymbol *EndLabel = Asm->createTempSymbol("pub" + SecName + "_end");
724097a140dSpatrick
725097a140dSpatrick bool HeaderEmitted = false;
726097a140dSpatrick // Emit the pubnames for this compilation unit.
727097a140dSpatrick for (const auto &Name : Names) {
728097a140dSpatrick if (Name.SkipPubSection)
729097a140dSpatrick continue;
730097a140dSpatrick
731097a140dSpatrick if (!HeaderEmitted) {
732097a140dSpatrick // Emit the header.
733097a140dSpatrick Asm->emitLabelDifference(EndLabel, BeginLabel, 4); // Length
734097a140dSpatrick Asm->OutStreamer->emitLabel(BeginLabel);
735097a140dSpatrick Asm->emitInt16(dwarf::DW_PUBNAMES_VERSION); // Version
736097a140dSpatrick Asm->emitInt32(Unit.getStartOffset()); // Unit offset
737097a140dSpatrick Asm->emitInt32(Unit.getNextUnitOffset() - Unit.getStartOffset()); // Size
738097a140dSpatrick HeaderEmitted = true;
739097a140dSpatrick }
740097a140dSpatrick Asm->emitInt32(Name.Die->getOffset());
741097a140dSpatrick
742097a140dSpatrick // Emit the string itself.
743097a140dSpatrick Asm->OutStreamer->emitBytes(Name.Name.getString());
744097a140dSpatrick // Emit a null terminator.
745097a140dSpatrick Asm->emitInt8(0);
746097a140dSpatrick }
747097a140dSpatrick
748097a140dSpatrick if (!HeaderEmitted)
749097a140dSpatrick return;
750097a140dSpatrick Asm->emitInt32(0); // End marker.
751097a140dSpatrick Asm->OutStreamer->emitLabel(EndLabel);
752097a140dSpatrick }
753097a140dSpatrick
754097a140dSpatrick /// Emit .debug_pubnames for \p Unit.
emitPubNamesForUnit(const CompileUnit & Unit)755097a140dSpatrick void DwarfStreamer::emitPubNamesForUnit(const CompileUnit &Unit) {
756097a140dSpatrick emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubNamesSection(),
757097a140dSpatrick "names", Unit, Unit.getPubnames());
758097a140dSpatrick }
759097a140dSpatrick
760097a140dSpatrick /// Emit .debug_pubtypes for \p Unit.
emitPubTypesForUnit(const CompileUnit & Unit)761097a140dSpatrick void DwarfStreamer::emitPubTypesForUnit(const CompileUnit &Unit) {
762097a140dSpatrick emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubTypesSection(),
763097a140dSpatrick "types", Unit, Unit.getPubtypes());
764097a140dSpatrick }
765097a140dSpatrick
766097a140dSpatrick /// Emit a CIE into the debug_frame section.
emitCIE(StringRef CIEBytes)767097a140dSpatrick void DwarfStreamer::emitCIE(StringRef CIEBytes) {
768*d415bd75Srobert MS->switchSection(MC->getObjectFileInfo()->getDwarfFrameSection());
769097a140dSpatrick
770097a140dSpatrick MS->emitBytes(CIEBytes);
771097a140dSpatrick FrameSectionSize += CIEBytes.size();
772097a140dSpatrick }
773097a140dSpatrick
774097a140dSpatrick /// Emit a FDE into the debug_frame section. \p FDEBytes
775097a140dSpatrick /// contains the FDE data without the length, CIE offset and address
776097a140dSpatrick /// which will be replaced with the parameter values.
emitFDE(uint32_t CIEOffset,uint32_t AddrSize,uint64_t Address,StringRef FDEBytes)777097a140dSpatrick void DwarfStreamer::emitFDE(uint32_t CIEOffset, uint32_t AddrSize,
778*d415bd75Srobert uint64_t Address, StringRef FDEBytes) {
779*d415bd75Srobert MS->switchSection(MC->getObjectFileInfo()->getDwarfFrameSection());
780097a140dSpatrick
781097a140dSpatrick MS->emitIntValue(FDEBytes.size() + 4 + AddrSize, 4);
782097a140dSpatrick MS->emitIntValue(CIEOffset, 4);
783097a140dSpatrick MS->emitIntValue(Address, AddrSize);
784097a140dSpatrick MS->emitBytes(FDEBytes);
785097a140dSpatrick FrameSectionSize += FDEBytes.size() + 8 + AddrSize;
786097a140dSpatrick }
787097a140dSpatrick
emitMacroTables(DWARFContext * Context,const Offset2UnitMap & UnitMacroMap,OffsetsStringPool & StringPool)788*d415bd75Srobert void DwarfStreamer::emitMacroTables(DWARFContext *Context,
789*d415bd75Srobert const Offset2UnitMap &UnitMacroMap,
790*d415bd75Srobert OffsetsStringPool &StringPool) {
791*d415bd75Srobert assert(Context != nullptr && "Empty DWARF context");
792*d415bd75Srobert
793*d415bd75Srobert // Check for .debug_macinfo table.
794*d415bd75Srobert if (const DWARFDebugMacro *Table = Context->getDebugMacinfo()) {
795*d415bd75Srobert MS->switchSection(MC->getObjectFileInfo()->getDwarfMacinfoSection());
796*d415bd75Srobert emitMacroTableImpl(Table, UnitMacroMap, StringPool, MacInfoSectionSize);
797*d415bd75Srobert }
798*d415bd75Srobert
799*d415bd75Srobert // Check for .debug_macro table.
800*d415bd75Srobert if (const DWARFDebugMacro *Table = Context->getDebugMacro()) {
801*d415bd75Srobert MS->switchSection(MC->getObjectFileInfo()->getDwarfMacroSection());
802*d415bd75Srobert emitMacroTableImpl(Table, UnitMacroMap, StringPool, MacroSectionSize);
803*d415bd75Srobert }
804*d415bd75Srobert }
805*d415bd75Srobert
emitMacroTableImpl(const DWARFDebugMacro * MacroTable,const Offset2UnitMap & UnitMacroMap,OffsetsStringPool & StringPool,uint64_t & OutOffset)806*d415bd75Srobert void DwarfStreamer::emitMacroTableImpl(const DWARFDebugMacro *MacroTable,
807*d415bd75Srobert const Offset2UnitMap &UnitMacroMap,
808*d415bd75Srobert OffsetsStringPool &StringPool,
809*d415bd75Srobert uint64_t &OutOffset) {
810*d415bd75Srobert bool DefAttributeIsReported = false;
811*d415bd75Srobert bool UndefAttributeIsReported = false;
812*d415bd75Srobert bool ImportAttributeIsReported = false;
813*d415bd75Srobert for (const DWARFDebugMacro::MacroList &List : MacroTable->MacroLists) {
814*d415bd75Srobert Offset2UnitMap::const_iterator UnitIt = UnitMacroMap.find(List.Offset);
815*d415bd75Srobert if (UnitIt == UnitMacroMap.end()) {
816*d415bd75Srobert warn(formatv(
817*d415bd75Srobert "couldn`t find compile unit for the macro table with offset = {0:x}",
818*d415bd75Srobert List.Offset));
819*d415bd75Srobert continue;
820*d415bd75Srobert }
821*d415bd75Srobert
822*d415bd75Srobert // Skip macro table if the unit was not cloned.
823*d415bd75Srobert DIE *OutputUnitDIE = UnitIt->second->getOutputUnitDIE();
824*d415bd75Srobert if (OutputUnitDIE == nullptr)
825*d415bd75Srobert continue;
826*d415bd75Srobert
827*d415bd75Srobert // Update macro attribute of cloned compile unit with the proper offset to
828*d415bd75Srobert // the macro table.
829*d415bd75Srobert bool hasDWARFv5Header = false;
830*d415bd75Srobert for (auto &V : OutputUnitDIE->values()) {
831*d415bd75Srobert if (V.getAttribute() == dwarf::DW_AT_macro_info) {
832*d415bd75Srobert V = DIEValue(V.getAttribute(), V.getForm(), DIEInteger(OutOffset));
833*d415bd75Srobert break;
834*d415bd75Srobert } else if (V.getAttribute() == dwarf::DW_AT_macros) {
835*d415bd75Srobert hasDWARFv5Header = true;
836*d415bd75Srobert V = DIEValue(V.getAttribute(), V.getForm(), DIEInteger(OutOffset));
837*d415bd75Srobert break;
838*d415bd75Srobert }
839*d415bd75Srobert }
840*d415bd75Srobert
841*d415bd75Srobert // Write DWARFv5 header.
842*d415bd75Srobert if (hasDWARFv5Header) {
843*d415bd75Srobert // Write header version.
844*d415bd75Srobert MS->emitIntValue(List.Header.Version, sizeof(List.Header.Version));
845*d415bd75Srobert OutOffset += sizeof(List.Header.Version);
846*d415bd75Srobert
847*d415bd75Srobert uint8_t Flags = List.Header.Flags;
848*d415bd75Srobert
849*d415bd75Srobert // Check for OPCODE_OPERANDS_TABLE.
850*d415bd75Srobert if (Flags &
851*d415bd75Srobert DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE) {
852*d415bd75Srobert Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE;
853*d415bd75Srobert warn("opcode_operands_table is not supported yet.");
854*d415bd75Srobert }
855*d415bd75Srobert
856*d415bd75Srobert // Check for DEBUG_LINE_OFFSET.
857*d415bd75Srobert std::optional<uint64_t> StmtListOffset;
858*d415bd75Srobert if (Flags & DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET) {
859*d415bd75Srobert // Get offset to the line table from the cloned compile unit.
860*d415bd75Srobert for (auto &V : OutputUnitDIE->values()) {
861*d415bd75Srobert if (V.getAttribute() == dwarf::DW_AT_stmt_list) {
862*d415bd75Srobert StmtListOffset = V.getDIEInteger().getValue();
863*d415bd75Srobert break;
864*d415bd75Srobert }
865*d415bd75Srobert }
866*d415bd75Srobert
867*d415bd75Srobert if (!StmtListOffset) {
868*d415bd75Srobert Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET;
869*d415bd75Srobert warn("couldn`t find line table for macro table.");
870*d415bd75Srobert }
871*d415bd75Srobert }
872*d415bd75Srobert
873*d415bd75Srobert // Write flags.
874*d415bd75Srobert MS->emitIntValue(Flags, sizeof(Flags));
875*d415bd75Srobert OutOffset += sizeof(Flags);
876*d415bd75Srobert
877*d415bd75Srobert // Write offset to line table.
878*d415bd75Srobert if (StmtListOffset) {
879*d415bd75Srobert MS->emitIntValue(*StmtListOffset, List.Header.getOffsetByteSize());
880*d415bd75Srobert OutOffset += List.Header.getOffsetByteSize();
881*d415bd75Srobert }
882*d415bd75Srobert }
883*d415bd75Srobert
884*d415bd75Srobert // Write macro entries.
885*d415bd75Srobert for (const DWARFDebugMacro::Entry &MacroEntry : List.Macros) {
886*d415bd75Srobert if (MacroEntry.Type == 0) {
887*d415bd75Srobert OutOffset += MS->emitULEB128IntValue(MacroEntry.Type);
888*d415bd75Srobert continue;
889*d415bd75Srobert }
890*d415bd75Srobert
891*d415bd75Srobert uint8_t MacroType = MacroEntry.Type;
892*d415bd75Srobert switch (MacroType) {
893*d415bd75Srobert default: {
894*d415bd75Srobert bool HasVendorSpecificExtension =
895*d415bd75Srobert (!hasDWARFv5Header && MacroType == dwarf::DW_MACINFO_vendor_ext) ||
896*d415bd75Srobert (hasDWARFv5Header && (MacroType >= dwarf::DW_MACRO_lo_user &&
897*d415bd75Srobert MacroType <= dwarf::DW_MACRO_hi_user));
898*d415bd75Srobert
899*d415bd75Srobert if (HasVendorSpecificExtension) {
900*d415bd75Srobert // Write macinfo type.
901*d415bd75Srobert MS->emitIntValue(MacroType, 1);
902*d415bd75Srobert OutOffset++;
903*d415bd75Srobert
904*d415bd75Srobert // Write vendor extension constant.
905*d415bd75Srobert OutOffset += MS->emitULEB128IntValue(MacroEntry.ExtConstant);
906*d415bd75Srobert
907*d415bd75Srobert // Write vendor extension string.
908*d415bd75Srobert StringRef String = MacroEntry.ExtStr;
909*d415bd75Srobert MS->emitBytes(String);
910*d415bd75Srobert MS->emitIntValue(0, 1);
911*d415bd75Srobert OutOffset += String.size() + 1;
912*d415bd75Srobert } else
913*d415bd75Srobert warn("unknown macro type. skip.");
914*d415bd75Srobert } break;
915*d415bd75Srobert // debug_macro and debug_macinfo share some common encodings.
916*d415bd75Srobert // DW_MACRO_define == DW_MACINFO_define
917*d415bd75Srobert // DW_MACRO_undef == DW_MACINFO_undef
918*d415bd75Srobert // DW_MACRO_start_file == DW_MACINFO_start_file
919*d415bd75Srobert // DW_MACRO_end_file == DW_MACINFO_end_file
920*d415bd75Srobert // For readibility/uniformity we are using DW_MACRO_*.
921*d415bd75Srobert case dwarf::DW_MACRO_define:
922*d415bd75Srobert case dwarf::DW_MACRO_undef: {
923*d415bd75Srobert // Write macinfo type.
924*d415bd75Srobert MS->emitIntValue(MacroType, 1);
925*d415bd75Srobert OutOffset++;
926*d415bd75Srobert
927*d415bd75Srobert // Write source line.
928*d415bd75Srobert OutOffset += MS->emitULEB128IntValue(MacroEntry.Line);
929*d415bd75Srobert
930*d415bd75Srobert // Write macro string.
931*d415bd75Srobert StringRef String = MacroEntry.MacroStr;
932*d415bd75Srobert MS->emitBytes(String);
933*d415bd75Srobert MS->emitIntValue(0, 1);
934*d415bd75Srobert OutOffset += String.size() + 1;
935*d415bd75Srobert } break;
936*d415bd75Srobert case dwarf::DW_MACRO_define_strp:
937*d415bd75Srobert case dwarf::DW_MACRO_undef_strp:
938*d415bd75Srobert case dwarf::DW_MACRO_define_strx:
939*d415bd75Srobert case dwarf::DW_MACRO_undef_strx: {
940*d415bd75Srobert assert(UnitIt->second->getOrigUnit().getVersion() >= 5);
941*d415bd75Srobert
942*d415bd75Srobert // DW_MACRO_*_strx forms are not supported currently.
943*d415bd75Srobert // Convert to *_strp.
944*d415bd75Srobert switch (MacroType) {
945*d415bd75Srobert case dwarf::DW_MACRO_define_strx: {
946*d415bd75Srobert MacroType = dwarf::DW_MACRO_define_strp;
947*d415bd75Srobert if (!DefAttributeIsReported) {
948*d415bd75Srobert warn("DW_MACRO_define_strx unsupported yet. Convert to "
949*d415bd75Srobert "DW_MACRO_define_strp.");
950*d415bd75Srobert DefAttributeIsReported = true;
951*d415bd75Srobert }
952*d415bd75Srobert } break;
953*d415bd75Srobert case dwarf::DW_MACRO_undef_strx: {
954*d415bd75Srobert MacroType = dwarf::DW_MACRO_undef_strp;
955*d415bd75Srobert if (!UndefAttributeIsReported) {
956*d415bd75Srobert warn("DW_MACRO_undef_strx unsupported yet. Convert to "
957*d415bd75Srobert "DW_MACRO_undef_strp.");
958*d415bd75Srobert UndefAttributeIsReported = true;
959*d415bd75Srobert }
960*d415bd75Srobert } break;
961*d415bd75Srobert default:
962*d415bd75Srobert // Nothing to do.
963*d415bd75Srobert break;
964*d415bd75Srobert }
965*d415bd75Srobert
966*d415bd75Srobert // Write macinfo type.
967*d415bd75Srobert MS->emitIntValue(MacroType, 1);
968*d415bd75Srobert OutOffset++;
969*d415bd75Srobert
970*d415bd75Srobert // Write source line.
971*d415bd75Srobert OutOffset += MS->emitULEB128IntValue(MacroEntry.Line);
972*d415bd75Srobert
973*d415bd75Srobert // Write macro string.
974*d415bd75Srobert DwarfStringPoolEntryRef EntryRef =
975*d415bd75Srobert StringPool.getEntry(MacroEntry.MacroStr);
976*d415bd75Srobert MS->emitIntValue(EntryRef.getOffset(), List.Header.getOffsetByteSize());
977*d415bd75Srobert OutOffset += List.Header.getOffsetByteSize();
978*d415bd75Srobert break;
979*d415bd75Srobert }
980*d415bd75Srobert case dwarf::DW_MACRO_start_file: {
981*d415bd75Srobert // Write macinfo type.
982*d415bd75Srobert MS->emitIntValue(MacroType, 1);
983*d415bd75Srobert OutOffset++;
984*d415bd75Srobert // Write source line.
985*d415bd75Srobert OutOffset += MS->emitULEB128IntValue(MacroEntry.Line);
986*d415bd75Srobert // Write source file id.
987*d415bd75Srobert OutOffset += MS->emitULEB128IntValue(MacroEntry.File);
988*d415bd75Srobert } break;
989*d415bd75Srobert case dwarf::DW_MACRO_end_file: {
990*d415bd75Srobert // Write macinfo type.
991*d415bd75Srobert MS->emitIntValue(MacroType, 1);
992*d415bd75Srobert OutOffset++;
993*d415bd75Srobert } break;
994*d415bd75Srobert case dwarf::DW_MACRO_import:
995*d415bd75Srobert case dwarf::DW_MACRO_import_sup: {
996*d415bd75Srobert if (!ImportAttributeIsReported) {
997*d415bd75Srobert warn("DW_MACRO_import and DW_MACRO_import_sup are unsupported yet. "
998*d415bd75Srobert "remove.");
999*d415bd75Srobert ImportAttributeIsReported = true;
1000*d415bd75Srobert }
1001*d415bd75Srobert } break;
1002*d415bd75Srobert }
1003*d415bd75Srobert }
1004*d415bd75Srobert }
1005*d415bd75Srobert }
1006*d415bd75Srobert
1007097a140dSpatrick } // namespace llvm
1008