[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / llvm / lib / DWARFLinker / DWARFStreamer.cpp
blob2c6aba7225adccec27edfc5ac1cffcff9303571b
1 //===- DwarfStreamer.cpp --------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "llvm/DWARFLinker/DWARFStreamer.h"
10 #include "llvm/CodeGen/NonRelocatableStringpool.h"
11 #include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
12 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
13 #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
14 #include "llvm/MC/MCAsmBackend.h"
15 #include "llvm/MC/MCCodeEmitter.h"
16 #include "llvm/MC/MCDwarf.h"
17 #include "llvm/MC/MCObjectWriter.h"
18 #include "llvm/MC/MCSection.h"
19 #include "llvm/MC/MCStreamer.h"
20 #include "llvm/MC/MCSubtargetInfo.h"
21 #include "llvm/MC/MCTargetOptions.h"
22 #include "llvm/MC/MCTargetOptionsCommandFlags.h"
23 #include "llvm/MC/TargetRegistry.h"
24 #include "llvm/Support/FormatVariadic.h"
25 #include "llvm/Support/LEB128.h"
26 #include "llvm/Target/TargetOptions.h"
27 #include "llvm/TargetParser/Triple.h"
29 namespace llvm {
31 Error DwarfStreamer::init(Triple TheTriple,
32 StringRef Swift5ReflectionSegmentName) {
33 std::string ErrorStr;
34 std::string TripleName;
36 // Get the target.
37 const Target *TheTarget =
38 TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);
39 if (!TheTarget)
40 return createStringError(std::errc::invalid_argument, ErrorStr.c_str());
42 TripleName = TheTriple.getTriple();
44 // Create all the MC Objects.
45 MRI.reset(TheTarget->createMCRegInfo(TripleName));
46 if (!MRI)
47 return createStringError(std::errc::invalid_argument,
48 "no register info for target %s",
49 TripleName.c_str());
51 MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();
52 MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
53 if (!MAI)
54 return createStringError(std::errc::invalid_argument,
55 "no asm info for target %s", TripleName.c_str());
57 MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
58 if (!MSTI)
59 return createStringError(std::errc::invalid_argument,
60 "no subtarget info for target %s",
61 TripleName.c_str());
63 MC.reset(new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get(), nullptr,
64 nullptr, true, Swift5ReflectionSegmentName));
65 MOFI.reset(TheTarget->createMCObjectFileInfo(*MC, /*PIC=*/false, false));
66 MC->setObjectFileInfo(MOFI.get());
68 MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, MCOptions);
69 if (!MAB)
70 return createStringError(std::errc::invalid_argument,
71 "no asm backend for target %s",
72 TripleName.c_str());
74 MII.reset(TheTarget->createMCInstrInfo());
75 if (!MII)
76 return createStringError(std::errc::invalid_argument,
77 "no instr info info for target %s",
78 TripleName.c_str());
80 MCE = TheTarget->createMCCodeEmitter(*MII, *MC);
81 if (!MCE)
82 return createStringError(std::errc::invalid_argument,
83 "no code emitter for target %s",
84 TripleName.c_str());
86 switch (OutFileType) {
87 case DWARFLinker::OutputFileType::Assembly: {
88 MIP = TheTarget->createMCInstPrinter(TheTriple, MAI->getAssemblerDialect(),
89 *MAI, *MII, *MRI);
90 MS = TheTarget->createAsmStreamer(
91 *MC, std::make_unique<formatted_raw_ostream>(OutFile), true, true, MIP,
92 std::unique_ptr<MCCodeEmitter>(MCE), std::unique_ptr<MCAsmBackend>(MAB),
93 true);
94 break;
96 case DWARFLinker::OutputFileType::Object: {
97 MS = TheTarget->createMCObjectStreamer(
98 TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB),
99 MAB->createObjectWriter(OutFile), std::unique_ptr<MCCodeEmitter>(MCE),
100 *MSTI, MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible,
101 /*DWARFMustBeAtTheEnd*/ false);
102 break;
106 if (!MS)
107 return createStringError(std::errc::invalid_argument,
108 "no object streamer for target %s",
109 TripleName.c_str());
111 // Finally create the AsmPrinter we'll use to emit the DIEs.
112 TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(),
113 std::nullopt));
114 if (!TM)
115 return createStringError(std::errc::invalid_argument,
116 "no target machine for target %s",
117 TripleName.c_str());
119 Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS)));
120 if (!Asm)
121 return createStringError(std::errc::invalid_argument,
122 "no asm printer for target %s",
123 TripleName.c_str());
124 Asm->setDwarfUsesRelocationsAcrossSections(false);
126 RangesSectionSize = 0;
127 RngListsSectionSize = 0;
128 LocSectionSize = 0;
129 LocListsSectionSize = 0;
130 LineSectionSize = 0;
131 FrameSectionSize = 0;
132 DebugInfoSectionSize = 0;
133 MacInfoSectionSize = 0;
134 MacroSectionSize = 0;
136 return Error::success();
139 void DwarfStreamer::finish() { MS->finish(); }
141 void DwarfStreamer::switchToDebugInfoSection(unsigned DwarfVersion) {
142 MS->switchSection(MOFI->getDwarfInfoSection());
143 MC->setDwarfVersion(DwarfVersion);
146 /// Emit the compilation unit header for \p Unit in the debug_info section.
148 /// A Dwarf 4 section header is encoded as:
149 /// uint32_t Unit length (omitting this field)
150 /// uint16_t Version
151 /// uint32_t Abbreviation table offset
152 /// uint8_t Address size
153 /// Leading to a total of 11 bytes.
155 /// A Dwarf 5 section header is encoded as:
156 /// uint32_t Unit length (omitting this field)
157 /// uint16_t Version
158 /// uint8_t Unit type
159 /// uint8_t Address size
160 /// uint32_t Abbreviation table offset
161 /// Leading to a total of 12 bytes.
162 void DwarfStreamer::emitCompileUnitHeader(CompileUnit &Unit,
163 unsigned DwarfVersion) {
164 switchToDebugInfoSection(DwarfVersion);
166 /// The start of the unit within its section.
167 Unit.setLabelBegin(Asm->createTempSymbol("cu_begin"));
168 Asm->OutStreamer->emitLabel(Unit.getLabelBegin());
170 // Emit size of content not including length itself. The size has already
171 // been computed in CompileUnit::computeOffsets(). Subtract 4 to that size to
172 // account for the length field.
173 Asm->emitInt32(Unit.getNextUnitOffset() - Unit.getStartOffset() - 4);
174 Asm->emitInt16(DwarfVersion);
176 if (DwarfVersion >= 5) {
177 Asm->emitInt8(dwarf::DW_UT_compile);
178 Asm->emitInt8(Unit.getOrigUnit().getAddressByteSize());
179 // We share one abbreviations table across all units so it's always at the
180 // start of the section.
181 Asm->emitInt32(0);
182 DebugInfoSectionSize += 12;
183 } else {
184 // We share one abbreviations table across all units so it's always at the
185 // start of the section.
186 Asm->emitInt32(0);
187 Asm->emitInt8(Unit.getOrigUnit().getAddressByteSize());
188 DebugInfoSectionSize += 11;
191 // Remember this CU.
192 EmittedUnits.push_back({Unit.getUniqueID(), Unit.getLabelBegin()});
195 /// Emit the \p Abbrevs array as the shared abbreviation table
196 /// for the linked Dwarf file.
197 void DwarfStreamer::emitAbbrevs(
198 const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs,
199 unsigned DwarfVersion) {
200 MS->switchSection(MOFI->getDwarfAbbrevSection());
201 MC->setDwarfVersion(DwarfVersion);
202 Asm->emitDwarfAbbrevs(Abbrevs);
205 /// Recursively emit the DIE tree rooted at \p Die.
206 void DwarfStreamer::emitDIE(DIE &Die) {
207 MS->switchSection(MOFI->getDwarfInfoSection());
208 Asm->emitDwarfDIE(Die);
209 DebugInfoSectionSize += Die.getSize();
212 /// Emit contents of section SecName From Obj.
213 void DwarfStreamer::emitSectionContents(StringRef SecData, StringRef SecName) {
214 MCSection *Section =
215 StringSwitch<MCSection *>(SecName)
216 .Case("debug_line", MC->getObjectFileInfo()->getDwarfLineSection())
217 .Case("debug_loc", MC->getObjectFileInfo()->getDwarfLocSection())
218 .Case("debug_ranges",
219 MC->getObjectFileInfo()->getDwarfRangesSection())
220 .Case("debug_frame", MC->getObjectFileInfo()->getDwarfFrameSection())
221 .Case("debug_aranges",
222 MC->getObjectFileInfo()->getDwarfARangesSection())
223 .Case("debug_addr", MC->getObjectFileInfo()->getDwarfAddrSection())
224 .Case("debug_rnglists",
225 MC->getObjectFileInfo()->getDwarfRnglistsSection())
226 .Case("debug_loclists",
227 MC->getObjectFileInfo()->getDwarfLoclistsSection())
228 .Default(nullptr);
230 if (Section) {
231 MS->switchSection(Section);
233 MS->emitBytes(SecData);
237 /// Emit the debug_str section stored in \p Pool.
238 void DwarfStreamer::emitStrings(const NonRelocatableStringpool &Pool) {
239 Asm->OutStreamer->switchSection(MOFI->getDwarfStrSection());
240 std::vector<DwarfStringPoolEntryRef> Entries = Pool.getEntriesForEmission();
241 for (auto Entry : Entries) {
242 // Emit the string itself.
243 Asm->OutStreamer->emitBytes(Entry.getString());
244 // Emit a null terminator.
245 Asm->emitInt8(0);
249 /// Emit the debug string offset table described by \p StringOffsets into the
250 /// .debug_str_offsets table.
251 void DwarfStreamer::emitStringOffsets(
252 const SmallVector<uint64_t> &StringOffsets, uint16_t TargetDWARFVersion) {
254 if (TargetDWARFVersion < 5 || StringOffsets.empty())
255 return;
257 Asm->OutStreamer->switchSection(MOFI->getDwarfStrOffSection());
259 MCSymbol *BeginLabel = Asm->createTempSymbol("Bdebugstroff");
260 MCSymbol *EndLabel = Asm->createTempSymbol("Edebugstroff");
262 // Length.
263 Asm->emitLabelDifference(EndLabel, BeginLabel, sizeof(uint32_t));
264 Asm->OutStreamer->emitLabel(BeginLabel);
265 StrOffsetSectionSize += sizeof(uint32_t);
267 // Version.
268 MS->emitInt16(5);
269 StrOffsetSectionSize += sizeof(uint16_t);
271 // Padding.
272 MS->emitInt16(0);
273 StrOffsetSectionSize += sizeof(uint16_t);
275 for (auto Off : StringOffsets) {
276 Asm->OutStreamer->emitInt32(Off);
277 StrOffsetSectionSize += sizeof(uint32_t);
279 Asm->OutStreamer->emitLabel(EndLabel);
282 /// Emit the debug_line_str section stored in \p Pool.
283 void DwarfStreamer::emitLineStrings(const NonRelocatableStringpool &Pool) {
284 Asm->OutStreamer->switchSection(MOFI->getDwarfLineStrSection());
285 std::vector<DwarfStringPoolEntryRef> Entries = Pool.getEntriesForEmission();
286 for (auto Entry : Entries) {
287 // Emit the string itself.
288 Asm->OutStreamer->emitBytes(Entry.getString());
289 // Emit a null terminator.
290 Asm->emitInt8(0);
294 void DwarfStreamer::emitDebugNames(DWARF5AccelTable &Table) {
295 if (EmittedUnits.empty())
296 return;
298 // Build up data structures needed to emit this section.
299 std::vector<std::variant<MCSymbol *, uint64_t>> CompUnits;
300 DenseMap<unsigned, size_t> UniqueIdToCuMap;
301 unsigned Id = 0;
302 for (auto &CU : EmittedUnits) {
303 CompUnits.push_back(CU.LabelBegin);
304 // We might be omitting CUs, so we need to remap them.
305 UniqueIdToCuMap[CU.ID] = Id++;
308 Asm->OutStreamer->switchSection(MOFI->getDwarfDebugNamesSection());
309 emitDWARF5AccelTable(Asm.get(), Table, CompUnits,
310 [&UniqueIdToCuMap](const DWARF5AccelTableData &Entry) {
311 return UniqueIdToCuMap[Entry.getUnitID()];
315 void DwarfStreamer::emitAppleNamespaces(
316 AccelTable<AppleAccelTableStaticOffsetData> &Table) {
317 Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamespaceSection());
318 auto *SectionBegin = Asm->createTempSymbol("namespac_begin");
319 Asm->OutStreamer->emitLabel(SectionBegin);
320 emitAppleAccelTable(Asm.get(), Table, "namespac", SectionBegin);
323 void DwarfStreamer::emitAppleNames(
324 AccelTable<AppleAccelTableStaticOffsetData> &Table) {
325 Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamesSection());
326 auto *SectionBegin = Asm->createTempSymbol("names_begin");
327 Asm->OutStreamer->emitLabel(SectionBegin);
328 emitAppleAccelTable(Asm.get(), Table, "names", SectionBegin);
331 void DwarfStreamer::emitAppleObjc(
332 AccelTable<AppleAccelTableStaticOffsetData> &Table) {
333 Asm->OutStreamer->switchSection(MOFI->getDwarfAccelObjCSection());
334 auto *SectionBegin = Asm->createTempSymbol("objc_begin");
335 Asm->OutStreamer->emitLabel(SectionBegin);
336 emitAppleAccelTable(Asm.get(), Table, "objc", SectionBegin);
339 void DwarfStreamer::emitAppleTypes(
340 AccelTable<AppleAccelTableStaticTypeData> &Table) {
341 Asm->OutStreamer->switchSection(MOFI->getDwarfAccelTypesSection());
342 auto *SectionBegin = Asm->createTempSymbol("types_begin");
343 Asm->OutStreamer->emitLabel(SectionBegin);
344 emitAppleAccelTable(Asm.get(), Table, "types", SectionBegin);
347 /// Emit the swift_ast section stored in \p Buffers.
348 void DwarfStreamer::emitSwiftAST(StringRef Buffer) {
349 MCSection *SwiftASTSection = MOFI->getDwarfSwiftASTSection();
350 SwiftASTSection->setAlignment(Align(32));
351 MS->switchSection(SwiftASTSection);
352 MS->emitBytes(Buffer);
355 void DwarfStreamer::emitSwiftReflectionSection(
356 llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind,
357 StringRef Buffer, uint32_t Alignment, uint32_t Size) {
358 MCSection *ReflectionSection =
359 MOFI->getSwift5ReflectionSection(ReflSectionKind);
360 if (ReflectionSection == nullptr)
361 return;
362 ReflectionSection->setAlignment(Align(Alignment));
363 MS->switchSection(ReflectionSection);
364 MS->emitBytes(Buffer);
367 void DwarfStreamer::emitDwarfDebugArangesTable(
368 const CompileUnit &Unit, const AddressRanges &LinkedRanges) {
369 unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
371 // Make .debug_aranges to be current section.
372 MS->switchSection(MC->getObjectFileInfo()->getDwarfARangesSection());
374 // Emit Header.
375 MCSymbol *BeginLabel = Asm->createTempSymbol("Barange");
376 MCSymbol *EndLabel = Asm->createTempSymbol("Earange");
378 unsigned HeaderSize =
379 sizeof(int32_t) + // Size of contents (w/o this field
380 sizeof(int16_t) + // DWARF ARange version number
381 sizeof(int32_t) + // Offset of CU in the .debug_info section
382 sizeof(int8_t) + // Pointer Size (in bytes)
383 sizeof(int8_t); // Segment Size (in bytes)
385 unsigned TupleSize = AddressSize * 2;
386 unsigned Padding = offsetToAlignment(HeaderSize, Align(TupleSize));
388 Asm->emitLabelDifference(EndLabel, BeginLabel, 4); // Arange length
389 Asm->OutStreamer->emitLabel(BeginLabel);
390 Asm->emitInt16(dwarf::DW_ARANGES_VERSION); // Version number
391 Asm->emitInt32(Unit.getStartOffset()); // Corresponding unit's offset
392 Asm->emitInt8(AddressSize); // Address size
393 Asm->emitInt8(0); // Segment size
395 Asm->OutStreamer->emitFill(Padding, 0x0);
397 // Emit linked ranges.
398 for (const AddressRange &Range : LinkedRanges) {
399 MS->emitIntValue(Range.start(), AddressSize);
400 MS->emitIntValue(Range.end() - Range.start(), AddressSize);
403 // Emit terminator.
404 Asm->OutStreamer->emitIntValue(0, AddressSize);
405 Asm->OutStreamer->emitIntValue(0, AddressSize);
406 Asm->OutStreamer->emitLabel(EndLabel);
409 void DwarfStreamer::emitDwarfDebugRangesTableFragment(
410 const CompileUnit &Unit, const AddressRanges &LinkedRanges,
411 PatchLocation Patch) {
412 Patch.set(RangesSectionSize);
414 // Make .debug_ranges to be current section.
415 MS->switchSection(MC->getObjectFileInfo()->getDwarfRangesSection());
416 unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
418 // Emit ranges.
419 uint64_t BaseAddress = 0;
420 if (std::optional<uint64_t> LowPC = Unit.getLowPc())
421 BaseAddress = *LowPC;
423 for (const AddressRange &Range : LinkedRanges) {
424 MS->emitIntValue(Range.start() - BaseAddress, AddressSize);
425 MS->emitIntValue(Range.end() - BaseAddress, AddressSize);
427 RangesSectionSize += AddressSize;
428 RangesSectionSize += AddressSize;
431 // Add the terminator entry.
432 MS->emitIntValue(0, AddressSize);
433 MS->emitIntValue(0, AddressSize);
435 RangesSectionSize += AddressSize;
436 RangesSectionSize += AddressSize;
439 MCSymbol *
440 DwarfStreamer::emitDwarfDebugRangeListHeader(const CompileUnit &Unit) {
441 if (Unit.getOrigUnit().getVersion() < 5)
442 return nullptr;
444 // Make .debug_rnglists to be current section.
445 MS->switchSection(MC->getObjectFileInfo()->getDwarfRnglistsSection());
447 MCSymbol *BeginLabel = Asm->createTempSymbol("Brnglists");
448 MCSymbol *EndLabel = Asm->createTempSymbol("Ernglists");
449 unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
451 // Length
452 Asm->emitLabelDifference(EndLabel, BeginLabel, sizeof(uint32_t));
453 Asm->OutStreamer->emitLabel(BeginLabel);
454 RngListsSectionSize += sizeof(uint32_t);
456 // Version.
457 MS->emitInt16(5);
458 RngListsSectionSize += sizeof(uint16_t);
460 // Address size.
461 MS->emitInt8(AddressSize);
462 RngListsSectionSize++;
464 // Seg_size
465 MS->emitInt8(0);
466 RngListsSectionSize++;
468 // Offset entry count
469 MS->emitInt32(0);
470 RngListsSectionSize += sizeof(uint32_t);
472 return EndLabel;
475 void DwarfStreamer::emitDwarfDebugRangeListFragment(
476 const CompileUnit &Unit, const AddressRanges &LinkedRanges,
477 PatchLocation Patch, DebugDieValuePool &AddrPool) {
478 if (Unit.getOrigUnit().getVersion() < 5) {
479 emitDwarfDebugRangesTableFragment(Unit, LinkedRanges, Patch);
480 return;
483 emitDwarfDebugRngListsTableFragment(Unit, LinkedRanges, Patch, AddrPool);
486 void DwarfStreamer::emitDwarfDebugRangeListFooter(const CompileUnit &Unit,
487 MCSymbol *EndLabel) {
488 if (Unit.getOrigUnit().getVersion() < 5)
489 return;
491 // Make .debug_rnglists to be current section.
492 MS->switchSection(MC->getObjectFileInfo()->getDwarfRnglistsSection());
494 if (EndLabel != nullptr)
495 Asm->OutStreamer->emitLabel(EndLabel);
498 void DwarfStreamer::emitDwarfDebugRngListsTableFragment(
499 const CompileUnit &Unit, const AddressRanges &LinkedRanges,
500 PatchLocation Patch, DebugDieValuePool &AddrPool) {
501 Patch.set(RngListsSectionSize);
503 // Make .debug_rnglists to be current section.
504 MS->switchSection(MC->getObjectFileInfo()->getDwarfRnglistsSection());
505 std::optional<uint64_t> BaseAddress;
507 for (const AddressRange &Range : LinkedRanges) {
509 if (!BaseAddress) {
510 BaseAddress = Range.start();
512 // Emit base address.
513 MS->emitInt8(dwarf::DW_RLE_base_addressx);
514 RngListsSectionSize += 1;
515 RngListsSectionSize +=
516 MS->emitULEB128IntValue(AddrPool.getValueIndex(*BaseAddress));
519 // Emit type of entry.
520 MS->emitInt8(dwarf::DW_RLE_offset_pair);
521 RngListsSectionSize += 1;
523 // Emit start offset relative to base address.
524 RngListsSectionSize +=
525 MS->emitULEB128IntValue(Range.start() - *BaseAddress);
527 // Emit end offset relative to base address.
528 RngListsSectionSize += MS->emitULEB128IntValue(Range.end() - *BaseAddress);
531 // Emit the terminator entry.
532 MS->emitInt8(dwarf::DW_RLE_end_of_list);
533 RngListsSectionSize += 1;
536 /// Emit debug locations(.debug_loc, .debug_loclists) header.
537 MCSymbol *DwarfStreamer::emitDwarfDebugLocListHeader(const CompileUnit &Unit) {
538 if (Unit.getOrigUnit().getVersion() < 5)
539 return nullptr;
541 // Make .debug_loclists the current section.
542 MS->switchSection(MC->getObjectFileInfo()->getDwarfLoclistsSection());
544 MCSymbol *BeginLabel = Asm->createTempSymbol("Bloclists");
545 MCSymbol *EndLabel = Asm->createTempSymbol("Eloclists");
546 unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
548 // Length
549 Asm->emitLabelDifference(EndLabel, BeginLabel, sizeof(uint32_t));
550 Asm->OutStreamer->emitLabel(BeginLabel);
551 LocListsSectionSize += sizeof(uint32_t);
553 // Version.
554 MS->emitInt16(5);
555 LocListsSectionSize += sizeof(uint16_t);
557 // Address size.
558 MS->emitInt8(AddressSize);
559 LocListsSectionSize++;
561 // Seg_size
562 MS->emitInt8(0);
563 LocListsSectionSize++;
565 // Offset entry count
566 MS->emitInt32(0);
567 LocListsSectionSize += sizeof(uint32_t);
569 return EndLabel;
572 /// Emit debug locations(.debug_loc, .debug_loclists) fragment.
573 void DwarfStreamer::emitDwarfDebugLocListFragment(
574 const CompileUnit &Unit,
575 const DWARFLocationExpressionsVector &LinkedLocationExpression,
576 PatchLocation Patch, DebugDieValuePool &AddrPool) {
577 if (Unit.getOrigUnit().getVersion() < 5) {
578 emitDwarfDebugLocTableFragment(Unit, LinkedLocationExpression, Patch);
579 return;
582 emitDwarfDebugLocListsTableFragment(Unit, LinkedLocationExpression, Patch,
583 AddrPool);
586 /// Emit debug locations(.debug_loc, .debug_loclists) footer.
587 void DwarfStreamer::emitDwarfDebugLocListFooter(const CompileUnit &Unit,
588 MCSymbol *EndLabel) {
589 if (Unit.getOrigUnit().getVersion() < 5)
590 return;
592 // Make .debug_loclists the current section.
593 MS->switchSection(MC->getObjectFileInfo()->getDwarfLoclistsSection());
595 if (EndLabel != nullptr)
596 Asm->OutStreamer->emitLabel(EndLabel);
599 /// Emit piece of .debug_loc for \p LinkedLocationExpression.
600 void DwarfStreamer::emitDwarfDebugLocTableFragment(
601 const CompileUnit &Unit,
602 const DWARFLocationExpressionsVector &LinkedLocationExpression,
603 PatchLocation Patch) {
604 Patch.set(LocSectionSize);
606 // Make .debug_loc to be current section.
607 MS->switchSection(MC->getObjectFileInfo()->getDwarfLocSection());
608 unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
610 // Emit ranges.
611 uint64_t BaseAddress = 0;
612 if (std::optional<uint64_t> LowPC = Unit.getLowPc())
613 BaseAddress = *LowPC;
615 for (const DWARFLocationExpression &LocExpression :
616 LinkedLocationExpression) {
617 if (LocExpression.Range) {
618 MS->emitIntValue(LocExpression.Range->LowPC - BaseAddress, AddressSize);
619 MS->emitIntValue(LocExpression.Range->HighPC - BaseAddress, AddressSize);
621 LocSectionSize += AddressSize;
622 LocSectionSize += AddressSize;
625 Asm->OutStreamer->emitIntValue(LocExpression.Expr.size(), 2);
626 Asm->OutStreamer->emitBytes(StringRef(
627 (const char *)LocExpression.Expr.data(), LocExpression.Expr.size()));
628 LocSectionSize += LocExpression.Expr.size() + 2;
631 // Add the terminator entry.
632 MS->emitIntValue(0, AddressSize);
633 MS->emitIntValue(0, AddressSize);
635 LocSectionSize += AddressSize;
636 LocSectionSize += AddressSize;
639 /// Emit .debug_addr header.
640 MCSymbol *DwarfStreamer::emitDwarfDebugAddrsHeader(const CompileUnit &Unit) {
642 // Make .debug_addr the current section.
643 MS->switchSection(MC->getObjectFileInfo()->getDwarfAddrSection());
645 MCSymbol *BeginLabel = Asm->createTempSymbol("Bdebugaddr");
646 MCSymbol *EndLabel = Asm->createTempSymbol("Edebugaddr");
647 unsigned AddrSize = Unit.getOrigUnit().getAddressByteSize();
649 // Emit length.
650 Asm->emitLabelDifference(EndLabel, BeginLabel, sizeof(uint32_t));
651 Asm->OutStreamer->emitLabel(BeginLabel);
652 AddrSectionSize += sizeof(uint32_t);
654 // Emit version.
655 Asm->emitInt16(5);
656 AddrSectionSize += 2;
658 // Emit address size.
659 Asm->emitInt8(AddrSize);
660 AddrSectionSize += 1;
662 // Emit segment size.
663 Asm->emitInt8(0);
664 AddrSectionSize += 1;
666 return EndLabel;
669 /// Emit the .debug_addr addresses stored in \p Addrs.
670 void DwarfStreamer::emitDwarfDebugAddrs(const SmallVector<uint64_t> &Addrs,
671 uint8_t AddrSize) {
672 Asm->OutStreamer->switchSection(MOFI->getDwarfAddrSection());
673 for (auto Addr : Addrs) {
674 Asm->OutStreamer->emitIntValue(Addr, AddrSize);
675 AddrSectionSize += AddrSize;
679 /// Emit .debug_addr footer.
680 void DwarfStreamer::emitDwarfDebugAddrsFooter(const CompileUnit &Unit,
681 MCSymbol *EndLabel) {
683 // Make .debug_addr the current section.
684 MS->switchSection(MC->getObjectFileInfo()->getDwarfAddrSection());
686 if (EndLabel != nullptr)
687 Asm->OutStreamer->emitLabel(EndLabel);
690 /// Emit piece of .debug_loclists for \p LinkedLocationExpression.
691 void DwarfStreamer::emitDwarfDebugLocListsTableFragment(
692 const CompileUnit &Unit,
693 const DWARFLocationExpressionsVector &LinkedLocationExpression,
694 PatchLocation Patch, DebugDieValuePool &AddrPool) {
695 Patch.set(LocListsSectionSize);
697 // Make .debug_loclists the current section.
698 MS->switchSection(MC->getObjectFileInfo()->getDwarfLoclistsSection());
699 std::optional<uint64_t> BaseAddress;
701 for (const DWARFLocationExpression &LocExpression :
702 LinkedLocationExpression) {
703 if (LocExpression.Range) {
705 if (!BaseAddress) {
707 BaseAddress = LocExpression.Range->LowPC;
709 // Emit base address.
710 MS->emitInt8(dwarf::DW_LLE_base_addressx);
711 LocListsSectionSize += 1;
712 LocListsSectionSize +=
713 MS->emitULEB128IntValue(AddrPool.getValueIndex(*BaseAddress));
716 // Emit type of entry.
717 MS->emitInt8(dwarf::DW_LLE_offset_pair);
718 LocListsSectionSize += 1;
720 // Emit start offset relative to base address.
721 LocListsSectionSize +=
722 MS->emitULEB128IntValue(LocExpression.Range->LowPC - *BaseAddress);
724 // Emit end offset relative to base address.
725 LocListsSectionSize +=
726 MS->emitULEB128IntValue(LocExpression.Range->HighPC - *BaseAddress);
727 } else {
728 // Emit type of entry.
729 MS->emitInt8(dwarf::DW_LLE_default_location);
730 LocListsSectionSize += 1;
733 LocListsSectionSize += MS->emitULEB128IntValue(LocExpression.Expr.size());
734 Asm->OutStreamer->emitBytes(StringRef(
735 (const char *)LocExpression.Expr.data(), LocExpression.Expr.size()));
736 LocListsSectionSize += LocExpression.Expr.size();
739 // Emit the terminator entry.
740 MS->emitInt8(dwarf::DW_LLE_end_of_list);
741 LocListsSectionSize += 1;
744 void DwarfStreamer::emitLineTableForUnit(
745 const DWARFDebugLine::LineTable &LineTable, const CompileUnit &Unit,
746 OffsetsStringPool &DebugStrPool, OffsetsStringPool &DebugLineStrPool) {
747 // Switch to the section where the table will be emitted into.
748 MS->switchSection(MC->getObjectFileInfo()->getDwarfLineSection());
750 MCSymbol *LineStartSym = MC->createTempSymbol();
751 MCSymbol *LineEndSym = MC->createTempSymbol();
753 // unit_length.
754 if (LineTable.Prologue.FormParams.Format == dwarf::DwarfFormat::DWARF64) {
755 MS->emitInt32(dwarf::DW_LENGTH_DWARF64);
756 LineSectionSize += 4;
758 emitLabelDifference(LineEndSym, LineStartSym,
759 LineTable.Prologue.FormParams.Format, LineSectionSize);
760 Asm->OutStreamer->emitLabel(LineStartSym);
762 // Emit prologue.
763 emitLineTablePrologue(LineTable.Prologue, DebugStrPool, DebugLineStrPool);
765 // Emit rows.
766 emitLineTableRows(LineTable, LineEndSym,
767 Unit.getOrigUnit().getAddressByteSize());
770 void DwarfStreamer::emitLineTablePrologue(const DWARFDebugLine::Prologue &P,
771 OffsetsStringPool &DebugStrPool,
772 OffsetsStringPool &DebugLineStrPool) {
773 MCSymbol *PrologueStartSym = MC->createTempSymbol();
774 MCSymbol *PrologueEndSym = MC->createTempSymbol();
776 // version (uhalf).
777 MS->emitInt16(P.getVersion());
778 LineSectionSize += 2;
779 if (P.getVersion() == 5) {
780 // address_size (ubyte).
781 MS->emitInt8(P.getAddressSize());
782 LineSectionSize += 1;
784 // segment_selector_size (ubyte).
785 MS->emitInt8(P.SegSelectorSize);
786 LineSectionSize += 1;
789 // header_length.
790 emitLabelDifference(PrologueEndSym, PrologueStartSym, P.FormParams.Format,
791 LineSectionSize);
793 Asm->OutStreamer->emitLabel(PrologueStartSym);
794 emitLineTableProloguePayload(P, DebugStrPool, DebugLineStrPool);
795 Asm->OutStreamer->emitLabel(PrologueEndSym);
798 void DwarfStreamer::emitLineTablePrologueV2IncludeAndFileTable(
799 const DWARFDebugLine::Prologue &P, OffsetsStringPool &DebugStrPool,
800 OffsetsStringPool &DebugLineStrPool) {
801 // include_directories (sequence of path names).
802 for (const DWARFFormValue &Include : P.IncludeDirectories)
803 emitLineTableString(P, Include, DebugStrPool, DebugLineStrPool);
804 // The last entry is followed by a single null byte.
805 MS->emitInt8(0);
806 LineSectionSize += 1;
808 // file_names (sequence of file entries).
809 for (const DWARFDebugLine::FileNameEntry &File : P.FileNames) {
810 // A null-terminated string containing the full or relative path name of a
811 // source file.
812 emitLineTableString(P, File.Name, DebugStrPool, DebugLineStrPool);
813 // An unsigned LEB128 number representing the directory index of a directory
814 // in the include_directories section.
815 LineSectionSize += MS->emitULEB128IntValue(File.DirIdx);
816 // An unsigned LEB128 number representing the (implementation-defined) time
817 // of last modification for the file, or 0 if not available.
818 LineSectionSize += MS->emitULEB128IntValue(File.ModTime);
819 // An unsigned LEB128 number representing the length in bytes of the file,
820 // or 0 if not available.
821 LineSectionSize += MS->emitULEB128IntValue(File.Length);
823 // The last entry is followed by a single null byte.
824 MS->emitInt8(0);
825 LineSectionSize += 1;
828 void DwarfStreamer::emitLineTablePrologueV5IncludeAndFileTable(
829 const DWARFDebugLine::Prologue &P, OffsetsStringPool &DebugStrPool,
830 OffsetsStringPool &DebugLineStrPool) {
831 if (P.IncludeDirectories.empty()) {
832 // directory_entry_format_count(ubyte).
833 MS->emitInt8(0);
834 LineSectionSize += 1;
835 } else {
836 // directory_entry_format_count(ubyte).
837 MS->emitInt8(1);
838 LineSectionSize += 1;
840 // directory_entry_format (sequence of ULEB128 pairs).
841 LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_path);
842 LineSectionSize +=
843 MS->emitULEB128IntValue(P.IncludeDirectories[0].getForm());
846 // directories_count (ULEB128).
847 LineSectionSize += MS->emitULEB128IntValue(P.IncludeDirectories.size());
848 // directories (sequence of directory names).
849 for (auto Include : P.IncludeDirectories)
850 emitLineTableString(P, Include, DebugStrPool, DebugLineStrPool);
852 if (P.FileNames.empty()) {
853 // file_name_entry_format_count (ubyte).
854 MS->emitInt8(0);
855 LineSectionSize += 1;
856 } else {
857 // file_name_entry_format_count (ubyte).
858 MS->emitInt8(2);
859 LineSectionSize += 1;
861 // file_name_entry_format (sequence of ULEB128 pairs).
862 LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_path);
863 LineSectionSize += MS->emitULEB128IntValue(P.FileNames[0].Name.getForm());
865 LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_directory_index);
866 LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_FORM_data1);
869 // file_names_count (ULEB128).
870 LineSectionSize += MS->emitULEB128IntValue(P.FileNames.size());
872 // file_names (sequence of file name entries).
873 for (auto File : P.FileNames) {
874 emitLineTableString(P, File.Name, DebugStrPool, DebugLineStrPool);
875 MS->emitInt8(File.DirIdx);
876 LineSectionSize += 1;
880 void DwarfStreamer::emitLineTableString(const DWARFDebugLine::Prologue &P,
881 const DWARFFormValue &String,
882 OffsetsStringPool &DebugStrPool,
883 OffsetsStringPool &DebugLineStrPool) {
884 std::optional<const char *> StringVal = dwarf::toString(String);
885 if (!StringVal) {
886 warn("Cann't read string from line table.");
887 return;
890 switch (String.getForm()) {
891 case dwarf::DW_FORM_string: {
892 StringRef TranslatedString =
893 (Translator) ? Translator(*StringVal) : *StringVal;
894 Asm->OutStreamer->emitBytes(TranslatedString.data());
895 Asm->emitInt8(0);
896 LineSectionSize += TranslatedString.size() + 1;
897 } break;
898 case dwarf::DW_FORM_strp:
899 case dwarf::DW_FORM_line_strp: {
900 DwarfStringPoolEntryRef StringRef =
901 String.getForm() == dwarf::DW_FORM_strp
902 ? DebugStrPool.getEntry(*StringVal)
903 : DebugLineStrPool.getEntry(*StringVal);
905 emitIntOffset(StringRef.getOffset(), P.FormParams.Format, LineSectionSize);
906 } break;
907 default:
908 warn("Unsupported string form inside line table.");
909 break;
913 void DwarfStreamer::emitLineTableProloguePayload(
914 const DWARFDebugLine::Prologue &P, OffsetsStringPool &DebugStrPool,
915 OffsetsStringPool &DebugLineStrPool) {
916 // minimum_instruction_length (ubyte).
917 MS->emitInt8(P.MinInstLength);
918 LineSectionSize += 1;
919 if (P.FormParams.Version >= 4) {
920 // maximum_operations_per_instruction (ubyte).
921 MS->emitInt8(P.MaxOpsPerInst);
922 LineSectionSize += 1;
924 // default_is_stmt (ubyte).
925 MS->emitInt8(P.DefaultIsStmt);
926 LineSectionSize += 1;
927 // line_base (sbyte).
928 MS->emitInt8(P.LineBase);
929 LineSectionSize += 1;
930 // line_range (ubyte).
931 MS->emitInt8(P.LineRange);
932 LineSectionSize += 1;
933 // opcode_base (ubyte).
934 MS->emitInt8(P.OpcodeBase);
935 LineSectionSize += 1;
937 // standard_opcode_lengths (array of ubyte).
938 for (auto Length : P.StandardOpcodeLengths) {
939 MS->emitInt8(Length);
940 LineSectionSize += 1;
943 if (P.FormParams.Version < 5)
944 emitLineTablePrologueV2IncludeAndFileTable(P, DebugStrPool,
945 DebugLineStrPool);
946 else
947 emitLineTablePrologueV5IncludeAndFileTable(P, DebugStrPool,
948 DebugLineStrPool);
951 void DwarfStreamer::emitLineTableRows(
952 const DWARFDebugLine::LineTable &LineTable, MCSymbol *LineEndSym,
953 unsigned AddressByteSize) {
955 MCDwarfLineTableParams Params;
956 Params.DWARF2LineOpcodeBase = LineTable.Prologue.OpcodeBase;
957 Params.DWARF2LineBase = LineTable.Prologue.LineBase;
958 Params.DWARF2LineRange = LineTable.Prologue.LineRange;
960 SmallString<128> EncodingBuffer;
962 if (LineTable.Rows.empty()) {
963 // We only have the dummy entry, dsymutil emits an entry with a 0
964 // address in that case.
965 MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0,
966 EncodingBuffer);
967 MS->emitBytes(EncodingBuffer);
968 LineSectionSize += EncodingBuffer.size();
969 MS->emitLabel(LineEndSym);
970 return;
973 // Line table state machine fields
974 unsigned FileNum = 1;
975 unsigned LastLine = 1;
976 unsigned Column = 0;
977 unsigned IsStatement = 1;
978 unsigned Isa = 0;
979 uint64_t Address = -1ULL;
981 unsigned RowsSinceLastSequence = 0;
983 for (const DWARFDebugLine::Row &Row : LineTable.Rows) {
984 int64_t AddressDelta;
985 if (Address == -1ULL) {
986 MS->emitIntValue(dwarf::DW_LNS_extended_op, 1);
987 MS->emitULEB128IntValue(AddressByteSize + 1);
988 MS->emitIntValue(dwarf::DW_LNE_set_address, 1);
989 MS->emitIntValue(Row.Address.Address, AddressByteSize);
990 LineSectionSize +=
991 2 + AddressByteSize + getULEB128Size(AddressByteSize + 1);
992 AddressDelta = 0;
993 } else {
994 AddressDelta =
995 (Row.Address.Address - Address) / LineTable.Prologue.MinInstLength;
998 // FIXME: code copied and transformed from MCDwarf.cpp::EmitDwarfLineTable.
999 // We should find a way to share this code, but the current compatibility
1000 // requirement with classic dsymutil makes it hard. Revisit that once this
1001 // requirement is dropped.
1003 if (FileNum != Row.File) {
1004 FileNum = Row.File;
1005 MS->emitIntValue(dwarf::DW_LNS_set_file, 1);
1006 MS->emitULEB128IntValue(FileNum);
1007 LineSectionSize += 1 + getULEB128Size(FileNum);
1009 if (Column != Row.Column) {
1010 Column = Row.Column;
1011 MS->emitIntValue(dwarf::DW_LNS_set_column, 1);
1012 MS->emitULEB128IntValue(Column);
1013 LineSectionSize += 1 + getULEB128Size(Column);
1016 // FIXME: We should handle the discriminator here, but dsymutil doesn't
1017 // consider it, thus ignore it for now.
1019 if (Isa != Row.Isa) {
1020 Isa = Row.Isa;
1021 MS->emitIntValue(dwarf::DW_LNS_set_isa, 1);
1022 MS->emitULEB128IntValue(Isa);
1023 LineSectionSize += 1 + getULEB128Size(Isa);
1025 if (IsStatement != Row.IsStmt) {
1026 IsStatement = Row.IsStmt;
1027 MS->emitIntValue(dwarf::DW_LNS_negate_stmt, 1);
1028 LineSectionSize += 1;
1030 if (Row.BasicBlock) {
1031 MS->emitIntValue(dwarf::DW_LNS_set_basic_block, 1);
1032 LineSectionSize += 1;
1035 if (Row.PrologueEnd) {
1036 MS->emitIntValue(dwarf::DW_LNS_set_prologue_end, 1);
1037 LineSectionSize += 1;
1040 if (Row.EpilogueBegin) {
1041 MS->emitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1);
1042 LineSectionSize += 1;
1045 int64_t LineDelta = int64_t(Row.Line) - LastLine;
1046 if (!Row.EndSequence) {
1047 MCDwarfLineAddr::encode(*MC, Params, LineDelta, AddressDelta,
1048 EncodingBuffer);
1049 MS->emitBytes(EncodingBuffer);
1050 LineSectionSize += EncodingBuffer.size();
1051 EncodingBuffer.resize(0);
1052 Address = Row.Address.Address;
1053 LastLine = Row.Line;
1054 RowsSinceLastSequence++;
1055 } else {
1056 if (LineDelta) {
1057 MS->emitIntValue(dwarf::DW_LNS_advance_line, 1);
1058 MS->emitSLEB128IntValue(LineDelta);
1059 LineSectionSize += 1 + getSLEB128Size(LineDelta);
1061 if (AddressDelta) {
1062 MS->emitIntValue(dwarf::DW_LNS_advance_pc, 1);
1063 MS->emitULEB128IntValue(AddressDelta);
1064 LineSectionSize += 1 + getULEB128Size(AddressDelta);
1066 MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(),
1067 0, EncodingBuffer);
1068 MS->emitBytes(EncodingBuffer);
1069 LineSectionSize += EncodingBuffer.size();
1070 EncodingBuffer.resize(0);
1071 Address = -1ULL;
1072 LastLine = FileNum = IsStatement = 1;
1073 RowsSinceLastSequence = Column = Isa = 0;
1077 if (RowsSinceLastSequence) {
1078 MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0,
1079 EncodingBuffer);
1080 MS->emitBytes(EncodingBuffer);
1081 LineSectionSize += EncodingBuffer.size();
1082 EncodingBuffer.resize(0);
1085 MS->emitLabel(LineEndSym);
1088 void DwarfStreamer::emitIntOffset(uint64_t Offset, dwarf::DwarfFormat Format,
1089 uint64_t &SectionSize) {
1090 uint8_t Size = dwarf::getDwarfOffsetByteSize(Format);
1091 MS->emitIntValue(Offset, Size);
1092 SectionSize += Size;
1095 void DwarfStreamer::emitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo,
1096 dwarf::DwarfFormat Format,
1097 uint64_t &SectionSize) {
1098 uint8_t Size = dwarf::getDwarfOffsetByteSize(Format);
1099 Asm->emitLabelDifference(Hi, Lo, Size);
1100 SectionSize += Size;
1103 /// Emit the pubnames or pubtypes section contribution for \p
1104 /// Unit into \p Sec. The data is provided in \p Names.
1105 void DwarfStreamer::emitPubSectionForUnit(
1106 MCSection *Sec, StringRef SecName, const CompileUnit &Unit,
1107 const std::vector<CompileUnit::AccelInfo> &Names) {
1108 if (Names.empty())
1109 return;
1111 // Start the dwarf pubnames section.
1112 Asm->OutStreamer->switchSection(Sec);
1113 MCSymbol *BeginLabel = Asm->createTempSymbol("pub" + SecName + "_begin");
1114 MCSymbol *EndLabel = Asm->createTempSymbol("pub" + SecName + "_end");
1116 bool HeaderEmitted = false;
1117 // Emit the pubnames for this compilation unit.
1118 for (const auto &Name : Names) {
1119 if (Name.SkipPubSection)
1120 continue;
1122 if (!HeaderEmitted) {
1123 // Emit the header.
1124 Asm->emitLabelDifference(EndLabel, BeginLabel, 4); // Length
1125 Asm->OutStreamer->emitLabel(BeginLabel);
1126 Asm->emitInt16(dwarf::DW_PUBNAMES_VERSION); // Version
1127 Asm->emitInt32(Unit.getStartOffset()); // Unit offset
1128 Asm->emitInt32(Unit.getNextUnitOffset() - Unit.getStartOffset()); // Size
1129 HeaderEmitted = true;
1131 Asm->emitInt32(Name.Die->getOffset());
1133 // Emit the string itself.
1134 Asm->OutStreamer->emitBytes(Name.Name.getString());
1135 // Emit a null terminator.
1136 Asm->emitInt8(0);
1139 if (!HeaderEmitted)
1140 return;
1141 Asm->emitInt32(0); // End marker.
1142 Asm->OutStreamer->emitLabel(EndLabel);
1145 /// Emit .debug_pubnames for \p Unit.
1146 void DwarfStreamer::emitPubNamesForUnit(const CompileUnit &Unit) {
1147 emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubNamesSection(),
1148 "names", Unit, Unit.getPubnames());
1151 /// Emit .debug_pubtypes for \p Unit.
1152 void DwarfStreamer::emitPubTypesForUnit(const CompileUnit &Unit) {
1153 emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubTypesSection(),
1154 "types", Unit, Unit.getPubtypes());
1157 /// Emit a CIE into the debug_frame section.
1158 void DwarfStreamer::emitCIE(StringRef CIEBytes) {
1159 MS->switchSection(MC->getObjectFileInfo()->getDwarfFrameSection());
1161 MS->emitBytes(CIEBytes);
1162 FrameSectionSize += CIEBytes.size();
1165 /// Emit a FDE into the debug_frame section. \p FDEBytes
1166 /// contains the FDE data without the length, CIE offset and address
1167 /// which will be replaced with the parameter values.
1168 void DwarfStreamer::emitFDE(uint32_t CIEOffset, uint32_t AddrSize,
1169 uint64_t Address, StringRef FDEBytes) {
1170 MS->switchSection(MC->getObjectFileInfo()->getDwarfFrameSection());
1172 MS->emitIntValue(FDEBytes.size() + 4 + AddrSize, 4);
1173 MS->emitIntValue(CIEOffset, 4);
1174 MS->emitIntValue(Address, AddrSize);
1175 MS->emitBytes(FDEBytes);
1176 FrameSectionSize += FDEBytes.size() + 8 + AddrSize;
1179 void DwarfStreamer::emitMacroTables(DWARFContext *Context,
1180 const Offset2UnitMap &UnitMacroMap,
1181 OffsetsStringPool &StringPool) {
1182 assert(Context != nullptr && "Empty DWARF context");
1184 // Check for .debug_macinfo table.
1185 if (const DWARFDebugMacro *Table = Context->getDebugMacinfo()) {
1186 MS->switchSection(MC->getObjectFileInfo()->getDwarfMacinfoSection());
1187 emitMacroTableImpl(Table, UnitMacroMap, StringPool, MacInfoSectionSize);
1190 // Check for .debug_macro table.
1191 if (const DWARFDebugMacro *Table = Context->getDebugMacro()) {
1192 MS->switchSection(MC->getObjectFileInfo()->getDwarfMacroSection());
1193 emitMacroTableImpl(Table, UnitMacroMap, StringPool, MacroSectionSize);
1197 void DwarfStreamer::emitMacroTableImpl(const DWARFDebugMacro *MacroTable,
1198 const Offset2UnitMap &UnitMacroMap,
1199 OffsetsStringPool &StringPool,
1200 uint64_t &OutOffset) {
1201 bool DefAttributeIsReported = false;
1202 bool UndefAttributeIsReported = false;
1203 bool ImportAttributeIsReported = false;
1204 for (const DWARFDebugMacro::MacroList &List : MacroTable->MacroLists) {
1205 Offset2UnitMap::const_iterator UnitIt = UnitMacroMap.find(List.Offset);
1206 if (UnitIt == UnitMacroMap.end()) {
1207 warn(formatv(
1208 "couldn`t find compile unit for the macro table with offset = {0:x}",
1209 List.Offset));
1210 continue;
1213 // Skip macro table if the unit was not cloned.
1214 DIE *OutputUnitDIE = UnitIt->second->getOutputUnitDIE();
1215 if (OutputUnitDIE == nullptr)
1216 continue;
1218 // Update macro attribute of cloned compile unit with the proper offset to
1219 // the macro table.
1220 bool hasDWARFv5Header = false;
1221 for (auto &V : OutputUnitDIE->values()) {
1222 if (V.getAttribute() == dwarf::DW_AT_macro_info) {
1223 V = DIEValue(V.getAttribute(), V.getForm(), DIEInteger(OutOffset));
1224 break;
1225 } else if (V.getAttribute() == dwarf::DW_AT_macros) {
1226 hasDWARFv5Header = true;
1227 V = DIEValue(V.getAttribute(), V.getForm(), DIEInteger(OutOffset));
1228 break;
1232 // Write DWARFv5 header.
1233 if (hasDWARFv5Header) {
1234 // Write header version.
1235 MS->emitIntValue(List.Header.Version, sizeof(List.Header.Version));
1236 OutOffset += sizeof(List.Header.Version);
1238 uint8_t Flags = List.Header.Flags;
1240 // Check for OPCODE_OPERANDS_TABLE.
1241 if (Flags &
1242 DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE) {
1243 Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE;
1244 warn("opcode_operands_table is not supported yet.");
1247 // Check for DEBUG_LINE_OFFSET.
1248 std::optional<uint64_t> StmtListOffset;
1249 if (Flags & DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET) {
1250 // Get offset to the line table from the cloned compile unit.
1251 for (auto &V : OutputUnitDIE->values()) {
1252 if (V.getAttribute() == dwarf::DW_AT_stmt_list) {
1253 StmtListOffset = V.getDIEInteger().getValue();
1254 break;
1258 if (!StmtListOffset) {
1259 Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET;
1260 warn("couldn`t find line table for macro table.");
1264 // Write flags.
1265 MS->emitIntValue(Flags, sizeof(Flags));
1266 OutOffset += sizeof(Flags);
1268 // Write offset to line table.
1269 if (StmtListOffset) {
1270 MS->emitIntValue(*StmtListOffset, List.Header.getOffsetByteSize());
1271 OutOffset += List.Header.getOffsetByteSize();
1275 // Write macro entries.
1276 for (const DWARFDebugMacro::Entry &MacroEntry : List.Macros) {
1277 if (MacroEntry.Type == 0) {
1278 OutOffset += MS->emitULEB128IntValue(MacroEntry.Type);
1279 continue;
1282 uint8_t MacroType = MacroEntry.Type;
1283 switch (MacroType) {
1284 default: {
1285 bool HasVendorSpecificExtension =
1286 (!hasDWARFv5Header && MacroType == dwarf::DW_MACINFO_vendor_ext) ||
1287 (hasDWARFv5Header && (MacroType >= dwarf::DW_MACRO_lo_user &&
1288 MacroType <= dwarf::DW_MACRO_hi_user));
1290 if (HasVendorSpecificExtension) {
1291 // Write macinfo type.
1292 MS->emitIntValue(MacroType, 1);
1293 OutOffset++;
1295 // Write vendor extension constant.
1296 OutOffset += MS->emitULEB128IntValue(MacroEntry.ExtConstant);
1298 // Write vendor extension string.
1299 StringRef String = MacroEntry.ExtStr;
1300 MS->emitBytes(String);
1301 MS->emitIntValue(0, 1);
1302 OutOffset += String.size() + 1;
1303 } else
1304 warn("unknown macro type. skip.");
1305 } break;
1306 // debug_macro and debug_macinfo share some common encodings.
1307 // DW_MACRO_define == DW_MACINFO_define
1308 // DW_MACRO_undef == DW_MACINFO_undef
1309 // DW_MACRO_start_file == DW_MACINFO_start_file
1310 // DW_MACRO_end_file == DW_MACINFO_end_file
1311 // For readibility/uniformity we are using DW_MACRO_*.
1312 case dwarf::DW_MACRO_define:
1313 case dwarf::DW_MACRO_undef: {
1314 // Write macinfo type.
1315 MS->emitIntValue(MacroType, 1);
1316 OutOffset++;
1318 // Write source line.
1319 OutOffset += MS->emitULEB128IntValue(MacroEntry.Line);
1321 // Write macro string.
1322 StringRef String = MacroEntry.MacroStr;
1323 MS->emitBytes(String);
1324 MS->emitIntValue(0, 1);
1325 OutOffset += String.size() + 1;
1326 } break;
1327 case dwarf::DW_MACRO_define_strp:
1328 case dwarf::DW_MACRO_undef_strp:
1329 case dwarf::DW_MACRO_define_strx:
1330 case dwarf::DW_MACRO_undef_strx: {
1331 assert(UnitIt->second->getOrigUnit().getVersion() >= 5);
1333 // DW_MACRO_*_strx forms are not supported currently.
1334 // Convert to *_strp.
1335 switch (MacroType) {
1336 case dwarf::DW_MACRO_define_strx: {
1337 MacroType = dwarf::DW_MACRO_define_strp;
1338 if (!DefAttributeIsReported) {
1339 warn("DW_MACRO_define_strx unsupported yet. Convert to "
1340 "DW_MACRO_define_strp.");
1341 DefAttributeIsReported = true;
1343 } break;
1344 case dwarf::DW_MACRO_undef_strx: {
1345 MacroType = dwarf::DW_MACRO_undef_strp;
1346 if (!UndefAttributeIsReported) {
1347 warn("DW_MACRO_undef_strx unsupported yet. Convert to "
1348 "DW_MACRO_undef_strp.");
1349 UndefAttributeIsReported = true;
1351 } break;
1352 default:
1353 // Nothing to do.
1354 break;
1357 // Write macinfo type.
1358 MS->emitIntValue(MacroType, 1);
1359 OutOffset++;
1361 // Write source line.
1362 OutOffset += MS->emitULEB128IntValue(MacroEntry.Line);
1364 // Write macro string.
1365 DwarfStringPoolEntryRef EntryRef =
1366 StringPool.getEntry(MacroEntry.MacroStr);
1367 MS->emitIntValue(EntryRef.getOffset(), List.Header.getOffsetByteSize());
1368 OutOffset += List.Header.getOffsetByteSize();
1369 break;
1371 case dwarf::DW_MACRO_start_file: {
1372 // Write macinfo type.
1373 MS->emitIntValue(MacroType, 1);
1374 OutOffset++;
1375 // Write source line.
1376 OutOffset += MS->emitULEB128IntValue(MacroEntry.Line);
1377 // Write source file id.
1378 OutOffset += MS->emitULEB128IntValue(MacroEntry.File);
1379 } break;
1380 case dwarf::DW_MACRO_end_file: {
1381 // Write macinfo type.
1382 MS->emitIntValue(MacroType, 1);
1383 OutOffset++;
1384 } break;
1385 case dwarf::DW_MACRO_import:
1386 case dwarf::DW_MACRO_import_sup: {
1387 if (!ImportAttributeIsReported) {
1388 warn("DW_MACRO_import and DW_MACRO_import_sup are unsupported yet. "
1389 "remove.");
1390 ImportAttributeIsReported = true;
1392 } break;
1398 } // namespace llvm