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