1 //===-- PdbSymUid.h ---------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // A unique identification scheme for Pdb records. 10 // The scheme is to partition a 64-bit integer into an 8-bit tag field, which 11 // will contain some value from the PDB_SymType enumeration. The format of the 12 // other 48-bits depend on the tag, but must be sufficient to locate the 13 // corresponding entry in the underlying PDB file quickly. For example, for 14 // a compile unit, we use 2 bytes to represent the index, which allows fast 15 // access to the compile unit's information. 16 //===----------------------------------------------------------------------===// 17 18 #ifndef LLDB_PLUGINS_SYMBOLFILENATIVEPDB_PDBSYMUID_H 19 #define LLDB_PLUGINS_SYMBOLFILENATIVEPDB_PDBSYMUID_H 20 21 #include "llvm/DebugInfo/CodeView/SymbolRecord.h" 22 #include "llvm/DebugInfo/PDB/PDBTypes.h" 23 #include "llvm/Support/Compiler.h" 24 25 #include "lldb/Utility/LLDBAssert.h" 26 #include "lldb/lldb-types.h" 27 28 namespace lldb_private { 29 namespace npdb { 30 31 // **important** - All concrete id types must have the 1-byte tag field at 32 // the beginning so that the types are all layout-compatible with each 33 // other, which is necessary in order to be able to safely access the tag 34 // member through any union member. 35 struct PdbCompilandId { 36 uint64_t tag : 8; // PDB_SymType::Compiland 37 uint64_t modi : 16; // 0-based index of module in PDB 38 uint64_t unused : 32; 39 }; 40 struct PdbCuSymId { 41 uint64_t tag : 8; // PDB_SymType::Data, Function, Block, etc. 42 uint64_t 43 offset : 30; // Offset of symbol's record in module stream. This is 44 // offset by 4 from the CVSymbolArray's notion of offset 45 // due to the debug magic at the beginning of the stream. 46 uint64_t global : 1; // True if this is from the globals stream. 47 uint64_t unused : 1; 48 uint64_t modi : 16; // For non-global, this is the 0-based index of module. 49 }; 50 51 struct PdbTypeSymId { 52 uint64_t tag : 8; // PDB_SymType::FunctionSig, Enum, PointerType, etc. 53 uint64_t is_ipi : 8; // 1 if this value is from the IPI stream, 0 for TPI. 54 uint64_t unused : 16; 55 uint64_t index : 32; // codeview::TypeIndex 56 }; 57 58 static_assert(sizeof(PdbCompilandId) == 8, "invalid uid size"); 59 static_assert(sizeof(PdbCuSymId) == 8, "invalid uid size"); 60 static_assert(std::is_standard_layout<PdbCompilandId>::value, 61 "type is not standard layout!"); 62 static_assert(std::is_standard_layout<PdbCuSymId>::value, 63 "type is not standard layout!"); 64 65 class PdbSymUid { 66 union { 67 PdbCompilandId comp_id; 68 PdbCuSymId cu_sym; 69 PdbTypeSymId type_sym; 70 } m_uid; 71 72 PdbSymUid() { ::memset(&m_uid, 0, sizeof(m_uid)); } 73 74 public: 75 static bool isTypeSym(llvm::pdb::PDB_SymType tag) { 76 switch (tag) { 77 case llvm::pdb::PDB_SymType::ArrayType: 78 case llvm::pdb::PDB_SymType::BaseClass: 79 case llvm::pdb::PDB_SymType::BaseInterface: 80 case llvm::pdb::PDB_SymType::BuiltinType: 81 case llvm::pdb::PDB_SymType::CustomType: 82 case llvm::pdb::PDB_SymType::Enum: 83 case llvm::pdb::PDB_SymType::FunctionArg: 84 case llvm::pdb::PDB_SymType::FunctionSig: 85 case llvm::pdb::PDB_SymType::Typedef: 86 case llvm::pdb::PDB_SymType::VectorType: 87 case llvm::pdb::PDB_SymType::VTableShape: 88 case llvm::pdb::PDB_SymType::PointerType: 89 case llvm::pdb::PDB_SymType::UDT: 90 return true; 91 default: 92 return false; 93 } 94 } 95 96 static bool isCuSym(llvm::pdb::PDB_SymType tag) { 97 switch (tag) { 98 case llvm::pdb::PDB_SymType::Block: 99 case llvm::pdb::PDB_SymType::Callee: 100 case llvm::pdb::PDB_SymType::Caller: 101 case llvm::pdb::PDB_SymType::CallSite: 102 case llvm::pdb::PDB_SymType::CoffGroup: 103 case llvm::pdb::PDB_SymType::CompilandDetails: 104 case llvm::pdb::PDB_SymType::CompilandEnv: 105 case llvm::pdb::PDB_SymType::Custom: 106 case llvm::pdb::PDB_SymType::Data: 107 case llvm::pdb::PDB_SymType::Function: 108 case llvm::pdb::PDB_SymType::Inlinee: 109 case llvm::pdb::PDB_SymType::InlineSite: 110 case llvm::pdb::PDB_SymType::Label: 111 case llvm::pdb::PDB_SymType::Thunk: 112 return true; 113 default: 114 return false; 115 } 116 } 117 118 static PdbSymUid makeCuSymId(llvm::codeview::ProcRefSym sym) { 119 return makeCuSymId(llvm::pdb::PDB_SymType::Function, sym.Module - 1, 120 sym.SymOffset); 121 } 122 123 static PdbSymUid makeCuSymId(llvm::pdb::PDB_SymType type, uint16_t modi, 124 uint32_t offset) { 125 lldbassert(isCuSym(type)); 126 127 PdbSymUid uid; 128 uid.m_uid.cu_sym.modi = modi; 129 uid.m_uid.cu_sym.offset = offset; 130 uid.m_uid.cu_sym.global = false; 131 uid.m_uid.cu_sym.tag = static_cast<uint8_t>(type); 132 return uid; 133 } 134 135 static PdbSymUid makeGlobalVariableUid(uint32_t offset) { 136 PdbSymUid uid = {}; 137 uid.m_uid.cu_sym.modi = 0; 138 uid.m_uid.cu_sym.offset = offset; 139 uid.m_uid.cu_sym.global = 1; 140 uid.m_uid.cu_sym.unused = 0; 141 uid.m_uid.cu_sym.tag = static_cast<uint8_t>(llvm::pdb::PDB_SymType::Data); 142 return uid; 143 } 144 145 static PdbSymUid makeCompilandId(llvm::codeview::ProcRefSym sym) { 146 // S_PROCREF symbols are 1-based 147 lldbassert(sym.Module > 0); 148 return makeCompilandId(sym.Module - 1); 149 } 150 151 static PdbSymUid makeCompilandId(uint16_t modi) { 152 PdbSymUid uid; 153 uid.m_uid.comp_id.modi = modi; 154 uid.m_uid.cu_sym.tag = 155 static_cast<uint8_t>(llvm::pdb::PDB_SymType::Compiland); 156 return uid; 157 } 158 159 static PdbSymUid makeTypeSymId(llvm::pdb::PDB_SymType type, 160 llvm::codeview::TypeIndex index, bool is_ipi) { 161 lldbassert(isTypeSym(type)); 162 163 PdbSymUid uid; 164 uid.m_uid.type_sym.tag = static_cast<uint8_t>(type); 165 uid.m_uid.type_sym.index = index.getIndex(); 166 uid.m_uid.type_sym.is_ipi = static_cast<uint8_t>(is_ipi); 167 return uid; 168 } 169 170 static PdbSymUid fromOpaqueId(uint64_t value) { 171 PdbSymUid result; 172 ::memcpy(&result.m_uid, &value, sizeof(value)); 173 return result; 174 } 175 176 uint64_t toOpaqueId() const { 177 uint64_t result; 178 ::memcpy(&result, &m_uid, sizeof(m_uid)); 179 return result; 180 } 181 182 bool isPubSym() const { 183 return tag() == llvm::pdb::PDB_SymType::PublicSymbol; 184 } 185 bool isCompiland() const { 186 return tag() == llvm::pdb::PDB_SymType::Compiland; 187 } 188 bool isGlobalVariable() const { 189 if (tag() != llvm::pdb::PDB_SymType::Data) 190 return false; 191 return static_cast<bool>(asCuSym().global); 192 } 193 194 llvm::pdb::PDB_SymType tag() const { 195 return static_cast<llvm::pdb::PDB_SymType>(m_uid.comp_id.tag); 196 } 197 198 const PdbCompilandId &asCompiland() const { 199 lldbassert(tag() == llvm::pdb::PDB_SymType::Compiland); 200 return m_uid.comp_id; 201 } 202 203 const PdbCuSymId &asCuSym() const { 204 lldbassert(isCuSym(tag())); 205 return m_uid.cu_sym; 206 } 207 208 const PdbTypeSymId &asTypeSym() const { 209 lldbassert(isTypeSym(tag())); 210 return m_uid.type_sym; 211 } 212 }; 213 214 struct SymbolAndUid { 215 llvm::codeview::CVSymbol sym; 216 PdbSymUid uid; 217 }; 218 } // namespace npdb 219 } // namespace lldb_private 220 221 #endif 222