LCOV - code coverage report
Current view: top level - lib/DebugInfo/CodeView - RecordName.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 115 139 82.7 %
Date: 2017-09-14 15:23:50 Functions: 23 30 76.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- RecordName.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/RecordName.h"
      11             : 
      12             : #include "llvm/ADT/SmallString.h"
      13             : #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
      14             : #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
      15             : #include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h"
      16             : #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
      17             : #include "llvm/Support/FormatVariadic.h"
      18             : 
      19             : using namespace llvm;
      20             : using namespace llvm::codeview;
      21             : 
      22             : namespace {
      23        3642 : class TypeNameComputer : public TypeVisitorCallbacks {
      24             :   /// The type collection.  Used to calculate names of nested types.
      25             :   TypeCollection &Types;
      26             :   TypeIndex CurrentTypeIndex = TypeIndex::None();
      27             : 
      28             :   /// Name of the current type. Only valid before visitTypeEnd.
      29             :   SmallString<256> Name;
      30             : 
      31             : public:
      32        5463 :   explicit TypeNameComputer(TypeCollection &Types) : Types(Types) {}
      33             : 
      34        3642 :   StringRef name() const { return Name; }
      35             : 
      36             :   /// Paired begin/end actions for all types. Receives all record data,
      37             :   /// including the fixed-length record prefix.
      38             :   Error visitTypeBegin(CVType &Record) override;
      39             :   Error visitTypeBegin(CVType &Record, TypeIndex Index) override;
      40             :   Error visitTypeEnd(CVType &Record) override;
      41             : 
      42             : #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
      43             :   Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
      44             : #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
      45             : #define MEMBER_RECORD(EnumName, EnumVal, Name)
      46             : #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
      47             : };
      48             : } // namespace
      49             : 
      50           0 : Error TypeNameComputer::visitTypeBegin(CVType &Record) {
      51           0 :   llvm_unreachable("Must call visitTypeBegin with a TypeIndex!");
      52             :   return Error::success();
      53             : }
      54             : 
      55        1821 : Error TypeNameComputer::visitTypeBegin(CVType &Record, TypeIndex Index) {
      56             :   // Reset Name to the empty string. If the visitor sets it, we know it.
      57        3642 :   Name = "";
      58        1821 :   CurrentTypeIndex = Index;
      59        5463 :   return Error::success();
      60             : }
      61             : 
      62        7284 : Error TypeNameComputer::visitTypeEnd(CVType &CVR) { return Error::success(); }
      63             : 
      64         201 : Error TypeNameComputer::visitKnownRecord(CVType &CVR,
      65             :                                          FieldListRecord &FieldList) {
      66         402 :   Name = "<field list>";
      67         603 :   return Error::success();
      68             : }
      69             : 
      70         182 : Error TypeNameComputer::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
      71             :                                          StringIdRecord &String) {
      72         364 :   Name = String.getString();
      73         546 :   return Error::success();
      74             : }
      75             : 
      76         221 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArgListRecord &Args) {
      77         221 :   auto Indices = Args.getIndices();
      78         221 :   uint32_t Size = Indices.size();
      79         442 :   Name = "(";
      80         221 :   for (uint32_t I = 0; I < Size; ++I) {
      81             :     assert(Indices[I] < CurrentTypeIndex);
      82             : 
      83         660 :     Name.append(Types.getTypeName(Indices[I]));
      84         220 :     if (I + 1 != Size)
      85         104 :       Name.append(", ");
      86             :   }
      87         221 :   Name.push_back(')');
      88         663 :   return Error::success();
      89             : }
      90             : 
      91          18 : Error TypeNameComputer::visitKnownRecord(CVType &CVR,
      92             :                                          StringListRecord &Strings) {
      93          18 :   auto Indices = Strings.getIndices();
      94          18 :   uint32_t Size = Indices.size();
      95          36 :   Name = "\"";
      96          18 :   for (uint32_t I = 0; I < Size; ++I) {
      97          54 :     Name.append(Types.getTypeName(Indices[I]));
      98          18 :     if (I + 1 != Size)
      99           0 :       Name.append("\" \"");
     100             :   }
     101          18 :   Name.push_back('\"');
     102          54 :   return Error::success();
     103             : }
     104             : 
     105         280 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, ClassRecord &Class) {
     106         560 :   Name = Class.getName();
     107         840 :   return Error::success();
     108             : }
     109             : 
     110           7 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, UnionRecord &Union) {
     111          14 :   Name = Union.getName();
     112          21 :   return Error::success();
     113             : }
     114             : 
     115          72 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
     116         144 :   Name = Enum.getName();
     117         216 :   return Error::success();
     118             : }
     119             : 
     120          18 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
     121          36 :   Name = AT.getName();
     122          54 :   return Error::success();
     123             : }
     124             : 
     125           4 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) {
     126           8 :   Name = VFT.getName();
     127          12 :   return Error::success();
     128             : }
     129             : 
     130          25 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) {
     131          50 :   Name = Id.getName();
     132          75 :   return Error::success();
     133             : }
     134             : 
     135         152 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) {
     136         304 :   StringRef Ret = Types.getTypeName(Proc.getReturnType());
     137         304 :   StringRef Params = Types.getTypeName(Proc.getArgumentList());
     138         608 :   Name = formatv("{0} {1}", Ret, Params).sstr<256>();
     139         456 :   return Error::success();
     140             : }
     141             : 
     142         175 : Error TypeNameComputer::visitKnownRecord(CVType &CVR,
     143             :                                          MemberFunctionRecord &MF) {
     144         350 :   StringRef Ret = Types.getTypeName(MF.getReturnType());
     145         350 :   StringRef Class = Types.getTypeName(MF.getClassType());
     146         350 :   StringRef Params = Types.getTypeName(MF.getArgumentList());
     147         700 :   Name = formatv("{0} {1}::{2}", Ret, Class, Params).sstr<256>();
     148         525 :   return Error::success();
     149             : }
     150             : 
     151         120 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {
     152         240 :   Name = Func.getName();
     153         360 :   return Error::success();
     154             : }
     155             : 
     156           0 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) {
     157           0 :   Name = TS.getName();
     158           0 :   return Error::success();
     159             : }
     160             : 
     161         209 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {
     162             : 
     163         197 :   if (Ptr.isPointerToMember()) {
     164          12 :     const MemberPointerInfo &MI = Ptr.getMemberInfo();
     165             : 
     166          24 :     StringRef Pointee = Types.getTypeName(Ptr.getReferentType());
     167          24 :     StringRef Class = Types.getTypeName(MI.getContainingType());
     168          60 :     Name = formatv("{0} {1}::*", Pointee, Class);
     169             :   } else {
     170         394 :     if (Ptr.isConst())
     171         116 :       Name.append("const ");
     172         394 :     if (Ptr.isVolatile())
     173           0 :       Name.append("volatile ");
     174         394 :     if (Ptr.isUnaligned())
     175           0 :       Name.append("__unaligned ");
     176             : 
     177         591 :     Name.append(Types.getTypeName(Ptr.getReferentType()));
     178             : 
     179         394 :     if (Ptr.getMode() == PointerMode::LValueReference)
     180          70 :       Name.append("&");
     181         162 :     else if (Ptr.getMode() == PointerMode::RValueReference)
     182          14 :       Name.append("&&");
     183         155 :     else if (Ptr.getMode() == PointerMode::Pointer)
     184         310 :       Name.append("*");
     185             :   }
     186         627 :   return Error::success();
     187             : }
     188             : 
     189          52 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {
     190          52 :   uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
     191             : 
     192         104 :   SmallString<256> TypeName;
     193          52 :   if (Mods & uint16_t(ModifierOptions::Const))
     194          94 :     Name.append("const ");
     195          52 :   if (Mods & uint16_t(ModifierOptions::Volatile))
     196          12 :     Name.append("volatile ");
     197          52 :   if (Mods & uint16_t(ModifierOptions::Unaligned))
     198           0 :     Name.append("__unaligned ");
     199         156 :   Name.append(Types.getTypeName(Mod.getModifiedType()));
     200         208 :   return Error::success();
     201             : }
     202             : 
     203          15 : Error TypeNameComputer::visitKnownRecord(CVType &CVR,
     204             :                                          VFTableShapeRecord &Shape) {
     205          90 :   Name = formatv("<vftable {0} methods>", Shape.getEntryCount());
     206          45 :   return Error::success();
     207             : }
     208             : 
     209           0 : Error TypeNameComputer::visitKnownRecord(
     210             :     CVType &CVR, UdtModSourceLineRecord &ModSourceLine) {
     211           0 :   return Error::success();
     212             : }
     213             : 
     214           0 : Error TypeNameComputer::visitKnownRecord(CVType &CVR,
     215             :                                          UdtSourceLineRecord &SourceLine) {
     216           0 :   return Error::success();
     217             : }
     218             : 
     219           5 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, BitFieldRecord &BF) {
     220          15 :   return Error::success();
     221             : }
     222             : 
     223          49 : Error TypeNameComputer::visitKnownRecord(CVType &CVR,
     224             :                                          MethodOverloadListRecord &Overloads) {
     225         147 :   return Error::success();
     226             : }
     227             : 
     228          16 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, BuildInfoRecord &BI) {
     229          48 :   return Error::success();
     230             : }
     231             : 
     232           0 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, LabelRecord &R) {
     233           0 :   return Error::success();
     234             : }
     235             : 
     236        1821 : std::string llvm::codeview::computeTypeName(TypeCollection &Types,
     237             :                                             TypeIndex Index) {
     238        3642 :   TypeNameComputer Computer(Types);
     239        3642 :   CVType Record = Types.getType(Index);
     240        5463 :   if (auto EC = visitTypeRecord(Record, Index, Computer)) {
     241           0 :     consumeError(std::move(EC));
     242           0 :     return "<unknown UDT>";
     243             :   }
     244        1821 :   return Computer.name();
     245             : }
     246             : 
     247             : static int getSymbolNameOffset(CVSymbol Sym) {
     248         177 :   switch (Sym.kind()) {
     249             :   // See ProcSym
     250             :   case SymbolKind::S_GPROC32:
     251             :   case SymbolKind::S_LPROC32:
     252             :   case SymbolKind::S_GPROC32_ID:
     253             :   case SymbolKind::S_LPROC32_ID:
     254             :   case SymbolKind::S_LPROC32_DPC:
     255             :   case SymbolKind::S_LPROC32_DPC_ID:
     256             :     return 35;
     257             :   // See Thunk32Sym
     258             :   case SymbolKind::S_THUNK32:
     259             :     return 21;
     260             :   // See SectionSym
     261             :   case SymbolKind::S_SECTION:
     262             :     return 16;
     263             :   // See CoffGroupSym
     264             :   case SymbolKind::S_COFFGROUP:
     265             :     return 14;
     266             :   // See PublicSym32, FileStaticSym, RegRelativeSym, DataSym, ThreadLocalDataSym
     267             :   case SymbolKind::S_PUB32:
     268             :   case SymbolKind::S_FILESTATIC:
     269             :   case SymbolKind::S_REGREL32:
     270             :   case SymbolKind::S_GDATA32:
     271             :   case SymbolKind::S_LDATA32:
     272             :   case SymbolKind::S_LMANDATA:
     273             :   case SymbolKind::S_GMANDATA:
     274             :   case SymbolKind::S_LTHREAD32:
     275             :   case SymbolKind::S_GTHREAD32:
     276             :     return 10;
     277             :   // See RegisterSym and LocalSym
     278             :   case SymbolKind::S_REGISTER:
     279             :   case SymbolKind::S_LOCAL:
     280             :     return 6;
     281             :   // See BlockSym
     282             :   case SymbolKind::S_BLOCK32:
     283             :     return 18;
     284             :   // See LabelSym
     285             :   case SymbolKind::S_LABEL32:
     286             :     return 7;
     287             :   // See ObjNameSym, ExportSym, and UDTSym
     288             :   case SymbolKind::S_OBJNAME:
     289             :   case SymbolKind::S_EXPORT:
     290             :   case SymbolKind::S_UDT:
     291             :     return 4;
     292             :   // See BPRelativeSym
     293             :   case SymbolKind::S_BPREL32:
     294             :     return 8;
     295             :   default:
     296             :     return -1;
     297             :   }
     298             : }
     299             : 
     300         177 : StringRef llvm::codeview::getSymbolName(CVSymbol Sym) {
     301         177 :   if (Sym.kind() == SymbolKind::S_CONSTANT) {
     302             :     // S_CONSTANT is preceded by an APSInt, which has a variable length.  So we
     303             :     // have to do a full deserialization.
     304           0 :     BinaryStreamReader Reader(Sym.content(), llvm::support::little);
     305             :     // The container doesn't matter for single records.
     306           0 :     SymbolRecordMapping Mapping(Reader, CodeViewContainer::ObjectFile);
     307           0 :     ConstantSym Const(SymbolKind::S_CONSTANT);
     308           0 :     cantFail(Mapping.visitSymbolBegin(Sym));
     309           0 :     cantFail(Mapping.visitKnownRecord(Sym, Const));
     310           0 :     cantFail(Mapping.visitSymbolEnd(Sym));
     311           0 :     return Const.Name;
     312             :   }
     313             : 
     314         531 :   int Offset = getSymbolNameOffset(Sym);
     315         177 :   if (Offset == -1)
     316          37 :     return StringRef();
     317             : 
     318         420 :   StringRef StringData = toStringRef(Sym.content()).drop_front(Offset);
     319         140 :   return StringData.split('\0').first;
     320             : }

Generated by: LCOV version 1.13