1//===-- TypeRecord.cpp ------------------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "llvm/DebugInfo/CodeView/TypeRecord.h" 11#include "llvm/DebugInfo/CodeView/TypeIndex.h" 12#include "llvm/DebugInfo/CodeView/RecordSerialization.h" 13 14using namespace llvm; 15using namespace llvm::codeview; 16 17//===----------------------------------------------------------------------===// 18// Type record deserialization 19//===----------------------------------------------------------------------===// 20 21ErrorOr<MemberPointerInfo> 22MemberPointerInfo::deserialize(ArrayRef<uint8_t> &Data) { 23 const Layout *L = nullptr; 24 if (auto EC = consumeObject(Data, L)) 25 return EC; 26 27 TypeIndex T = L->ClassType; 28 uint16_t R = L->Representation; 29 PointerToMemberRepresentation PMR = 30 static_cast<PointerToMemberRepresentation>(R); 31 return MemberPointerInfo(T, PMR); 32} 33 34ErrorOr<ModifierRecord> ModifierRecord::deserialize(TypeRecordKind Kind, 35 ArrayRef<uint8_t> &Data) { 36 const Layout *L = nullptr; 37 if (auto EC = consumeObject(Data, L)) 38 return EC; 39 40 TypeIndex M = L->ModifiedType; 41 uint16_t O = L->Modifiers; 42 ModifierOptions MO = static_cast<ModifierOptions>(O); 43 return ModifierRecord(M, MO); 44} 45 46ErrorOr<ProcedureRecord> ProcedureRecord::deserialize(TypeRecordKind Kind, 47 ArrayRef<uint8_t> &Data) { 48 const Layout *L = nullptr; 49 if (auto EC = consumeObject(Data, L)) 50 return EC; 51 return ProcedureRecord(L->ReturnType, L->CallConv, L->Options, 52 L->NumParameters, L->ArgListType); 53} 54 55ErrorOr<MemberFunctionRecord> 56MemberFunctionRecord::deserialize(TypeRecordKind Kind, 57 ArrayRef<uint8_t> &Data) { 58 const Layout *L = nullptr; 59 CV_DESERIALIZE(Data, L); 60 return MemberFunctionRecord(L->ReturnType, L->ClassType, L->ThisType, 61 L->CallConv, L->Options, L->NumParameters, 62 L->ArgListType, L->ThisAdjustment); 63} 64 65ErrorOr<MemberFuncIdRecord> 66MemberFuncIdRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { 67 const Layout *L = nullptr; 68 StringRef Name; 69 CV_DESERIALIZE(Data, L, Name); 70 return MemberFuncIdRecord(L->ClassType, L->FunctionType, Name); 71} 72 73ErrorOr<ArgListRecord> ArgListRecord::deserialize(TypeRecordKind Kind, 74 ArrayRef<uint8_t> &Data) { 75 if (Kind != TypeRecordKind::StringList && Kind != TypeRecordKind::ArgList) 76 return std::make_error_code(std::errc::illegal_byte_sequence); 77 78 const Layout *L = nullptr; 79 ArrayRef<TypeIndex> Indices; 80 CV_DESERIALIZE(Data, L, CV_ARRAY_FIELD_N(Indices, L->NumArgs)); 81 return ArgListRecord(Kind, Indices); 82} 83 84ErrorOr<PointerRecord> PointerRecord::deserialize(TypeRecordKind Kind, 85 ArrayRef<uint8_t> &Data) { 86 const Layout *L = nullptr; 87 if (auto EC = consumeObject(Data, L)) 88 return EC; 89 90 PointerKind PtrKind = L->getPtrKind(); 91 PointerMode Mode = L->getPtrMode(); 92 uint32_t Opts = L->Attrs; 93 PointerOptions Options = static_cast<PointerOptions>(Opts); 94 uint8_t Size = L->getPtrSize(); 95 96 if (L->isPointerToMember()) { 97 auto E = MemberPointerInfo::deserialize(Data); 98 if (E.getError()) 99 return std::make_error_code(std::errc::illegal_byte_sequence); 100 return PointerRecord(L->PointeeType, PtrKind, Mode, Options, Size, *E); 101 } 102 103 return PointerRecord(L->PointeeType, PtrKind, Mode, Options, Size); 104} 105 106ErrorOr<NestedTypeRecord> 107NestedTypeRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { 108 const Layout *L = nullptr; 109 StringRef Name; 110 CV_DESERIALIZE(Data, L, Name); 111 return NestedTypeRecord(L->Type, Name); 112} 113 114ErrorOr<ArrayRecord> ArrayRecord::deserialize(TypeRecordKind Kind, 115 ArrayRef<uint8_t> &Data) { 116 const Layout *L = nullptr; 117 uint64_t Size; 118 StringRef Name; 119 CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Size), Name); 120 return ArrayRecord(L->ElementType, L->IndexType, Size, Name); 121} 122 123ErrorOr<ClassRecord> ClassRecord::deserialize(TypeRecordKind Kind, 124 ArrayRef<uint8_t> &Data) { 125 uint64_t Size = 0; 126 StringRef Name; 127 StringRef UniqueName; 128 uint16_t Props; 129 const Layout *L = nullptr; 130 131 CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Size), Name, 132 CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName())); 133 134 Props = L->Properties; 135 uint16_t WrtValue = (Props & WinRTKindMask) >> WinRTKindShift; 136 WindowsRTClassKind WRT = static_cast<WindowsRTClassKind>(WrtValue); 137 uint16_t HfaMask = (Props & HfaKindMask) >> HfaKindShift; 138 HfaKind Hfa = static_cast<HfaKind>(HfaMask); 139 140 ClassOptions Options = static_cast<ClassOptions>(Props); 141 return ClassRecord(Kind, L->MemberCount, Options, Hfa, WRT, L->FieldList, 142 L->DerivedFrom, L->VShape, Size, Name, UniqueName); 143} 144 145ErrorOr<UnionRecord> UnionRecord::deserialize(TypeRecordKind Kind, 146 ArrayRef<uint8_t> &Data) { 147 uint64_t Size = 0; 148 StringRef Name; 149 StringRef UniqueName; 150 uint16_t Props; 151 152 const Layout *L = nullptr; 153 CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Size), Name, 154 CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName())); 155 156 Props = L->Properties; 157 158 uint16_t HfaMask = (Props & HfaKindMask) >> HfaKindShift; 159 HfaKind Hfa = static_cast<HfaKind>(HfaMask); 160 ClassOptions Options = static_cast<ClassOptions>(Props); 161 return UnionRecord(L->MemberCount, Options, Hfa, L->FieldList, Size, Name, 162 UniqueName); 163} 164 165ErrorOr<EnumRecord> EnumRecord::deserialize(TypeRecordKind Kind, 166 ArrayRef<uint8_t> &Data) { 167 const Layout *L = nullptr; 168 StringRef Name; 169 StringRef UniqueName; 170 CV_DESERIALIZE(Data, L, Name, 171 CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName())); 172 173 uint16_t P = L->Properties; 174 ClassOptions Options = static_cast<ClassOptions>(P); 175 return EnumRecord(L->NumEnumerators, Options, L->FieldListType, Name, 176 UniqueName, L->UnderlyingType); 177} 178 179ErrorOr<BitFieldRecord> BitFieldRecord::deserialize(TypeRecordKind Kind, 180 ArrayRef<uint8_t> &Data) { 181 const Layout *L = nullptr; 182 CV_DESERIALIZE(Data, L); 183 return BitFieldRecord(L->Type, L->BitSize, L->BitOffset); 184} 185 186ErrorOr<VFTableShapeRecord> 187VFTableShapeRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { 188 const Layout *L = nullptr; 189 if (auto EC = consumeObject(Data, L)) 190 return EC; 191 192 std::vector<VFTableSlotKind> Slots; 193 uint16_t Count = L->VFEntryCount; 194 while (Count > 0) { 195 if (Data.empty()) 196 return std::make_error_code(std::errc::illegal_byte_sequence); 197 198 // Process up to 2 nibbles at a time (if there are at least 2 remaining) 199 uint8_t Value = Data[0] & 0x0F; 200 Slots.push_back(static_cast<VFTableSlotKind>(Value)); 201 if (--Count > 0) { 202 Value = (Data[0] & 0xF0) >> 4; 203 Slots.push_back(static_cast<VFTableSlotKind>(Value)); 204 --Count; 205 } 206 Data = Data.slice(1); 207 } 208 209 return VFTableShapeRecord(Slots); 210} 211 212ErrorOr<TypeServer2Record> 213TypeServer2Record::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { 214 const Layout *L = nullptr; 215 StringRef Name; 216 CV_DESERIALIZE(Data, L, Name); 217 return TypeServer2Record(StringRef(L->Guid, 16), L->Age, Name); 218} 219 220ErrorOr<StringIdRecord> StringIdRecord::deserialize(TypeRecordKind Kind, 221 ArrayRef<uint8_t> &Data) { 222 const Layout *L = nullptr; 223 StringRef Name; 224 CV_DESERIALIZE(Data, L, Name); 225 return StringIdRecord(L->id, Name); 226} 227 228ErrorOr<FuncIdRecord> FuncIdRecord::deserialize(TypeRecordKind Kind, 229 ArrayRef<uint8_t> &Data) { 230 const Layout *L = nullptr; 231 StringRef Name; 232 CV_DESERIALIZE(Data, L, Name); 233 return FuncIdRecord(L->ParentScope, L->FunctionType, Name); 234} 235 236ErrorOr<UdtSourceLineRecord> 237UdtSourceLineRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { 238 const Layout *L = nullptr; 239 CV_DESERIALIZE(Data, L); 240 return UdtSourceLineRecord(L->UDT, L->SourceFile, L->LineNumber); 241} 242 243ErrorOr<BuildInfoRecord> BuildInfoRecord::deserialize(TypeRecordKind Kind, 244 ArrayRef<uint8_t> &Data) { 245 const Layout *L = nullptr; 246 ArrayRef<TypeIndex> Indices; 247 CV_DESERIALIZE(Data, L, CV_ARRAY_FIELD_N(Indices, L->NumArgs)); 248 return BuildInfoRecord(Indices); 249} 250 251ErrorOr<VFTableRecord> VFTableRecord::deserialize(TypeRecordKind Kind, 252 ArrayRef<uint8_t> &Data) { 253 const Layout *L = nullptr; 254 StringRef Name; 255 std::vector<StringRef> Names; 256 CV_DESERIALIZE(Data, L, Name, CV_ARRAY_FIELD_TAIL(Names)); 257 return VFTableRecord(L->CompleteClass, L->OverriddenVFTable, L->VFPtrOffset, 258 Name, Names); 259} 260 261ErrorOr<OneMethodRecord> OneMethodRecord::deserialize(TypeRecordKind Kind, 262 ArrayRef<uint8_t> &Data) { 263 const Layout *L = nullptr; 264 StringRef Name; 265 int32_t VFTableOffset = -1; 266 267 CV_DESERIALIZE(Data, L, CV_CONDITIONAL_FIELD(VFTableOffset, 268 L->Attrs.isIntroducedVirtual()), 269 Name); 270 271 MethodOptions Options = L->Attrs.getFlags(); 272 MethodKind MethKind = L->Attrs.getMethodKind(); 273 MemberAccess Access = L->Attrs.getAccess(); 274 OneMethodRecord Method(L->Type, MethKind, Options, Access, VFTableOffset, 275 Name); 276 // Validate the vftable offset. 277 if (Method.isIntroducingVirtual() && Method.getVFTableOffset() < 0) 278 return std::make_error_code(std::errc::illegal_byte_sequence); 279 return Method; 280} 281 282ErrorOr<MethodOverloadListRecord> 283MethodOverloadListRecord::deserialize(TypeRecordKind Kind, 284 ArrayRef<uint8_t> &Data) { 285 std::vector<OneMethodRecord> Methods; 286 while (!Data.empty()) { 287 const Layout *L = nullptr; 288 int32_t VFTableOffset = -1; 289 CV_DESERIALIZE(Data, L, CV_CONDITIONAL_FIELD( 290 VFTableOffset, L->Attrs.isIntroducedVirtual())); 291 292 MethodOptions Options = L->Attrs.getFlags(); 293 MethodKind MethKind = L->Attrs.getMethodKind(); 294 MemberAccess Access = L->Attrs.getAccess(); 295 296 Methods.emplace_back(L->Type, MethKind, Options, Access, VFTableOffset, 297 StringRef()); 298 299 // Validate the vftable offset. 300 auto &Method = Methods.back(); 301 if (Method.isIntroducingVirtual() && Method.getVFTableOffset() < 0) 302 return std::make_error_code(std::errc::illegal_byte_sequence); 303 } 304 return MethodOverloadListRecord(Methods); 305} 306 307ErrorOr<OverloadedMethodRecord> 308OverloadedMethodRecord::deserialize(TypeRecordKind Kind, 309 ArrayRef<uint8_t> &Data) { 310 const Layout *L = nullptr; 311 StringRef Name; 312 CV_DESERIALIZE(Data, L, Name); 313 return OverloadedMethodRecord(L->MethodCount, L->MethList, Name); 314} 315 316ErrorOr<DataMemberRecord> 317DataMemberRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { 318 const Layout *L = nullptr; 319 uint64_t Offset; 320 StringRef Name; 321 CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Offset), Name); 322 return DataMemberRecord(L->Attrs.getAccess(), L->Type, Offset, Name); 323} 324 325ErrorOr<StaticDataMemberRecord> 326StaticDataMemberRecord::deserialize(TypeRecordKind Kind, 327 ArrayRef<uint8_t> &Data) { 328 const Layout *L = nullptr; 329 StringRef Name; 330 CV_DESERIALIZE(Data, L, Name); 331 return StaticDataMemberRecord(L->Attrs.getAccess(), L->Type, Name); 332} 333 334ErrorOr<EnumeratorRecord> 335EnumeratorRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { 336 const Layout *L = nullptr; 337 APSInt Value; 338 StringRef Name; 339 CV_DESERIALIZE(Data, L, Value, Name); 340 return EnumeratorRecord(L->Attrs.getAccess(), Value, Name); 341} 342 343ErrorOr<VFPtrRecord> VFPtrRecord::deserialize(TypeRecordKind Kind, 344 ArrayRef<uint8_t> &Data) { 345 const Layout *L = nullptr; 346 if (auto EC = consumeObject(Data, L)) 347 return EC; 348 return VFPtrRecord(L->Type); 349} 350 351ErrorOr<BaseClassRecord> BaseClassRecord::deserialize(TypeRecordKind Kind, 352 ArrayRef<uint8_t> &Data) { 353 const Layout *L = nullptr; 354 uint64_t Offset; 355 CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Offset)); 356 return BaseClassRecord(L->Attrs.getAccess(), L->BaseType, Offset); 357} 358 359ErrorOr<VirtualBaseClassRecord> 360VirtualBaseClassRecord::deserialize(TypeRecordKind Kind, 361 ArrayRef<uint8_t> &Data) { 362 const Layout *L = nullptr; 363 uint64_t Offset; 364 uint64_t Index; 365 CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Offset), CV_NUMERIC_FIELD(Index)); 366 return VirtualBaseClassRecord(L->Attrs.getAccess(), L->BaseType, L->VBPtrType, 367 Offset, Index); 368} 369 370ErrorOr<ListContinuationRecord> 371ListContinuationRecord::deserialize(TypeRecordKind Kind, 372 ArrayRef<uint8_t> &Data) { 373 const Layout *L = nullptr; 374 CV_DESERIALIZE(Data, L); 375 return ListContinuationRecord(L->ContinuationIndex); 376} 377 378//===----------------------------------------------------------------------===// 379// Type index remapping 380//===----------------------------------------------------------------------===// 381 382static bool remapIndex(ArrayRef<TypeIndex> IndexMap, TypeIndex &Idx) { 383 // Simple types are unchanged. 384 if (Idx.isSimple()) 385 return true; 386 unsigned MapPos = Idx.getIndex() - TypeIndex::FirstNonSimpleIndex; 387 if (MapPos < IndexMap.size()) { 388 Idx = IndexMap[MapPos]; 389 return true; 390 } 391 392 // This type index is invalid. Remap this to "not translated by cvpack", 393 // and return failure. 394 Idx = TypeIndex(SimpleTypeKind::NotTranslated, SimpleTypeMode::Direct); 395 return false; 396} 397 398bool ModifierRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 399 return remapIndex(IndexMap, ModifiedType); 400} 401 402bool ProcedureRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 403 bool Success = true; 404 Success &= remapIndex(IndexMap, ReturnType); 405 Success &= remapIndex(IndexMap, ArgumentList); 406 return Success; 407} 408 409bool MemberFunctionRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 410 bool Success = true; 411 Success &= remapIndex(IndexMap, ReturnType); 412 Success &= remapIndex(IndexMap, ClassType); 413 Success &= remapIndex(IndexMap, ThisType); 414 Success &= remapIndex(IndexMap, ArgumentList); 415 return Success; 416} 417 418bool MemberFuncIdRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 419 bool Success = true; 420 Success &= remapIndex(IndexMap, ClassType); 421 Success &= remapIndex(IndexMap, FunctionType); 422 return Success; 423} 424 425bool ArgListRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 426 bool Success = true; 427 for (TypeIndex &Str : StringIndices) 428 Success &= remapIndex(IndexMap, Str); 429 return Success; 430} 431 432bool MemberPointerInfo::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 433 return remapIndex(IndexMap, ContainingType); 434} 435 436bool PointerRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 437 bool Success = true; 438 Success &= remapIndex(IndexMap, ReferentType); 439 if (isPointerToMember()) 440 Success &= MemberInfo.remapTypeIndices(IndexMap); 441 return Success; 442} 443 444bool NestedTypeRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 445 return remapIndex(IndexMap, Type); 446} 447 448bool ArrayRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 449 bool Success = true; 450 Success &= remapIndex(IndexMap, ElementType); 451 Success &= remapIndex(IndexMap, IndexType); 452 return Success; 453} 454 455bool TagRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 456 return remapIndex(IndexMap, FieldList); 457} 458 459bool ClassRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 460 bool Success = true; 461 Success &= TagRecord::remapTypeIndices(IndexMap); 462 Success &= remapIndex(IndexMap, DerivationList); 463 Success &= remapIndex(IndexMap, VTableShape); 464 return Success; 465} 466 467bool EnumRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 468 bool Success = true; 469 Success &= TagRecord::remapTypeIndices(IndexMap); 470 Success &= remapIndex(IndexMap, UnderlyingType); 471 return Success; 472} 473 474bool BitFieldRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 475 return remapIndex(IndexMap, Type); 476} 477 478bool VFTableShapeRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 479 return true; 480} 481 482bool TypeServer2Record::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 483 return true; 484} 485 486bool StringIdRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 487 return remapIndex(IndexMap, Id); 488} 489 490bool FuncIdRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 491 bool Success = true; 492 Success &= remapIndex(IndexMap, ParentScope); 493 Success &= remapIndex(IndexMap, FunctionType); 494 return Success; 495} 496 497bool UdtSourceLineRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 498 bool Success = true; 499 Success &= remapIndex(IndexMap, UDT); 500 Success &= remapIndex(IndexMap, SourceFile); 501 return Success; 502} 503 504bool UdtModSourceLineRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 505 bool Success = true; 506 Success &= remapIndex(IndexMap, UDT); 507 Success &= remapIndex(IndexMap, SourceFile); 508 return Success; 509} 510 511bool BuildInfoRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 512 bool Success = true; 513 for (TypeIndex &Arg : ArgIndices) 514 Success &= remapIndex(IndexMap, Arg); 515 return Success; 516} 517 518bool VFTableRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 519 bool Success = true; 520 Success &= remapIndex(IndexMap, CompleteClass); 521 Success &= remapIndex(IndexMap, OverriddenVFTable); 522 return Success; 523} 524 525bool OneMethodRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 526 bool Success = true; 527 Success &= remapIndex(IndexMap, Type); 528 return Success; 529} 530 531bool MethodOverloadListRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 532 bool Success = true; 533 for (OneMethodRecord &Meth : Methods) 534 if ((Success = Meth.remapTypeIndices(IndexMap))) 535 return Success; 536 return Success; 537} 538 539bool OverloadedMethodRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 540 return remapIndex(IndexMap, MethodList); 541} 542 543bool DataMemberRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 544 return remapIndex(IndexMap, Type); 545} 546 547bool StaticDataMemberRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 548 return remapIndex(IndexMap, Type); 549} 550 551bool EnumeratorRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 552 return true; 553} 554 555bool VFPtrRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 556 return remapIndex(IndexMap, Type); 557} 558 559bool BaseClassRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 560 return remapIndex(IndexMap, Type); 561} 562 563bool VirtualBaseClassRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 564 bool Success = true; 565 Success &= remapIndex(IndexMap, BaseType); 566 Success &= remapIndex(IndexMap, VBPtrType); 567 return Success; 568} 569 570bool ListContinuationRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 571 return remapIndex(IndexMap, ContinuationIndex); 572} 573