Range.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. //===- Range.cpp ------------------------------------------------*- 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. #include "llvm/DebugInfo/GSYM/Range.h"
  9. #include "llvm/DebugInfo/GSYM/FileWriter.h"
  10. #include "llvm/Support/DataExtractor.h"
  11. #include <algorithm>
  12. #include <inttypes.h>
  13. using namespace llvm;
  14. using namespace gsym;
  15. void AddressRanges::insert(AddressRange Range) {
  16. if (Range.size() == 0)
  17. return;
  18. auto It = llvm::upper_bound(Ranges, Range);
  19. auto It2 = It;
  20. while (It2 != Ranges.end() && It2->Start < Range.End)
  21. ++It2;
  22. if (It != It2) {
  23. Range.End = std::max(Range.End, It2[-1].End);
  24. It = Ranges.erase(It, It2);
  25. }
  26. if (It != Ranges.begin() && Range.Start < It[-1].End)
  27. It[-1].End = std::max(It[-1].End, Range.End);
  28. else
  29. Ranges.insert(It, Range);
  30. }
  31. bool AddressRanges::contains(uint64_t Addr) const {
  32. auto It = std::partition_point(
  33. Ranges.begin(), Ranges.end(),
  34. [=](const AddressRange &R) { return R.Start <= Addr; });
  35. return It != Ranges.begin() && Addr < It[-1].End;
  36. }
  37. bool AddressRanges::contains(AddressRange Range) const {
  38. if (Range.size() == 0)
  39. return false;
  40. auto It = std::partition_point(
  41. Ranges.begin(), Ranges.end(),
  42. [=](const AddressRange &R) { return R.Start <= Range.Start; });
  43. if (It == Ranges.begin())
  44. return false;
  45. return Range.End <= It[-1].End;
  46. }
  47. Optional<AddressRange>
  48. AddressRanges::getRangeThatContains(uint64_t Addr) const {
  49. auto It = std::partition_point(
  50. Ranges.begin(), Ranges.end(),
  51. [=](const AddressRange &R) { return R.Start <= Addr; });
  52. if (It != Ranges.begin() && Addr < It[-1].End)
  53. return It[-1];
  54. return llvm::None;
  55. }
  56. raw_ostream &llvm::gsym::operator<<(raw_ostream &OS, const AddressRange &R) {
  57. return OS << '[' << HEX64(R.Start) << " - " << HEX64(R.End) << ")";
  58. }
  59. raw_ostream &llvm::gsym::operator<<(raw_ostream &OS, const AddressRanges &AR) {
  60. size_t Size = AR.size();
  61. for (size_t I = 0; I < Size; ++I) {
  62. if (I)
  63. OS << ' ';
  64. OS << AR[I];
  65. }
  66. return OS;
  67. }
  68. void AddressRange::encode(FileWriter &O, uint64_t BaseAddr) const {
  69. assert(Start >= BaseAddr);
  70. O.writeULEB(Start - BaseAddr);
  71. O.writeULEB(size());
  72. }
  73. void AddressRange::decode(DataExtractor &Data, uint64_t BaseAddr,
  74. uint64_t &Offset) {
  75. const uint64_t AddrOffset = Data.getULEB128(&Offset);
  76. const uint64_t Size = Data.getULEB128(&Offset);
  77. const uint64_t StartAddr = BaseAddr + AddrOffset;
  78. Start = StartAddr;
  79. End = StartAddr + Size;
  80. }
  81. void AddressRanges::encode(FileWriter &O, uint64_t BaseAddr) const {
  82. O.writeULEB(Ranges.size());
  83. if (Ranges.empty())
  84. return;
  85. for (auto Range : Ranges)
  86. Range.encode(O, BaseAddr);
  87. }
  88. void AddressRanges::decode(DataExtractor &Data, uint64_t BaseAddr,
  89. uint64_t &Offset) {
  90. clear();
  91. uint64_t NumRanges = Data.getULEB128(&Offset);
  92. if (NumRanges == 0)
  93. return;
  94. Ranges.resize(NumRanges);
  95. for (auto &Range : Ranges)
  96. Range.decode(Data, BaseAddr, Offset);
  97. }
  98. void AddressRange::skip(DataExtractor &Data, uint64_t &Offset) {
  99. Data.getULEB128(&Offset);
  100. Data.getULEB128(&Offset);
  101. }
  102. uint64_t AddressRanges::skip(DataExtractor &Data, uint64_t &Offset) {
  103. uint64_t NumRanges = Data.getULEB128(&Offset);
  104. for (uint64_t I=0; I<NumRanges; ++I)
  105. AddressRange::skip(Data, Offset);
  106. return NumRanges;
  107. }