1 : // Copyright 2015 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/refinery/types/pdb_crawler.h"
16 :
17 : #include <vector>
18 :
19 : #include "base/logging.h"
20 : #include "base/strings/string16.h"
21 : #include "syzygy/common/align.h"
22 : #include "syzygy/pdb/pdb_file.h"
23 : #include "syzygy/pdb/pdb_reader.h"
24 : #include "syzygy/pdb/pdb_type_info_stream_enum.h"
25 : #include "syzygy/pdb/gen/pdb_type_info_records.h"
26 : #include "syzygy/pe/cvinfo_ext.h"
27 : #include "syzygy/refinery/types/type.h"
28 : #include "syzygy/refinery/types/type_namer.h"
29 : #include "syzygy/refinery/types/type_repository.h"
30 :
31 : namespace refinery {
32 :
33 : namespace {
34 :
35 : namespace cci = Microsoft_Cci_Pdb;
36 :
37 : const uint16_t kNoLeafType = static_cast<uint16_t>(-1);
38 :
39 : class TypeCreator {
40 : public:
41 : explicit TypeCreator(TypeRepository* repository);
42 : ~TypeCreator();
43 :
44 : // Crawls @p stream, creates all types and assigns names to pointers.
45 : // @returns true on success, false on failure.
46 : bool CreateTypes(scoped_refptr<pdb::PdbStream> stream);
47 :
48 : private:
49 : // The following functions parse objects from the data stream.
50 : // @returns pointer to the created object or nullptr on failure.
51 : TypePtr CreateUserDefinedType(TypeId type_id);
52 : TypePtr CreateBasicPointerType(TypeId type_id);
53 : TypePtr CreatePointerType(TypeId type_id);
54 : TypePtr CreateArrayType(TypeId type_id);
55 : TypePtr CreateFunctionType(TypeId type_id);
56 : TypePtr CreateBasicType(TypeId type_id);
57 : TypePtr CreateWildcardType(TypeId type_id);
58 :
59 : // The following functions parse records but do not save them in the type
60 : // repository. Instead they just pass out the flags (and bit field values)
61 : // to the caller. However they ensure parsing of the underlying types.
62 : // @returns pointer to the type underlying the modifier.
63 : TypePtr ReadModifier(TypeId type_id, Type::Flags* flags);
64 : TypePtr ReadPointer(TypeId type_id, Type::Flags* flags);
65 : TypePtr ReadBitfield(TypeId type_id,
66 : Type::Flags* flags,
67 : size_t* bit_pos,
68 : size_t* bit_len);
69 :
70 : // Processes a member field and inserts it into given field list.
71 : // @param member pointer to the member type record.
72 : // @param fields pointer to the field list.
73 : // @returns true on success, false on failure.
74 : bool ProcessMember(pdb::LeafMember* member, UserDefinedType::Fields* fields);
75 :
76 : // Processes one method field and adds it as a member function in the member
77 : // function list.
78 : // @param method pointer to the one method type record.
79 : // @param functions pointer to the member function list.
80 : // @returns true on success, false on failure.
81 : bool ProcessOneMethod(pdb::LeafOneMethod* method,
82 : UserDefinedType::Functions* functions);
83 :
84 : // Processes overloaded method field and add the member functions to the given
85 : // list.
86 : // @param method pointer to the method type record.
87 : // @param functions pointer to the member function list.
88 : // @returns true on success, false on failure.
89 : bool ProcessMethod(pdb::LeafMethod* method,
90 : UserDefinedType::Functions* functions);
91 :
92 : // Parses field list from the data stream and populates the UDT with fields
93 : // and member functions.
94 : // @param fields pointer to the field list.
95 : // @param functions pointer to the member function list.
96 : // @returns true on success, false on failure.
97 : bool ReadFieldlist(TypeId type_id,
98 : UserDefinedType::Fields* fields,
99 : UserDefinedType::Functions* functions);
100 :
101 : // Parses arglist from the data stream and populates the given list of
102 : // argument types.
103 : // @param args pointer to the the argument list.
104 : // @returns true on success, false on failure.
105 : bool ReadArglist(TypeId type_id, FunctionType::Arguments* args);
106 :
107 : // Parses type given by a type from the PDB type info stream.
108 : // @param type_id index of the type to create.
109 : // @returns pointer to the created object.
110 : TypePtr CreateType(TypeId type_id);
111 :
112 : // Returns the leaf type of a record with given type index.
113 : // @param type_id type index of the record.
114 : // @returns type of the record, -1 as an error sentinel.
115 : uint16_t GetLeafType(TypeId type_id);
116 :
117 : // Does a first pass through the stream making the map of type indices for
118 : // UDT and saves indices of all types that will get translated to the type
119 : // repo.
120 : // @returns true on success, false on failure.
121 : bool PrepareData();
122 :
123 : // Checks if type object exists and constructs one if it does not.
124 : // @param type_id type index of the type.
125 : // @returns pointer to the type object.
126 : TypePtr FindOrCreateTypeImpl(TypeId type_id);
127 :
128 : // The following functions are called during parsing to recurse deeper and
129 : // validate the references we expect to be there. For better description see
130 : // the file pdb_type_info_stream_description.md in the pdb directory.
131 : TypePtr FindOrCreateBasicType(TypeId type_id);
132 : TypePtr FindOrCreateIndexingType(TypeId type_id);
133 : TypePtr FindOrCreateIntegralBasicType(TypeId type_id);
134 : TypePtr FindOrCreateStructuredType(TypeId type_id);
135 : TypePtr FindOrCreateInheritableType(TypeId type_id);
136 : TypePtr FindOrCreateUserDefinedType(TypeId type_id);
137 : TypePtr FindOrCreateModifiableType(TypeId type_id);
138 : TypePtr FindOrCreateSpecificType(TypeId type_id, uint16_t type);
139 :
140 : // The following function also propagate the flags and bit field information
141 : // to their parents.
142 : TypePtr FindOrCreateOptionallyModifiedType(TypeId type_id,
143 : Type::Flags* flags);
144 : TypePtr FindOrCreateBitfieldType(TypeId type_id, Type::Flags* flags);
145 : TypePtr FindOrCreatePointableType(TypeId type_id, Type::Flags* flags);
146 : TypePtr FindOrCreateMemberType(TypeId type_id,
147 : Type::Flags* flags,
148 : size_t* bit_pos,
149 : size_t* bit_len);
150 :
151 : // Accessors for forward references caching.
152 : bool CacheUserDefinedTypeForwardDeclaration(TypeId fwd_id, TypeId class_id);
153 : TypeId LookupConcreteClassForForwardDeclaration(TypeId type_id);
154 :
155 : // @returns name for a basic type specified by its @p type.
156 : static base::string16 BasicTypeName(uint16_t type);
157 :
158 : // @returns size for a basic type specified by its @p type.
159 : static size_t BasicTypeSize(uint16_t type);
160 :
161 : // @returns name for a leaf specified by its @p type.
162 : static base::string16 LeafTypeName(uint16_t type);
163 :
164 : // @returns size of a pointer given its @p ptr type info record.
165 : static size_t PointerSize(const pdb::LeafPointer& ptr);
166 :
167 : // Computes size of a pointer to member function or data.
168 : // @param pmtype CV_pmtype field of the pointer.
169 : // @param ptrtype CV_ptrtype field of the pointer.
170 : // @returns size of a member field pointer.
171 : static size_t MemberPointerSize(cci::CV_pmtype pmtype,
172 : cci::CV_ptrtype ptrtype);
173 :
174 : // Pulls CV_prmode out of basic type index.
175 : // @param type_id type index of a basic type.
176 : // @returns the CV_prmode field.
177 : static cci::CV_prmode TypeIndexToPrMode(TypeId type_id);
178 :
179 : // Construct string of CV modifiers.
180 : // @param is_const true if type is const.
181 : // @param is_volatile true if type is volatile.
182 : // @returns the string of CV modifiers.
183 : static base::string16 GetCVMod(bool is_const, bool is_volatile);
184 :
185 : // Creates Type::Flags from the individual bool values.
186 : // @param is_const true if type is const.
187 : // @param is_volatile true if type is volatile.
188 : // @returns type flags.
189 : static Type::Flags CreateTypeFlags(bool is_const, bool is_volatile);
190 :
191 : // Checks if the type gets translated to a type repository.
192 : // @param type the type of this record.
193 : // @returns true if this record gets translated to the repository.
194 : static bool IsImportantType(uint32_t type);
195 :
196 : // Checks if this is actually pointer encoded in basic type index.
197 : // @param type_id type index of the record.
198 : // @returns true if the record is pointer.
199 : bool IsBasicPointerType(TypeId type_id);
200 :
201 : // Pointer to the type info repository.
202 : TypeRepository* repository_;
203 :
204 : // Type info enumerator used to traverse the stream.
205 : pdb::TypeInfoEnumerator type_info_enum_;
206 :
207 : // Direct access to the Pdb stream inside the type info enumerator.
208 : scoped_refptr<pdb::PdbStream> stream_;
209 :
210 : // Hash to map forward references to the right UDT records. For each unique
211 : // decorated name of an UDT, it contains type index of the class definition.
212 : base::hash_map<base::string16, TypeId> udt_map_;
213 :
214 : // Hash to store the pdb leaf types of the individual records. Indexed by type
215 : // indices.
216 : base::hash_map<TypeId, uint16_t> types_map_;
217 :
218 : // Hash which stores for each forward declaration the type index of the
219 : // actual class type.
220 : base::hash_map<TypeId, TypeId> fwd_reference_map_;
221 :
222 : // Vector of records to process.
223 : std::vector<TypeId> records_to_process_;
224 :
225 : TypeNamer type_namer_;
226 : };
227 :
228 E : TypePtr TypeCreator::CreatePointerType(TypeId type_id) {
229 E : DCHECK_EQ(GetLeafType(type_id), cci::LF_POINTER);
230 :
231 E : if (!type_info_enum_.SeekRecord(type_id))
232 i : return nullptr;
233 :
234 E : pdb::LeafPointer type_info;
235 E : if (!type_info.Initialize(stream_.get())) {
236 i : LOG(ERROR) << "Unable to read type info record.";
237 i : return nullptr;
238 : }
239 :
240 : // Save type information.
241 E : size_t size = PointerSize(type_info);
242 E : PointerType::Mode ptr_mode = PointerType::PTR_MODE_PTR;
243 E : if (type_info.attr().ptrmode == cci::CV_PTR_MODE_REF)
244 E : ptr_mode = PointerType::PTR_MODE_REF;
245 :
246 E : PointerTypePtr created = new PointerType(size, ptr_mode);
247 E : if (!repository_->AddTypeWithId(created, type_id))
248 i : return nullptr;
249 :
250 : // Try to find the object in the repository.
251 E : TypeId pointee_id = type_info.body().utype;
252 E : Type::Flags pointee_flags = kNoTypeFlags;
253 E : TypePtr pointee_type = FindOrCreatePointableType(pointee_id, &pointee_flags);
254 E : if (pointee_type == nullptr)
255 i : return nullptr;
256 :
257 : // Setting the flags from the child node - this is needed because of
258 : // different semantics between PDB file and Type interface. In PDB pointer
259 : // has a const flag when it's const, while here pointer has a const flag if
260 : // it points to a const type.
261 E : created->Finalize(pointee_flags, pointee_type->type_id());
262 E : return created;
263 E : }
264 :
265 E : TypePtr TypeCreator::CreateBasicPointerType(TypeId type_id) {
266 E : DCHECK(IsBasicPointerType(type_id));
267 : TypeId basic_index = type_id & (cci::CV_PRIMITIVE_TYPE::CV_TMASK |
268 E : cci::CV_PRIMITIVE_TYPE::CV_SMASK);
269 E : if (FindOrCreateBasicType(basic_index) == nullptr)
270 i : return nullptr;
271 :
272 : // Get pointer size.
273 E : size_t size = 0;
274 E : cci::CV_prmode prmode = TypeIndexToPrMode(type_id);
275 E : switch (prmode) {
276 : case cci::CV_TM_NPTR32:
277 E : size = 4;
278 E : break;
279 : case cci::CV_TM_NPTR64:
280 E : size = 8;
281 E : break;
282 : case cci::CV_TM_NPTR128:
283 i : size = 16;
284 i : break;
285 : default:
286 i : return nullptr;
287 : }
288 :
289 : // Create and finalize type.
290 : PointerTypePtr pointer_type =
291 E : new PointerType(size, PointerType::PTR_MODE_PTR);
292 E : pointer_type->Finalize(kNoTypeFlags, basic_index);
293 :
294 E : if (!repository_->AddTypeWithId(pointer_type, type_id))
295 i : return nullptr;
296 E : return pointer_type;
297 E : }
298 :
299 E : TypePtr TypeCreator::ReadPointer(TypeId type_id, Type::Flags* flags) {
300 E : DCHECK(flags);
301 E : DCHECK_EQ(GetLeafType(type_id), cci::LF_POINTER);
302 :
303 E : if (!type_info_enum_.SeekRecord(type_id))
304 i : return nullptr;
305 :
306 E : pdb::LeafPointer type_info;
307 E : if (!type_info.Initialize(stream_.get())) {
308 i : LOG(ERROR) << "Unable to read type info record.";
309 i : return nullptr;
310 : }
311 :
312 : *flags =
313 E : CreateTypeFlags(type_info.attr().isconst, type_info.attr().isvolatile);
314 :
315 E : return FindOrCreateSpecificType(type_info_enum_.type_id(), cci::LF_POINTER);
316 E : }
317 :
318 E : TypePtr TypeCreator::ReadModifier(TypeId type_id, Type::Flags* flags) {
319 E : DCHECK(flags);
320 E : DCHECK_EQ(GetLeafType(type_id), cci::LF_MODIFIER);
321 :
322 E : if (!type_info_enum_.SeekRecord(type_id))
323 i : return nullptr;
324 :
325 E : pdb::LeafModifier type_info;
326 E : if (!type_info.Initialize(stream_.get())) {
327 i : LOG(ERROR) << "Unable to read type info record.";
328 i : return nullptr;
329 : }
330 :
331 E : TypePtr underlying_type = FindOrCreateModifiableType(type_info.body().type);
332 E : if (underlying_type == nullptr)
333 i : return nullptr;
334 :
335 : *flags = CreateTypeFlags(type_info.attr().mod_const,
336 E : type_info.attr().mod_volatile);
337 E : return underlying_type;
338 E : }
339 :
340 : bool TypeCreator::ReadFieldlist(TypeId type_id,
341 : UserDefinedType::Fields* fields,
342 E : UserDefinedType::Functions* functions) {
343 E : DCHECK(fields);
344 E : DCHECK(functions);
345 E : DCHECK_EQ(GetLeafType(type_id), cci::LF_FIELDLIST);
346 :
347 E : if (!type_info_enum_.SeekRecord(type_id))
348 i : return nullptr;
349 :
350 E : size_t leaf_end = stream_->pos() + type_info_enum_.len();
351 :
352 : // Make our local copy of the data. This is necessary to avoid clutter with
353 : // deeper levels of recursion.
354 E : scoped_refptr<pdb::PdbByteStream> local_stream(new pdb::PdbByteStream());
355 E : local_stream->Init(stream_.get());
356 :
357 E : while (local_stream->pos() < leaf_end) {
358 E : uint16_t leaf_type = 0;
359 E : if (!local_stream->Read(&leaf_type, 1)) {
360 i : LOG(ERROR) << "Unable to read the type of a list field.";
361 i : return false;
362 : }
363 :
364 E : switch (leaf_type) {
365 : case cci::LF_MEMBER: {
366 E : pdb::LeafMember type_info;
367 : if (!type_info.Initialize(local_stream.get()) ||
368 E : !ProcessMember(&type_info, fields)) {
369 i : return false;
370 : }
371 E : break;
372 : }
373 : case cci::LF_BCLASS: {
374 E : pdb::LeafBClass type_info;
375 E : if (!type_info.Initialize(local_stream.get()))
376 i : return false;
377 E : break;
378 : }
379 : case cci::LF_VBCLASS:
380 : case cci::LF_IVBCLASS: {
381 E : pdb::LeafVBClass type_info;
382 E : if (!type_info.Initialize(local_stream.get()))
383 i : return false;
384 E : break;
385 : }
386 : case cci::LF_ENUMERATE: {
387 i : pdb::LeafEnumerate type_info;
388 i : if (!type_info.Initialize(local_stream.get()))
389 i : return false;
390 i : break;
391 : }
392 : case cci::LF_FRIENDFCN: {
393 i : pdb::LeafFriendFcn type_info;
394 i : if (!type_info.Initialize(local_stream.get()))
395 i : return false;
396 i : break;
397 : }
398 : case cci::LF_STMEMBER: {
399 E : pdb::LeafSTMember type_info;
400 E : if (!type_info.Initialize(local_stream.get()))
401 i : return false;
402 E : break;
403 : }
404 : case cci::LF_METHOD: {
405 E : pdb::LeafMethod type_info;
406 : if (!type_info.Initialize(local_stream.get()) ||
407 E : !ProcessMethod(&type_info, functions)) {
408 i : return false;
409 : }
410 E : break;
411 : }
412 : case cci::LF_NESTTYPE: {
413 E : pdb::LeafNestType type_info;
414 E : if (!type_info.Initialize(local_stream.get()))
415 i : return false;
416 E : break;
417 : }
418 : case cci::LF_VFUNCTAB: {
419 E : pdb::LeafVFuncTab type_info;
420 E : if (!type_info.Initialize(local_stream.get()))
421 i : return false;
422 E : break;
423 : }
424 : case cci::LF_FRIENDCLS: {
425 i : pdb::LeafFriendCls type_info;
426 i : if (!type_info.Initialize(local_stream.get()))
427 i : return false;
428 i : break;
429 : }
430 : case cci::LF_ONEMETHOD: {
431 E : pdb::LeafOneMethod type_info;
432 : if (!type_info.Initialize(local_stream.get()) ||
433 E : !ProcessOneMethod(&type_info, functions)) {
434 i : return false;
435 : }
436 E : break;
437 : }
438 : case cci::LF_VFUNCOFF: {
439 i : pdb::LeafVFuncOff type_info;
440 i : if (!type_info.Initialize(local_stream.get()))
441 i : return false;
442 i : break;
443 : }
444 : case cci::LF_INDEX: {
445 E : pdb::LeafIndex type_info;
446 E : if (!type_info.Initialize(local_stream.get()))
447 i : return false;
448 : // This is always the last record of the fieldlist.
449 : // TODO(manzagop): ask siggi@ if he thinks this optimization is wise.
450 E : return ReadFieldlist(type_info.body().index, fields, functions);
451 : }
452 : default: {
453 i : NOTREACHED();
454 : break;
455 : }
456 : }
457 : // The records are aligned.
458 E : local_stream->Seek(common::AlignUp(local_stream->pos(), 4));
459 E : }
460 E : return true;
461 E : }
462 :
463 : bool TypeCreator::ReadArglist(TypeId type_id,
464 E : FunctionType::Arguments* arglist) {
465 E : DCHECK(arglist);
466 E : DCHECK_EQ(GetLeafType(type_id), cci::LF_ARGLIST);
467 :
468 E : if (!type_info_enum_.SeekRecord(type_id))
469 i : return nullptr;
470 :
471 : // Make our local copy of the data. This is necessary to avoid clutter with
472 : // deeper levels of recursion.
473 E : scoped_refptr<pdb::PdbByteStream> stream(new pdb::PdbByteStream());
474 E : stream->Init(stream_.get());
475 :
476 E : uint32_t num_args = 0;
477 E : if (!stream->Read(&num_args, 1))
478 i : return false;
479 :
480 E : while (arglist->size() < num_args) {
481 E : uint32_t arg_type_id = 0;
482 E : if (!stream->Read(&arg_type_id, 1)) {
483 i : LOG(ERROR) << "Unable to read the type index of an argument.";
484 i : return false;
485 : }
486 :
487 E : Type::Flags flags = kNoTypeFlags;
488 E : TypePtr arg_type = FindOrCreateOptionallyModifiedType(arg_type_id, &flags);
489 E : if (arg_type == nullptr)
490 i : return false;
491 :
492 E : arglist->push_back(FunctionType::ArgumentType(flags, arg_type->type_id()));
493 E : }
494 E : return true;
495 E : }
496 :
497 E : TypePtr TypeCreator::CreateUserDefinedType(TypeId type_id) {
498 : DCHECK(GetLeafType(type_id) == cci::LF_CLASS ||
499 : GetLeafType(type_id) == cci::LF_STRUCTURE ||
500 E : GetLeafType(type_id) == cci::LF_UNION);
501 :
502 E : if (!type_info_enum_.SeekRecord(type_id))
503 i : return nullptr;
504 :
505 : // Read the values from the PDB records.
506 E : LeafPropertyField property = {};
507 E : TypeId fieldlist_id = kNoTypeId;
508 E : uint64_t size = 0;
509 E : base::string16 name;
510 E : base::string16 decorated_name;
511 :
512 : if (type_info_enum_.type() == cci::LF_CLASS ||
513 E : type_info_enum_.type() == cci::LF_STRUCTURE) {
514 E : pdb::LeafClass type_info;
515 E : if (!type_info.Initialize(stream_.get())) {
516 i : LOG(ERROR) << "Unable to read type info record.";
517 i : return nullptr;
518 : }
519 E : property = type_info.property();
520 E : fieldlist_id = type_info.body().field;
521 E : size = type_info.size();
522 E : name = type_info.name();
523 E : decorated_name = type_info.decorated_name();
524 E : } else if (type_info_enum_.type() == cci::LF_UNION) {
525 E : pdb::LeafUnion type_info;
526 E : if (!type_info.Initialize(stream_.get())) {
527 i : LOG(ERROR) << "Unable to read type info record.";
528 i : return nullptr;
529 : }
530 E : property = type_info.property();
531 E : fieldlist_id = type_info.body().field;
532 E : size = type_info.size();
533 E : name = type_info.name();
534 E : decorated_name = type_info.decorated_name();
535 E : }
536 :
537 : // Set the correct UDT kind.
538 E : UserDefinedType::UdtKind udt_kind = UserDefinedType::UDT_CLASS;
539 E : switch (type_info_enum_.type()) {
540 : case cci::LF_CLASS: {
541 E : udt_kind = UserDefinedType::UDT_CLASS;
542 E : break;
543 : }
544 : case cci::LF_STRUCTURE: {
545 E : udt_kind = UserDefinedType::UDT_STRUCT;
546 E : break;
547 : }
548 : case cci::LF_UNION: {
549 E : udt_kind = UserDefinedType::UDT_UNION;
550 : break;
551 : }
552 : }
553 :
554 E : if (property.fwdref) {
555 : // Find the type index of the UDT.
556 E : auto real_class_id = udt_map_.find(decorated_name);
557 E : if (real_class_id == udt_map_.end()) {
558 : // This is a forward reference without real UDT record.
559 : UserDefinedTypePtr udt =
560 E : new UserDefinedType(name, decorated_name, size, udt_kind);
561 E : udt->SetIsForwardDeclaration();
562 E : if (!repository_->AddTypeWithId(udt, type_id))
563 i : return nullptr;
564 E : return udt;
565 : }
566 :
567 : // Cache redirection to the real UDT.
568 E : if (!CacheUserDefinedTypeForwardDeclaration(type_id, real_class_id->second))
569 i : return nullptr;
570 :
571 : // Force parsing of the UDT.
572 : return FindOrCreateSpecificType(real_class_id->second,
573 E : type_info_enum_.type());
574 i : } else {
575 : // Create UDT of the class and find its fieldlist.
576 : UserDefinedTypePtr udt =
577 E : new UserDefinedType(name, decorated_name, size, udt_kind);
578 E : if (!repository_->AddTypeWithId(udt, type_id))
579 i : return nullptr;
580 :
581 E : UserDefinedType::Fields fieldlist;
582 E : UserDefinedType::Functions functionlist;
583 E : if (!ReadFieldlist(fieldlist_id, &fieldlist, &functionlist))
584 i : return false;
585 :
586 E : udt->Finalize(fieldlist, functionlist);
587 E : return udt;
588 : }
589 E : }
590 :
591 E : TypePtr TypeCreator::CreateArrayType(TypeId type_id) {
592 E : DCHECK_EQ(GetLeafType(type_id), cci::LF_ARRAY);
593 :
594 E : if (!type_info_enum_.SeekRecord(type_id))
595 i : return nullptr;
596 :
597 E : pdb::LeafArray type_info;
598 E : if (!type_info.Initialize(stream_.get())) {
599 i : LOG(ERROR) << "Unable to read type info record.";
600 i : return nullptr;
601 : }
602 :
603 E : ArrayTypePtr array_type = new ArrayType(type_info.size());
604 E : if (!repository_->AddTypeWithId(array_type, type_id))
605 i : return false;
606 :
607 : // Find the types in the repository.
608 E : Type::Flags flags = kNoTypeFlags;
609 E : TypeId index_id = type_info.body().idxtype;
610 E : TypeId elem_id = type_info.body().elemtype;
611 E : TypePtr index_type = FindOrCreateIndexingType(index_id);
612 E : TypePtr elem_type = FindOrCreateOptionallyModifiedType(elem_id, &flags);
613 E : if (index_type == nullptr || elem_type == nullptr)
614 i : return false;
615 :
616 E : size_t num_elements = 0;
617 : // TODO(mopler): Once we load everything test against the size not being zero.
618 E : if (elem_type->size() != 0)
619 E : num_elements = type_info.size() / elem_type->size();
620 : array_type->Finalize(flags, index_type->type_id(), num_elements,
621 E : elem_type->type_id());
622 E : return array_type;
623 E : }
624 :
625 E : TypePtr TypeCreator::CreateFunctionType(TypeId type_id) {
626 : DCHECK(GetLeafType(type_id) == cci::LF_PROCEDURE ||
627 E : GetLeafType(type_id) == cci::LF_MFUNCTION);
628 :
629 E : if (!type_info_enum_.SeekRecord(type_id))
630 i : return nullptr;
631 :
632 : FunctionType::CallConvention call_convention;
633 E : TypeId return_type_id = kNoTypeId;
634 E : TypeId containing_class_id = kNoTypeId;
635 E : TypeId arglist_id = kNoTypeId;
636 :
637 E : if (type_info_enum_.type() == cci::LF_PROCEDURE) {
638 : // Load the procedure record.
639 E : pdb::LeafProcedure type_info;
640 E : if (!type_info.Initialize(stream_.get())) {
641 i : LOG(ERROR) << "Unable to read type info record.";
642 i : return nullptr;
643 : }
644 :
645 : call_convention =
646 E : static_cast<FunctionType::CallConvention>(type_info.body().calltype);
647 E : return_type_id = type_info.body().rvtype;
648 E : arglist_id = type_info.body().arglist;
649 E : } else if (type_info_enum_.type() == cci::LF_MFUNCTION) {
650 : // Load the member function record.
651 E : pdb::LeafMFunction type_info;
652 E : if (!type_info.Initialize(stream_.get())) {
653 i : LOG(ERROR) << "Unable to read type info record.";
654 i : return nullptr;
655 : }
656 :
657 : call_convention =
658 E : static_cast<FunctionType::CallConvention>(type_info.body().calltype);
659 E : return_type_id = type_info.body().rvtype;
660 E : arglist_id = type_info.body().arglist;
661 E : containing_class_id = type_info.body().classtype;
662 E : } else {
663 i : return nullptr;
664 : }
665 :
666 E : FunctionTypePtr function_type = new FunctionType(call_convention);
667 E : if (!repository_->AddTypeWithId(function_type, type_id))
668 i : return false;
669 :
670 E : Type::Flags flags = kNoTypeFlags;
671 : TypePtr return_type =
672 E : FindOrCreateOptionallyModifiedType(return_type_id, &flags);
673 E : if (return_type == nullptr)
674 i : return false;
675 :
676 : // If this is a member function parse the containing class.
677 E : if (containing_class_id != kNoTypeId) {
678 E : TypePtr class_type = FindOrCreateStructuredType(containing_class_id);
679 E : if (class_type == nullptr)
680 i : return nullptr;
681 :
682 E : containing_class_id = class_type->type_id();
683 E : }
684 :
685 : // Parse the argument list.
686 E : FunctionType::Arguments arglist;
687 E : if (!ReadArglist(arglist_id, &arglist))
688 i : return false;
689 :
690 : function_type->Finalize(
691 : FunctionType::ArgumentType(flags, return_type->type_id()), arglist,
692 E : containing_class_id);
693 E : return function_type;
694 E : }
695 :
696 : TypePtr TypeCreator::ReadBitfield(TypeId type_id,
697 : Type::Flags* flags,
698 : size_t* bit_pos,
699 E : size_t* bit_len) {
700 E : DCHECK(flags);
701 E : DCHECK(bit_pos);
702 E : DCHECK(bit_len);
703 E : DCHECK(GetLeafType(type_id) == cci::LF_BITFIELD);
704 :
705 E : if (!type_info_enum_.SeekRecord(type_id))
706 i : return nullptr;
707 :
708 E : pdb::LeafBitfield type_info;
709 E : if (!type_info.Initialize(stream_.get())) {
710 i : LOG(ERROR) << "Unable to read type info record.";
711 i : return nullptr;
712 : }
713 :
714 E : const size_t kMaxBitfieldValue = 63;
715 : if (type_info.body().position > kMaxBitfieldValue ||
716 E : type_info.body().length > kMaxBitfieldValue) {
717 i : LOG(ERROR) << "The bit position or length of bitfield is too large.";
718 i : return nullptr;
719 : }
720 :
721 E : *bit_pos = type_info.body().position;
722 E : *bit_len = type_info.body().length;
723 :
724 E : TypeId underlying_id = type_info.body().type;
725 E : *flags = kNoTypeFlags;
726 :
727 E : return FindOrCreateBitfieldType(underlying_id, flags);
728 E : }
729 :
730 : TypeCreator::TypeCreator(TypeRepository* repository)
731 E : : repository_(repository), type_namer_(true) {
732 E : DCHECK(repository);
733 E : }
734 :
735 E : TypeCreator::~TypeCreator() {
736 E : }
737 :
738 : bool TypeCreator::ProcessMember(pdb::LeafMember* member,
739 E : UserDefinedType::Fields* fields) {
740 E : DCHECK(member);
741 E : DCHECK(fields);
742 :
743 : // TODO(mopler): Should we store the access protection and other info?
744 : // Get the member info.
745 E : TypeId member_id = member->body().index;
746 E : Type::Flags flags = kNoTypeFlags;
747 E : size_t bit_pos = 0;
748 E : size_t bit_len = 0;
749 : TypePtr member_type =
750 E : FindOrCreateMemberType(member_id, &flags, &bit_pos, &bit_len);
751 E : if (member_type == nullptr)
752 i : return false;
753 :
754 : fields->push_back(UserDefinedType::Field(member->name(), member->offset(),
755 : flags, bit_pos, bit_len,
756 E : member_type->type_id()));
757 E : return true;
758 E : }
759 :
760 : bool TypeCreator::ProcessOneMethod(pdb::LeafOneMethod* method,
761 E : UserDefinedType::Functions* functions) {
762 E : DCHECK(method);
763 E : DCHECK(functions);
764 :
765 : // Parse the function type.
766 E : TypeId function_id = method->body().index;
767 E : if (FindOrCreateSpecificType(function_id, cci::LF_MFUNCTION) == nullptr)
768 i : return false;
769 :
770 E : functions->push_back(UserDefinedType::Function(method->name(), function_id));
771 E : return true;
772 E : }
773 :
774 : bool TypeCreator::ProcessMethod(pdb::LeafMethod* method,
775 E : UserDefinedType::Functions* functions) {
776 E : DCHECK(method);
777 E : DCHECK(functions);
778 :
779 : // Seek the method list record.
780 : if (!type_info_enum_.SeekRecord(method->body().mList) ||
781 E : type_info_enum_.type() != cci::LF_METHODLIST) {
782 i : return false;
783 : }
784 :
785 : // We need a local copy of the data in order to load the records.
786 E : scoped_refptr<pdb::PdbByteStream> local_stream(new pdb::PdbByteStream());
787 E : local_stream->Init(stream_.get());
788 :
789 E : uint16_t count = method->body().count;
790 E : while (count > 0) {
791 E : pdb::MethodListRecord method_record;
792 E : if (!method_record.Initialize(local_stream.get())) {
793 i : LOG(ERROR) << "Unable to read method list record.";
794 i : return false;
795 : }
796 :
797 : // Parse the function type.
798 E : TypeId function_id = method_record.body().index;
799 E : if (FindOrCreateSpecificType(function_id, cci::LF_MFUNCTION) == nullptr)
800 i : return false;
801 :
802 : functions->push_back(
803 E : UserDefinedType::Function(method->name(), function_id));
804 :
805 E : count--;
806 E : }
807 E : return true;
808 E : }
809 :
810 E : base::string16 TypeCreator::BasicTypeName(uint16_t type) {
811 E : switch (type) {
812 : // Just return the name of the type.
813 : #define SPECIAL_TYPE_NAME(record_type, type_name, size) \
814 : case cci::record_type: return L#type_name;
815 E : SPECIAL_TYPE_NAME_CASE_TABLE(SPECIAL_TYPE_NAME)
816 : #undef SPECIAL_TYPE_NAME
817 : }
818 i : return L"unknown_basic_type";
819 E : }
820 :
821 E : size_t TypeCreator::BasicTypeSize(uint16_t type) {
822 E : switch (type) {
823 : // Just return the size of the type.
824 : #define SPECIAL_TYPE_NAME(record_type, type_name, size) \
825 : case cci::record_type: return size;
826 E : SPECIAL_TYPE_NAME_CASE_TABLE(SPECIAL_TYPE_NAME)
827 : #undef SPECIAL_TYPE_NAME
828 : }
829 i : return 0;
830 E : }
831 :
832 E : base::string16 TypeCreator::LeafTypeName(uint16_t leaf_type) {
833 E : switch (leaf_type) {
834 : // Just return the name of the enum.
835 : #define LEAF_TYPE_NAME(record_type, unused) \
836 : case cci::record_type: { \
837 : return L#record_type; \
838 : }
839 E : LEAF_CASE_TABLE(LEAF_TYPE_NAME)
840 : #undef LEAF_TYPE_NAME
841 : default:
842 i : return L"UnknownLeaf";
843 : }
844 E : }
845 :
846 E : size_t TypeCreator::PointerSize(const pdb::LeafPointer& ptr) {
847 E : size_t size = 0;
848 : const cci::CV_ptrtype ptrtype =
849 E : static_cast<cci::CV_ptrtype>(ptr.attr().ptrtype);
850 : // Set the size of the pointer.
851 E : switch (ptr.attr().ptrmode) {
852 : // The size of a regular pointer or reference can be deduced from its type.
853 : // TODO(mopler): Investigate references.
854 : case cci::CV_PTR_MODE_PTR:
855 : case cci::CV_PTR_MODE_REF: {
856 E : if (ptrtype == cci::CV_PTR_NEAR32)
857 E : size = 4;
858 E : else if (ptrtype == cci::CV_PTR_64)
859 E : size = 8;
860 E : break;
861 : }
862 : // However in case of a member field pointer, its size depends on the
863 : // properties of the containing class. The pointer contains extra
864 : // information about the containing class.
865 : case cci::CV_PTR_MODE_PMFUNC:
866 : case cci::CV_PTR_MODE_PMEM: {
867 E : const cci::CV_pmtype pmtype = static_cast<cci::CV_pmtype>(ptr.pmtype());
868 E : size = MemberPointerSize(pmtype, ptrtype);
869 : break;
870 : }
871 : }
872 E : return size;
873 E : }
874 :
875 : size_t TypeCreator::MemberPointerSize(cci::CV_pmtype pmtype,
876 E : cci::CV_ptrtype ptrtype) {
877 E : DCHECK(ptrtype == cci::CV_PTR_NEAR32 || ptrtype == cci::CV_PTR_64);
878 :
879 : // The translation of modes to pointer sizes depends on the compiler. The
880 : // following values have been determined experimentally. For details see
881 : // https://github.com/google/syzygy/wiki/MemberPointersInPdbFiles.
882 E : if (ptrtype == cci::CV_PTR_NEAR32) {
883 E : switch (pmtype) {
884 : case cci::CV_PMTYPE_Undef:
885 i : return 0;
886 : case cci::CV_PMTYPE_D_Single:
887 E : return 4;
888 : case cci::CV_PMTYPE_D_Multiple:
889 E : return 4;
890 : case cci::CV_PMTYPE_D_Virtual:
891 E : return 8;
892 : case cci::CV_PMTYPE_D_General:
893 E : return 12;
894 : case cci::CV_PMTYPE_F_Single:
895 E : return 4;
896 : case cci::CV_PMTYPE_F_Multiple:
897 E : return 8;
898 : case cci::CV_PMTYPE_F_Virtual:
899 E : return 12;
900 : case cci::CV_PMTYPE_F_General:
901 E : return 16;
902 : }
903 E : } else if (ptrtype == cci::CV_PTR_64) {
904 E : switch (pmtype) {
905 : case cci::CV_PMTYPE_Undef:
906 i : return 0;
907 : case cci::CV_PMTYPE_D_Single:
908 E : return 4;
909 : case cci::CV_PMTYPE_D_Multiple:
910 E : return 4;
911 : case cci::CV_PMTYPE_D_Virtual:
912 E : return 8;
913 : case cci::CV_PMTYPE_D_General:
914 E : return 12;
915 : case cci::CV_PMTYPE_F_Single:
916 E : return 8;
917 : case cci::CV_PMTYPE_F_Multiple:
918 E : return 16;
919 : case cci::CV_PMTYPE_F_Virtual:
920 E : return 16;
921 : case cci::CV_PMTYPE_F_General:
922 E : return 24;
923 : }
924 : }
925 : // It seems that VS doesn't use the other pointer types in PDB files.
926 i : NOTREACHED();
927 i : return 0;
928 E : }
929 :
930 E : bool TypeCreator::IsImportantType(uint32_t type) {
931 E : switch (type) {
932 : case cci::LF_CLASS:
933 : case cci::LF_STRUCTURE:
934 : case cci::LF_UNION:
935 : case cci::LF_ARRAY:
936 : case cci::LF_POINTER:
937 : case cci::LF_PROCEDURE:
938 : case cci::LF_MFUNCTION:
939 E : return true;
940 : }
941 E : return false;
942 E : }
943 :
944 E : Type::Flags TypeCreator::CreateTypeFlags(bool is_const, bool is_volatile) {
945 E : Type::Flags flags = kNoTypeFlags;
946 E : if (is_const)
947 E : flags |= Type::FLAG_CONST;
948 E : if (is_volatile)
949 E : flags |= Type::FLAG_VOLATILE;
950 E : return flags;
951 E : }
952 :
953 E : uint16_t TypeCreator::GetLeafType(TypeId type_id) {
954 E : if (type_id < cci::CV_PRIMITIVE_TYPE::CV_FIRST_NONPRIM)
955 E : return type_id;
956 :
957 E : auto it = types_map_.find(type_id);
958 E : if (it == types_map_.end()) {
959 i : LOG(ERROR) << "Couldn't find record with type index " << type_id
960 : << " in the types map.";
961 i : return kNoLeafType;
962 i : } else {
963 E : return it->second;
964 : }
965 E : }
966 :
967 : bool TypeCreator::CacheUserDefinedTypeForwardDeclaration(TypeId fwd_id,
968 E : TypeId class_id) {
969 E : return fwd_reference_map_.insert(std::make_pair(fwd_id, class_id)).second;
970 E : }
971 :
972 E : TypeId TypeCreator::LookupConcreteClassForForwardDeclaration(TypeId type_id) {
973 E : auto redir = fwd_reference_map_.find(type_id);
974 E : if (redir != fwd_reference_map_.end()) {
975 E : return redir->second;
976 i : } else {
977 E : return kNoTypeId;
978 : }
979 E : }
980 :
981 E : bool TypeCreator::IsBasicPointerType(TypeId type_id) {
982 E : if (type_id >= cci::CV_PRIMITIVE_TYPE::CV_FIRST_NONPRIM)
983 E : return false;
984 :
985 : // T_PVOID is used to encode std::nullptr_t which we save as a basic type.
986 E : if (type_id == cci::T_PVOID)
987 E : return false;
988 :
989 E : if (TypeIndexToPrMode(type_id) == cci::CV_TM_DIRECT)
990 E : return false;
991 :
992 E : return true;
993 E : }
994 :
995 E : cci::CV_prmode TypeCreator::TypeIndexToPrMode(TypeId type_id) {
996 : return static_cast<cci::CV_prmode>(
997 : (type_id & cci::CV_PRIMITIVE_TYPE::CV_MMASK) >>
998 E : cci::CV_PRIMITIVE_TYPE::CV_MSHIFT);
999 E : }
1000 :
1001 E : TypePtr TypeCreator::CreateBasicType(TypeId type_id) {
1002 E : DCHECK(type_id < cci::CV_PRIMITIVE_TYPE::CV_FIRST_NONPRIM);
1003 :
1004 : BasicTypePtr basic_type =
1005 E : new BasicType(BasicTypeName(type_id), BasicTypeSize(type_id));
1006 :
1007 : // Save type and additional info.
1008 E : if (!repository_->AddTypeWithId(basic_type, type_id))
1009 i : return nullptr;
1010 E : return basic_type;
1011 E : }
1012 :
1013 E : TypePtr TypeCreator::CreateWildcardType(TypeId type_id) {
1014 E : base::string16 name = LeafTypeName(GetLeafType(type_id));
1015 E : TypePtr wildcard_type = new WildcardType(name, name, 0);
1016 E : if (!repository_->AddTypeWithId(wildcard_type, type_id))
1017 i : return nullptr;
1018 E : return wildcard_type;
1019 E : }
1020 :
1021 E : TypePtr TypeCreator::FindOrCreateTypeImpl(TypeId type_id) {
1022 E : TypeId concrete_type_id = LookupConcreteClassForForwardDeclaration(type_id);
1023 E : if (concrete_type_id != kNoTypeId)
1024 E : return repository_->GetType(concrete_type_id);
1025 :
1026 E : TypePtr type = repository_->GetType(type_id);
1027 E : if (type != nullptr)
1028 E : return type;
1029 :
1030 : // We need to create new type object.
1031 : // Check if it is a regular type index.
1032 E : if (type_id >= type_info_enum_.type_info_header().type_min) {
1033 E : return CreateType(type_id);
1034 i : } else {
1035 : // Check if this is actually a pointer.
1036 E : if (IsBasicPointerType(type_id)) {
1037 E : return CreateBasicPointerType(type_id);
1038 i : } else {
1039 : // Otherwise create the basic type.
1040 E : return CreateBasicType(type_id);
1041 : }
1042 : }
1043 E : }
1044 :
1045 E : TypePtr TypeCreator::FindOrCreateIndexingType(TypeId type_id) {
1046 E : if (type_id == cci::T_ULONG || type_id == cci::T_UQUAD)
1047 E : return FindOrCreateTypeImpl(type_id);
1048 :
1049 i : return nullptr;
1050 E : }
1051 :
1052 E : TypePtr TypeCreator::FindOrCreateIntegralBasicType(TypeId type_id) {
1053 : TypeId type_mask = (type_id & cci::CV_PRIMITIVE_TYPE::CV_TMASK) >>
1054 E : cci::CV_PRIMITIVE_TYPE::CV_TSHIFT;
1055 :
1056 : if (type_mask == cci::CV_SIGNED || type_mask == cci::CV_UNSIGNED ||
1057 E : type_mask == cci::CV_INT || type_mask == cci::CV_BOOLEAN) {
1058 E : return FindOrCreateBasicType(type_id);
1059 : }
1060 :
1061 i : return nullptr;
1062 E : }
1063 :
1064 E : TypePtr TypeCreator::FindOrCreateBasicType(TypeId type_id) {
1065 : if (type_id < cci::CV_PRIMITIVE_TYPE::CV_FIRST_NONPRIM &&
1066 E : !IsBasicPointerType(type_id)) {
1067 E : return FindOrCreateTypeImpl(type_id);
1068 : }
1069 :
1070 i : return nullptr;
1071 E : }
1072 :
1073 E : TypePtr TypeCreator::FindOrCreateInheritableType(TypeId type_id) {
1074 E : uint16_t type = GetLeafType(type_id);
1075 E : if (type == cci::LF_CLASS || type == cci::LF_STRUCTURE)
1076 E : return FindOrCreateTypeImpl(type_id);
1077 :
1078 i : return nullptr;
1079 E : }
1080 :
1081 E : TypePtr TypeCreator::FindOrCreateStructuredType(TypeId type_id) {
1082 E : uint16_t type = GetLeafType(type_id);
1083 E : if (type == cci::LF_UNION)
1084 E : return FindOrCreateTypeImpl(type_id);
1085 :
1086 E : return FindOrCreateInheritableType(type_id);
1087 E : }
1088 :
1089 E : TypePtr TypeCreator::FindOrCreateUserDefinedType(TypeId type_id) {
1090 E : uint16_t type = GetLeafType(type_id);
1091 E : if (type == cci::LF_ENUM)
1092 E : return FindOrCreateTypeImpl(type_id);
1093 :
1094 E : return FindOrCreateStructuredType(type_id);
1095 E : }
1096 :
1097 E : TypePtr TypeCreator::FindOrCreateModifiableType(TypeId type_id) {
1098 E : uint16_t type = GetLeafType(type_id);
1099 :
1100 E : if (type < cci::CV_PRIMITIVE_TYPE::CV_FIRST_NONPRIM)
1101 E : return FindOrCreateBasicType(type_id);
1102 :
1103 E : return FindOrCreateUserDefinedType(type_id);
1104 E : }
1105 :
1106 : TypePtr TypeCreator::FindOrCreateOptionallyModifiedType(TypeId type_id,
1107 E : Type::Flags* flags) {
1108 E : DCHECK(flags);
1109 E : uint16_t type = GetLeafType(type_id);
1110 E : *flags = kNoTypeFlags;
1111 :
1112 E : if (type == cci::LF_MODIFIER)
1113 E : return ReadModifier(type_id, flags);
1114 :
1115 E : if (type == cci::LF_POINTER)
1116 E : return ReadPointer(type_id, flags);
1117 :
1118 E : if (type == cci::LF_ARRAY)
1119 E : return FindOrCreateTypeImpl(type_id);
1120 :
1121 E : if (IsBasicPointerType(type_id))
1122 E : return FindOrCreateTypeImpl(type_id);
1123 :
1124 E : return FindOrCreateModifiableType(type_id);
1125 E : }
1126 :
1127 : TypePtr TypeCreator::FindOrCreateBitfieldType(TypeId type_id,
1128 E : Type::Flags* flags) {
1129 E : DCHECK(flags);
1130 E : uint16_t type = GetLeafType(type_id);
1131 E : *flags = kNoTypeFlags;
1132 :
1133 E : if (type == cci::LF_MODIFIER) {
1134 E : TypePtr type = ReadModifier(type_id, flags);
1135 : // TODO(mopler): Once we load enums change the name test to type test.
1136 E : if (type->kind() == Type::BASIC_TYPE_KIND || type->name() == L"LF_ENUM")
1137 E : return type;
1138 :
1139 i : return nullptr;
1140 : }
1141 :
1142 E : if (type == cci::LF_ENUM)
1143 E : return FindOrCreateTypeImpl(type_id);
1144 :
1145 E : return FindOrCreateIntegralBasicType(type_id);
1146 E : }
1147 :
1148 : TypePtr TypeCreator::FindOrCreateMemberType(TypeId type_id,
1149 : Type::Flags* flags,
1150 : size_t* bit_pos,
1151 E : size_t* bit_len) {
1152 E : DCHECK(flags);
1153 E : DCHECK(bit_pos);
1154 E : DCHECK(bit_len);
1155 :
1156 E : uint16_t type = GetLeafType(type_id);
1157 E : *flags = kNoTypeFlags;
1158 E : *bit_pos = 0;
1159 E : *bit_len = 0;
1160 :
1161 E : if (type == cci::LF_BITFIELD)
1162 E : return ReadBitfield(type_id, flags, bit_pos, bit_len);
1163 :
1164 E : return FindOrCreateOptionallyModifiedType(type_id, flags);
1165 E : }
1166 :
1167 : TypePtr TypeCreator::FindOrCreatePointableType(TypeId type_id,
1168 E : Type::Flags* flags) {
1169 E : DCHECK(flags);
1170 E : *flags = kNoTypeFlags;
1171 E : uint16_t type = GetLeafType(type_id);
1172 :
1173 : if (type == cci::LF_MFUNCTION || type == cci::LF_PROCEDURE ||
1174 E : type == cci::LF_VTSHAPE) {
1175 E : return FindOrCreateTypeImpl(type_id);
1176 : }
1177 :
1178 E : return FindOrCreateOptionallyModifiedType(type_id, flags);
1179 E : }
1180 :
1181 E : TypePtr TypeCreator::FindOrCreateSpecificType(TypeId type_id, uint16_t type) {
1182 E : DCHECK_NE(kNoLeafType, type);
1183 E : uint16_t this_type = GetLeafType(type_id);
1184 :
1185 E : if (this_type != type)
1186 i : return nullptr;
1187 :
1188 E : return FindOrCreateTypeImpl(type_id);
1189 E : }
1190 :
1191 E : TypePtr TypeCreator::CreateType(TypeId type_id) {
1192 E : switch (GetLeafType(type_id)) {
1193 : case cci::LF_CLASS:
1194 : case cci::LF_STRUCTURE:
1195 : case cci::LF_UNION: {
1196 E : return CreateUserDefinedType(type_id);
1197 : }
1198 : case cci::LF_POINTER: {
1199 E : return CreatePointerType(type_id);
1200 : }
1201 : case cci::LF_ARRAY: {
1202 E : return CreateArrayType(type_id);
1203 : }
1204 : case cci::LF_PROCEDURE:
1205 : case cci::LF_MFUNCTION: {
1206 E : return CreateFunctionType(type_id);
1207 : }
1208 E : default: { return CreateWildcardType(type_id); }
1209 : }
1210 E : }
1211 :
1212 E : bool TypeCreator::PrepareData() {
1213 E : size_t unexpected_duplicate_types = 0;
1214 :
1215 E : while (!type_info_enum_.EndOfStream()) {
1216 E : if (!type_info_enum_.NextTypeInfoRecord())
1217 i : return false;
1218 :
1219 : types_map_.insert(
1220 E : std::make_pair(type_info_enum_.type_id(), type_info_enum_.type()));
1221 :
1222 : // We remember ids of the types that we will later descend into.
1223 E : if (IsImportantType(type_info_enum_.type()))
1224 E : records_to_process_.push_back(type_info_enum_.type_id());
1225 :
1226 : if (type_info_enum_.type() == cci::LF_CLASS ||
1227 E : type_info_enum_.type() == cci::LF_STRUCTURE) {
1228 E : pdb::LeafClass type_info;
1229 E : if (!type_info.Initialize(stream_.get())) {
1230 i : LOG(ERROR) << "Unable to read type info record.";
1231 i : return false;
1232 : }
1233 :
1234 : // Populate the decorated name to type index map. Note that this
1235 : // overwrites any preceding record of the same name, which can occur for
1236 : // 2 reasons:
1237 : // - the unnamed nested structures get assigned the name <unnamed-tag>
1238 : // - we've observed UDTs that are identical up to extra LF_NESTTYPE
1239 : // (which do not make it to our type representation).
1240 : // TODO(manzagop): investigate more and consider folding duplicate types.
1241 E : if (!type_info.property().fwdref) {
1242 : if (type_info.name().find(L'<') != 0 &&
1243 E : udt_map_.find(type_info.decorated_name()) != udt_map_.end()) {
1244 i : VLOG(1) << "Encountered duplicate decorated name: "
1245 : << type_info.decorated_name();
1246 i : unexpected_duplicate_types++;
1247 : }
1248 :
1249 E : udt_map_[type_info.decorated_name()] = type_info_enum_.type_id();
1250 : }
1251 E : }
1252 E : }
1253 :
1254 E : if (unexpected_duplicate_types > 0) {
1255 i : LOG(INFO) << "Encountered " << unexpected_duplicate_types
1256 : << " unexpected duplicate types.";
1257 : }
1258 :
1259 E : return type_info_enum_.ResetStream();
1260 E : }
1261 :
1262 E : bool TypeCreator::CreateTypes(scoped_refptr<pdb::PdbStream> stream) {
1263 E : DCHECK(stream);
1264 :
1265 E : if (!type_info_enum_.Init(stream.get())) {
1266 i : LOG(ERROR) << "Unable to initialize type info stream enumerator.";
1267 i : return false;
1268 : }
1269 :
1270 E : const TypeId kSmallestUnreservedIndex = 0x1000;
1271 E : if (type_info_enum_.type_info_header().type_min < kSmallestUnreservedIndex) {
1272 i : LOG(ERROR) << "Degenerate stream with type indices in the reserved range.";
1273 i : return false;
1274 : }
1275 :
1276 E : stream_ = type_info_enum_.GetDataStream();
1277 :
1278 : // Create the map of forward declarations and populate the process queue.
1279 E : if (!PrepareData())
1280 i : return false;
1281 :
1282 : // Process every important type.
1283 E : for (TypeId type_id : records_to_process_) {
1284 E : if (FindOrCreateTypeImpl(type_id) == nullptr)
1285 i : return false;
1286 E : }
1287 :
1288 : // And assign type names.
1289 E : for (auto type : *repository_) {
1290 E : if (!type_namer_.EnsureTypeName(type))
1291 i : return false;
1292 E : }
1293 :
1294 E : return true;
1295 E : }
1296 :
1297 : } // namespace
1298 :
1299 E : PdbCrawler::PdbCrawler() {
1300 E : }
1301 :
1302 E : PdbCrawler::~PdbCrawler() {
1303 E : }
1304 :
1305 E : bool PdbCrawler::InitializeForFile(const base::FilePath& path) {
1306 E : pdb::PdbReader reader;
1307 E : pdb::PdbFile pdb_file;
1308 :
1309 E : if (!reader.Read(path, &pdb_file)) {
1310 i : LOG(ERROR) << "Failed to read PDB file " << path.value() << ".";
1311 i : return false;
1312 : }
1313 :
1314 E : stream_ = pdb_file.GetStream(pdb::kTpiStream);
1315 E : return true;
1316 E : }
1317 :
1318 E : bool PdbCrawler::GetTypes(TypeRepository* types) {
1319 E : DCHECK(types);
1320 E : DCHECK(stream_);
1321 :
1322 E : TypeCreator creator(types);
1323 :
1324 E : return creator.CreateTypes(stream_);
1325 E : }
1326 :
1327 : } // namespace refinery
|