DWARFDebugAranges.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. //===-- DWARFDebugAranges.cpp -----------------------------------*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h"
  10. #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
  11. #include "llvm/DebugInfo/DWARF/DWARFContext.h"
  12. #include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
  13. #include "llvm/Support/Format.h"
  14. #include "llvm/Support/raw_ostream.h"
  15. #include <algorithm>
  16. #include <cassert>
  17. #include <set>
  18. using namespace llvm;
  19. void DWARFDebugAranges::extract(DataExtractor DebugArangesData) {
  20. if (!DebugArangesData.isValidOffset(0))
  21. return;
  22. uint32_t Offset = 0;
  23. DWARFDebugArangeSet Set;
  24. while (Set.extract(DebugArangesData, &Offset)) {
  25. uint32_t CUOffset = Set.getCompileUnitDIEOffset();
  26. for (const auto &Desc : Set.descriptors()) {
  27. uint64_t LowPC = Desc.Address;
  28. uint64_t HighPC = Desc.getEndAddress();
  29. appendRange(CUOffset, LowPC, HighPC);
  30. }
  31. ParsedCUOffsets.insert(CUOffset);
  32. }
  33. }
  34. void DWARFDebugAranges::generate(DWARFContext *CTX) {
  35. clear();
  36. if (!CTX)
  37. return;
  38. // Extract aranges from .debug_aranges section.
  39. DataExtractor ArangesData(CTX->getARangeSection(), CTX->isLittleEndian(), 0);
  40. extract(ArangesData);
  41. // Generate aranges from DIEs: even if .debug_aranges section is present,
  42. // it may describe only a small subset of compilation units, so we need to
  43. // manually build aranges for the rest of them.
  44. for (const auto &CU : CTX->compile_units()) {
  45. uint32_t CUOffset = CU->getOffset();
  46. if (ParsedCUOffsets.insert(CUOffset).second) {
  47. DWARFAddressRangesVector CURanges;
  48. CU->collectAddressRanges(CURanges);
  49. for (const auto &R : CURanges) {
  50. appendRange(CUOffset, R.first, R.second);
  51. }
  52. }
  53. }
  54. construct();
  55. }
  56. void DWARFDebugAranges::clear() {
  57. Endpoints.clear();
  58. Aranges.clear();
  59. ParsedCUOffsets.clear();
  60. }
  61. void DWARFDebugAranges::appendRange(uint32_t CUOffset, uint64_t LowPC,
  62. uint64_t HighPC) {
  63. if (LowPC >= HighPC)
  64. return;
  65. Endpoints.emplace_back(LowPC, CUOffset, true);
  66. Endpoints.emplace_back(HighPC, CUOffset, false);
  67. }
  68. void DWARFDebugAranges::construct() {
  69. std::multiset<uint32_t> ValidCUs; // Maintain the set of CUs describing
  70. // a current address range.
  71. std::sort(Endpoints.begin(), Endpoints.end());
  72. uint64_t PrevAddress = -1ULL;
  73. for (const auto &E : Endpoints) {
  74. if (PrevAddress < E.Address && ValidCUs.size() > 0) {
  75. // If the address range between two endpoints is described by some
  76. // CU, first try to extend the last range in Aranges. If we can't
  77. // do it, start a new range.
  78. if (!Aranges.empty() && Aranges.back().HighPC() == PrevAddress &&
  79. ValidCUs.find(Aranges.back().CUOffset) != ValidCUs.end()) {
  80. Aranges.back().setHighPC(E.Address);
  81. } else {
  82. Aranges.emplace_back(PrevAddress, E.Address, *ValidCUs.begin());
  83. }
  84. }
  85. // Update the set of valid CUs.
  86. if (E.IsRangeStart) {
  87. ValidCUs.insert(E.CUOffset);
  88. } else {
  89. auto CUPos = ValidCUs.find(E.CUOffset);
  90. assert(CUPos != ValidCUs.end());
  91. ValidCUs.erase(CUPos);
  92. }
  93. PrevAddress = E.Address;
  94. }
  95. assert(ValidCUs.empty());
  96. // Endpoints are not needed now.
  97. std::vector<RangeEndpoint> EmptyEndpoints;
  98. EmptyEndpoints.swap(Endpoints);
  99. }
  100. uint32_t DWARFDebugAranges::findAddress(uint64_t Address) const {
  101. if (!Aranges.empty()) {
  102. Range range(Address);
  103. RangeCollIterator begin = Aranges.begin();
  104. RangeCollIterator end = Aranges.end();
  105. RangeCollIterator pos =
  106. std::lower_bound(begin, end, range);
  107. if (pos != end && pos->containsAddress(Address)) {
  108. return pos->CUOffset;
  109. } else if (pos != begin) {
  110. --pos;
  111. if (pos->containsAddress(Address))
  112. return pos->CUOffset;
  113. }
  114. }
  115. return -1U;
  116. }