Coverage for /Syzygy/refinery/types/pdb_crawler.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
81.3%5366590.C++source

Line-by-line coverage:

   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

Coverage information generated Thu Jan 14 17:40:38 2016.