1 //===- bolt/Core/DebugData.h - Debugging information handling ---*- C++ -*-===//
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 // This file contains declaration of classes that represent and serialize
10 // DWARF-related entities.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef BOLT_CORE_DEBUG_DATA_H
15 #define BOLT_CORE_DEBUG_DATA_H
16 
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
19 #include "llvm/MC/MCDwarf.h"
20 #include "llvm/Support/SMLoc.h"
21 #include "llvm/Support/raw_ostream.h"
22 #include <cstdint>
23 #include <map>
24 #include <mutex>
25 #include <string>
26 #include <unordered_map>
27 #include <unordered_set>
28 #include <utility>
29 #include <vector>
30 
31 #define DWARF2_FLAG_END_SEQUENCE (1 << 4)
32 
33 namespace llvm {
34 
35 namespace bolt {
36 
37 struct AttrInfo {
38   DWARFFormValue V;
39   const DWARFAbbreviationDeclaration *AbbrevDecl;
40   uint64_t Offset;
41   uint32_t Size; // Size of the attribute.
42 };
43 
44 /// Finds attributes FormValue and Offset.
45 ///
46 /// \param DIE die to look up in.
47 /// \param AbbrevDecl abbrev declaration for the die.
48 /// \param Index an index in Abbrev declaration entry.
49 Optional<AttrInfo>
50 findAttributeInfo(const DWARFDie DIE,
51                   const DWARFAbbreviationDeclaration *AbbrevDecl,
52                   uint32_t Index);
53 
54 /// Finds attributes FormValue and Offset.
55 ///
56 /// \param DIE die to look up in.
57 /// \param Attr the attribute to extract.
58 /// \return an optional AttrInfo with DWARFFormValue and Offset.
59 Optional<AttrInfo> findAttributeInfo(const DWARFDie DIE, dwarf::Attribute Attr);
60 
61 // DWARF5 Header in order of encoding.
62 // Types represent encodnig sizes.
63 using UnitLengthType = uint32_t;
64 using VersionType = uint16_t;
65 using AddressSizeType = uint8_t;
66 using SegmentSelectorType = uint8_t;
67 using OffsetEntryCountType = uint32_t;
68 /// Get DWARF5 Header size.
69 /// Rangelists and Loclists have the same header.
getDWARF5RngListLocListHeaderSize()70 constexpr uint32_t getDWARF5RngListLocListHeaderSize() {
71   return sizeof(UnitLengthType) + sizeof(VersionType) +
72          sizeof(AddressSizeType) + sizeof(SegmentSelectorType) +
73          sizeof(OffsetEntryCountType);
74 }
75 
76 class BinaryContext;
77 
78 /// Address range representation. Takes less space than DWARFAddressRange.
79 struct DebugAddressRange {
80   uint64_t LowPC{0};
81   uint64_t HighPC{0};
82 
83   DebugAddressRange() = default;
84 
DebugAddressRangeDebugAddressRange85   DebugAddressRange(uint64_t LowPC, uint64_t HighPC)
86       : LowPC(LowPC), HighPC(HighPC) {}
87 };
88 
89 static inline bool operator<(const DebugAddressRange &LHS,
90                              const DebugAddressRange &RHS) {
91   return std::tie(LHS.LowPC, LHS.HighPC) < std::tie(RHS.LowPC, RHS.HighPC);
92 }
93 
94 /// DebugAddressRangesVector - represents a set of absolute address ranges.
95 using DebugAddressRangesVector = SmallVector<DebugAddressRange, 2>;
96 
97 /// Address range with location used by .debug_loc section.
98 /// More compact than DWARFLocationEntry and uses absolute addresses.
99 struct DebugLocationEntry {
100   uint64_t LowPC;
101   uint64_t HighPC;
102   SmallVector<uint8_t, 4> Expr;
103 };
104 
105 using DebugLocationsVector = SmallVector<DebugLocationEntry, 4>;
106 
107 /// References a row in a DWARFDebugLine::LineTable by the DWARF
108 /// Context index of the DWARF Compile Unit that owns the Line Table and the row
109 /// index. This is tied to our IR during disassembly so that we can later update
110 /// .debug_line information. RowIndex has a base of 1, which means a RowIndex
111 /// of 1 maps to the first row of the line table and a RowIndex of 0 is invalid.
112 struct DebugLineTableRowRef {
113   uint32_t DwCompileUnitIndex;
114   uint32_t RowIndex;
115 
116   const static DebugLineTableRowRef NULL_ROW;
117 
118   bool operator==(const DebugLineTableRowRef &Rhs) const {
119     return DwCompileUnitIndex == Rhs.DwCompileUnitIndex &&
120            RowIndex == Rhs.RowIndex;
121   }
122 
123   bool operator!=(const DebugLineTableRowRef &Rhs) const {
124     return !(*this == Rhs);
125   }
126 
fromSMLocDebugLineTableRowRef127   static DebugLineTableRowRef fromSMLoc(const SMLoc &Loc) {
128     union {
129       decltype(Loc.getPointer()) Ptr;
130       DebugLineTableRowRef Ref;
131     } U;
132     U.Ptr = Loc.getPointer();
133     return U.Ref;
134   }
135 
toSMLocDebugLineTableRowRef136   SMLoc toSMLoc() const {
137     union {
138       decltype(SMLoc().getPointer()) Ptr;
139       DebugLineTableRowRef Ref;
140     } U;
141     U.Ref = *this;
142     return SMLoc::getFromPointer(U.Ptr);
143   }
144 };
145 
146 /// Common buffer vector used for debug info handling.
147 using DebugBufferVector = SmallVector<char, 16>;
148 
149 /// Map of old CU offset to new offset and length.
150 struct CUInfo {
151   uint32_t Offset;
152   uint32_t Length;
153 };
154 using CUOffsetMap = std::map<uint32_t, CUInfo>;
155 
156 enum class RangesWriterKind { DebugRangesWriter, DebugRangeListsWriter };
157 /// Serializes the .debug_ranges DWARF section.
158 class DebugRangesSectionWriter {
159 public:
160   DebugRangesSectionWriter();
161 
DebugRangesSectionWriter(RangesWriterKind K)162   DebugRangesSectionWriter(RangesWriterKind K) : Kind(K){};
163 
~DebugRangesSectionWriter()164   virtual ~DebugRangesSectionWriter(){};
165 
166   /// Add ranges with caching.
167   virtual uint64_t
168   addRanges(DebugAddressRangesVector &&Ranges,
169             std::map<DebugAddressRangesVector, uint64_t> &CachedRanges);
170 
171   /// Add ranges and return offset into section.
172   virtual uint64_t addRanges(const DebugAddressRangesVector &Ranges);
173 
174   /// Returns an offset of an empty address ranges list that is always written
175   /// to .debug_ranges
getEmptyRangesOffset()176   uint64_t getEmptyRangesOffset() const { return EmptyRangesOffset; }
177 
178   /// Returns the SectionOffset.
179   uint64_t getSectionOffset();
180 
181   /// Returns a buffer containing Ranges.
releaseBuffer()182   virtual std::unique_ptr<DebugBufferVector> releaseBuffer() {
183     return std::move(RangesBuffer);
184   }
185 
getKind()186   RangesWriterKind getKind() const { return Kind; }
187 
classof(const DebugRangesSectionWriter * Writer)188   static bool classof(const DebugRangesSectionWriter *Writer) {
189     return Writer->getKind() == RangesWriterKind::DebugRangesWriter;
190   }
191 
192   /// Writes out range lists for a current CU being processed.
finalizeSection()193   void virtual finalizeSection(){};
194 
195   /// Needs to be invoked before each \p CU is processed.
initSection(DWARFUnit & CU)196   void virtual initSection(DWARFUnit &CU){};
197 
198 protected:
199   std::unique_ptr<DebugBufferVector> RangesBuffer;
200 
201   std::unique_ptr<raw_svector_ostream> RangesStream;
202 
203   std::mutex WriterMutex;
204 
205   /// Current offset in the section (updated as new entries are written).
206   /// Starts with 16 since the first 16 bytes are reserved for an empty range.
207   uint32_t SectionOffset{0};
208 
209   /// Offset of an empty address ranges list.
210   static constexpr uint64_t EmptyRangesOffset{0};
211 
212 private:
213   RangesWriterKind Kind;
214 };
215 
216 class DebugAddrWriter;
217 class DebugRangeListsSectionWriter : public DebugRangesSectionWriter {
218 public:
DebugRangeListsSectionWriter()219   DebugRangeListsSectionWriter()
220       : DebugRangesSectionWriter(RangesWriterKind::DebugRangeListsWriter) {
221     RangesBuffer = std::make_unique<DebugBufferVector>();
222     RangesStream = std::make_unique<raw_svector_ostream>(*RangesBuffer);
223   };
~DebugRangeListsSectionWriter()224   virtual ~DebugRangeListsSectionWriter(){};
225 
setAddressWriter(DebugAddrWriter * AddrW)226   static void setAddressWriter(DebugAddrWriter *AddrW) { AddrWriter = AddrW; }
227 
228   /// Add ranges with caching.
229   virtual uint64_t addRanges(
230       DebugAddressRangesVector &&Ranges,
231       std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) override;
232 
233   /// Add ranges and return offset into section.
234   virtual uint64_t addRanges(const DebugAddressRangesVector &Ranges) override;
235 
releaseBuffer()236   virtual std::unique_ptr<DebugBufferVector> releaseBuffer() override {
237     return std::move(RangesBuffer);
238   }
239 
240   /// Needs to be invoked before each \p CU is processed.
241   void virtual initSection(DWARFUnit &CU) override;
242 
243   /// Writes out range lists for a current CU being processed.
244   void virtual finalizeSection() override;
245 
246   // Returns true if section is empty.
empty()247   bool empty() { return RangesBuffer->empty(); }
248 
classof(const DebugRangesSectionWriter * Writer)249   static bool classof(const DebugRangesSectionWriter *Writer) {
250     return Writer->getKind() == RangesWriterKind::DebugRangeListsWriter;
251   }
252 
253 private:
254   static DebugAddrWriter *AddrWriter;
255   /// Used to find unique CU ID.
256   DWARFUnit *CU;
257   /// Current relative offset of range list entry within this CUs rangelist
258   /// body.
259   uint32_t CurrentOffset{0};
260   /// Contains relative offset of each range list entry.
261   SmallVector<uint32_t, 1> RangeEntries;
262 
263   std::unique_ptr<DebugBufferVector> CUBodyBuffer;
264   std::unique_ptr<raw_svector_ostream> CUBodyStream;
265 };
266 
267 /// Serializes the .debug_aranges DWARF section.
268 class DebugARangesSectionWriter {
269 public:
270   /// Add ranges for CU matching \p CUOffset.
271   void addCURanges(uint64_t CUOffset, DebugAddressRangesVector &&Ranges);
272 
273   /// Writes .debug_aranges with the added ranges to the MCObjectWriter.
274   /// Takes in \p RangesStream to write into, and \p CUMap which maps CU
275   /// original offsets to new ones.
276   void writeARangesSection(raw_svector_ostream &RangesStream,
277                            const CUOffsetMap &CUMap) const;
278 
279   /// Resets the writer to a clear state.
reset()280   void reset() { CUAddressRanges.clear(); }
281 
282   /// Map DWARFCompileUnit index to ranges.
283   using CUAddressRangesType = std::map<uint64_t, DebugAddressRangesVector>;
284 
285   /// Return ranges for a given CU.
getCUAddressRanges()286   const CUAddressRangesType &getCUAddressRanges() const {
287     return CUAddressRanges;
288   }
289 
290 private:
291   /// Map from compile unit offset to the list of address intervals that belong
292   /// to that compile unit. Each interval is a pair
293   /// (first address, interval size).
294   CUAddressRangesType CUAddressRanges;
295 
296   std::mutex CUAddressRangesMutex;
297 };
298 
299 using IndexAddressPair = std::pair<uint32_t, uint64_t>;
300 using AddressToIndexMap = std::unordered_map<uint64_t, uint32_t>;
301 using IndexToAddressMap = std::unordered_map<uint32_t, uint64_t>;
302 using AddressSectionBuffer = SmallVector<char, 4>;
303 class DebugAddrWriter {
304 public:
305   DebugAddrWriter() = delete;
306   DebugAddrWriter(BinaryContext *BC_);
~DebugAddrWriter()307   virtual ~DebugAddrWriter(){};
308   /// Given an address returns an index in .debug_addr.
309   /// Adds Address to map.
310   uint32_t getIndexFromAddress(uint64_t Address, DWARFUnit &CU);
311 
312   /// Adds {\p Address, \p Index} to \p CU.
313   void addIndexAddress(uint64_t Address, uint32_t Index, DWARFUnit &CU);
314 
315   /// Creates consolidated .debug_addr section, and builds DWOID to offset map.
316   virtual AddressSectionBuffer finalize();
317 
318   /// Given DWARFUnit \p Unit returns offset of this CU in to .debug_addr
319   /// section.
320   virtual uint64_t getOffset(DWARFUnit &Unit);
321 
322   /// Returns False if .debug_addr section was created..
isInitialized()323   bool isInitialized() const { return !AddressMaps.empty(); }
324 
325 protected:
326   class AddressForDWOCU {
327   public:
find(uint64_t Adddress)328     AddressToIndexMap::iterator find(uint64_t Adddress) {
329       return AddressToIndex.find(Adddress);
330     }
end()331     AddressToIndexMap::iterator end() { return AddressToIndex.end(); }
begin()332     AddressToIndexMap::iterator begin() { return AddressToIndex.begin(); }
333 
indexToAdddessEnd()334     IndexToAddressMap::iterator indexToAdddessEnd() {
335       return IndexToAddress.end();
336     }
indexToAddressBegin()337     IndexToAddressMap::iterator indexToAddressBegin() {
338       return IndexToAddress.begin();
339     }
getNextIndex()340     uint32_t getNextIndex() {
341       while (IndexToAddress.count(CurrentIndex))
342         ++CurrentIndex;
343       return CurrentIndex;
344     }
345 
346     /// Inserts elements in to IndexToAddress and AddressToIndex.
347     /// Follows the same semantics as unordered_map insert.
insert(uint64_t Address,uint32_t Index)348     std::pair<AddressToIndexMap::iterator, bool> insert(uint64_t Address,
349                                                         uint32_t Index) {
350       IndexToAddress.insert({Index, Address});
351       return AddressToIndex.insert({Address, Index});
352     }
353 
354     /// Updates AddressToIndex Map.
355     /// Follows the same symantics as unordered map [].
updateAddressToIndex(uint64_t Address,uint32_t Index)356     void updateAddressToIndex(uint64_t Address, uint32_t Index) {
357       AddressToIndex[Address] = Index;
358     }
359 
360     /// Updates IndexToAddress Map.
361     /// Follows the same symantics as unordered map [].
updateIndexToAddrss(uint64_t Address,uint32_t Index)362     void updateIndexToAddrss(uint64_t Address, uint32_t Index) {
363       IndexToAddress[Index] = Address;
364     }
365 
366     void dump();
367 
368   private:
369     AddressToIndexMap AddressToIndex;
370     IndexToAddressMap IndexToAddress;
371     uint32_t CurrentIndex{0};
372   };
373 
getCUID(DWARFUnit & Unit)374   virtual uint64_t getCUID(DWARFUnit &Unit) {
375     assert(Unit.getDWOId() && "Unit is not Skeleton CU.");
376     return *Unit.getDWOId();
377   }
378 
379   BinaryContext *BC;
380   /// Maps DWOID to AddressForDWOCU.
381   std::unordered_map<uint64_t, AddressForDWOCU> AddressMaps;
382   /// Maps DWOID to offset within .debug_addr section.
383   std::unordered_map<uint64_t, uint64_t> DWOIdToOffsetMap;
384   /// Mutex used for parallel processing of debug info.
385   std::mutex WriterMutex;
386 };
387 
388 class DebugAddrWriterDwarf5 : public DebugAddrWriter {
389 public:
390   DebugAddrWriterDwarf5() = delete;
DebugAddrWriterDwarf5(BinaryContext * BC)391   DebugAddrWriterDwarf5(BinaryContext *BC) : DebugAddrWriter(BC) {}
392 
393   /// Creates consolidated .debug_addr section, and builds DWOID to offset map.
394   virtual AddressSectionBuffer finalize() override;
395   /// Given DWARFUnit \p Unit returns offset of this CU in to .debug_addr
396   /// section.
397   virtual uint64_t getOffset(DWARFUnit &Unit) override;
398 
399 protected:
400   /// Given DWARFUnit \p Unit returns either DWO ID or it's offset within
401   /// .debug_info.
getCUID(DWARFUnit & Unit)402   virtual uint64_t getCUID(DWARFUnit &Unit) override {
403     if (Unit.isDWOUnit()) {
404       DWARFUnit *SkeletonCU = Unit.getLinkedUnit();
405       return SkeletonCU->getOffset();
406     }
407     return Unit.getOffset();
408   }
409 };
410 
411 /// This class is NOT thread safe.
412 using DebugStrOffsetsBufferVector = SmallVector<char, 16>;
413 class DebugStrOffsetsWriter {
414 public:
DebugStrOffsetsWriter()415   DebugStrOffsetsWriter() {
416     StrOffsetsBuffer = std::make_unique<DebugStrOffsetsBufferVector>();
417     StrOffsetsStream = std::make_unique<raw_svector_ostream>(*StrOffsetsBuffer);
418   }
419 
420   /// Initializes Buffer and Stream.
421   void initialize(const DWARFSection &StrOffsetsSection,
422                   const Optional<StrOffsetsContributionDescriptor> Contr);
423 
424   /// Update Str offset in .debug_str in .debug_str_offsets.
425   void updateAddressMap(uint32_t Index, uint32_t Address);
426 
427   /// Writes out current sections entry into .debug_str_offsets.
428   void finalizeSection();
429 
430   /// Returns False if no strings were added to .debug_str.
isFinalized()431   bool isFinalized() const { return !StrOffsetsBuffer->empty(); }
432 
433   /// Returns buffer containing .debug_str_offsets.
releaseBuffer()434   std::unique_ptr<DebugStrOffsetsBufferVector> releaseBuffer() {
435     return std::move(StrOffsetsBuffer);
436   }
437 
438 private:
439   std::unique_ptr<DebugStrOffsetsBufferVector> StrOffsetsBuffer;
440   std::unique_ptr<raw_svector_ostream> StrOffsetsStream;
441   std::map<uint32_t, uint32_t> IndexToAddressMap;
442   // Section size not including header.
443   uint32_t CurrentSectionSize{0};
444 };
445 
446 using DebugStrBufferVector = SmallVector<char, 16>;
447 class DebugStrWriter {
448 public:
449   DebugStrWriter() = delete;
DebugStrWriter(BinaryContext & BC)450   DebugStrWriter(BinaryContext &BC) : BC(BC) { create(); }
releaseBuffer()451   std::unique_ptr<DebugStrBufferVector> releaseBuffer() {
452     return std::move(StrBuffer);
453   }
454 
455   /// Adds string to .debug_str.
456   /// On first invokation it initializes internal data stractures.
457   uint32_t addString(StringRef Str);
458 
459   /// Returns False if no strings were added to .debug_str.
isInitialized()460   bool isInitialized() const { return !StrBuffer->empty(); }
461 
462 private:
463   /// Mutex used for parallel processing of debug info.
464   std::mutex WriterMutex;
465   /// Initializes Buffer and Stream.
466   void initialize();
467   /// Creats internal data stractures.
468   void create();
469   std::unique_ptr<DebugStrBufferVector> StrBuffer;
470   std::unique_ptr<raw_svector_ostream> StrStream;
471   BinaryContext &BC;
472 };
473 
474 class DebugInfoBinaryPatcher;
475 class DebugAbbrevWriter;
476 enum class LocWriterKind { DebugLocWriter, DebugLoclistWriter };
477 
478 /// Serializes part of a .debug_loc DWARF section with LocationLists.
479 class SimpleBinaryPatcher;
480 class DebugLocWriter {
481 protected:
DebugLocWriter(uint8_t DwarfVersion,LocWriterKind Kind)482   DebugLocWriter(uint8_t DwarfVersion, LocWriterKind Kind)
483       : DwarfVersion(DwarfVersion), Kind(Kind) {
484     init();
485   }
486 
487 public:
DebugLocWriter()488   DebugLocWriter() { init(); };
~DebugLocWriter()489   virtual ~DebugLocWriter(){};
490 
491   /// Writes out location lists and stores internal patches.
492   virtual void addList(AttrInfo &AttrVal, DebugLocationsVector &LocList,
493                        DebugInfoBinaryPatcher &DebugInfoPatcher,
494                        DebugAbbrevWriter &AbbrevWriter);
495 
496   /// Writes out locations in to a local buffer, and adds Debug Info patches.
497   virtual void finalize(DebugInfoBinaryPatcher &DebugInfoPatcher,
498                         DebugAbbrevWriter &AbbrevWriter);
499 
500   /// Return internal buffer.
501   virtual std::unique_ptr<DebugBufferVector> getBuffer();
502 
503   /// Returns DWARF version.
getDwarfVersion()504   uint8_t getDwarfVersion() const { return DwarfVersion; }
505 
506   /// Offset of an empty location list.
507   static constexpr uint32_t EmptyListOffset = 0;
508 
getKind()509   LocWriterKind getKind() const { return Kind; }
510 
classof(const DebugLocWriter * Writer)511   static bool classof(const DebugLocWriter *Writer) {
512     return Writer->getKind() == LocWriterKind::DebugLocWriter;
513   }
514 
515 protected:
516   std::unique_ptr<DebugBufferVector> LocBuffer;
517   std::unique_ptr<raw_svector_ostream> LocStream;
518   /// Current offset in the section (updated as new entries are written).
519   /// Starts with 0 here since this only writes part of a full location lists
520   /// section. In the final section, for DWARF4, the first 16 bytes are reserved
521   /// for an empty list.
522   static uint32_t LocSectionOffset;
523   uint8_t DwarfVersion{4};
524   LocWriterKind Kind{LocWriterKind::DebugLocWriter};
525 
526 private:
527   /// Inits all the related data structures.
528   void init();
529   struct LocListDebugInfoPatchType {
530     uint64_t DebugInfoAttrOffset;
531     uint64_t LocListOffset;
532   };
533   using VectorLocListDebugInfoPatchType =
534       std::vector<LocListDebugInfoPatchType>;
535   /// The list of debug info patches to be made once individual
536   /// location list writers have been filled
537   VectorLocListDebugInfoPatchType LocListDebugInfoPatches;
538 };
539 
540 class DebugLoclistWriter : public DebugLocWriter {
541 public:
~DebugLoclistWriter()542   ~DebugLoclistWriter() {}
543   DebugLoclistWriter() = delete;
DebugLoclistWriter(DWARFUnit & Unit,uint8_t DV,bool SD)544   DebugLoclistWriter(DWARFUnit &Unit, uint8_t DV, bool SD)
545       : DebugLocWriter(DV, LocWriterKind::DebugLoclistWriter), CU(Unit),
546         IsSplitDwarf(SD) {
547     assert(DebugLoclistWriter::AddrWriter &&
548            "Please use SetAddressWriter to initialize "
549            "DebugAddrWriter before instantiation.");
550     if (DwarfVersion >= 5) {
551       LocBodyBuffer = std::make_unique<DebugBufferVector>();
552       LocBodyStream = std::make_unique<raw_svector_ostream>(*LocBodyBuffer);
553     } else {
554       // Writing out empty location list to which all references to empty
555       // location lists will point.
556       const char Zeroes[16] = {0};
557       *LocStream << StringRef(Zeroes, 16);
558     }
559   }
560 
setAddressWriter(DebugAddrWriter * AddrW)561   static void setAddressWriter(DebugAddrWriter *AddrW) { AddrWriter = AddrW; }
562 
563   /// Stores location lists internally to be written out during finalize phase.
564   virtual void addList(AttrInfo &AttrVal, DebugLocationsVector &LocList,
565                        DebugInfoBinaryPatcher &DebugInfoPatcher,
566                        DebugAbbrevWriter &AbbrevWriter) override;
567 
568   /// Writes out locations in to a local buffer and applies debug info patches.
569   void finalize(DebugInfoBinaryPatcher &DebugInfoPatcher,
570                 DebugAbbrevWriter &AbbrevWriter) override;
571 
572   /// Returns CU ID.
573   /// For Skelton CU it is a CU Offset.
574   /// For DWO CU it is a DWO ID.
getCUID()575   uint64_t getCUID() const {
576     return CU.isDWOUnit() ? *CU.getDWOId() : CU.getOffset();
577   }
578 
getKind()579   LocWriterKind getKind() const { return DebugLocWriter::getKind(); }
580 
classof(const DebugLocWriter * Writer)581   static bool classof(const DebugLocWriter *Writer) {
582     return Writer->getKind() == LocWriterKind::DebugLoclistWriter;
583   }
584 
isSplitDwarf()585   bool isSplitDwarf() const { return IsSplitDwarf; }
586 
587   constexpr static uint32_t InvalidIndex = UINT32_MAX;
588 
589 private:
590   /// Writes out locations in to a local buffer and applies debug info patches.
591   void finalizeDWARF5(DebugInfoBinaryPatcher &DebugInfoPatcher,
592                       DebugAbbrevWriter &AbbrevWriter);
593 
594   static DebugAddrWriter *AddrWriter;
595   DWARFUnit &CU;
596   bool IsSplitDwarf{false};
597   // Used for DWARF5 to store location lists before being finalized.
598   std::unique_ptr<DebugBufferVector> LocBodyBuffer;
599   std::unique_ptr<raw_svector_ostream> LocBodyStream;
600   std::vector<uint32_t> RelativeLocListOffsets;
601   uint32_t NumberOfEntries{0};
602   static uint32_t LoclistBaseOffset;
603 };
604 
605 enum class PatcherKind { SimpleBinaryPatcher, DebugInfoBinaryPatcher };
606 /// Abstract interface for classes that apply modifications to a binary string.
607 class BinaryPatcher {
608 public:
~BinaryPatcher()609   virtual ~BinaryPatcher() {}
610   /// Applies modifications to the copy of binary string \p BinaryContents .
611   /// Implementations do not need to guarantee that size of a new \p
612   /// BinaryContents remains unchanged.
613   virtual std::string patchBinary(StringRef BinaryContents) = 0;
614 };
615 
616 /// Applies simple modifications to a binary string, such as directly replacing
617 /// the contents of a certain portion with a string or an integer.
618 class SimpleBinaryPatcher : public BinaryPatcher {
619 private:
620   std::vector<std::pair<uint32_t, std::string>> Patches;
621 
622   /// Adds a patch to replace the contents of \p ByteSize bytes with the integer
623   /// \p NewValue encoded in little-endian, with the least-significant byte
624   /// being written at the offset \p Offset.
625   void addLEPatch(uint64_t Offset, uint64_t NewValue, size_t ByteSize);
626 
627   /// RangeBase for DWO DebugInfo Patcher.
628   uint64_t RangeBase{0};
629 
630   /// Gets reset to false when setRangeBase is invoked.
631   /// Gets set to true when getRangeBase is called
632   uint64_t WasRangeBaseUsed{false};
633 
634 public:
~SimpleBinaryPatcher()635   virtual ~SimpleBinaryPatcher() {}
636 
getKind()637   virtual PatcherKind getKind() const {
638     return PatcherKind::SimpleBinaryPatcher;
639   }
640 
classof(const SimpleBinaryPatcher * Patcher)641   static bool classof(const SimpleBinaryPatcher *Patcher) {
642     return Patcher->getKind() == PatcherKind::SimpleBinaryPatcher;
643   }
644 
645   /// Adds a patch to replace the contents of the binary string starting at the
646   /// specified \p Offset with the string \p NewValue.
647   /// The \p OldValueSize is the size of the old value that will be replaced.
648   void addBinaryPatch(uint64_t Offset, std::string &&NewValue,
649                       uint32_t OldValueSize);
650 
651   /// Adds a patch to replace the contents of a single byte of the string, at
652   /// the offset \p Offset, with the value \Value.
653   void addBytePatch(uint64_t Offset, uint8_t Value);
654 
655   /// Adds a patch to put the integer \p NewValue encoded as a 64-bit
656   /// little-endian value at offset \p Offset.
657   virtual void addLE64Patch(uint64_t Offset, uint64_t NewValue);
658 
659   /// Adds a patch to put the integer \p NewValue encoded as a 32-bit
660   /// little-endian value at offset \p Offset.
661   /// The \p OldValueSize is the size of the old value that will be replaced.
662   virtual void addLE32Patch(uint64_t Offset, uint32_t NewValue,
663                             uint32_t OldValueSize = 4);
664 
665   /// Add a patch at \p Offset with \p Value using unsigned LEB128 encoding with
666   /// size \p OldValueSize.
667   /// The \p OldValueSize is the size of the old value that will be replaced.
668   virtual void addUDataPatch(uint64_t Offset, uint64_t Value,
669                              uint32_t OldValueSize);
670 
671   /// Setting DW_AT_GNU_ranges_base
setRangeBase(uint64_t Rb)672   void setRangeBase(uint64_t Rb) {
673     WasRangeBaseUsed = false;
674     RangeBase = Rb;
675   }
676 
677   /// Gets DW_AT_GNU_ranges_base
getRangeBase()678   uint64_t getRangeBase() {
679     WasRangeBaseUsed = true;
680     return RangeBase;
681   }
682 
683   /// Proxy for if we broke up low_pc/high_pc to ranges.
getWasRangBasedUsed()684   bool getWasRangBasedUsed() const { return WasRangeBaseUsed; }
685 
686   /// This function takes in \p BinaryContents, applies patches to it and
687   /// returns an updated string.
688   virtual std::string patchBinary(StringRef BinaryContents) override;
689 };
690 
691 class DebugInfoBinaryPatcher : public SimpleBinaryPatcher {
692 public:
693   enum class DebugPatchKind {
694     PatchBaseClass,
695     PatchValue32,
696     PatchValue64to32,
697     PatchValue32GenericSize,
698     PatchValue64,
699     PatchValueVariable,
700     ReferencePatchValue,
701     DWARFUnitOffsetBaseLabel,
702     DestinationReferenceLabel,
703     NewDebugEntry
704   };
705 
706   struct Patch {
PatchPatch707     Patch(uint32_t O, DebugPatchKind K) : Offset(O), Kind(K) {}
getKindPatch708     DebugPatchKind getKind() const { return Kind; }
709 
classofPatch710     static bool classof(const Patch *Writer) {
711       return Writer->getKind() == DebugPatchKind::PatchBaseClass;
712     }
713 
714     uint32_t Offset;
715     DebugPatchKind Kind;
716   };
717 
718   struct DebugPatch64to32 : public Patch {
DebugPatch64to32DebugPatch64to32719     DebugPatch64to32(uint32_t O, uint32_t V)
720         : Patch(O, DebugPatchKind::PatchValue64to32) {
721       Value = V;
722     }
getKindDebugPatch64to32723     DebugPatchKind getKind() const { return Kind; }
724 
classofDebugPatch64to32725     static bool classof(const Patch *Writer) {
726       return Writer->getKind() == DebugPatchKind::PatchValue64to32;
727     }
728     uint32_t Value;
729   };
730 
731   struct DebugPatch32 : public Patch {
DebugPatch32DebugPatch32732     DebugPatch32(uint32_t O, uint32_t V)
733         : Patch(O, DebugPatchKind::PatchValue32) {
734       Value = V;
735     }
getKindDebugPatch32736     DebugPatchKind getKind() const { return Kind; }
737 
classofDebugPatch32738     static bool classof(const Patch *Writer) {
739       return Writer->getKind() == DebugPatchKind::PatchValue32;
740     }
741     uint32_t Value;
742   };
743 
744   /// Patch for 4 byte entry, where original entry size is not 4 bytes or 8
745   /// bytes.
746   struct DebugPatch32GenericSize : public Patch {
DebugPatch32GenericSizeDebugPatch32GenericSize747     DebugPatch32GenericSize(uint32_t O, uint32_t V, uint32_t OVS)
748         : Patch(O, DebugPatchKind::PatchValue32GenericSize) {
749       Value = V;
750       OldValueSize = OVS;
751     }
752 
classofDebugPatch32GenericSize753     static bool classof(const Patch *Writer) {
754       return Writer->getKind() == DebugPatchKind::PatchValue32GenericSize;
755     }
756     uint32_t Value;
757     uint32_t OldValueSize;
758   };
759 
760   struct DebugPatch64 : public Patch {
DebugPatch64DebugPatch64761     DebugPatch64(uint32_t O, uint64_t V)
762         : Patch(O, DebugPatchKind::PatchValue64) {
763       Value = V;
764     }
765 
classofDebugPatch64766     static bool classof(const Patch *Writer) {
767       return Writer->getKind() == DebugPatchKind::PatchValue64;
768     }
769     uint64_t Value;
770   };
771 
772   struct DebugPatchVariableSize : public Patch {
DebugPatchVariableSizeDebugPatchVariableSize773     DebugPatchVariableSize(uint32_t O, uint32_t OVS, uint32_t V)
774         : Patch(O, DebugPatchKind::PatchValueVariable) {
775       OldValueSize = OVS;
776       Value = V;
777     }
778 
classofDebugPatchVariableSize779     static bool classof(const Patch *Writer) {
780       return Writer->getKind() == DebugPatchKind::PatchValueVariable;
781     }
782     uint32_t OldValueSize;
783     uint32_t Value;
784   };
785 
786   struct DebugPatchReference : public Patch {
787     struct Data {
788       uint32_t OldValueSize : 4;
789       uint32_t DirectRelative : 1;
790       uint32_t IndirectRelative : 1;
791       uint32_t DirectAbsolute : 1;
792     };
DebugPatchReferenceDebugPatchReference793     DebugPatchReference(uint32_t O, uint32_t OVS, uint32_t DO, dwarf::Form F)
794         : Patch(O, DebugPatchKind::ReferencePatchValue) {
795       PatchInfo.OldValueSize = OVS;
796       DestinationOffset = DO;
797       PatchInfo.DirectRelative =
798           F == dwarf::DW_FORM_ref1 || F == dwarf::DW_FORM_ref2 ||
799           F == dwarf::DW_FORM_ref4 || F == dwarf::DW_FORM_ref8;
800       PatchInfo.IndirectRelative = F == dwarf::DW_FORM_ref_udata;
801       PatchInfo.DirectAbsolute = F == dwarf::DW_FORM_ref_addr;
802     }
803 
classofDebugPatchReference804     static bool classof(const Patch *Writer) {
805       return Writer->getKind() == DebugPatchKind::ReferencePatchValue;
806     }
807     Data PatchInfo;
808     uint32_t DestinationOffset;
809   };
810 
811   struct DWARFUnitOffsetBaseLabel : public Patch {
DWARFUnitOffsetBaseLabelDWARFUnitOffsetBaseLabel812     DWARFUnitOffsetBaseLabel(uint32_t O)
813         : Patch(O, DebugPatchKind::DWARFUnitOffsetBaseLabel) {}
814 
classofDWARFUnitOffsetBaseLabel815     static bool classof(const Patch *Writer) {
816       return Writer->getKind() == DebugPatchKind::DWARFUnitOffsetBaseLabel;
817     }
818   };
819 
820   struct DestinationReferenceLabel : public Patch {
821     DestinationReferenceLabel() = delete;
DestinationReferenceLabelDestinationReferenceLabel822     DestinationReferenceLabel(uint32_t O)
823         : Patch(O, DebugPatchKind::DestinationReferenceLabel) {}
824 
classofDestinationReferenceLabel825     static bool classof(const Patch *Writer) {
826       return Writer->getKind() == DebugPatchKind::DestinationReferenceLabel;
827     }
828   };
829 
830   struct NewDebugEntry : public Patch {
831     NewDebugEntry() = delete;
NewDebugEntryNewDebugEntry832     NewDebugEntry(uint32_t O, std::string &&V)
833         : Patch(O, DebugPatchKind::NewDebugEntry) {
834       CurrentOrder = NewDebugEntry::OrderCounter++;
835       Value = std::move(V);
836     }
837 
classofNewDebugEntry838     static bool classof(const Patch *Writer) {
839       return Writer->getKind() == DebugPatchKind::NewDebugEntry;
840     }
841     static uint32_t OrderCounter;
842     uint32_t CurrentOrder;
843     std::string Value;
844   };
845 
getKind()846   virtual PatcherKind getKind() const override {
847     return PatcherKind::DebugInfoBinaryPatcher;
848   }
849 
classof(const SimpleBinaryPatcher * Patcher)850   static bool classof(const SimpleBinaryPatcher *Patcher) {
851     return Patcher->getKind() == PatcherKind::DebugInfoBinaryPatcher;
852   }
853 
854   /// This function takes in \p BinaryContents, and re-writes it with new
855   /// patches inserted into it. It returns an updated string.
856   virtual std::string patchBinary(StringRef BinaryContents) override;
857 
858   /// Adds a patch to put the integer \p NewValue encoded as a 64-bit
859   /// little-endian value at offset \p Offset.
860   virtual void addLE64Patch(uint64_t Offset, uint64_t NewValue) override;
861 
862   /// Adds a patch to put the integer \p NewValue encoded as a 32-bit
863   /// little-endian value at offset \p Offset.
864   /// The \p OldValueSize is the size of the old value that will be replaced.
865   virtual void addLE32Patch(uint64_t Offset, uint32_t NewValue,
866                             uint32_t OldValueSize = 4) override;
867 
868   /// Add a patch at \p Offset with \p Value using unsigned LEB128 encoding with
869   /// size \p OldValueSize.
870   /// The \p OldValueSize is the size of the old value that will be replaced.
871   virtual void addUDataPatch(uint64_t Offset, uint64_t Value,
872                              uint32_t OldValueSize) override;
873 
874   /// Adds a label \p Offset for DWARF UNit.
875   /// Used to recompute relative references.
876   void addUnitBaseOffsetLabel(uint64_t Offset);
877 
878   /// Adds a Label for destination. Either relative or explicit reference.
879   void addDestinationReferenceLabel(uint64_t Offset);
880 
881   /// Adds a reference at \p Offset to patch with new fully resolved \p
882   /// DestinationOffset . The \p OldValueSize is the original size of entry in
883   /// the DIE. The \p Form is the form of the entry.
884   void addReferenceToPatch(uint64_t Offset, uint32_t DestinationOffset,
885                            uint32_t OldValueSize, dwarf::Form Form);
886 
887   /// Inserts a new uint32_t \p Value at the end of \p DIE .
888   void insertNewEntry(const DWARFDie &DIE, uint32_t);
889 
890   /// Inserts a new encoded \p Value at the end of \p DIE .
891   void insertNewEntry(const DWARFDie &DIE, std::string &&Value);
892 
893   /// Clears unordered set for DestinationLabels.
clearDestinationLabels()894   void clearDestinationLabels() { DestinationLabels.clear(); }
895 
896   /// Sets DWARF Units offset, \p  DWPOffset , within DWP file.
setDWPOffset(uint64_t DWPOffset)897   void setDWPOffset(uint64_t DWPOffset) { DWPUnitOffset = DWPOffset; }
898 
899   /// When this function is invoked all of the DebugInfo Patches must be done.
900   /// Returns a map of old CU offsets to new offsets and new sizes.
901   CUOffsetMap computeNewOffsets(DWARFContext &DWCtx, bool IsDWOContext);
902 
903 private:
904   struct PatchDeleter {
operatorPatchDeleter905     void operator()(Patch *P) const {
906       Patch *Pp = reinterpret_cast<Patch *>(P);
907       switch (Pp->Kind) {
908       default:
909         llvm_unreachable(
910             "Not all delete instances handled for Patch derived classes");
911       case DebugPatchKind::PatchValue32:
912         delete reinterpret_cast<DebugPatch32 *>(P);
913         break;
914       case DebugPatchKind::PatchValue64to32:
915         delete reinterpret_cast<DebugPatch64to32 *>(P);
916         break;
917       case DebugPatchKind::PatchValue32GenericSize:
918         delete reinterpret_cast<DebugPatch32GenericSize *>(P);
919         break;
920       case DebugPatchKind::PatchValue64:
921         delete reinterpret_cast<DebugPatch64 *>(P);
922         break;
923       case DebugPatchKind::PatchValueVariable:
924         delete reinterpret_cast<DebugPatchVariableSize *>(P);
925         break;
926       case DebugPatchKind::ReferencePatchValue:
927         delete reinterpret_cast<DebugPatchReference *>(P);
928         break;
929       case DebugPatchKind::DWARFUnitOffsetBaseLabel:
930         delete reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P);
931         break;
932       case DebugPatchKind::DestinationReferenceLabel:
933         delete reinterpret_cast<DestinationReferenceLabel *>(P);
934         break;
935       case DebugPatchKind::NewDebugEntry:
936         delete reinterpret_cast<NewDebugEntry *>(P);
937         break;
938       }
939     }
940   };
941   using UniquePatchPtrType = std::unique_ptr<Patch, PatchDeleter>;
942 
943   uint64_t DWPUnitOffset{0};
944   int32_t ChangeInSize{0};
945   std::vector<UniquePatchPtrType> DebugPatches;
946   /// Mutex used for parallel processing of debug info.
947   std::mutex WriterMutex;
948   /// Stores fully resolved addresses of DIEs that are being referenced.
949   std::unordered_set<uint32_t> DestinationLabels;
950   /// Map of original debug info references to new ones.
951   std::unordered_map<uint32_t, uint32_t> OldToNewOffset;
952 };
953 
954 /// Class to facilitate modifying and writing abbreviation sections.
955 class DebugAbbrevWriter {
956   /// Mutex used for parallel processing of debug info.
957   std::mutex WriterMutex;
958 
959   /// Offsets of abbreviation sets in normal .debug_abbrev section.
960   std::vector<uint64_t> AbbrevSetOffsets;
961 
962   /// Abbrev data set for a single unit.
963   struct AbbrevData {
964     uint64_t Offset{0}; ///< Offset of the data in the final section.
965     std::unique_ptr<DebugBufferVector> Buffer;
966     std::unique_ptr<raw_svector_ostream> Stream;
967   };
968   /// Map original unit to abbreviations data.
969   std::unordered_map<const DWARFUnit *, AbbrevData *> UnitsAbbrevData;
970 
971   /// Map from Hash Signature to AbbrevData.
972   llvm::StringMap<std::unique_ptr<AbbrevData>> AbbrevDataCache;
973 
974   /// Attributes substitution (patch) information.
975   struct PatchInfo {
976     dwarf::Attribute OldAttr;
977     dwarf::Attribute NewAttr;
978     uint8_t NewAttrForm;
979   };
980 
981   struct AbbrevEntry {
982     dwarf::Attribute Attr;
983     dwarf::Form Form;
984   };
985 
986   using PatchesTy = std::unordered_map<const DWARFAbbreviationDeclaration *,
987                                        SmallVector<PatchInfo, 2>>;
988   std::unordered_map<const DWARFUnit *, PatchesTy> Patches;
989 
990   using AbbrevEntryTy = std::unordered_map<const DWARFAbbreviationDeclaration *,
991                                            SmallVector<AbbrevEntry, 2>>;
992   std::unordered_map<const DWARFUnit *, AbbrevEntryTy> NewAbbrevEntries;
993 
994   /// DWARF context containing abbreviations.
995   DWARFContext &Context;
996 
997   /// DWO ID used to identify unit contribution in DWP.
998   Optional<uint64_t> DWOId;
999 
1000   /// Add abbreviations from compile/type \p Unit to the writer.
1001   void addUnitAbbreviations(DWARFUnit &Unit);
1002 
1003 public:
1004   /// Create an abbrev section writer for abbreviations in \p Context.
1005   /// If no \p DWOId is given, all normal (non-DWO) abbreviations in the
1006   /// \p Context are handled. Otherwise, only abbreviations associated with
1007   /// the compile unit matching \p DWOId in DWP or DWO will be covered by
1008   /// an instance of this class.
1009   ///
1010   /// NOTE: Type unit abbreviations are not handled separately for DWOs.
1011   ///       Most of the time, using type units with DWO is not a good idea.
1012   ///       If type units are used, the caller is responsible for verifying
1013   ///       that abbreviations are shared by CU and TUs.
1014   DebugAbbrevWriter(DWARFContext &Context, Optional<uint64_t> DWOId = None)
Context(Context)1015       : Context(Context), DWOId(DWOId) {}
1016 
1017   DebugAbbrevWriter(const DebugAbbrevWriter &) = delete;
1018   DebugAbbrevWriter &operator=(const DebugAbbrevWriter &) = delete;
1019 
1020   DebugAbbrevWriter(DebugAbbrevWriter &&) = delete;
1021   DebugAbbrevWriter &operator=(DebugAbbrevWriter &&) = delete;
1022 
1023   virtual ~DebugAbbrevWriter() = default;
1024 
1025   /// Substitute attribute \p AttrTag in abbreviation declaration \p Abbrev
1026   /// belonging to CU \p Unit with new attribute \p NewAttrTag having
1027   /// \p NewAttrForm form.
addAttributePatch(const DWARFUnit & Unit,const DWARFAbbreviationDeclaration * Abbrev,dwarf::Attribute AttrTag,dwarf::Attribute NewAttrTag,uint8_t NewAttrForm)1028   void addAttributePatch(const DWARFUnit &Unit,
1029                          const DWARFAbbreviationDeclaration *Abbrev,
1030                          dwarf::Attribute AttrTag, dwarf::Attribute NewAttrTag,
1031                          uint8_t NewAttrForm) {
1032     assert(&Unit.getContext() == &Context &&
1033            "cannot update attribute from a different DWARF context");
1034     std::lock_guard<std::mutex> Lock(WriterMutex);
1035     Patches[&Unit][Abbrev].emplace_back(
1036         PatchInfo{AttrTag, NewAttrTag, NewAttrForm});
1037   }
1038 
1039   /// Adds attribute \p AttrTag and \p NewAttrForm in abbreviation declaration
1040   /// \p Abbrev belonging to CU \p Unit .
addAttribute(const DWARFUnit & Unit,const DWARFAbbreviationDeclaration * Abbrev,dwarf::Attribute AttrTag,dwarf::Form AttrForm)1041   void addAttribute(const DWARFUnit &Unit,
1042                     const DWARFAbbreviationDeclaration *Abbrev,
1043                     dwarf::Attribute AttrTag, dwarf::Form AttrForm) {
1044     assert(&Unit.getContext() == &Context &&
1045            "cannot update attribute from a different DWARF context");
1046     std::lock_guard<std::mutex> Lock(WriterMutex);
1047     bool AlreadyAdded = false;
1048     for (AbbrevEntry &E : NewAbbrevEntries[&Unit][Abbrev])
1049       if (E.Attr == AttrTag) {
1050         AlreadyAdded = true;
1051         break;
1052       }
1053 
1054     if (AlreadyAdded)
1055       return;
1056     NewAbbrevEntries[&Unit][Abbrev].emplace_back(
1057         AbbrevEntry{AttrTag, AttrForm});
1058   }
1059 
1060   /// Return a buffer with concatenated abbrev sections for all CUs and TUs
1061   /// in the associated DWARF context. Section offsets could be queried using
1062   /// getAbbreviationsOffsetForUnit() interface. For DWP, we are using DWOId
1063   /// to return only that unit's contribution to abbrev section.
1064   std::unique_ptr<DebugBufferVector> finalize();
1065 
1066   /// Return an offset in the finalized abbrev section corresponding to CU/TU.
getAbbreviationsOffsetForUnit(const DWARFUnit & Unit)1067   uint64_t getAbbreviationsOffsetForUnit(const DWARFUnit &Unit) {
1068     assert(!DWOId && "offsets are tracked for non-DWO units only");
1069     assert(UnitsAbbrevData.count(&Unit) && "no abbrev data found for unit");
1070     return UnitsAbbrevData[&Unit]->Offset;
1071   }
1072 };
1073 
1074 /// Similar to MCDwarfLineEntry, but identifies the location by its address
1075 /// instead of MCLabel.
1076 class BinaryDwarfLineEntry : public MCDwarfLoc {
1077   uint64_t Address;
1078 
1079 public:
1080   // Constructor to create an BinaryDwarfLineEntry given a symbol and the dwarf
1081   // loc.
BinaryDwarfLineEntry(uint64_t Address,const MCDwarfLoc loc)1082   BinaryDwarfLineEntry(uint64_t Address, const MCDwarfLoc loc)
1083       : MCDwarfLoc(loc), Address(Address) {}
1084 
getAddress()1085   uint64_t getAddress() const { return Address; }
1086 };
1087 
1088 /// Line number information for the output binary. One instance per CU.
1089 ///
1090 /// For any given CU, we may:
1091 ///   1. Generate new line table using:
1092 ///     a) emitted code: getMCLineSections().addEntry()
1093 ///     b) information from the input line table: addLineTableSequence()
1094 /// or
1095 ///   2. Copy line table from the input file: addRawContents().
1096 class DwarfLineTable {
1097 public:
1098   /// Line number information on contiguous code region from the input binary.
1099   /// It is represented by [FirstIndex, LastIndex] rows range in the input
1100   /// line table, and the end address of the sequence used for issuing the end
1101   /// of the sequence directive.
1102   struct RowSequence {
1103     uint32_t FirstIndex;
1104     uint32_t LastIndex;
1105     uint64_t EndAddress;
1106   };
1107 
1108 private:
1109   MCDwarfLineTableHeader Header;
1110 
1111   /// MC line tables for the code generated via MC layer.
1112   MCLineSection MCLineSections;
1113 
1114   /// Line info for the original code. To be merged with tables for new code.
1115   const DWARFDebugLine::LineTable *InputTable{nullptr};
1116   std::vector<RowSequence> InputSequences;
1117 
1118   /// Raw data representing complete debug line section for the unit.
1119   StringRef RawData;
1120 
1121   /// DWARF Version
1122   uint16_t DwarfVersion;
1123 
1124 public:
1125   /// Emit line info for all units in the binary context.
1126   static void emit(BinaryContext &BC, MCStreamer &Streamer);
1127 
1128   /// Emit the Dwarf file and the line tables for a given CU.
1129   void emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params,
1130               Optional<MCDwarfLineStr> &LineStr, BinaryContext &BC) const;
1131 
1132   Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName,
1133                                 Optional<MD5::MD5Result> Checksum,
1134                                 Optional<StringRef> Source,
1135                                 uint16_t DwarfVersion,
1136                                 unsigned FileNumber = 0) {
1137     assert(RawData.empty() && "cannot use with raw data");
1138     return Header.tryGetFile(Directory, FileName, Checksum, Source,
1139                              DwarfVersion, FileNumber);
1140   }
1141 
1142   /// Return label at the start of the emitted debug line for the unit.
getLabel()1143   MCSymbol *getLabel() const { return Header.Label; }
1144 
setLabel(MCSymbol * Label)1145   void setLabel(MCSymbol *Label) { Header.Label = Label; }
1146 
1147   /// Sets the root file \p Directory, \p FileName, optional \p CheckSum, and
1148   /// optional \p Source.
setRootFile(StringRef Directory,StringRef FileName,Optional<MD5::MD5Result> Checksum,Optional<StringRef> Source)1149   void setRootFile(StringRef Directory, StringRef FileName,
1150                    Optional<MD5::MD5Result> Checksum,
1151                    Optional<StringRef> Source) {
1152     Header.setRootFile(Directory, FileName, Checksum, Source);
1153   }
1154 
1155   /// Access to MC line info.
getMCLineSections()1156   MCLineSection &getMCLineSections() { return MCLineSections; }
1157 
1158   /// Add line information using the sequence from the input line \p Table.
addLineTableSequence(const DWARFDebugLine::LineTable * Table,uint32_t FirstRow,uint32_t LastRow,uint64_t EndOfSequenceAddress)1159   void addLineTableSequence(const DWARFDebugLine::LineTable *Table,
1160                             uint32_t FirstRow, uint32_t LastRow,
1161                             uint64_t EndOfSequenceAddress) {
1162     assert((!InputTable || InputTable == Table) &&
1163            "expected same table for CU");
1164     InputTable = Table;
1165     InputSequences.emplace_back(
1166         RowSequence{FirstRow, LastRow, EndOfSequenceAddress});
1167   }
1168 
1169   /// Indicate that for the unit we should emit specified contents instead of
1170   /// generating a new line info table.
addRawContents(StringRef DebugLineContents)1171   void addRawContents(StringRef DebugLineContents) {
1172     RawData = DebugLineContents;
1173   }
1174 
1175   /// Sets DWARF version for this line table.
setDwarfVersion(uint16_t V)1176   void setDwarfVersion(uint16_t V) { DwarfVersion = V; }
1177 
1178   // Returns DWARF Version for this line table.
getDwarfVersion()1179   uint16_t getDwarfVersion() const { return DwarfVersion; }
1180 };
1181 } // namespace bolt
1182 } // namespace llvm
1183 
1184 #endif
1185