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