xref: /src/contrib/llvm-project/llvm/lib/DebugInfo/CodeView/RecordName.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1044eb2f6SDimitry Andric //===- RecordName.cpp ----------------------------------------- *- C++ --*-===//
208bbd35aSDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
608bbd35aSDimitry Andric //
708bbd35aSDimitry Andric //===----------------------------------------------------------------------===//
808bbd35aSDimitry Andric 
9044eb2f6SDimitry Andric #include "llvm/DebugInfo/CodeView/RecordName.h"
1008bbd35aSDimitry Andric 
1108bbd35aSDimitry Andric #include "llvm/ADT/SmallString.h"
12b60736ecSDimitry Andric #include "llvm/ADT/StringExtras.h"
1308bbd35aSDimitry Andric #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
14145449b1SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeView.h"
15145449b1SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
16044eb2f6SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h"
17145449b1SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeCollection.h"
18145449b1SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeIndex.h"
19145449b1SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeRecord.h"
2008bbd35aSDimitry Andric #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
2108bbd35aSDimitry Andric #include "llvm/Support/FormatVariadic.h"
2208bbd35aSDimitry Andric 
2308bbd35aSDimitry Andric using namespace llvm;
2408bbd35aSDimitry Andric using namespace llvm::codeview;
2508bbd35aSDimitry Andric 
2608bbd35aSDimitry Andric namespace {
2708bbd35aSDimitry Andric class TypeNameComputer : public TypeVisitorCallbacks {
2808bbd35aSDimitry Andric   /// The type collection.  Used to calculate names of nested types.
2908bbd35aSDimitry Andric   TypeCollection &Types;
3008bbd35aSDimitry Andric   TypeIndex CurrentTypeIndex = TypeIndex::None();
3108bbd35aSDimitry Andric 
3208bbd35aSDimitry Andric   /// Name of the current type. Only valid before visitTypeEnd.
3308bbd35aSDimitry Andric   SmallString<256> Name;
3408bbd35aSDimitry Andric 
3508bbd35aSDimitry Andric public:
TypeNameComputer(TypeCollection & Types)3608bbd35aSDimitry Andric   explicit TypeNameComputer(TypeCollection &Types) : Types(Types) {}
3708bbd35aSDimitry Andric 
name() const3808bbd35aSDimitry Andric   StringRef name() const { return Name; }
3908bbd35aSDimitry Andric 
4008bbd35aSDimitry Andric   /// Paired begin/end actions for all types. Receives all record data,
4108bbd35aSDimitry Andric   /// including the fixed-length record prefix.
4208bbd35aSDimitry Andric   Error visitTypeBegin(CVType &Record) override;
4308bbd35aSDimitry Andric   Error visitTypeBegin(CVType &Record, TypeIndex Index) override;
4408bbd35aSDimitry Andric   Error visitTypeEnd(CVType &Record) override;
4508bbd35aSDimitry Andric 
4608bbd35aSDimitry Andric #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
4708bbd35aSDimitry Andric   Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
4808bbd35aSDimitry Andric #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
4908bbd35aSDimitry Andric #define MEMBER_RECORD(EnumName, EnumVal, Name)
5008bbd35aSDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
5108bbd35aSDimitry Andric };
5208bbd35aSDimitry Andric } // namespace
5308bbd35aSDimitry Andric 
visitTypeBegin(CVType & Record)5408bbd35aSDimitry Andric Error TypeNameComputer::visitTypeBegin(CVType &Record) {
5508bbd35aSDimitry Andric   llvm_unreachable("Must call visitTypeBegin with a TypeIndex!");
5608bbd35aSDimitry Andric   return Error::success();
5708bbd35aSDimitry Andric }
5808bbd35aSDimitry Andric 
visitTypeBegin(CVType & Record,TypeIndex Index)5908bbd35aSDimitry Andric Error TypeNameComputer::visitTypeBegin(CVType &Record, TypeIndex Index) {
6008bbd35aSDimitry Andric   // Reset Name to the empty string. If the visitor sets it, we know it.
6108bbd35aSDimitry Andric   Name = "";
6208bbd35aSDimitry Andric   CurrentTypeIndex = Index;
6308bbd35aSDimitry Andric   return Error::success();
6408bbd35aSDimitry Andric }
6508bbd35aSDimitry Andric 
visitTypeEnd(CVType & CVR)6608bbd35aSDimitry Andric Error TypeNameComputer::visitTypeEnd(CVType &CVR) { return Error::success(); }
6708bbd35aSDimitry Andric 
visitKnownRecord(CVType & CVR,FieldListRecord & FieldList)6808bbd35aSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR,
6908bbd35aSDimitry Andric                                          FieldListRecord &FieldList) {
7008bbd35aSDimitry Andric   Name = "<field list>";
7108bbd35aSDimitry Andric   return Error::success();
7208bbd35aSDimitry Andric }
7308bbd35aSDimitry Andric 
visitKnownRecord(CVRecord<TypeLeafKind> & CVR,StringIdRecord & String)7408bbd35aSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
7508bbd35aSDimitry Andric                                          StringIdRecord &String) {
7608bbd35aSDimitry Andric   Name = String.getString();
7708bbd35aSDimitry Andric   return Error::success();
7808bbd35aSDimitry Andric }
7908bbd35aSDimitry Andric 
visitKnownRecord(CVType & CVR,ArgListRecord & Args)8008bbd35aSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArgListRecord &Args) {
8108bbd35aSDimitry Andric   auto Indices = Args.getIndices();
8208bbd35aSDimitry Andric   uint32_t Size = Indices.size();
8308bbd35aSDimitry Andric   Name = "(";
8408bbd35aSDimitry Andric   for (uint32_t I = 0; I < Size; ++I) {
85b60736ecSDimitry Andric     if (Indices[I] < CurrentTypeIndex)
8608bbd35aSDimitry Andric       Name.append(Types.getTypeName(Indices[I]));
87b60736ecSDimitry Andric     else
88b60736ecSDimitry Andric       Name.append("<unknown 0x" + utohexstr(Indices[I].getIndex()) + ">");
8908bbd35aSDimitry Andric     if (I + 1 != Size)
9008bbd35aSDimitry Andric       Name.append(", ");
9108bbd35aSDimitry Andric   }
9208bbd35aSDimitry Andric   Name.push_back(')');
9308bbd35aSDimitry Andric   return Error::success();
9408bbd35aSDimitry Andric }
9508bbd35aSDimitry Andric 
visitKnownRecord(CVType & CVR,StringListRecord & Strings)9608bbd35aSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR,
9708bbd35aSDimitry Andric                                          StringListRecord &Strings) {
9808bbd35aSDimitry Andric   auto Indices = Strings.getIndices();
9908bbd35aSDimitry Andric   uint32_t Size = Indices.size();
10008bbd35aSDimitry Andric   Name = "\"";
10108bbd35aSDimitry Andric   for (uint32_t I = 0; I < Size; ++I) {
10208bbd35aSDimitry Andric     Name.append(Types.getTypeName(Indices[I]));
10308bbd35aSDimitry Andric     if (I + 1 != Size)
10408bbd35aSDimitry Andric       Name.append("\" \"");
10508bbd35aSDimitry Andric   }
10608bbd35aSDimitry Andric   Name.push_back('\"');
10708bbd35aSDimitry Andric   return Error::success();
10808bbd35aSDimitry Andric }
10908bbd35aSDimitry Andric 
visitKnownRecord(CVType & CVR,ClassRecord & Class)11008bbd35aSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, ClassRecord &Class) {
11108bbd35aSDimitry Andric   Name = Class.getName();
11208bbd35aSDimitry Andric   return Error::success();
11308bbd35aSDimitry Andric }
11408bbd35aSDimitry Andric 
visitKnownRecord(CVType & CVR,UnionRecord & Union)11508bbd35aSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, UnionRecord &Union) {
11608bbd35aSDimitry Andric   Name = Union.getName();
11708bbd35aSDimitry Andric   return Error::success();
11808bbd35aSDimitry Andric }
11908bbd35aSDimitry Andric 
visitKnownRecord(CVType & CVR,EnumRecord & Enum)12008bbd35aSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
12108bbd35aSDimitry Andric   Name = Enum.getName();
12208bbd35aSDimitry Andric   return Error::success();
12308bbd35aSDimitry Andric }
12408bbd35aSDimitry Andric 
visitKnownRecord(CVType & CVR,ArrayRecord & AT)12508bbd35aSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
12608bbd35aSDimitry Andric   Name = AT.getName();
12708bbd35aSDimitry Andric   return Error::success();
12808bbd35aSDimitry Andric }
12908bbd35aSDimitry Andric 
visitKnownRecord(CVType & CVR,VFTableRecord & VFT)13008bbd35aSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) {
13108bbd35aSDimitry Andric   Name = VFT.getName();
13208bbd35aSDimitry Andric   return Error::success();
13308bbd35aSDimitry Andric }
13408bbd35aSDimitry Andric 
visitKnownRecord(CVType & CVR,MemberFuncIdRecord & Id)13508bbd35aSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) {
13608bbd35aSDimitry Andric   Name = Id.getName();
13708bbd35aSDimitry Andric   return Error::success();
13808bbd35aSDimitry Andric }
13908bbd35aSDimitry Andric 
visitKnownRecord(CVType & CVR,ProcedureRecord & Proc)14008bbd35aSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) {
14108bbd35aSDimitry Andric   StringRef Ret = Types.getTypeName(Proc.getReturnType());
14208bbd35aSDimitry Andric   StringRef Params = Types.getTypeName(Proc.getArgumentList());
14308bbd35aSDimitry Andric   Name = formatv("{0} {1}", Ret, Params).sstr<256>();
14408bbd35aSDimitry Andric   return Error::success();
14508bbd35aSDimitry Andric }
14608bbd35aSDimitry Andric 
visitKnownRecord(CVType & CVR,MemberFunctionRecord & MF)14708bbd35aSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR,
14808bbd35aSDimitry Andric                                          MemberFunctionRecord &MF) {
14908bbd35aSDimitry Andric   StringRef Ret = Types.getTypeName(MF.getReturnType());
15008bbd35aSDimitry Andric   StringRef Class = Types.getTypeName(MF.getClassType());
15108bbd35aSDimitry Andric   StringRef Params = Types.getTypeName(MF.getArgumentList());
15208bbd35aSDimitry Andric   Name = formatv("{0} {1}::{2}", Ret, Class, Params).sstr<256>();
15308bbd35aSDimitry Andric   return Error::success();
15408bbd35aSDimitry Andric }
15508bbd35aSDimitry Andric 
visitKnownRecord(CVType & CVR,FuncIdRecord & Func)15608bbd35aSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {
15708bbd35aSDimitry Andric   Name = Func.getName();
15808bbd35aSDimitry Andric   return Error::success();
15908bbd35aSDimitry Andric }
16008bbd35aSDimitry Andric 
visitKnownRecord(CVType & CVR,TypeServer2Record & TS)16108bbd35aSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) {
16208bbd35aSDimitry Andric   Name = TS.getName();
16308bbd35aSDimitry Andric   return Error::success();
16408bbd35aSDimitry Andric }
16508bbd35aSDimitry Andric 
visitKnownRecord(CVType & CVR,PointerRecord & Ptr)16608bbd35aSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {
16708bbd35aSDimitry Andric 
16808bbd35aSDimitry Andric   if (Ptr.isPointerToMember()) {
16908bbd35aSDimitry Andric     const MemberPointerInfo &MI = Ptr.getMemberInfo();
17008bbd35aSDimitry Andric 
17108bbd35aSDimitry Andric     StringRef Pointee = Types.getTypeName(Ptr.getReferentType());
17208bbd35aSDimitry Andric     StringRef Class = Types.getTypeName(MI.getContainingType());
17308bbd35aSDimitry Andric     Name = formatv("{0} {1}::*", Pointee, Class);
17408bbd35aSDimitry Andric   } else {
17508bbd35aSDimitry Andric     Name.append(Types.getTypeName(Ptr.getReferentType()));
17608bbd35aSDimitry Andric 
17708bbd35aSDimitry Andric     if (Ptr.getMode() == PointerMode::LValueReference)
17808bbd35aSDimitry Andric       Name.append("&");
17908bbd35aSDimitry Andric     else if (Ptr.getMode() == PointerMode::RValueReference)
18008bbd35aSDimitry Andric       Name.append("&&");
18108bbd35aSDimitry Andric     else if (Ptr.getMode() == PointerMode::Pointer)
18208bbd35aSDimitry Andric       Name.append("*");
183eb11fae6SDimitry Andric 
184eb11fae6SDimitry Andric     // Qualifiers in pointer records apply to the pointer, not the pointee, so
185eb11fae6SDimitry Andric     // they go on the right.
186eb11fae6SDimitry Andric     if (Ptr.isConst())
187eb11fae6SDimitry Andric       Name.append(" const");
188eb11fae6SDimitry Andric     if (Ptr.isVolatile())
189eb11fae6SDimitry Andric       Name.append(" volatile");
190eb11fae6SDimitry Andric     if (Ptr.isUnaligned())
191eb11fae6SDimitry Andric       Name.append(" __unaligned");
192eb11fae6SDimitry Andric     if (Ptr.isRestrict())
193eb11fae6SDimitry Andric       Name.append(" __restrict");
19408bbd35aSDimitry Andric   }
19508bbd35aSDimitry Andric   return Error::success();
19608bbd35aSDimitry Andric }
19708bbd35aSDimitry Andric 
visitKnownRecord(CVType & CVR,ModifierRecord & Mod)19808bbd35aSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {
19908bbd35aSDimitry Andric   uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
20008bbd35aSDimitry Andric 
20108bbd35aSDimitry Andric   if (Mods & uint16_t(ModifierOptions::Const))
20208bbd35aSDimitry Andric     Name.append("const ");
20308bbd35aSDimitry Andric   if (Mods & uint16_t(ModifierOptions::Volatile))
20408bbd35aSDimitry Andric     Name.append("volatile ");
20508bbd35aSDimitry Andric   if (Mods & uint16_t(ModifierOptions::Unaligned))
20608bbd35aSDimitry Andric     Name.append("__unaligned ");
20708bbd35aSDimitry Andric   Name.append(Types.getTypeName(Mod.getModifiedType()));
20808bbd35aSDimitry Andric   return Error::success();
20908bbd35aSDimitry Andric }
21008bbd35aSDimitry Andric 
visitKnownRecord(CVType & CVR,VFTableShapeRecord & Shape)21108bbd35aSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR,
21208bbd35aSDimitry Andric                                          VFTableShapeRecord &Shape) {
21308bbd35aSDimitry Andric   Name = formatv("<vftable {0} methods>", Shape.getEntryCount());
21408bbd35aSDimitry Andric   return Error::success();
21508bbd35aSDimitry Andric }
21608bbd35aSDimitry Andric 
visitKnownRecord(CVType & CVR,UdtModSourceLineRecord & ModSourceLine)21708bbd35aSDimitry Andric Error TypeNameComputer::visitKnownRecord(
21808bbd35aSDimitry Andric     CVType &CVR, UdtModSourceLineRecord &ModSourceLine) {
21908bbd35aSDimitry Andric   return Error::success();
22008bbd35aSDimitry Andric }
22108bbd35aSDimitry Andric 
visitKnownRecord(CVType & CVR,UdtSourceLineRecord & SourceLine)22208bbd35aSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR,
22308bbd35aSDimitry Andric                                          UdtSourceLineRecord &SourceLine) {
22408bbd35aSDimitry Andric   return Error::success();
22508bbd35aSDimitry Andric }
22608bbd35aSDimitry Andric 
visitKnownRecord(CVType & CVR,BitFieldRecord & BF)22708bbd35aSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, BitFieldRecord &BF) {
22808bbd35aSDimitry Andric   return Error::success();
22908bbd35aSDimitry Andric }
23008bbd35aSDimitry Andric 
visitKnownRecord(CVType & CVR,MethodOverloadListRecord & Overloads)23108bbd35aSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR,
23208bbd35aSDimitry Andric                                          MethodOverloadListRecord &Overloads) {
23308bbd35aSDimitry Andric   return Error::success();
23408bbd35aSDimitry Andric }
23508bbd35aSDimitry Andric 
visitKnownRecord(CVType & CVR,BuildInfoRecord & BI)23608bbd35aSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, BuildInfoRecord &BI) {
23708bbd35aSDimitry Andric   return Error::success();
23808bbd35aSDimitry Andric }
23908bbd35aSDimitry Andric 
visitKnownRecord(CVType & CVR,LabelRecord & R)24008bbd35aSDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR, LabelRecord &R) {
24108bbd35aSDimitry Andric   return Error::success();
24208bbd35aSDimitry Andric }
24308bbd35aSDimitry Andric 
visitKnownRecord(CVType & CVR,PrecompRecord & Precomp)244eb11fae6SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR,
245eb11fae6SDimitry Andric                                          PrecompRecord &Precomp) {
246eb11fae6SDimitry Andric   return Error::success();
247eb11fae6SDimitry Andric }
248eb11fae6SDimitry Andric 
visitKnownRecord(CVType & CVR,EndPrecompRecord & EndPrecomp)249eb11fae6SDimitry Andric Error TypeNameComputer::visitKnownRecord(CVType &CVR,
250eb11fae6SDimitry Andric                                          EndPrecompRecord &EndPrecomp) {
251eb11fae6SDimitry Andric   return Error::success();
252eb11fae6SDimitry Andric }
253eb11fae6SDimitry Andric 
computeTypeName(TypeCollection & Types,TypeIndex Index)25408bbd35aSDimitry Andric std::string llvm::codeview::computeTypeName(TypeCollection &Types,
25508bbd35aSDimitry Andric                                             TypeIndex Index) {
25608bbd35aSDimitry Andric   TypeNameComputer Computer(Types);
25708bbd35aSDimitry Andric   CVType Record = Types.getType(Index);
25808bbd35aSDimitry Andric   if (auto EC = visitTypeRecord(Record, Index, Computer)) {
25908bbd35aSDimitry Andric     consumeError(std::move(EC));
26008bbd35aSDimitry Andric     return "<unknown UDT>";
26108bbd35aSDimitry Andric   }
262cfca06d7SDimitry Andric   return std::string(Computer.name());
26308bbd35aSDimitry Andric }
264044eb2f6SDimitry Andric 
getSymbolNameOffset(CVSymbol Sym)265044eb2f6SDimitry Andric static int getSymbolNameOffset(CVSymbol Sym) {
266044eb2f6SDimitry Andric   switch (Sym.kind()) {
267044eb2f6SDimitry Andric   // See ProcSym
268044eb2f6SDimitry Andric   case SymbolKind::S_GPROC32:
269044eb2f6SDimitry Andric   case SymbolKind::S_LPROC32:
270044eb2f6SDimitry Andric   case SymbolKind::S_GPROC32_ID:
271044eb2f6SDimitry Andric   case SymbolKind::S_LPROC32_ID:
272044eb2f6SDimitry Andric   case SymbolKind::S_LPROC32_DPC:
273044eb2f6SDimitry Andric   case SymbolKind::S_LPROC32_DPC_ID:
274044eb2f6SDimitry Andric     return 35;
275044eb2f6SDimitry Andric   // See Thunk32Sym
276044eb2f6SDimitry Andric   case SymbolKind::S_THUNK32:
277044eb2f6SDimitry Andric     return 21;
278044eb2f6SDimitry Andric   // See SectionSym
279044eb2f6SDimitry Andric   case SymbolKind::S_SECTION:
280044eb2f6SDimitry Andric     return 16;
281044eb2f6SDimitry Andric   // See CoffGroupSym
282044eb2f6SDimitry Andric   case SymbolKind::S_COFFGROUP:
283044eb2f6SDimitry Andric     return 14;
284044eb2f6SDimitry Andric   // See PublicSym32, FileStaticSym, RegRelativeSym, DataSym, ThreadLocalDataSym
285044eb2f6SDimitry Andric   case SymbolKind::S_PUB32:
286044eb2f6SDimitry Andric   case SymbolKind::S_FILESTATIC:
287044eb2f6SDimitry Andric   case SymbolKind::S_REGREL32:
288044eb2f6SDimitry Andric   case SymbolKind::S_GDATA32:
289044eb2f6SDimitry Andric   case SymbolKind::S_LDATA32:
290044eb2f6SDimitry Andric   case SymbolKind::S_LMANDATA:
291044eb2f6SDimitry Andric   case SymbolKind::S_GMANDATA:
292044eb2f6SDimitry Andric   case SymbolKind::S_LTHREAD32:
293044eb2f6SDimitry Andric   case SymbolKind::S_GTHREAD32:
294eb11fae6SDimitry Andric   case SymbolKind::S_PROCREF:
295eb11fae6SDimitry Andric   case SymbolKind::S_LPROCREF:
296044eb2f6SDimitry Andric     return 10;
297044eb2f6SDimitry Andric   // See RegisterSym and LocalSym
298044eb2f6SDimitry Andric   case SymbolKind::S_REGISTER:
299044eb2f6SDimitry Andric   case SymbolKind::S_LOCAL:
300044eb2f6SDimitry Andric     return 6;
301044eb2f6SDimitry Andric   // See BlockSym
302044eb2f6SDimitry Andric   case SymbolKind::S_BLOCK32:
303044eb2f6SDimitry Andric     return 18;
304044eb2f6SDimitry Andric   // See LabelSym
305044eb2f6SDimitry Andric   case SymbolKind::S_LABEL32:
306044eb2f6SDimitry Andric     return 7;
307044eb2f6SDimitry Andric   // See ObjNameSym, ExportSym, and UDTSym
308044eb2f6SDimitry Andric   case SymbolKind::S_OBJNAME:
309044eb2f6SDimitry Andric   case SymbolKind::S_EXPORT:
310044eb2f6SDimitry Andric   case SymbolKind::S_UDT:
311044eb2f6SDimitry Andric     return 4;
312044eb2f6SDimitry Andric   // See BPRelativeSym
313044eb2f6SDimitry Andric   case SymbolKind::S_BPREL32:
314044eb2f6SDimitry Andric     return 8;
315b7eb8e35SDimitry Andric   // See UsingNamespaceSym
316b7eb8e35SDimitry Andric   case SymbolKind::S_UNAMESPACE:
317b7eb8e35SDimitry Andric     return 0;
318044eb2f6SDimitry Andric   default:
319044eb2f6SDimitry Andric     return -1;
320044eb2f6SDimitry Andric   }
321044eb2f6SDimitry Andric }
322044eb2f6SDimitry Andric 
getSymbolName(CVSymbol Sym)323044eb2f6SDimitry Andric StringRef llvm::codeview::getSymbolName(CVSymbol Sym) {
324044eb2f6SDimitry Andric   if (Sym.kind() == SymbolKind::S_CONSTANT) {
325044eb2f6SDimitry Andric     // S_CONSTANT is preceded by an APSInt, which has a variable length.  So we
326044eb2f6SDimitry Andric     // have to do a full deserialization.
327b1c73532SDimitry Andric     BinaryStreamReader Reader(Sym.content(), llvm::endianness::little);
328044eb2f6SDimitry Andric     // The container doesn't matter for single records.
329044eb2f6SDimitry Andric     SymbolRecordMapping Mapping(Reader, CodeViewContainer::ObjectFile);
330044eb2f6SDimitry Andric     ConstantSym Const(SymbolKind::S_CONSTANT);
331044eb2f6SDimitry Andric     cantFail(Mapping.visitSymbolBegin(Sym));
332044eb2f6SDimitry Andric     cantFail(Mapping.visitKnownRecord(Sym, Const));
333044eb2f6SDimitry Andric     cantFail(Mapping.visitSymbolEnd(Sym));
334044eb2f6SDimitry Andric     return Const.Name;
335044eb2f6SDimitry Andric   }
336044eb2f6SDimitry Andric 
337044eb2f6SDimitry Andric   int Offset = getSymbolNameOffset(Sym);
338044eb2f6SDimitry Andric   if (Offset == -1)
339044eb2f6SDimitry Andric     return StringRef();
340044eb2f6SDimitry Andric 
341044eb2f6SDimitry Andric   StringRef StringData = toStringRef(Sym.content()).drop_front(Offset);
342044eb2f6SDimitry Andric   return StringData.split('\0').first;
343044eb2f6SDimitry Andric }
344