LCOV - code coverage report
Current view: top level - lib/DebugInfo/CodeView - RecordName.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 87 109 79.8 %
Date: 2018-10-20 13:21:21 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        3559 : 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        3559 :   explicit TypeNameComputer(TypeCollection &Types) : Types(Types) {}
      33             : 
      34             :   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        3559 : Error TypeNameComputer::visitTypeBegin(CVType &Record, TypeIndex Index) {
      56             :   // Reset Name to the empty string. If the visitor sets it, we know it.
      57             :   Name = "";
      58        3559 :   CurrentTypeIndex = Index;
      59        3559 :   return Error::success();
      60             : }
      61             : 
      62        7118 : Error TypeNameComputer::visitTypeEnd(CVType &CVR) { return Error::success(); }
      63             : 
      64         388 : Error TypeNameComputer::visitKnownRecord(CVType &CVR,
      65             :                                          FieldListRecord &FieldList) {
      66             :   Name = "<field list>";
      67         388 :   return Error::success();
      68             : }
      69             : 
      70         497 : Error TypeNameComputer::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
      71             :                                          StringIdRecord &String) {
      72             :   Name = String.getString();
      73         497 :   return Error::success();
      74             : }
      75             : 
      76         319 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArgListRecord &Args) {
      77             :   auto Indices = Args.getIndices();
      78         319 :   uint32_t Size = Indices.size();
      79             :   Name = "(";
      80         707 :   for (uint32_t I = 0; I < Size; ++I) {
      81             :     assert(Indices[I] < CurrentTypeIndex);
      82             : 
      83         776 :     Name.append(Types.getTypeName(Indices[I]));
      84         388 :     if (I + 1 != Size)
      85             :       Name.append(", ");
      86             :   }
      87         319 :   Name.push_back(')');
      88         319 :   return Error::success();
      89             : }
      90             : 
      91          20 : Error TypeNameComputer::visitKnownRecord(CVType &CVR,
      92             :                                          StringListRecord &Strings) {
      93             :   auto Indices = Strings.getIndices();
      94          20 :   uint32_t Size = Indices.size();
      95             :   Name = "\"";
      96          41 :   for (uint32_t I = 0; I < Size; ++I) {
      97          42 :     Name.append(Types.getTypeName(Indices[I]));
      98          21 :     if (I + 1 != Size)
      99             :       Name.append("\" \"");
     100             :   }
     101          20 :   Name.push_back('\"');
     102          20 :   return Error::success();
     103             : }
     104             : 
     105         635 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, ClassRecord &Class) {
     106             :   Name = Class.getName();
     107         635 :   return Error::success();
     108             : }
     109             : 
     110          16 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, UnionRecord &Union) {
     111             :   Name = Union.getName();
     112          16 :   return Error::success();
     113             : }
     114             : 
     115          99 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
     116             :   Name = Enum.getName();
     117          99 :   return Error::success();
     118             : }
     119             : 
     120          27 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
     121             :   Name = AT.getName();
     122          27 :   return Error::success();
     123             : }
     124             : 
     125           4 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) {
     126             :   Name = VFT.getName();
     127           4 :   return Error::success();
     128             : }
     129             : 
     130          36 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) {
     131             :   Name = Id.getName();
     132          36 :   return Error::success();
     133             : }
     134             : 
     135         216 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) {
     136         432 :   StringRef Ret = Types.getTypeName(Proc.getReturnType());
     137         432 :   StringRef Params = Types.getTypeName(Proc.getArgumentList());
     138         432 :   Name = formatv("{0} {1}", Ret, Params).sstr<256>();
     139         216 :   return Error::success();
     140             : }
     141             : 
     142         417 : Error TypeNameComputer::visitKnownRecord(CVType &CVR,
     143             :                                          MemberFunctionRecord &MF) {
     144         834 :   StringRef Ret = Types.getTypeName(MF.getReturnType());
     145         834 :   StringRef Class = Types.getTypeName(MF.getClassType());
     146         834 :   StringRef Params = Types.getTypeName(MF.getArgumentList());
     147         834 :   Name = formatv("{0} {1}::{2}", Ret, Class, Params).sstr<256>();
     148         417 :   return Error::success();
     149             : }
     150             : 
     151         177 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {
     152             :   Name = Func.getName();
     153         177 :   return Error::success();
     154             : }
     155             : 
     156           0 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) {
     157             :   Name = TS.getName();
     158           0 :   return Error::success();
     159             : }
     160             : 
     161         422 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {
     162             : 
     163             :   if (Ptr.isPointerToMember()) {
     164          15 :     const MemberPointerInfo &MI = Ptr.getMemberInfo();
     165             : 
     166          30 :     StringRef Pointee = Types.getTypeName(Ptr.getReferentType());
     167          30 :     StringRef Class = Types.getTypeName(MI.getContainingType());
     168          30 :     Name = formatv("{0} {1}::*", Pointee, Class);
     169             :   } else {
     170         814 :     Name.append(Types.getTypeName(Ptr.getReferentType()));
     171             : 
     172         814 :     if (Ptr.getMode() == PointerMode::LValueReference)
     173             :       Name.append("&");
     174         354 :     else if (Ptr.getMode() == PointerMode::RValueReference)
     175             :       Name.append("&&");
     176         347 :     else if (Ptr.getMode() == PointerMode::Pointer)
     177             :       Name.append("*");
     178             : 
     179             :     // Qualifiers in pointer records apply to the pointer, not the pointee, so
     180             :     // they go on the right.
     181         814 :     if (Ptr.isConst())
     182             :       Name.append(" const");
     183         814 :     if (Ptr.isVolatile())
     184             :       Name.append(" volatile");
     185         814 :     if (Ptr.isUnaligned())
     186             :       Name.append(" __unaligned");
     187         814 :     if (Ptr.isRestrict())
     188             :       Name.append(" __restrict");
     189             :   }
     190         422 :   return Error::success();
     191             : }
     192             : 
     193          82 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {
     194          82 :   uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
     195             : 
     196          82 :   if (Mods & uint16_t(ModifierOptions::Const))
     197             :     Name.append("const ");
     198          82 :   if (Mods & uint16_t(ModifierOptions::Volatile))
     199             :     Name.append("volatile ");
     200          82 :   if (Mods & uint16_t(ModifierOptions::Unaligned))
     201             :     Name.append("__unaligned ");
     202         164 :   Name.append(Types.getTypeName(Mod.getModifiedType()));
     203          82 :   return Error::success();
     204             : }
     205             : 
     206          18 : Error TypeNameComputer::visitKnownRecord(CVType &CVR,
     207             :                                          VFTableShapeRecord &Shape) {
     208          18 :   Name = formatv("<vftable {0} methods>", Shape.getEntryCount());
     209          18 :   return Error::success();
     210             : }
     211             : 
     212           0 : Error TypeNameComputer::visitKnownRecord(
     213             :     CVType &CVR, UdtModSourceLineRecord &ModSourceLine) {
     214           0 :   return Error::success();
     215             : }
     216             : 
     217           0 : Error TypeNameComputer::visitKnownRecord(CVType &CVR,
     218             :                                          UdtSourceLineRecord &SourceLine) {
     219           0 :   return Error::success();
     220             : }
     221             : 
     222           7 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, BitFieldRecord &BF) {
     223           7 :   return Error::success();
     224             : }
     225             : 
     226          87 : Error TypeNameComputer::visitKnownRecord(CVType &CVR,
     227             :                                          MethodOverloadListRecord &Overloads) {
     228          87 :   return Error::success();
     229             : }
     230             : 
     231          92 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, BuildInfoRecord &BI) {
     232          92 :   return Error::success();
     233             : }
     234             : 
     235           0 : Error TypeNameComputer::visitKnownRecord(CVType &CVR, LabelRecord &R) {
     236           0 :   return Error::success();
     237             : }
     238             : 
     239           0 : Error TypeNameComputer::visitKnownRecord(CVType &CVR,
     240             :                                          PrecompRecord &Precomp) {
     241           0 :   return Error::success();
     242             : }
     243             : 
     244           0 : Error TypeNameComputer::visitKnownRecord(CVType &CVR,
     245             :                                          EndPrecompRecord &EndPrecomp) {
     246           0 :   return Error::success();
     247             : }
     248             : 
     249        3559 : std::string llvm::codeview::computeTypeName(TypeCollection &Types,
     250             :                                             TypeIndex Index) {
     251             :   TypeNameComputer Computer(Types);
     252        3559 :   CVType Record = Types.getType(Index);
     253        7118 :   if (auto EC = visitTypeRecord(Record, Index, Computer)) {
     254           0 :     consumeError(std::move(EC));
     255           0 :     return "<unknown UDT>";
     256             :   }
     257             :   return Computer.name();
     258             : }
     259             : 
     260             : static int getSymbolNameOffset(CVSymbol Sym) {
     261             :   switch (Sym.kind()) {
     262             :   // See ProcSym
     263             :   case SymbolKind::S_GPROC32:
     264             :   case SymbolKind::S_LPROC32:
     265             :   case SymbolKind::S_GPROC32_ID:
     266             :   case SymbolKind::S_LPROC32_ID:
     267             :   case SymbolKind::S_LPROC32_DPC:
     268             :   case SymbolKind::S_LPROC32_DPC_ID:
     269             :     return 35;
     270             :   // See Thunk32Sym
     271             :   case SymbolKind::S_THUNK32:
     272             :     return 21;
     273             :   // See SectionSym
     274             :   case SymbolKind::S_SECTION:
     275             :     return 16;
     276             :   // See CoffGroupSym
     277             :   case SymbolKind::S_COFFGROUP:
     278             :     return 14;
     279             :   // See PublicSym32, FileStaticSym, RegRelativeSym, DataSym, ThreadLocalDataSym
     280             :   case SymbolKind::S_PUB32:
     281             :   case SymbolKind::S_FILESTATIC:
     282             :   case SymbolKind::S_REGREL32:
     283             :   case SymbolKind::S_GDATA32:
     284             :   case SymbolKind::S_LDATA32:
     285             :   case SymbolKind::S_LMANDATA:
     286             :   case SymbolKind::S_GMANDATA:
     287             :   case SymbolKind::S_LTHREAD32:
     288             :   case SymbolKind::S_GTHREAD32:
     289             :   case SymbolKind::S_PROCREF:
     290             :   case SymbolKind::S_LPROCREF:
     291             :     return 10;
     292             :   // See RegisterSym and LocalSym
     293             :   case SymbolKind::S_REGISTER:
     294             :   case SymbolKind::S_LOCAL:
     295             :     return 6;
     296             :   // See BlockSym
     297             :   case SymbolKind::S_BLOCK32:
     298             :     return 18;
     299             :   // See LabelSym
     300             :   case SymbolKind::S_LABEL32:
     301             :     return 7;
     302             :   // See ObjNameSym, ExportSym, and UDTSym
     303             :   case SymbolKind::S_OBJNAME:
     304             :   case SymbolKind::S_EXPORT:
     305             :   case SymbolKind::S_UDT:
     306             :     return 4;
     307             :   // See BPRelativeSym
     308             :   case SymbolKind::S_BPREL32:
     309             :     return 8;
     310             :   // See UsingNamespaceSym
     311             :   case SymbolKind::S_UNAMESPACE:
     312             :     return 0;
     313             :   default:
     314             :     return -1;
     315             :   }
     316             : }
     317             : 
     318         394 : StringRef llvm::codeview::getSymbolName(CVSymbol Sym) {
     319         394 :   if (Sym.kind() == SymbolKind::S_CONSTANT) {
     320             :     // S_CONSTANT is preceded by an APSInt, which has a variable length.  So we
     321             :     // have to do a full deserialization.
     322           0 :     BinaryStreamReader Reader(Sym.content(), llvm::support::little);
     323             :     // The container doesn't matter for single records.
     324             :     SymbolRecordMapping Mapping(Reader, CodeViewContainer::ObjectFile);
     325             :     ConstantSym Const(SymbolKind::S_CONSTANT);
     326           0 :     cantFail(Mapping.visitSymbolBegin(Sym));
     327           0 :     cantFail(Mapping.visitKnownRecord(Sym, Const));
     328           0 :     cantFail(Mapping.visitSymbolEnd(Sym));
     329           0 :     return Const.Name;
     330             :   }
     331             : 
     332             :   int Offset = getSymbolNameOffset(Sym);
     333         394 :   if (Offset == -1)
     334           0 :     return StringRef();
     335             : 
     336         788 :   StringRef StringData = toStringRef(Sym.content()).drop_front(Offset);
     337         394 :   return StringData.split('\0').first;
     338             : }

Generated by: LCOV version 1.13