xref: /openbsd-src/gnu/llvm/llvm/lib/DebugInfo/CodeView/RecordName.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===- RecordName.cpp ----------------------------------------- *- C++ --*-===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick 
909467b48Spatrick #include "llvm/DebugInfo/CodeView/RecordName.h"
1009467b48Spatrick 
1109467b48Spatrick #include "llvm/ADT/SmallString.h"
1273471bf0Spatrick #include "llvm/ADT/StringExtras.h"
1309467b48Spatrick #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
14*d415bd75Srobert #include "llvm/DebugInfo/CodeView/CodeView.h"
15*d415bd75Srobert #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
1609467b48Spatrick #include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h"
17*d415bd75Srobert #include "llvm/DebugInfo/CodeView/TypeCollection.h"
18*d415bd75Srobert #include "llvm/DebugInfo/CodeView/TypeIndex.h"
19*d415bd75Srobert #include "llvm/DebugInfo/CodeView/TypeRecord.h"
2009467b48Spatrick #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
2109467b48Spatrick #include "llvm/Support/FormatVariadic.h"
2209467b48Spatrick 
2309467b48Spatrick using namespace llvm;
2409467b48Spatrick using namespace llvm::codeview;
2509467b48Spatrick 
2609467b48Spatrick namespace {
2709467b48Spatrick class TypeNameComputer : public TypeVisitorCallbacks {
2809467b48Spatrick   /// The type collection.  Used to calculate names of nested types.
2909467b48Spatrick   TypeCollection &Types;
3009467b48Spatrick   TypeIndex CurrentTypeIndex = TypeIndex::None();
3109467b48Spatrick 
3209467b48Spatrick   /// Name of the current type. Only valid before visitTypeEnd.
3309467b48Spatrick   SmallString<256> Name;
3409467b48Spatrick 
3509467b48Spatrick public:
TypeNameComputer(TypeCollection & Types)3609467b48Spatrick   explicit TypeNameComputer(TypeCollection &Types) : Types(Types) {}
3709467b48Spatrick 
name() const3809467b48Spatrick   StringRef name() const { return Name; }
3909467b48Spatrick 
4009467b48Spatrick   /// Paired begin/end actions for all types. Receives all record data,
4109467b48Spatrick   /// including the fixed-length record prefix.
4209467b48Spatrick   Error visitTypeBegin(CVType &Record) override;
4309467b48Spatrick   Error visitTypeBegin(CVType &Record, TypeIndex Index) override;
4409467b48Spatrick   Error visitTypeEnd(CVType &Record) override;
4509467b48Spatrick 
4609467b48Spatrick #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
4709467b48Spatrick   Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
4809467b48Spatrick #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
4909467b48Spatrick #define MEMBER_RECORD(EnumName, EnumVal, Name)
5009467b48Spatrick #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
5109467b48Spatrick };
5209467b48Spatrick } // namespace
5309467b48Spatrick 
visitTypeBegin(CVType & Record)5409467b48Spatrick Error TypeNameComputer::visitTypeBegin(CVType &Record) {
5509467b48Spatrick   llvm_unreachable("Must call visitTypeBegin with a TypeIndex!");
5609467b48Spatrick   return Error::success();
5709467b48Spatrick }
5809467b48Spatrick 
visitTypeBegin(CVType & Record,TypeIndex Index)5909467b48Spatrick Error TypeNameComputer::visitTypeBegin(CVType &Record, TypeIndex Index) {
6009467b48Spatrick   // Reset Name to the empty string. If the visitor sets it, we know it.
6109467b48Spatrick   Name = "";
6209467b48Spatrick   CurrentTypeIndex = Index;
6309467b48Spatrick   return Error::success();
6409467b48Spatrick }
6509467b48Spatrick 
visitTypeEnd(CVType & CVR)6609467b48Spatrick Error TypeNameComputer::visitTypeEnd(CVType &CVR) { return Error::success(); }
6709467b48Spatrick 
visitKnownRecord(CVType & CVR,FieldListRecord & FieldList)6809467b48Spatrick Error TypeNameComputer::visitKnownRecord(CVType &CVR,
6909467b48Spatrick                                          FieldListRecord &FieldList) {
7009467b48Spatrick   Name = "<field list>";
7109467b48Spatrick   return Error::success();
7209467b48Spatrick }
7309467b48Spatrick 
visitKnownRecord(CVRecord<TypeLeafKind> & CVR,StringIdRecord & String)7409467b48Spatrick Error TypeNameComputer::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
7509467b48Spatrick                                          StringIdRecord &String) {
7609467b48Spatrick   Name = String.getString();
7709467b48Spatrick   return Error::success();
7809467b48Spatrick }
7909467b48Spatrick 
visitKnownRecord(CVType & CVR,ArgListRecord & Args)8009467b48Spatrick Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArgListRecord &Args) {
8109467b48Spatrick   auto Indices = Args.getIndices();
8209467b48Spatrick   uint32_t Size = Indices.size();
8309467b48Spatrick   Name = "(";
8409467b48Spatrick   for (uint32_t I = 0; I < Size; ++I) {
8573471bf0Spatrick     if (Indices[I] < CurrentTypeIndex)
8609467b48Spatrick       Name.append(Types.getTypeName(Indices[I]));
8773471bf0Spatrick     else
8873471bf0Spatrick       Name.append("<unknown 0x" + utohexstr(Indices[I].getIndex()) + ">");
8909467b48Spatrick     if (I + 1 != Size)
9009467b48Spatrick       Name.append(", ");
9109467b48Spatrick   }
9209467b48Spatrick   Name.push_back(')');
9309467b48Spatrick   return Error::success();
9409467b48Spatrick }
9509467b48Spatrick 
visitKnownRecord(CVType & CVR,StringListRecord & Strings)9609467b48Spatrick Error TypeNameComputer::visitKnownRecord(CVType &CVR,
9709467b48Spatrick                                          StringListRecord &Strings) {
9809467b48Spatrick   auto Indices = Strings.getIndices();
9909467b48Spatrick   uint32_t Size = Indices.size();
10009467b48Spatrick   Name = "\"";
10109467b48Spatrick   for (uint32_t I = 0; I < Size; ++I) {
10209467b48Spatrick     Name.append(Types.getTypeName(Indices[I]));
10309467b48Spatrick     if (I + 1 != Size)
10409467b48Spatrick       Name.append("\" \"");
10509467b48Spatrick   }
10609467b48Spatrick   Name.push_back('\"');
10709467b48Spatrick   return Error::success();
10809467b48Spatrick }
10909467b48Spatrick 
visitKnownRecord(CVType & CVR,ClassRecord & Class)11009467b48Spatrick Error TypeNameComputer::visitKnownRecord(CVType &CVR, ClassRecord &Class) {
11109467b48Spatrick   Name = Class.getName();
11209467b48Spatrick   return Error::success();
11309467b48Spatrick }
11409467b48Spatrick 
visitKnownRecord(CVType & CVR,UnionRecord & Union)11509467b48Spatrick Error TypeNameComputer::visitKnownRecord(CVType &CVR, UnionRecord &Union) {
11609467b48Spatrick   Name = Union.getName();
11709467b48Spatrick   return Error::success();
11809467b48Spatrick }
11909467b48Spatrick 
visitKnownRecord(CVType & CVR,EnumRecord & Enum)12009467b48Spatrick Error TypeNameComputer::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
12109467b48Spatrick   Name = Enum.getName();
12209467b48Spatrick   return Error::success();
12309467b48Spatrick }
12409467b48Spatrick 
visitKnownRecord(CVType & CVR,ArrayRecord & AT)12509467b48Spatrick Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
12609467b48Spatrick   Name = AT.getName();
12709467b48Spatrick   return Error::success();
12809467b48Spatrick }
12909467b48Spatrick 
visitKnownRecord(CVType & CVR,VFTableRecord & VFT)13009467b48Spatrick Error TypeNameComputer::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) {
13109467b48Spatrick   Name = VFT.getName();
13209467b48Spatrick   return Error::success();
13309467b48Spatrick }
13409467b48Spatrick 
visitKnownRecord(CVType & CVR,MemberFuncIdRecord & Id)13509467b48Spatrick Error TypeNameComputer::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) {
13609467b48Spatrick   Name = Id.getName();
13709467b48Spatrick   return Error::success();
13809467b48Spatrick }
13909467b48Spatrick 
visitKnownRecord(CVType & CVR,ProcedureRecord & Proc)14009467b48Spatrick Error TypeNameComputer::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) {
14109467b48Spatrick   StringRef Ret = Types.getTypeName(Proc.getReturnType());
14209467b48Spatrick   StringRef Params = Types.getTypeName(Proc.getArgumentList());
14309467b48Spatrick   Name = formatv("{0} {1}", Ret, Params).sstr<256>();
14409467b48Spatrick   return Error::success();
14509467b48Spatrick }
14609467b48Spatrick 
visitKnownRecord(CVType & CVR,MemberFunctionRecord & MF)14709467b48Spatrick Error TypeNameComputer::visitKnownRecord(CVType &CVR,
14809467b48Spatrick                                          MemberFunctionRecord &MF) {
14909467b48Spatrick   StringRef Ret = Types.getTypeName(MF.getReturnType());
15009467b48Spatrick   StringRef Class = Types.getTypeName(MF.getClassType());
15109467b48Spatrick   StringRef Params = Types.getTypeName(MF.getArgumentList());
15209467b48Spatrick   Name = formatv("{0} {1}::{2}", Ret, Class, Params).sstr<256>();
15309467b48Spatrick   return Error::success();
15409467b48Spatrick }
15509467b48Spatrick 
visitKnownRecord(CVType & CVR,FuncIdRecord & Func)15609467b48Spatrick Error TypeNameComputer::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {
15709467b48Spatrick   Name = Func.getName();
15809467b48Spatrick   return Error::success();
15909467b48Spatrick }
16009467b48Spatrick 
visitKnownRecord(CVType & CVR,TypeServer2Record & TS)16109467b48Spatrick Error TypeNameComputer::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) {
16209467b48Spatrick   Name = TS.getName();
16309467b48Spatrick   return Error::success();
16409467b48Spatrick }
16509467b48Spatrick 
visitKnownRecord(CVType & CVR,PointerRecord & Ptr)16609467b48Spatrick Error TypeNameComputer::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {
16709467b48Spatrick 
16809467b48Spatrick   if (Ptr.isPointerToMember()) {
16909467b48Spatrick     const MemberPointerInfo &MI = Ptr.getMemberInfo();
17009467b48Spatrick 
17109467b48Spatrick     StringRef Pointee = Types.getTypeName(Ptr.getReferentType());
17209467b48Spatrick     StringRef Class = Types.getTypeName(MI.getContainingType());
17309467b48Spatrick     Name = formatv("{0} {1}::*", Pointee, Class);
17409467b48Spatrick   } else {
17509467b48Spatrick     Name.append(Types.getTypeName(Ptr.getReferentType()));
17609467b48Spatrick 
17709467b48Spatrick     if (Ptr.getMode() == PointerMode::LValueReference)
17809467b48Spatrick       Name.append("&");
17909467b48Spatrick     else if (Ptr.getMode() == PointerMode::RValueReference)
18009467b48Spatrick       Name.append("&&");
18109467b48Spatrick     else if (Ptr.getMode() == PointerMode::Pointer)
18209467b48Spatrick       Name.append("*");
18309467b48Spatrick 
18409467b48Spatrick     // Qualifiers in pointer records apply to the pointer, not the pointee, so
18509467b48Spatrick     // they go on the right.
18609467b48Spatrick     if (Ptr.isConst())
18709467b48Spatrick       Name.append(" const");
18809467b48Spatrick     if (Ptr.isVolatile())
18909467b48Spatrick       Name.append(" volatile");
19009467b48Spatrick     if (Ptr.isUnaligned())
19109467b48Spatrick       Name.append(" __unaligned");
19209467b48Spatrick     if (Ptr.isRestrict())
19309467b48Spatrick       Name.append(" __restrict");
19409467b48Spatrick   }
19509467b48Spatrick   return Error::success();
19609467b48Spatrick }
19709467b48Spatrick 
visitKnownRecord(CVType & CVR,ModifierRecord & Mod)19809467b48Spatrick Error TypeNameComputer::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {
19909467b48Spatrick   uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
20009467b48Spatrick 
20109467b48Spatrick   if (Mods & uint16_t(ModifierOptions::Const))
20209467b48Spatrick     Name.append("const ");
20309467b48Spatrick   if (Mods & uint16_t(ModifierOptions::Volatile))
20409467b48Spatrick     Name.append("volatile ");
20509467b48Spatrick   if (Mods & uint16_t(ModifierOptions::Unaligned))
20609467b48Spatrick     Name.append("__unaligned ");
20709467b48Spatrick   Name.append(Types.getTypeName(Mod.getModifiedType()));
20809467b48Spatrick   return Error::success();
20909467b48Spatrick }
21009467b48Spatrick 
visitKnownRecord(CVType & CVR,VFTableShapeRecord & Shape)21109467b48Spatrick Error TypeNameComputer::visitKnownRecord(CVType &CVR,
21209467b48Spatrick                                          VFTableShapeRecord &Shape) {
21309467b48Spatrick   Name = formatv("<vftable {0} methods>", Shape.getEntryCount());
21409467b48Spatrick   return Error::success();
21509467b48Spatrick }
21609467b48Spatrick 
visitKnownRecord(CVType & CVR,UdtModSourceLineRecord & ModSourceLine)21709467b48Spatrick Error TypeNameComputer::visitKnownRecord(
21809467b48Spatrick     CVType &CVR, UdtModSourceLineRecord &ModSourceLine) {
21909467b48Spatrick   return Error::success();
22009467b48Spatrick }
22109467b48Spatrick 
visitKnownRecord(CVType & CVR,UdtSourceLineRecord & SourceLine)22209467b48Spatrick Error TypeNameComputer::visitKnownRecord(CVType &CVR,
22309467b48Spatrick                                          UdtSourceLineRecord &SourceLine) {
22409467b48Spatrick   return Error::success();
22509467b48Spatrick }
22609467b48Spatrick 
visitKnownRecord(CVType & CVR,BitFieldRecord & BF)22709467b48Spatrick Error TypeNameComputer::visitKnownRecord(CVType &CVR, BitFieldRecord &BF) {
22809467b48Spatrick   return Error::success();
22909467b48Spatrick }
23009467b48Spatrick 
visitKnownRecord(CVType & CVR,MethodOverloadListRecord & Overloads)23109467b48Spatrick Error TypeNameComputer::visitKnownRecord(CVType &CVR,
23209467b48Spatrick                                          MethodOverloadListRecord &Overloads) {
23309467b48Spatrick   return Error::success();
23409467b48Spatrick }
23509467b48Spatrick 
visitKnownRecord(CVType & CVR,BuildInfoRecord & BI)23609467b48Spatrick Error TypeNameComputer::visitKnownRecord(CVType &CVR, BuildInfoRecord &BI) {
23709467b48Spatrick   return Error::success();
23809467b48Spatrick }
23909467b48Spatrick 
visitKnownRecord(CVType & CVR,LabelRecord & R)24009467b48Spatrick Error TypeNameComputer::visitKnownRecord(CVType &CVR, LabelRecord &R) {
24109467b48Spatrick   return Error::success();
24209467b48Spatrick }
24309467b48Spatrick 
visitKnownRecord(CVType & CVR,PrecompRecord & Precomp)24409467b48Spatrick Error TypeNameComputer::visitKnownRecord(CVType &CVR,
24509467b48Spatrick                                          PrecompRecord &Precomp) {
24609467b48Spatrick   return Error::success();
24709467b48Spatrick }
24809467b48Spatrick 
visitKnownRecord(CVType & CVR,EndPrecompRecord & EndPrecomp)24909467b48Spatrick Error TypeNameComputer::visitKnownRecord(CVType &CVR,
25009467b48Spatrick                                          EndPrecompRecord &EndPrecomp) {
25109467b48Spatrick   return Error::success();
25209467b48Spatrick }
25309467b48Spatrick 
computeTypeName(TypeCollection & Types,TypeIndex Index)25409467b48Spatrick std::string llvm::codeview::computeTypeName(TypeCollection &Types,
25509467b48Spatrick                                             TypeIndex Index) {
25609467b48Spatrick   TypeNameComputer Computer(Types);
25709467b48Spatrick   CVType Record = Types.getType(Index);
25809467b48Spatrick   if (auto EC = visitTypeRecord(Record, Index, Computer)) {
25909467b48Spatrick     consumeError(std::move(EC));
26009467b48Spatrick     return "<unknown UDT>";
26109467b48Spatrick   }
262097a140dSpatrick   return std::string(Computer.name());
26309467b48Spatrick }
26409467b48Spatrick 
getSymbolNameOffset(CVSymbol Sym)26509467b48Spatrick static int getSymbolNameOffset(CVSymbol Sym) {
26609467b48Spatrick   switch (Sym.kind()) {
26709467b48Spatrick   // See ProcSym
26809467b48Spatrick   case SymbolKind::S_GPROC32:
26909467b48Spatrick   case SymbolKind::S_LPROC32:
27009467b48Spatrick   case SymbolKind::S_GPROC32_ID:
27109467b48Spatrick   case SymbolKind::S_LPROC32_ID:
27209467b48Spatrick   case SymbolKind::S_LPROC32_DPC:
27309467b48Spatrick   case SymbolKind::S_LPROC32_DPC_ID:
27409467b48Spatrick     return 35;
27509467b48Spatrick   // See Thunk32Sym
27609467b48Spatrick   case SymbolKind::S_THUNK32:
27709467b48Spatrick     return 21;
27809467b48Spatrick   // See SectionSym
27909467b48Spatrick   case SymbolKind::S_SECTION:
28009467b48Spatrick     return 16;
28109467b48Spatrick   // See CoffGroupSym
28209467b48Spatrick   case SymbolKind::S_COFFGROUP:
28309467b48Spatrick     return 14;
28409467b48Spatrick   // See PublicSym32, FileStaticSym, RegRelativeSym, DataSym, ThreadLocalDataSym
28509467b48Spatrick   case SymbolKind::S_PUB32:
28609467b48Spatrick   case SymbolKind::S_FILESTATIC:
28709467b48Spatrick   case SymbolKind::S_REGREL32:
28809467b48Spatrick   case SymbolKind::S_GDATA32:
28909467b48Spatrick   case SymbolKind::S_LDATA32:
29009467b48Spatrick   case SymbolKind::S_LMANDATA:
29109467b48Spatrick   case SymbolKind::S_GMANDATA:
29209467b48Spatrick   case SymbolKind::S_LTHREAD32:
29309467b48Spatrick   case SymbolKind::S_GTHREAD32:
29409467b48Spatrick   case SymbolKind::S_PROCREF:
29509467b48Spatrick   case SymbolKind::S_LPROCREF:
29609467b48Spatrick     return 10;
29709467b48Spatrick   // See RegisterSym and LocalSym
29809467b48Spatrick   case SymbolKind::S_REGISTER:
29909467b48Spatrick   case SymbolKind::S_LOCAL:
30009467b48Spatrick     return 6;
30109467b48Spatrick   // See BlockSym
30209467b48Spatrick   case SymbolKind::S_BLOCK32:
30309467b48Spatrick     return 18;
30409467b48Spatrick   // See LabelSym
30509467b48Spatrick   case SymbolKind::S_LABEL32:
30609467b48Spatrick     return 7;
30709467b48Spatrick   // See ObjNameSym, ExportSym, and UDTSym
30809467b48Spatrick   case SymbolKind::S_OBJNAME:
30909467b48Spatrick   case SymbolKind::S_EXPORT:
31009467b48Spatrick   case SymbolKind::S_UDT:
31109467b48Spatrick     return 4;
31209467b48Spatrick   // See BPRelativeSym
31309467b48Spatrick   case SymbolKind::S_BPREL32:
31409467b48Spatrick     return 8;
31509467b48Spatrick   // See UsingNamespaceSym
31609467b48Spatrick   case SymbolKind::S_UNAMESPACE:
31709467b48Spatrick     return 0;
31809467b48Spatrick   default:
31909467b48Spatrick     return -1;
32009467b48Spatrick   }
32109467b48Spatrick }
32209467b48Spatrick 
getSymbolName(CVSymbol Sym)32309467b48Spatrick StringRef llvm::codeview::getSymbolName(CVSymbol Sym) {
32409467b48Spatrick   if (Sym.kind() == SymbolKind::S_CONSTANT) {
32509467b48Spatrick     // S_CONSTANT is preceded by an APSInt, which has a variable length.  So we
32609467b48Spatrick     // have to do a full deserialization.
32709467b48Spatrick     BinaryStreamReader Reader(Sym.content(), llvm::support::little);
32809467b48Spatrick     // The container doesn't matter for single records.
32909467b48Spatrick     SymbolRecordMapping Mapping(Reader, CodeViewContainer::ObjectFile);
33009467b48Spatrick     ConstantSym Const(SymbolKind::S_CONSTANT);
33109467b48Spatrick     cantFail(Mapping.visitSymbolBegin(Sym));
33209467b48Spatrick     cantFail(Mapping.visitKnownRecord(Sym, Const));
33309467b48Spatrick     cantFail(Mapping.visitSymbolEnd(Sym));
33409467b48Spatrick     return Const.Name;
33509467b48Spatrick   }
33609467b48Spatrick 
33709467b48Spatrick   int Offset = getSymbolNameOffset(Sym);
33809467b48Spatrick   if (Offset == -1)
33909467b48Spatrick     return StringRef();
34009467b48Spatrick 
34109467b48Spatrick   StringRef StringData = toStringRef(Sym.content()).drop_front(Offset);
34209467b48Spatrick   return StringData.split('\0').first;
34309467b48Spatrick }
344