1 //===-- DWARFDIE.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 "DWARFDIE.h" 11 12 #include "DWARFASTParser.h" 13 #include "DWARFCompileUnit.h" 14 #include "DWARFDIECollection.h" 15 #include "DWARFDebugAbbrev.h" 16 #include "DWARFDebugAranges.h" 17 #include "DWARFDebugInfo.h" 18 #include "DWARFDebugInfoEntry.h" 19 #include "DWARFDebugRanges.h" 20 #include "DWARFDeclContext.h" 21 #include "DWARFFormValue.h" 22 #include "SymbolFileDWARF.h" 23 24 #include "lldb/Core/Module.h" 25 #include "lldb/Symbol/ObjectFile.h" 26 #include "lldb/Symbol/Type.h" 27 #include "lldb/Symbol/TypeSystem.h" 28 29 using namespace lldb_private; 30 31 DIERef DWARFDIE::GetDIERef() const { 32 if (!IsValid()) 33 return DIERef(); 34 35 dw_offset_t cu_offset = m_cu->GetOffset(); 36 if (m_cu->GetBaseObjOffset() != DW_INVALID_OFFSET) 37 cu_offset = m_cu->GetBaseObjOffset(); 38 return DIERef(cu_offset, m_die->GetOffset()); 39 } 40 41 dw_tag_t DWARFDIE::Tag() const { 42 if (m_die) 43 return m_die->Tag(); 44 else 45 return 0; 46 } 47 48 const char *DWARFDIE::GetTagAsCString() const { 49 return lldb_private::DW_TAG_value_to_name(Tag()); 50 } 51 52 DWARFDIE 53 DWARFDIE::GetParent() const { 54 if (IsValid()) 55 return DWARFDIE(m_cu, m_die->GetParent()); 56 else 57 return DWARFDIE(); 58 } 59 60 DWARFDIE 61 DWARFDIE::GetFirstChild() const { 62 if (IsValid()) 63 return DWARFDIE(m_cu, m_die->GetFirstChild()); 64 else 65 return DWARFDIE(); 66 } 67 68 DWARFDIE 69 DWARFDIE::GetSibling() const { 70 if (IsValid()) 71 return DWARFDIE(m_cu, m_die->GetSibling()); 72 else 73 return DWARFDIE(); 74 } 75 76 DWARFDIE 77 DWARFDIE::GetReferencedDIE(const dw_attr_t attr) const { 78 const dw_offset_t die_offset = 79 GetAttributeValueAsReference(attr, DW_INVALID_OFFSET); 80 if (die_offset != DW_INVALID_OFFSET) 81 return GetDIE(die_offset); 82 else 83 return DWARFDIE(); 84 } 85 86 DWARFDIE 87 DWARFDIE::GetDIE(dw_offset_t die_offset) const { 88 if (IsValid()) 89 return m_cu->GetDIE(die_offset); 90 else 91 return DWARFDIE(); 92 } 93 94 const char *DWARFDIE::GetAttributeValueAsString(const dw_attr_t attr, 95 const char *fail_value) const { 96 if (IsValid()) 97 return m_die->GetAttributeValueAsString(GetDWARF(), GetCU(), attr, 98 fail_value); 99 else 100 return fail_value; 101 } 102 103 uint64_t DWARFDIE::GetAttributeValueAsUnsigned(const dw_attr_t attr, 104 uint64_t fail_value) const { 105 if (IsValid()) 106 return m_die->GetAttributeValueAsUnsigned(GetDWARF(), GetCU(), attr, 107 fail_value); 108 else 109 return fail_value; 110 } 111 112 int64_t DWARFDIE::GetAttributeValueAsSigned(const dw_attr_t attr, 113 int64_t fail_value) const { 114 if (IsValid()) 115 return m_die->GetAttributeValueAsSigned(GetDWARF(), GetCU(), attr, 116 fail_value); 117 else 118 return fail_value; 119 } 120 121 DWARFDIE 122 DWARFDIE::GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const { 123 if (IsValid()) { 124 DWARFCompileUnit *cu = GetCU(); 125 SymbolFileDWARF *dwarf = cu->GetSymbolFileDWARF(); 126 const bool check_specification_or_abstract_origin = true; 127 DWARFFormValue form_value; 128 if (m_die->GetAttributeValue(dwarf, cu, attr, form_value, nullptr, 129 check_specification_or_abstract_origin)) 130 return dwarf->GetDIE(DIERef(form_value)); 131 } 132 return DWARFDIE(); 133 } 134 135 uint64_t DWARFDIE::GetAttributeValueAsReference(const dw_attr_t attr, 136 uint64_t fail_value) const { 137 if (IsValid()) 138 return m_die->GetAttributeValueAsReference(GetDWARF(), GetCU(), attr, 139 fail_value); 140 else 141 return fail_value; 142 } 143 144 uint64_t DWARFDIE::GetAttributeValueAsAddress(const dw_attr_t attr, 145 uint64_t fail_value) const { 146 if (IsValid()) 147 return m_die->GetAttributeValueAsAddress(GetDWARF(), GetCU(), attr, 148 fail_value); 149 else 150 return fail_value; 151 } 152 153 DWARFDIE 154 DWARFDIE::LookupDeepestBlock(lldb::addr_t file_addr) const { 155 if (IsValid()) { 156 SymbolFileDWARF *dwarf = GetDWARF(); 157 DWARFCompileUnit *cu = GetCU(); 158 DWARFDebugInfoEntry *function_die = nullptr; 159 DWARFDebugInfoEntry *block_die = nullptr; 160 if (m_die->LookupAddress(file_addr, dwarf, cu, &function_die, &block_die)) { 161 if (block_die && block_die != function_die) { 162 if (cu->ContainsDIEOffset(block_die->GetOffset())) 163 return DWARFDIE(cu, block_die); 164 else 165 return DWARFDIE(dwarf->DebugInfo()->GetCompileUnit( 166 DIERef(cu->GetOffset(), block_die->GetOffset())), 167 block_die); 168 } 169 } 170 } 171 return DWARFDIE(); 172 } 173 174 lldb::user_id_t DWARFDIE::GetID() const { 175 return GetDIERef().GetUID(GetDWARF()); 176 } 177 178 const char *DWARFDIE::GetName() const { 179 if (IsValid()) 180 return m_die->GetName(GetDWARF(), m_cu); 181 else 182 return nullptr; 183 } 184 185 const char *DWARFDIE::GetMangledName() const { 186 if (IsValid()) 187 return m_die->GetMangledName(GetDWARF(), m_cu); 188 else 189 return nullptr; 190 } 191 192 const char *DWARFDIE::GetPubname() const { 193 if (IsValid()) 194 return m_die->GetPubname(GetDWARF(), m_cu); 195 else 196 return nullptr; 197 } 198 199 const char *DWARFDIE::GetQualifiedName(std::string &storage) const { 200 if (IsValid()) 201 return m_die->GetQualifiedName(GetDWARF(), m_cu, storage); 202 else 203 return nullptr; 204 } 205 206 lldb::LanguageType DWARFDIE::GetLanguage() const { 207 if (IsValid()) 208 return m_cu->GetLanguageType(); 209 else 210 return lldb::eLanguageTypeUnknown; 211 } 212 213 lldb::ModuleSP DWARFDIE::GetModule() const { 214 SymbolFileDWARF *dwarf = GetDWARF(); 215 if (dwarf) 216 return dwarf->GetObjectFile()->GetModule(); 217 else 218 return lldb::ModuleSP(); 219 } 220 221 lldb_private::CompileUnit *DWARFDIE::GetLLDBCompileUnit() const { 222 if (IsValid()) 223 return GetDWARF()->GetCompUnitForDWARFCompUnit(GetCU()); 224 else 225 return nullptr; 226 } 227 228 lldb_private::Type *DWARFDIE::ResolveType() const { 229 if (IsValid()) 230 return GetDWARF()->ResolveType(*this, true); 231 else 232 return nullptr; 233 } 234 235 lldb_private::Type *DWARFDIE::ResolveTypeUID(const DIERef &die_ref) const { 236 SymbolFileDWARF *dwarf = GetDWARF(); 237 if (dwarf) 238 return dwarf->ResolveTypeUID(dwarf->GetDIE(die_ref), true); 239 else 240 return nullptr; 241 } 242 243 void DWARFDIE::GetDeclContextDIEs(DWARFDIECollection &decl_context_dies) const { 244 if (IsValid()) { 245 DWARFDIE parent_decl_ctx_die = 246 m_die->GetParentDeclContextDIE(GetDWARF(), GetCU()); 247 if (parent_decl_ctx_die && parent_decl_ctx_die.GetDIE() != GetDIE()) { 248 decl_context_dies.Append(parent_decl_ctx_die); 249 parent_decl_ctx_die.GetDeclContextDIEs(decl_context_dies); 250 } 251 } 252 } 253 254 void DWARFDIE::GetDWARFDeclContext(DWARFDeclContext &dwarf_decl_ctx) const { 255 if (IsValid()) { 256 dwarf_decl_ctx.SetLanguage(GetLanguage()); 257 m_die->GetDWARFDeclContext(GetDWARF(), GetCU(), dwarf_decl_ctx); 258 } else { 259 dwarf_decl_ctx.Clear(); 260 } 261 } 262 263 void DWARFDIE::GetDWOContext(std::vector<CompilerContext> &context) const { 264 const dw_tag_t tag = Tag(); 265 if (tag == DW_TAG_compile_unit) 266 return; 267 DWARFDIE parent = GetParent(); 268 if (parent) 269 parent.GetDWOContext(context); 270 switch (tag) { 271 case DW_TAG_module: 272 context.push_back( 273 CompilerContext(CompilerContextKind::Module, ConstString(GetName()))); 274 break; 275 case DW_TAG_namespace: 276 context.push_back(CompilerContext(CompilerContextKind::Namespace, 277 ConstString(GetName()))); 278 break; 279 case DW_TAG_structure_type: 280 context.push_back(CompilerContext(CompilerContextKind::Structure, 281 ConstString(GetName()))); 282 break; 283 case DW_TAG_union_type: 284 context.push_back( 285 CompilerContext(CompilerContextKind::Union, ConstString(GetName()))); 286 break; 287 case DW_TAG_class_type: 288 context.push_back( 289 CompilerContext(CompilerContextKind::Class, ConstString(GetName()))); 290 break; 291 case DW_TAG_enumeration_type: 292 context.push_back(CompilerContext(CompilerContextKind::Enumeration, 293 ConstString(GetName()))); 294 break; 295 case DW_TAG_subprogram: 296 context.push_back(CompilerContext(CompilerContextKind::Function, 297 ConstString(GetPubname()))); 298 break; 299 case DW_TAG_variable: 300 context.push_back(CompilerContext(CompilerContextKind::Variable, 301 ConstString(GetPubname()))); 302 break; 303 case DW_TAG_typedef: 304 context.push_back( 305 CompilerContext(CompilerContextKind::Typedef, ConstString(GetName()))); 306 break; 307 default: 308 break; 309 } 310 } 311 312 DWARFDIE 313 DWARFDIE::GetParentDeclContextDIE() const { 314 if (IsValid()) 315 return m_die->GetParentDeclContextDIE(GetDWARF(), m_cu); 316 else 317 return DWARFDIE(); 318 } 319 320 dw_offset_t DWARFDIE::GetOffset() const { 321 if (IsValid()) 322 return m_die->GetOffset(); 323 else 324 return DW_INVALID_OFFSET; 325 } 326 327 dw_offset_t DWARFDIE::GetCompileUnitRelativeOffset() const { 328 if (IsValid()) 329 return m_die->GetOffset() - m_cu->GetOffset(); 330 else 331 return DW_INVALID_OFFSET; 332 } 333 334 SymbolFileDWARF *DWARFDIE::GetDWARF() const { 335 if (m_cu) 336 return m_cu->GetSymbolFileDWARF(); 337 else 338 return nullptr; 339 } 340 341 lldb_private::TypeSystem *DWARFDIE::GetTypeSystem() const { 342 if (m_cu) 343 return m_cu->GetTypeSystem(); 344 else 345 return nullptr; 346 } 347 348 DWARFASTParser *DWARFDIE::GetDWARFParser() const { 349 lldb_private::TypeSystem *type_system = GetTypeSystem(); 350 if (type_system) 351 return type_system->GetDWARFParser(); 352 else 353 return nullptr; 354 } 355 356 bool DWARFDIE::IsStructOrClass() const { 357 const dw_tag_t tag = Tag(); 358 return tag == DW_TAG_class_type || tag == DW_TAG_structure_type; 359 } 360 361 DWARFDIE 362 DWARFDIE::GetContainingDWOModuleDIE() const { 363 if (IsValid()) { 364 DWARFDIE top_module_die; 365 // Now make sure this DIE is scoped in a DW_TAG_module tag and return true 366 // if so 367 for (DWARFDIE parent = GetParent(); parent.IsValid(); 368 parent = parent.GetParent()) { 369 const dw_tag_t tag = parent.Tag(); 370 if (tag == DW_TAG_module) 371 top_module_die = parent; 372 else if (tag == DW_TAG_compile_unit) 373 break; 374 } 375 376 return top_module_die; 377 } 378 return DWARFDIE(); 379 } 380 381 lldb::ModuleSP DWARFDIE::GetContainingDWOModule() const { 382 if (IsValid()) { 383 DWARFDIE dwo_module_die = GetContainingDWOModuleDIE(); 384 385 if (dwo_module_die) { 386 const char *module_name = dwo_module_die.GetName(); 387 if (module_name) 388 return GetDWARF()->GetDWOModule(lldb_private::ConstString(module_name)); 389 } 390 } 391 return lldb::ModuleSP(); 392 } 393 394 bool DWARFDIE::HasChildren() const { 395 if (m_die) 396 return m_die->HasChildren(); 397 else 398 return false; 399 } 400 401 bool DWARFDIE::Supports_DW_AT_APPLE_objc_complete_type() const { 402 if (IsValid()) 403 return GetDWARF()->Supports_DW_AT_APPLE_objc_complete_type(m_cu); 404 else 405 return false; 406 } 407 408 size_t DWARFDIE::GetAttributes(DWARFAttributes &attributes, 409 uint32_t depth) const { 410 if (IsValid()) { 411 return m_die->GetAttributes(m_cu, m_cu->GetFixedFormSizes(), attributes, 412 depth); 413 } 414 if (depth == 0) 415 attributes.Clear(); 416 return 0; 417 } 418 419 bool DWARFDIE::GetDIENamesAndRanges( 420 const char *&name, const char *&mangled, DWARFRangeList &ranges, 421 int &decl_file, int &decl_line, int &decl_column, int &call_file, 422 int &call_line, int &call_column, 423 lldb_private::DWARFExpression *frame_base) const { 424 if (IsValid()) { 425 return m_die->GetDIENamesAndRanges( 426 GetDWARF(), GetCU(), name, mangled, ranges, decl_file, decl_line, 427 decl_column, call_file, call_line, call_column, frame_base); 428 } else 429 return false; 430 } 431 432 void DWARFDIE::Dump(lldb_private::Stream *s, 433 const uint32_t recurse_depth) const { 434 if (s && IsValid()) 435 m_die->Dump(GetDWARF(), GetCU(), *s, recurse_depth); 436 } 437 438 CompilerDecl DWARFDIE::GetDecl() const { 439 DWARFASTParser *dwarf_ast = GetDWARFParser(); 440 if (dwarf_ast) 441 return dwarf_ast->GetDeclForUIDFromDWARF(*this); 442 else 443 return CompilerDecl(); 444 } 445 446 CompilerDeclContext DWARFDIE::GetDeclContext() const { 447 DWARFASTParser *dwarf_ast = GetDWARFParser(); 448 if (dwarf_ast) 449 return dwarf_ast->GetDeclContextForUIDFromDWARF(*this); 450 else 451 return CompilerDeclContext(); 452 } 453 454 CompilerDeclContext DWARFDIE::GetContainingDeclContext() const { 455 DWARFASTParser *dwarf_ast = GetDWARFParser(); 456 if (dwarf_ast) 457 return dwarf_ast->GetDeclContextContainingUIDFromDWARF(*this); 458 else 459 return CompilerDeclContext(); 460 } 461 462 bool operator==(const DWARFDIE &lhs, const DWARFDIE &rhs) { 463 return lhs.GetDIE() == rhs.GetDIE() && lhs.GetCU() == rhs.GetCU(); 464 } 465 466 bool operator!=(const DWARFDIE &lhs, const DWARFDIE &rhs) { 467 return lhs.GetDIE() != rhs.GetDIE() || lhs.GetCU() != rhs.GetCU(); 468 } 469