12cab237bSDimitry Andric //===- RecordName.cpp ----------------------------------------- *- C++ --*-===//
22cab237bSDimitry Andric //
32cab237bSDimitry Andric //                     The LLVM Compiler Infrastructure
42cab237bSDimitry Andric //
52cab237bSDimitry Andric // This file is distributed under the University of Illinois Open Source
62cab237bSDimitry Andric // License. See LICENSE.TXT for details.
72cab237bSDimitry Andric //
82cab237bSDimitry Andric //===----------------------------------------------------------------------===//
92cab237bSDimitry Andric 
102cab237bSDimitry Andric #include "llvm/DebugInfo/CodeView/RecordName.h"
112cab237bSDimitry Andric 
122cab237bSDimitry Andric #include "llvm/ADT/SmallString.h"
132cab237bSDimitry Andric #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
142cab237bSDimitry Andric #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
152cab237bSDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h"
162cab237bSDimitry Andric #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
172cab237bSDimitry Andric #include "llvm/Support/FormatVariadic.h"
182cab237bSDimitry Andric 
192cab237bSDimitry Andric using namespace llvm;
202cab237bSDimitry Andric using namespace llvm::codeview;
212cab237bSDimitry Andric 
222cab237bSDimitry Andric namespace {
232cab237bSDimitry Andric class TypeNameComputer : public TypeVisitorCallbacks {
242cab237bSDimitry Andric   /// The type collection.  Used to calculate names of nested types.
252cab237bSDimitry Andric   TypeCollection &Types;
262cab237bSDimitry Andric   TypeIndex CurrentTypeIndex = TypeIndex::None();
272cab237bSDimitry Andric 
282cab237bSDimitry Andric   /// Name of the current type. Only valid before visitTypeEnd.
292cab237bSDimitry Andric   SmallString<256> Name;
302cab237bSDimitry Andric 
312cab237bSDimitry Andric public:
TypeNameComputer(TypeCollection & Types)322cab237bSDimitry Andric   explicit TypeNameComputer(TypeCollection &Types) : Types(Types) {}
332cab237bSDimitry Andric 
name() const342cab237bSDimitry Andric   StringRef name() const { return Name; }
352cab237bSDimitry Andric 
362cab237bSDimitry Andric   /// Paired begin/end actions for all types. Receives all record data,
372cab237bSDimitry Andric   /// including the fixed-length record prefix.
382cab237bSDimitry Andric   Error visitTypeBegin(CVType &Record) override;
392cab237bSDimitry Andric   Error visitTypeBegin(CVType &Record, TypeIndex Index) override;
402cab237bSDimitry Andric   Error visitTypeEnd(CVType &Record) override;
412cab237bSDimitry Andric 
422cab237bSDimitry Andric #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
432cab237bSDimitry Andric   Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
442cab237bSDimitry Andric #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
452cab237bSDimitry Andric #define MEMBER_RECORD(EnumName, EnumVal, Name)
462cab237bSDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
472cab237bSDimitry Andric };
482cab237bSDimitry Andric } // namespace
492cab237bSDimitry Andric 
visitTypeBegin(CVType & Record)502cab237bSDimitry Andric Error TypeNameComputer::visitTypeBegin(CVType &Record) {
512cab237bSDimitry Andric   llvm_unreachable("Must call visitTypeBegin with a TypeIndex!");
522cab237bSDimitry Andric   return Error::success();
532cab237bSDimitry Andric }
542cab237bSDimitry Andric 
visitTypeBegin(CVType & Record,TypeIndex Index)552cab237bSDimitry Andric Error TypeNameComputer::visitTypeBegin(CVType &Record, TypeIndex Index) {
562cab237bSDimitry Andric   // Reset Name to the empty string. If the visitor sets it, we know it.
572cab237bSDimitry Andric   Name = "";
582cab237bSDimitry Andric   CurrentTypeIndex = Index;
592cab237bSDimitry Andric   return Error::success();
602cab237bSDimitry Andric }
612cab237bSDimitry Andric 
visitTypeEnd(CVType & CVR)622cab237bSDimitry Andric Error TypeNameComputer::visitTypeEnd(CVType &CVR) { return Error::success(); }
632cab237bSDimitry Andric 
visitKnownRecord(CVType & CVR,FieldListRecord & FieldList)642cab237bSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR,
652cab237bSDimitry Andric                                          FieldListRecord &FieldList) {
662cab237bSDimitry Andric   Name = "<field list>";
672cab237bSDimitry Andric   return Error::success();
682cab237bSDimitry Andric }
692cab237bSDimitry Andric 
visitKnownRecord(CVRecord<TypeLeafKind> & CVR,StringIdRecord & String)702cab237bSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
712cab237bSDimitry Andric                                          StringIdRecord &String) {
722cab237bSDimitry Andric   Name = String.getString();
732cab237bSDimitry Andric   return Error::success();
742cab237bSDimitry Andric }
752cab237bSDimitry Andric 
visitKnownRecord(CVType & CVR,ArgListRecord & Args)762cab237bSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArgListRecord &Args) {
772cab237bSDimitry Andric   auto Indices = Args.getIndices();
782cab237bSDimitry Andric   uint32_t Size = Indices.size();
792cab237bSDimitry Andric   Name = "(";
802cab237bSDimitry Andric   for (uint32_t I = 0; I < Size; ++I) {
812cab237bSDimitry Andric     assert(Indices[I] < CurrentTypeIndex);
822cab237bSDimitry Andric 
832cab237bSDimitry Andric     Name.append(Types.getTypeName(Indices[I]));
842cab237bSDimitry Andric     if (I + 1 != Size)
852cab237bSDimitry Andric       Name.append(", ");
862cab237bSDimitry Andric   }
872cab237bSDimitry Andric   Name.push_back(')');
882cab237bSDimitry Andric   return Error::success();
892cab237bSDimitry Andric }
902cab237bSDimitry Andric 
visitKnownRecord(CVType & CVR,StringListRecord & Strings)912cab237bSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR,
922cab237bSDimitry Andric                                          StringListRecord &Strings) {
932cab237bSDimitry Andric   auto Indices = Strings.getIndices();
942cab237bSDimitry Andric   uint32_t Size = Indices.size();
952cab237bSDimitry Andric   Name = "\"";
962cab237bSDimitry Andric   for (uint32_t I = 0; I < Size; ++I) {
972cab237bSDimitry Andric     Name.append(Types.getTypeName(Indices[I]));
982cab237bSDimitry Andric     if (I + 1 != Size)
992cab237bSDimitry Andric       Name.append("\" \"");
1002cab237bSDimitry Andric   }
1012cab237bSDimitry Andric   Name.push_back('\"');
1022cab237bSDimitry Andric   return Error::success();
1032cab237bSDimitry Andric }
1042cab237bSDimitry Andric 
visitKnownRecord(CVType & CVR,ClassRecord & Class)1052cab237bSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, ClassRecord &Class) {
1062cab237bSDimitry Andric   Name = Class.getName();
1072cab237bSDimitry Andric   return Error::success();
1082cab237bSDimitry Andric }
1092cab237bSDimitry Andric 
visitKnownRecord(CVType & CVR,UnionRecord & Union)1102cab237bSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, UnionRecord &Union) {
1112cab237bSDimitry Andric   Name = Union.getName();
1122cab237bSDimitry Andric   return Error::success();
1132cab237bSDimitry Andric }
1142cab237bSDimitry Andric 
visitKnownRecord(CVType & CVR,EnumRecord & Enum)1152cab237bSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
1162cab237bSDimitry Andric   Name = Enum.getName();
1172cab237bSDimitry Andric   return Error::success();
1182cab237bSDimitry Andric }
1192cab237bSDimitry Andric 
visitKnownRecord(CVType & CVR,ArrayRecord & AT)1202cab237bSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
1212cab237bSDimitry Andric   Name = AT.getName();
1222cab237bSDimitry Andric   return Error::success();
1232cab237bSDimitry Andric }
1242cab237bSDimitry Andric 
visitKnownRecord(CVType & CVR,VFTableRecord & VFT)1252cab237bSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) {
1262cab237bSDimitry Andric   Name = VFT.getName();
1272cab237bSDimitry Andric   return Error::success();
1282cab237bSDimitry Andric }
1292cab237bSDimitry Andric 
visitKnownRecord(CVType & CVR,MemberFuncIdRecord & Id)1302cab237bSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) {
1312cab237bSDimitry Andric   Name = Id.getName();
1322cab237bSDimitry Andric   return Error::success();
1332cab237bSDimitry Andric }
1342cab237bSDimitry Andric 
visitKnownRecord(CVType & CVR,ProcedureRecord & Proc)1352cab237bSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) {
1362cab237bSDimitry Andric   StringRef Ret = Types.getTypeName(Proc.getReturnType());
1372cab237bSDimitry Andric   StringRef Params = Types.getTypeName(Proc.getArgumentList());
1382cab237bSDimitry Andric   Name = formatv("{0} {1}", Ret, Params).sstr<256>();
1392cab237bSDimitry Andric   return Error::success();
1402cab237bSDimitry Andric }
1412cab237bSDimitry Andric 
visitKnownRecord(CVType & CVR,MemberFunctionRecord & MF)1422cab237bSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR,
1432cab237bSDimitry Andric                                          MemberFunctionRecord &MF) {
1442cab237bSDimitry Andric   StringRef Ret = Types.getTypeName(MF.getReturnType());
1452cab237bSDimitry Andric   StringRef Class = Types.getTypeName(MF.getClassType());
1462cab237bSDimitry Andric   StringRef Params = Types.getTypeName(MF.getArgumentList());
1472cab237bSDimitry Andric   Name = formatv("{0} {1}::{2}", Ret, Class, Params).sstr<256>();
1482cab237bSDimitry Andric   return Error::success();
1492cab237bSDimitry Andric }
1502cab237bSDimitry Andric 
visitKnownRecord(CVType & CVR,FuncIdRecord & Func)1512cab237bSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {
1522cab237bSDimitry Andric   Name = Func.getName();
1532cab237bSDimitry Andric   return Error::success();
1542cab237bSDimitry Andric }
1552cab237bSDimitry Andric 
visitKnownRecord(CVType & CVR,TypeServer2Record & TS)1562cab237bSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) {
1572cab237bSDimitry Andric   Name = TS.getName();
1582cab237bSDimitry Andric   return Error::success();
1592cab237bSDimitry Andric }
1602cab237bSDimitry Andric 
visitKnownRecord(CVType & CVR,PointerRecord & Ptr)1612cab237bSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {
1622cab237bSDimitry Andric 
1632cab237bSDimitry Andric   if (Ptr.isPointerToMember()) {
1642cab237bSDimitry Andric     const MemberPointerInfo &MI = Ptr.getMemberInfo();
1652cab237bSDimitry Andric 
1662cab237bSDimitry Andric     StringRef Pointee = Types.getTypeName(Ptr.getReferentType());
1672cab237bSDimitry Andric     StringRef Class = Types.getTypeName(MI.getContainingType());
1682cab237bSDimitry Andric     Name = formatv("{0} {1}::*", Pointee, Class);
1692cab237bSDimitry Andric   } else {
1702cab237bSDimitry Andric     Name.append(Types.getTypeName(Ptr.getReferentType()));
1712cab237bSDimitry Andric 
1722cab237bSDimitry Andric     if (Ptr.getMode() == PointerMode::LValueReference)
1732cab237bSDimitry Andric       Name.append("&");
1742cab237bSDimitry Andric     else if (Ptr.getMode() == PointerMode::RValueReference)
1752cab237bSDimitry Andric       Name.append("&&");
1762cab237bSDimitry Andric     else if (Ptr.getMode() == PointerMode::Pointer)
1772cab237bSDimitry Andric       Name.append("*");
178*4ba319b5SDimitry Andric 
179*4ba319b5SDimitry Andric     // Qualifiers in pointer records apply to the pointer, not the pointee, so
180*4ba319b5SDimitry Andric     // they go on the right.
181*4ba319b5SDimitry Andric     if (Ptr.isConst())
182*4ba319b5SDimitry Andric       Name.append(" const");
183*4ba319b5SDimitry Andric     if (Ptr.isVolatile())
184*4ba319b5SDimitry Andric       Name.append(" volatile");
185*4ba319b5SDimitry Andric     if (Ptr.isUnaligned())
186*4ba319b5SDimitry Andric       Name.append(" __unaligned");
187*4ba319b5SDimitry Andric     if (Ptr.isRestrict())
188*4ba319b5SDimitry Andric       Name.append(" __restrict");
1892cab237bSDimitry Andric   }
1902cab237bSDimitry Andric   return Error::success();
1912cab237bSDimitry Andric }
1922cab237bSDimitry Andric 
visitKnownRecord(CVType & CVR,ModifierRecord & Mod)1932cab237bSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {
1942cab237bSDimitry Andric   uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
1952cab237bSDimitry Andric 
1962cab237bSDimitry Andric   if (Mods & uint16_t(ModifierOptions::Const))
1972cab237bSDimitry Andric     Name.append("const ");
1982cab237bSDimitry Andric   if (Mods & uint16_t(ModifierOptions::Volatile))
1992cab237bSDimitry Andric     Name.append("volatile ");
2002cab237bSDimitry Andric   if (Mods & uint16_t(ModifierOptions::Unaligned))
2012cab237bSDimitry Andric     Name.append("__unaligned ");
2022cab237bSDimitry Andric   Name.append(Types.getTypeName(Mod.getModifiedType()));
2032cab237bSDimitry Andric   return Error::success();
2042cab237bSDimitry Andric }
2052cab237bSDimitry Andric 
visitKnownRecord(CVType & CVR,VFTableShapeRecord & Shape)2062cab237bSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR,
2072cab237bSDimitry Andric                                          VFTableShapeRecord &Shape) {
2082cab237bSDimitry Andric   Name = formatv("<vftable {0} methods>", Shape.getEntryCount());
2092cab237bSDimitry Andric   return Error::success();
2102cab237bSDimitry Andric }
2112cab237bSDimitry Andric 
visitKnownRecord(CVType & CVR,UdtModSourceLineRecord & ModSourceLine)2122cab237bSDimitry Andric Error TypeNameComputer::visitKnownRecord(
2132cab237bSDimitry Andric     CVType &CVR, UdtModSourceLineRecord &ModSourceLine) {
2142cab237bSDimitry Andric   return Error::success();
2152cab237bSDimitry Andric }
2162cab237bSDimitry Andric 
visitKnownRecord(CVType & CVR,UdtSourceLineRecord & SourceLine)2172cab237bSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR,
2182cab237bSDimitry Andric                                          UdtSourceLineRecord &SourceLine) {
2192cab237bSDimitry Andric   return Error::success();
2202cab237bSDimitry Andric }
2212cab237bSDimitry Andric 
visitKnownRecord(CVType & CVR,BitFieldRecord & BF)2222cab237bSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, BitFieldRecord &BF) {
2232cab237bSDimitry Andric   return Error::success();
2242cab237bSDimitry Andric }
2252cab237bSDimitry Andric 
visitKnownRecord(CVType & CVR,MethodOverloadListRecord & Overloads)2262cab237bSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR,
2272cab237bSDimitry Andric                                          MethodOverloadListRecord &Overloads) {
2282cab237bSDimitry Andric   return Error::success();
2292cab237bSDimitry Andric }
2302cab237bSDimitry Andric 
visitKnownRecord(CVType & CVR,BuildInfoRecord & BI)2312cab237bSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, BuildInfoRecord &BI) {
2322cab237bSDimitry Andric   return Error::success();
2332cab237bSDimitry Andric }
2342cab237bSDimitry Andric 
visitKnownRecord(CVType & CVR,LabelRecord & R)2352cab237bSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, LabelRecord &R) {
2362cab237bSDimitry Andric   return Error::success();
2372cab237bSDimitry Andric }
2382cab237bSDimitry Andric 
visitKnownRecord(CVType & CVR,PrecompRecord & Precomp)239*4ba319b5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR,
240*4ba319b5SDimitry Andric                                          PrecompRecord &Precomp) {
241*4ba319b5SDimitry Andric   return Error::success();
242*4ba319b5SDimitry Andric }
243*4ba319b5SDimitry Andric 
visitKnownRecord(CVType & CVR,EndPrecompRecord & EndPrecomp)244*4ba319b5SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR,
245*4ba319b5SDimitry Andric                                          EndPrecompRecord &EndPrecomp) {
246*4ba319b5SDimitry Andric   return Error::success();
247*4ba319b5SDimitry Andric }
248*4ba319b5SDimitry Andric 
computeTypeName(TypeCollection & Types,TypeIndex Index)2492cab237bSDimitry Andric std::string llvm::codeview::computeTypeName(TypeCollection &Types,
2502cab237bSDimitry Andric                                             TypeIndex Index) {
2512cab237bSDimitry Andric   TypeNameComputer Computer(Types);
2522cab237bSDimitry Andric   CVType Record = Types.getType(Index);
2532cab237bSDimitry Andric   if (auto EC = visitTypeRecord(Record, Index, Computer)) {
2542cab237bSDimitry Andric     consumeError(std::move(EC));
2552cab237bSDimitry Andric     return "<unknown UDT>";
2562cab237bSDimitry Andric   }
2572cab237bSDimitry Andric   return Computer.name();
2582cab237bSDimitry Andric }
2592cab237bSDimitry Andric 
getSymbolNameOffset(CVSymbol Sym)2602cab237bSDimitry Andric static int getSymbolNameOffset(CVSymbol Sym) {
2612cab237bSDimitry Andric   switch (Sym.kind()) {
2622cab237bSDimitry Andric   // See ProcSym
2632cab237bSDimitry Andric   case SymbolKind::S_GPROC32:
2642cab237bSDimitry Andric   case SymbolKind::S_LPROC32:
2652cab237bSDimitry Andric   case SymbolKind::S_GPROC32_ID:
2662cab237bSDimitry Andric   case SymbolKind::S_LPROC32_ID:
2672cab237bSDimitry Andric   case SymbolKind::S_LPROC32_DPC:
2682cab237bSDimitry Andric   case SymbolKind::S_LPROC32_DPC_ID:
2692cab237bSDimitry Andric     return 35;
2702cab237bSDimitry Andric   // See Thunk32Sym
2712cab237bSDimitry Andric   case SymbolKind::S_THUNK32:
2722cab237bSDimitry Andric     return 21;
2732cab237bSDimitry Andric   // See SectionSym
2742cab237bSDimitry Andric   case SymbolKind::S_SECTION:
2752cab237bSDimitry Andric     return 16;
2762cab237bSDimitry Andric   // See CoffGroupSym
2772cab237bSDimitry Andric   case SymbolKind::S_COFFGROUP:
2782cab237bSDimitry Andric     return 14;
2792cab237bSDimitry Andric   // See PublicSym32, FileStaticSym, RegRelativeSym, DataSym, ThreadLocalDataSym
2802cab237bSDimitry Andric   case SymbolKind::S_PUB32:
2812cab237bSDimitry Andric   case SymbolKind::S_FILESTATIC:
2822cab237bSDimitry Andric   case SymbolKind::S_REGREL32:
2832cab237bSDimitry Andric   case SymbolKind::S_GDATA32:
2842cab237bSDimitry Andric   case SymbolKind::S_LDATA32:
2852cab237bSDimitry Andric   case SymbolKind::S_LMANDATA:
2862cab237bSDimitry Andric   case SymbolKind::S_GMANDATA:
2872cab237bSDimitry Andric   case SymbolKind::S_LTHREAD32:
2882cab237bSDimitry Andric   case SymbolKind::S_GTHREAD32:
289*4ba319b5SDimitry Andric   case SymbolKind::S_PROCREF:
290*4ba319b5SDimitry Andric   case SymbolKind::S_LPROCREF:
2912cab237bSDimitry Andric     return 10;
2922cab237bSDimitry Andric   // See RegisterSym and LocalSym
2932cab237bSDimitry Andric   case SymbolKind::S_REGISTER:
2942cab237bSDimitry Andric   case SymbolKind::S_LOCAL:
2952cab237bSDimitry Andric     return 6;
2962cab237bSDimitry Andric   // See BlockSym
2972cab237bSDimitry Andric   case SymbolKind::S_BLOCK32:
2982cab237bSDimitry Andric     return 18;
2992cab237bSDimitry Andric   // See LabelSym
3002cab237bSDimitry Andric   case SymbolKind::S_LABEL32:
3012cab237bSDimitry Andric     return 7;
3022cab237bSDimitry Andric   // See ObjNameSym, ExportSym, and UDTSym
3032cab237bSDimitry Andric   case SymbolKind::S_OBJNAME:
3042cab237bSDimitry Andric   case SymbolKind::S_EXPORT:
3052cab237bSDimitry Andric   case SymbolKind::S_UDT:
3062cab237bSDimitry Andric     return 4;
3072cab237bSDimitry Andric   // See BPRelativeSym
3082cab237bSDimitry Andric   case SymbolKind::S_BPREL32:
3092cab237bSDimitry Andric     return 8;
310*4ba319b5SDimitry Andric   // See UsingNamespaceSym
311*4ba319b5SDimitry Andric   case SymbolKind::S_UNAMESPACE:
312*4ba319b5SDimitry Andric     return 0;
3132cab237bSDimitry Andric   default:
3142cab237bSDimitry Andric     return -1;
3152cab237bSDimitry Andric   }
3162cab237bSDimitry Andric }
3172cab237bSDimitry Andric 
getSymbolName(CVSymbol Sym)3182cab237bSDimitry Andric StringRef llvm::codeview::getSymbolName(CVSymbol Sym) {
3192cab237bSDimitry Andric   if (Sym.kind() == SymbolKind::S_CONSTANT) {
3202cab237bSDimitry Andric     // S_CONSTANT is preceded by an APSInt, which has a variable length.  So we
3212cab237bSDimitry Andric     // have to do a full deserialization.
3222cab237bSDimitry Andric     BinaryStreamReader Reader(Sym.content(), llvm::support::little);
3232cab237bSDimitry Andric     // The container doesn't matter for single records.
3242cab237bSDimitry Andric     SymbolRecordMapping Mapping(Reader, CodeViewContainer::ObjectFile);
3252cab237bSDimitry Andric     ConstantSym Const(SymbolKind::S_CONSTANT);
3262cab237bSDimitry Andric     cantFail(Mapping.visitSymbolBegin(Sym));
3272cab237bSDimitry Andric     cantFail(Mapping.visitKnownRecord(Sym, Const));
3282cab237bSDimitry Andric     cantFail(Mapping.visitSymbolEnd(Sym));
3292cab237bSDimitry Andric     return Const.Name;
3302cab237bSDimitry Andric   }
3312cab237bSDimitry Andric 
3322cab237bSDimitry Andric   int Offset = getSymbolNameOffset(Sym);
3332cab237bSDimitry Andric   if (Offset == -1)
3342cab237bSDimitry Andric     return StringRef();
3352cab237bSDimitry Andric 
3362cab237bSDimitry Andric   StringRef StringData = toStringRef(Sym.content()).drop_front(Offset);
3372cab237bSDimitry Andric   return StringData.split('\0').first;
3382cab237bSDimitry Andric }
339