123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 |
- //===- RecordName.cpp ----------------------------------------- *- C++ --*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "llvm/DebugInfo/CodeView/RecordName.h"
- #include "llvm/ADT/SmallString.h"
- #include "llvm/ADT/StringExtras.h"
- #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
- #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
- #include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h"
- #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
- #include "llvm/Support/FormatVariadic.h"
- using namespace llvm;
- using namespace llvm::codeview;
- namespace {
- class TypeNameComputer : public TypeVisitorCallbacks {
- /// The type collection. Used to calculate names of nested types.
- TypeCollection &Types;
- TypeIndex CurrentTypeIndex = TypeIndex::None();
- /// Name of the current type. Only valid before visitTypeEnd.
- SmallString<256> Name;
- public:
- explicit TypeNameComputer(TypeCollection &Types) : Types(Types) {}
- StringRef name() const { return Name; }
- /// Paired begin/end actions for all types. Receives all record data,
- /// including the fixed-length record prefix.
- Error visitTypeBegin(CVType &Record) override;
- Error visitTypeBegin(CVType &Record, TypeIndex Index) override;
- Error visitTypeEnd(CVType &Record) override;
- #define TYPE_RECORD(EnumName, EnumVal, Name) \
- Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
- #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
- #define MEMBER_RECORD(EnumName, EnumVal, Name)
- #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
- };
- } // namespace
- Error TypeNameComputer::visitTypeBegin(CVType &Record) {
- llvm_unreachable("Must call visitTypeBegin with a TypeIndex!");
- return Error::success();
- }
- Error TypeNameComputer::visitTypeBegin(CVType &Record, TypeIndex Index) {
- // Reset Name to the empty string. If the visitor sets it, we know it.
- Name = "";
- CurrentTypeIndex = Index;
- return Error::success();
- }
- Error TypeNameComputer::visitTypeEnd(CVType &CVR) { return Error::success(); }
- Error TypeNameComputer::visitKnownRecord(CVType &CVR,
- FieldListRecord &FieldList) {
- Name = "<field list>";
- return Error::success();
- }
- Error TypeNameComputer::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
- StringIdRecord &String) {
- Name = String.getString();
- return Error::success();
- }
- Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArgListRecord &Args) {
- auto Indices = Args.getIndices();
- uint32_t Size = Indices.size();
- Name = "(";
- for (uint32_t I = 0; I < Size; ++I) {
- if (Indices[I] < CurrentTypeIndex)
- Name.append(Types.getTypeName(Indices[I]));
- else
- Name.append("<unknown 0x" + utohexstr(Indices[I].getIndex()) + ">");
- if (I + 1 != Size)
- Name.append(", ");
- }
- Name.push_back(')');
- return Error::success();
- }
- Error TypeNameComputer::visitKnownRecord(CVType &CVR,
- StringListRecord &Strings) {
- auto Indices = Strings.getIndices();
- uint32_t Size = Indices.size();
- Name = "\"";
- for (uint32_t I = 0; I < Size; ++I) {
- Name.append(Types.getTypeName(Indices[I]));
- if (I + 1 != Size)
- Name.append("\" \"");
- }
- Name.push_back('\"');
- return Error::success();
- }
- Error TypeNameComputer::visitKnownRecord(CVType &CVR, ClassRecord &Class) {
- Name = Class.getName();
- return Error::success();
- }
- Error TypeNameComputer::visitKnownRecord(CVType &CVR, UnionRecord &Union) {
- Name = Union.getName();
- return Error::success();
- }
- Error TypeNameComputer::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
- Name = Enum.getName();
- return Error::success();
- }
- Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
- Name = AT.getName();
- return Error::success();
- }
- Error TypeNameComputer::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) {
- Name = VFT.getName();
- return Error::success();
- }
- Error TypeNameComputer::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) {
- Name = Id.getName();
- return Error::success();
- }
- Error TypeNameComputer::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) {
- StringRef Ret = Types.getTypeName(Proc.getReturnType());
- StringRef Params = Types.getTypeName(Proc.getArgumentList());
- Name = formatv("{0} {1}", Ret, Params).sstr<256>();
- return Error::success();
- }
- Error TypeNameComputer::visitKnownRecord(CVType &CVR,
- MemberFunctionRecord &MF) {
- StringRef Ret = Types.getTypeName(MF.getReturnType());
- StringRef Class = Types.getTypeName(MF.getClassType());
- StringRef Params = Types.getTypeName(MF.getArgumentList());
- Name = formatv("{0} {1}::{2}", Ret, Class, Params).sstr<256>();
- return Error::success();
- }
- Error TypeNameComputer::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {
- Name = Func.getName();
- return Error::success();
- }
- Error TypeNameComputer::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) {
- Name = TS.getName();
- return Error::success();
- }
- Error TypeNameComputer::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {
- if (Ptr.isPointerToMember()) {
- const MemberPointerInfo &MI = Ptr.getMemberInfo();
- StringRef Pointee = Types.getTypeName(Ptr.getReferentType());
- StringRef Class = Types.getTypeName(MI.getContainingType());
- Name = formatv("{0} {1}::*", Pointee, Class);
- } else {
- Name.append(Types.getTypeName(Ptr.getReferentType()));
- if (Ptr.getMode() == PointerMode::LValueReference)
- Name.append("&");
- else if (Ptr.getMode() == PointerMode::RValueReference)
- Name.append("&&");
- else if (Ptr.getMode() == PointerMode::Pointer)
- Name.append("*");
- // Qualifiers in pointer records apply to the pointer, not the pointee, so
- // they go on the right.
- if (Ptr.isConst())
- Name.append(" const");
- if (Ptr.isVolatile())
- Name.append(" volatile");
- if (Ptr.isUnaligned())
- Name.append(" __unaligned");
- if (Ptr.isRestrict())
- Name.append(" __restrict");
- }
- return Error::success();
- }
- Error TypeNameComputer::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {
- uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
- if (Mods & uint16_t(ModifierOptions::Const))
- Name.append("const ");
- if (Mods & uint16_t(ModifierOptions::Volatile))
- Name.append("volatile ");
- if (Mods & uint16_t(ModifierOptions::Unaligned))
- Name.append("__unaligned ");
- Name.append(Types.getTypeName(Mod.getModifiedType()));
- return Error::success();
- }
- Error TypeNameComputer::visitKnownRecord(CVType &CVR,
- VFTableShapeRecord &Shape) {
- Name = formatv("<vftable {0} methods>", Shape.getEntryCount());
- return Error::success();
- }
- Error TypeNameComputer::visitKnownRecord(
- CVType &CVR, UdtModSourceLineRecord &ModSourceLine) {
- return Error::success();
- }
- Error TypeNameComputer::visitKnownRecord(CVType &CVR,
- UdtSourceLineRecord &SourceLine) {
- return Error::success();
- }
- Error TypeNameComputer::visitKnownRecord(CVType &CVR, BitFieldRecord &BF) {
- return Error::success();
- }
- Error TypeNameComputer::visitKnownRecord(CVType &CVR,
- MethodOverloadListRecord &Overloads) {
- return Error::success();
- }
- Error TypeNameComputer::visitKnownRecord(CVType &CVR, BuildInfoRecord &BI) {
- return Error::success();
- }
- Error TypeNameComputer::visitKnownRecord(CVType &CVR, LabelRecord &R) {
- return Error::success();
- }
- Error TypeNameComputer::visitKnownRecord(CVType &CVR,
- PrecompRecord &Precomp) {
- return Error::success();
- }
- Error TypeNameComputer::visitKnownRecord(CVType &CVR,
- EndPrecompRecord &EndPrecomp) {
- return Error::success();
- }
- std::string llvm::codeview::computeTypeName(TypeCollection &Types,
- TypeIndex Index) {
- TypeNameComputer Computer(Types);
- CVType Record = Types.getType(Index);
- if (auto EC = visitTypeRecord(Record, Index, Computer)) {
- consumeError(std::move(EC));
- return "<unknown UDT>";
- }
- return std::string(Computer.name());
- }
- static int getSymbolNameOffset(CVSymbol Sym) {
- switch (Sym.kind()) {
- // See ProcSym
- case SymbolKind::S_GPROC32:
- case SymbolKind::S_LPROC32:
- case SymbolKind::S_GPROC32_ID:
- case SymbolKind::S_LPROC32_ID:
- case SymbolKind::S_LPROC32_DPC:
- case SymbolKind::S_LPROC32_DPC_ID:
- return 35;
- // See Thunk32Sym
- case SymbolKind::S_THUNK32:
- return 21;
- // See SectionSym
- case SymbolKind::S_SECTION:
- return 16;
- // See CoffGroupSym
- case SymbolKind::S_COFFGROUP:
- return 14;
- // See PublicSym32, FileStaticSym, RegRelativeSym, DataSym, ThreadLocalDataSym
- case SymbolKind::S_PUB32:
- case SymbolKind::S_FILESTATIC:
- case SymbolKind::S_REGREL32:
- case SymbolKind::S_GDATA32:
- case SymbolKind::S_LDATA32:
- case SymbolKind::S_LMANDATA:
- case SymbolKind::S_GMANDATA:
- case SymbolKind::S_LTHREAD32:
- case SymbolKind::S_GTHREAD32:
- case SymbolKind::S_PROCREF:
- case SymbolKind::S_LPROCREF:
- return 10;
- // See RegisterSym and LocalSym
- case SymbolKind::S_REGISTER:
- case SymbolKind::S_LOCAL:
- return 6;
- // See BlockSym
- case SymbolKind::S_BLOCK32:
- return 18;
- // See LabelSym
- case SymbolKind::S_LABEL32:
- return 7;
- // See ObjNameSym, ExportSym, and UDTSym
- case SymbolKind::S_OBJNAME:
- case SymbolKind::S_EXPORT:
- case SymbolKind::S_UDT:
- return 4;
- // See BPRelativeSym
- case SymbolKind::S_BPREL32:
- return 8;
- // See UsingNamespaceSym
- case SymbolKind::S_UNAMESPACE:
- return 0;
- default:
- return -1;
- }
- }
- StringRef llvm::codeview::getSymbolName(CVSymbol Sym) {
- if (Sym.kind() == SymbolKind::S_CONSTANT) {
- // S_CONSTANT is preceded by an APSInt, which has a variable length. So we
- // have to do a full deserialization.
- BinaryStreamReader Reader(Sym.content(), llvm::support::little);
- // The container doesn't matter for single records.
- SymbolRecordMapping Mapping(Reader, CodeViewContainer::ObjectFile);
- ConstantSym Const(SymbolKind::S_CONSTANT);
- cantFail(Mapping.visitSymbolBegin(Sym));
- cantFail(Mapping.visitKnownRecord(Sym, Const));
- cantFail(Mapping.visitSymbolEnd(Sym));
- return Const.Name;
- }
- int Offset = getSymbolNameOffset(Sym);
- if (Offset == -1)
- return StringRef();
- StringRef StringData = toStringRef(Sym.content()).drop_front(Offset);
- return StringData.split('\0').first;
- }
|