1 //===- Range.h --------------------------------------------------*- 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 #ifndef LLVM_DEBUGINFO_GSYM_RANGE_H 10 #define LLVM_DEBUGINFO_GSYM_RANGE_H 11 12 #include "llvm/Support/Format.h" 13 #include "llvm/Support/raw_ostream.h" 14 #include <stdint.h> 15 #include <vector> 16 17 #define HEX8(v) llvm::format_hex(v, 4) 18 #define HEX16(v) llvm::format_hex(v, 6) 19 #define HEX32(v) llvm::format_hex(v, 10) 20 #define HEX64(v) llvm::format_hex(v, 18) 21 22 namespace llvm { 23 class DataExtractor; 24 class raw_ostream; 25 26 namespace gsym { 27 28 class FileWriter; 29 30 /// A class that represents an address range. The range is specified using 31 /// a start and an end address. 32 struct AddressRange { 33 uint64_t Start; 34 uint64_t End; AddressRangeAddressRange35 AddressRange() : Start(0), End(0) {} AddressRangeAddressRange36 AddressRange(uint64_t S, uint64_t E) : Start(S), End(E) {} sizeAddressRange37 uint64_t size() const { return End - Start; } containsAddressRange38 bool contains(uint64_t Addr) const { return Start <= Addr && Addr < End; } intersectsAddressRange39 bool intersects(const AddressRange &R) const { 40 return Start < R.End && R.Start < End; 41 } 42 43 bool operator==(const AddressRange &R) const { 44 return Start == R.Start && End == R.End; 45 } 46 bool operator!=(const AddressRange &R) const { 47 return !(*this == R); 48 } 49 bool operator<(const AddressRange &R) const { 50 return std::make_pair(Start, End) < std::make_pair(R.Start, R.End); 51 } 52 /// AddressRange objects are encoded and decoded to be relative to a base 53 /// address. This will be the FunctionInfo's start address if the AddressRange 54 /// is directly contained in a FunctionInfo, or a base address of the 55 /// containing parent AddressRange or AddressRanges. This allows address 56 /// ranges to be efficiently encoded using ULEB128 encodings as we encode the 57 /// offset and size of each range instead of full addresses. This also makes 58 /// encoded addresses easy to relocate as we just need to relocate one base 59 /// address. 60 /// @{ 61 void decode(DataExtractor &Data, uint64_t BaseAddr, uint64_t &Offset); 62 void encode(FileWriter &O, uint64_t BaseAddr) const; 63 /// @} 64 65 /// Skip an address range object in the specified data a the specified 66 /// offset. 67 /// 68 /// \param Data The binary stream to read the data from. 69 /// 70 /// \param Offset The byte offset within \a Data. 71 static void skip(DataExtractor &Data, uint64_t &Offset); 72 }; 73 74 raw_ostream &operator<<(raw_ostream &OS, const AddressRange &R); 75 76 /// The AddressRanges class helps normalize address range collections. 77 /// This class keeps a sorted vector of AddressRange objects and can perform 78 /// insertions and searches efficiently. The address ranges are always sorted 79 /// and never contain any invalid or empty address ranges. This allows us to 80 /// emit address ranges into the GSYM file efficiently. Intersecting address 81 /// ranges are combined during insertion so that we can emit the most compact 82 /// representation for address ranges when writing to disk. 83 class AddressRanges { 84 protected: 85 using Collection = std::vector<AddressRange>; 86 Collection Ranges; 87 public: clear()88 void clear() { Ranges.clear(); } empty()89 bool empty() const { return Ranges.empty(); } 90 bool contains(uint64_t Addr) const; 91 bool contains(AddressRange Range) const; 92 void insert(AddressRange Range); size()93 size_t size() const { return Ranges.size(); } 94 bool operator==(const AddressRanges &RHS) const { 95 return Ranges == RHS.Ranges; 96 } 97 const AddressRange &operator[](size_t i) const { 98 assert(i < Ranges.size()); 99 return Ranges[i]; 100 } begin()101 Collection::const_iterator begin() const { return Ranges.begin(); } end()102 Collection::const_iterator end() const { return Ranges.end(); } 103 104 /// Address ranges are decoded and encoded to be relative to a base address. 105 /// See the AddressRange comment for the encode and decode methods for full 106 /// details. 107 /// @{ 108 void decode(DataExtractor &Data, uint64_t BaseAddr, uint64_t &Offset); 109 void encode(FileWriter &O, uint64_t BaseAddr) const; 110 /// @} 111 112 /// Skip an address range object in the specified data a the specified 113 /// offset. 114 /// 115 /// \param Data The binary stream to read the data from. 116 /// 117 /// \param Offset The byte offset within \a Data. 118 /// 119 /// \returns The number of address ranges that were skipped. 120 static uint64_t skip(DataExtractor &Data, uint64_t &Offset); 121 }; 122 123 raw_ostream &operator<<(raw_ostream &OS, const AddressRanges &AR); 124 125 } // namespace gsym 126 } // namespace llvm 127 128 #endif // #ifndef LLVM_DEBUGINFO_GSYM_RANGE_H 129