1 //===-- PdbUtil.cpp ---------------------------------------------*- 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 10 #include "PdbUtil.h" 11 12 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" 13 14 #include "lldb/Utility/LLDBAssert.h" 15 16 using namespace lldb_private; 17 using namespace lldb_private::npdb; 18 using namespace llvm::codeview; 19 using namespace llvm::pdb; 20 21 llvm::pdb::PDB_SymType 22 lldb_private::npdb::CVSymToPDBSym(llvm::codeview::SymbolKind kind) { 23 switch (kind) { 24 case S_COMPILE3: 25 case S_OBJNAME: 26 return PDB_SymType::CompilandDetails; 27 case S_ENVBLOCK: 28 return PDB_SymType::CompilandEnv; 29 case S_THUNK32: 30 case S_TRAMPOLINE: 31 return PDB_SymType::Thunk; 32 case S_COFFGROUP: 33 return PDB_SymType::CoffGroup; 34 case S_EXPORT: 35 return PDB_SymType::Export; 36 case S_LPROC32: 37 case S_GPROC32: 38 case S_LPROC32_DPC: 39 return PDB_SymType::Function; 40 case S_PUB32: 41 return PDB_SymType::PublicSymbol; 42 case S_INLINESITE: 43 return PDB_SymType::InlineSite; 44 case S_LOCAL: 45 case S_BPREL32: 46 case S_REGREL32: 47 case S_MANCONSTANT: 48 case S_CONSTANT: 49 case S_LDATA32: 50 case S_GDATA32: 51 case S_LMANDATA: 52 case S_GMANDATA: 53 case S_LTHREAD32: 54 case S_GTHREAD32: 55 return PDB_SymType::Data; 56 case S_BLOCK32: 57 return PDB_SymType::Block; 58 case S_LABEL32: 59 return PDB_SymType::Label; 60 case S_CALLSITEINFO: 61 return PDB_SymType::CallSite; 62 case S_HEAPALLOCSITE: 63 return PDB_SymType::HeapAllocationSite; 64 case S_CALLEES: 65 return PDB_SymType::Callee; 66 case S_CALLERS: 67 return PDB_SymType::Caller; 68 default: 69 lldbassert(false && "Invalid symbol record kind!"); 70 } 71 return PDB_SymType::None; 72 } 73 74 bool lldb_private::npdb::SymbolHasAddress(const llvm::codeview::CVSymbol &sym) { 75 switch (sym.kind()) { 76 case S_GPROC32: 77 case S_LPROC32: 78 case S_GPROC32_ID: 79 case S_LPROC32_ID: 80 case S_LPROC32_DPC: 81 case S_LPROC32_DPC_ID: 82 case S_THUNK32: 83 case S_TRAMPOLINE: 84 case S_COFFGROUP: 85 case S_BLOCK32: 86 case S_LABEL32: 87 case S_CALLSITEINFO: 88 case S_HEAPALLOCSITE: 89 case S_LDATA32: 90 case S_GDATA32: 91 case S_LMANDATA: 92 case S_GMANDATA: 93 case S_LTHREAD32: 94 case S_GTHREAD32: 95 return true; 96 default: 97 return false; 98 } 99 } 100 101 bool lldb_private::npdb::SymbolIsCode(const llvm::codeview::CVSymbol &sym) { 102 switch (sym.kind()) { 103 case S_GPROC32: 104 case S_LPROC32: 105 case S_GPROC32_ID: 106 case S_LPROC32_ID: 107 case S_LPROC32_DPC: 108 case S_LPROC32_DPC_ID: 109 case S_THUNK32: 110 case S_TRAMPOLINE: 111 case S_COFFGROUP: 112 case S_BLOCK32: 113 return true; 114 default: 115 return false; 116 } 117 } 118 119 template <typename RecordT> RecordT createRecord(const CVSymbol &sym) { 120 RecordT record(static_cast<SymbolRecordKind>(sym.kind())); 121 cantFail(SymbolDeserializer::deserializeAs<RecordT>(sym, record)); 122 return record; 123 } 124 125 template <typename RecordT> 126 static SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) { 127 RecordT record = createRecord<RecordT>(sym); 128 return {record.Segment, record.CodeOffset}; 129 } 130 131 template <> 132 SegmentOffset GetSegmentAndOffset<TrampolineSym>(const CVSymbol &sym) { 133 TrampolineSym record = createRecord<TrampolineSym>(sym); 134 return {record.ThunkSection, record.ThunkOffset}; 135 } 136 137 template <> SegmentOffset GetSegmentAndOffset<Thunk32Sym>(const CVSymbol &sym) { 138 Thunk32Sym record = createRecord<Thunk32Sym>(sym); 139 return {record.Segment, record.Offset}; 140 } 141 142 template <> 143 SegmentOffset GetSegmentAndOffset<CoffGroupSym>(const CVSymbol &sym) { 144 CoffGroupSym record = createRecord<CoffGroupSym>(sym); 145 return {record.Segment, record.Offset}; 146 } 147 148 template <> SegmentOffset GetSegmentAndOffset<DataSym>(const CVSymbol &sym) { 149 DataSym record = createRecord<DataSym>(sym); 150 return {record.Segment, record.DataOffset}; 151 } 152 153 template <> 154 SegmentOffset GetSegmentAndOffset<ThreadLocalDataSym>(const CVSymbol &sym) { 155 ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym); 156 return {record.Segment, record.DataOffset}; 157 } 158 159 SegmentOffset 160 lldb_private::npdb::GetSegmentAndOffset(const llvm::codeview::CVSymbol &sym) { 161 switch (sym.kind()) { 162 case S_GPROC32: 163 case S_LPROC32: 164 case S_GPROC32_ID: 165 case S_LPROC32_ID: 166 case S_LPROC32_DPC: 167 case S_LPROC32_DPC_ID: 168 return ::GetSegmentAndOffset<ProcSym>(sym); 169 case S_THUNK32: 170 return ::GetSegmentAndOffset<Thunk32Sym>(sym); 171 break; 172 case S_TRAMPOLINE: 173 return ::GetSegmentAndOffset<TrampolineSym>(sym); 174 break; 175 case S_COFFGROUP: 176 return ::GetSegmentAndOffset<CoffGroupSym>(sym); 177 break; 178 case S_BLOCK32: 179 return ::GetSegmentAndOffset<BlockSym>(sym); 180 break; 181 case S_LABEL32: 182 return ::GetSegmentAndOffset<LabelSym>(sym); 183 break; 184 case S_CALLSITEINFO: 185 return ::GetSegmentAndOffset<CallSiteInfoSym>(sym); 186 break; 187 case S_HEAPALLOCSITE: 188 return ::GetSegmentAndOffset<HeapAllocationSiteSym>(sym); 189 break; 190 case S_LDATA32: 191 case S_GDATA32: 192 case S_LMANDATA: 193 case S_GMANDATA: 194 return ::GetSegmentAndOffset<DataSym>(sym); 195 break; 196 case S_LTHREAD32: 197 case S_GTHREAD32: 198 return ::GetSegmentAndOffset<ThreadLocalDataSym>(sym); 199 break; 200 default: 201 lldbassert(false && "Record does not have a segment/offset!"); 202 } 203 return {0, 0}; 204 } 205 206 template <typename RecordT> 207 SegmentOffsetLength GetSegmentOffsetAndLength(const CVSymbol &sym) { 208 RecordT record = createRecord<RecordT>(sym); 209 return {record.Segment, record.CodeOffset, record.CodeSize}; 210 } 211 212 template <> 213 SegmentOffsetLength 214 GetSegmentOffsetAndLength<TrampolineSym>(const CVSymbol &sym) { 215 TrampolineSym record = createRecord<TrampolineSym>(sym); 216 return {record.ThunkSection, record.ThunkOffset, record.Size}; 217 } 218 219 template <> 220 SegmentOffsetLength GetSegmentOffsetAndLength<Thunk32Sym>(const CVSymbol &sym) { 221 Thunk32Sym record = createRecord<Thunk32Sym>(sym); 222 return SegmentOffsetLength{record.Segment, record.Offset, record.Length}; 223 } 224 225 template <> 226 SegmentOffsetLength 227 GetSegmentOffsetAndLength<CoffGroupSym>(const CVSymbol &sym) { 228 CoffGroupSym record = createRecord<CoffGroupSym>(sym); 229 return SegmentOffsetLength{record.Segment, record.Offset, record.Size}; 230 } 231 232 SegmentOffsetLength lldb_private::npdb::GetSegmentOffsetAndLength( 233 const llvm::codeview::CVSymbol &sym) { 234 switch (sym.kind()) { 235 case S_GPROC32: 236 case S_LPROC32: 237 case S_GPROC32_ID: 238 case S_LPROC32_ID: 239 case S_LPROC32_DPC: 240 case S_LPROC32_DPC_ID: 241 return ::GetSegmentOffsetAndLength<ProcSym>(sym); 242 case S_THUNK32: 243 return ::GetSegmentOffsetAndLength<Thunk32Sym>(sym); 244 break; 245 case S_TRAMPOLINE: 246 return ::GetSegmentOffsetAndLength<TrampolineSym>(sym); 247 break; 248 case S_COFFGROUP: 249 return ::GetSegmentOffsetAndLength<CoffGroupSym>(sym); 250 break; 251 case S_BLOCK32: 252 return ::GetSegmentOffsetAndLength<BlockSym>(sym); 253 break; 254 default: 255 lldbassert(false && "Record does not have a segment/offset/length triple!"); 256 } 257 return {0, 0, 0}; 258 } 259