xref: /llvm-project/bolt/lib/Core/DebugData.cpp (revision a34c753fe709a624f5b087397fb05adeac2311e4)
1 //===- DebugData.cpp - Representation and writing of debugging information. ==//
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 //===----------------------------------------------------------------------===//
8 //
9 //===----------------------------------------------------------------------===//
10 
11 #include "bolt/Core/DebugData.h"
12 #include "bolt/Core/BinaryBasicBlock.h"
13 #include "bolt/Core/BinaryFunction.h"
14 #include "bolt/Utils/Utils.h"
15 #include "llvm/MC/MCObjectStreamer.h"
16 #include "llvm/MC/MCSymbol.h"
17 #include "llvm/Support/CommandLine.h"
18 #include "llvm/Support/EndianStream.h"
19 #include "llvm/Support/LEB128.h"
20 #include <algorithm>
21 #include <cassert>
22 #include <cstdint>
23 #include <limits>
24 
25 #undef  DEBUG_TYPE
26 #define DEBUG_TYPE "bolt-debug-info"
27 
28 namespace opts {
29 extern llvm::cl::opt<unsigned> Verbosity;
30 }
31 
32 namespace llvm {
33 namespace bolt {
34 
35 const DebugLineTableRowRef DebugLineTableRowRef::NULL_ROW{0, 0};
36 
37 namespace {
38 
39 // Writes address ranges to Writer as pairs of 64-bit (address, size).
40 // If RelativeRange is true, assumes the address range to be written must be of
41 // the form (begin address, range size), otherwise (begin address, end address).
42 // Terminates the list by writing a pair of two zeroes.
43 // Returns the number of written bytes.
44 uint64_t writeAddressRanges(
45     raw_svector_ostream &Stream,
46     const DebugAddressRangesVector &AddressRanges,
47     const bool WriteRelativeRanges = false) {
48   for (const DebugAddressRange &Range : AddressRanges) {
49     support::endian::write(Stream, Range.LowPC, support::little);
50     support::endian::write(
51         Stream, WriteRelativeRanges ? Range.HighPC - Range.LowPC : Range.HighPC,
52         support::little);
53   }
54   // Finish with 0 entries.
55   support::endian::write(Stream, 0ULL, support::little);
56   support::endian::write(Stream, 0ULL, support::little);
57   return AddressRanges.size() * 16 + 16;
58 }
59 
60 } // namespace
61 
62 DebugRangesSectionWriter::DebugRangesSectionWriter() {
63   RangesBuffer = std::make_unique<DebugBufferVector>();
64   RangesStream = std::make_unique<raw_svector_ostream>(*RangesBuffer);
65 
66   // Add an empty range as the first entry;
67   SectionOffset +=
68       writeAddressRanges(*RangesStream.get(), DebugAddressRangesVector{});
69 }
70 
71 uint64_t DebugRangesSectionWriter::addRanges(
72     DebugAddressRangesVector &&Ranges,
73     std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) {
74   if (Ranges.empty())
75     return getEmptyRangesOffset();
76 
77   const auto RI = CachedRanges.find(Ranges);
78   if (RI != CachedRanges.end())
79     return RI->second;
80 
81   const uint64_t EntryOffset = addRanges(Ranges);
82   CachedRanges.emplace(std::move(Ranges), EntryOffset);
83 
84   return EntryOffset;
85 }
86 
87 uint64_t
88 DebugRangesSectionWriter::addRanges(const DebugAddressRangesVector &Ranges) {
89   if (Ranges.empty())
90     return getEmptyRangesOffset();
91 
92   // Reading the SectionOffset and updating it should be atomic to guarantee
93   // unique and correct offsets in patches.
94   std::lock_guard<std::mutex> Lock(WriterMutex);
95   const uint32_t EntryOffset = SectionOffset;
96   SectionOffset += writeAddressRanges(*RangesStream.get(), Ranges);
97 
98   return EntryOffset;
99 }
100 
101 uint64_t DebugRangesSectionWriter::getSectionOffset() {
102   std::lock_guard<std::mutex> Lock(WriterMutex);
103   return SectionOffset;
104 }
105 
106 void DebugARangesSectionWriter::addCURanges(uint64_t CUOffset,
107                                             DebugAddressRangesVector &&Ranges) {
108   std::lock_guard<std::mutex> Lock(CUAddressRangesMutex);
109   CUAddressRanges.emplace(CUOffset, std::move(Ranges));
110 }
111 
112 void DebugARangesSectionWriter::writeARangesSection(
113     raw_svector_ostream &RangesStream) const {
114   // For reference on the format of the .debug_aranges section, see the DWARF4
115   // specification, section 6.1.4 Lookup by Address
116   // http://www.dwarfstd.org/doc/DWARF4.pdf
117   for (const auto &CUOffsetAddressRangesPair : CUAddressRanges) {
118     const uint64_t Offset = CUOffsetAddressRangesPair.first;
119     const DebugAddressRangesVector &AddressRanges =
120         CUOffsetAddressRangesPair.second;
121 
122     // Emit header.
123 
124     // Size of this set: 8 (size of the header) + 4 (padding after header)
125     // + 2*sizeof(uint64_t) bytes for each of the ranges, plus an extra
126     // pair of uint64_t's for the terminating, zero-length range.
127     // Does not include size field itself.
128     uint32_t Size = 8 + 4 + 2*sizeof(uint64_t) * (AddressRanges.size() + 1);
129 
130     // Header field #1: set size.
131     support::endian::write(RangesStream, Size, support::little);
132 
133     // Header field #2: version number, 2 as per the specification.
134     support::endian::write(RangesStream, static_cast<uint16_t>(2),
135                            support::little);
136 
137     // Header field #3: debug info offset of the correspondent compile unit.
138     support::endian::write(RangesStream, static_cast<uint32_t>(Offset),
139                            support::little);
140 
141     // Header field #4: address size.
142     // 8 since we only write ELF64 binaries for now.
143     RangesStream << char(8);
144 
145     // Header field #5: segment size of target architecture.
146     RangesStream << char(0);
147 
148     // Padding before address table - 4 bytes in the 64-bit-pointer case.
149     support::endian::write(RangesStream, static_cast<uint32_t>(0),
150                            support::little);
151 
152     writeAddressRanges(RangesStream, AddressRanges, true);
153   }
154 }
155 
156 DebugAddrWriter::DebugAddrWriter(BinaryContext *Bc) { BC = Bc; }
157 
158 void DebugAddrWriter::AddressForDWOCU::dump() {
159   std::vector<IndexAddressPair> SortedMap(indexToAddressBegin(),
160                                           indexToAdddessEnd());
161   // Sorting address in increasing order of indices.
162   std::sort(SortedMap.begin(), SortedMap.end(),
163             [](const IndexAddressPair &A, const IndexAddressPair &B) {
164               return A.first < B.first;
165             });
166   for (auto &Pair : SortedMap)
167     dbgs() << Twine::utohexstr(Pair.second) << "\t" << Pair.first << "\n";
168 }
169 uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address,
170                                               uint64_t DWOId) {
171   if (!AddressMaps.count(DWOId))
172     AddressMaps[DWOId] = AddressForDWOCU();
173 
174   AddressForDWOCU &Map = AddressMaps[DWOId];
175   auto Entry = Map.find(Address);
176   if (Entry == Map.end()) {
177     auto Index = Map.getNextIndex();
178     Entry = Map.insert(Address, Index).first;
179   }
180   return Entry->second;
181 }
182 
183 // Case1) Address is not in map insert in to AddresToIndex and IndexToAddres
184 // Case2) Address is in the map but Index is higher or equal. Need to update
185 // IndexToAddrss. Case3) Address is in the map but Index is lower. Need to
186 // update AddressToIndex and IndexToAddress
187 void DebugAddrWriter::addIndexAddress(uint64_t Address, uint32_t Index,
188                                       uint64_t DWOId) {
189   AddressForDWOCU &Map = AddressMaps[DWOId];
190   auto Entry = Map.find(Address);
191   if (Entry != Map.end()) {
192     if (Entry->second > Index)
193       Map.updateAddressToIndex(Address, Index);
194     Map.updateIndexToAddrss(Address, Index);
195   } else
196     Map.insert(Address, Index);
197 }
198 
199 AddressSectionBuffer DebugAddrWriter::finalize() {
200   // Need to layout all sections within .debug_addr
201   // Within each section sort Address by index.
202   AddressSectionBuffer Buffer;
203   raw_svector_ostream AddressStream(Buffer);
204   for (std::unique_ptr<DWARFUnit> &CU : BC->DwCtx->compile_units()) {
205     Optional<uint64_t> DWOId = CU->getDWOId();
206     // Handling the case wehre debug information is a mix of Debug fission and
207     // monolitic.
208     if (!DWOId)
209       continue;
210     auto AM = AddressMaps.find(*DWOId);
211     // Adding to map even if it did not contribute to .debug_addr.
212     // The Skeleton CU will still have DW_AT_GNU_addr_base.
213     DWOIdToOffsetMap[*DWOId] = Buffer.size();
214     // If does not exist this CUs DWO section didn't contribute to .debug_addr.
215     if (AM == AddressMaps.end())
216       continue;
217     std::vector<IndexAddressPair> SortedMap(AM->second.indexToAddressBegin(),
218                                             AM->second.indexToAdddessEnd());
219     // Sorting address in increasing order of indices.
220     std::sort(SortedMap.begin(), SortedMap.end(),
221               [](const IndexAddressPair &A, const IndexAddressPair &B) {
222                 return A.first < B.first;
223               });
224 
225     uint8_t AddrSize = CU->getAddressByteSize();
226     uint32_t Counter = 0;
227     auto WriteAddress = [&](uint64_t Address) -> void {
228       ++Counter;
229       switch (AddrSize) {
230       default:
231         assert(false && "Address Size is invalid.");
232         break;
233       case 4:
234         support::endian::write(AddressStream, static_cast<uint32_t>(Address),
235                                support::little);
236         break;
237       case 8:
238         support::endian::write(AddressStream, Address, support::little);
239         break;
240       }
241     };
242 
243     for (const IndexAddressPair &Val : SortedMap) {
244       while (Val.first > Counter)
245         WriteAddress(0);
246       WriteAddress(Val.second);
247     }
248   }
249 
250   return Buffer;
251 }
252 
253 uint64_t DebugAddrWriter::getOffset(uint64_t DWOId) {
254   auto Iter = DWOIdToOffsetMap.find(DWOId);
255   assert(Iter != DWOIdToOffsetMap.end() &&
256          "Offset in to.debug_addr was not found for DWO ID.");
257   return Iter->second;
258 }
259 
260 DebugLocWriter::DebugLocWriter(BinaryContext *BC) {
261   LocBuffer = std::make_unique<DebugBufferVector>();
262   LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer);
263 }
264 
265 void DebugLocWriter::addList(uint64_t AttrOffset,
266                              DebugLocationsVector &&LocList) {
267   if (LocList.empty()) {
268     EmptyAttrLists.push_back(AttrOffset);
269     return;
270   }
271   // Since there is a separate DebugLocWriter for each thread,
272   // we don't need a lock to read the SectionOffset and update it.
273   const uint32_t EntryOffset = SectionOffset;
274 
275   for (const DebugLocationEntry &Entry : LocList) {
276     support::endian::write(*LocStream, static_cast<uint64_t>(Entry.LowPC),
277                            support::little);
278     support::endian::write(*LocStream, static_cast<uint64_t>(Entry.HighPC),
279                            support::little);
280     support::endian::write(*LocStream, static_cast<uint16_t>(Entry.Expr.size()),
281                            support::little);
282     *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()),
283                             Entry.Expr.size());
284     SectionOffset += 2 * 8 + 2 + Entry.Expr.size();
285   }
286   LocStream->write_zeros(16);
287   SectionOffset += 16;
288   LocListDebugInfoPatches.push_back({AttrOffset, EntryOffset});
289 }
290 
291 void DebugLoclistWriter::addList(uint64_t AttrOffset,
292                                  DebugLocationsVector &&LocList) {
293   Patches.push_back({AttrOffset, std::move(LocList)});
294 }
295 
296 std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() {
297   return std::move(LocBuffer);
298 }
299 
300 // DWARF 4: 2.6.2
301 void DebugLocWriter::finalize(uint64_t SectionOffset,
302                               SimpleBinaryPatcher &DebugInfoPatcher) {
303   for (const auto LocListDebugInfoPatchType : LocListDebugInfoPatches) {
304     uint64_t Offset = SectionOffset + LocListDebugInfoPatchType.LocListOffset;
305     DebugInfoPatcher.addLE32Patch(LocListDebugInfoPatchType.DebugInfoAttrOffset,
306                                   Offset);
307   }
308 
309   for (uint64_t DebugInfoAttrOffset : EmptyAttrLists)
310     DebugInfoPatcher.addLE32Patch(DebugInfoAttrOffset,
311                                   DebugLocWriter::EmptyListOffset);
312 }
313 
314 void DebugLoclistWriter::finalize(uint64_t SectionOffset,
315                                   SimpleBinaryPatcher &DebugInfoPatcher) {
316   for (LocPatch &Patch : Patches) {
317     if (Patch.LocList.empty()) {
318       DebugInfoPatcher.addLE32Patch(Patch.AttrOffset,
319                                     DebugLocWriter::EmptyListOffset);
320       continue;
321     }
322     const uint32_t EntryOffset = LocBuffer->size();
323     for (const DebugLocationEntry &Entry : Patch.LocList) {
324       support::endian::write(*LocStream,
325                              static_cast<uint8_t>(dwarf::DW_LLE_startx_length),
326                              support::little);
327       uint32_t Index = AddrWriter->getIndexFromAddress(Entry.LowPC, DWOId);
328       encodeULEB128(Index, *LocStream);
329 
330       // TODO: Support DWARF5
331       support::endian::write(*LocStream,
332                              static_cast<uint32_t>(Entry.HighPC - Entry.LowPC),
333                              support::little);
334       support::endian::write(*LocStream,
335                              static_cast<uint16_t>(Entry.Expr.size()),
336                              support::little);
337       *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()),
338                               Entry.Expr.size());
339     }
340     support::endian::write(*LocStream,
341                            static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),
342                            support::little);
343     DebugInfoPatcher.addLE32Patch(Patch.AttrOffset, EntryOffset);
344     clearList(Patch.LocList);
345   }
346   clearList(Patches);
347 }
348 
349 DebugAddrWriter *DebugLoclistWriter::AddrWriter = nullptr;
350 
351 void SimpleBinaryPatcher::addBinaryPatch(uint32_t Offset,
352                                          const std::string &NewValue) {
353   Patches.emplace_back(Offset, NewValue);
354 }
355 
356 void SimpleBinaryPatcher::addBytePatch(uint32_t Offset, uint8_t Value) {
357   Patches.emplace_back(Offset, std::string(1, Value));
358 }
359 
360 void SimpleBinaryPatcher::addLEPatch(uint32_t Offset, uint64_t NewValue,
361                                      size_t ByteSize) {
362   std::string LE64(ByteSize, 0);
363   for (size_t I = 0; I < ByteSize; ++I) {
364     LE64[I] = NewValue & 0xff;
365     NewValue >>= 8;
366   }
367   Patches.emplace_back(Offset, LE64);
368 }
369 
370 void SimpleBinaryPatcher::addUDataPatch(uint32_t Offset, uint64_t Value, uint64_t Size) {
371   std::string Buff;
372   raw_string_ostream OS(Buff);
373   encodeULEB128(Value, OS, Size);
374 
375   Patches.emplace_back(Offset, OS.str());
376 }
377 
378 void SimpleBinaryPatcher::addLE64Patch(uint32_t Offset, uint64_t NewValue) {
379   addLEPatch(Offset, NewValue, 8);
380 }
381 
382 void SimpleBinaryPatcher::addLE32Patch(uint32_t Offset, uint32_t NewValue) {
383   addLEPatch(Offset, NewValue, 4);
384 }
385 
386 void SimpleBinaryPatcher::patchBinary(std::string &BinaryContents,
387                                       uint32_t DWPOffset = 0) {
388   for (const auto &Patch : Patches) {
389     uint32_t Offset = Patch.first - DWPOffset;
390     const std::string &ByteSequence = Patch.second;
391     assert(Offset + ByteSequence.size() <= BinaryContents.size() &&
392         "Applied patch runs over binary size.");
393     for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) {
394       BinaryContents[Offset + I] = ByteSequence[I];
395     }
396   }
397 }
398 
399 void DebugStrWriter::create() {
400   StrBuffer = std::make_unique<DebugStrBufferVector>();
401   StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer);
402 }
403 
404 void DebugStrWriter::initialize() {
405   auto StrSection = BC->DwCtx->getDWARFObj().getStrSection();
406   (*StrStream) << StrSection;
407 }
408 
409 uint32_t DebugStrWriter::addString(StringRef Str) {
410   if (StrBuffer->empty())
411     initialize();
412   auto Offset = StrBuffer->size();
413   (*StrStream) << Str;
414   StrStream->write_zeros(1);
415   return Offset;
416 }
417 
418 void DebugAbbrevWriter::addUnitAbbreviations(DWARFUnit &Unit) {
419   const DWARFAbbreviationDeclarationSet *Abbrevs = Unit.getAbbreviations();
420   if (!Abbrevs)
421     return;
422 
423   // Multiple units may share the same abbreviations. Only add abbreviations
424   // for the first unit and reuse them.
425   const uint64_t AbbrevOffset = Unit.getAbbreviationsOffset();
426   if (CUAbbrevData.find(AbbrevOffset) != CUAbbrevData.end())
427     return;
428 
429   std::lock_guard<std::mutex> Lock(WriterMutex);
430   AbbrevData &UnitData = CUAbbrevData[AbbrevOffset];
431   UnitData.Buffer = std::make_unique<DebugBufferVector>();
432   UnitData.Stream = std::make_unique<raw_svector_ostream>(*UnitData.Buffer);
433 
434   const auto &UnitPatches = Patches[&Unit];
435 
436   raw_svector_ostream &OS = *UnitData.Stream.get();
437 
438   // Take a fast path if there are no patches to apply. Simply copy the original
439   // contents.
440   if (UnitPatches.empty()) {
441     StringRef AbbrevSectionContents =
442         Unit.isDWOUnit() ? Unit.getContext().getDWARFObj().getAbbrevDWOSection()
443                          : Unit.getContext().getDWARFObj().getAbbrevSection();
444     StringRef AbbrevContents;
445 
446     const DWARFUnitIndex &CUIndex = Unit.getContext().getCUIndex();
447     if (!CUIndex.getRows().empty()) {
448       // Handle DWP section contribution.
449       const DWARFUnitIndex::Entry *DWOEntry =
450           CUIndex.getFromHash(*Unit.getDWOId());
451       if (!DWOEntry)
452         return;
453 
454       const DWARFUnitIndex::Entry::SectionContribution *DWOContrubution =
455           DWOEntry->getContribution(DWARFSectionKind::DW_SECT_ABBREV);
456       AbbrevContents = AbbrevSectionContents.substr(DWOContrubution->Offset,
457                                                     DWOContrubution->Length);
458     } else {
459       DWARFCompileUnit *NextUnit =
460           Unit.getContext().getCompileUnitForOffset(Unit.getNextUnitOffset());
461       const uint64_t StartOffset = Unit.getAbbreviationsOffset();
462       const uint64_t EndOffset = NextUnit ? NextUnit->getAbbreviationsOffset()
463                                           : AbbrevSectionContents.size();
464       AbbrevContents = AbbrevSectionContents.slice(StartOffset, EndOffset);
465     }
466 
467     OS.reserveExtraSpace(AbbrevContents.size());
468     OS << AbbrevContents;
469 
470     return;
471   }
472 
473   for (auto I = Abbrevs->begin(), E = Abbrevs->end(); I != E; ++I) {
474     const DWARFAbbreviationDeclaration &Abbrev = *I;
475     auto Patch = UnitPatches.find(&Abbrev);
476 
477     encodeULEB128(Abbrev.getCode(), OS);
478     encodeULEB128(Abbrev.getTag(), OS);
479     encodeULEB128(Abbrev.hasChildren(), OS);
480     for (const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec :
481          Abbrev.attributes()) {
482       if (Patch != UnitPatches.end()) {
483         bool Patched = false;
484         // Patches added later take a precedence over earlier ones.
485         for (auto I = Patch->second.rbegin(), E = Patch->second.rend(); I != E;
486              ++I) {
487           if (I->OldAttr != AttrSpec.Attr)
488             continue;
489 
490           encodeULEB128(I->NewAttr, OS);
491           encodeULEB128(I->NewAttrForm, OS);
492           Patched = true;
493           break;
494         }
495         if (Patched)
496           continue;
497       }
498 
499       encodeULEB128(AttrSpec.Attr, OS);
500       encodeULEB128(AttrSpec.Form, OS);
501       if (AttrSpec.isImplicitConst())
502         encodeSLEB128(AttrSpec.getImplicitConstValue(), OS);
503     }
504 
505     encodeULEB128(0, OS);
506     encodeULEB128(0, OS);
507   }
508   encodeULEB128(0, OS);
509 }
510 
511 std::unique_ptr<DebugBufferVector> DebugAbbrevWriter::finalize() {
512   DebugBufferVector ReturnBuffer;
513 
514   // Pre-calculate the total size of abbrev section.
515   uint64_t Size = 0;
516   for (const auto &KV : CUAbbrevData) {
517     const AbbrevData &UnitData = KV.second;
518     Size += UnitData.Buffer->size();
519   }
520   ReturnBuffer.reserve(Size);
521 
522   uint64_t Pos = 0;
523   for (auto &KV : CUAbbrevData) {
524     AbbrevData &UnitData = KV.second;
525     ReturnBuffer.append(*UnitData.Buffer);
526     UnitData.Offset = Pos;
527     Pos += UnitData.Buffer->size();
528 
529     UnitData.Buffer.reset();
530     UnitData.Stream.reset();
531   }
532 
533   return std::make_unique<DebugBufferVector>(ReturnBuffer);
534 }
535 
536 static void emitDwarfSetLineAddrAbs(MCStreamer &OS,
537                                     MCDwarfLineTableParams Params,
538                                     int64_t LineDelta, uint64_t Address,
539                                     int PointerSize) {
540   // emit the sequence to set the address
541   OS.emitIntValue(dwarf::DW_LNS_extended_op, 1);
542   OS.emitULEB128IntValue(PointerSize + 1);
543   OS.emitIntValue(dwarf::DW_LNE_set_address, 1);
544   OS.emitIntValue(Address, PointerSize);
545 
546   // emit the sequence for the LineDelta (from 1) and a zero address delta.
547   MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0);
548 }
549 
550 static inline void emitBinaryDwarfLineTable(
551     MCStreamer *MCOS, MCDwarfLineTableParams Params,
552     const DWARFDebugLine::LineTable *Table,
553     const std::vector<DwarfLineTable::RowSequence> &InputSequences) {
554   if (InputSequences.empty())
555     return;
556 
557   constexpr uint64_t InvalidAddress = UINT64_MAX;
558   unsigned FileNum = 1;
559   unsigned LastLine = 1;
560   unsigned Column = 0;
561   unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
562   unsigned Isa = 0;
563   unsigned Discriminator = 0;
564   uint64_t LastAddress = InvalidAddress;
565   uint64_t PrevEndOfSequence = InvalidAddress;
566   const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();
567 
568   auto emitEndOfSequence = [&](uint64_t Address) {
569     MCDwarfLineAddr::Emit(MCOS, Params, INT64_MAX, Address - LastAddress);
570     FileNum = 1;
571     LastLine = 1;
572     Column = 0;
573     Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
574     Isa = 0;
575     Discriminator = 0;
576     LastAddress = InvalidAddress;
577   };
578 
579   for (const DwarfLineTable::RowSequence &Sequence : InputSequences) {
580     const uint64_t SequenceStart =
581         Table->Rows[Sequence.FirstIndex].Address.Address;
582 
583     // Check if we need to mark the end of the sequence.
584     if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress &&
585         PrevEndOfSequence != SequenceStart) {
586       emitEndOfSequence(PrevEndOfSequence);
587     }
588 
589     for (uint32_t RowIndex = Sequence.FirstIndex;
590          RowIndex <= Sequence.LastIndex; ++RowIndex) {
591       const DWARFDebugLine::Row &Row = Table->Rows[RowIndex];
592       int64_t LineDelta = static_cast<int64_t>(Row.Line) - LastLine;
593       const uint64_t Address = Row.Address.Address;
594 
595       if (FileNum != Row.File) {
596         FileNum = Row.File;
597         MCOS->emitInt8(dwarf::DW_LNS_set_file);
598         MCOS->emitULEB128IntValue(FileNum);
599       }
600       if (Column != Row.Column) {
601         Column = Row.Column;
602         MCOS->emitInt8(dwarf::DW_LNS_set_column);
603         MCOS->emitULEB128IntValue(Column);
604       }
605       if (Discriminator != Row.Discriminator &&
606           MCOS->getContext().getDwarfVersion() >= 4) {
607         Discriminator = Row.Discriminator;
608         unsigned Size = getULEB128Size(Discriminator);
609         MCOS->emitInt8(dwarf::DW_LNS_extended_op);
610         MCOS->emitULEB128IntValue(Size + 1);
611         MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
612         MCOS->emitULEB128IntValue(Discriminator);
613       }
614       if (Isa != Row.Isa) {
615         Isa = Row.Isa;
616         MCOS->emitInt8(dwarf::DW_LNS_set_isa);
617         MCOS->emitULEB128IntValue(Isa);
618       }
619       if (Row.IsStmt != Flags) {
620         Flags = Row.IsStmt;
621         MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
622       }
623       if (Row.BasicBlock)
624         MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
625       if (Row.PrologueEnd)
626         MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
627       if (Row.EpilogueBegin)
628         MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);
629 
630       // The end of the sequence is not normal in the middle of the input
631       // sequence, but could happen, e.g. for assembly code.
632       if (Row.EndSequence) {
633         emitEndOfSequence(Address);
634       } else {
635         if (LastAddress == InvalidAddress)
636           emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address,
637                                   AsmInfo->getCodePointerSize());
638         else
639           MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress);
640 
641         LastAddress = Address;
642         LastLine = Row.Line;
643       }
644 
645       Discriminator = 0;
646     }
647     PrevEndOfSequence = Sequence.EndAddress;
648   }
649 
650   // Finish with the end of the sequence.
651   if (LastAddress != InvalidAddress)
652     emitEndOfSequence(PrevEndOfSequence);
653 }
654 
655 // This function is similar to the one from MCDwarfLineTable, except it handles
656 // end-of-sequence entries differently by utilizing line entries with
657 // DWARF2_FLAG_END_SEQUENCE flag.
658 static inline void emitDwarfLineTable(
659     MCStreamer *MCOS, MCSection *Section,
660     const MCLineSection::MCDwarfLineEntryCollection &LineEntries) {
661   unsigned FileNum = 1;
662   unsigned LastLine = 1;
663   unsigned Column = 0;
664   unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
665   unsigned Isa = 0;
666   unsigned Discriminator = 0;
667   MCSymbol *LastLabel = nullptr;
668   const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();
669 
670   // Loop through each MCDwarfLineEntry and encode the dwarf line number table.
671   for (const MCDwarfLineEntry &LineEntry : LineEntries) {
672     if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) {
673       MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(),
674                                      AsmInfo->getCodePointerSize());
675       FileNum = 1;
676       LastLine = 1;
677       Column = 0;
678       Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
679       Isa = 0;
680       Discriminator = 0;
681       LastLabel = nullptr;
682       continue;
683     }
684 
685     int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine;
686 
687     if (FileNum != LineEntry.getFileNum()) {
688       FileNum = LineEntry.getFileNum();
689       MCOS->emitInt8(dwarf::DW_LNS_set_file);
690       MCOS->emitULEB128IntValue(FileNum);
691     }
692     if (Column != LineEntry.getColumn()) {
693       Column = LineEntry.getColumn();
694       MCOS->emitInt8(dwarf::DW_LNS_set_column);
695       MCOS->emitULEB128IntValue(Column);
696     }
697     if (Discriminator != LineEntry.getDiscriminator() &&
698         MCOS->getContext().getDwarfVersion() >= 4) {
699       Discriminator = LineEntry.getDiscriminator();
700       unsigned Size = getULEB128Size(Discriminator);
701       MCOS->emitInt8(dwarf::DW_LNS_extended_op);
702       MCOS->emitULEB128IntValue(Size + 1);
703       MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
704       MCOS->emitULEB128IntValue(Discriminator);
705     }
706     if (Isa != LineEntry.getIsa()) {
707       Isa = LineEntry.getIsa();
708       MCOS->emitInt8(dwarf::DW_LNS_set_isa);
709       MCOS->emitULEB128IntValue(Isa);
710     }
711     if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {
712       Flags = LineEntry.getFlags();
713       MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
714     }
715     if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK)
716       MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
717     if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END)
718       MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
719     if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN)
720       MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);
721 
722     MCSymbol *Label = LineEntry.getLabel();
723 
724     // At this point we want to emit/create the sequence to encode the delta
725     // in line numbers and the increment of the address from the previous
726     // Label and the current Label.
727     MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,
728                                    AsmInfo->getCodePointerSize());
729     Discriminator = 0;
730     LastLine = LineEntry.getLine();
731     LastLabel = Label;
732   }
733 
734   assert(LastLabel == nullptr && "end of sequence expected");
735 }
736 
737 void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params,
738                             Optional<MCDwarfLineStr> &LineStr) const {
739   if (!RawData.empty()) {
740     assert(MCLineSections.getMCLineEntries().empty() &&
741            InputSequences.empty() &&
742            "cannot combine raw data with new line entries");
743     MCOS->emitLabel(getLabel());
744     MCOS->emitBytes(RawData);
745 
746     return;
747   }
748 
749   MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second;
750 
751   // Put out the line tables.
752   for (const auto &LineSec : MCLineSections.getMCLineEntries())
753     emitDwarfLineTable(MCOS, LineSec.first, LineSec.second);
754 
755   // Emit line tables for the original code.
756   emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences);
757 
758   // This is the end of the section, so set the value of the symbol at the end
759   // of this section (that was used in a previous expression).
760   MCOS->emitLabel(LineEndSym);
761 }
762 
763 void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) {
764   MCAssembler &Assembler =
765       static_cast<MCObjectStreamer *>(&Streamer)->getAssembler();
766 
767   MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams();
768 
769   auto &LineTables = BC.getDwarfLineTables();
770 
771   // Bail out early so we don't switch to the debug_line section needlessly and
772   // in doing so create an unnecessary (if empty) section.
773   if (LineTables.empty())
774     return;
775 
776   // In a v5 non-split line table, put the strings in a separate section.
777   Optional<MCDwarfLineStr> LineStr(None);
778   if (BC.Ctx->getDwarfVersion() >= 5)
779     LineStr = MCDwarfLineStr(*BC.Ctx);
780 
781   // Switch to the section where the table will be emitted into.
782   Streamer.SwitchSection(BC.MOFI->getDwarfLineSection());
783 
784   // Handle the rest of the Compile Units.
785   for (auto &CUIDTablePair : LineTables) {
786     CUIDTablePair.second.emitCU(&Streamer, Params, LineStr);
787   }
788 }
789 
790 } // namespace bolt
791 } // namespace llvm
792