LCOV - code coverage report
Current view: top level - lib/DebugInfo/CodeView - TypeRecordMapping.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 197 208 94.7 %
Date: 2018-10-20 13:21:21 Functions: 40 41 97.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- TypeRecordMapping.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/TypeRecordMapping.h"
      11             : 
      12             : using namespace llvm;
      13             : using namespace llvm::codeview;
      14             : 
      15             : #define error(X)                                                               \
      16             :   if (auto EC = X)                                                             \
      17             :     return EC;
      18             : 
      19             : namespace {
      20             : struct MapOneMethodRecord {
      21             :   explicit MapOneMethodRecord(bool IsFromOverloadList)
      22         881 :       : IsFromOverloadList(IsFromOverloadList) {}
      23             : 
      24           0 :   Error operator()(CodeViewRecordIO &IO, OneMethodRecord &Method) const {
      25           0 :     error(IO.mapInteger(Method.Attrs.Attrs));
      26           0 :     if (IsFromOverloadList) {
      27           0 :       uint16_t Padding = 0;
      28           0 :       error(IO.mapInteger(Padding));
      29             :     }
      30           0 :     error(IO.mapInteger(Method.Type));
      31             :     if (Method.isIntroducingVirtual()) {
      32           0 :       error(IO.mapInteger(Method.VFTableOffset));
      33           0 :     } else if (!IO.isWriting())
      34           0 :       Method.VFTableOffset = -1;
      35             : 
      36           0 :     if (!IsFromOverloadList)
      37           0 :       error(IO.mapStringZ(Method.Name));
      38             : 
      39             :     return Error::success();
      40             :   }
      41             : 
      42             : private:
      43             :   bool IsFromOverloadList;
      44             : };
      45             : }
      46             : 
      47        3514 : static Error mapNameAndUniqueName(CodeViewRecordIO &IO, StringRef &Name,
      48             :                                   StringRef &UniqueName, bool HasUniqueName) {
      49        3514 :   if (IO.isWriting()) {
      50             :     // Try to be smart about what we write here.  We can't write anything too
      51             :     // large, so if we're going to go over the limit, truncate both the name
      52             :     // and unique name by the same amount.
      53         415 :     size_t BytesLeft = IO.maxFieldLength();
      54         415 :     if (HasUniqueName) {
      55         355 :       size_t BytesNeeded = Name.size() + UniqueName.size() + 2;
      56         355 :       StringRef N = Name;
      57         355 :       StringRef U = UniqueName;
      58         355 :       if (BytesNeeded > BytesLeft) {
      59           3 :         size_t BytesToDrop = (BytesNeeded - BytesLeft);
      60           3 :         size_t DropN = std::min(N.size(), BytesToDrop / 2);
      61           6 :         size_t DropU = std::min(U.size(), BytesToDrop - DropN);
      62             : 
      63           3 :         N = N.drop_back(DropN);
      64           3 :         U = U.drop_back(DropU);
      65             :       }
      66             : 
      67         710 :       error(IO.mapStringZ(N));
      68         710 :       error(IO.mapStringZ(U));
      69             :     } else {
      70             :       // Cap the length of the string at however many bytes we have available,
      71             :       // plus one for the required null terminator.
      72          60 :       auto N = StringRef(Name).take_front(BytesLeft - 1);
      73         120 :       error(IO.mapStringZ(N));
      74             :     }
      75             :   } else {
      76        6198 :     error(IO.mapStringZ(Name));
      77        3099 :     if (HasUniqueName)
      78        6002 :       error(IO.mapStringZ(UniqueName));
      79             :   }
      80             : 
      81             :   return Error::success();
      82             : }
      83             : 
      84       16329 : Error TypeRecordMapping::visitTypeBegin(CVType &CVR) {
      85             :   assert(!TypeKind.hasValue() && "Already in a type mapping!");
      86             :   assert(!MemberKind.hasValue() && "Already in a member mapping!");
      87             : 
      88             :   // FieldList and MethodList records can be any length because they can be
      89             :   // split with continuation records.  All other record types cannot be
      90             :   // longer than the maximum record length.
      91             :   Optional<uint32_t> MaxLen;
      92       16329 :   if (CVR.Type != TypeLeafKind::LF_FIELDLIST &&
      93             :       CVR.Type != TypeLeafKind::LF_METHODLIST)
      94             :     MaxLen = MaxRecordLength - sizeof(RecordPrefix);
      95       30139 :   error(IO.beginRecord(MaxLen));
      96       16329 :   TypeKind = CVR.Type;
      97             :   return Error::success();
      98             : }
      99             : 
     100       16327 : Error TypeRecordMapping::visitTypeEnd(CVType &Record) {
     101             :   assert(TypeKind.hasValue() && "Not in a type mapping!");
     102             :   assert(!MemberKind.hasValue() && "Still in a member mapping!");
     103             : 
     104       32654 :   error(IO.endRecord());
     105             : 
     106             :   TypeKind.reset();
     107             :   return Error::success();
     108             : }
     109             : 
     110       15879 : Error TypeRecordMapping::visitMemberBegin(CVMemberRecord &Record) {
     111             :   assert(TypeKind.hasValue() && "Not in a type mapping!");
     112             :   assert(!MemberKind.hasValue() && "Already in a member mapping!");
     113             : 
     114             :   // The largest possible subrecord is one in which there is a record prefix,
     115             :   // followed by the subrecord, followed by a continuation, and that entire
     116             :   // sequence spaws `MaxRecordLength` bytes.  So the record's length is
     117             :   // calculated as follows.
     118             :   constexpr uint32_t ContinuationLength = 8;
     119       31758 :   error(IO.beginRecord(MaxRecordLength - sizeof(RecordPrefix) -
     120             :                        ContinuationLength));
     121             : 
     122       15879 :   MemberKind = Record.Kind;
     123             :   return Error::success();
     124             : }
     125             : 
     126       15879 : Error TypeRecordMapping::visitMemberEnd(CVMemberRecord &Record) {
     127             :   assert(TypeKind.hasValue() && "Not in a type mapping!");
     128             :   assert(MemberKind.hasValue() && "Not in a member mapping!");
     129             : 
     130       15879 :   if (!IO.isWriting()) {
     131       18444 :     if (auto EC = IO.skipPadding())
     132             :       return EC;
     133             :   }
     134             : 
     135             :   MemberKind.reset();
     136       31758 :   error(IO.endRecord());
     137             :   return Error::success();
     138             : }
     139             : 
     140         305 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ModifierRecord &Record) {
     141         610 :   error(IO.mapInteger(Record.ModifiedType));
     142         610 :   error(IO.mapEnum(Record.Modifiers));
     143             : 
     144             :   return Error::success();
     145             : }
     146             : 
     147         755 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     148             :                                           ProcedureRecord &Record) {
     149        1510 :   error(IO.mapInteger(Record.ReturnType));
     150        1510 :   error(IO.mapEnum(Record.CallConv));
     151        1510 :   error(IO.mapEnum(Record.Options));
     152        1510 :   error(IO.mapInteger(Record.ParameterCount));
     153        1510 :   error(IO.mapInteger(Record.ArgumentList));
     154             : 
     155             :   return Error::success();
     156             : }
     157             : 
     158        1744 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     159             :                                           MemberFunctionRecord &Record) {
     160        3488 :   error(IO.mapInteger(Record.ReturnType));
     161        3488 :   error(IO.mapInteger(Record.ClassType));
     162        3488 :   error(IO.mapInteger(Record.ThisType));
     163        3488 :   error(IO.mapEnum(Record.CallConv));
     164        3488 :   error(IO.mapEnum(Record.Options));
     165        3488 :   error(IO.mapInteger(Record.ParameterCount));
     166        3488 :   error(IO.mapInteger(Record.ArgumentList));
     167        3488 :   error(IO.mapInteger(Record.ThisPointerAdjustment));
     168             : 
     169             :   return Error::success();
     170             : }
     171             : 
     172        1400 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ArgListRecord &Record) {
     173        2800 :   error(IO.mapVectorN<uint32_t>(
     174             :       Record.ArgIndices,
     175             :       [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
     176             : 
     177             :   return Error::success();
     178             : }
     179             : 
     180          87 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     181             :                                           StringListRecord &Record) {
     182         174 :   error(IO.mapVectorN<uint32_t>(
     183             :       Record.StringIndices,
     184             :       [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
     185             : 
     186             :   return Error::success();
     187             : }
     188             : 
     189        1676 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, PointerRecord &Record) {
     190        3352 :   error(IO.mapInteger(Record.ReferentType));
     191        3352 :   error(IO.mapInteger(Record.Attrs));
     192             : 
     193             :   if (Record.isPointerToMember()) {
     194          55 :     if (!IO.isWriting())
     195             :       Record.MemberInfo.emplace();
     196             : 
     197             :     MemberPointerInfo &M = *Record.MemberInfo;
     198         110 :     error(IO.mapInteger(M.ContainingType));
     199         110 :     error(IO.mapEnum(M.Representation));
     200             :   }
     201             : 
     202             :   return Error::success();
     203             : }
     204             : 
     205         182 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ArrayRecord &Record) {
     206         364 :   error(IO.mapInteger(Record.ElementType));
     207         364 :   error(IO.mapInteger(Record.IndexType));
     208         364 :   error(IO.mapEncodedInteger(Record.Size));
     209         364 :   error(IO.mapStringZ(Record.Name));
     210             : 
     211             :   return Error::success();
     212             : }
     213             : 
     214        2916 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ClassRecord &Record) {
     215             :   assert((CVR.Type == TypeLeafKind::LF_STRUCTURE) ||
     216             :          (CVR.Type == TypeLeafKind::LF_CLASS) ||
     217             :          (CVR.Type == TypeLeafKind::LF_INTERFACE));
     218             : 
     219        5832 :   error(IO.mapInteger(Record.MemberCount));
     220        5832 :   error(IO.mapEnum(Record.Options));
     221        5832 :   error(IO.mapInteger(Record.FieldList));
     222        5832 :   error(IO.mapInteger(Record.DerivationList));
     223        5832 :   error(IO.mapInteger(Record.VTableShape));
     224        5832 :   error(IO.mapEncodedInteger(Record.Size));
     225        8748 :   error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
     226             :                              Record.hasUniqueName()));
     227             : 
     228             :   return Error::success();
     229             : }
     230             : 
     231          71 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, UnionRecord &Record) {
     232         142 :   error(IO.mapInteger(Record.MemberCount));
     233         142 :   error(IO.mapEnum(Record.Options));
     234         142 :   error(IO.mapInteger(Record.FieldList));
     235         142 :   error(IO.mapEncodedInteger(Record.Size));
     236         213 :   error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
     237             :                              Record.hasUniqueName()));
     238             : 
     239             :   return Error::success();
     240             : }
     241             : 
     242         527 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, EnumRecord &Record) {
     243        1054 :   error(IO.mapInteger(Record.MemberCount));
     244        1054 :   error(IO.mapEnum(Record.Options));
     245        1054 :   error(IO.mapInteger(Record.UnderlyingType));
     246        1054 :   error(IO.mapInteger(Record.FieldList));
     247        1581 :   error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
     248             :                              Record.hasUniqueName()));
     249             : 
     250             :   return Error::success();
     251             : }
     252             : 
     253          32 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, BitFieldRecord &Record) {
     254          64 :   error(IO.mapInteger(Record.Type));
     255          64 :   error(IO.mapInteger(Record.BitSize));
     256          64 :   error(IO.mapInteger(Record.BitOffset));
     257             : 
     258             :   return Error::success();
     259             : }
     260             : 
     261          56 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     262             :                                           VFTableShapeRecord &Record) {
     263             :   uint16_t Size;
     264          56 :   if (IO.isWriting()) {
     265             :     ArrayRef<VFTableSlotKind> Slots = Record.getSlots();
     266          17 :     Size = Slots.size();
     267          34 :     error(IO.mapInteger(Size));
     268             : 
     269          32 :     for (size_t SlotIndex = 0; SlotIndex < Slots.size(); SlotIndex += 2) {
     270          15 :       uint8_t Byte = static_cast<uint8_t>(Slots[SlotIndex]) << 4;
     271          15 :       if ((SlotIndex + 1) < Slots.size()) {
     272           2 :         Byte |= static_cast<uint8_t>(Slots[SlotIndex + 1]);
     273             :       }
     274          15 :       error(IO.mapInteger(Byte));
     275             :     }
     276             :   } else {
     277          78 :     error(IO.mapInteger(Size));
     278          80 :     for (uint16_t I = 0; I < Size; I += 2) {
     279             :       uint8_t Byte;
     280          82 :       error(IO.mapInteger(Byte));
     281          41 :       Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte & 0xF));
     282          41 :       if ((I + 1) < Size)
     283          12 :         Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte >> 4));
     284             :     }
     285             :   }
     286             : 
     287             :   return Error::success();
     288             : }
     289             : 
     290          17 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, VFTableRecord &Record) {
     291          34 :   error(IO.mapInteger(Record.CompleteClass));
     292          34 :   error(IO.mapInteger(Record.OverriddenVFTable));
     293          34 :   error(IO.mapInteger(Record.VFPtrOffset));
     294          17 :   uint32_t NamesLen = 0;
     295          17 :   if (IO.isWriting()) {
     296          16 :     for (auto Name : Record.MethodNames)
     297          10 :       NamesLen += Name.size() + 1;
     298             :   }
     299          34 :   error(IO.mapInteger(NamesLen));
     300          34 :   error(IO.mapVectorTail(
     301             :       Record.MethodNames,
     302             :       [](CodeViewRecordIO &IO, StringRef &S) { return IO.mapStringZ(S); }));
     303             : 
     304             :   return Error::success();
     305             : }
     306             : 
     307        1651 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, StringIdRecord &Record) {
     308        3302 :   error(IO.mapInteger(Record.Id));
     309        3302 :   error(IO.mapStringZ(Record.String));
     310             : 
     311             :   return Error::success();
     312             : }
     313             : 
     314         945 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     315             :                                           UdtSourceLineRecord &Record) {
     316        1890 :   error(IO.mapInteger(Record.UDT));
     317        1890 :   error(IO.mapInteger(Record.SourceFile));
     318        1890 :   error(IO.mapInteger(Record.LineNumber));
     319             : 
     320             :   return Error::success();
     321             : }
     322             : 
     323          52 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     324             :                                           UdtModSourceLineRecord &Record) {
     325         104 :   error(IO.mapInteger(Record.UDT));
     326         104 :   error(IO.mapInteger(Record.SourceFile));
     327         104 :   error(IO.mapInteger(Record.LineNumber));
     328         104 :   error(IO.mapInteger(Record.Module));
     329             : 
     330             :   return Error::success();
     331             : }
     332             : 
     333         761 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, FuncIdRecord &Record) {
     334        1522 :   error(IO.mapInteger(Record.ParentScope));
     335        1522 :   error(IO.mapInteger(Record.FunctionType));
     336        1522 :   error(IO.mapStringZ(Record.Name));
     337             : 
     338             :   return Error::success();
     339             : }
     340             : 
     341         171 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     342             :                                           MemberFuncIdRecord &Record) {
     343         342 :   error(IO.mapInteger(Record.ClassType));
     344         342 :   error(IO.mapInteger(Record.FunctionType));
     345         342 :   error(IO.mapStringZ(Record.Name));
     346             : 
     347             :   return Error::success();
     348             : }
     349             : 
     350         433 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     351             :                                           BuildInfoRecord &Record) {
     352         866 :   error(IO.mapVectorN<uint16_t>(
     353             :       Record.ArgIndices,
     354             :       [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
     355             : 
     356             :   return Error::success();
     357             : }
     358             : 
     359         368 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     360             :                                           MethodOverloadListRecord &Record) {
     361             :   // TODO: Split the list into multiple records if it's longer than 64KB, using
     362             :   // a subrecord of TypeRecordKind::Index to chain the records together.
     363         368 :   error(IO.mapVectorTail(Record.Methods, MapOneMethodRecord(true)));
     364             : 
     365             :   return Error::success();
     366             : }
     367             : 
     368        1004 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     369             :                                           FieldListRecord &Record) {
     370        2008 :   error(IO.mapByteVectorTail(Record.Data));
     371             : 
     372             :   return Error::success();
     373             : }
     374             : 
     375          20 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     376             :                                           TypeServer2Record &Record) {
     377          40 :   error(IO.mapGuid(Record.Guid));
     378          40 :   error(IO.mapInteger(Record.Age));
     379          40 :   error(IO.mapStringZ(Record.Name));
     380             :   return Error::success();
     381             : }
     382             : 
     383           1 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR, LabelRecord &Record) {
     384           2 :   error(IO.mapEnum(Record.Mode));
     385             :   return Error::success();
     386             : }
     387             : 
     388          48 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     389             :                                           BaseClassRecord &Record) {
     390          96 :   error(IO.mapInteger(Record.Attrs.Attrs));
     391          96 :   error(IO.mapInteger(Record.Type));
     392          96 :   error(IO.mapEncodedInteger(Record.Offset));
     393             : 
     394             :   return Error::success();
     395             : }
     396             : 
     397       13034 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     398             :                                           EnumeratorRecord &Record) {
     399       26068 :   error(IO.mapInteger(Record.Attrs.Attrs));
     400             : 
     401             :   // FIXME: Handle full APInt such as __int128.
     402       26068 :   error(IO.mapEncodedInteger(Record.Value));
     403       26068 :   error(IO.mapStringZ(Record.Name));
     404             : 
     405             :   return Error::success();
     406             : }
     407             : 
     408        1465 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     409             :                                           DataMemberRecord &Record) {
     410        2930 :   error(IO.mapInteger(Record.Attrs.Attrs));
     411        2930 :   error(IO.mapInteger(Record.Type));
     412        2930 :   error(IO.mapEncodedInteger(Record.FieldOffset));
     413        2930 :   error(IO.mapStringZ(Record.Name));
     414             : 
     415             :   return Error::success();
     416             : }
     417             : 
     418         281 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     419             :                                           OverloadedMethodRecord &Record) {
     420         562 :   error(IO.mapInteger(Record.NumOverloads));
     421         562 :   error(IO.mapInteger(Record.MethodList));
     422         562 :   error(IO.mapStringZ(Record.Name));
     423             : 
     424             :   return Error::success();
     425             : }
     426             : 
     427         513 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     428             :                                           OneMethodRecord &Record) {
     429             :   const bool IsFromOverloadList = (TypeKind == LF_METHODLIST);
     430             :   MapOneMethodRecord Mapper(IsFromOverloadList);
     431         513 :   return Mapper(IO, Record);
     432             : }
     433             : 
     434         244 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     435             :                                           NestedTypeRecord &Record) {
     436         244 :   uint16_t Padding = 0;
     437         488 :   error(IO.mapInteger(Padding));
     438         488 :   error(IO.mapInteger(Record.Type));
     439         488 :   error(IO.mapStringZ(Record.Name));
     440             : 
     441             :   return Error::success();
     442             : }
     443             : 
     444         127 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     445             :                                           StaticDataMemberRecord &Record) {
     446             : 
     447         254 :   error(IO.mapInteger(Record.Attrs.Attrs));
     448         254 :   error(IO.mapInteger(Record.Type));
     449         254 :   error(IO.mapStringZ(Record.Name));
     450             : 
     451             :   return Error::success();
     452             : }
     453             : 
     454          34 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     455             :                                           VirtualBaseClassRecord &Record) {
     456             : 
     457          68 :   error(IO.mapInteger(Record.Attrs.Attrs));
     458          68 :   error(IO.mapInteger(Record.BaseType));
     459          68 :   error(IO.mapInteger(Record.VBPtrType));
     460          68 :   error(IO.mapEncodedInteger(Record.VBPtrOffset));
     461          68 :   error(IO.mapEncodedInteger(Record.VTableIndex));
     462             : 
     463             :   return Error::success();
     464             : }
     465             : 
     466          37 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     467             :                                           VFPtrRecord &Record) {
     468          37 :   uint16_t Padding = 0;
     469          74 :   error(IO.mapInteger(Padding));
     470          74 :   error(IO.mapInteger(Record.Type));
     471             : 
     472             :   return Error::success();
     473             : }
     474             : 
     475           6 : Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
     476             :                                           ListContinuationRecord &Record) {
     477           6 :   uint16_t Padding = 0;
     478          12 :   error(IO.mapInteger(Padding));
     479          12 :   error(IO.mapInteger(Record.ContinuationIndex));
     480             : 
     481             :   return Error::success();
     482             : }
     483             : 
     484           4 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     485             :                                           PrecompRecord &Precomp) {
     486           8 :   error(IO.mapInteger(Precomp.StartTypeIndex));
     487           8 :   error(IO.mapInteger(Precomp.TypesCount));
     488           8 :   error(IO.mapInteger(Precomp.Signature));
     489           8 :   error(IO.mapStringZ(Precomp.PrecompFilePath));
     490             :   return Error::success();
     491             : }
     492             : 
     493           4 : Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
     494             :                                           EndPrecompRecord &EndPrecomp) {
     495           8 :   error(IO.mapInteger(EndPrecomp.Signature));
     496             :   return Error::success();
     497             : }

Generated by: LCOV version 1.13