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