DWARFDebugInfoEntry.cpp revision 321369
1254721Semaste//===-- DWARFDebugInfoEntry.cpp ---------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include "DWARFDebugInfoEntry.h" 11254721Semaste 12254721Semaste#include <assert.h> 13254721Semaste 14254721Semaste#include <algorithm> 15254721Semaste 16254721Semaste#include "lldb/Core/Module.h" 17254721Semaste#include "lldb/Expression/DWARFExpression.h" 18254721Semaste#include "lldb/Symbol/ObjectFile.h" 19321369Sdim#include "lldb/Utility/Stream.h" 20254721Semaste 21254721Semaste#include "DWARFCompileUnit.h" 22314564Sdim#include "DWARFDIECollection.h" 23254721Semaste#include "DWARFDebugAbbrev.h" 24254721Semaste#include "DWARFDebugAranges.h" 25254721Semaste#include "DWARFDebugInfo.h" 26314564Sdim#include "DWARFDebugRanges.h" 27254721Semaste#include "DWARFDeclContext.h" 28254721Semaste#include "DWARFFormValue.h" 29296417Sdim#include "SymbolFileDWARF.h" 30296417Sdim#include "SymbolFileDWARFDwo.h" 31254721Semaste 32254721Semasteusing namespace lldb_private; 33254721Semasteusing namespace std; 34254721Semasteextern int g_verbose; 35254721Semaste 36314564Sdimbool DWARFDebugInfoEntry::FastExtract( 37314564Sdim const DWARFDataExtractor &debug_info_data, const DWARFCompileUnit *cu, 38314564Sdim const DWARFFormValue::FixedFormSizes &fixed_form_sizes, 39314564Sdim lldb::offset_t *offset_ptr) { 40314564Sdim m_offset = *offset_ptr; 41314564Sdim m_parent_idx = 0; 42314564Sdim m_sibling_idx = 0; 43314564Sdim m_empty_children = false; 44314564Sdim const uint64_t abbr_idx = debug_info_data.GetULEB128(offset_ptr); 45314564Sdim assert(abbr_idx < (1 << DIE_ABBR_IDX_BITSIZE)); 46314564Sdim m_abbr_idx = abbr_idx; 47254721Semaste 48314564Sdim // assert (fixed_form_sizes); // For best performance this should be 49314564Sdim // specified! 50254721Semaste 51314564Sdim if (m_abbr_idx) { 52314564Sdim lldb::offset_t offset = *offset_ptr; 53254721Semaste 54314564Sdim const DWARFAbbreviationDeclaration *abbrevDecl = 55314564Sdim cu->GetAbbreviations()->GetAbbreviationDeclaration(m_abbr_idx); 56254721Semaste 57314564Sdim if (abbrevDecl == NULL) { 58314564Sdim cu->GetSymbolFileDWARF()->GetObjectFile()->GetModule()->ReportError( 59314564Sdim "{0x%8.8x}: invalid abbreviation code %u, please file a bug and " 60314564Sdim "attach the file at the start of this error message", 61314564Sdim m_offset, (unsigned)abbr_idx); 62314564Sdim // WE can't parse anymore if the DWARF is borked... 63314564Sdim *offset_ptr = UINT32_MAX; 64314564Sdim return false; 65314564Sdim } 66314564Sdim m_tag = abbrevDecl->Tag(); 67314564Sdim m_has_children = abbrevDecl->HasChildren(); 68314564Sdim // Skip all data in the .debug_info for the attributes 69314564Sdim const uint32_t numAttributes = abbrevDecl->NumAttributes(); 70314564Sdim uint32_t i; 71314564Sdim dw_form_t form; 72314564Sdim for (i = 0; i < numAttributes; ++i) { 73314564Sdim form = abbrevDecl->GetFormByIndexUnchecked(i); 74254721Semaste 75314564Sdim const uint8_t fixed_skip_size = fixed_form_sizes.GetSize(form); 76314564Sdim if (fixed_skip_size) 77314564Sdim offset += fixed_skip_size; 78314564Sdim else { 79314564Sdim bool form_is_indirect = false; 80314564Sdim do { 81314564Sdim form_is_indirect = false; 82314564Sdim uint32_t form_size = 0; 83314564Sdim switch (form) { 84314564Sdim // Blocks if inlined data that have a length field and the data bytes 85314564Sdim // inlined in the .debug_info 86314564Sdim case DW_FORM_exprloc: 87314564Sdim case DW_FORM_block: 88314564Sdim form_size = debug_info_data.GetULEB128(&offset); 89314564Sdim break; 90314564Sdim case DW_FORM_block1: 91314564Sdim form_size = debug_info_data.GetU8_unchecked(&offset); 92314564Sdim break; 93314564Sdim case DW_FORM_block2: 94314564Sdim form_size = debug_info_data.GetU16_unchecked(&offset); 95314564Sdim break; 96314564Sdim case DW_FORM_block4: 97314564Sdim form_size = debug_info_data.GetU32_unchecked(&offset); 98314564Sdim break; 99254721Semaste 100314564Sdim // Inlined NULL terminated C-strings 101314564Sdim case DW_FORM_string: 102314564Sdim debug_info_data.GetCStr(&offset); 103314564Sdim break; 104254721Semaste 105314564Sdim // Compile unit address sized values 106314564Sdim case DW_FORM_addr: 107314564Sdim form_size = cu->GetAddressByteSize(); 108314564Sdim break; 109314564Sdim case DW_FORM_ref_addr: 110314564Sdim if (cu->GetVersion() <= 2) 111314564Sdim form_size = cu->GetAddressByteSize(); 112314564Sdim else 113314564Sdim form_size = cu->IsDWARF64() ? 8 : 4; 114314564Sdim break; 115254721Semaste 116314564Sdim // 0 sized form 117314564Sdim case DW_FORM_flag_present: 118314564Sdim form_size = 0; 119314564Sdim break; 120254721Semaste 121314564Sdim // 1 byte values 122314564Sdim case DW_FORM_data1: 123314564Sdim case DW_FORM_flag: 124314564Sdim case DW_FORM_ref1: 125314564Sdim form_size = 1; 126314564Sdim break; 127254721Semaste 128314564Sdim // 2 byte values 129314564Sdim case DW_FORM_data2: 130314564Sdim case DW_FORM_ref2: 131314564Sdim form_size = 2; 132314564Sdim break; 133254721Semaste 134314564Sdim // 4 byte values 135314564Sdim case DW_FORM_data4: 136314564Sdim case DW_FORM_ref4: 137314564Sdim form_size = 4; 138314564Sdim break; 139254721Semaste 140314564Sdim // 8 byte values 141314564Sdim case DW_FORM_data8: 142314564Sdim case DW_FORM_ref8: 143314564Sdim case DW_FORM_ref_sig8: 144314564Sdim form_size = 8; 145314564Sdim break; 146254721Semaste 147314564Sdim // signed or unsigned LEB 128 values 148314564Sdim case DW_FORM_sdata: 149314564Sdim case DW_FORM_udata: 150314564Sdim case DW_FORM_ref_udata: 151314564Sdim case DW_FORM_GNU_addr_index: 152314564Sdim case DW_FORM_GNU_str_index: 153314564Sdim debug_info_data.Skip_LEB128(&offset); 154314564Sdim break; 155254721Semaste 156314564Sdim case DW_FORM_indirect: 157314564Sdim form_is_indirect = true; 158314564Sdim form = debug_info_data.GetULEB128(&offset); 159314564Sdim break; 160314564Sdim 161314564Sdim case DW_FORM_strp: 162314564Sdim case DW_FORM_sec_offset: 163314564Sdim if (cu->IsDWARF64()) 164314564Sdim debug_info_data.GetU64(offset_ptr); 165314564Sdim else 166314564Sdim debug_info_data.GetU32(offset_ptr); 167314564Sdim break; 168314564Sdim 169314564Sdim default: 170314564Sdim *offset_ptr = m_offset; 171314564Sdim return false; 172314564Sdim } 173314564Sdim offset += form_size; 174314564Sdim 175314564Sdim } while (form_is_indirect); 176314564Sdim } 177254721Semaste } 178314564Sdim *offset_ptr = offset; 179314564Sdim return true; 180314564Sdim } else { 181314564Sdim m_tag = 0; 182314564Sdim m_has_children = false; 183314564Sdim return true; // NULL debug tag entry 184314564Sdim } 185254721Semaste 186314564Sdim return false; 187254721Semaste} 188254721Semaste 189254721Semaste//---------------------------------------------------------------------- 190254721Semaste// Extract 191254721Semaste// 192254721Semaste// Extract a debug info entry for a given compile unit from the 193254721Semaste// .debug_info and .debug_abbrev data within the SymbolFileDWARF class 194254721Semaste// starting at the given offset 195254721Semaste//---------------------------------------------------------------------- 196314564Sdimbool DWARFDebugInfoEntry::Extract(SymbolFileDWARF *dwarf2Data, 197314564Sdim const DWARFCompileUnit *cu, 198314564Sdim lldb::offset_t *offset_ptr) { 199314564Sdim const DWARFDataExtractor &debug_info_data = dwarf2Data->get_debug_info_data(); 200314564Sdim // const DWARFDataExtractor& debug_str_data = 201314564Sdim // dwarf2Data->get_debug_str_data(); 202314564Sdim const uint32_t cu_end_offset = cu->GetNextCompileUnitOffset(); 203314564Sdim lldb::offset_t offset = *offset_ptr; 204314564Sdim // if (offset >= cu_end_offset) 205321369Sdim // Log::Status("DIE at offset 0x%8.8x is beyond the end of the current 206314564Sdim // compile unit (0x%8.8x)", m_offset, cu_end_offset); 207314564Sdim if ((offset < cu_end_offset) && debug_info_data.ValidOffset(offset)) { 208314564Sdim m_offset = offset; 209254721Semaste 210314564Sdim const uint64_t abbr_idx = debug_info_data.GetULEB128(&offset); 211314564Sdim assert(abbr_idx < (1 << DIE_ABBR_IDX_BITSIZE)); 212314564Sdim m_abbr_idx = abbr_idx; 213314564Sdim if (abbr_idx) { 214314564Sdim const DWARFAbbreviationDeclaration *abbrevDecl = 215314564Sdim cu->GetAbbreviations()->GetAbbreviationDeclaration(abbr_idx); 216254721Semaste 217314564Sdim if (abbrevDecl) { 218314564Sdim m_tag = abbrevDecl->Tag(); 219314564Sdim m_has_children = abbrevDecl->HasChildren(); 220254721Semaste 221314564Sdim bool isCompileUnitTag = m_tag == DW_TAG_compile_unit; 222314564Sdim if (cu && isCompileUnitTag) 223314564Sdim const_cast<DWARFCompileUnit *>(cu)->SetBaseAddress(0); 224254721Semaste 225314564Sdim // Skip all data in the .debug_info for the attributes 226314564Sdim const uint32_t numAttributes = abbrevDecl->NumAttributes(); 227314564Sdim uint32_t i; 228314564Sdim dw_attr_t attr; 229314564Sdim dw_form_t form; 230314564Sdim for (i = 0; i < numAttributes; ++i) { 231314564Sdim abbrevDecl->GetAttrAndFormByIndexUnchecked(i, attr, form); 232254721Semaste 233314564Sdim if (isCompileUnitTag && 234314564Sdim ((attr == DW_AT_entry_pc) || (attr == DW_AT_low_pc))) { 235314564Sdim DWARFFormValue form_value(cu, form); 236314564Sdim if (form_value.ExtractValue(debug_info_data, &offset)) { 237314564Sdim if (attr == DW_AT_low_pc || attr == DW_AT_entry_pc) 238314564Sdim const_cast<DWARFCompileUnit *>(cu)->SetBaseAddress( 239314564Sdim form_value.Address()); 240314564Sdim } 241314564Sdim } else { 242314564Sdim bool form_is_indirect = false; 243314564Sdim do { 244314564Sdim form_is_indirect = false; 245314564Sdim uint32_t form_size = 0; 246314564Sdim switch (form) { 247314564Sdim // Blocks if inlined data that have a length field and the data 248314564Sdim // bytes 249314564Sdim // inlined in the .debug_info 250314564Sdim case DW_FORM_exprloc: 251314564Sdim case DW_FORM_block: 252314564Sdim form_size = debug_info_data.GetULEB128(&offset); 253314564Sdim break; 254314564Sdim case DW_FORM_block1: 255314564Sdim form_size = debug_info_data.GetU8(&offset); 256314564Sdim break; 257314564Sdim case DW_FORM_block2: 258314564Sdim form_size = debug_info_data.GetU16(&offset); 259314564Sdim break; 260314564Sdim case DW_FORM_block4: 261314564Sdim form_size = debug_info_data.GetU32(&offset); 262314564Sdim break; 263254721Semaste 264314564Sdim // Inlined NULL terminated C-strings 265314564Sdim case DW_FORM_string: 266314564Sdim debug_info_data.GetCStr(&offset); 267314564Sdim break; 268254721Semaste 269314564Sdim // Compile unit address sized values 270314564Sdim case DW_FORM_addr: 271314564Sdim form_size = cu->GetAddressByteSize(); 272314564Sdim break; 273314564Sdim case DW_FORM_ref_addr: 274314564Sdim if (cu->GetVersion() <= 2) 275314564Sdim form_size = cu->GetAddressByteSize(); 276314564Sdim else 277314564Sdim form_size = cu->IsDWARF64() ? 8 : 4; 278314564Sdim break; 279254721Semaste 280314564Sdim // 0 sized form 281314564Sdim case DW_FORM_flag_present: 282314564Sdim form_size = 0; 283314564Sdim break; 284254721Semaste 285314564Sdim // 1 byte values 286314564Sdim case DW_FORM_data1: 287314564Sdim case DW_FORM_flag: 288314564Sdim case DW_FORM_ref1: 289314564Sdim form_size = 1; 290314564Sdim break; 291254721Semaste 292314564Sdim // 2 byte values 293314564Sdim case DW_FORM_data2: 294314564Sdim case DW_FORM_ref2: 295314564Sdim form_size = 2; 296314564Sdim break; 297254721Semaste 298314564Sdim // 4 byte values 299314564Sdim case DW_FORM_data4: 300314564Sdim case DW_FORM_ref4: 301314564Sdim form_size = 4; 302314564Sdim break; 303254721Semaste 304314564Sdim // 8 byte values 305314564Sdim case DW_FORM_data8: 306314564Sdim case DW_FORM_ref8: 307314564Sdim case DW_FORM_ref_sig8: 308314564Sdim form_size = 8; 309314564Sdim break; 310254721Semaste 311314564Sdim // signed or unsigned LEB 128 values 312314564Sdim case DW_FORM_sdata: 313314564Sdim case DW_FORM_udata: 314314564Sdim case DW_FORM_ref_udata: 315314564Sdim case DW_FORM_GNU_addr_index: 316314564Sdim case DW_FORM_GNU_str_index: 317314564Sdim debug_info_data.Skip_LEB128(&offset); 318314564Sdim break; 319254721Semaste 320314564Sdim case DW_FORM_indirect: 321314564Sdim form = debug_info_data.GetULEB128(&offset); 322314564Sdim form_is_indirect = true; 323314564Sdim break; 324254721Semaste 325314564Sdim case DW_FORM_strp: 326314564Sdim case DW_FORM_sec_offset: 327314564Sdim if (cu->IsDWARF64()) 328314564Sdim debug_info_data.GetU64(offset_ptr); 329314564Sdim else 330314564Sdim debug_info_data.GetU32(offset_ptr); 331314564Sdim break; 332254721Semaste 333314564Sdim default: 334314564Sdim *offset_ptr = offset; 335314564Sdim return false; 336314564Sdim } 337254721Semaste 338314564Sdim offset += form_size; 339314564Sdim } while (form_is_indirect); 340314564Sdim } 341254721Semaste } 342314564Sdim *offset_ptr = offset; 343314564Sdim return true; 344314564Sdim } 345314564Sdim } else { 346314564Sdim m_tag = 0; 347314564Sdim m_has_children = false; 348314564Sdim *offset_ptr = offset; 349314564Sdim return true; // NULL debug tag entry 350254721Semaste } 351314564Sdim } 352254721Semaste 353314564Sdim return false; 354254721Semaste} 355254721Semaste 356254721Semaste//---------------------------------------------------------------------- 357254721Semaste// DumpAncestry 358254721Semaste// 359254721Semaste// Dumps all of a debug information entries parents up until oldest and 360254721Semaste// all of it's attributes to the specified stream. 361254721Semaste//---------------------------------------------------------------------- 362314564Sdimvoid DWARFDebugInfoEntry::DumpAncestry(SymbolFileDWARF *dwarf2Data, 363314564Sdim const DWARFCompileUnit *cu, 364314564Sdim const DWARFDebugInfoEntry *oldest, 365314564Sdim Stream &s, 366314564Sdim uint32_t recurse_depth) const { 367314564Sdim const DWARFDebugInfoEntry *parent = GetParent(); 368314564Sdim if (parent && parent != oldest) 369314564Sdim parent->DumpAncestry(dwarf2Data, cu, oldest, s, 0); 370314564Sdim Dump(dwarf2Data, cu, s, recurse_depth); 371254721Semaste} 372254721Semaste 373254721Semaste//---------------------------------------------------------------------- 374254721Semaste// GetDIENamesAndRanges 375254721Semaste// 376254721Semaste// Gets the valid address ranges for a given DIE by looking for a 377254721Semaste// DW_AT_low_pc/DW_AT_high_pc pair, DW_AT_entry_pc, or DW_AT_ranges 378254721Semaste// attributes. 379254721Semaste//---------------------------------------------------------------------- 380314564Sdimbool DWARFDebugInfoEntry::GetDIENamesAndRanges( 381314564Sdim SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, const char *&name, 382314564Sdim const char *&mangled, DWARFRangeList &ranges, int &decl_file, 383314564Sdim int &decl_line, int &decl_column, int &call_file, int &call_line, 384314564Sdim int &call_column, DWARFExpression *frame_base) const { 385314564Sdim if (dwarf2Data == nullptr) 386314564Sdim return false; 387254721Semaste 388314564Sdim SymbolFileDWARFDwo *dwo_symbol_file = cu->GetDwoSymbolFile(); 389314564Sdim if (dwo_symbol_file) 390314564Sdim return GetDIENamesAndRanges( 391314564Sdim dwo_symbol_file, dwo_symbol_file->GetCompileUnit(), name, mangled, 392314564Sdim ranges, decl_file, decl_line, decl_column, call_file, call_line, 393314564Sdim call_column, frame_base); 394296417Sdim 395314564Sdim dw_addr_t lo_pc = LLDB_INVALID_ADDRESS; 396314564Sdim dw_addr_t hi_pc = LLDB_INVALID_ADDRESS; 397314564Sdim std::vector<DIERef> die_refs; 398314564Sdim bool set_frame_base_loclist_addr = false; 399254721Semaste 400314564Sdim lldb::offset_t offset; 401314564Sdim const DWARFAbbreviationDeclaration *abbrevDecl = 402314564Sdim GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset); 403258054Semaste 404314564Sdim lldb::ModuleSP module = dwarf2Data->GetObjectFile()->GetModule(); 405254721Semaste 406314564Sdim if (abbrevDecl) { 407314564Sdim const DWARFDataExtractor &debug_info_data = 408314564Sdim dwarf2Data->get_debug_info_data(); 409254721Semaste 410314564Sdim if (!debug_info_data.ValidOffset(offset)) 411314564Sdim return false; 412254721Semaste 413314564Sdim const uint32_t numAttributes = abbrevDecl->NumAttributes(); 414314564Sdim uint32_t i; 415314564Sdim dw_attr_t attr; 416314564Sdim dw_form_t form; 417314564Sdim bool do_offset = false; 418254721Semaste 419314564Sdim for (i = 0; i < numAttributes; ++i) { 420314564Sdim abbrevDecl->GetAttrAndFormByIndexUnchecked(i, attr, form); 421314564Sdim DWARFFormValue form_value(cu, form); 422314564Sdim if (form_value.ExtractValue(debug_info_data, &offset)) { 423314564Sdim switch (attr) { 424314564Sdim case DW_AT_low_pc: 425314564Sdim lo_pc = form_value.Address(); 426254721Semaste 427314564Sdim if (do_offset) 428314564Sdim hi_pc += lo_pc; 429314564Sdim do_offset = false; 430314564Sdim break; 431254721Semaste 432314564Sdim case DW_AT_entry_pc: 433314564Sdim lo_pc = form_value.Address(); 434314564Sdim break; 435254721Semaste 436314564Sdim case DW_AT_high_pc: 437314564Sdim if (form_value.Form() == DW_FORM_addr || 438314564Sdim form_value.Form() == DW_FORM_GNU_addr_index) { 439314564Sdim hi_pc = form_value.Address(); 440314564Sdim } else { 441314564Sdim hi_pc = form_value.Unsigned(); 442314564Sdim if (lo_pc == LLDB_INVALID_ADDRESS) 443314564Sdim do_offset = hi_pc != LLDB_INVALID_ADDRESS; 444314564Sdim else 445314564Sdim hi_pc += lo_pc; // DWARF 4 introduces <offset-from-lo-pc> to save 446314564Sdim // on relocations 447314564Sdim } 448314564Sdim break; 449254721Semaste 450314564Sdim case DW_AT_ranges: { 451314564Sdim const DWARFDebugRanges *debug_ranges = dwarf2Data->DebugRanges(); 452314564Sdim if (debug_ranges) { 453314564Sdim debug_ranges->FindRanges(cu->GetRangesBase(), form_value.Unsigned(), ranges); 454314564Sdim // All DW_AT_ranges are relative to the base address of the 455314564Sdim // compile unit. We add the compile unit base address to make 456314564Sdim // sure all the addresses are properly fixed up. 457314564Sdim ranges.Slide(cu->GetBaseAddress()); 458314564Sdim } else { 459314564Sdim cu->GetSymbolFileDWARF()->GetObjectFile()->GetModule()->ReportError( 460314564Sdim "{0x%8.8x}: DIE has DW_AT_ranges(0x%" PRIx64 461314564Sdim ") attribute yet DWARF has no .debug_ranges, please file a bug " 462314564Sdim "and attach the file at the start of this error message", 463314564Sdim m_offset, form_value.Unsigned()); 464314564Sdim } 465314564Sdim } break; 466254721Semaste 467314564Sdim case DW_AT_name: 468314564Sdim if (name == NULL) 469314564Sdim name = form_value.AsCString(); 470314564Sdim break; 471254721Semaste 472314564Sdim case DW_AT_MIPS_linkage_name: 473314564Sdim case DW_AT_linkage_name: 474314564Sdim if (mangled == NULL) 475314564Sdim mangled = form_value.AsCString(); 476314564Sdim break; 477254721Semaste 478314564Sdim case DW_AT_abstract_origin: 479314564Sdim die_refs.emplace_back(form_value); 480314564Sdim break; 481254721Semaste 482314564Sdim case DW_AT_specification: 483314564Sdim die_refs.emplace_back(form_value); 484314564Sdim break; 485254721Semaste 486314564Sdim case DW_AT_decl_file: 487314564Sdim if (decl_file == 0) 488314564Sdim decl_file = form_value.Unsigned(); 489314564Sdim break; 490254721Semaste 491314564Sdim case DW_AT_decl_line: 492314564Sdim if (decl_line == 0) 493314564Sdim decl_line = form_value.Unsigned(); 494314564Sdim break; 495254721Semaste 496314564Sdim case DW_AT_decl_column: 497314564Sdim if (decl_column == 0) 498314564Sdim decl_column = form_value.Unsigned(); 499314564Sdim break; 500254721Semaste 501314564Sdim case DW_AT_call_file: 502314564Sdim if (call_file == 0) 503314564Sdim call_file = form_value.Unsigned(); 504314564Sdim break; 505254721Semaste 506314564Sdim case DW_AT_call_line: 507314564Sdim if (call_line == 0) 508314564Sdim call_line = form_value.Unsigned(); 509314564Sdim break; 510254721Semaste 511314564Sdim case DW_AT_call_column: 512314564Sdim if (call_column == 0) 513314564Sdim call_column = form_value.Unsigned(); 514314564Sdim break; 515254721Semaste 516314564Sdim case DW_AT_frame_base: 517314564Sdim if (frame_base) { 518314564Sdim if (form_value.BlockData()) { 519314564Sdim uint32_t block_offset = 520314564Sdim form_value.BlockData() - debug_info_data.GetDataStart(); 521314564Sdim uint32_t block_length = form_value.Unsigned(); 522314564Sdim frame_base->SetOpcodeData(module, debug_info_data, block_offset, 523314564Sdim block_length); 524314564Sdim } else { 525314564Sdim const DWARFDataExtractor &debug_loc_data = 526314564Sdim dwarf2Data->get_debug_loc_data(); 527314564Sdim const dw_offset_t debug_loc_offset = form_value.Unsigned(); 528254721Semaste 529314564Sdim size_t loc_list_length = DWARFExpression::LocationListSize( 530314564Sdim cu, debug_loc_data, debug_loc_offset); 531314564Sdim if (loc_list_length > 0) { 532314564Sdim frame_base->SetOpcodeData(module, debug_loc_data, 533314564Sdim debug_loc_offset, loc_list_length); 534314564Sdim if (lo_pc != LLDB_INVALID_ADDRESS) { 535314564Sdim assert(lo_pc >= cu->GetBaseAddress()); 536314564Sdim frame_base->SetLocationListSlide(lo_pc - 537314564Sdim cu->GetBaseAddress()); 538314564Sdim } else { 539314564Sdim set_frame_base_loclist_addr = true; 540254721Semaste } 541314564Sdim } 542254721Semaste } 543314564Sdim } 544314564Sdim break; 545314564Sdim 546314564Sdim default: 547314564Sdim break; 548254721Semaste } 549314564Sdim } 550254721Semaste } 551314564Sdim } 552254721Semaste 553314564Sdim if (ranges.IsEmpty()) { 554314564Sdim if (lo_pc != LLDB_INVALID_ADDRESS) { 555314564Sdim if (hi_pc != LLDB_INVALID_ADDRESS && hi_pc > lo_pc) 556314564Sdim ranges.Append(DWARFRangeList::Entry(lo_pc, hi_pc - lo_pc)); 557314564Sdim else 558314564Sdim ranges.Append(DWARFRangeList::Entry(lo_pc, 0)); 559254721Semaste } 560314564Sdim } 561254721Semaste 562314564Sdim if (set_frame_base_loclist_addr) { 563314564Sdim dw_addr_t lowest_range_pc = ranges.GetMinRangeBase(0); 564314564Sdim assert(lowest_range_pc >= cu->GetBaseAddress()); 565314564Sdim frame_base->SetLocationListSlide(lowest_range_pc - cu->GetBaseAddress()); 566314564Sdim } 567314564Sdim 568314564Sdim if (ranges.IsEmpty() || name == NULL || mangled == NULL) { 569314564Sdim for (const DIERef &die_ref : die_refs) { 570314564Sdim if (die_ref.die_offset != DW_INVALID_OFFSET) { 571314564Sdim DWARFDIE die = dwarf2Data->GetDIE(die_ref); 572314564Sdim if (die) 573314564Sdim die.GetDIE()->GetDIENamesAndRanges( 574314564Sdim die.GetDWARF(), die.GetCU(), name, mangled, ranges, decl_file, 575314564Sdim decl_line, decl_column, call_file, call_line, call_column); 576314564Sdim } 577254721Semaste } 578314564Sdim } 579314564Sdim return !ranges.IsEmpty(); 580254721Semaste} 581254721Semaste 582254721Semaste//---------------------------------------------------------------------- 583254721Semaste// Dump 584254721Semaste// 585254721Semaste// Dumps a debug information entry and all of it's attributes to the 586254721Semaste// specified stream. 587254721Semaste//---------------------------------------------------------------------- 588314564Sdimvoid DWARFDebugInfoEntry::Dump(SymbolFileDWARF *dwarf2Data, 589314564Sdim const DWARFCompileUnit *cu, Stream &s, 590314564Sdim uint32_t recurse_depth) const { 591314564Sdim const DWARFDataExtractor &debug_info_data = dwarf2Data->get_debug_info_data(); 592314564Sdim lldb::offset_t offset = m_offset; 593254721Semaste 594314564Sdim if (debug_info_data.ValidOffset(offset)) { 595314564Sdim dw_uleb128_t abbrCode = debug_info_data.GetULEB128(&offset); 596254721Semaste 597314564Sdim s.Printf("\n0x%8.8x: ", m_offset); 598314564Sdim s.Indent(); 599314564Sdim if (abbrCode != m_abbr_idx) { 600314564Sdim s.Printf("error: DWARF has been modified\n"); 601314564Sdim } else if (abbrCode) { 602314564Sdim const DWARFAbbreviationDeclaration *abbrevDecl = 603314564Sdim cu->GetAbbreviations()->GetAbbreviationDeclaration(abbrCode); 604254721Semaste 605314564Sdim if (abbrevDecl) { 606314564Sdim s.PutCString(DW_TAG_value_to_name(abbrevDecl->Tag())); 607314564Sdim s.Printf(" [%u] %c\n", abbrCode, abbrevDecl->HasChildren() ? '*' : ' '); 608254721Semaste 609314564Sdim // Dump all data in the .debug_info for the attributes 610314564Sdim const uint32_t numAttributes = abbrevDecl->NumAttributes(); 611314564Sdim uint32_t i; 612314564Sdim dw_attr_t attr; 613314564Sdim dw_form_t form; 614314564Sdim for (i = 0; i < numAttributes; ++i) { 615314564Sdim abbrevDecl->GetAttrAndFormByIndexUnchecked(i, attr, form); 616254721Semaste 617314564Sdim DumpAttribute(dwarf2Data, cu, debug_info_data, &offset, s, attr, 618314564Sdim form); 619314564Sdim } 620254721Semaste 621314564Sdim const DWARFDebugInfoEntry *child = GetFirstChild(); 622314564Sdim if (recurse_depth > 0 && child) { 623314564Sdim s.IndentMore(); 624254721Semaste 625314564Sdim while (child) { 626314564Sdim child->Dump(dwarf2Data, cu, s, recurse_depth - 1); 627314564Sdim child = child->GetSibling(); 628314564Sdim } 629314564Sdim s.IndentLess(); 630254721Semaste } 631314564Sdim } else 632314564Sdim s.Printf("Abbreviation code note found in 'debug_abbrev' class for " 633314564Sdim "code: %u\n", 634314564Sdim abbrCode); 635314564Sdim } else { 636314564Sdim s.Printf("NULL\n"); 637254721Semaste } 638314564Sdim } 639254721Semaste} 640254721Semaste 641314564Sdimvoid DWARFDebugInfoEntry::DumpLocation(SymbolFileDWARF *dwarf2Data, 642314564Sdim DWARFCompileUnit *cu, Stream &s) const { 643314564Sdim const DWARFDIE cu_die = cu->GetCompileUnitDIEOnly(); 644314564Sdim const char *cu_name = NULL; 645314564Sdim if (cu_die) 646314564Sdim cu_name = cu_die.GetName(); 647314564Sdim const char *obj_file_name = NULL; 648314564Sdim ObjectFile *obj_file = dwarf2Data->GetObjectFile(); 649314564Sdim if (obj_file) 650314564Sdim obj_file_name = 651314564Sdim obj_file->GetFileSpec().GetFilename().AsCString("<Unknown>"); 652314564Sdim const char *die_name = GetName(dwarf2Data, cu); 653314564Sdim s.Printf("0x%8.8x/0x%8.8x: %-30s (from %s in %s)", cu->GetOffset(), 654314564Sdim GetOffset(), die_name ? die_name : "", cu_name ? cu_name : "<NULL>", 655314564Sdim obj_file_name ? obj_file_name : "<NULL>"); 656254721Semaste} 657254721Semaste 658254721Semaste//---------------------------------------------------------------------- 659254721Semaste// DumpAttribute 660254721Semaste// 661254721Semaste// Dumps a debug information entry attribute along with it's form. Any 662254721Semaste// special display of attributes is done (disassemble location lists, 663254721Semaste// show enumeration values for attributes, etc). 664254721Semaste//---------------------------------------------------------------------- 665314564Sdimvoid DWARFDebugInfoEntry::DumpAttribute( 666314564Sdim SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, 667314564Sdim const DWARFDataExtractor &debug_info_data, lldb::offset_t *offset_ptr, 668314564Sdim Stream &s, dw_attr_t attr, dw_form_t form) { 669314564Sdim bool show_form = s.GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowForm); 670254721Semaste 671321369Sdim s.Printf(" "); 672314564Sdim s.Indent(DW_AT_value_to_name(attr)); 673254721Semaste 674314564Sdim if (show_form) { 675314564Sdim s.Printf("[%s", DW_FORM_value_to_name(form)); 676314564Sdim } 677254721Semaste 678314564Sdim DWARFFormValue form_value(cu, form); 679254721Semaste 680314564Sdim if (!form_value.ExtractValue(debug_info_data, offset_ptr)) 681314564Sdim return; 682254721Semaste 683314564Sdim if (show_form) { 684314564Sdim if (form == DW_FORM_indirect) { 685314564Sdim s.Printf(" [%s]", DW_FORM_value_to_name(form_value.Form())); 686254721Semaste } 687254721Semaste 688314564Sdim s.PutCString("] "); 689314564Sdim } 690254721Semaste 691314564Sdim s.PutCString("( "); 692254721Semaste 693314564Sdim // Check to see if we have any special attribute formatters 694314564Sdim switch (attr) { 695314564Sdim case DW_AT_stmt_list: 696314564Sdim s.Printf("0x%8.8" PRIx64, form_value.Unsigned()); 697314564Sdim break; 698254721Semaste 699314564Sdim case DW_AT_language: 700314564Sdim s.PutCString(DW_LANG_value_to_name(form_value.Unsigned())); 701314564Sdim break; 702254721Semaste 703314564Sdim case DW_AT_encoding: 704314564Sdim s.PutCString(DW_ATE_value_to_name(form_value.Unsigned())); 705314564Sdim break; 706254721Semaste 707314564Sdim case DW_AT_frame_base: 708314564Sdim case DW_AT_location: 709314564Sdim case DW_AT_data_member_location: { 710314564Sdim const uint8_t *blockData = form_value.BlockData(); 711314564Sdim if (blockData) { 712314564Sdim // Location description is inlined in data in the form value 713314564Sdim DWARFDataExtractor locationData(debug_info_data, 714314564Sdim (*offset_ptr) - form_value.Unsigned(), 715314564Sdim form_value.Unsigned()); 716314564Sdim DWARFExpression::PrintDWARFExpression( 717314564Sdim s, locationData, DWARFCompileUnit::GetAddressByteSize(cu), 4, false); 718314564Sdim } else { 719314564Sdim // We have a location list offset as the value that is 720314564Sdim // the offset into the .debug_loc section that describes 721314564Sdim // the value over it's lifetime 722314564Sdim uint64_t debug_loc_offset = form_value.Unsigned(); 723314564Sdim if (dwarf2Data) { 724314564Sdim DWARFExpression::PrintDWARFLocationList( 725314564Sdim s, cu, dwarf2Data->get_debug_loc_data(), debug_loc_offset); 726314564Sdim } 727314564Sdim } 728314564Sdim } break; 729254721Semaste 730314564Sdim case DW_AT_abstract_origin: 731314564Sdim case DW_AT_specification: { 732314564Sdim uint64_t abstract_die_offset = form_value.Reference(); 733314564Sdim form_value.Dump(s); 734314564Sdim // *ostrm_ptr << HEX32 << abstract_die_offset << " ( "; 735314564Sdim GetName(dwarf2Data, cu, abstract_die_offset, s); 736314564Sdim } break; 737254721Semaste 738314564Sdim case DW_AT_type: { 739314564Sdim uint64_t type_die_offset = form_value.Reference(); 740314564Sdim s.PutCString(" ( "); 741314564Sdim AppendTypeName(dwarf2Data, cu, type_die_offset, s); 742314564Sdim s.PutCString(" )"); 743314564Sdim } break; 744254721Semaste 745314564Sdim case DW_AT_ranges: { 746314564Sdim lldb::offset_t ranges_offset = form_value.Unsigned(); 747314564Sdim dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0; 748314564Sdim if (dwarf2Data) 749314564Sdim DWARFDebugRanges::Dump(s, dwarf2Data->get_debug_ranges_data(), 750314564Sdim &ranges_offset, base_addr); 751314564Sdim } break; 752254721Semaste 753314564Sdim default: 754314564Sdim break; 755314564Sdim } 756254721Semaste 757314564Sdim s.PutCString(" )\n"); 758254721Semaste} 759254721Semaste 760254721Semaste//---------------------------------------------------------------------- 761254721Semaste// Get all attribute values for a given DIE, including following any 762254721Semaste// specification or abstract origin attributes and including those in 763254721Semaste// the results. Any duplicate attributes will have the first instance 764254721Semaste// take precedence (this can happen for declaration attributes). 765254721Semaste//---------------------------------------------------------------------- 766314564Sdimsize_t DWARFDebugInfoEntry::GetAttributes( 767314564Sdim const DWARFCompileUnit *cu, DWARFFormValue::FixedFormSizes fixed_form_sizes, 768314564Sdim DWARFAttributes &attributes, uint32_t curr_depth) const { 769314564Sdim SymbolFileDWARF *dwarf2Data = nullptr; 770314564Sdim const DWARFAbbreviationDeclaration *abbrevDecl = nullptr; 771314564Sdim lldb::offset_t offset = 0; 772314564Sdim if (cu) { 773314564Sdim if (m_tag != DW_TAG_compile_unit) { 774314564Sdim SymbolFileDWARFDwo *dwo_symbol_file = cu->GetDwoSymbolFile(); 775314564Sdim if (dwo_symbol_file) 776314564Sdim return GetAttributes(dwo_symbol_file->GetCompileUnit(), 777314564Sdim fixed_form_sizes, attributes, curr_depth); 778296417Sdim } 779296417Sdim 780314564Sdim dwarf2Data = cu->GetSymbolFileDWARF(); 781314564Sdim abbrevDecl = GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset); 782314564Sdim } 783254721Semaste 784314564Sdim if (abbrevDecl) { 785314564Sdim const DWARFDataExtractor &debug_info_data = 786314564Sdim dwarf2Data->get_debug_info_data(); 787254721Semaste 788314564Sdim if (fixed_form_sizes.Empty()) 789314564Sdim fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize( 790314564Sdim cu->GetAddressByteSize(), cu->IsDWARF64()); 791254721Semaste 792314564Sdim const uint32_t num_attributes = abbrevDecl->NumAttributes(); 793314564Sdim uint32_t i; 794314564Sdim dw_attr_t attr; 795314564Sdim dw_form_t form; 796314564Sdim for (i = 0; i < num_attributes; ++i) { 797314564Sdim abbrevDecl->GetAttrAndFormByIndexUnchecked(i, attr, form); 798314564Sdim 799314564Sdim // If we are tracking down DW_AT_specification or DW_AT_abstract_origin 800314564Sdim // attributes, the depth will be non-zero. We need to omit certain 801314564Sdim // attributes that don't make sense. 802314564Sdim switch (attr) { 803314564Sdim case DW_AT_sibling: 804314564Sdim case DW_AT_declaration: 805314564Sdim if (curr_depth > 0) { 806314564Sdim // This attribute doesn't make sense when combined with 807314564Sdim // the DIE that references this DIE. We know a DIE is 808314564Sdim // referencing this DIE because curr_depth is not zero 809314564Sdim break; 810254721Semaste } 811314564Sdim LLVM_FALLTHROUGH; 812314564Sdim default: 813314564Sdim attributes.Append(cu, offset, attr, form); 814314564Sdim break; 815314564Sdim } 816314564Sdim 817314564Sdim if ((attr == DW_AT_specification) || (attr == DW_AT_abstract_origin)) { 818314564Sdim DWARFFormValue form_value(cu, form); 819314564Sdim if (form_value.ExtractValue(debug_info_data, &offset)) { 820314564Sdim dw_offset_t die_offset = form_value.Reference(); 821314564Sdim DWARFDIE spec_die = 822314564Sdim const_cast<DWARFCompileUnit *>(cu)->GetDIE(die_offset); 823314564Sdim if (spec_die) 824314564Sdim spec_die.GetAttributes(attributes, curr_depth + 1); 825314564Sdim } 826314564Sdim } else { 827314564Sdim const uint8_t fixed_skip_size = fixed_form_sizes.GetSize(form); 828314564Sdim if (fixed_skip_size) 829314564Sdim offset += fixed_skip_size; 830314564Sdim else 831314564Sdim DWARFFormValue::SkipValue(form, debug_info_data, &offset, cu); 832314564Sdim } 833254721Semaste } 834314564Sdim } else { 835314564Sdim attributes.Clear(); 836314564Sdim } 837314564Sdim return attributes.Size(); 838254721Semaste} 839254721Semaste 840254721Semaste//---------------------------------------------------------------------- 841254721Semaste// GetAttributeValue 842254721Semaste// 843254721Semaste// Get the value of an attribute and return the .debug_info offset of the 844254721Semaste// attribute if it was properly extracted into form_value, or zero 845254721Semaste// if we fail since an offset of zero is invalid for an attribute (it 846254721Semaste// would be a compile unit header). 847254721Semaste//---------------------------------------------------------------------- 848314564Sdimdw_offset_t DWARFDebugInfoEntry::GetAttributeValue( 849314564Sdim SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, 850314564Sdim const dw_attr_t attr, DWARFFormValue &form_value, 851314564Sdim dw_offset_t *end_attr_offset_ptr, 852314564Sdim bool check_specification_or_abstract_origin) const { 853314564Sdim SymbolFileDWARFDwo *dwo_symbol_file = cu->GetDwoSymbolFile(); 854314564Sdim if (dwo_symbol_file && m_tag != DW_TAG_compile_unit) 855314564Sdim return GetAttributeValue(dwo_symbol_file, dwo_symbol_file->GetCompileUnit(), 856314564Sdim attr, form_value, end_attr_offset_ptr, 857314564Sdim check_specification_or_abstract_origin); 858296417Sdim 859314564Sdim lldb::offset_t offset; 860314564Sdim const DWARFAbbreviationDeclaration *abbrevDecl = 861314564Sdim GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset); 862254721Semaste 863314564Sdim if (abbrevDecl) { 864314564Sdim uint32_t attr_idx = abbrevDecl->FindAttributeIndex(attr); 865254721Semaste 866314564Sdim if (attr_idx != DW_INVALID_INDEX) { 867314564Sdim const DWARFDataExtractor &debug_info_data = 868314564Sdim dwarf2Data->get_debug_info_data(); 869254721Semaste 870314564Sdim uint32_t idx = 0; 871314564Sdim while (idx < attr_idx) 872314564Sdim DWARFFormValue::SkipValue(abbrevDecl->GetFormByIndex(idx++), 873314564Sdim debug_info_data, &offset, cu); 874254721Semaste 875314564Sdim const dw_offset_t attr_offset = offset; 876314564Sdim form_value.SetCompileUnit(cu); 877314564Sdim form_value.SetForm(abbrevDecl->GetFormByIndex(idx)); 878314564Sdim if (form_value.ExtractValue(debug_info_data, &offset)) { 879314564Sdim if (end_attr_offset_ptr) 880314564Sdim *end_attr_offset_ptr = offset; 881314564Sdim return attr_offset; 882314564Sdim } 883254721Semaste } 884314564Sdim } 885254721Semaste 886314564Sdim if (check_specification_or_abstract_origin) { 887314564Sdim if (GetAttributeValue(dwarf2Data, cu, DW_AT_specification, form_value)) { 888314564Sdim DWARFDIE die = 889314564Sdim const_cast<DWARFCompileUnit *>(cu)->GetDIE(form_value.Reference()); 890314564Sdim if (die) { 891314564Sdim dw_offset_t die_offset = die.GetDIE()->GetAttributeValue( 892314564Sdim die.GetDWARF(), die.GetCU(), attr, form_value, end_attr_offset_ptr, 893314564Sdim false); 894314564Sdim if (die_offset) 895314564Sdim return die_offset; 896314564Sdim } 897314564Sdim } 898296417Sdim 899314564Sdim if (GetAttributeValue(dwarf2Data, cu, DW_AT_abstract_origin, form_value)) { 900314564Sdim DWARFDIE die = 901314564Sdim const_cast<DWARFCompileUnit *>(cu)->GetDIE(form_value.Reference()); 902314564Sdim if (die) { 903314564Sdim dw_offset_t die_offset = die.GetDIE()->GetAttributeValue( 904314564Sdim die.GetDWARF(), die.GetCU(), attr, form_value, end_attr_offset_ptr, 905314564Sdim false); 906314564Sdim if (die_offset) 907314564Sdim return die_offset; 908314564Sdim } 909296417Sdim } 910314564Sdim } 911296417Sdim 912314564Sdim if (!dwo_symbol_file) 913314564Sdim return 0; 914296417Sdim 915314564Sdim DWARFCompileUnit *dwo_cu = dwo_symbol_file->GetCompileUnit(); 916314564Sdim if (!dwo_cu) 917314564Sdim return 0; 918296417Sdim 919314564Sdim DWARFDIE dwo_cu_die = dwo_cu->GetCompileUnitDIEOnly(); 920314564Sdim if (!dwo_cu_die.IsValid()) 921314564Sdim return 0; 922296417Sdim 923314564Sdim return dwo_cu_die.GetDIE()->GetAttributeValue( 924314564Sdim dwo_symbol_file, dwo_cu, attr, form_value, end_attr_offset_ptr, 925314564Sdim check_specification_or_abstract_origin); 926254721Semaste} 927254721Semaste 928254721Semaste//---------------------------------------------------------------------- 929254721Semaste// GetAttributeValueAsString 930254721Semaste// 931254721Semaste// Get the value of an attribute as a string return it. The resulting 932254721Semaste// pointer to the string data exists within the supplied SymbolFileDWARF 933254721Semaste// and will only be available as long as the SymbolFileDWARF is still around 934254721Semaste// and it's content doesn't change. 935254721Semaste//---------------------------------------------------------------------- 936314564Sdimconst char *DWARFDebugInfoEntry::GetAttributeValueAsString( 937314564Sdim SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, 938314564Sdim const dw_attr_t attr, const char *fail_value, 939314564Sdim bool check_specification_or_abstract_origin) const { 940314564Sdim DWARFFormValue form_value; 941314564Sdim if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, 942314564Sdim check_specification_or_abstract_origin)) 943314564Sdim return form_value.AsCString(); 944314564Sdim return fail_value; 945254721Semaste} 946254721Semaste 947254721Semaste//---------------------------------------------------------------------- 948254721Semaste// GetAttributeValueAsUnsigned 949254721Semaste// 950254721Semaste// Get the value of an attribute as unsigned and return it. 951254721Semaste//---------------------------------------------------------------------- 952314564Sdimuint64_t DWARFDebugInfoEntry::GetAttributeValueAsUnsigned( 953314564Sdim SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, 954314564Sdim const dw_attr_t attr, uint64_t fail_value, 955314564Sdim bool check_specification_or_abstract_origin) const { 956314564Sdim DWARFFormValue form_value; 957314564Sdim if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, 958314564Sdim check_specification_or_abstract_origin)) 959314564Sdim return form_value.Unsigned(); 960314564Sdim return fail_value; 961254721Semaste} 962254721Semaste 963254721Semaste//---------------------------------------------------------------------- 964254721Semaste// GetAttributeValueAsSigned 965254721Semaste// 966254721Semaste// Get the value of an attribute a signed value and return it. 967254721Semaste//---------------------------------------------------------------------- 968314564Sdimint64_t DWARFDebugInfoEntry::GetAttributeValueAsSigned( 969314564Sdim SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, 970314564Sdim const dw_attr_t attr, int64_t fail_value, 971314564Sdim bool check_specification_or_abstract_origin) const { 972314564Sdim DWARFFormValue form_value; 973314564Sdim if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, 974314564Sdim check_specification_or_abstract_origin)) 975314564Sdim return form_value.Signed(); 976314564Sdim return fail_value; 977254721Semaste} 978254721Semaste 979254721Semaste//---------------------------------------------------------------------- 980254721Semaste// GetAttributeValueAsReference 981254721Semaste// 982254721Semaste// Get the value of an attribute as reference and fix up and compile 983254721Semaste// unit relative offsets as needed. 984254721Semaste//---------------------------------------------------------------------- 985314564Sdimuint64_t DWARFDebugInfoEntry::GetAttributeValueAsReference( 986314564Sdim SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, 987314564Sdim const dw_attr_t attr, uint64_t fail_value, 988314564Sdim bool check_specification_or_abstract_origin) const { 989314564Sdim DWARFFormValue form_value; 990314564Sdim if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, 991314564Sdim check_specification_or_abstract_origin)) 992314564Sdim return form_value.Reference(); 993314564Sdim return fail_value; 994254721Semaste} 995254721Semaste 996314564Sdimuint64_t DWARFDebugInfoEntry::GetAttributeValueAsAddress( 997314564Sdim SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, 998314564Sdim const dw_attr_t attr, uint64_t fail_value, 999314564Sdim bool check_specification_or_abstract_origin) const { 1000314564Sdim DWARFFormValue form_value; 1001314564Sdim if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, 1002314564Sdim check_specification_or_abstract_origin)) 1003314564Sdim return form_value.Address(); 1004314564Sdim return fail_value; 1005296417Sdim} 1006296417Sdim 1007254721Semaste//---------------------------------------------------------------------- 1008254721Semaste// GetAttributeHighPC 1009254721Semaste// 1010254721Semaste// Get the hi_pc, adding hi_pc to lo_pc when specified 1011254721Semaste// as an <offset-from-low-pc>. 1012254721Semaste// 1013254721Semaste// Returns the hi_pc or fail_value. 1014254721Semaste//---------------------------------------------------------------------- 1015314564Sdimdw_addr_t DWARFDebugInfoEntry::GetAttributeHighPC( 1016314564Sdim SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, dw_addr_t lo_pc, 1017314564Sdim uint64_t fail_value, bool check_specification_or_abstract_origin) const { 1018314564Sdim DWARFFormValue form_value; 1019314564Sdim if (GetAttributeValue(dwarf2Data, cu, DW_AT_high_pc, form_value, nullptr, 1020314564Sdim check_specification_or_abstract_origin)) { 1021314564Sdim dw_form_t form = form_value.Form(); 1022314564Sdim if (form == DW_FORM_addr || form == DW_FORM_GNU_addr_index) 1023314564Sdim return form_value.Address(); 1024314564Sdim 1025314564Sdim // DWARF4 can specify the hi_pc as an <offset-from-lowpc> 1026314564Sdim return lo_pc + form_value.Unsigned(); 1027314564Sdim } 1028314564Sdim return fail_value; 1029254721Semaste} 1030254721Semaste 1031254721Semaste//---------------------------------------------------------------------- 1032254721Semaste// GetAttributeAddressRange 1033254721Semaste// 1034254721Semaste// Get the lo_pc and hi_pc, adding hi_pc to lo_pc when specified 1035254721Semaste// as an <offset-from-low-pc>. 1036254721Semaste// 1037254721Semaste// Returns true or sets lo_pc and hi_pc to fail_value. 1038254721Semaste//---------------------------------------------------------------------- 1039314564Sdimbool DWARFDebugInfoEntry::GetAttributeAddressRange( 1040314564Sdim SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, dw_addr_t &lo_pc, 1041314564Sdim dw_addr_t &hi_pc, uint64_t fail_value, 1042314564Sdim bool check_specification_or_abstract_origin) const { 1043314564Sdim lo_pc = GetAttributeValueAsAddress(dwarf2Data, cu, DW_AT_low_pc, fail_value, 1044314564Sdim check_specification_or_abstract_origin); 1045314564Sdim if (lo_pc != fail_value) { 1046314564Sdim hi_pc = GetAttributeHighPC(dwarf2Data, cu, lo_pc, fail_value, 1047314564Sdim check_specification_or_abstract_origin); 1048314564Sdim if (hi_pc != fail_value) 1049314564Sdim return true; 1050314564Sdim } 1051314564Sdim lo_pc = fail_value; 1052314564Sdim hi_pc = fail_value; 1053314564Sdim return false; 1054254721Semaste} 1055276479Sdim 1056314564Sdimsize_t DWARFDebugInfoEntry::GetAttributeAddressRanges( 1057314564Sdim SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, 1058314564Sdim DWARFRangeList &ranges, bool check_hi_lo_pc, 1059314564Sdim bool check_specification_or_abstract_origin) const { 1060314564Sdim ranges.Clear(); 1061314564Sdim 1062314564Sdim dw_offset_t debug_ranges_offset = GetAttributeValueAsUnsigned( 1063314564Sdim dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET, 1064314564Sdim check_specification_or_abstract_origin); 1065314564Sdim if (debug_ranges_offset != DW_INVALID_OFFSET) { 1066314564Sdim DWARFDebugRanges *debug_ranges = dwarf2Data->DebugRanges(); 1067314564Sdim 1068314564Sdim debug_ranges->FindRanges(cu->GetRangesBase(), debug_ranges_offset, ranges); 1069314564Sdim ranges.Slide(cu->GetBaseAddress()); 1070314564Sdim } else if (check_hi_lo_pc) { 1071314564Sdim dw_addr_t lo_pc = LLDB_INVALID_ADDRESS; 1072314564Sdim dw_addr_t hi_pc = LLDB_INVALID_ADDRESS; 1073314564Sdim if (GetAttributeAddressRange(dwarf2Data, cu, lo_pc, hi_pc, 1074314564Sdim LLDB_INVALID_ADDRESS, 1075314564Sdim check_specification_or_abstract_origin)) { 1076314564Sdim if (lo_pc < hi_pc) 1077314564Sdim ranges.Append(DWARFRangeList::Entry(lo_pc, hi_pc - lo_pc)); 1078276479Sdim } 1079314564Sdim } 1080314564Sdim return ranges.GetSize(); 1081276479Sdim} 1082276479Sdim 1083254721Semaste//---------------------------------------------------------------------- 1084254721Semaste// GetName 1085254721Semaste// 1086254721Semaste// Get value of the DW_AT_name attribute and return it if one exists, 1087254721Semaste// else return NULL. 1088254721Semaste//---------------------------------------------------------------------- 1089314564Sdimconst char *DWARFDebugInfoEntry::GetName(SymbolFileDWARF *dwarf2Data, 1090314564Sdim const DWARFCompileUnit *cu) const { 1091314564Sdim return GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, nullptr, true); 1092254721Semaste} 1093254721Semaste 1094254721Semaste//---------------------------------------------------------------------- 1095254721Semaste// GetMangledName 1096254721Semaste// 1097254721Semaste// Get value of the DW_AT_MIPS_linkage_name attribute and return it if 1098254721Semaste// one exists, else return the value of the DW_AT_name attribute 1099254721Semaste//---------------------------------------------------------------------- 1100314564Sdimconst char * 1101314564SdimDWARFDebugInfoEntry::GetMangledName(SymbolFileDWARF *dwarf2Data, 1102314564Sdim const DWARFCompileUnit *cu, 1103314564Sdim bool substitute_name_allowed) const { 1104314564Sdim const char *name = nullptr; 1105254721Semaste 1106314564Sdim name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_MIPS_linkage_name, 1107314564Sdim nullptr, true); 1108314564Sdim if (name) 1109314564Sdim return name; 1110254721Semaste 1111314564Sdim name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_linkage_name, nullptr, 1112314564Sdim true); 1113314564Sdim if (name) 1114314564Sdim return name; 1115254721Semaste 1116314564Sdim if (!substitute_name_allowed) 1117314564Sdim return nullptr; 1118296417Sdim 1119314564Sdim name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, nullptr, true); 1120314564Sdim return name; 1121254721Semaste} 1122254721Semaste 1123254721Semaste//---------------------------------------------------------------------- 1124254721Semaste// GetPubname 1125254721Semaste// 1126254721Semaste// Get value the name for a DIE as it should appear for a 1127254721Semaste// .debug_pubnames or .debug_pubtypes section. 1128254721Semaste//---------------------------------------------------------------------- 1129314564Sdimconst char *DWARFDebugInfoEntry::GetPubname(SymbolFileDWARF *dwarf2Data, 1130314564Sdim const DWARFCompileUnit *cu) const { 1131314564Sdim const char *name = nullptr; 1132314564Sdim if (!dwarf2Data) 1133314564Sdim return name; 1134254721Semaste 1135314564Sdim name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_MIPS_linkage_name, 1136314564Sdim nullptr, true); 1137314564Sdim if (name) 1138314564Sdim return name; 1139296417Sdim 1140314564Sdim name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_linkage_name, nullptr, 1141314564Sdim true); 1142314564Sdim if (name) 1143314564Sdim return name; 1144296417Sdim 1145314564Sdim name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, nullptr, true); 1146314564Sdim return name; 1147254721Semaste} 1148254721Semaste 1149254721Semaste//---------------------------------------------------------------------- 1150254721Semaste// GetName 1151254721Semaste// 1152254721Semaste// Get value of the DW_AT_name attribute for a debug information entry 1153254721Semaste// that exists at offset "die_offset" and place that value into the 1154254721Semaste// supplied stream object. If the DIE is a NULL object "NULL" is placed 1155254721Semaste// into the stream, and if no DW_AT_name attribute exists for the DIE 1156254721Semaste// then nothing is printed. 1157254721Semaste//---------------------------------------------------------------------- 1158314564Sdimbool DWARFDebugInfoEntry::GetName(SymbolFileDWARF *dwarf2Data, 1159314564Sdim const DWARFCompileUnit *cu, 1160314564Sdim const dw_offset_t die_offset, Stream &s) { 1161314564Sdim if (dwarf2Data == NULL) { 1162314564Sdim s.PutCString("NULL"); 1163314564Sdim return false; 1164314564Sdim } 1165314564Sdim 1166314564Sdim DWARFDebugInfoEntry die; 1167314564Sdim lldb::offset_t offset = die_offset; 1168314564Sdim if (die.Extract(dwarf2Data, cu, &offset)) { 1169314564Sdim if (die.IsNULL()) { 1170314564Sdim s.PutCString("NULL"); 1171314564Sdim return true; 1172314564Sdim } else { 1173314564Sdim const char *name = die.GetAttributeValueAsString( 1174314564Sdim dwarf2Data, cu, DW_AT_name, nullptr, true); 1175314564Sdim if (name) { 1176314564Sdim s.PutCString(name); 1177314564Sdim return true; 1178314564Sdim } 1179254721Semaste } 1180314564Sdim } 1181314564Sdim return false; 1182254721Semaste} 1183254721Semaste 1184254721Semaste//---------------------------------------------------------------------- 1185254721Semaste// AppendTypeName 1186254721Semaste// 1187254721Semaste// Follows the type name definition down through all needed tags to 1188254721Semaste// end up with a fully qualified type name and dump the results to 1189254721Semaste// the supplied stream. This is used to show the name of types given 1190254721Semaste// a type identifier. 1191254721Semaste//---------------------------------------------------------------------- 1192314564Sdimbool DWARFDebugInfoEntry::AppendTypeName(SymbolFileDWARF *dwarf2Data, 1193314564Sdim const DWARFCompileUnit *cu, 1194314564Sdim const dw_offset_t die_offset, 1195314564Sdim Stream &s) { 1196314564Sdim if (dwarf2Data == NULL) { 1197314564Sdim s.PutCString("NULL"); 1198314564Sdim return false; 1199314564Sdim } 1200254721Semaste 1201314564Sdim DWARFDebugInfoEntry die; 1202314564Sdim lldb::offset_t offset = die_offset; 1203314564Sdim if (die.Extract(dwarf2Data, cu, &offset)) { 1204314564Sdim if (die.IsNULL()) { 1205314564Sdim s.PutCString("NULL"); 1206314564Sdim return true; 1207314564Sdim } else { 1208314564Sdim const char *name = die.GetPubname(dwarf2Data, cu); 1209314564Sdim if (name) 1210314564Sdim s.PutCString(name); 1211314564Sdim else { 1212314564Sdim bool result = true; 1213314564Sdim const DWARFAbbreviationDeclaration *abbrevDecl = 1214314564Sdim die.GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset); 1215254721Semaste 1216314564Sdim if (abbrevDecl == NULL) 1217314564Sdim return false; 1218254721Semaste 1219314564Sdim switch (abbrevDecl->Tag()) { 1220314564Sdim case DW_TAG_array_type: 1221314564Sdim break; // print out a "[]" after printing the full type of the element 1222314564Sdim // below 1223314564Sdim case DW_TAG_base_type: 1224314564Sdim s.PutCString("base "); 1225314564Sdim break; 1226314564Sdim case DW_TAG_class_type: 1227314564Sdim s.PutCString("class "); 1228314564Sdim break; 1229314564Sdim case DW_TAG_const_type: 1230314564Sdim s.PutCString("const "); 1231314564Sdim break; 1232314564Sdim case DW_TAG_enumeration_type: 1233314564Sdim s.PutCString("enum "); 1234314564Sdim break; 1235314564Sdim case DW_TAG_file_type: 1236314564Sdim s.PutCString("file "); 1237314564Sdim break; 1238314564Sdim case DW_TAG_interface_type: 1239314564Sdim s.PutCString("interface "); 1240314564Sdim break; 1241314564Sdim case DW_TAG_packed_type: 1242314564Sdim s.PutCString("packed "); 1243314564Sdim break; 1244314564Sdim case DW_TAG_pointer_type: 1245314564Sdim break; // print out a '*' after printing the full type below 1246314564Sdim case DW_TAG_ptr_to_member_type: 1247314564Sdim break; // print out a '*' after printing the full type below 1248314564Sdim case DW_TAG_reference_type: 1249314564Sdim break; // print out a '&' after printing the full type below 1250314564Sdim case DW_TAG_restrict_type: 1251314564Sdim s.PutCString("restrict "); 1252314564Sdim break; 1253314564Sdim case DW_TAG_set_type: 1254314564Sdim s.PutCString("set "); 1255314564Sdim break; 1256314564Sdim case DW_TAG_shared_type: 1257314564Sdim s.PutCString("shared "); 1258314564Sdim break; 1259314564Sdim case DW_TAG_string_type: 1260314564Sdim s.PutCString("string "); 1261314564Sdim break; 1262314564Sdim case DW_TAG_structure_type: 1263314564Sdim s.PutCString("struct "); 1264314564Sdim break; 1265314564Sdim case DW_TAG_subrange_type: 1266314564Sdim s.PutCString("subrange "); 1267314564Sdim break; 1268314564Sdim case DW_TAG_subroutine_type: 1269314564Sdim s.PutCString("function "); 1270314564Sdim break; 1271314564Sdim case DW_TAG_thrown_type: 1272314564Sdim s.PutCString("thrown "); 1273314564Sdim break; 1274314564Sdim case DW_TAG_union_type: 1275314564Sdim s.PutCString("union "); 1276314564Sdim break; 1277314564Sdim case DW_TAG_unspecified_type: 1278314564Sdim s.PutCString("unspecified "); 1279314564Sdim break; 1280314564Sdim case DW_TAG_volatile_type: 1281314564Sdim s.PutCString("volatile "); 1282314564Sdim break; 1283314564Sdim default: 1284314564Sdim return false; 1285254721Semaste } 1286314564Sdim 1287314564Sdim // Follow the DW_AT_type if possible 1288314564Sdim DWARFFormValue form_value; 1289314564Sdim if (die.GetAttributeValue(dwarf2Data, cu, DW_AT_type, form_value)) { 1290314564Sdim uint64_t next_die_offset = form_value.Reference(); 1291314564Sdim result = AppendTypeName(dwarf2Data, cu, next_die_offset, s); 1292314564Sdim } 1293314564Sdim 1294314564Sdim switch (abbrevDecl->Tag()) { 1295314564Sdim case DW_TAG_array_type: 1296314564Sdim s.PutCString("[]"); 1297314564Sdim break; 1298314564Sdim case DW_TAG_pointer_type: 1299314564Sdim s.PutChar('*'); 1300314564Sdim break; 1301314564Sdim case DW_TAG_ptr_to_member_type: 1302314564Sdim s.PutChar('*'); 1303314564Sdim break; 1304314564Sdim case DW_TAG_reference_type: 1305314564Sdim s.PutChar('&'); 1306314564Sdim break; 1307314564Sdim default: 1308314564Sdim break; 1309314564Sdim } 1310314564Sdim return result; 1311314564Sdim } 1312254721Semaste } 1313314564Sdim } 1314314564Sdim return false; 1315254721Semaste} 1316254721Semaste 1317314564Sdimbool DWARFDebugInfoEntry::Contains(const DWARFDebugInfoEntry *die) const { 1318314564Sdim if (die) { 1319314564Sdim const dw_offset_t die_offset = die->GetOffset(); 1320314564Sdim if (die_offset > GetOffset()) { 1321314564Sdim const DWARFDebugInfoEntry *sibling = GetSibling(); 1322314564Sdim assert(sibling); // TODO: take this out 1323314564Sdim if (sibling) 1324314564Sdim return die_offset < sibling->GetOffset(); 1325254721Semaste } 1326314564Sdim } 1327314564Sdim return false; 1328254721Semaste} 1329254721Semaste 1330254721Semaste//---------------------------------------------------------------------- 1331254721Semaste// BuildAddressRangeTable 1332254721Semaste//---------------------------------------------------------------------- 1333314564Sdimvoid DWARFDebugInfoEntry::BuildAddressRangeTable( 1334314564Sdim SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, 1335314564Sdim DWARFDebugAranges *debug_aranges) const { 1336314564Sdim if (m_tag) { 1337314564Sdim if (m_tag == DW_TAG_subprogram) { 1338314564Sdim dw_addr_t lo_pc = LLDB_INVALID_ADDRESS; 1339314564Sdim dw_addr_t hi_pc = LLDB_INVALID_ADDRESS; 1340314564Sdim if (GetAttributeAddressRange(dwarf2Data, cu, lo_pc, hi_pc, 1341314564Sdim LLDB_INVALID_ADDRESS)) { 1342314564Sdim /// printf("BuildAddressRangeTable() 0x%8.8x: %30s: [0x%8.8x - 1343314564Sdim /// 0x%8.8x)\n", m_offset, DW_TAG_value_to_name(tag), lo_pc, hi_pc); 1344314564Sdim debug_aranges->AppendRange(cu->GetOffset(), lo_pc, hi_pc); 1345314564Sdim } 1346314564Sdim } 1347254721Semaste 1348314564Sdim const DWARFDebugInfoEntry *child = GetFirstChild(); 1349314564Sdim while (child) { 1350314564Sdim child->BuildAddressRangeTable(dwarf2Data, cu, debug_aranges); 1351314564Sdim child = child->GetSibling(); 1352254721Semaste } 1353314564Sdim } 1354254721Semaste} 1355254721Semaste 1356254721Semaste//---------------------------------------------------------------------- 1357254721Semaste// BuildFunctionAddressRangeTable 1358254721Semaste// 1359254721Semaste// This function is very similar to the BuildAddressRangeTable function 1360254721Semaste// except that the actual DIE offset for the function is placed in the 1361254721Semaste// table instead of the compile unit offset (which is the way the 1362254721Semaste// standard .debug_aranges section does it). 1363254721Semaste//---------------------------------------------------------------------- 1364314564Sdimvoid DWARFDebugInfoEntry::BuildFunctionAddressRangeTable( 1365314564Sdim SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, 1366314564Sdim DWARFDebugAranges *debug_aranges) const { 1367314564Sdim if (m_tag) { 1368314564Sdim if (m_tag == DW_TAG_subprogram) { 1369314564Sdim dw_addr_t lo_pc = LLDB_INVALID_ADDRESS; 1370314564Sdim dw_addr_t hi_pc = LLDB_INVALID_ADDRESS; 1371314564Sdim if (GetAttributeAddressRange(dwarf2Data, cu, lo_pc, hi_pc, 1372314564Sdim LLDB_INVALID_ADDRESS)) { 1373314564Sdim // printf("BuildAddressRangeTable() 0x%8.8x: [0x%16.16" PRIx64 " - 1374314564Sdim // 0x%16.16" PRIx64 ")\n", m_offset, lo_pc, hi_pc); // DEBUG ONLY 1375314564Sdim debug_aranges->AppendRange(GetOffset(), lo_pc, hi_pc); 1376314564Sdim } 1377314564Sdim } 1378254721Semaste 1379314564Sdim const DWARFDebugInfoEntry *child = GetFirstChild(); 1380314564Sdim while (child) { 1381314564Sdim child->BuildFunctionAddressRangeTable(dwarf2Data, cu, debug_aranges); 1382314564Sdim child = child->GetSibling(); 1383254721Semaste } 1384314564Sdim } 1385254721Semaste} 1386254721Semaste 1387314564Sdimvoid DWARFDebugInfoEntry::GetDeclContextDIEs( 1388314564Sdim DWARFCompileUnit *cu, DWARFDIECollection &decl_context_dies) const { 1389296417Sdim 1390314564Sdim DWARFDIE die(cu, const_cast<DWARFDebugInfoEntry *>(this)); 1391314564Sdim die.GetDeclContextDIEs(decl_context_dies); 1392254721Semaste} 1393254721Semaste 1394314564Sdimvoid DWARFDebugInfoEntry::GetDWARFDeclContext( 1395314564Sdim SymbolFileDWARF *dwarf2Data, DWARFCompileUnit *cu, 1396314564Sdim DWARFDeclContext &dwarf_decl_ctx) const { 1397314564Sdim const dw_tag_t tag = Tag(); 1398314564Sdim if (tag != DW_TAG_compile_unit) { 1399314564Sdim dwarf_decl_ctx.AppendDeclContext(tag, GetName(dwarf2Data, cu)); 1400314564Sdim DWARFDIE parent_decl_ctx_die = GetParentDeclContextDIE(dwarf2Data, cu); 1401314564Sdim if (parent_decl_ctx_die && parent_decl_ctx_die.GetDIE() != this) { 1402314564Sdim if (parent_decl_ctx_die.Tag() != DW_TAG_compile_unit) 1403314564Sdim parent_decl_ctx_die.GetDIE()->GetDWARFDeclContext( 1404314564Sdim parent_decl_ctx_die.GetDWARF(), parent_decl_ctx_die.GetCU(), 1405314564Sdim dwarf_decl_ctx); 1406254721Semaste } 1407314564Sdim } 1408254721Semaste} 1409254721Semaste 1410314564Sdimbool DWARFDebugInfoEntry::MatchesDWARFDeclContext( 1411314564Sdim SymbolFileDWARF *dwarf2Data, DWARFCompileUnit *cu, 1412314564Sdim const DWARFDeclContext &dwarf_decl_ctx) const { 1413254721Semaste 1414314564Sdim DWARFDeclContext this_dwarf_decl_ctx; 1415314564Sdim GetDWARFDeclContext(dwarf2Data, cu, this_dwarf_decl_ctx); 1416314564Sdim return this_dwarf_decl_ctx == dwarf_decl_ctx; 1417254721Semaste} 1418254721Semaste 1419296417SdimDWARFDIE 1420314564SdimDWARFDebugInfoEntry::GetParentDeclContextDIE(SymbolFileDWARF *dwarf2Data, 1421314564Sdim DWARFCompileUnit *cu) const { 1422314564Sdim DWARFAttributes attributes; 1423314564Sdim GetAttributes(cu, DWARFFormValue::FixedFormSizes(), attributes); 1424314564Sdim return GetParentDeclContextDIE(dwarf2Data, cu, attributes); 1425254721Semaste} 1426254721Semaste 1427296417SdimDWARFDIE 1428314564SdimDWARFDebugInfoEntry::GetParentDeclContextDIE( 1429314564Sdim SymbolFileDWARF *dwarf2Data, DWARFCompileUnit *cu, 1430314564Sdim const DWARFAttributes &attributes) const { 1431314564Sdim DWARFDIE die(cu, const_cast<DWARFDebugInfoEntry *>(this)); 1432296417Sdim 1433314564Sdim while (die) { 1434314564Sdim // If this is the original DIE that we are searching for a declaration 1435314564Sdim // for, then don't look in the cache as we don't want our own decl 1436314564Sdim // context to be our decl context... 1437314564Sdim if (die.GetDIE() != this) { 1438314564Sdim switch (die.Tag()) { 1439314564Sdim case DW_TAG_compile_unit: 1440314564Sdim case DW_TAG_namespace: 1441314564Sdim case DW_TAG_structure_type: 1442314564Sdim case DW_TAG_union_type: 1443314564Sdim case DW_TAG_class_type: 1444314564Sdim return die; 1445254721Semaste 1446314564Sdim default: 1447314564Sdim break; 1448314564Sdim } 1449314564Sdim } 1450254721Semaste 1451314564Sdim dw_offset_t die_offset; 1452314564Sdim 1453314564Sdim die_offset = 1454314564Sdim attributes.FormValueAsUnsigned(DW_AT_specification, DW_INVALID_OFFSET); 1455314564Sdim if (die_offset != DW_INVALID_OFFSET) { 1456314564Sdim DWARFDIE spec_die = cu->GetDIE(die_offset); 1457314564Sdim if (spec_die) { 1458314564Sdim DWARFDIE decl_ctx_die = spec_die.GetParentDeclContextDIE(); 1459314564Sdim if (decl_ctx_die) 1460314564Sdim return decl_ctx_die; 1461314564Sdim } 1462314564Sdim } 1463314564Sdim 1464314564Sdim die_offset = attributes.FormValueAsUnsigned(DW_AT_abstract_origin, 1465314564Sdim DW_INVALID_OFFSET); 1466314564Sdim if (die_offset != DW_INVALID_OFFSET) { 1467314564Sdim DWARFDIE abs_die = cu->GetDIE(die_offset); 1468314564Sdim if (abs_die) { 1469314564Sdim DWARFDIE decl_ctx_die = abs_die.GetParentDeclContextDIE(); 1470314564Sdim if (decl_ctx_die) 1471314564Sdim return decl_ctx_die; 1472314564Sdim } 1473314564Sdim } 1474314564Sdim 1475314564Sdim die = die.GetParent(); 1476314564Sdim } 1477314564Sdim return DWARFDIE(); 1478254721Semaste} 1479254721Semaste 1480314564Sdimconst char *DWARFDebugInfoEntry::GetQualifiedName(SymbolFileDWARF *dwarf2Data, 1481314564Sdim DWARFCompileUnit *cu, 1482314564Sdim std::string &storage) const { 1483314564Sdim DWARFAttributes attributes; 1484314564Sdim GetAttributes(cu, DWARFFormValue::FixedFormSizes(), attributes); 1485314564Sdim return GetQualifiedName(dwarf2Data, cu, attributes, storage); 1486254721Semaste} 1487254721Semaste 1488314564Sdimconst char *DWARFDebugInfoEntry::GetQualifiedName( 1489314564Sdim SymbolFileDWARF *dwarf2Data, DWARFCompileUnit *cu, 1490314564Sdim const DWARFAttributes &attributes, std::string &storage) const { 1491254721Semaste 1492314564Sdim const char *name = GetName(dwarf2Data, cu); 1493314564Sdim 1494314564Sdim if (name) { 1495314564Sdim DWARFDIE parent_decl_ctx_die = GetParentDeclContextDIE(dwarf2Data, cu); 1496314564Sdim storage.clear(); 1497314564Sdim // TODO: change this to get the correct decl context parent.... 1498314564Sdim while (parent_decl_ctx_die) { 1499314564Sdim const dw_tag_t parent_tag = parent_decl_ctx_die.Tag(); 1500314564Sdim switch (parent_tag) { 1501314564Sdim case DW_TAG_namespace: { 1502314564Sdim const char *namespace_name = parent_decl_ctx_die.GetName(); 1503314564Sdim if (namespace_name) { 1504314564Sdim storage.insert(0, "::"); 1505314564Sdim storage.insert(0, namespace_name); 1506314564Sdim } else { 1507314564Sdim storage.insert(0, "(anonymous namespace)::"); 1508254721Semaste } 1509314564Sdim parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE(); 1510314564Sdim } break; 1511254721Semaste 1512314564Sdim case DW_TAG_class_type: 1513314564Sdim case DW_TAG_structure_type: 1514314564Sdim case DW_TAG_union_type: { 1515314564Sdim const char *class_union_struct_name = parent_decl_ctx_die.GetName(); 1516254721Semaste 1517314564Sdim if (class_union_struct_name) { 1518314564Sdim storage.insert(0, "::"); 1519314564Sdim storage.insert(0, class_union_struct_name); 1520314564Sdim } 1521314564Sdim parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE(); 1522314564Sdim } break; 1523254721Semaste 1524314564Sdim default: 1525314564Sdim parent_decl_ctx_die.Clear(); 1526314564Sdim break; 1527314564Sdim } 1528314564Sdim } 1529254721Semaste 1530314564Sdim if (storage.empty()) 1531314564Sdim storage.append("::"); 1532254721Semaste 1533314564Sdim storage.append(name); 1534314564Sdim } 1535314564Sdim if (storage.empty()) 1536314564Sdim return NULL; 1537314564Sdim return storage.c_str(); 1538314564Sdim} 1539254721Semaste 1540314564Sdim//---------------------------------------------------------------------- 1541314564Sdim// LookupAddress 1542314564Sdim//---------------------------------------------------------------------- 1543314564Sdimbool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address, 1544314564Sdim SymbolFileDWARF *dwarf2Data, 1545314564Sdim const DWARFCompileUnit *cu, 1546314564Sdim DWARFDebugInfoEntry **function_die, 1547314564Sdim DWARFDebugInfoEntry **block_die) { 1548314564Sdim bool found_address = false; 1549314564Sdim if (m_tag) { 1550314564Sdim bool check_children = false; 1551314564Sdim bool match_addr_range = false; 1552314564Sdim // printf("0x%8.8x: %30s: address = 0x%8.8x - ", m_offset, 1553314564Sdim // DW_TAG_value_to_name(tag), address); 1554314564Sdim switch (m_tag) { 1555314564Sdim case DW_TAG_array_type: 1556314564Sdim break; 1557314564Sdim case DW_TAG_class_type: 1558314564Sdim check_children = true; 1559314564Sdim break; 1560314564Sdim case DW_TAG_entry_point: 1561314564Sdim break; 1562314564Sdim case DW_TAG_enumeration_type: 1563314564Sdim break; 1564314564Sdim case DW_TAG_formal_parameter: 1565314564Sdim break; 1566314564Sdim case DW_TAG_imported_declaration: 1567314564Sdim break; 1568314564Sdim case DW_TAG_label: 1569314564Sdim break; 1570314564Sdim case DW_TAG_lexical_block: 1571314564Sdim check_children = true; 1572314564Sdim match_addr_range = true; 1573314564Sdim break; 1574314564Sdim case DW_TAG_member: 1575314564Sdim break; 1576314564Sdim case DW_TAG_pointer_type: 1577314564Sdim break; 1578314564Sdim case DW_TAG_reference_type: 1579314564Sdim break; 1580314564Sdim case DW_TAG_compile_unit: 1581314564Sdim match_addr_range = true; 1582314564Sdim break; 1583314564Sdim case DW_TAG_string_type: 1584314564Sdim break; 1585314564Sdim case DW_TAG_structure_type: 1586314564Sdim check_children = true; 1587314564Sdim break; 1588314564Sdim case DW_TAG_subroutine_type: 1589314564Sdim break; 1590314564Sdim case DW_TAG_typedef: 1591314564Sdim break; 1592314564Sdim case DW_TAG_union_type: 1593314564Sdim break; 1594314564Sdim case DW_TAG_unspecified_parameters: 1595314564Sdim break; 1596314564Sdim case DW_TAG_variant: 1597314564Sdim break; 1598314564Sdim case DW_TAG_common_block: 1599314564Sdim check_children = true; 1600314564Sdim break; 1601314564Sdim case DW_TAG_common_inclusion: 1602314564Sdim break; 1603314564Sdim case DW_TAG_inheritance: 1604314564Sdim break; 1605314564Sdim case DW_TAG_inlined_subroutine: 1606314564Sdim check_children = true; 1607314564Sdim match_addr_range = true; 1608314564Sdim break; 1609314564Sdim case DW_TAG_module: 1610314564Sdim match_addr_range = true; 1611314564Sdim break; 1612314564Sdim case DW_TAG_ptr_to_member_type: 1613314564Sdim break; 1614314564Sdim case DW_TAG_set_type: 1615314564Sdim break; 1616314564Sdim case DW_TAG_subrange_type: 1617314564Sdim break; 1618314564Sdim case DW_TAG_with_stmt: 1619314564Sdim break; 1620314564Sdim case DW_TAG_access_declaration: 1621314564Sdim break; 1622314564Sdim case DW_TAG_base_type: 1623314564Sdim break; 1624314564Sdim case DW_TAG_catch_block: 1625314564Sdim match_addr_range = true; 1626314564Sdim break; 1627314564Sdim case DW_TAG_const_type: 1628314564Sdim break; 1629314564Sdim case DW_TAG_constant: 1630314564Sdim break; 1631314564Sdim case DW_TAG_enumerator: 1632314564Sdim break; 1633314564Sdim case DW_TAG_file_type: 1634314564Sdim break; 1635314564Sdim case DW_TAG_friend: 1636314564Sdim break; 1637314564Sdim case DW_TAG_namelist: 1638314564Sdim break; 1639314564Sdim case DW_TAG_namelist_item: 1640314564Sdim break; 1641314564Sdim case DW_TAG_packed_type: 1642314564Sdim break; 1643314564Sdim case DW_TAG_subprogram: 1644314564Sdim match_addr_range = true; 1645314564Sdim break; 1646314564Sdim case DW_TAG_template_type_parameter: 1647314564Sdim break; 1648314564Sdim case DW_TAG_template_value_parameter: 1649314564Sdim break; 1650321369Sdim case DW_TAG_GNU_template_parameter_pack: 1651321369Sdim break; 1652314564Sdim case DW_TAG_thrown_type: 1653314564Sdim break; 1654314564Sdim case DW_TAG_try_block: 1655314564Sdim match_addr_range = true; 1656314564Sdim break; 1657314564Sdim case DW_TAG_variant_part: 1658314564Sdim break; 1659314564Sdim case DW_TAG_variable: 1660314564Sdim break; 1661314564Sdim case DW_TAG_volatile_type: 1662314564Sdim break; 1663314564Sdim case DW_TAG_dwarf_procedure: 1664314564Sdim break; 1665314564Sdim case DW_TAG_restrict_type: 1666314564Sdim break; 1667314564Sdim case DW_TAG_interface_type: 1668314564Sdim break; 1669314564Sdim case DW_TAG_namespace: 1670314564Sdim check_children = true; 1671314564Sdim break; 1672314564Sdim case DW_TAG_imported_module: 1673314564Sdim break; 1674314564Sdim case DW_TAG_unspecified_type: 1675314564Sdim break; 1676314564Sdim case DW_TAG_partial_unit: 1677314564Sdim break; 1678314564Sdim case DW_TAG_imported_unit: 1679314564Sdim break; 1680314564Sdim case DW_TAG_shared_type: 1681314564Sdim break; 1682314564Sdim default: 1683314564Sdim break; 1684314564Sdim } 1685254721Semaste 1686314564Sdim if (match_addr_range) { 1687314564Sdim dw_addr_t lo_pc = GetAttributeValueAsAddress(dwarf2Data, cu, DW_AT_low_pc, 1688314564Sdim LLDB_INVALID_ADDRESS); 1689314564Sdim if (lo_pc != LLDB_INVALID_ADDRESS) { 1690314564Sdim dw_addr_t hi_pc = 1691314564Sdim GetAttributeHighPC(dwarf2Data, cu, lo_pc, LLDB_INVALID_ADDRESS); 1692314564Sdim if (hi_pc != LLDB_INVALID_ADDRESS) { 1693314564Sdim // printf("\n0x%8.8x: %30s: address = 0x%8.8x [0x%8.8x - 0x%8.8x) ", 1694314564Sdim // m_offset, DW_TAG_value_to_name(tag), address, lo_pc, hi_pc); 1695314564Sdim if ((lo_pc <= address) && (address < hi_pc)) { 1696314564Sdim found_address = true; 1697314564Sdim // puts("***MATCH***"); 1698314564Sdim switch (m_tag) { 1699314564Sdim case DW_TAG_compile_unit: // File 1700314564Sdim check_children = ((function_die != NULL) || (block_die != NULL)); 1701314564Sdim break; 1702254721Semaste 1703314564Sdim case DW_TAG_subprogram: // Function 1704314564Sdim if (function_die) 1705314564Sdim *function_die = this; 1706314564Sdim check_children = (block_die != NULL); 1707314564Sdim break; 1708254721Semaste 1709314564Sdim case DW_TAG_inlined_subroutine: // Inlined Function 1710314564Sdim case DW_TAG_lexical_block: // Block { } in code 1711314564Sdim if (block_die) { 1712314564Sdim *block_die = this; 1713314564Sdim check_children = true; 1714314564Sdim } 1715314564Sdim break; 1716314564Sdim 1717314564Sdim default: 1718314564Sdim check_children = true; 1719314564Sdim break; 1720254721Semaste } 1721314564Sdim } 1722314564Sdim } else { // compile units may not have a valid high/low pc when there 1723314564Sdim // are address gaps in subroutines so we must always search 1724314564Sdim // if there is no valid high and low PC 1725314564Sdim check_children = (m_tag == DW_TAG_compile_unit) && 1726314564Sdim ((function_die != NULL) || (block_die != NULL)); 1727254721Semaste } 1728314564Sdim } else { 1729314564Sdim dw_offset_t debug_ranges_offset = GetAttributeValueAsUnsigned( 1730314564Sdim dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET); 1731314564Sdim if (debug_ranges_offset != DW_INVALID_OFFSET) { 1732314564Sdim DWARFRangeList ranges; 1733314564Sdim DWARFDebugRanges *debug_ranges = dwarf2Data->DebugRanges(); 1734314564Sdim debug_ranges->FindRanges(cu->GetRangesBase(), debug_ranges_offset, ranges); 1735314564Sdim // All DW_AT_ranges are relative to the base address of the 1736314564Sdim // compile unit. We add the compile unit base address to make 1737314564Sdim // sure all the addresses are properly fixed up. 1738314564Sdim ranges.Slide(cu->GetBaseAddress()); 1739314564Sdim if (ranges.FindEntryThatContains(address)) { 1740314564Sdim found_address = true; 1741314564Sdim // puts("***MATCH***"); 1742314564Sdim switch (m_tag) { 1743314564Sdim case DW_TAG_compile_unit: // File 1744314564Sdim check_children = ((function_die != NULL) || (block_die != NULL)); 1745314564Sdim break; 1746254721Semaste 1747314564Sdim case DW_TAG_subprogram: // Function 1748314564Sdim if (function_die) 1749314564Sdim *function_die = this; 1750314564Sdim check_children = (block_die != NULL); 1751314564Sdim break; 1752288943Sdim 1753314564Sdim case DW_TAG_inlined_subroutine: // Inlined Function 1754314564Sdim case DW_TAG_lexical_block: // Block { } in code 1755314564Sdim if (block_die) { 1756314564Sdim *block_die = this; 1757314564Sdim check_children = true; 1758314564Sdim } 1759314564Sdim break; 1760314564Sdim 1761314564Sdim default: 1762314564Sdim check_children = true; 1763314564Sdim break; 1764288943Sdim } 1765314564Sdim } else { 1766314564Sdim check_children = false; 1767314564Sdim } 1768254721Semaste } 1769314564Sdim } 1770254721Semaste } 1771314564Sdim 1772314564Sdim if (check_children) { 1773314564Sdim // printf("checking children\n"); 1774314564Sdim DWARFDebugInfoEntry *child = GetFirstChild(); 1775314564Sdim while (child) { 1776314564Sdim if (child->LookupAddress(address, dwarf2Data, cu, function_die, 1777314564Sdim block_die)) 1778314564Sdim return true; 1779314564Sdim child = child->GetSibling(); 1780314564Sdim } 1781314564Sdim } 1782314564Sdim } 1783314564Sdim return found_address; 1784254721Semaste} 1785254721Semaste 1786314564Sdimconst DWARFAbbreviationDeclaration * 1787314564SdimDWARFDebugInfoEntry::GetAbbreviationDeclarationPtr( 1788314564Sdim SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, 1789314564Sdim lldb::offset_t &offset) const { 1790314564Sdim if (dwarf2Data) { 1791314564Sdim offset = GetOffset(); 1792254721Semaste 1793314564Sdim const DWARFAbbreviationDeclarationSet *abbrev_set = cu->GetAbbreviations(); 1794314564Sdim if (abbrev_set) { 1795314564Sdim const DWARFAbbreviationDeclaration *abbrev_decl = 1796314564Sdim abbrev_set->GetAbbreviationDeclaration(m_abbr_idx); 1797314564Sdim if (abbrev_decl) { 1798314564Sdim // Make sure the abbreviation code still matches. If it doesn't and 1799314564Sdim // the DWARF data was mmap'ed, the backing file might have been modified 1800314564Sdim // which is bad news. 1801314564Sdim const uint64_t abbrev_code = 1802314564Sdim dwarf2Data->get_debug_info_data().GetULEB128(&offset); 1803254721Semaste 1804314564Sdim if (abbrev_decl->Code() == abbrev_code) 1805314564Sdim return abbrev_decl; 1806314564Sdim 1807314564Sdim dwarf2Data->GetObjectFile()->GetModule()->ReportErrorIfModifyDetected( 1808314564Sdim "0x%8.8x: the DWARF debug information has been modified (abbrev " 1809314564Sdim "code was %u, and is now %u)", 1810314564Sdim GetOffset(), (uint32_t)abbrev_decl->Code(), (uint32_t)abbrev_code); 1811314564Sdim } 1812254721Semaste } 1813314564Sdim } 1814314564Sdim offset = DW_INVALID_OFFSET; 1815314564Sdim return NULL; 1816254721Semaste} 1817254721Semaste 1818314564Sdimbool DWARFDebugInfoEntry::OffsetLessThan(const DWARFDebugInfoEntry &a, 1819314564Sdim const DWARFDebugInfoEntry &b) { 1820314564Sdim return a.GetOffset() < b.GetOffset(); 1821314564Sdim} 1822254721Semaste 1823314564Sdimvoid DWARFDebugInfoEntry::DumpDIECollection( 1824314564Sdim Stream &strm, DWARFDebugInfoEntry::collection &die_collection) { 1825314564Sdim DWARFDebugInfoEntry::const_iterator pos; 1826314564Sdim DWARFDebugInfoEntry::const_iterator end = die_collection.end(); 1827314564Sdim strm.PutCString("\noffset parent sibling child\n"); 1828314564Sdim strm.PutCString("-------- -------- -------- --------\n"); 1829314564Sdim for (pos = die_collection.begin(); pos != end; ++pos) { 1830314564Sdim const DWARFDebugInfoEntry &die_ref = *pos; 1831314564Sdim const DWARFDebugInfoEntry *p = die_ref.GetParent(); 1832314564Sdim const DWARFDebugInfoEntry *s = die_ref.GetSibling(); 1833314564Sdim const DWARFDebugInfoEntry *c = die_ref.GetFirstChild(); 1834314564Sdim strm.Printf("%.8x: %.8x %.8x %.8x 0x%4.4x %s%s\n", die_ref.GetOffset(), 1835314564Sdim p ? p->GetOffset() : 0, s ? s->GetOffset() : 0, 1836314564Sdim c ? c->GetOffset() : 0, die_ref.Tag(), 1837314564Sdim DW_TAG_value_to_name(die_ref.Tag()), 1838314564Sdim die_ref.HasChildren() ? " *" : ""); 1839314564Sdim } 1840314564Sdim} 1841