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