DWARFDebugAbbrev.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. //===- DWARFDebugAbbrev.cpp -----------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
  9. #include "llvm/Support/Format.h"
  10. #include "llvm/Support/raw_ostream.h"
  11. #include <algorithm>
  12. #include <cinttypes>
  13. #include <cstdint>
  14. using namespace llvm;
  15. DWARFAbbreviationDeclarationSet::DWARFAbbreviationDeclarationSet() {
  16. clear();
  17. }
  18. void DWARFAbbreviationDeclarationSet::clear() {
  19. Offset = 0;
  20. FirstAbbrCode = 0;
  21. Decls.clear();
  22. }
  23. bool DWARFAbbreviationDeclarationSet::extract(DataExtractor Data,
  24. uint64_t *OffsetPtr) {
  25. clear();
  26. const uint64_t BeginOffset = *OffsetPtr;
  27. Offset = BeginOffset;
  28. DWARFAbbreviationDeclaration AbbrDecl;
  29. uint32_t PrevAbbrCode = 0;
  30. while (AbbrDecl.extract(Data, OffsetPtr)) {
  31. if (FirstAbbrCode == 0) {
  32. FirstAbbrCode = AbbrDecl.getCode();
  33. } else {
  34. if (PrevAbbrCode + 1 != AbbrDecl.getCode()) {
  35. // Codes are not consecutive, can't do O(1) lookups.
  36. FirstAbbrCode = UINT32_MAX;
  37. }
  38. }
  39. PrevAbbrCode = AbbrDecl.getCode();
  40. Decls.push_back(std::move(AbbrDecl));
  41. }
  42. return BeginOffset != *OffsetPtr;
  43. }
  44. void DWARFAbbreviationDeclarationSet::dump(raw_ostream &OS) const {
  45. for (const auto &Decl : Decls)
  46. Decl.dump(OS);
  47. }
  48. const DWARFAbbreviationDeclaration *
  49. DWARFAbbreviationDeclarationSet::getAbbreviationDeclaration(
  50. uint32_t AbbrCode) const {
  51. if (FirstAbbrCode == UINT32_MAX) {
  52. for (const auto &Decl : Decls) {
  53. if (Decl.getCode() == AbbrCode)
  54. return &Decl;
  55. }
  56. return nullptr;
  57. }
  58. if (AbbrCode < FirstAbbrCode || AbbrCode >= FirstAbbrCode + Decls.size())
  59. return nullptr;
  60. return &Decls[AbbrCode - FirstAbbrCode];
  61. }
  62. std::string DWARFAbbreviationDeclarationSet::getCodeRange() const {
  63. // Create a sorted list of all abbrev codes.
  64. std::vector<uint32_t> Codes;
  65. Codes.reserve(Decls.size());
  66. for (const auto &Decl : Decls)
  67. Codes.push_back(Decl.getCode());
  68. std::string Buffer;
  69. raw_string_ostream Stream(Buffer);
  70. // Each iteration through this loop represents a single contiguous range in
  71. // the set of codes.
  72. for (auto Current = Codes.begin(), End = Codes.end(); Current != End;) {
  73. uint32_t RangeStart = *Current;
  74. // Add the current range start.
  75. Stream << *Current;
  76. uint32_t RangeEnd = RangeStart;
  77. // Find the end of the current range.
  78. while (++Current != End && *Current == RangeEnd + 1)
  79. ++RangeEnd;
  80. // If there is more than one value in the range, add the range end too.
  81. if (RangeStart != RangeEnd)
  82. Stream << "-" << RangeEnd;
  83. // If there is at least one more range, add a separator.
  84. if (Current != End)
  85. Stream << ", ";
  86. }
  87. return Buffer;
  88. }
  89. DWARFDebugAbbrev::DWARFDebugAbbrev() { clear(); }
  90. void DWARFDebugAbbrev::clear() {
  91. AbbrDeclSets.clear();
  92. PrevAbbrOffsetPos = AbbrDeclSets.end();
  93. }
  94. void DWARFDebugAbbrev::extract(DataExtractor Data) {
  95. clear();
  96. this->Data = Data;
  97. }
  98. void DWARFDebugAbbrev::parse() const {
  99. if (!Data)
  100. return;
  101. uint64_t Offset = 0;
  102. auto I = AbbrDeclSets.begin();
  103. while (Data->isValidOffset(Offset)) {
  104. while (I != AbbrDeclSets.end() && I->first < Offset)
  105. ++I;
  106. uint64_t CUAbbrOffset = Offset;
  107. DWARFAbbreviationDeclarationSet AbbrDecls;
  108. if (!AbbrDecls.extract(*Data, &Offset))
  109. break;
  110. AbbrDeclSets.insert(I, std::make_pair(CUAbbrOffset, std::move(AbbrDecls)));
  111. }
  112. Data = None;
  113. }
  114. void DWARFDebugAbbrev::dump(raw_ostream &OS) const {
  115. parse();
  116. if (AbbrDeclSets.empty()) {
  117. OS << "< EMPTY >\n";
  118. return;
  119. }
  120. for (const auto &I : AbbrDeclSets) {
  121. OS << format("Abbrev table for offset: 0x%8.8" PRIx64 "\n", I.first);
  122. I.second.dump(OS);
  123. }
  124. }
  125. const DWARFAbbreviationDeclarationSet*
  126. DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const {
  127. const auto End = AbbrDeclSets.end();
  128. if (PrevAbbrOffsetPos != End && PrevAbbrOffsetPos->first == CUAbbrOffset) {
  129. return &(PrevAbbrOffsetPos->second);
  130. }
  131. const auto Pos = AbbrDeclSets.find(CUAbbrOffset);
  132. if (Pos != End) {
  133. PrevAbbrOffsetPos = Pos;
  134. return &(Pos->second);
  135. }
  136. if (Data && CUAbbrOffset < Data->getData().size()) {
  137. uint64_t Offset = CUAbbrOffset;
  138. DWARFAbbreviationDeclarationSet AbbrDecls;
  139. if (!AbbrDecls.extract(*Data, &Offset))
  140. return nullptr;
  141. PrevAbbrOffsetPos =
  142. AbbrDeclSets.insert(std::make_pair(CUAbbrOffset, std::move(AbbrDecls)))
  143. .first;
  144. return &PrevAbbrOffsetPos->second;
  145. }
  146. return nullptr;
  147. }