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