brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.7 KiB · e06b036 Raw
344 lines · cpp
1//===- RecordName.cpp ----------------------------------------- *- C++ --*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/DebugInfo/CodeView/RecordName.h"10 11#include "llvm/ADT/SmallString.h"12#include "llvm/ADT/StringExtras.h"13#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"14#include "llvm/DebugInfo/CodeView/CodeView.h"15#include "llvm/DebugInfo/CodeView/SymbolRecord.h"16#include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h"17#include "llvm/DebugInfo/CodeView/TypeCollection.h"18#include "llvm/DebugInfo/CodeView/TypeIndex.h"19#include "llvm/DebugInfo/CodeView/TypeRecord.h"20#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"21#include "llvm/Support/FormatVariadic.h"22 23using namespace llvm;24using namespace llvm::codeview;25 26namespace {27class TypeNameComputer : public TypeVisitorCallbacks {28  /// The type collection.  Used to calculate names of nested types.29  TypeCollection &Types;30  TypeIndex CurrentTypeIndex = TypeIndex::None();31 32  /// Name of the current type. Only valid before visitTypeEnd.33  SmallString<256> Name;34 35public:36  explicit TypeNameComputer(TypeCollection &Types) : Types(Types) {}37 38  StringRef name() const { return Name; }39 40  /// Paired begin/end actions for all types. Receives all record data,41  /// including the fixed-length record prefix.42  Error visitTypeBegin(CVType &Record) override;43  Error visitTypeBegin(CVType &Record, TypeIndex Index) override;44  Error visitTypeEnd(CVType &Record) override;45 46#define TYPE_RECORD(EnumName, EnumVal, Name)                                   \47  Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;48#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)49#define MEMBER_RECORD(EnumName, EnumVal, Name)50#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"51};52} // namespace53 54Error TypeNameComputer::visitTypeBegin(CVType &Record) {55  llvm_unreachable("Must call visitTypeBegin with a TypeIndex!");56  return Error::success();57}58 59Error TypeNameComputer::visitTypeBegin(CVType &Record, TypeIndex Index) {60  // Reset Name to the empty string. If the visitor sets it, we know it.61  Name = "";62  CurrentTypeIndex = Index;63  return Error::success();64}65 66Error TypeNameComputer::visitTypeEnd(CVType &CVR) { return Error::success(); }67 68Error TypeNameComputer::visitKnownRecord(CVType &CVR,69                                         FieldListRecord &FieldList) {70  Name = "<field list>";71  return Error::success();72}73 74Error TypeNameComputer::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,75                                         StringIdRecord &String) {76  Name = String.getString();77  return Error::success();78}79 80Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArgListRecord &Args) {81  auto Indices = Args.getIndices();82  uint32_t Size = Indices.size();83  Name = "(";84  for (uint32_t I = 0; I < Size; ++I) {85    if (Indices[I] < CurrentTypeIndex)86      Name.append(Types.getTypeName(Indices[I]));87    else88      Name.append("<unknown 0x" + utohexstr(Indices[I].getIndex()) + ">");89    if (I + 1 != Size)90      Name.append(", ");91  }92  Name.push_back(')');93  return Error::success();94}95 96Error TypeNameComputer::visitKnownRecord(CVType &CVR,97                                         StringListRecord &Strings) {98  auto Indices = Strings.getIndices();99  uint32_t Size = Indices.size();100  Name = "\"";101  for (uint32_t I = 0; I < Size; ++I) {102    Name.append(Types.getTypeName(Indices[I]));103    if (I + 1 != Size)104      Name.append("\" \"");105  }106  Name.push_back('\"');107  return Error::success();108}109 110Error TypeNameComputer::visitKnownRecord(CVType &CVR, ClassRecord &Class) {111  Name = Class.getName();112  return Error::success();113}114 115Error TypeNameComputer::visitKnownRecord(CVType &CVR, UnionRecord &Union) {116  Name = Union.getName();117  return Error::success();118}119 120Error TypeNameComputer::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {121  Name = Enum.getName();122  return Error::success();123}124 125Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {126  Name = AT.getName();127  return Error::success();128}129 130Error TypeNameComputer::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) {131  Name = VFT.getName();132  return Error::success();133}134 135Error TypeNameComputer::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) {136  Name = Id.getName();137  return Error::success();138}139 140Error TypeNameComputer::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) {141  StringRef Ret = Types.getTypeName(Proc.getReturnType());142  StringRef Params = Types.getTypeName(Proc.getArgumentList());143  Name = formatv("{0} {1}", Ret, Params).sstr<256>();144  return Error::success();145}146 147Error TypeNameComputer::visitKnownRecord(CVType &CVR,148                                         MemberFunctionRecord &MF) {149  StringRef Ret = Types.getTypeName(MF.getReturnType());150  StringRef Class = Types.getTypeName(MF.getClassType());151  StringRef Params = Types.getTypeName(MF.getArgumentList());152  Name = formatv("{0} {1}::{2}", Ret, Class, Params).sstr<256>();153  return Error::success();154}155 156Error TypeNameComputer::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {157  Name = Func.getName();158  return Error::success();159}160 161Error TypeNameComputer::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) {162  Name = TS.getName();163  return Error::success();164}165 166Error TypeNameComputer::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {167 168  if (Ptr.isPointerToMember()) {169    const MemberPointerInfo &MI = Ptr.getMemberInfo();170 171    StringRef Pointee = Types.getTypeName(Ptr.getReferentType());172    StringRef Class = Types.getTypeName(MI.getContainingType());173    Name = formatv("{0} {1}::*", Pointee, Class);174  } else {175    Name.append(Types.getTypeName(Ptr.getReferentType()));176 177    if (Ptr.getMode() == PointerMode::LValueReference)178      Name.append("&");179    else if (Ptr.getMode() == PointerMode::RValueReference)180      Name.append("&&");181    else if (Ptr.getMode() == PointerMode::Pointer)182      Name.append("*");183 184    // Qualifiers in pointer records apply to the pointer, not the pointee, so185    // they go on the right.186    if (Ptr.isConst())187      Name.append(" const");188    if (Ptr.isVolatile())189      Name.append(" volatile");190    if (Ptr.isUnaligned())191      Name.append(" __unaligned");192    if (Ptr.isRestrict())193      Name.append(" __restrict");194  }195  return Error::success();196}197 198Error TypeNameComputer::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {199  uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());200 201  if (Mods & uint16_t(ModifierOptions::Const))202    Name.append("const ");203  if (Mods & uint16_t(ModifierOptions::Volatile))204    Name.append("volatile ");205  if (Mods & uint16_t(ModifierOptions::Unaligned))206    Name.append("__unaligned ");207  Name.append(Types.getTypeName(Mod.getModifiedType()));208  return Error::success();209}210 211Error TypeNameComputer::visitKnownRecord(CVType &CVR,212                                         VFTableShapeRecord &Shape) {213  Name = formatv("<vftable {0} methods>", Shape.getEntryCount());214  return Error::success();215}216 217Error TypeNameComputer::visitKnownRecord(218    CVType &CVR, UdtModSourceLineRecord &ModSourceLine) {219  return Error::success();220}221 222Error TypeNameComputer::visitKnownRecord(CVType &CVR,223                                         UdtSourceLineRecord &SourceLine) {224  return Error::success();225}226 227Error TypeNameComputer::visitKnownRecord(CVType &CVR, BitFieldRecord &BF) {228  return Error::success();229}230 231Error TypeNameComputer::visitKnownRecord(CVType &CVR,232                                         MethodOverloadListRecord &Overloads) {233  return Error::success();234}235 236Error TypeNameComputer::visitKnownRecord(CVType &CVR, BuildInfoRecord &BI) {237  return Error::success();238}239 240Error TypeNameComputer::visitKnownRecord(CVType &CVR, LabelRecord &R) {241  return Error::success();242}243 244Error TypeNameComputer::visitKnownRecord(CVType &CVR,245                                         PrecompRecord &Precomp) {246  return Error::success();247}248 249Error TypeNameComputer::visitKnownRecord(CVType &CVR,250                                         EndPrecompRecord &EndPrecomp) {251  return Error::success();252}253 254std::string llvm::codeview::computeTypeName(TypeCollection &Types,255                                            TypeIndex Index) {256  TypeNameComputer Computer(Types);257  CVType Record = Types.getType(Index);258  if (auto EC = visitTypeRecord(Record, Index, Computer)) {259    consumeError(std::move(EC));260    return "<unknown UDT>";261  }262  return std::string(Computer.name());263}264 265static int getSymbolNameOffset(CVSymbol Sym) {266  switch (Sym.kind()) {267  // See ProcSym268  case SymbolKind::S_GPROC32:269  case SymbolKind::S_LPROC32:270  case SymbolKind::S_GPROC32_ID:271  case SymbolKind::S_LPROC32_ID:272  case SymbolKind::S_LPROC32_DPC:273  case SymbolKind::S_LPROC32_DPC_ID:274    return 35;275  // See Thunk32Sym276  case SymbolKind::S_THUNK32:277    return 21;278  // See SectionSym279  case SymbolKind::S_SECTION:280    return 16;281  // See CoffGroupSym282  case SymbolKind::S_COFFGROUP:283    return 14;284  // See PublicSym32, FileStaticSym, RegRelativeSym, DataSym, ThreadLocalDataSym285  case SymbolKind::S_PUB32:286  case SymbolKind::S_FILESTATIC:287  case SymbolKind::S_REGREL32:288  case SymbolKind::S_GDATA32:289  case SymbolKind::S_LDATA32:290  case SymbolKind::S_LMANDATA:291  case SymbolKind::S_GMANDATA:292  case SymbolKind::S_LTHREAD32:293  case SymbolKind::S_GTHREAD32:294  case SymbolKind::S_PROCREF:295  case SymbolKind::S_LPROCREF:296    return 10;297  // See RegisterSym and LocalSym298  case SymbolKind::S_REGISTER:299  case SymbolKind::S_LOCAL:300    return 6;301  // See BlockSym302  case SymbolKind::S_BLOCK32:303    return 18;304  // See LabelSym305  case SymbolKind::S_LABEL32:306    return 7;307  // See ObjNameSym, ExportSym, and UDTSym308  case SymbolKind::S_OBJNAME:309  case SymbolKind::S_EXPORT:310  case SymbolKind::S_UDT:311    return 4;312  // See BPRelativeSym313  case SymbolKind::S_BPREL32:314    return 8;315  // See UsingNamespaceSym316  case SymbolKind::S_UNAMESPACE:317    return 0;318  default:319    return -1;320  }321}322 323StringRef llvm::codeview::getSymbolName(CVSymbol Sym) {324  if (Sym.kind() == SymbolKind::S_CONSTANT) {325    // S_CONSTANT is preceded by an APSInt, which has a variable length.  So we326    // have to do a full deserialization.327    BinaryStreamReader Reader(Sym.content(), llvm::endianness::little);328    // The container doesn't matter for single records.329    SymbolRecordMapping Mapping(Reader, CodeViewContainer::ObjectFile);330    ConstantSym Const(SymbolKind::S_CONSTANT);331    cantFail(Mapping.visitSymbolBegin(Sym));332    cantFail(Mapping.visitKnownRecord(Sym, Const));333    cantFail(Mapping.visitSymbolEnd(Sym));334    return Const.Name;335  }336 337  int Offset = getSymbolNameOffset(Sym);338  if (Offset == -1)339    return StringRef();340 341  StringRef StringData = toStringRef(Sym.content()).drop_front(Offset);342  return StringData.split('\0').first;343}344