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

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
0.0%00369.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/type_namer.h"
  16    :  
  17    :  #include <vector>
  18    :  
  19    :  #include "base/strings/string_util.h"
  20    :  #include "base/strings/stringprintf.h"
  21    :  #include "base/strings/utf_string_conversions.h"
  22    :  #include "syzygy/pe/dia_util.h"
  23    :  #include "third_party/cci/files/cvinfo.h"
  24    :  
  25  m :  namespace refinery {
  26    :  
  27  m :  namespace {
  28    :  
  29  m :  namespace cci = Microsoft_Cci_Pdb;
  30    :  
  31  m :  base::string16 GetCVMod(bool is_const, bool is_volatile) {
  32  m :    base::string16 suffix;
  33  m :    if (is_const)
  34  m :      suffix += L" const";
  35  m :    if (is_volatile)
  36  m :      suffix += L" volatile";
  37  m :    return suffix;
  38  m :  }
  39    :  
  40  m :  void AppendPointerNameSuffix(bool is_const,
  41  m :                               bool is_volatile,
  42  m :                               bool is_ref,
  43  m :                               base::string16* name) {
  44  m :    DCHECK(name);
  45    :  
  46  m :    name->append(GetCVMod(is_const, is_volatile));
  47  m :    if (is_ref)
  48  m :      name->append(L"&");
  49  m :    else
  50  m :      name->append(L"*");
  51  m :  }
  52    :  
  53  m :  void AppendArrayNameSuffix(bool is_const,
  54  m :                             bool is_volatile,
  55  m :                             size_t count,
  56  m :                             base::string16* name) {
  57  m :    DCHECK(name);
  58  m :    name->append(GetCVMod(is_const, is_volatile));
  59  m :    base::StringAppendF(name, L"[%d]", count);
  60  m :  }
  61    :  
  62  m :  }  // namespace
  63    :  
  64  m :  bool GetSymBaseTypeName(IDiaSymbol* symbol, base::string16* type_name) {
  65  m :    DWORD base_type = 0;
  66  m :    HRESULT hr = symbol->get_baseType(&base_type);
  67  m :    if (hr != S_OK)
  68  m :      return false;
  69    :  
  70  m :    ULONGLONG length = 0;
  71  m :    hr = symbol->get_length(&length);
  72  m :    if (hr != S_OK)
  73  m :      return false;
  74    :  
  75    :    // TODO(siggi): What to do for these basic type names?
  76    :    //     One idea is to standardize on stdint.h types?
  77  m :    switch (base_type) {
  78  m :      case btNoType:
  79  m :        *type_name = L"btNoType";
  80  m :        break;
  81  m :      case btVoid:
  82  m :        *type_name = L"void";
  83  m :        break;
  84  m :      case btChar:
  85  m :        *type_name = L"char";
  86  m :        break;
  87  m :      case btWChar:
  88  m :        *type_name = L"wchar_t";
  89  m :        break;
  90  m :      case btInt:
  91  m :      case btLong: {
  92  m :        switch (length) {
  93  m :          case 1:
  94  m :            *type_name = L"int8_t";
  95  m :            break;
  96  m :          case 2:
  97  m :            *type_name = L"int16_t";
  98  m :            break;
  99  m :          case 4:
 100  m :            *type_name = L"int32_t";
 101  m :            break;
 102  m :          case 8:
 103  m :            *type_name = L"int64_t";
 104  m :            break;
 105    :  
 106  m :          default:
 107  m :            return false;
 108  m :        }
 109  m :        break;
 110  m :      }
 111  m :      case btUInt:
 112  m :      case btULong: {
 113  m :        switch (length) {
 114  m :          case 1:
 115  m :            *type_name = L"uint8_t";
 116  m :            break;
 117  m :          case 2:
 118  m :            *type_name = L"uint16_t";
 119  m :            break;
 120  m :          case 4:
 121  m :            *type_name = L"uint32_t";
 122  m :            break;
 123  m :          case 8:
 124  m :            *type_name = L"uint64_t";
 125  m :            break;
 126    :  
 127  m :          default:
 128  m :            return false;
 129  m :        }
 130  m :        break;
 131  m :      }
 132    :  
 133  m :      case btFloat:
 134  m :        *type_name = L"float";
 135  m :        break;
 136  m :      case btBCD:
 137  m :        *type_name = L"BCD";
 138  m :        break;
 139  m :      case btBool:
 140  m :        *type_name = L"bool";
 141  m :        break;
 142  m :      case btCurrency:
 143  m :        *type_name = L"Currency";
 144  m :        break;
 145  m :      case btDate:
 146  m :        *type_name = L"Date";
 147  m :        break;
 148  m :      case btVariant:
 149  m :        *type_name = L"Variant";
 150  m :        break;
 151  m :      case btComplex:
 152  m :        *type_name = L"Complex";
 153  m :        break;
 154  m :      case btBit:
 155  m :        *type_name = L"Bit";
 156  m :        break;
 157  m :      case btBSTR:
 158  m :        *type_name = L"BSTR";
 159  m :        break;
 160  m :      case btHresult:
 161  m :        *type_name = L"HRESULT";
 162  m :        break;
 163  m :      default:
 164  m :        return false;
 165  m :    }
 166    :  
 167  m :    return true;
 168  m :  }
 169    :  
 170  m :  bool TypeNamer::GetName(ConstTypePtr type, base::string16* type_name) {
 171  m :    return GetName(type, false, type_name);
 172  m :  }
 173    :  
 174  m :  bool TypeNamer::GetDecoratedName(ConstTypePtr type,
 175  m :                                   base::string16* type_name) {
 176  m :    return GetName(type, true, type_name);
 177  m :  }
 178    :  
 179  m :  bool TypeNamer::GetName(ConstTypePtr type,
 180  m :                          bool decorated,
 181  m :                          base::string16* type_name) {
 182  m :    DCHECK(type);  DCHECK(type_name);
 183  m :    type_name->clear();
 184    :  
 185  m :    switch (type->kind()) {
 186  m :      case Type::POINTER_TYPE_KIND: {
 187  m :        ConstPointerTypePtr ptr;
 188  m :        CHECK(type->CastTo(&ptr));
 189  m :        return GetPointerName(ptr, decorated, type_name);
 190  m :      }
 191  m :      case Type::ARRAY_TYPE_KIND: {
 192  m :        ConstArrayTypePtr array;
 193  m :        CHECK(type->CastTo(&array));
 194  m :        return GetArrayName(array, decorated, type_name);
 195  m :      }
 196  m :      case Type::FUNCTION_TYPE_KIND: {
 197  m :        ConstFunctionTypePtr function;
 198  m :        CHECK(type->CastTo(&function));
 199  m :        return GetFunctionName(function, decorated, type_name);
 200  m :      }
 201  m :      case Type::USER_DEFINED_TYPE_KIND:
 202  m :      case Type::BASIC_TYPE_KIND:
 203  m :      case Type::GLOBAL_TYPE_KIND:
 204  m :      case Type::WILDCARD_TYPE_KIND: {
 205    :        // These types should have their name set up.
 206  m :        if (decorated)
 207  m :          *type_name = type->GetDecoratedName();
 208  m :        else
 209  m :          *type_name = type->GetName();
 210  m :        return true;
 211  m :      }
 212  m :      default:
 213  m :        DCHECK(false);
 214  m :        return false;
 215  m :    }
 216  m :  }
 217    :  
 218  m :  bool TypeNamer::GetPointerName(ConstPointerTypePtr ptr,
 219  m :                                 bool decorated,
 220  m :                                 base::string16* type_name) {
 221  m :    DCHECK(ptr);  DCHECK(type_name);
 222  m :    type_name->clear();
 223    :  
 224    :    // Get the content type's name.
 225  m :    ConstTypePtr content_type = ptr->GetContentType();
 226  m :    if (!content_type)
 227  m :      return false;
 228  m :    if (!GetName(content_type, decorated, type_name))
 229  m :      return false;
 230    :  
 231    :    // Append the suffix.
 232  m :    bool is_ref = (ptr->ptr_mode() != PointerType::PTR_MODE_PTR);
 233  m :    AppendPointerNameSuffix(ptr->is_const(), ptr->is_volatile(), is_ref,
 234  m :                            type_name);
 235    :  
 236  m :    return true;
 237  m :  }
 238    :  
 239  m :  bool TypeNamer::GetArrayName(ConstArrayTypePtr array,
 240  m :                               bool decorated,
 241  m :                               base::string16* type_name) {
 242  m :    DCHECK(array);  DCHECK(type_name);
 243  m :    type_name->clear();
 244    :  
 245    :    // Get the element type's name.
 246  m :    ConstTypePtr element_type = array->GetElementType();
 247  m :    if (!element_type)
 248  m :      return false;
 249  m :    if (!GetName(element_type, decorated, type_name))
 250  m :      return false;
 251    :  
 252    :    // Append the suffix.
 253  m :    AppendArrayNameSuffix(array->is_const(), array->is_volatile(),
 254  m :                          array->num_elements(), type_name);
 255  m :    return true;
 256  m :  }
 257    :  
 258  m :  bool TypeNamer::GetFunctionName(ConstFunctionTypePtr function,
 259  m :                                  bool decorated,
 260  m :                                  base::string16* type_name) {
 261  m :    DCHECK(function);  DCHECK(type_name);
 262  m :    type_name->clear();
 263    :  
 264    :    // Start with the return type.
 265  m :    ConstTypePtr return_type = function->GetReturnType();
 266  m :    if (!return_type)
 267  m :      return false;
 268  m :    if (!GetName(return_type, decorated, type_name))
 269  m :      return false;
 270    :  
 271    :    // Append CV qualifiers.
 272  m :    base::string16 suffix = GetCVMod(function->return_type().is_const(),
 273  m :                                     function->return_type().is_volatile());
 274  m :    suffix.append(L" (");
 275  m :    type_name->append(suffix);
 276    :  
 277    :    // Continue with containing class.
 278  m :    if (function->IsMemberFunction()) {
 279  m :      ConstTypePtr class_type = function->GetContainingClassType();
 280  m :      if (!class_type)
 281  m :        return false;
 282  m :      base::string16 class_name;
 283  m :      if (!GetName(class_type, decorated, &class_name))
 284  m :        return false;
 285  m :      type_name->append(class_name + L"::)(");
 286  m :    }
 287    :  
 288    :    // Get the argument types names.
 289  m :    std::vector<base::string16> arg_names;
 290  m :    for (size_t i = 0; i < function->argument_types().size(); ++i) {
 291  m :      ConstTypePtr arg_type = function->GetArgumentType(i);
 292  m :      if (!arg_type)
 293  m :        return false;
 294    :  
 295    :      // Append the names, if the argument type is T_NOTYPE then this is a
 296    :      // C-style variadic function like printf and we append "..." instead.
 297  m :      if (arg_type->type_id() == cci::T_NOTYPE) {
 298  m :        arg_names.push_back(L"...");
 299  m :      } else {
 300  m :        arg_names.push_back(L"");
 301    :  
 302  m :        if (!GetName(arg_type, decorated, &arg_names[i]))
 303  m :          return false;
 304    :  
 305  m :        const FunctionType::ArgumentType& arg = function->argument_types()[i];
 306  m :        base::string16 CV_mods = GetCVMod(arg.is_const(), arg.is_volatile());
 307    :  
 308  m :        arg_names[i].append(CV_mods);
 309  m :      }
 310  m :    }
 311    :  
 312  m :    type_name->append(base::JoinString(arg_names, L", "));
 313  m :    type_name->append(L")");
 314    :  
 315  m :    return true;
 316  m :  }
 317    :  
 318  m :  bool DiaTypeNamer::GetTypeName(IDiaSymbol* type, base::string16* type_name) {
 319  m :    DCHECK(type); DCHECK(type_name);
 320    :  
 321  m :    enum SymTagEnum sym_tag_type = SymTagNull;
 322  m :    if (!pe::GetSymTag(type, &sym_tag_type))
 323  m :      return false;
 324    :  
 325  m :    switch (sym_tag_type) {
 326  m :      case SymTagUDT:
 327  m :      case SymTagEnum:
 328  m :      case SymTagTypedef:
 329  m :      case SymTagData:
 330  m :        return pe::GetSymName(type, type_name);
 331  m :      case SymTagBaseType:
 332  m :        return GetSymBaseTypeName(type, type_name);
 333  m :      case SymTagPointerType:
 334  m :        return GetPointerName(type, type_name);
 335  m :      case SymTagArrayType:
 336  m :        return GetArrayName(type, type_name);
 337  m :      case SymTagFunctionType:
 338  m :        return GetFunctionName(type, type_name);
 339  m :      case SymTagVTableShape:
 340  m :      case SymTagVTable:
 341  m :      default:
 342  m :        return false;
 343  m :    }
 344  m :  }
 345    :  
 346  m :  bool DiaTypeNamer::GetPointerName(IDiaSymbol* type, base::string16* type_name) {
 347  m :    DCHECK(type); DCHECK(type_name);
 348  m :    DCHECK(pe::IsSymTag(type, SymTagPointerType));
 349    :  
 350  m :    base::string16 name;
 351    :  
 352    :    // Get the content type's name.
 353  m :    base::win::ScopedComPtr<IDiaSymbol> content_type;
 354  m :    if (!pe::GetSymType(type, &content_type))
 355  m :      return false;
 356  m :    if (!GetTypeName(content_type.get(), &name))
 357  m :      return false;
 358    :  
 359    :    // Append the suffix.
 360  m :    bool is_const = false;
 361  m :    bool is_volatile = false;
 362  m :    if (!pe::GetSymQualifiers(content_type.get(), &is_const, &is_volatile))
 363  m :      return false;
 364  m :    BOOL is_ref;
 365  m :    HRESULT hr = type->get_reference(&is_ref);
 366  m :    if (hr != S_OK)
 367  m :      return false;
 368  m :    AppendPointerNameSuffix(is_const, is_volatile, is_ref == TRUE, &name);
 369    :  
 370  m :    type_name->swap(name);
 371  m :    return true;
 372  m :  }
 373    :  
 374  m :  bool DiaTypeNamer::GetArrayName(IDiaSymbol* type, base::string16* type_name) {
 375  m :    DCHECK(type); DCHECK(type_name);
 376  m :    DCHECK(pe::IsSymTag(type, SymTagArrayType));
 377    :  
 378    :    // Get the element type's name.
 379  m :    base::win::ScopedComPtr<IDiaSymbol> element_type;
 380  m :    if (!pe::GetSymType(type, &element_type))
 381  m :      return false;
 382  m :    base::string16 name;
 383  m :    if (!GetTypeName(element_type.get(), &name))
 384  m :      return false;
 385    :  
 386    :    // Determine the suffix.
 387  m :    bool is_const = false;
 388  m :    bool is_volatile = false;
 389  m :    if (!pe::GetSymQualifiers(element_type.get(), &is_const, &is_volatile))
 390  m :      return false;
 391  m :    size_t element_count = 0;
 392  m :    if (!pe::GetSymCount(type, &element_count))
 393  m :      return false;
 394  m :    AppendArrayNameSuffix(is_const, is_volatile, element_count, &name);
 395    :  
 396    :    // Set the name.
 397  m :    type_name->swap(name);
 398    :  
 399  m :    return true;
 400  m :  }
 401    :  
 402    :  // TODO(manzagop): function type name should include function's CV qualifiers?
 403  m :  bool DiaTypeNamer::GetFunctionName(IDiaSymbol* type,
 404  m :                                     base::string16* type_name) {
 405  m :    DCHECK(type); DCHECK(type_name);
 406  m :    DCHECK(pe::IsSymTag(type, SymTagFunctionType));
 407    :  
 408    :    // Start with the return type.
 409  m :    base::win::ScopedComPtr<IDiaSymbol> return_type;
 410  m :    if (!pe::GetSymType(type, &return_type))
 411  m :      return false;
 412  m :    base::string16 name;
 413  m :    if (!GetTypeName(return_type.get(), &name))
 414  m :      return false;
 415    :  
 416  m :    bool is_const = false;
 417  m :    bool is_volatile = false;
 418  m :    if (!pe::GetSymQualifiers(return_type.get(), &is_const, &is_volatile))
 419  m :      return false;
 420  m :    name.append(GetCVMod(is_const, is_volatile));
 421  m :    name.append(L" (");
 422    :  
 423    :    // Continue with containing class.
 424  m :    base::win::ScopedComPtr<IDiaSymbol> parent_type_sym;
 425  m :    if (!pe::GetSymClassParent(type, &parent_type_sym))
 426  m :      return false;
 427  m :    if (parent_type_sym.get() != nullptr) {
 428  m :      base::string16 class_name;
 429  m :      if (!GetTypeName(parent_type_sym.get(), &class_name))
 430  m :        return false;
 431  m :      name.append(class_name + L"::)(");
 432  m :    }
 433    :  
 434    :    // Get the argument types names.
 435  m :    size_t arg_count = 0;
 436  m :    if (!pe::GetSymCount(type, &arg_count))
 437  m :      return false;
 438    :  
 439  m :    base::win::ScopedComPtr<IDiaEnumSymbols> argument_types;
 440  m :    HRESULT hr = type->findChildren(SymTagFunctionArgType, nullptr, nsNone,
 441  m :                                    argument_types.Receive());
 442  m :    if (!SUCCEEDED(hr))
 443  m :      return false;
 444    :  
 445  m :    std::vector<base::string16> arg_names;
 446  m :    base::win::ScopedComPtr<IDiaSymbol> arg_sym;
 447  m :    ULONG received = 0;
 448  m :    hr = argument_types->Next(1, arg_sym.Receive(), &received);
 449  m :    while (hr == S_OK) {
 450  m :      base::win::ScopedComPtr<IDiaSymbol> arg_type_sym;
 451  m :      if (!pe::GetSymType(arg_sym.get(), &arg_type_sym))
 452  m :        return false;
 453    :  
 454    :      // TODO(manzagop): look into how cci::T_NOTYPE fits in (C-style variadic
 455    :      // function).
 456  m :      base::string16 arg_name;
 457  m :      if (!GetTypeName(arg_type_sym.get(), &arg_name))
 458  m :        return false;
 459    :  
 460  m :      if (!pe::GetSymQualifiers(arg_type_sym.get(), &is_const, &is_volatile))
 461  m :        return false;
 462  m :      arg_name.append(GetCVMod(is_const, is_volatile));
 463    :  
 464  m :      arg_names.push_back(arg_name);
 465    :  
 466  m :      arg_sym.Release();
 467  m :      received = 0;
 468  m :      hr = argument_types->Next(1, arg_sym.Receive(), &received);
 469  m :    }
 470  m :    if (!SUCCEEDED(hr))
 471  m :      return false;
 472    :  
 473  m :    name.append(base::JoinString(arg_names, L", "));
 474  m :    name.append(L")");
 475    :  
 476  m :    type_name->swap(name);
 477  m :    return true;
 478  m :  }
 479    :  
 480  m :  }  // namespace refinery

Coverage information generated Fri Jul 29 11:00:21 2016.