1 : // Copyright 2012 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/pdb/pdb_byte_stream.h"
16 :
17 : #include <algorithm>
18 : #include "base/logging.h"
19 :
20 : namespace pdb {
21 :
22 : // The writable half of an in-memory PDB stream. This is not in an anonymous
23 : // namespace as it is forward declared in the header and is a friend of
24 : // PdbByteStream, allowing access to the underlying storage vector. Once we
25 : // hoist storage to another interface, this implementation can be entirely
26 : // hidden.
27 : class WritablePdbByteStream : public WritablePdbStream {
28 : public:
29 : // Constructor.
30 : // @param pdb_byte_stream a pointer to the PDB byte stream whose data we
31 : // wrap.
32 : explicit WritablePdbByteStream(PdbByteStream* pdb_byte_stream);
33 :
34 : protected:
35 : // This is protected to enforce use of reference counted pointers.
36 : virtual ~WritablePdbByteStream();
37 :
38 : // common::BufferWriter implementation.
39 : virtual uint8* GrowBuffer(size_t size) OVERRIDE;
40 :
41 : // A reference counted pointer to the PdbByteStream we are wrapping.
42 : scoped_refptr<PdbByteStream> pdb_byte_stream_;
43 : };
44 :
45 E : PdbByteStream::PdbByteStream() : PdbStream(0), writable_pdb_stream_(NULL) {
46 E : }
47 :
48 E : PdbByteStream::~PdbByteStream() {
49 E : }
50 :
51 E : bool PdbByteStream::Init(const uint8* data, size_t length) {
52 E : set_length(length);
53 E : data_.resize(length);
54 E : memcpy(this->data(), data, length);
55 E : return true;
56 E : }
57 :
58 E : bool PdbByteStream::Init(PdbStream* stream) {
59 E : DCHECK(stream != NULL);
60 :
61 : // Init data members.
62 E : set_length(stream->length());
63 E : data_.resize(length());
64 :
65 E : if (data_.empty())
66 E : return true;
67 :
68 : // Read the file stream.
69 E : if (!stream->Seek(0)) {
70 i : LOG(ERROR) << "Failed to seek in pdb stream.";
71 i : return false;
72 : }
73 E : if (!stream->Read(data(), length())) {
74 i : LOG(ERROR) << "Failed to read pdb stream.";
75 i : return false;
76 : }
77 :
78 E : return true;
79 E : }
80 :
81 E : bool PdbByteStream::ReadBytes(void* dest, size_t count, size_t* bytes_read) {
82 E : DCHECK(dest != NULL);
83 E : DCHECK(bytes_read != NULL);
84 :
85 : // Return 0 once we've reached the end of the stream.
86 E : if (pos() == length()) {
87 E : *bytes_read = 0;
88 E : return true;
89 : }
90 :
91 : // Don't read beyond the end of the known stream length.
92 E : count = std::min(count, length() - pos());
93 :
94 : // Read the stream.
95 E : memcpy(dest, data() + pos(), count);
96 E : Seek(pos() + count);
97 E : *bytes_read = count;
98 :
99 E : return true;
100 E : }
101 :
102 E : scoped_refptr<WritablePdbStream> PdbByteStream::GetWritablePdbStream() {
103 : // This is very not thread-safe! If we want this to be thread-safe, we'll
104 : // need to be using thread-safe reference counting, and a little smarts here
105 : // to ensure we're not mid-destructor on some other thread.
106 E : if (writable_pdb_stream_ == NULL)
107 E : writable_pdb_stream_ = new WritablePdbByteStream(this);
108 E : return scoped_refptr<WritablePdbStream>(writable_pdb_stream_);
109 E : }
110 :
111 E : WritablePdbByteStream::WritablePdbByteStream(PdbByteStream* pdb_byte_stream) {
112 E : DCHECK(pdb_byte_stream != NULL);
113 E : pdb_byte_stream_ = pdb_byte_stream;
114 :
115 : // If the stream contains data, initialize the BufferWriter.
116 E : if (pdb_byte_stream_->length() > 0) {
117 E : SetBuffer(pdb_byte_stream_->data(), pdb_byte_stream_->length());
118 : }
119 E : }
120 :
121 E : WritablePdbByteStream::~WritablePdbByteStream() {
122 : // Clear our parent's pointer to us.
123 E : pdb_byte_stream_->writable_pdb_stream_ = NULL;
124 E : }
125 :
126 E : uint8* WritablePdbByteStream::GrowBuffer(size_t size) {
127 E : DCHECK_GT(size, pdb_byte_stream_->data_.size());
128 : // Resize the vector underlying the PdbByteStream, and notify the parent
129 : // PdbStream object of the new length.
130 E : pdb_byte_stream_->data_.resize(size);
131 E : pdb_byte_stream_->set_length(size);
132 E : return pdb_byte_stream_->data();
133 E : }
134 :
135 : } // namespace pdb
|