blob: 09d7198503156460c564ec2c45a2e5f6e49289eb [file] [log] [blame]
Zachary Turner6ba65de2016-04-29 17:22:58 +00001//===- MappedBlockStream.cpp - Reads stream data from a PDBFile -----------===//
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/PDB/Raw/MappedBlockStream.h"
11#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
Zachary Turner819e77d2016-05-06 20:51:57 +000012#include "llvm/DebugInfo/PDB/Raw/RawError.h"
Zachary Turner6ba65de2016-04-29 17:22:58 +000013
14using namespace llvm;
Zachary Turner2f09b502016-04-29 17:28:47 +000015using namespace llvm::pdb;
Zachary Turner6ba65de2016-04-29 17:22:58 +000016
17MappedBlockStream::MappedBlockStream(uint32_t StreamIdx, const PDBFile &File) : Pdb(File) {
Zachary Turner96e60f72016-05-24 20:31:48 +000018 if (StreamIdx >= Pdb.getNumStreams()) {
19 StreamLength = 0;
20 } else {
21 StreamLength = Pdb.getStreamByteSize(StreamIdx);
22 BlockList = Pdb.getStreamBlockList(StreamIdx);
23 }
Zachary Turner6ba65de2016-04-29 17:22:58 +000024}
25
Zachary Turner819e77d2016-05-06 20:51:57 +000026Error MappedBlockStream::readBytes(uint32_t Offset,
27 MutableArrayRef<uint8_t> Buffer) const {
Zachary Turner6ba65de2016-04-29 17:22:58 +000028 uint32_t BlockNum = Offset / Pdb.getBlockSize();
29 uint32_t OffsetInBlock = Offset % Pdb.getBlockSize();
30
31 // Make sure we aren't trying to read beyond the end of the stream.
32 if (Buffer.size() > StreamLength)
Zachary Turner819e77d2016-05-06 20:51:57 +000033 return make_error<RawError>(raw_error_code::insufficient_buffer);
Zachary Turner6ba65de2016-04-29 17:22:58 +000034 if (Offset > StreamLength - Buffer.size())
Zachary Turner819e77d2016-05-06 20:51:57 +000035 return make_error<RawError>(raw_error_code::insufficient_buffer);
Zachary Turner6ba65de2016-04-29 17:22:58 +000036
37 uint32_t BytesLeft = Buffer.size();
38 uint32_t BytesWritten = 0;
39 uint8_t *WriteBuffer = Buffer.data();
40 while (BytesLeft > 0) {
41 uint32_t StreamBlockAddr = BlockList[BlockNum];
42
43 StringRef Data = Pdb.getBlockData(StreamBlockAddr, Pdb.getBlockSize());
44
45 const char *ChunkStart = Data.data() + OffsetInBlock;
46 uint32_t BytesInChunk =
47 std::min(BytesLeft, Pdb.getBlockSize() - OffsetInBlock);
48 ::memcpy(WriteBuffer + BytesWritten, ChunkStart, BytesInChunk);
49
50 BytesWritten += BytesInChunk;
51 BytesLeft -= BytesInChunk;
52 ++BlockNum;
53 OffsetInBlock = 0;
54 }
55
Zachary Turner819e77d2016-05-06 20:51:57 +000056 return Error::success();
Zachary Turner6ba65de2016-04-29 17:22:58 +000057}
Zachary Turnerf5c59652016-05-03 00:28:21 +000058
Zachary Turner819e77d2016-05-06 20:51:57 +000059Error MappedBlockStream::getArrayRef(uint32_t Offset, ArrayRef<uint8_t> &Buffer,
60 uint32_t Length) const {
Zachary Turner96e60f72016-05-24 20:31:48 +000061 uint32_t BlockNum = Offset / Pdb.getBlockSize();
62 uint32_t OffsetInBlock = Offset % Pdb.getBlockSize();
63 uint32_t BytesAvailableInBlock = Pdb.getBlockSize() - OffsetInBlock;
64
65 // If this is the last block in the stream, not all of the data is valid.
66 if (BlockNum == BlockList.size() - 1) {
67 uint32_t AllocatedBytesInBlock = StreamLength % Pdb.getBlockSize();
68 if (AllocatedBytesInBlock < BytesAvailableInBlock)
69 BytesAvailableInBlock = AllocatedBytesInBlock;
70 }
71 if (BytesAvailableInBlock < Length)
72 return make_error<RawError>(raw_error_code::feature_unsupported);
73
74 uint32_t StreamBlockAddr = BlockList[BlockNum];
75 StringRef Data = Pdb.getBlockData(StreamBlockAddr, Pdb.getBlockSize());
76 Data = Data.substr(OffsetInBlock, Length);
77
78 Buffer = ArrayRef<uint8_t>(Data.bytes_begin(), Data.bytes_end());
79 return Error::success();
Zachary Turnerf5c59652016-05-03 00:28:21 +000080}