10b57cec5SDimitry Andric //===- RecordName.cpp ----------------------------------------- *- C++ --*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/RecordName.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
12*af732203SDimitry Andric #include "llvm/ADT/StringExtras.h"
130b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
140b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
150b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h"
160b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
170b57cec5SDimitry Andric #include "llvm/Support/FormatVariadic.h"
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric using namespace llvm;
200b57cec5SDimitry Andric using namespace llvm::codeview;
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric namespace {
230b57cec5SDimitry Andric class TypeNameComputer : public TypeVisitorCallbacks {
240b57cec5SDimitry Andric   /// The type collection.  Used to calculate names of nested types.
250b57cec5SDimitry Andric   TypeCollection &Types;
260b57cec5SDimitry Andric   TypeIndex CurrentTypeIndex = TypeIndex::None();
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric   /// Name of the current type. Only valid before visitTypeEnd.
290b57cec5SDimitry Andric   SmallString<256> Name;
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric public:
TypeNameComputer(TypeCollection & Types)320b57cec5SDimitry Andric   explicit TypeNameComputer(TypeCollection &Types) : Types(Types) {}
330b57cec5SDimitry Andric 
name() const340b57cec5SDimitry Andric   StringRef name() const { return Name; }
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric   /// Paired begin/end actions for all types. Receives all record data,
370b57cec5SDimitry Andric   /// including the fixed-length record prefix.
380b57cec5SDimitry Andric   Error visitTypeBegin(CVType &Record) override;
390b57cec5SDimitry Andric   Error visitTypeBegin(CVType &Record, TypeIndex Index) override;
400b57cec5SDimitry Andric   Error visitTypeEnd(CVType &Record) override;
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
430b57cec5SDimitry Andric   Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
440b57cec5SDimitry Andric #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
450b57cec5SDimitry Andric #define MEMBER_RECORD(EnumName, EnumVal, Name)
460b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
470b57cec5SDimitry Andric };
480b57cec5SDimitry Andric } // namespace
490b57cec5SDimitry Andric 
visitTypeBegin(CVType & Record)500b57cec5SDimitry Andric Error TypeNameComputer::visitTypeBegin(CVType &Record) {
510b57cec5SDimitry Andric   llvm_unreachable("Must call visitTypeBegin with a TypeIndex!");
520b57cec5SDimitry Andric   return Error::success();
530b57cec5SDimitry Andric }
540b57cec5SDimitry Andric 
visitTypeBegin(CVType & Record,TypeIndex Index)550b57cec5SDimitry Andric Error TypeNameComputer::visitTypeBegin(CVType &Record, TypeIndex Index) {
560b57cec5SDimitry Andric   // Reset Name to the empty string. If the visitor sets it, we know it.
570b57cec5SDimitry Andric   Name = "";
580b57cec5SDimitry Andric   CurrentTypeIndex = Index;
590b57cec5SDimitry Andric   return Error::success();
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric 
visitTypeEnd(CVType & CVR)620b57cec5SDimitry Andric Error TypeNameComputer::visitTypeEnd(CVType &CVR) { return Error::success(); }
630b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,FieldListRecord & FieldList)640b57cec5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR,
650b57cec5SDimitry Andric                                          FieldListRecord &FieldList) {
660b57cec5SDimitry Andric   Name = "<field list>";
670b57cec5SDimitry Andric   return Error::success();
680b57cec5SDimitry Andric }
690b57cec5SDimitry Andric 
visitKnownRecord(CVRecord<TypeLeafKind> & CVR,StringIdRecord & String)700b57cec5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
710b57cec5SDimitry Andric                                          StringIdRecord &String) {
720b57cec5SDimitry Andric   Name = String.getString();
730b57cec5SDimitry Andric   return Error::success();
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,ArgListRecord & Args)760b57cec5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArgListRecord &Args) {
770b57cec5SDimitry Andric   auto Indices = Args.getIndices();
780b57cec5SDimitry Andric   uint32_t Size = Indices.size();
790b57cec5SDimitry Andric   Name = "(";
800b57cec5SDimitry Andric   for (uint32_t I = 0; I < Size; ++I) {
81*af732203SDimitry Andric     if (Indices[I] < CurrentTypeIndex)
820b57cec5SDimitry Andric       Name.append(Types.getTypeName(Indices[I]));
83*af732203SDimitry Andric     else
84*af732203SDimitry Andric       Name.append("<unknown 0x" + utohexstr(Indices[I].getIndex()) + ">");
850b57cec5SDimitry Andric     if (I + 1 != Size)
860b57cec5SDimitry Andric       Name.append(", ");
870b57cec5SDimitry Andric   }
880b57cec5SDimitry Andric   Name.push_back(')');
890b57cec5SDimitry Andric   return Error::success();
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,StringListRecord & Strings)920b57cec5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR,
930b57cec5SDimitry Andric                                          StringListRecord &Strings) {
940b57cec5SDimitry Andric   auto Indices = Strings.getIndices();
950b57cec5SDimitry Andric   uint32_t Size = Indices.size();
960b57cec5SDimitry Andric   Name = "\"";
970b57cec5SDimitry Andric   for (uint32_t I = 0; I < Size; ++I) {
980b57cec5SDimitry Andric     Name.append(Types.getTypeName(Indices[I]));
990b57cec5SDimitry Andric     if (I + 1 != Size)
1000b57cec5SDimitry Andric       Name.append("\" \"");
1010b57cec5SDimitry Andric   }
1020b57cec5SDimitry Andric   Name.push_back('\"');
1030b57cec5SDimitry Andric   return Error::success();
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,ClassRecord & Class)1060b57cec5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, ClassRecord &Class) {
1070b57cec5SDimitry Andric   Name = Class.getName();
1080b57cec5SDimitry Andric   return Error::success();
1090b57cec5SDimitry Andric }
1100b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,UnionRecord & Union)1110b57cec5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, UnionRecord &Union) {
1120b57cec5SDimitry Andric   Name = Union.getName();
1130b57cec5SDimitry Andric   return Error::success();
1140b57cec5SDimitry Andric }
1150b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,EnumRecord & Enum)1160b57cec5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
1170b57cec5SDimitry Andric   Name = Enum.getName();
1180b57cec5SDimitry Andric   return Error::success();
1190b57cec5SDimitry Andric }
1200b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,ArrayRecord & AT)1210b57cec5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
1220b57cec5SDimitry Andric   Name = AT.getName();
1230b57cec5SDimitry Andric   return Error::success();
1240b57cec5SDimitry Andric }
1250b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,VFTableRecord & VFT)1260b57cec5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) {
1270b57cec5SDimitry Andric   Name = VFT.getName();
1280b57cec5SDimitry Andric   return Error::success();
1290b57cec5SDimitry Andric }
1300b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,MemberFuncIdRecord & Id)1310b57cec5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) {
1320b57cec5SDimitry Andric   Name = Id.getName();
1330b57cec5SDimitry Andric   return Error::success();
1340b57cec5SDimitry Andric }
1350b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,ProcedureRecord & Proc)1360b57cec5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) {
1370b57cec5SDimitry Andric   StringRef Ret = Types.getTypeName(Proc.getReturnType());
1380b57cec5SDimitry Andric   StringRef Params = Types.getTypeName(Proc.getArgumentList());
1390b57cec5SDimitry Andric   Name = formatv("{0} {1}", Ret, Params).sstr<256>();
1400b57cec5SDimitry Andric   return Error::success();
1410b57cec5SDimitry Andric }
1420b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,MemberFunctionRecord & MF)1430b57cec5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR,
1440b57cec5SDimitry Andric                                          MemberFunctionRecord &MF) {
1450b57cec5SDimitry Andric   StringRef Ret = Types.getTypeName(MF.getReturnType());
1460b57cec5SDimitry Andric   StringRef Class = Types.getTypeName(MF.getClassType());
1470b57cec5SDimitry Andric   StringRef Params = Types.getTypeName(MF.getArgumentList());
1480b57cec5SDimitry Andric   Name = formatv("{0} {1}::{2}", Ret, Class, Params).sstr<256>();
1490b57cec5SDimitry Andric   return Error::success();
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,FuncIdRecord & Func)1520b57cec5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {
1530b57cec5SDimitry Andric   Name = Func.getName();
1540b57cec5SDimitry Andric   return Error::success();
1550b57cec5SDimitry Andric }
1560b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,TypeServer2Record & TS)1570b57cec5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) {
1580b57cec5SDimitry Andric   Name = TS.getName();
1590b57cec5SDimitry Andric   return Error::success();
1600b57cec5SDimitry Andric }
1610b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,PointerRecord & Ptr)1620b57cec5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   if (Ptr.isPointerToMember()) {
1650b57cec5SDimitry Andric     const MemberPointerInfo &MI = Ptr.getMemberInfo();
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric     StringRef Pointee = Types.getTypeName(Ptr.getReferentType());
1680b57cec5SDimitry Andric     StringRef Class = Types.getTypeName(MI.getContainingType());
1690b57cec5SDimitry Andric     Name = formatv("{0} {1}::*", Pointee, Class);
1700b57cec5SDimitry Andric   } else {
1710b57cec5SDimitry Andric     Name.append(Types.getTypeName(Ptr.getReferentType()));
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric     if (Ptr.getMode() == PointerMode::LValueReference)
1740b57cec5SDimitry Andric       Name.append("&");
1750b57cec5SDimitry Andric     else if (Ptr.getMode() == PointerMode::RValueReference)
1760b57cec5SDimitry Andric       Name.append("&&");
1770b57cec5SDimitry Andric     else if (Ptr.getMode() == PointerMode::Pointer)
1780b57cec5SDimitry Andric       Name.append("*");
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric     // Qualifiers in pointer records apply to the pointer, not the pointee, so
1810b57cec5SDimitry Andric     // they go on the right.
1820b57cec5SDimitry Andric     if (Ptr.isConst())
1830b57cec5SDimitry Andric       Name.append(" const");
1840b57cec5SDimitry Andric     if (Ptr.isVolatile())
1850b57cec5SDimitry Andric       Name.append(" volatile");
1860b57cec5SDimitry Andric     if (Ptr.isUnaligned())
1870b57cec5SDimitry Andric       Name.append(" __unaligned");
1880b57cec5SDimitry Andric     if (Ptr.isRestrict())
1890b57cec5SDimitry Andric       Name.append(" __restrict");
1900b57cec5SDimitry Andric   }
1910b57cec5SDimitry Andric   return Error::success();
1920b57cec5SDimitry Andric }
1930b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,ModifierRecord & Mod)1940b57cec5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {
1950b57cec5SDimitry Andric   uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric   if (Mods & uint16_t(ModifierOptions::Const))
1980b57cec5SDimitry Andric     Name.append("const ");
1990b57cec5SDimitry Andric   if (Mods & uint16_t(ModifierOptions::Volatile))
2000b57cec5SDimitry Andric     Name.append("volatile ");
2010b57cec5SDimitry Andric   if (Mods & uint16_t(ModifierOptions::Unaligned))
2020b57cec5SDimitry Andric     Name.append("__unaligned ");
2030b57cec5SDimitry Andric   Name.append(Types.getTypeName(Mod.getModifiedType()));
2040b57cec5SDimitry Andric   return Error::success();
2050b57cec5SDimitry Andric }
2060b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,VFTableShapeRecord & Shape)2070b57cec5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR,
2080b57cec5SDimitry Andric                                          VFTableShapeRecord &Shape) {
2090b57cec5SDimitry Andric   Name = formatv("<vftable {0} methods>", Shape.getEntryCount());
2100b57cec5SDimitry Andric   return Error::success();
2110b57cec5SDimitry Andric }
2120b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,UdtModSourceLineRecord & ModSourceLine)2130b57cec5SDimitry Andric Error TypeNameComputer::visitKnownRecord(
2140b57cec5SDimitry Andric     CVType &CVR, UdtModSourceLineRecord &ModSourceLine) {
2150b57cec5SDimitry Andric   return Error::success();
2160b57cec5SDimitry Andric }
2170b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,UdtSourceLineRecord & SourceLine)2180b57cec5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR,
2190b57cec5SDimitry Andric                                          UdtSourceLineRecord &SourceLine) {
2200b57cec5SDimitry Andric   return Error::success();
2210b57cec5SDimitry Andric }
2220b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,BitFieldRecord & BF)2230b57cec5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, BitFieldRecord &BF) {
2240b57cec5SDimitry Andric   return Error::success();
2250b57cec5SDimitry Andric }
2260b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,MethodOverloadListRecord & Overloads)2270b57cec5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR,
2280b57cec5SDimitry Andric                                          MethodOverloadListRecord &Overloads) {
2290b57cec5SDimitry Andric   return Error::success();
2300b57cec5SDimitry Andric }
2310b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,BuildInfoRecord & BI)2320b57cec5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, BuildInfoRecord &BI) {
2330b57cec5SDimitry Andric   return Error::success();
2340b57cec5SDimitry Andric }
2350b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,LabelRecord & R)2360b57cec5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, LabelRecord &R) {
2370b57cec5SDimitry Andric   return Error::success();
2380b57cec5SDimitry Andric }
2390b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,PrecompRecord & Precomp)2400b57cec5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR,
2410b57cec5SDimitry Andric                                          PrecompRecord &Precomp) {
2420b57cec5SDimitry Andric   return Error::success();
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,EndPrecompRecord & EndPrecomp)2450b57cec5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR,
2460b57cec5SDimitry Andric                                          EndPrecompRecord &EndPrecomp) {
2470b57cec5SDimitry Andric   return Error::success();
2480b57cec5SDimitry Andric }
2490b57cec5SDimitry Andric 
computeTypeName(TypeCollection & Types,TypeIndex Index)2500b57cec5SDimitry Andric std::string llvm::codeview::computeTypeName(TypeCollection &Types,
2510b57cec5SDimitry Andric                                             TypeIndex Index) {
2520b57cec5SDimitry Andric   TypeNameComputer Computer(Types);
2530b57cec5SDimitry Andric   CVType Record = Types.getType(Index);
2540b57cec5SDimitry Andric   if (auto EC = visitTypeRecord(Record, Index, Computer)) {
2550b57cec5SDimitry Andric     consumeError(std::move(EC));
2560b57cec5SDimitry Andric     return "<unknown UDT>";
2570b57cec5SDimitry Andric   }
2585ffd83dbSDimitry Andric   return std::string(Computer.name());
2590b57cec5SDimitry Andric }
2600b57cec5SDimitry Andric 
getSymbolNameOffset(CVSymbol Sym)2610b57cec5SDimitry Andric static int getSymbolNameOffset(CVSymbol Sym) {
2620b57cec5SDimitry Andric   switch (Sym.kind()) {
2630b57cec5SDimitry Andric   // See ProcSym
2640b57cec5SDimitry Andric   case SymbolKind::S_GPROC32:
2650b57cec5SDimitry Andric   case SymbolKind::S_LPROC32:
2660b57cec5SDimitry Andric   case SymbolKind::S_GPROC32_ID:
2670b57cec5SDimitry Andric   case SymbolKind::S_LPROC32_ID:
2680b57cec5SDimitry Andric   case SymbolKind::S_LPROC32_DPC:
2690b57cec5SDimitry Andric   case SymbolKind::S_LPROC32_DPC_ID:
2700b57cec5SDimitry Andric     return 35;
2710b57cec5SDimitry Andric   // See Thunk32Sym
2720b57cec5SDimitry Andric   case SymbolKind::S_THUNK32:
2730b57cec5SDimitry Andric     return 21;
2740b57cec5SDimitry Andric   // See SectionSym
2750b57cec5SDimitry Andric   case SymbolKind::S_SECTION:
2760b57cec5SDimitry Andric     return 16;
2770b57cec5SDimitry Andric   // See CoffGroupSym
2780b57cec5SDimitry Andric   case SymbolKind::S_COFFGROUP:
2790b57cec5SDimitry Andric     return 14;
2800b57cec5SDimitry Andric   // See PublicSym32, FileStaticSym, RegRelativeSym, DataSym, ThreadLocalDataSym
2810b57cec5SDimitry Andric   case SymbolKind::S_PUB32:
2820b57cec5SDimitry Andric   case SymbolKind::S_FILESTATIC:
2830b57cec5SDimitry Andric   case SymbolKind::S_REGREL32:
2840b57cec5SDimitry Andric   case SymbolKind::S_GDATA32:
2850b57cec5SDimitry Andric   case SymbolKind::S_LDATA32:
2860b57cec5SDimitry Andric   case SymbolKind::S_LMANDATA:
2870b57cec5SDimitry Andric   case SymbolKind::S_GMANDATA:
2880b57cec5SDimitry Andric   case SymbolKind::S_LTHREAD32:
2890b57cec5SDimitry Andric   case SymbolKind::S_GTHREAD32:
2900b57cec5SDimitry Andric   case SymbolKind::S_PROCREF:
2910b57cec5SDimitry Andric   case SymbolKind::S_LPROCREF:
2920b57cec5SDimitry Andric     return 10;
2930b57cec5SDimitry Andric   // See RegisterSym and LocalSym
2940b57cec5SDimitry Andric   case SymbolKind::S_REGISTER:
2950b57cec5SDimitry Andric   case SymbolKind::S_LOCAL:
2960b57cec5SDimitry Andric     return 6;
2970b57cec5SDimitry Andric   // See BlockSym
2980b57cec5SDimitry Andric   case SymbolKind::S_BLOCK32:
2990b57cec5SDimitry Andric     return 18;
3000b57cec5SDimitry Andric   // See LabelSym
3010b57cec5SDimitry Andric   case SymbolKind::S_LABEL32:
3020b57cec5SDimitry Andric     return 7;
3030b57cec5SDimitry Andric   // See ObjNameSym, ExportSym, and UDTSym
3040b57cec5SDimitry Andric   case SymbolKind::S_OBJNAME:
3050b57cec5SDimitry Andric   case SymbolKind::S_EXPORT:
3060b57cec5SDimitry Andric   case SymbolKind::S_UDT:
3070b57cec5SDimitry Andric     return 4;
3080b57cec5SDimitry Andric   // See BPRelativeSym
3090b57cec5SDimitry Andric   case SymbolKind::S_BPREL32:
3100b57cec5SDimitry Andric     return 8;
3110b57cec5SDimitry Andric   // See UsingNamespaceSym
3120b57cec5SDimitry Andric   case SymbolKind::S_UNAMESPACE:
3130b57cec5SDimitry Andric     return 0;
3140b57cec5SDimitry Andric   default:
3150b57cec5SDimitry Andric     return -1;
3160b57cec5SDimitry Andric   }
3170b57cec5SDimitry Andric }
3180b57cec5SDimitry Andric 
getSymbolName(CVSymbol Sym)3190b57cec5SDimitry Andric StringRef llvm::codeview::getSymbolName(CVSymbol Sym) {
3200b57cec5SDimitry Andric   if (Sym.kind() == SymbolKind::S_CONSTANT) {
3210b57cec5SDimitry Andric     // S_CONSTANT is preceded by an APSInt, which has a variable length.  So we
3220b57cec5SDimitry Andric     // have to do a full deserialization.
3230b57cec5SDimitry Andric     BinaryStreamReader Reader(Sym.content(), llvm::support::little);
3240b57cec5SDimitry Andric     // The container doesn't matter for single records.
3250b57cec5SDimitry Andric     SymbolRecordMapping Mapping(Reader, CodeViewContainer::ObjectFile);
3260b57cec5SDimitry Andric     ConstantSym Const(SymbolKind::S_CONSTANT);
3270b57cec5SDimitry Andric     cantFail(Mapping.visitSymbolBegin(Sym));
3280b57cec5SDimitry Andric     cantFail(Mapping.visitKnownRecord(Sym, Const));
3290b57cec5SDimitry Andric     cantFail(Mapping.visitSymbolEnd(Sym));
3300b57cec5SDimitry Andric     return Const.Name;
3310b57cec5SDimitry Andric   }
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric   int Offset = getSymbolNameOffset(Sym);
3340b57cec5SDimitry Andric   if (Offset == -1)
3350b57cec5SDimitry Andric     return StringRef();
3360b57cec5SDimitry Andric 
3370b57cec5SDimitry Andric   StringRef StringData = toStringRef(Sym.content()).drop_front(Offset);
3380b57cec5SDimitry Andric   return StringData.split('\0').first;
3390b57cec5SDimitry Andric }
340