xref: /aosp_15_r20/external/llvm/lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===- MappedBlockStream.cpp - Reads stream data from a PDBFile -----------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker 
10*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
11*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/DirectoryStreamData.h"
12*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/IPDBStreamData.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/RawError.h"
16*9880d681SAndroid Build Coastguard Worker 
17*9880d681SAndroid Build Coastguard Worker using namespace llvm;
18*9880d681SAndroid Build Coastguard Worker using namespace llvm::pdb;
19*9880d681SAndroid Build Coastguard Worker 
20*9880d681SAndroid Build Coastguard Worker namespace {
21*9880d681SAndroid Build Coastguard Worker // This exists so that we can use make_unique while still keeping the
22*9880d681SAndroid Build Coastguard Worker // constructor of MappedBlockStream private, forcing users to go through
23*9880d681SAndroid Build Coastguard Worker // the `create` interface.
24*9880d681SAndroid Build Coastguard Worker class MappedBlockStreamImpl : public MappedBlockStream {
25*9880d681SAndroid Build Coastguard Worker public:
MappedBlockStreamImpl(std::unique_ptr<IPDBStreamData> Data,const IPDBFile & File)26*9880d681SAndroid Build Coastguard Worker   MappedBlockStreamImpl(std::unique_ptr<IPDBStreamData> Data,
27*9880d681SAndroid Build Coastguard Worker                         const IPDBFile &File)
28*9880d681SAndroid Build Coastguard Worker       : MappedBlockStream(std::move(Data), File) {}
29*9880d681SAndroid Build Coastguard Worker };
30*9880d681SAndroid Build Coastguard Worker }
31*9880d681SAndroid Build Coastguard Worker 
32*9880d681SAndroid Build Coastguard Worker typedef std::pair<uint32_t, uint32_t> Interval;
intersect(const Interval & I1,const Interval & I2)33*9880d681SAndroid Build Coastguard Worker static Interval intersect(const Interval &I1, const Interval &I2) {
34*9880d681SAndroid Build Coastguard Worker   return std::make_pair(std::max(I1.first, I2.first),
35*9880d681SAndroid Build Coastguard Worker                         std::min(I1.second, I2.second));
36*9880d681SAndroid Build Coastguard Worker }
37*9880d681SAndroid Build Coastguard Worker 
MappedBlockStream(std::unique_ptr<IPDBStreamData> Data,const IPDBFile & Pdb)38*9880d681SAndroid Build Coastguard Worker MappedBlockStream::MappedBlockStream(std::unique_ptr<IPDBStreamData> Data,
39*9880d681SAndroid Build Coastguard Worker                                      const IPDBFile &Pdb)
40*9880d681SAndroid Build Coastguard Worker     : Pdb(Pdb), Data(std::move(Data)) {}
41*9880d681SAndroid Build Coastguard Worker 
readBytes(uint32_t Offset,uint32_t Size,ArrayRef<uint8_t> & Buffer) const42*9880d681SAndroid Build Coastguard Worker Error MappedBlockStream::readBytes(uint32_t Offset, uint32_t Size,
43*9880d681SAndroid Build Coastguard Worker                                    ArrayRef<uint8_t> &Buffer) const {
44*9880d681SAndroid Build Coastguard Worker   // Make sure we aren't trying to read beyond the end of the stream.
45*9880d681SAndroid Build Coastguard Worker   if (Size > Data->getLength())
46*9880d681SAndroid Build Coastguard Worker     return make_error<RawError>(raw_error_code::insufficient_buffer);
47*9880d681SAndroid Build Coastguard Worker   if (Offset > Data->getLength() - Size)
48*9880d681SAndroid Build Coastguard Worker     return make_error<RawError>(raw_error_code::insufficient_buffer);
49*9880d681SAndroid Build Coastguard Worker 
50*9880d681SAndroid Build Coastguard Worker   if (tryReadContiguously(Offset, Size, Buffer))
51*9880d681SAndroid Build Coastguard Worker     return Error::success();
52*9880d681SAndroid Build Coastguard Worker 
53*9880d681SAndroid Build Coastguard Worker   auto CacheIter = CacheMap.find(Offset);
54*9880d681SAndroid Build Coastguard Worker   if (CacheIter != CacheMap.end()) {
55*9880d681SAndroid Build Coastguard Worker     // Try to find an alloc that was large enough for this request.
56*9880d681SAndroid Build Coastguard Worker     for (auto &Entry : CacheIter->second) {
57*9880d681SAndroid Build Coastguard Worker       if (Entry.size() >= Size) {
58*9880d681SAndroid Build Coastguard Worker         Buffer = Entry.slice(0, Size);
59*9880d681SAndroid Build Coastguard Worker         return Error::success();
60*9880d681SAndroid Build Coastguard Worker       }
61*9880d681SAndroid Build Coastguard Worker     }
62*9880d681SAndroid Build Coastguard Worker   }
63*9880d681SAndroid Build Coastguard Worker 
64*9880d681SAndroid Build Coastguard Worker   // We couldn't find a buffer that started at the correct offset (the most
65*9880d681SAndroid Build Coastguard Worker   // common scenario).  Try to see if there is a buffer that starts at some
66*9880d681SAndroid Build Coastguard Worker   // other offset but overlaps the desired range.
67*9880d681SAndroid Build Coastguard Worker   for (auto &CacheItem : CacheMap) {
68*9880d681SAndroid Build Coastguard Worker     Interval RequestExtent = std::make_pair(Offset, Offset + Size);
69*9880d681SAndroid Build Coastguard Worker 
70*9880d681SAndroid Build Coastguard Worker     // We already checked this one on the fast path above.
71*9880d681SAndroid Build Coastguard Worker     if (CacheItem.first == Offset)
72*9880d681SAndroid Build Coastguard Worker       continue;
73*9880d681SAndroid Build Coastguard Worker     // If the initial extent of the cached item is beyond the ending extent
74*9880d681SAndroid Build Coastguard Worker     // of the request, there is no overlap.
75*9880d681SAndroid Build Coastguard Worker     if (CacheItem.first >= Offset + Size)
76*9880d681SAndroid Build Coastguard Worker       continue;
77*9880d681SAndroid Build Coastguard Worker 
78*9880d681SAndroid Build Coastguard Worker     // We really only have to check the last item in the list, since we append
79*9880d681SAndroid Build Coastguard Worker     // in order of increasing length.
80*9880d681SAndroid Build Coastguard Worker     if (CacheItem.second.empty())
81*9880d681SAndroid Build Coastguard Worker       continue;
82*9880d681SAndroid Build Coastguard Worker 
83*9880d681SAndroid Build Coastguard Worker     auto CachedAlloc = CacheItem.second.back();
84*9880d681SAndroid Build Coastguard Worker     // If the initial extent of the request is beyond the ending extent of
85*9880d681SAndroid Build Coastguard Worker     // the cached item, there is no overlap.
86*9880d681SAndroid Build Coastguard Worker     Interval CachedExtent =
87*9880d681SAndroid Build Coastguard Worker         std::make_pair(CacheItem.first, CacheItem.first + CachedAlloc.size());
88*9880d681SAndroid Build Coastguard Worker     if (RequestExtent.first >= CachedExtent.first + CachedExtent.second)
89*9880d681SAndroid Build Coastguard Worker       continue;
90*9880d681SAndroid Build Coastguard Worker 
91*9880d681SAndroid Build Coastguard Worker     Interval Intersection = intersect(CachedExtent, RequestExtent);
92*9880d681SAndroid Build Coastguard Worker     // Only use this if the entire request extent is contained in the cached
93*9880d681SAndroid Build Coastguard Worker     // extent.
94*9880d681SAndroid Build Coastguard Worker     if (Intersection != RequestExtent)
95*9880d681SAndroid Build Coastguard Worker       continue;
96*9880d681SAndroid Build Coastguard Worker 
97*9880d681SAndroid Build Coastguard Worker     uint32_t CacheRangeOffset =
98*9880d681SAndroid Build Coastguard Worker         AbsoluteDifference(CachedExtent.first, Intersection.first);
99*9880d681SAndroid Build Coastguard Worker     Buffer = CachedAlloc.slice(CacheRangeOffset, Size);
100*9880d681SAndroid Build Coastguard Worker     return Error::success();
101*9880d681SAndroid Build Coastguard Worker   }
102*9880d681SAndroid Build Coastguard Worker 
103*9880d681SAndroid Build Coastguard Worker   // Otherwise allocate a large enough buffer in the pool, memcpy the data
104*9880d681SAndroid Build Coastguard Worker   // into it, and return an ArrayRef to that.  Do not touch existing pool
105*9880d681SAndroid Build Coastguard Worker   // allocations, as existing clients may be holding a pointer which must
106*9880d681SAndroid Build Coastguard Worker   // not be invalidated.
107*9880d681SAndroid Build Coastguard Worker   uint8_t *WriteBuffer = static_cast<uint8_t *>(Pool.Allocate(Size, 8));
108*9880d681SAndroid Build Coastguard Worker   if (auto EC = readBytes(Offset, MutableArrayRef<uint8_t>(WriteBuffer, Size)))
109*9880d681SAndroid Build Coastguard Worker     return EC;
110*9880d681SAndroid Build Coastguard Worker 
111*9880d681SAndroid Build Coastguard Worker   if (CacheIter != CacheMap.end()) {
112*9880d681SAndroid Build Coastguard Worker     CacheIter->second.emplace_back(WriteBuffer, Size);
113*9880d681SAndroid Build Coastguard Worker   } else {
114*9880d681SAndroid Build Coastguard Worker     std::vector<CacheEntry> List;
115*9880d681SAndroid Build Coastguard Worker     List.emplace_back(WriteBuffer, Size);
116*9880d681SAndroid Build Coastguard Worker     CacheMap.insert(std::make_pair(Offset, List));
117*9880d681SAndroid Build Coastguard Worker   }
118*9880d681SAndroid Build Coastguard Worker   Buffer = ArrayRef<uint8_t>(WriteBuffer, Size);
119*9880d681SAndroid Build Coastguard Worker   return Error::success();
120*9880d681SAndroid Build Coastguard Worker }
121*9880d681SAndroid Build Coastguard Worker 
readLongestContiguousChunk(uint32_t Offset,ArrayRef<uint8_t> & Buffer) const122*9880d681SAndroid Build Coastguard Worker Error MappedBlockStream::readLongestContiguousChunk(
123*9880d681SAndroid Build Coastguard Worker     uint32_t Offset, ArrayRef<uint8_t> &Buffer) const {
124*9880d681SAndroid Build Coastguard Worker   // Make sure we aren't trying to read beyond the end of the stream.
125*9880d681SAndroid Build Coastguard Worker   if (Offset >= Data->getLength())
126*9880d681SAndroid Build Coastguard Worker     return make_error<RawError>(raw_error_code::insufficient_buffer);
127*9880d681SAndroid Build Coastguard Worker   uint32_t First = Offset / Pdb.getBlockSize();
128*9880d681SAndroid Build Coastguard Worker   uint32_t Last = First;
129*9880d681SAndroid Build Coastguard Worker 
130*9880d681SAndroid Build Coastguard Worker   auto BlockList = Data->getStreamBlocks();
131*9880d681SAndroid Build Coastguard Worker   while (Last < Pdb.getBlockCount() - 1) {
132*9880d681SAndroid Build Coastguard Worker     if (BlockList[Last] != BlockList[Last + 1] - 1)
133*9880d681SAndroid Build Coastguard Worker       break;
134*9880d681SAndroid Build Coastguard Worker     ++Last;
135*9880d681SAndroid Build Coastguard Worker   }
136*9880d681SAndroid Build Coastguard Worker 
137*9880d681SAndroid Build Coastguard Worker   uint32_t OffsetInFirstBlock = Offset % Pdb.getBlockSize();
138*9880d681SAndroid Build Coastguard Worker   uint32_t BytesFromFirstBlock = Pdb.getBlockSize() - OffsetInFirstBlock;
139*9880d681SAndroid Build Coastguard Worker   uint32_t BlockSpan = Last - First + 1;
140*9880d681SAndroid Build Coastguard Worker   uint32_t ByteSpan =
141*9880d681SAndroid Build Coastguard Worker       BytesFromFirstBlock + (BlockSpan - 1) * Pdb.getBlockSize();
142*9880d681SAndroid Build Coastguard Worker   auto Result = Pdb.getBlockData(BlockList[First], Pdb.getBlockSize());
143*9880d681SAndroid Build Coastguard Worker   if (!Result)
144*9880d681SAndroid Build Coastguard Worker     return Result.takeError();
145*9880d681SAndroid Build Coastguard Worker   Buffer = Result->drop_front(OffsetInFirstBlock);
146*9880d681SAndroid Build Coastguard Worker   Buffer = ArrayRef<uint8_t>(Buffer.data(), ByteSpan);
147*9880d681SAndroid Build Coastguard Worker   return Error::success();
148*9880d681SAndroid Build Coastguard Worker }
149*9880d681SAndroid Build Coastguard Worker 
getLength() const150*9880d681SAndroid Build Coastguard Worker uint32_t MappedBlockStream::getLength() const { return Data->getLength(); }
151*9880d681SAndroid Build Coastguard Worker 
commit() const152*9880d681SAndroid Build Coastguard Worker Error MappedBlockStream::commit() const { return Error::success(); }
153*9880d681SAndroid Build Coastguard Worker 
tryReadContiguously(uint32_t Offset,uint32_t Size,ArrayRef<uint8_t> & Buffer) const154*9880d681SAndroid Build Coastguard Worker bool MappedBlockStream::tryReadContiguously(uint32_t Offset, uint32_t Size,
155*9880d681SAndroid Build Coastguard Worker                                             ArrayRef<uint8_t> &Buffer) const {
156*9880d681SAndroid Build Coastguard Worker   // Attempt to fulfill the request with a reference directly into the stream.
157*9880d681SAndroid Build Coastguard Worker   // This can work even if the request crosses a block boundary, provided that
158*9880d681SAndroid Build Coastguard Worker   // all subsequent blocks are contiguous.  For example, a 10k read with a 4k
159*9880d681SAndroid Build Coastguard Worker   // block size can be filled with a reference if, from the starting offset,
160*9880d681SAndroid Build Coastguard Worker   // 3 blocks in a row are contiguous.
161*9880d681SAndroid Build Coastguard Worker   uint32_t BlockNum = Offset / Pdb.getBlockSize();
162*9880d681SAndroid Build Coastguard Worker   uint32_t OffsetInBlock = Offset % Pdb.getBlockSize();
163*9880d681SAndroid Build Coastguard Worker   uint32_t BytesFromFirstBlock =
164*9880d681SAndroid Build Coastguard Worker       std::min(Size, Pdb.getBlockSize() - OffsetInBlock);
165*9880d681SAndroid Build Coastguard Worker   uint32_t NumAdditionalBlocks =
166*9880d681SAndroid Build Coastguard Worker       llvm::alignTo(Size - BytesFromFirstBlock, Pdb.getBlockSize()) /
167*9880d681SAndroid Build Coastguard Worker       Pdb.getBlockSize();
168*9880d681SAndroid Build Coastguard Worker 
169*9880d681SAndroid Build Coastguard Worker   auto BlockList = Data->getStreamBlocks();
170*9880d681SAndroid Build Coastguard Worker   uint32_t RequiredContiguousBlocks = NumAdditionalBlocks + 1;
171*9880d681SAndroid Build Coastguard Worker   uint32_t E = BlockList[BlockNum];
172*9880d681SAndroid Build Coastguard Worker   for (uint32_t I = 0; I < RequiredContiguousBlocks; ++I, ++E) {
173*9880d681SAndroid Build Coastguard Worker     if (BlockList[I + BlockNum] != E)
174*9880d681SAndroid Build Coastguard Worker       return false;
175*9880d681SAndroid Build Coastguard Worker   }
176*9880d681SAndroid Build Coastguard Worker 
177*9880d681SAndroid Build Coastguard Worker   uint32_t FirstBlockAddr = BlockList[BlockNum];
178*9880d681SAndroid Build Coastguard Worker   auto Result = Pdb.getBlockData(FirstBlockAddr, Pdb.getBlockSize());
179*9880d681SAndroid Build Coastguard Worker   if (!Result) {
180*9880d681SAndroid Build Coastguard Worker     consumeError(Result.takeError());
181*9880d681SAndroid Build Coastguard Worker     return false;
182*9880d681SAndroid Build Coastguard Worker   }
183*9880d681SAndroid Build Coastguard Worker   auto Data = Result->drop_front(OffsetInBlock);
184*9880d681SAndroid Build Coastguard Worker   Buffer = ArrayRef<uint8_t>(Data.data(), Size);
185*9880d681SAndroid Build Coastguard Worker   return true;
186*9880d681SAndroid Build Coastguard Worker }
187*9880d681SAndroid Build Coastguard Worker 
readBytes(uint32_t Offset,MutableArrayRef<uint8_t> Buffer) const188*9880d681SAndroid Build Coastguard Worker Error MappedBlockStream::readBytes(uint32_t Offset,
189*9880d681SAndroid Build Coastguard Worker                                    MutableArrayRef<uint8_t> Buffer) const {
190*9880d681SAndroid Build Coastguard Worker   uint32_t BlockNum = Offset / Pdb.getBlockSize();
191*9880d681SAndroid Build Coastguard Worker   uint32_t OffsetInBlock = Offset % Pdb.getBlockSize();
192*9880d681SAndroid Build Coastguard Worker 
193*9880d681SAndroid Build Coastguard Worker   // Make sure we aren't trying to read beyond the end of the stream.
194*9880d681SAndroid Build Coastguard Worker   if (Buffer.size() > Data->getLength())
195*9880d681SAndroid Build Coastguard Worker     return make_error<RawError>(raw_error_code::insufficient_buffer);
196*9880d681SAndroid Build Coastguard Worker   if (Offset > Data->getLength() - Buffer.size())
197*9880d681SAndroid Build Coastguard Worker     return make_error<RawError>(raw_error_code::insufficient_buffer);
198*9880d681SAndroid Build Coastguard Worker 
199*9880d681SAndroid Build Coastguard Worker   uint32_t BytesLeft = Buffer.size();
200*9880d681SAndroid Build Coastguard Worker   uint32_t BytesWritten = 0;
201*9880d681SAndroid Build Coastguard Worker   uint8_t *WriteBuffer = Buffer.data();
202*9880d681SAndroid Build Coastguard Worker   auto BlockList = Data->getStreamBlocks();
203*9880d681SAndroid Build Coastguard Worker   while (BytesLeft > 0) {
204*9880d681SAndroid Build Coastguard Worker     uint32_t StreamBlockAddr = BlockList[BlockNum];
205*9880d681SAndroid Build Coastguard Worker 
206*9880d681SAndroid Build Coastguard Worker     auto Result = Pdb.getBlockData(StreamBlockAddr, Pdb.getBlockSize());
207*9880d681SAndroid Build Coastguard Worker     if (!Result)
208*9880d681SAndroid Build Coastguard Worker       return Result.takeError();
209*9880d681SAndroid Build Coastguard Worker 
210*9880d681SAndroid Build Coastguard Worker     auto Data = *Result;
211*9880d681SAndroid Build Coastguard Worker     const uint8_t *ChunkStart = Data.data() + OffsetInBlock;
212*9880d681SAndroid Build Coastguard Worker     uint32_t BytesInChunk =
213*9880d681SAndroid Build Coastguard Worker         std::min(BytesLeft, Pdb.getBlockSize() - OffsetInBlock);
214*9880d681SAndroid Build Coastguard Worker     ::memcpy(WriteBuffer + BytesWritten, ChunkStart, BytesInChunk);
215*9880d681SAndroid Build Coastguard Worker 
216*9880d681SAndroid Build Coastguard Worker     BytesWritten += BytesInChunk;
217*9880d681SAndroid Build Coastguard Worker     BytesLeft -= BytesInChunk;
218*9880d681SAndroid Build Coastguard Worker     ++BlockNum;
219*9880d681SAndroid Build Coastguard Worker     OffsetInBlock = 0;
220*9880d681SAndroid Build Coastguard Worker   }
221*9880d681SAndroid Build Coastguard Worker 
222*9880d681SAndroid Build Coastguard Worker   return Error::success();
223*9880d681SAndroid Build Coastguard Worker }
224*9880d681SAndroid Build Coastguard Worker 
writeBytes(uint32_t Offset,ArrayRef<uint8_t> Buffer) const225*9880d681SAndroid Build Coastguard Worker Error MappedBlockStream::writeBytes(uint32_t Offset,
226*9880d681SAndroid Build Coastguard Worker                                     ArrayRef<uint8_t> Buffer) const {
227*9880d681SAndroid Build Coastguard Worker   // Make sure we aren't trying to write beyond the end of the stream.
228*9880d681SAndroid Build Coastguard Worker   if (Buffer.size() > Data->getLength())
229*9880d681SAndroid Build Coastguard Worker     return make_error<RawError>(raw_error_code::insufficient_buffer);
230*9880d681SAndroid Build Coastguard Worker 
231*9880d681SAndroid Build Coastguard Worker   if (Offset > Data->getLength() - Buffer.size())
232*9880d681SAndroid Build Coastguard Worker     return make_error<RawError>(raw_error_code::insufficient_buffer);
233*9880d681SAndroid Build Coastguard Worker 
234*9880d681SAndroid Build Coastguard Worker   uint32_t BlockNum = Offset / Pdb.getBlockSize();
235*9880d681SAndroid Build Coastguard Worker   uint32_t OffsetInBlock = Offset % Pdb.getBlockSize();
236*9880d681SAndroid Build Coastguard Worker 
237*9880d681SAndroid Build Coastguard Worker   uint32_t BytesLeft = Buffer.size();
238*9880d681SAndroid Build Coastguard Worker   auto BlockList = Data->getStreamBlocks();
239*9880d681SAndroid Build Coastguard Worker   uint32_t BytesWritten = 0;
240*9880d681SAndroid Build Coastguard Worker   while (BytesLeft > 0) {
241*9880d681SAndroid Build Coastguard Worker     uint32_t StreamBlockAddr = BlockList[BlockNum];
242*9880d681SAndroid Build Coastguard Worker     uint32_t BytesToWriteInChunk =
243*9880d681SAndroid Build Coastguard Worker         std::min(BytesLeft, Pdb.getBlockSize() - OffsetInBlock);
244*9880d681SAndroid Build Coastguard Worker 
245*9880d681SAndroid Build Coastguard Worker     const uint8_t *Chunk = Buffer.data() + BytesWritten;
246*9880d681SAndroid Build Coastguard Worker     ArrayRef<uint8_t> ChunkData(Chunk, BytesToWriteInChunk);
247*9880d681SAndroid Build Coastguard Worker     if (auto EC = Pdb.setBlockData(StreamBlockAddr, OffsetInBlock, ChunkData))
248*9880d681SAndroid Build Coastguard Worker       return EC;
249*9880d681SAndroid Build Coastguard Worker 
250*9880d681SAndroid Build Coastguard Worker     BytesLeft -= BytesToWriteInChunk;
251*9880d681SAndroid Build Coastguard Worker     BytesWritten += BytesToWriteInChunk;
252*9880d681SAndroid Build Coastguard Worker     ++BlockNum;
253*9880d681SAndroid Build Coastguard Worker     OffsetInBlock = 0;
254*9880d681SAndroid Build Coastguard Worker   }
255*9880d681SAndroid Build Coastguard Worker 
256*9880d681SAndroid Build Coastguard Worker   // If this write overlapped a read which previously came from the pool,
257*9880d681SAndroid Build Coastguard Worker   // someone may still be holding a pointer to that alloc which is now invalid.
258*9880d681SAndroid Build Coastguard Worker   // Compute the overlapping range and update the cache entry, so any
259*9880d681SAndroid Build Coastguard Worker   // outstanding buffers are automatically updated.
260*9880d681SAndroid Build Coastguard Worker   for (const auto &MapEntry : CacheMap) {
261*9880d681SAndroid Build Coastguard Worker     // If the end of the written extent precedes the beginning of the cached
262*9880d681SAndroid Build Coastguard Worker     // extent, ignore this map entry.
263*9880d681SAndroid Build Coastguard Worker     if (Offset + BytesWritten < MapEntry.first)
264*9880d681SAndroid Build Coastguard Worker       continue;
265*9880d681SAndroid Build Coastguard Worker     for (const auto &Alloc : MapEntry.second) {
266*9880d681SAndroid Build Coastguard Worker       // If the end of the cached extent precedes the beginning of the written
267*9880d681SAndroid Build Coastguard Worker       // extent, ignore this alloc.
268*9880d681SAndroid Build Coastguard Worker       if (MapEntry.first + Alloc.size() < Offset)
269*9880d681SAndroid Build Coastguard Worker         continue;
270*9880d681SAndroid Build Coastguard Worker 
271*9880d681SAndroid Build Coastguard Worker       // If we get here, they are guaranteed to overlap.
272*9880d681SAndroid Build Coastguard Worker       Interval WriteInterval = std::make_pair(Offset, Offset + BytesWritten);
273*9880d681SAndroid Build Coastguard Worker       Interval CachedInterval =
274*9880d681SAndroid Build Coastguard Worker           std::make_pair(MapEntry.first, MapEntry.first + Alloc.size());
275*9880d681SAndroid Build Coastguard Worker       // If they overlap, we need to write the new data into the overlapping
276*9880d681SAndroid Build Coastguard Worker       // range.
277*9880d681SAndroid Build Coastguard Worker       auto Intersection = intersect(WriteInterval, CachedInterval);
278*9880d681SAndroid Build Coastguard Worker       assert(Intersection.first <= Intersection.second);
279*9880d681SAndroid Build Coastguard Worker 
280*9880d681SAndroid Build Coastguard Worker       uint32_t Length = Intersection.second - Intersection.first;
281*9880d681SAndroid Build Coastguard Worker       uint32_t SrcOffset =
282*9880d681SAndroid Build Coastguard Worker           AbsoluteDifference(WriteInterval.first, Intersection.first);
283*9880d681SAndroid Build Coastguard Worker       uint32_t DestOffset =
284*9880d681SAndroid Build Coastguard Worker           AbsoluteDifference(CachedInterval.first, Intersection.first);
285*9880d681SAndroid Build Coastguard Worker       ::memcpy(Alloc.data() + DestOffset, Buffer.data() + SrcOffset, Length);
286*9880d681SAndroid Build Coastguard Worker     }
287*9880d681SAndroid Build Coastguard Worker   }
288*9880d681SAndroid Build Coastguard Worker 
289*9880d681SAndroid Build Coastguard Worker   return Error::success();
290*9880d681SAndroid Build Coastguard Worker }
291*9880d681SAndroid Build Coastguard Worker 
getNumBytesCopied() const292*9880d681SAndroid Build Coastguard Worker uint32_t MappedBlockStream::getNumBytesCopied() const {
293*9880d681SAndroid Build Coastguard Worker   return static_cast<uint32_t>(Pool.getBytesAllocated());
294*9880d681SAndroid Build Coastguard Worker }
295*9880d681SAndroid Build Coastguard Worker 
296*9880d681SAndroid Build Coastguard Worker Expected<std::unique_ptr<MappedBlockStream>>
createIndexedStream(uint32_t StreamIdx,const IPDBFile & File)297*9880d681SAndroid Build Coastguard Worker MappedBlockStream::createIndexedStream(uint32_t StreamIdx,
298*9880d681SAndroid Build Coastguard Worker                                        const IPDBFile &File) {
299*9880d681SAndroid Build Coastguard Worker   if (StreamIdx >= File.getNumStreams())
300*9880d681SAndroid Build Coastguard Worker     return make_error<RawError>(raw_error_code::no_stream);
301*9880d681SAndroid Build Coastguard Worker 
302*9880d681SAndroid Build Coastguard Worker   auto Data = llvm::make_unique<IndexedStreamData>(StreamIdx, File);
303*9880d681SAndroid Build Coastguard Worker   return llvm::make_unique<MappedBlockStreamImpl>(std::move(Data), File);
304*9880d681SAndroid Build Coastguard Worker }
305*9880d681SAndroid Build Coastguard Worker 
306*9880d681SAndroid Build Coastguard Worker Expected<std::unique_ptr<MappedBlockStream>>
createDirectoryStream(const PDBFile & File)307*9880d681SAndroid Build Coastguard Worker MappedBlockStream::createDirectoryStream(const PDBFile &File) {
308*9880d681SAndroid Build Coastguard Worker   auto Data = llvm::make_unique<DirectoryStreamData>(File);
309*9880d681SAndroid Build Coastguard Worker   return llvm::make_unique<MappedBlockStreamImpl>(std::move(Data), File);
310*9880d681SAndroid Build Coastguard Worker }
311