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 : #include "syzygy/pdb/pdb_util.h"
15 :
16 : #include <algorithm>
17 : #include <string>
18 :
19 : #include "base/stringprintf.h"
20 : #include "sawbuck/common/buffer_parser.h"
21 : #include "syzygy/pdb/pdb_byte_stream.h"
22 : #include "syzygy/pdb/pdb_reader.h"
23 : #include "syzygy/pdb/pdb_writer.h"
24 :
25 : namespace pdb {
26 :
27 : namespace {
28 :
29 : // Sets the stream associated with a given entry in the DBI DBG header.
30 : // Gets the index at position @p index_offset of the DBI DBG header. If invalid,
31 : // adds a new stream to the PDB and updates the index to point to it. If a valid
32 : // stream already exists, replaces it with the new @p stream.
33 : // @param index_offset the offset of the int16 stream index within the DBI DBG
34 : // header.
35 : // @param stream the stream to be associated with the given DBI DBG entry.
36 : // @param pdb_file the PDB file to be updated.
37 : bool SetDbiDbgStream(size_t index_offset,
38 : PdbStream* stream,
39 E : PdbFile* pdb_file) {
40 E : DCHECK(pdb_file != NULL);
41 :
42 E : if (!EnsureStreamWritable(kDbiStream, pdb_file)) {
43 i : LOG(ERROR) << "Failed to make DBI stream writable.";
44 i : return false;
45 : }
46 :
47 E : scoped_refptr<PdbStream> dbi_reader(pdb_file->GetStream(kDbiStream));
48 : scoped_refptr<WritablePdbStream> dbi_writer(
49 E : dbi_reader->GetWritablePdbStream());
50 E : DCHECK(dbi_writer.get() != NULL);
51 :
52 : // Read the DBI header.
53 E : DbiHeader dbi_header = {};
54 E : if (!dbi_reader->Seek(0) || !dbi_reader->Read(&dbi_header, 1)) {
55 i : LOG(ERROR) << "Failed to read DBI header.";
56 i : return false;
57 : }
58 :
59 : // Get the stream index at the provided offset.
60 E : uint32 dbi_dbg_offset = GetDbiDbgHeaderOffset(dbi_header);
61 E : int16 existing_index = -1;
62 : if (!dbi_reader->Seek(dbi_dbg_offset + index_offset) ||
63 E : !dbi_reader->Read(&existing_index, 1)) {
64 i : LOG(ERROR) << "Failed to read stream index at offset " << dbi_dbg_offset
65 : << " of DBI DBG header.";
66 i : return false;
67 : }
68 :
69 : // If the stream is an invalid index, we create a new one.
70 E : int16 new_index = existing_index;
71 : if (existing_index < 0 ||
72 E : existing_index >= static_cast<int16>(pdb_file->StreamCount())) {
73 E : new_index = static_cast<int16>(pdb_file->AppendStream(stream));
74 E : } else {
75 i : pdb_file->ReplaceStream(new_index, stream);
76 : }
77 :
78 : // Update the index in the header if we need to.
79 E : if (new_index != existing_index) {
80 E : dbi_writer->set_pos(dbi_dbg_offset + index_offset);
81 E : if (!dbi_writer->Write(new_index)) {
82 i : LOG(ERROR) << "Failed to write stream index at offset " << dbi_dbg_offset
83 : << " of DBI DBG header.";
84 i : return false;
85 : }
86 : }
87 :
88 E : return true;
89 E : }
90 :
91 : bool SetOmapStream(size_t dbi_dbg_index_offset,
92 : const std::vector<OMAP>& omap_list,
93 E : PdbFile* pdb_file) {
94 E : DCHECK(pdb_file != NULL);
95 :
96 E : scoped_refptr<PdbByteStream> stream = new PdbByteStream();
97 E : if (!omap_list.empty()) {
98 : if (!stream->Init(reinterpret_cast<const uint8*>(&omap_list.at(0)),
99 E : omap_list.size() * sizeof(OMAP))) {
100 i : LOG(ERROR) << "Failed to initialize OMAP stream.";
101 i : return false;
102 : }
103 : }
104 :
105 E : return SetDbiDbgStream(dbi_dbg_index_offset, stream.get(), pdb_file);
106 E : }
107 :
108 : // Calculates the size of the hash table required to represent a named stream
109 : // hash containing the given number of entries. This has been determined from
110 : // inspection of the output produced by pdbstr.exe.
111 E : size_t GetNamedStreamsHashTableSize(size_t entries) {
112 : // This produces the sequence of sizes: 6, 10, 14, 20, 28, 38, 52, etc.
113 E : size_t size = 3;
114 E : while (true) {
115 E : size_t threshold = 2 * size / 3;
116 E : if (entries <= threshold)
117 E : return size;
118 E : size = 2 * (threshold + 1);
119 E : }
120 E : }
121 :
122 : // Calculates the hash value associated with a stream name, as used by the
123 : // named streams hash table. This is required for interoperability with
124 : // dbghelp and srcsrv tools.
125 E : uint16 NamedStreamsHash(const base::StringPiece& name) {
126 E : size_t length = name.size();
127 E : const char* data = name.data();
128 :
129 E : uint32 hash = 0;
130 E : while (length >= 4) {
131 E : hash ^= *reinterpret_cast<const uint32*>(data);
132 E : data += 4;
133 E : length -= 4;
134 E : }
135 :
136 E : if (length >= 2) {
137 E : hash ^= *reinterpret_cast<const uint16*>(data);
138 E : data += 2;
139 E : length -= 2;
140 : }
141 :
142 E : if (length >= 1)
143 E : hash ^= *data;
144 :
145 E : hash |= 0x20202020;
146 E : hash ^= hash >> 11;
147 E : hash ^= hash >> 16;
148 :
149 E : return hash & 0xFFFF;
150 E : }
151 :
152 : // Sets the bit at the given index, with collision semantics. Returns the index
153 : // of the bit that was set. Note that there must be at least one bit that is not
154 : // already set, otherwise this will loop forever.
155 : size_t SetNamedStreamsHashTableBit(
156 E : size_t index, size_t max, PdbBitSet* bitset) {
157 E : DCHECK(bitset != NULL);
158 :
159 E : while (bitset->IsSet(index)) {
160 E : ++index;
161 E : if (index > max)
162 i : index = 0;
163 E : }
164 :
165 E : bitset->Set(index);
166 E : return index;
167 E : }
168 :
169 : // A small struct that is used for storing information regarding the name-stream
170 : // map, and the associated hash table. The (string table offset, stream id)
171 : // pairs need to be output in order of the hash value, which is the default sort
172 : // order of this object.
173 : struct NamedStreamInfo {
174 E : NamedStreamInfo(NameStreamMap::const_iterator it,
175 : uint32 offset,
176 : uint32 bucket)
177 : : it(it), offset(offset), bucket(bucket) {
178 E : }
179 :
180 E : bool operator<(const NamedStreamInfo& rhs) const {
181 E : return bucket < rhs.bucket;
182 E : }
183 :
184 : // An iterator into the (name, stream_id) map.
185 : NameStreamMap::const_iterator it;
186 : // The offset of the name in the string table.
187 : uint32 offset;
188 : // The bucket that this name occupies in the hash map, after collision
189 : // resolution. This is the sort key.
190 : uint32 bucket;
191 : };
192 :
193 : } // namespace
194 :
195 E : bool PdbBitSet::Read(PdbStream* stream) {
196 E : DCHECK(stream != NULL);
197 E : uint32 size = 0;
198 E : if (!stream->Read(&size, 1)) {
199 E : LOG(ERROR) << "Failed to read bitset size.";
200 E : return false;
201 : }
202 E : if (!stream->Read(&bits_, size)) {
203 i : LOG(ERROR) << "Failed to read bitset bits.";
204 i : return false;
205 : }
206 :
207 E : return true;
208 E : }
209 :
210 E : bool PdbBitSet::Write(WritablePdbStream* stream) {
211 E : DCHECK(stream != NULL);
212 E : if (!stream->Write(static_cast<uint32>(bits_.size()))) {
213 i : LOG(ERROR) << "Failed to write bitset size.";
214 i : return false;
215 : }
216 E : if (bits_.empty())
217 E : return true;
218 E : if (!stream->Write(bits_.size(), &bits_[0])) {
219 i : LOG(ERROR) << "Failed to write bitset bits.";
220 i : return false;
221 : }
222 :
223 E : return true;
224 E : }
225 :
226 E : void PdbBitSet::Resize(size_t bits) {
227 E : bits_.resize((bits + 31) / 32);
228 E : }
229 :
230 E : void PdbBitSet::Set(size_t bit) {
231 E : size_t index = bit / 32;
232 E : if (index >= bits_.size())
233 i : return;
234 E : bits_[index] |= (1 << (bit % 32));
235 E : }
236 :
237 E : void PdbBitSet::Clear(size_t bit) {
238 E : size_t index = bit / 32;
239 E : if (index >= bits_.size())
240 i : return;
241 E : bits_[index] &= ~(1 << (bit % 32));
242 E : }
243 :
244 E : void PdbBitSet::Toggle(size_t bit) {
245 E : size_t index = bit / 32;
246 E : if (index >= bits_.size())
247 i : return;
248 E : bits_[index] ^= (1 << (bit % 32));
249 E : }
250 :
251 E : bool PdbBitSet::IsSet(size_t bit) const {
252 E : size_t index = bit / 32;
253 E : if (index >= bits_.size())
254 i : return false;
255 :
256 E : return (bits_[index] & (1 << (bit % 32))) != 0;
257 E : }
258 :
259 E : bool PdbBitSet::IsEmpty() const {
260 E : return bits_.empty();
261 E : }
262 :
263 E : bool ReadString(PdbStream* stream, std::string* out) {
264 E : DCHECK(out != NULL);
265 :
266 E : std::string result;
267 E : char c = 0;
268 E : while (stream->Read(&c, 1)) {
269 E : if (c == '\0') {
270 E : out->swap(result);
271 E : return true;
272 : }
273 E : result.push_back(c);
274 E : }
275 :
276 i : return false;
277 E : }
278 :
279 E : bool ReadStringAt(PdbStream* stream, size_t pos, std::string* out) {
280 E : size_t save = stream->pos();
281 E : bool read = stream->Seek(pos) && ReadString(stream, out);
282 E : stream->Seek(save);
283 E : return read;
284 E : }
285 :
286 E : uint32 GetDbiDbgHeaderOffset(const DbiHeader& dbi_header) {
287 E : uint32 offset = sizeof(DbiHeader);
288 E : offset += dbi_header.gp_modi_size;
289 E : offset += dbi_header.section_contribution_size;
290 E : offset += dbi_header.section_map_size;
291 E : offset += dbi_header.file_info_size;
292 E : offset += dbi_header.ts_map_size;
293 E : offset += dbi_header.ec_info_size; // Unexpected, but necessary.
294 E : return offset;
295 E : }
296 :
297 E : bool EnsureStreamWritable(uint32 index, PdbFile* pdb_file) {
298 E : DCHECK(pdb_file != NULL);
299 :
300 : // Bail if the index is to a non-existent stream.
301 E : if (index >= pdb_file->StreamCount()) {
302 E : LOG(ERROR) << "Invalid PDB stream index.";
303 E : return false;
304 : }
305 :
306 : // Get the reader. If it doesn't actually exist, create a new one.
307 E : scoped_refptr<PdbStream> reader(pdb_file->GetStream(index));
308 E : if (reader.get() == NULL)
309 E : reader = new PdbByteStream();
310 :
311 : // Try and get a writer.
312 E : scoped_refptr<WritablePdbStream> writer(reader->GetWritablePdbStream());
313 E : if (writer.get() == NULL) {
314 : // If not possible, copy the existing reader to a PdbByteStream which will
315 : // be able to give us a writer.
316 E : scoped_refptr<PdbByteStream> new_stream = new PdbByteStream();
317 E : if (!new_stream->Init(reader.get())) {
318 i : LOG(ERROR) << "Failed to initialize writable stream.";
319 i : return false;
320 : }
321 E : reader = new_stream.get();
322 E : }
323 :
324 E : DCHECK(reader->GetWritablePdbStream() != NULL);
325 :
326 : // Be sure to replace the stream at this index with the new one. This is a
327 : // no-op if the stream hasn't changed.
328 E : pdb_file->ReplaceStream(index, reader.get());
329 :
330 E : return true;
331 E : }
332 :
333 : bool SetOmapToStream(const std::vector<OMAP>& omap_to_list,
334 E : PdbFile* pdb_file) {
335 E : DCHECK(pdb_file != NULL);
336 : return SetOmapStream(offsetof(DbiDbgHeader, omap_to_src),
337 : omap_to_list,
338 E : pdb_file);
339 E : }
340 :
341 : bool SetOmapFromStream(const std::vector<OMAP>& omap_from_list,
342 E : PdbFile* pdb_file) {
343 E : DCHECK(pdb_file != NULL);
344 : return SetOmapStream(offsetof(DbiDbgHeader, omap_from_src),
345 : omap_from_list,
346 E : pdb_file);
347 E : }
348 :
349 E : bool SetGuid(const GUID& guid, PdbFile* pdb_file) {
350 E : DCHECK(pdb_file != NULL);
351 :
352 : // Make sure the Pdb header and the Dbi streams are writable.
353 E : if (!EnsureStreamWritable(kPdbHeaderInfoStream, pdb_file)) {
354 i : LOG(ERROR) << "Failed to make PDB Header Info stream writable.";
355 i : return false;
356 : }
357 E : if (!EnsureStreamWritable(kDbiStream, pdb_file)) {
358 i : LOG(ERROR) << "Failed to make DBI Info stream writable.";
359 i : return false;
360 : }
361 :
362 : // Get the reader and writer for the header info stream.
363 E : scoped_refptr<PdbStream> reader(pdb_file->GetStream(kPdbHeaderInfoStream));
364 E : scoped_refptr<WritablePdbStream> writer(reader->GetWritablePdbStream());
365 E : DCHECK(writer.get() != NULL);
366 :
367 : // Read the header.
368 E : PdbInfoHeader70 info_header = {};
369 E : if (!reader->Seek(0) || !reader->Read(&info_header, 1)) {
370 E : LOG(ERROR) << "Failed to read PdbInfoHeader70.";
371 E : return false;
372 : }
373 :
374 : // Update it.
375 E : info_header.timestamp = static_cast<uint32>(time(NULL));
376 E : info_header.pdb_age = 1; // Reset age to 1, as this is a new generation.
377 E : info_header.signature = guid;
378 :
379 : // And write it back.
380 E : writer->set_pos(0);
381 E : if (!writer->Write(info_header)) {
382 i : LOG(ERROR) << "Failed to write PdbInfoHeader70.";
383 i : return false;
384 : }
385 :
386 : // Now update the age in the DBI stream to match the age we set above.
387 E : reader = pdb_file->GetStream(kDbiStream);
388 E : if (reader.get() == NULL) {
389 i : LOG(ERROR) << "No DBI stream in PDB.";
390 i : return false;
391 : }
392 E : writer = reader->GetWritablePdbStream();
393 :
394 E : DCHECK(writer.get() != NULL);
395 :
396 : // Read the header.
397 E : DbiHeader dbi_header = {};
398 E : if (!reader->Seek(0) || !reader->Read(&dbi_header, 1)) {
399 E : LOG(ERROR) << "Failed to read DbiHeader.";
400 E : return false;
401 : }
402 :
403 E : dbi_header.age = 1;
404 E : writer->set_pos(0);
405 E : if (!writer->Write(dbi_header)) {
406 i : LOG(ERROR) << "Failed to write DbiHeader";
407 i : return false;
408 : }
409 :
410 E : return true;
411 E : }
412 :
413 : bool ReadPdbHeader(const base::FilePath& pdb_path,
414 E : PdbInfoHeader70* pdb_header) {
415 E : DCHECK(!pdb_path.empty());
416 E : DCHECK(pdb_header != NULL);
417 :
418 E : PdbReader pdb_reader;
419 E : PdbFile pdb_file;
420 E : if (!pdb_reader.Read(pdb_path, &pdb_file)) {
421 E : LOG(ERROR) << "Unable to process PDB file: " << pdb_path.value();
422 E : return false;
423 : }
424 :
425 E : PdbStream* header_stream = pdb_file.GetStream(kPdbHeaderInfoStream);
426 E : if (header_stream == NULL) {
427 i : LOG(ERROR) << "PDB file contains no header stream: " << pdb_path.value();
428 i : return false;
429 : }
430 :
431 E : if (!header_stream->Read(pdb_header, 1)) {
432 i : LOG(ERROR) << "Failure reading PDB header: " << pdb_path.value();
433 i : return false;
434 : }
435 :
436 : // We only know how to deal with PDB files of the current version.
437 E : if (pdb_header->version != kPdbCurrentVersion) {
438 i : LOG(ERROR) << "PDB header has unsupported version (got "
439 : << pdb_header->version << ", expected " << kPdbCurrentVersion
440 : << ").";
441 i : return false;
442 : }
443 :
444 E : return true;
445 E : }
446 :
447 : bool ReadHeaderInfoStream(const PdbFile& pdb_file,
448 : PdbInfoHeader70* pdb_header,
449 E : NameStreamMap* name_stream_map) {
450 E : DCHECK(pdb_header != NULL);
451 E : DCHECK(name_stream_map != NULL);
452 :
453 : // Get the stream reader.
454 E : if (kPdbHeaderInfoStream >= pdb_file.StreamCount()) {
455 E : LOG(ERROR) << "No header info stream found.";
456 E : return false;
457 : }
458 : scoped_refptr<PdbStream> header_reader(
459 E : pdb_file.GetStream(kPdbHeaderInfoStream));
460 E : if (header_reader.get() == NULL) {
461 i : LOG(ERROR) << "No header info stream found.";
462 i : return false;
463 : }
464 :
465 : // Read the header.
466 : if (!pdb::ReadHeaderInfoStream(header_reader.get(), pdb_header,
467 E : name_stream_map)) {
468 i : LOG(ERROR) << "Failed to read header info stream.";
469 i : return false;
470 : }
471 :
472 E : return true;
473 E : }
474 :
475 : bool ReadHeaderInfoStream(PdbStream* pdb_stream,
476 : PdbInfoHeader70* pdb_header,
477 E : NameStreamMap* name_stream_map) {
478 E : VLOG(1) << "Header Info Stream size: " << pdb_stream->length();
479 :
480 E : if (!pdb_stream->Seek(0)) {
481 i : LOG(ERROR) << "Unable to seek to start of PDB header info stream.";
482 i : return false;
483 : }
484 :
485 : // The header stream starts with the fixed-size header pdb_header record.
486 E : if (!pdb_stream->Read(pdb_header, 1)) {
487 E : LOG(ERROR) << "Unable to read PDB pdb_header header.";
488 E : return false;
489 : }
490 :
491 E : uint32 string_len = 0;
492 E : if (!pdb_stream->Read(&string_len, 1)) {
493 E : LOG(ERROR) << "Unable to read string table length.";
494 E : return false;
495 : }
496 :
497 : // The fixed-size record is followed by information on named streams, which
498 : // is essentially a string->id mapping. This starts with the strings
499 : // themselves, which have been observed to be a packed run of zero-terminated
500 : // strings.
501 : // We store the start of the string list, as the string positions we read
502 : // later are relative to that position.
503 E : size_t string_start = pdb_stream->pos();
504 :
505 : // Seek past the strings.
506 E : if (!pdb_stream->Seek(string_start + string_len)) {
507 i : LOG(ERROR) << "Unable to seek past string list";
508 i : return false;
509 : }
510 :
511 : // Next there's a pair of integers. The first one of those is the number of
512 : // items in the string->id mapping. The purpose of the second one is not
513 : // clear, but has been observed as larger or equal to the first one.
514 E : uint32 size = 0;
515 E : uint32 max = 0;
516 E : if (!pdb_stream->Read(&size, 1) || !pdb_stream->Read(&max, 1)) {
517 i : LOG(ERROR) << "Unable to read name pdb_stream size/max";
518 i : return false;
519 : }
520 E : DCHECK(max >= size);
521 :
522 : // After the counts, there's a pair of bitsets. Each bitset has a 32 bit
523 : // length, followed by that number of 32 bit words that contain the bits.
524 : // The purpose of those is again not clear, though the first set will have
525 : // "size" bits of the bits in the range 0-max set.
526 E : PdbBitSet used;
527 E : PdbBitSet deleted;
528 E : if (!used.Read(pdb_stream) || !deleted.Read(pdb_stream)) {
529 i : LOG(ERROR) << "Unable to read name pdb_stream bitsets.";
530 i : return false;
531 : }
532 :
533 : #ifndef NDEBUG
534 : // The first bitset has "size" bits set of the first "max" bits.
535 E : size_t set_bits = 0;
536 E : for (size_t i = 0; i < max; ++i) {
537 E : if (used.IsSet(i))
538 E : ++set_bits;
539 E : }
540 :
541 : // The second bitset has always been observed to be empty.
542 E : DCHECK(deleted.IsEmpty());
543 :
544 E : DCHECK_EQ(size, set_bits);
545 : #endif
546 :
547 : // Read the mapping proper, this is simply a run of {string offset, id} pairs.
548 E : for (size_t i = 0; i < size; ++i) {
549 E : uint32 str_offs = 0;
550 E : uint32 stream_no = 0;
551 : // Read the offset and pdb_stream number.
552 E : if (!pdb_stream->Read(&str_offs, 1) || !pdb_stream->Read(&stream_no, 1)) {
553 i : LOG(ERROR) << "Unable to read pdb_stream data.";
554 i : return false;
555 : }
556 :
557 : // Read the string itself from the table.
558 E : std::string name;
559 E : if (!ReadStringAt(pdb_stream, string_start + str_offs, &name)) {
560 i : LOG(ERROR) << "Failed to read pdb_stream name.";
561 i : return false;
562 : }
563 :
564 E : (*name_stream_map)[name] = stream_no;
565 E : }
566 :
567 E : return true;
568 E : }
569 :
570 : bool WriteHeaderInfoStream(const PdbInfoHeader70& header,
571 : const NameStreamMap& name_stream_map,
572 E : PdbFile* pdb_file) {
573 E : DCHECK(pdb_file != NULL);
574 :
575 E : if (!pdb::EnsureStreamWritable(pdb::kPdbHeaderInfoStream, pdb_file)) {
576 i : LOG(ERROR) << "Failed to make PDB Header Info stream writable.";
577 i : return false;
578 : }
579 :
580 : // Get the stream reader.
581 : scoped_refptr<PdbStream> header_reader(
582 E : pdb_file->GetStream(pdb::kPdbHeaderInfoStream));
583 E : DCHECK(header_reader.get() != NULL);
584 :
585 : // Get the stream writer.
586 : scoped_refptr<WritablePdbStream> header_writer(
587 E : header_reader->GetWritablePdbStream());
588 E : DCHECK(header_writer.get() != NULL);
589 :
590 : // Write the new header.
591 E : if (!WriteHeaderInfoStream(header, name_stream_map, header_writer.get())) {
592 i : LOG(ERROR) << "Failed to write PDB Header Info stream.";
593 i : return false;
594 : }
595 :
596 E : return true;
597 E : }
598 :
599 : bool WriteHeaderInfoStream(const PdbInfoHeader70& pdb_header,
600 : const NameStreamMap& name_stream_map,
601 E : WritablePdbStream* pdb_stream) {
602 E : DCHECK(pdb_stream != NULL);
603 :
604 E : if (!pdb_stream->Write(pdb_header)) {
605 i : LOG(ERROR) << "Failed to write PDB header.";
606 i : return false;
607 : }
608 :
609 : // Calculate the hash table entry count and size.
610 E : uint32 string_count = name_stream_map.size();
611 E : uint32 table_size = GetNamedStreamsHashTableSize(string_count);
612 :
613 : // Initialize the 'used' bitset.
614 E : PdbBitSet used;
615 E : used.Resize(table_size);
616 :
617 : // Get the string table length. We also calculate hashes for each name,
618 : // populating the 'used' bitset and determining the order in which to output
619 : // the stream names.
620 E : std::vector<NamedStreamInfo> name_infos;
621 E : name_infos.reserve(string_count);
622 E : uint32 string_length = 0;
623 E : NameStreamMap::const_iterator name_it = name_stream_map.begin();
624 E : for (; name_it != name_stream_map.end(); ++name_it) {
625 E : uint16 hash = NamedStreamsHash(name_it->first);
626 E : size_t bucket = hash % table_size;
627 E : bucket = SetNamedStreamsHashTableBit(bucket, table_size, &used);
628 E : name_infos.push_back(NamedStreamInfo(name_it, 0, bucket));
629 E : string_length += name_it->first.size() + 1; // Include the trailing zero.
630 E : }
631 :
632 : // Sort the strings in the order in which they will be output.
633 E : std::sort(name_infos.begin(), name_infos.end());
634 :
635 : // Dump the string table.
636 E : if (!pdb_stream->Write(string_length)) {
637 i : LOG(ERROR) << "Failed to write stream name table length.";
638 i : return false;
639 : }
640 E : string_length = 0;
641 E : for (size_t i = 0; i < name_infos.size(); ++i) {
642 E : name_infos[i].offset = string_length;
643 E : name_it = name_infos[i].it;
644 E : string_length += name_it->first.size() + 1;
645 E : if (!pdb_stream->Write(name_it->first.size() + 1, name_it->first.c_str())) {
646 i : LOG(ERROR) << "Failed to write stream name.";
647 i : return false;
648 : }
649 E : }
650 :
651 : // Write the string hash table size.
652 E : if (!pdb_stream->Write(string_count) || !pdb_stream->Write(table_size)) {
653 i : LOG(ERROR) << "Failed to write string table size.";
654 i : return false;
655 : }
656 :
657 : // Write the 'used' bitset.
658 E : if (!used.Write(pdb_stream)) {
659 i : LOG(ERROR) << "Failed to write 'used' bitset.";
660 i : return false;
661 : }
662 :
663 : // The 'deleted' bitset is always empty.
664 E : PdbBitSet deleted;
665 E : DCHECK(deleted.IsEmpty());
666 E : if (!deleted.Write(pdb_stream)) {
667 i : LOG(ERROR) << "Failed to write 'deleted' bitset.";
668 i : return false;
669 : }
670 :
671 : // Now output the actual mapping, a run of (string table offset, stream id)
672 : // pairs. We output these in order of hash table buckets of each name,
673 : // mimicking the output produced by pdbstr.exe.
674 E : for (size_t i = 0; i < name_infos.size(); ++i) {
675 : if (!pdb_stream->Write(name_infos[i].offset) ||
676 E : !pdb_stream->Write(name_infos[i].it->second)) {
677 i : LOG(ERROR) << "Failed to write stream name mapping.";
678 i : return false;
679 : }
680 E : }
681 :
682 : // The run of pairs must be terminated with a single NULL entry.
683 E : if (!pdb_stream->Write(static_cast<uint32>(0))) {
684 i : LOG(ERROR) << "Failed to write terminating NULL.";
685 i : return false;
686 : }
687 :
688 E : return true;
689 E : }
690 :
691 : bool ReadStringTable(PdbStream* stream,
692 : const char* table_name,
693 : size_t table_start,
694 : size_t table_end,
695 E : OffsetStringMap* string_map) {
696 E : DCHECK(stream != NULL);
697 E : DCHECK(table_name != NULL);
698 E : DCHECK(string_map != NULL);
699 :
700 E : uint32 string_table_signature = 0;
701 E : uint32 string_table_version = 0;
702 :
703 : if (!stream->Seek(table_start) ||
704 : !stream->Read(&string_table_signature, 1) ||
705 E : !stream->Read(&string_table_version, 1)) {
706 i : LOG(ERROR) << "Unable to seek to " << table_name << " stream.";
707 i : return false;
708 : }
709 :
710 : if (string_table_signature != kPdbNameTableSignature ||
711 E : string_table_version != kPdbNameTableVersion) {
712 i : LOG(ERROR) << "Unexpected " << table_name << " header. Expected "
713 : << "signature/version "
714 : << base::StringPrintf("0x%08X", kPdbNameTableSignature) << "/"
715 : << kPdbNameTableVersion << ", read "
716 : << base::StringPrintf("0x%08X", string_table_signature) << "/"
717 : << string_table_version << ".";
718 i : return false;
719 : }
720 :
721 E : size_t string_table_size = 0;
722 E : if (!stream->Read(&string_table_size, 1)) {
723 i : LOG(ERROR) << "Unable to read the size of the " << table_name << " string "
724 : << "table.";
725 i : return false;
726 : }
727 :
728 E : size_t string_table_start = stream->pos();
729 E : size_t offset_table_start = stream->pos() + string_table_size;
730 :
731 : // Skip the string table and seek to the offset table.
732 E : if (!stream->Seek(offset_table_start)) {
733 i : LOG(ERROR) << "Unable to seek to the " << table_name << " offset table.";
734 i : return false;
735 : }
736 :
737 E : size_t entries_count = 0;
738 E : if (!stream->Read(&entries_count, 1)) {
739 i : LOG(ERROR) << "Unable to read the number of entries in the " << table_name
740 : << " offset table.";
741 i : return false;
742 : }
743 :
744 : // Some of the offsets present in the offset table have the value 0, which
745 : // refers to an empty string present at the beginning of the string table.
746 E : for (size_t i = 0; i < entries_count; ++i) {
747 E : size_t string_offset = 0;
748 E : std::string temp_string;
749 : if (!stream->Read(&string_offset, 1) ||
750 : !ReadStringAt(stream, string_table_start + string_offset,
751 E : &temp_string)) {
752 i : LOG(ERROR) << "Unable to read the " << table_name << " name table.";
753 i : return false;
754 : }
755 :
756 E : string_map->insert(std::make_pair(string_offset, temp_string));
757 E : }
758 :
759 E : uint32 string_count = 0;
760 : // Sometimes the string_count field matches the number of non-empty strings
761 : // in the string_map and sometimes it doesn't.
762 : // TODO(sebmarchand) : understand what's this value once the compiland streams
763 : // are deciphered.
764 E : if (!stream->Read(&string_count, 1)) {
765 i : LOG(ERROR) << "Unable to read the number of files present in the "
766 : << table_name << " stream.";
767 i : return false;
768 : }
769 :
770 E : if (stream->pos() != table_end) {
771 i : LOG(ERROR) << table_name << " stream is not valid.";
772 i : return false;
773 : }
774 :
775 E : return true;
776 E : }
777 :
778 : bool LoadNamedStreamFromPdbFile(
779 : const base::StringPiece& stream_name,
780 : PdbFile* pdb_file,
781 E : scoped_refptr<PdbStream>* stream) {
782 E : DCHECK(pdb_file != NULL);
783 E : DCHECK(stream != NULL);
784 E : DCHECK(stream->get() == NULL);
785 :
786 : // Get the PDB header and try to get the named stream ID from it.
787 E : pdb::PdbInfoHeader70 pdb_header = {0};
788 E : pdb::NameStreamMap name_stream_map;
789 : if (!ReadHeaderInfoStream(pdb_file->GetStream(pdb::kPdbHeaderInfoStream),
790 : &pdb_header,
791 E : &name_stream_map)) {
792 i : LOG(ERROR) << "Failed to read header info stream.";
793 i : return false;
794 : }
795 :
796 : // The stream with the given name does not exist.
797 : pdb::NameStreamMap::const_iterator name_it = name_stream_map.find(
798 E : stream_name.as_string());
799 E : if (name_it == name_stream_map.end())
800 E : return true;
801 :
802 : // Get the named stream and ensure that it's not empty.
803 E : *stream = pdb_file->GetStream(name_it->second);
804 E : if (stream->get() == NULL) {
805 i : LOG(ERROR) << "Failed to read the \"" << stream_name.as_string()
806 : << "\" stream from the PDB.";
807 i : return false;
808 : }
809 :
810 E : return true;
811 E : }
812 :
813 : } // namespace pdb
|