1254721Semaste//===-- DWARFDebugInfoEntry.cpp ---------------------------------*- C++ -*-===// 2254721Semaste// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6254721Semaste// 7254721Semaste//===----------------------------------------------------------------------===// 8254721Semaste 9254721Semaste#include "DWARFDebugInfoEntry.h" 10254721Semaste 11254721Semaste#include <assert.h> 12254721Semaste 13254721Semaste#include <algorithm> 14254721Semaste 15353358Sdim#include "llvm/Support/LEB128.h" 16353358Sdim 17254721Semaste#include "lldb/Core/Module.h" 18254721Semaste#include "lldb/Expression/DWARFExpression.h" 19254721Semaste#include "lldb/Symbol/ObjectFile.h" 20321369Sdim#include "lldb/Utility/Stream.h" 21254721Semaste 22353358Sdim#include "DWARFCompileUnit.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" 29353358Sdim#include "DWARFUnit.h" 30296417Sdim#include "SymbolFileDWARF.h" 31296417Sdim#include "SymbolFileDWARFDwo.h" 32254721Semaste 33254721Semasteusing namespace lldb_private; 34254721Semasteusing namespace std; 35254721Semasteextern int g_verbose; 36254721Semaste 37353358Sdim// Extract a debug info entry for a given DWARFUnit from the data 38353358Sdim// starting at the offset in offset_ptr 39353358Sdimbool DWARFDebugInfoEntry::Extract(const DWARFDataExtractor &data, 40353358Sdim const DWARFUnit *cu, 41353358Sdim lldb::offset_t *offset_ptr) { 42314564Sdim m_offset = *offset_ptr; 43314564Sdim m_parent_idx = 0; 44314564Sdim m_sibling_idx = 0; 45353358Sdim const uint64_t abbr_idx = data.GetULEB128(offset_ptr); 46344779Sdim lldbassert(abbr_idx <= UINT16_MAX); 47314564Sdim m_abbr_idx = abbr_idx; 48254721Semaste 49314564Sdim // assert (fixed_form_sizes); // For best performance this should be 50314564Sdim // specified! 51254721Semaste 52314564Sdim if (m_abbr_idx) { 53314564Sdim lldb::offset_t offset = *offset_ptr; 54353358Sdim const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu); 55353358Sdim if (abbrevDecl == nullptr) { 56353358Sdim cu->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( 57314564Sdim "{0x%8.8x}: invalid abbreviation code %u, please file a bug and " 58314564Sdim "attach the file at the start of this error message", 59314564Sdim m_offset, (unsigned)abbr_idx); 60314564Sdim // WE can't parse anymore if the DWARF is borked... 61314564Sdim *offset_ptr = UINT32_MAX; 62314564Sdim return false; 63314564Sdim } 64314564Sdim m_tag = abbrevDecl->Tag(); 65314564Sdim m_has_children = abbrevDecl->HasChildren(); 66353358Sdim // Skip all data in the .debug_info or .debug_types for the attributes 67314564Sdim const uint32_t numAttributes = abbrevDecl->NumAttributes(); 68314564Sdim uint32_t i; 69314564Sdim dw_form_t form; 70314564Sdim for (i = 0; i < numAttributes; ++i) { 71314564Sdim form = abbrevDecl->GetFormByIndexUnchecked(i); 72353358Sdim llvm::Optional<uint8_t> fixed_skip_size = 73353358Sdim DWARFFormValue::GetFixedSize(form, cu); 74314564Sdim if (fixed_skip_size) 75353358Sdim offset += *fixed_skip_size; 76314564Sdim else { 77314564Sdim bool form_is_indirect = false; 78314564Sdim do { 79314564Sdim form_is_indirect = false; 80314564Sdim uint32_t form_size = 0; 81314564Sdim switch (form) { 82314564Sdim // Blocks if inlined data that have a length field and the data bytes 83353358Sdim // inlined in the .debug_info/.debug_types 84314564Sdim case DW_FORM_exprloc: 85314564Sdim case DW_FORM_block: 86353358Sdim form_size = data.GetULEB128(&offset); 87314564Sdim break; 88314564Sdim case DW_FORM_block1: 89353358Sdim form_size = data.GetU8_unchecked(&offset); 90314564Sdim break; 91314564Sdim case DW_FORM_block2: 92353358Sdim form_size = data.GetU16_unchecked(&offset); 93314564Sdim break; 94314564Sdim case DW_FORM_block4: 95353358Sdim form_size = data.GetU32_unchecked(&offset); 96314564Sdim break; 97254721Semaste 98314564Sdim // Inlined NULL terminated C-strings 99314564Sdim case DW_FORM_string: 100353358Sdim data.GetCStr(&offset); 101314564Sdim break; 102254721Semaste 103314564Sdim // Compile unit address sized values 104314564Sdim case DW_FORM_addr: 105314564Sdim form_size = cu->GetAddressByteSize(); 106314564Sdim break; 107314564Sdim case DW_FORM_ref_addr: 108314564Sdim if (cu->GetVersion() <= 2) 109314564Sdim form_size = cu->GetAddressByteSize(); 110314564Sdim else 111353358Sdim form_size = 4; 112314564Sdim break; 113254721Semaste 114314564Sdim // 0 sized form 115314564Sdim case DW_FORM_flag_present: 116314564Sdim form_size = 0; 117314564Sdim break; 118254721Semaste 119314564Sdim // 1 byte values 120344779Sdim case DW_FORM_addrx1: 121314564Sdim case DW_FORM_data1: 122314564Sdim case DW_FORM_flag: 123314564Sdim case DW_FORM_ref1: 124344779Sdim case DW_FORM_strx1: 125314564Sdim form_size = 1; 126314564Sdim break; 127254721Semaste 128314564Sdim // 2 byte values 129344779Sdim case DW_FORM_addrx2: 130314564Sdim case DW_FORM_data2: 131314564Sdim case DW_FORM_ref2: 132344779Sdim case DW_FORM_strx2: 133314564Sdim form_size = 2; 134314564Sdim break; 135254721Semaste 136344779Sdim // 3 byte values 137344779Sdim case DW_FORM_addrx3: 138344779Sdim case DW_FORM_strx3: 139344779Sdim form_size = 3; 140344779Sdim break; 141344779Sdim 142314564Sdim // 4 byte values 143344779Sdim case DW_FORM_addrx4: 144314564Sdim case DW_FORM_data4: 145314564Sdim case DW_FORM_ref4: 146344779Sdim case DW_FORM_strx4: 147314564Sdim form_size = 4; 148314564Sdim break; 149254721Semaste 150314564Sdim // 8 byte values 151314564Sdim case DW_FORM_data8: 152314564Sdim case DW_FORM_ref8: 153314564Sdim case DW_FORM_ref_sig8: 154314564Sdim form_size = 8; 155314564Sdim break; 156254721Semaste 157314564Sdim // signed or unsigned LEB 128 values 158344779Sdim case DW_FORM_addrx: 159360784Sdim case DW_FORM_loclistx: 160344779Sdim case DW_FORM_rnglistx: 161314564Sdim case DW_FORM_sdata: 162314564Sdim case DW_FORM_udata: 163314564Sdim case DW_FORM_ref_udata: 164314564Sdim case DW_FORM_GNU_addr_index: 165314564Sdim case DW_FORM_GNU_str_index: 166344779Sdim case DW_FORM_strx: 167353358Sdim data.Skip_LEB128(&offset); 168314564Sdim break; 169254721Semaste 170314564Sdim case DW_FORM_indirect: 171314564Sdim form_is_indirect = true; 172353358Sdim form = data.GetULEB128(&offset); 173314564Sdim break; 174314564Sdim 175314564Sdim case DW_FORM_strp: 176314564Sdim case DW_FORM_sec_offset: 177353358Sdim data.GetU32(&offset); 178314564Sdim break; 179314564Sdim 180344779Sdim case DW_FORM_implicit_const: 181344779Sdim form_size = 0; 182344779Sdim break; 183344779Sdim 184314564Sdim default: 185314564Sdim *offset_ptr = m_offset; 186314564Sdim return false; 187314564Sdim } 188314564Sdim offset += form_size; 189314564Sdim 190314564Sdim } while (form_is_indirect); 191314564Sdim } 192254721Semaste } 193314564Sdim *offset_ptr = offset; 194314564Sdim return true; 195314564Sdim } else { 196360784Sdim m_tag = llvm::dwarf::DW_TAG_null; 197314564Sdim m_has_children = false; 198314564Sdim return true; // NULL debug tag entry 199314564Sdim } 200254721Semaste 201314564Sdim return false; 202254721Semaste} 203254721Semaste 204360784Sdimstatic DWARFRangeList GetRangesOrReportError(DWARFUnit &unit, 205353358Sdim const DWARFDebugInfoEntry &die, 206353358Sdim const DWARFFormValue &value) { 207353358Sdim llvm::Expected<DWARFRangeList> expected_ranges = 208353358Sdim (value.Form() == DW_FORM_rnglistx) 209353358Sdim ? unit.FindRnglistFromIndex(value.Unsigned()) 210353358Sdim : unit.FindRnglistFromOffset(value.Unsigned()); 211353358Sdim if (expected_ranges) 212353358Sdim return std::move(*expected_ranges); 213353358Sdim unit.GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( 214353358Sdim "{0x%8.8x}: DIE has DW_AT_ranges(0x%" PRIx64 ") attribute, but " 215353358Sdim "range extraction failed (%s), please file a bug " 216353358Sdim "and attach the file at the start of this error message", 217353358Sdim die.GetOffset(), value.Unsigned(), 218353358Sdim toString(expected_ranges.takeError()).c_str()); 219353358Sdim return DWARFRangeList(); 220254721Semaste} 221254721Semaste 222254721Semaste// GetDIENamesAndRanges 223254721Semaste// 224254721Semaste// Gets the valid address ranges for a given DIE by looking for a 225341825Sdim// DW_AT_low_pc/DW_AT_high_pc pair, DW_AT_entry_pc, or DW_AT_ranges attributes. 226314564Sdimbool DWARFDebugInfoEntry::GetDIENamesAndRanges( 227360784Sdim DWARFUnit *cu, const char *&name, const char *&mangled, 228353358Sdim DWARFRangeList &ranges, int &decl_file, int &decl_line, int &decl_column, 229353358Sdim int &call_file, int &call_line, int &call_column, 230353358Sdim DWARFExpression *frame_base) const { 231314564Sdim dw_addr_t lo_pc = LLDB_INVALID_ADDRESS; 232314564Sdim dw_addr_t hi_pc = LLDB_INVALID_ADDRESS; 233353358Sdim std::vector<DWARFDIE> dies; 234314564Sdim bool set_frame_base_loclist_addr = false; 235254721Semaste 236353358Sdim const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu); 237258054Semaste 238353358Sdim SymbolFileDWARF &dwarf = cu->GetSymbolFileDWARF(); 239353358Sdim lldb::ModuleSP module = dwarf.GetObjectFile()->GetModule(); 240254721Semaste 241314564Sdim if (abbrevDecl) { 242353358Sdim const DWARFDataExtractor &data = cu->GetData(); 243353358Sdim lldb::offset_t offset = GetFirstAttributeOffset(); 244254721Semaste 245353358Sdim if (!data.ValidOffset(offset)) 246314564Sdim return false; 247254721Semaste 248314564Sdim const uint32_t numAttributes = abbrevDecl->NumAttributes(); 249314564Sdim bool do_offset = false; 250254721Semaste 251344779Sdim for (uint32_t i = 0; i < numAttributes; ++i) { 252344779Sdim DWARFFormValue form_value(cu); 253344779Sdim dw_attr_t attr; 254344779Sdim abbrevDecl->GetAttrAndFormValueByIndex(i, attr, form_value); 255344779Sdim 256353358Sdim if (form_value.ExtractValue(data, &offset)) { 257314564Sdim switch (attr) { 258314564Sdim case DW_AT_low_pc: 259314564Sdim lo_pc = form_value.Address(); 260254721Semaste 261314564Sdim if (do_offset) 262314564Sdim hi_pc += lo_pc; 263314564Sdim do_offset = false; 264314564Sdim break; 265254721Semaste 266314564Sdim case DW_AT_entry_pc: 267314564Sdim lo_pc = form_value.Address(); 268314564Sdim break; 269254721Semaste 270314564Sdim case DW_AT_high_pc: 271314564Sdim if (form_value.Form() == DW_FORM_addr || 272353358Sdim form_value.Form() == DW_FORM_addrx || 273314564Sdim form_value.Form() == DW_FORM_GNU_addr_index) { 274314564Sdim hi_pc = form_value.Address(); 275314564Sdim } else { 276314564Sdim hi_pc = form_value.Unsigned(); 277314564Sdim if (lo_pc == LLDB_INVALID_ADDRESS) 278314564Sdim do_offset = hi_pc != LLDB_INVALID_ADDRESS; 279314564Sdim else 280314564Sdim hi_pc += lo_pc; // DWARF 4 introduces <offset-from-lo-pc> to save 281314564Sdim // on relocations 282314564Sdim } 283314564Sdim break; 284254721Semaste 285353358Sdim case DW_AT_ranges: 286353358Sdim ranges = GetRangesOrReportError(*cu, *this, form_value); 287353358Sdim break; 288254721Semaste 289314564Sdim case DW_AT_name: 290353358Sdim if (name == nullptr) 291314564Sdim name = form_value.AsCString(); 292314564Sdim break; 293254721Semaste 294314564Sdim case DW_AT_MIPS_linkage_name: 295314564Sdim case DW_AT_linkage_name: 296353358Sdim if (mangled == nullptr) 297314564Sdim mangled = form_value.AsCString(); 298314564Sdim break; 299254721Semaste 300314564Sdim case DW_AT_abstract_origin: 301353358Sdim dies.push_back(form_value.Reference()); 302314564Sdim break; 303254721Semaste 304314564Sdim case DW_AT_specification: 305353358Sdim dies.push_back(form_value.Reference()); 306314564Sdim break; 307254721Semaste 308314564Sdim case DW_AT_decl_file: 309314564Sdim if (decl_file == 0) 310314564Sdim decl_file = form_value.Unsigned(); 311314564Sdim break; 312254721Semaste 313314564Sdim case DW_AT_decl_line: 314314564Sdim if (decl_line == 0) 315314564Sdim decl_line = form_value.Unsigned(); 316314564Sdim break; 317254721Semaste 318314564Sdim case DW_AT_decl_column: 319314564Sdim if (decl_column == 0) 320314564Sdim decl_column = form_value.Unsigned(); 321314564Sdim break; 322254721Semaste 323314564Sdim case DW_AT_call_file: 324314564Sdim if (call_file == 0) 325314564Sdim call_file = form_value.Unsigned(); 326314564Sdim break; 327254721Semaste 328314564Sdim case DW_AT_call_line: 329314564Sdim if (call_line == 0) 330314564Sdim call_line = form_value.Unsigned(); 331314564Sdim break; 332254721Semaste 333314564Sdim case DW_AT_call_column: 334314564Sdim if (call_column == 0) 335314564Sdim call_column = form_value.Unsigned(); 336314564Sdim break; 337254721Semaste 338314564Sdim case DW_AT_frame_base: 339314564Sdim if (frame_base) { 340314564Sdim if (form_value.BlockData()) { 341314564Sdim uint32_t block_offset = 342353358Sdim form_value.BlockData() - data.GetDataStart(); 343314564Sdim uint32_t block_length = form_value.Unsigned(); 344360784Sdim *frame_base = DWARFExpression( 345360784Sdim module, DataExtractor(data, block_offset, block_length), cu); 346314564Sdim } else { 347360784Sdim DataExtractor data = cu->GetLocationData(); 348360784Sdim const dw_offset_t offset = form_value.Unsigned(); 349360784Sdim if (data.ValidOffset(offset)) { 350360784Sdim data = DataExtractor(data, offset, data.GetByteSize() - offset); 351360784Sdim *frame_base = DWARFExpression(module, data, cu); 352314564Sdim if (lo_pc != LLDB_INVALID_ADDRESS) { 353314564Sdim assert(lo_pc >= cu->GetBaseAddress()); 354360784Sdim frame_base->SetLocationListAddresses(cu->GetBaseAddress(), 355360784Sdim lo_pc); 356314564Sdim } else { 357314564Sdim set_frame_base_loclist_addr = true; 358254721Semaste } 359314564Sdim } 360254721Semaste } 361314564Sdim } 362314564Sdim break; 363314564Sdim 364314564Sdim default: 365314564Sdim break; 366254721Semaste } 367314564Sdim } 368254721Semaste } 369314564Sdim } 370254721Semaste 371314564Sdim if (ranges.IsEmpty()) { 372314564Sdim if (lo_pc != LLDB_INVALID_ADDRESS) { 373314564Sdim if (hi_pc != LLDB_INVALID_ADDRESS && hi_pc > lo_pc) 374314564Sdim ranges.Append(DWARFRangeList::Entry(lo_pc, hi_pc - lo_pc)); 375314564Sdim else 376314564Sdim ranges.Append(DWARFRangeList::Entry(lo_pc, 0)); 377254721Semaste } 378314564Sdim } 379254721Semaste 380314564Sdim if (set_frame_base_loclist_addr) { 381314564Sdim dw_addr_t lowest_range_pc = ranges.GetMinRangeBase(0); 382314564Sdim assert(lowest_range_pc >= cu->GetBaseAddress()); 383360784Sdim frame_base->SetLocationListAddresses(cu->GetBaseAddress(), lowest_range_pc); 384314564Sdim } 385314564Sdim 386353358Sdim if (ranges.IsEmpty() || name == nullptr || mangled == nullptr) { 387353358Sdim for (const DWARFDIE &die : dies) { 388353358Sdim if (die) { 389353358Sdim die.GetDIE()->GetDIENamesAndRanges(die.GetCU(), name, mangled, ranges, 390353358Sdim decl_file, decl_line, decl_column, 391353358Sdim call_file, call_line, call_column); 392314564Sdim } 393254721Semaste } 394314564Sdim } 395314564Sdim return !ranges.IsEmpty(); 396254721Semaste} 397254721Semaste 398254721Semaste// Dump 399254721Semaste// 400341825Sdim// Dumps a debug information entry and all of it's attributes to the specified 401341825Sdim// stream. 402353358Sdimvoid DWARFDebugInfoEntry::Dump(const DWARFUnit *cu, Stream &s, 403314564Sdim uint32_t recurse_depth) const { 404353358Sdim const DWARFDataExtractor &data = cu->GetData(); 405314564Sdim lldb::offset_t offset = m_offset; 406254721Semaste 407353358Sdim if (data.ValidOffset(offset)) { 408353358Sdim dw_uleb128_t abbrCode = data.GetULEB128(&offset); 409254721Semaste 410314564Sdim s.Printf("\n0x%8.8x: ", m_offset); 411314564Sdim s.Indent(); 412314564Sdim if (abbrCode != m_abbr_idx) { 413314564Sdim s.Printf("error: DWARF has been modified\n"); 414314564Sdim } else if (abbrCode) { 415353358Sdim const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu); 416314564Sdim if (abbrevDecl) { 417314564Sdim s.PutCString(DW_TAG_value_to_name(abbrevDecl->Tag())); 418314564Sdim s.Printf(" [%u] %c\n", abbrCode, abbrevDecl->HasChildren() ? '*' : ' '); 419254721Semaste 420353358Sdim // Dump all data in the .debug_info/.debug_types for the attributes 421314564Sdim const uint32_t numAttributes = abbrevDecl->NumAttributes(); 422344779Sdim for (uint32_t i = 0; i < numAttributes; ++i) { 423344779Sdim DWARFFormValue form_value(cu); 424344779Sdim dw_attr_t attr; 425344779Sdim abbrevDecl->GetAttrAndFormValueByIndex(i, attr, form_value); 426254721Semaste 427353358Sdim DumpAttribute(cu, data, &offset, s, attr, form_value); 428314564Sdim } 429254721Semaste 430314564Sdim const DWARFDebugInfoEntry *child = GetFirstChild(); 431314564Sdim if (recurse_depth > 0 && child) { 432314564Sdim s.IndentMore(); 433254721Semaste 434314564Sdim while (child) { 435353358Sdim child->Dump(cu, s, recurse_depth - 1); 436314564Sdim child = child->GetSibling(); 437314564Sdim } 438314564Sdim s.IndentLess(); 439254721Semaste } 440314564Sdim } else 441314564Sdim s.Printf("Abbreviation code note found in 'debug_abbrev' class for " 442314564Sdim "code: %u\n", 443314564Sdim abbrCode); 444314564Sdim } else { 445314564Sdim s.Printf("NULL\n"); 446254721Semaste } 447314564Sdim } 448254721Semaste} 449254721Semaste 450254721Semaste// DumpAttribute 451254721Semaste// 452341825Sdim// Dumps a debug information entry attribute along with it's form. Any special 453341825Sdim// display of attributes is done (disassemble location lists, show enumeration 454341825Sdim// values for attributes, etc). 455314564Sdimvoid DWARFDebugInfoEntry::DumpAttribute( 456353358Sdim const DWARFUnit *cu, const DWARFDataExtractor &data, 457353358Sdim lldb::offset_t *offset_ptr, Stream &s, dw_attr_t attr, 458353358Sdim DWARFFormValue &form_value) { 459314564Sdim bool show_form = s.GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowForm); 460254721Semaste 461321369Sdim s.Printf(" "); 462314564Sdim s.Indent(DW_AT_value_to_name(attr)); 463254721Semaste 464314564Sdim if (show_form) { 465344779Sdim s.Printf("[%s", DW_FORM_value_to_name(form_value.Form())); 466314564Sdim } 467254721Semaste 468353358Sdim if (!form_value.ExtractValue(data, offset_ptr)) 469314564Sdim return; 470254721Semaste 471314564Sdim if (show_form) { 472344779Sdim if (form_value.Form() == DW_FORM_indirect) { 473314564Sdim s.Printf(" [%s]", DW_FORM_value_to_name(form_value.Form())); 474254721Semaste } 475254721Semaste 476314564Sdim s.PutCString("] "); 477314564Sdim } 478254721Semaste 479314564Sdim s.PutCString("( "); 480254721Semaste 481314564Sdim // Check to see if we have any special attribute formatters 482314564Sdim switch (attr) { 483314564Sdim case DW_AT_stmt_list: 484314564Sdim s.Printf("0x%8.8" PRIx64, form_value.Unsigned()); 485314564Sdim break; 486254721Semaste 487314564Sdim case DW_AT_language: 488314564Sdim s.PutCString(DW_LANG_value_to_name(form_value.Unsigned())); 489314564Sdim break; 490254721Semaste 491314564Sdim case DW_AT_encoding: 492314564Sdim s.PutCString(DW_ATE_value_to_name(form_value.Unsigned())); 493314564Sdim break; 494254721Semaste 495314564Sdim case DW_AT_frame_base: 496314564Sdim case DW_AT_location: 497314564Sdim case DW_AT_data_member_location: { 498314564Sdim const uint8_t *blockData = form_value.BlockData(); 499314564Sdim if (blockData) { 500314564Sdim // Location description is inlined in data in the form value 501353358Sdim DWARFDataExtractor locationData(data, 502314564Sdim (*offset_ptr) - form_value.Unsigned(), 503314564Sdim form_value.Unsigned()); 504314564Sdim DWARFExpression::PrintDWARFExpression( 505341825Sdim s, locationData, DWARFUnit::GetAddressByteSize(cu), 4, false); 506314564Sdim } else { 507341825Sdim // We have a location list offset as the value that is the offset into 508341825Sdim // the .debug_loc section that describes the value over it's lifetime 509314564Sdim uint64_t debug_loc_offset = form_value.Unsigned(); 510360784Sdim DWARFExpression::PrintDWARFLocationList(s, cu, cu->GetLocationData(), 511353358Sdim debug_loc_offset); 512314564Sdim } 513314564Sdim } break; 514254721Semaste 515314564Sdim case DW_AT_abstract_origin: 516314564Sdim case DW_AT_specification: { 517353358Sdim DWARFDIE abstract_die = form_value.Reference(); 518314564Sdim form_value.Dump(s); 519353358Sdim // *ostrm_ptr << HEX32 << abstract_die.GetOffset() << " ( "; 520353358Sdim abstract_die.GetName(s); 521314564Sdim } break; 522254721Semaste 523314564Sdim case DW_AT_type: { 524353358Sdim DWARFDIE type_die = form_value.Reference(); 525314564Sdim s.PutCString(" ( "); 526353358Sdim type_die.AppendTypeName(s); 527314564Sdim s.PutCString(" )"); 528314564Sdim } break; 529254721Semaste 530314564Sdim default: 531314564Sdim break; 532314564Sdim } 533254721Semaste 534314564Sdim s.PutCString(" )\n"); 535254721Semaste} 536254721Semaste 537254721Semaste// Get all attribute values for a given DIE, including following any 538341825Sdim// specification or abstract origin attributes and including those in the 539341825Sdim// results. Any duplicate attributes will have the first instance take 540341825Sdim// precedence (this can happen for declaration attributes). 541314564Sdimsize_t DWARFDebugInfoEntry::GetAttributes( 542353358Sdim const DWARFUnit *cu, DWARFAttributes &attributes, 543353358Sdim uint32_t curr_depth) const { 544353358Sdim const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu); 545314564Sdim if (abbrevDecl) { 546353358Sdim const DWARFDataExtractor &data = cu->GetData(); 547353358Sdim lldb::offset_t offset = GetFirstAttributeOffset(); 548254721Semaste 549314564Sdim const uint32_t num_attributes = abbrevDecl->NumAttributes(); 550344779Sdim for (uint32_t i = 0; i < num_attributes; ++i) { 551344779Sdim DWARFFormValue form_value(cu); 552344779Sdim dw_attr_t attr; 553344779Sdim abbrevDecl->GetAttrAndFormValueByIndex(i, attr, form_value); 554344779Sdim const dw_form_t form = form_value.Form(); 555314564Sdim 556314564Sdim // If we are tracking down DW_AT_specification or DW_AT_abstract_origin 557314564Sdim // attributes, the depth will be non-zero. We need to omit certain 558314564Sdim // attributes that don't make sense. 559314564Sdim switch (attr) { 560314564Sdim case DW_AT_sibling: 561314564Sdim case DW_AT_declaration: 562314564Sdim if (curr_depth > 0) { 563341825Sdim // This attribute doesn't make sense when combined with the DIE that 564341825Sdim // references this DIE. We know a DIE is referencing this DIE because 565341825Sdim // curr_depth is not zero 566314564Sdim break; 567254721Semaste } 568314564Sdim LLVM_FALLTHROUGH; 569314564Sdim default: 570314564Sdim attributes.Append(cu, offset, attr, form); 571314564Sdim break; 572314564Sdim } 573314564Sdim 574314564Sdim if ((attr == DW_AT_specification) || (attr == DW_AT_abstract_origin)) { 575353358Sdim if (form_value.ExtractValue(data, &offset)) { 576353358Sdim DWARFDIE spec_die = form_value.Reference(); 577314564Sdim if (spec_die) 578314564Sdim spec_die.GetAttributes(attributes, curr_depth + 1); 579314564Sdim } 580314564Sdim } else { 581353358Sdim llvm::Optional<uint8_t> fixed_skip_size = DWARFFormValue::GetFixedSize(form, cu); 582314564Sdim if (fixed_skip_size) 583353358Sdim offset += *fixed_skip_size; 584314564Sdim else 585353358Sdim DWARFFormValue::SkipValue(form, data, &offset, cu); 586314564Sdim } 587254721Semaste } 588314564Sdim } else { 589314564Sdim attributes.Clear(); 590314564Sdim } 591314564Sdim return attributes.Size(); 592254721Semaste} 593254721Semaste 594254721Semaste// GetAttributeValue 595254721Semaste// 596353358Sdim// Get the value of an attribute and return the .debug_info or .debug_types 597353358Sdim// offset of the attribute if it was properly extracted into form_value, 598353358Sdim// or zero if we fail since an offset of zero is invalid for an attribute (it 599353358Sdim// would be a compile unit header). 600314564Sdimdw_offset_t DWARFDebugInfoEntry::GetAttributeValue( 601353358Sdim const DWARFUnit *cu, const dw_attr_t attr, DWARFFormValue &form_value, 602314564Sdim dw_offset_t *end_attr_offset_ptr, 603314564Sdim bool check_specification_or_abstract_origin) const { 604353358Sdim if (const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu)) { 605314564Sdim uint32_t attr_idx = abbrevDecl->FindAttributeIndex(attr); 606254721Semaste 607314564Sdim if (attr_idx != DW_INVALID_INDEX) { 608353358Sdim const DWARFDataExtractor &data = cu->GetData(); 609353358Sdim lldb::offset_t offset = GetFirstAttributeOffset(); 610254721Semaste 611314564Sdim uint32_t idx = 0; 612314564Sdim while (idx < attr_idx) 613314564Sdim DWARFFormValue::SkipValue(abbrevDecl->GetFormByIndex(idx++), 614353358Sdim data, &offset, cu); 615254721Semaste 616314564Sdim const dw_offset_t attr_offset = offset; 617353358Sdim form_value.SetUnit(cu); 618314564Sdim form_value.SetForm(abbrevDecl->GetFormByIndex(idx)); 619353358Sdim if (form_value.ExtractValue(data, &offset)) { 620314564Sdim if (end_attr_offset_ptr) 621314564Sdim *end_attr_offset_ptr = offset; 622314564Sdim return attr_offset; 623314564Sdim } 624254721Semaste } 625314564Sdim } 626254721Semaste 627314564Sdim if (check_specification_or_abstract_origin) { 628353358Sdim if (GetAttributeValue(cu, DW_AT_specification, form_value)) { 629353358Sdim DWARFDIE die = form_value.Reference(); 630314564Sdim if (die) { 631314564Sdim dw_offset_t die_offset = die.GetDIE()->GetAttributeValue( 632353358Sdim die.GetCU(), attr, form_value, end_attr_offset_ptr, false); 633314564Sdim if (die_offset) 634314564Sdim return die_offset; 635314564Sdim } 636314564Sdim } 637296417Sdim 638353358Sdim if (GetAttributeValue(cu, DW_AT_abstract_origin, form_value)) { 639353358Sdim DWARFDIE die = form_value.Reference(); 640314564Sdim if (die) { 641314564Sdim dw_offset_t die_offset = die.GetDIE()->GetAttributeValue( 642353358Sdim die.GetCU(), attr, form_value, end_attr_offset_ptr, false); 643314564Sdim if (die_offset) 644314564Sdim return die_offset; 645314564Sdim } 646296417Sdim } 647314564Sdim } 648360784Sdim return 0; 649254721Semaste} 650254721Semaste 651254721Semaste// GetAttributeValueAsString 652254721Semaste// 653341825Sdim// Get the value of an attribute as a string return it. The resulting pointer 654341825Sdim// to the string data exists within the supplied SymbolFileDWARF and will only 655341825Sdim// be available as long as the SymbolFileDWARF is still around and it's content 656341825Sdim// doesn't change. 657314564Sdimconst char *DWARFDebugInfoEntry::GetAttributeValueAsString( 658353358Sdim const DWARFUnit *cu, const dw_attr_t attr, const char *fail_value, 659314564Sdim bool check_specification_or_abstract_origin) const { 660314564Sdim DWARFFormValue form_value; 661353358Sdim if (GetAttributeValue(cu, attr, form_value, nullptr, 662314564Sdim check_specification_or_abstract_origin)) 663314564Sdim return form_value.AsCString(); 664314564Sdim return fail_value; 665254721Semaste} 666254721Semaste 667254721Semaste// GetAttributeValueAsUnsigned 668254721Semaste// 669254721Semaste// Get the value of an attribute as unsigned and return it. 670314564Sdimuint64_t DWARFDebugInfoEntry::GetAttributeValueAsUnsigned( 671353358Sdim const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value, 672314564Sdim bool check_specification_or_abstract_origin) const { 673314564Sdim DWARFFormValue form_value; 674353358Sdim if (GetAttributeValue(cu, attr, form_value, nullptr, 675314564Sdim check_specification_or_abstract_origin)) 676314564Sdim return form_value.Unsigned(); 677314564Sdim return fail_value; 678254721Semaste} 679254721Semaste 680254721Semaste// GetAttributeValueAsReference 681254721Semaste// 682341825Sdim// Get the value of an attribute as reference and fix up and compile unit 683341825Sdim// relative offsets as needed. 684353358SdimDWARFDIE DWARFDebugInfoEntry::GetAttributeValueAsReference( 685353358Sdim const DWARFUnit *cu, const dw_attr_t attr, 686314564Sdim bool check_specification_or_abstract_origin) const { 687314564Sdim DWARFFormValue form_value; 688353358Sdim if (GetAttributeValue(cu, attr, form_value, nullptr, 689314564Sdim check_specification_or_abstract_origin)) 690314564Sdim return form_value.Reference(); 691353358Sdim return {}; 692254721Semaste} 693254721Semaste 694314564Sdimuint64_t DWARFDebugInfoEntry::GetAttributeValueAsAddress( 695353358Sdim const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value, 696314564Sdim bool check_specification_or_abstract_origin) const { 697314564Sdim DWARFFormValue form_value; 698353358Sdim if (GetAttributeValue(cu, attr, form_value, nullptr, 699314564Sdim check_specification_or_abstract_origin)) 700314564Sdim return form_value.Address(); 701314564Sdim return fail_value; 702296417Sdim} 703296417Sdim 704254721Semaste// GetAttributeHighPC 705254721Semaste// 706341825Sdim// Get the hi_pc, adding hi_pc to lo_pc when specified as an <offset-from-low- 707341825Sdim// pc>. 708254721Semaste// 709254721Semaste// Returns the hi_pc or fail_value. 710314564Sdimdw_addr_t DWARFDebugInfoEntry::GetAttributeHighPC( 711353358Sdim const DWARFUnit *cu, dw_addr_t lo_pc, uint64_t fail_value, 712353358Sdim bool check_specification_or_abstract_origin) const { 713314564Sdim DWARFFormValue form_value; 714353358Sdim if (GetAttributeValue(cu, DW_AT_high_pc, form_value, nullptr, 715314564Sdim check_specification_or_abstract_origin)) { 716314564Sdim dw_form_t form = form_value.Form(); 717353358Sdim if (form == DW_FORM_addr || form == DW_FORM_addrx || 718353358Sdim form == DW_FORM_GNU_addr_index) 719314564Sdim return form_value.Address(); 720314564Sdim 721314564Sdim // DWARF4 can specify the hi_pc as an <offset-from-lowpc> 722314564Sdim return lo_pc + form_value.Unsigned(); 723314564Sdim } 724314564Sdim return fail_value; 725254721Semaste} 726254721Semaste 727254721Semaste// GetAttributeAddressRange 728254721Semaste// 729341825Sdim// Get the lo_pc and hi_pc, adding hi_pc to lo_pc when specified as an <offset- 730341825Sdim// from-low-pc>. 731254721Semaste// 732254721Semaste// Returns true or sets lo_pc and hi_pc to fail_value. 733314564Sdimbool DWARFDebugInfoEntry::GetAttributeAddressRange( 734353358Sdim const DWARFUnit *cu, dw_addr_t &lo_pc, dw_addr_t &hi_pc, 735353358Sdim uint64_t fail_value, bool check_specification_or_abstract_origin) const { 736353358Sdim lo_pc = GetAttributeValueAsAddress(cu, DW_AT_low_pc, fail_value, 737314564Sdim check_specification_or_abstract_origin); 738314564Sdim if (lo_pc != fail_value) { 739353358Sdim hi_pc = GetAttributeHighPC(cu, lo_pc, fail_value, 740314564Sdim check_specification_or_abstract_origin); 741314564Sdim if (hi_pc != fail_value) 742314564Sdim return true; 743314564Sdim } 744314564Sdim lo_pc = fail_value; 745314564Sdim hi_pc = fail_value; 746314564Sdim return false; 747254721Semaste} 748276479Sdim 749314564Sdimsize_t DWARFDebugInfoEntry::GetAttributeAddressRanges( 750360784Sdim DWARFUnit *cu, DWARFRangeList &ranges, bool check_hi_lo_pc, 751314564Sdim bool check_specification_or_abstract_origin) const { 752314564Sdim ranges.Clear(); 753314564Sdim 754344779Sdim DWARFFormValue form_value; 755353358Sdim if (GetAttributeValue(cu, DW_AT_ranges, form_value)) { 756353358Sdim ranges = GetRangesOrReportError(*cu, *this, form_value); 757314564Sdim } else if (check_hi_lo_pc) { 758314564Sdim dw_addr_t lo_pc = LLDB_INVALID_ADDRESS; 759314564Sdim dw_addr_t hi_pc = LLDB_INVALID_ADDRESS; 760353358Sdim if (GetAttributeAddressRange(cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS, 761314564Sdim check_specification_or_abstract_origin)) { 762314564Sdim if (lo_pc < hi_pc) 763314564Sdim ranges.Append(DWARFRangeList::Entry(lo_pc, hi_pc - lo_pc)); 764276479Sdim } 765314564Sdim } 766314564Sdim return ranges.GetSize(); 767276479Sdim} 768276479Sdim 769254721Semaste// GetName 770254721Semaste// 771341825Sdim// Get value of the DW_AT_name attribute and return it if one exists, else 772341825Sdim// return NULL. 773353358Sdimconst char *DWARFDebugInfoEntry::GetName(const DWARFUnit *cu) const { 774353358Sdim return GetAttributeValueAsString(cu, DW_AT_name, nullptr, true); 775254721Semaste} 776254721Semaste 777254721Semaste// GetMangledName 778254721Semaste// 779341825Sdim// Get value of the DW_AT_MIPS_linkage_name attribute and return it if one 780341825Sdim// exists, else return the value of the DW_AT_name attribute 781314564Sdimconst char * 782353358SdimDWARFDebugInfoEntry::GetMangledName(const DWARFUnit *cu, 783314564Sdim bool substitute_name_allowed) const { 784314564Sdim const char *name = nullptr; 785254721Semaste 786353358Sdim name = GetAttributeValueAsString(cu, DW_AT_MIPS_linkage_name, nullptr, true); 787314564Sdim if (name) 788314564Sdim return name; 789254721Semaste 790353358Sdim name = GetAttributeValueAsString(cu, DW_AT_linkage_name, nullptr, true); 791314564Sdim if (name) 792314564Sdim return name; 793254721Semaste 794314564Sdim if (!substitute_name_allowed) 795314564Sdim return nullptr; 796296417Sdim 797353358Sdim name = GetAttributeValueAsString(cu, DW_AT_name, nullptr, true); 798314564Sdim return name; 799254721Semaste} 800254721Semaste 801254721Semaste// GetPubname 802254721Semaste// 803341825Sdim// Get value the name for a DIE as it should appear for a .debug_pubnames or 804341825Sdim// .debug_pubtypes section. 805353358Sdimconst char *DWARFDebugInfoEntry::GetPubname(const DWARFUnit *cu) const { 806314564Sdim const char *name = nullptr; 807353358Sdim if (!cu) 808314564Sdim return name; 809254721Semaste 810353358Sdim name = GetAttributeValueAsString(cu, DW_AT_MIPS_linkage_name, nullptr, true); 811314564Sdim if (name) 812314564Sdim return name; 813296417Sdim 814353358Sdim name = GetAttributeValueAsString(cu, DW_AT_linkage_name, nullptr, true); 815314564Sdim if (name) 816314564Sdim return name; 817296417Sdim 818353358Sdim name = GetAttributeValueAsString(cu, DW_AT_name, nullptr, true); 819314564Sdim return name; 820254721Semaste} 821254721Semaste 822254721Semaste// BuildAddressRangeTable 823314564Sdimvoid DWARFDebugInfoEntry::BuildAddressRangeTable( 824353358Sdim const DWARFUnit *cu, DWARFDebugAranges *debug_aranges) const { 825314564Sdim if (m_tag) { 826314564Sdim if (m_tag == DW_TAG_subprogram) { 827314564Sdim dw_addr_t lo_pc = LLDB_INVALID_ADDRESS; 828314564Sdim dw_addr_t hi_pc = LLDB_INVALID_ADDRESS; 829353358Sdim if (GetAttributeAddressRange(cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS)) { 830314564Sdim /// printf("BuildAddressRangeTable() 0x%8.8x: %30s: [0x%8.8x - 831314564Sdim /// 0x%8.8x)\n", m_offset, DW_TAG_value_to_name(tag), lo_pc, hi_pc); 832314564Sdim debug_aranges->AppendRange(cu->GetOffset(), lo_pc, hi_pc); 833314564Sdim } 834314564Sdim } 835254721Semaste 836314564Sdim const DWARFDebugInfoEntry *child = GetFirstChild(); 837314564Sdim while (child) { 838353358Sdim child->BuildAddressRangeTable(cu, debug_aranges); 839314564Sdim child = child->GetSibling(); 840254721Semaste } 841314564Sdim } 842254721Semaste} 843254721Semaste 844254721Semaste// BuildFunctionAddressRangeTable 845254721Semaste// 846341825Sdim// This function is very similar to the BuildAddressRangeTable function except 847341825Sdim// that the actual DIE offset for the function is placed in the table instead 848341825Sdim// of the compile unit offset (which is the way the standard .debug_aranges 849341825Sdim// section does it). 850314564Sdimvoid DWARFDebugInfoEntry::BuildFunctionAddressRangeTable( 851353358Sdim const DWARFUnit *cu, DWARFDebugAranges *debug_aranges) const { 852314564Sdim if (m_tag) { 853314564Sdim if (m_tag == DW_TAG_subprogram) { 854314564Sdim dw_addr_t lo_pc = LLDB_INVALID_ADDRESS; 855314564Sdim dw_addr_t hi_pc = LLDB_INVALID_ADDRESS; 856353358Sdim if (GetAttributeAddressRange(cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS)) { 857314564Sdim // printf("BuildAddressRangeTable() 0x%8.8x: [0x%16.16" PRIx64 " - 858314564Sdim // 0x%16.16" PRIx64 ")\n", m_offset, lo_pc, hi_pc); // DEBUG ONLY 859314564Sdim debug_aranges->AppendRange(GetOffset(), lo_pc, hi_pc); 860314564Sdim } 861314564Sdim } 862254721Semaste 863314564Sdim const DWARFDebugInfoEntry *child = GetFirstChild(); 864314564Sdim while (child) { 865353358Sdim child->BuildFunctionAddressRangeTable(cu, debug_aranges); 866314564Sdim child = child->GetSibling(); 867254721Semaste } 868314564Sdim } 869254721Semaste} 870254721Semaste 871314564Sdimvoid DWARFDebugInfoEntry::GetDWARFDeclContext( 872353358Sdim DWARFUnit *cu, DWARFDeclContext &dwarf_decl_ctx) const { 873314564Sdim const dw_tag_t tag = Tag(); 874341825Sdim if (tag != DW_TAG_compile_unit && tag != DW_TAG_partial_unit) { 875353358Sdim dwarf_decl_ctx.AppendDeclContext(tag, GetName(cu)); 876353358Sdim DWARFDIE parent_decl_ctx_die = GetParentDeclContextDIE(cu); 877314564Sdim if (parent_decl_ctx_die && parent_decl_ctx_die.GetDIE() != this) { 878341825Sdim if (parent_decl_ctx_die.Tag() != DW_TAG_compile_unit && 879341825Sdim parent_decl_ctx_die.Tag() != DW_TAG_partial_unit) 880314564Sdim parent_decl_ctx_die.GetDIE()->GetDWARFDeclContext( 881353358Sdim parent_decl_ctx_die.GetCU(), dwarf_decl_ctx); 882254721Semaste } 883314564Sdim } 884254721Semaste} 885254721Semaste 886296417SdimDWARFDIE 887353358SdimDWARFDebugInfoEntry::GetParentDeclContextDIE(DWARFUnit *cu) const { 888314564Sdim DWARFAttributes attributes; 889353358Sdim GetAttributes(cu, attributes); 890353358Sdim return GetParentDeclContextDIE(cu, attributes); 891254721Semaste} 892254721Semaste 893296417SdimDWARFDIE 894314564SdimDWARFDebugInfoEntry::GetParentDeclContextDIE( 895353358Sdim DWARFUnit *cu, const DWARFAttributes &attributes) const { 896314564Sdim DWARFDIE die(cu, const_cast<DWARFDebugInfoEntry *>(this)); 897296417Sdim 898314564Sdim while (die) { 899341825Sdim // If this is the original DIE that we are searching for a declaration for, 900341825Sdim // then don't look in the cache as we don't want our own decl context to be 901341825Sdim // our decl context... 902314564Sdim if (die.GetDIE() != this) { 903314564Sdim switch (die.Tag()) { 904314564Sdim case DW_TAG_compile_unit: 905341825Sdim case DW_TAG_partial_unit: 906314564Sdim case DW_TAG_namespace: 907314564Sdim case DW_TAG_structure_type: 908314564Sdim case DW_TAG_union_type: 909314564Sdim case DW_TAG_class_type: 910314564Sdim return die; 911254721Semaste 912314564Sdim default: 913314564Sdim break; 914314564Sdim } 915314564Sdim } 916254721Semaste 917353358Sdim DWARFDIE spec_die = attributes.FormValueAsReference(DW_AT_specification); 918353358Sdim if (spec_die) { 919353358Sdim DWARFDIE decl_ctx_die = spec_die.GetParentDeclContextDIE(); 920353358Sdim if (decl_ctx_die) 921353358Sdim return decl_ctx_die; 922314564Sdim } 923314564Sdim 924353358Sdim DWARFDIE abs_die = attributes.FormValueAsReference(DW_AT_abstract_origin); 925353358Sdim if (abs_die) { 926353358Sdim DWARFDIE decl_ctx_die = abs_die.GetParentDeclContextDIE(); 927353358Sdim if (decl_ctx_die) 928353358Sdim return decl_ctx_die; 929314564Sdim } 930314564Sdim 931314564Sdim die = die.GetParent(); 932314564Sdim } 933314564Sdim return DWARFDIE(); 934254721Semaste} 935254721Semaste 936353358Sdimconst char *DWARFDebugInfoEntry::GetQualifiedName(DWARFUnit *cu, 937314564Sdim std::string &storage) const { 938314564Sdim DWARFAttributes attributes; 939353358Sdim GetAttributes(cu, attributes); 940353358Sdim return GetQualifiedName(cu, attributes, storage); 941254721Semaste} 942254721Semaste 943353358Sdimconst char * 944353358SdimDWARFDebugInfoEntry::GetQualifiedName(DWARFUnit *cu, 945353358Sdim const DWARFAttributes &attributes, 946353358Sdim std::string &storage) const { 947254721Semaste 948353358Sdim const char *name = GetName(cu); 949314564Sdim 950314564Sdim if (name) { 951353358Sdim DWARFDIE parent_decl_ctx_die = GetParentDeclContextDIE(cu); 952314564Sdim storage.clear(); 953314564Sdim // TODO: change this to get the correct decl context parent.... 954314564Sdim while (parent_decl_ctx_die) { 955314564Sdim const dw_tag_t parent_tag = parent_decl_ctx_die.Tag(); 956314564Sdim switch (parent_tag) { 957314564Sdim case DW_TAG_namespace: { 958314564Sdim const char *namespace_name = parent_decl_ctx_die.GetName(); 959314564Sdim if (namespace_name) { 960314564Sdim storage.insert(0, "::"); 961314564Sdim storage.insert(0, namespace_name); 962314564Sdim } else { 963314564Sdim storage.insert(0, "(anonymous namespace)::"); 964254721Semaste } 965314564Sdim parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE(); 966314564Sdim } break; 967254721Semaste 968314564Sdim case DW_TAG_class_type: 969314564Sdim case DW_TAG_structure_type: 970314564Sdim case DW_TAG_union_type: { 971314564Sdim const char *class_union_struct_name = parent_decl_ctx_die.GetName(); 972254721Semaste 973314564Sdim if (class_union_struct_name) { 974314564Sdim storage.insert(0, "::"); 975314564Sdim storage.insert(0, class_union_struct_name); 976314564Sdim } 977314564Sdim parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE(); 978314564Sdim } break; 979254721Semaste 980314564Sdim default: 981314564Sdim parent_decl_ctx_die.Clear(); 982314564Sdim break; 983314564Sdim } 984314564Sdim } 985254721Semaste 986314564Sdim if (storage.empty()) 987314564Sdim storage.append("::"); 988254721Semaste 989314564Sdim storage.append(name); 990314564Sdim } 991314564Sdim if (storage.empty()) 992353358Sdim return nullptr; 993314564Sdim return storage.c_str(); 994314564Sdim} 995254721Semaste 996360784Sdimbool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address, DWARFUnit *cu, 997314564Sdim DWARFDebugInfoEntry **function_die, 998314564Sdim DWARFDebugInfoEntry **block_die) { 999314564Sdim bool found_address = false; 1000314564Sdim if (m_tag) { 1001314564Sdim bool check_children = false; 1002314564Sdim bool match_addr_range = false; 1003314564Sdim // printf("0x%8.8x: %30s: address = 0x%8.8x - ", m_offset, 1004314564Sdim // DW_TAG_value_to_name(tag), address); 1005314564Sdim switch (m_tag) { 1006314564Sdim case DW_TAG_array_type: 1007314564Sdim break; 1008314564Sdim case DW_TAG_class_type: 1009314564Sdim check_children = true; 1010314564Sdim break; 1011314564Sdim case DW_TAG_entry_point: 1012314564Sdim case DW_TAG_enumeration_type: 1013314564Sdim case DW_TAG_formal_parameter: 1014314564Sdim case DW_TAG_imported_declaration: 1015314564Sdim case DW_TAG_label: 1016314564Sdim break; 1017314564Sdim case DW_TAG_lexical_block: 1018314564Sdim check_children = true; 1019314564Sdim match_addr_range = true; 1020314564Sdim break; 1021314564Sdim case DW_TAG_member: 1022314564Sdim case DW_TAG_pointer_type: 1023314564Sdim case DW_TAG_reference_type: 1024314564Sdim break; 1025314564Sdim case DW_TAG_compile_unit: 1026314564Sdim match_addr_range = true; 1027314564Sdim break; 1028314564Sdim case DW_TAG_string_type: 1029314564Sdim break; 1030314564Sdim case DW_TAG_structure_type: 1031314564Sdim check_children = true; 1032314564Sdim break; 1033314564Sdim case DW_TAG_subroutine_type: 1034314564Sdim case DW_TAG_typedef: 1035314564Sdim case DW_TAG_union_type: 1036314564Sdim case DW_TAG_unspecified_parameters: 1037314564Sdim case DW_TAG_variant: 1038314564Sdim break; 1039314564Sdim case DW_TAG_common_block: 1040314564Sdim check_children = true; 1041314564Sdim break; 1042314564Sdim case DW_TAG_common_inclusion: 1043314564Sdim case DW_TAG_inheritance: 1044314564Sdim break; 1045314564Sdim case DW_TAG_inlined_subroutine: 1046314564Sdim check_children = true; 1047314564Sdim match_addr_range = true; 1048314564Sdim break; 1049314564Sdim case DW_TAG_module: 1050314564Sdim match_addr_range = true; 1051314564Sdim break; 1052314564Sdim case DW_TAG_ptr_to_member_type: 1053314564Sdim case DW_TAG_set_type: 1054314564Sdim case DW_TAG_subrange_type: 1055314564Sdim case DW_TAG_with_stmt: 1056314564Sdim case DW_TAG_access_declaration: 1057314564Sdim case DW_TAG_base_type: 1058314564Sdim break; 1059314564Sdim case DW_TAG_catch_block: 1060314564Sdim match_addr_range = true; 1061314564Sdim break; 1062314564Sdim case DW_TAG_const_type: 1063314564Sdim case DW_TAG_constant: 1064314564Sdim case DW_TAG_enumerator: 1065314564Sdim case DW_TAG_file_type: 1066314564Sdim case DW_TAG_friend: 1067314564Sdim case DW_TAG_namelist: 1068314564Sdim case DW_TAG_namelist_item: 1069314564Sdim case DW_TAG_packed_type: 1070314564Sdim break; 1071314564Sdim case DW_TAG_subprogram: 1072314564Sdim match_addr_range = true; 1073314564Sdim break; 1074314564Sdim case DW_TAG_template_type_parameter: 1075314564Sdim case DW_TAG_template_value_parameter: 1076321369Sdim case DW_TAG_GNU_template_parameter_pack: 1077314564Sdim case DW_TAG_thrown_type: 1078314564Sdim break; 1079314564Sdim case DW_TAG_try_block: 1080314564Sdim match_addr_range = true; 1081314564Sdim break; 1082314564Sdim case DW_TAG_variant_part: 1083314564Sdim case DW_TAG_variable: 1084314564Sdim case DW_TAG_volatile_type: 1085314564Sdim case DW_TAG_dwarf_procedure: 1086314564Sdim case DW_TAG_restrict_type: 1087314564Sdim case DW_TAG_interface_type: 1088314564Sdim break; 1089314564Sdim case DW_TAG_namespace: 1090314564Sdim check_children = true; 1091314564Sdim break; 1092314564Sdim case DW_TAG_imported_module: 1093314564Sdim case DW_TAG_unspecified_type: 1094314564Sdim break; 1095314564Sdim case DW_TAG_partial_unit: 1096341825Sdim match_addr_range = true; 1097314564Sdim break; 1098314564Sdim case DW_TAG_imported_unit: 1099314564Sdim case DW_TAG_shared_type: 1100314564Sdim default: 1101314564Sdim break; 1102314564Sdim } 1103254721Semaste 1104314564Sdim if (match_addr_range) { 1105353358Sdim dw_addr_t lo_pc = 1106353358Sdim GetAttributeValueAsAddress(cu, DW_AT_low_pc, LLDB_INVALID_ADDRESS); 1107314564Sdim if (lo_pc != LLDB_INVALID_ADDRESS) { 1108353358Sdim dw_addr_t hi_pc = GetAttributeHighPC(cu, lo_pc, LLDB_INVALID_ADDRESS); 1109314564Sdim if (hi_pc != LLDB_INVALID_ADDRESS) { 1110314564Sdim // printf("\n0x%8.8x: %30s: address = 0x%8.8x [0x%8.8x - 0x%8.8x) ", 1111314564Sdim // m_offset, DW_TAG_value_to_name(tag), address, lo_pc, hi_pc); 1112314564Sdim if ((lo_pc <= address) && (address < hi_pc)) { 1113314564Sdim found_address = true; 1114314564Sdim // puts("***MATCH***"); 1115314564Sdim switch (m_tag) { 1116314564Sdim case DW_TAG_compile_unit: // File 1117341825Sdim case DW_TAG_partial_unit: // File 1118353358Sdim check_children = 1119353358Sdim ((function_die != nullptr) || (block_die != nullptr)); 1120314564Sdim break; 1121254721Semaste 1122314564Sdim case DW_TAG_subprogram: // Function 1123314564Sdim if (function_die) 1124314564Sdim *function_die = this; 1125353358Sdim check_children = (block_die != nullptr); 1126314564Sdim break; 1127254721Semaste 1128314564Sdim case DW_TAG_inlined_subroutine: // Inlined Function 1129314564Sdim case DW_TAG_lexical_block: // Block { } in code 1130314564Sdim if (block_die) { 1131314564Sdim *block_die = this; 1132314564Sdim check_children = true; 1133314564Sdim } 1134314564Sdim break; 1135314564Sdim 1136314564Sdim default: 1137314564Sdim check_children = true; 1138314564Sdim break; 1139254721Semaste } 1140314564Sdim } 1141341825Sdim } else { 1142341825Sdim // Compile units may not have a valid high/low pc when there 1143314564Sdim // are address gaps in subroutines so we must always search 1144341825Sdim // if there is no valid high and low PC. 1145353358Sdim check_children = 1146353358Sdim (m_tag == DW_TAG_compile_unit || m_tag == DW_TAG_partial_unit) && 1147353358Sdim ((function_die != nullptr) || (block_die != nullptr)); 1148254721Semaste } 1149314564Sdim } else { 1150353358Sdim DWARFRangeList ranges; 1151353358Sdim if (GetAttributeAddressRanges(cu, ranges, /*check_hi_lo_pc*/ false) && 1152353358Sdim ranges.FindEntryThatContains(address)) { 1153353358Sdim found_address = true; 1154353358Sdim // puts("***MATCH***"); 1155353358Sdim switch (m_tag) { 1156353358Sdim case DW_TAG_compile_unit: // File 1157353358Sdim case DW_TAG_partial_unit: // File 1158353358Sdim check_children = 1159353358Sdim ((function_die != nullptr) || (block_die != nullptr)); 1160314564Sdim break; 1161254721Semaste 1162353358Sdim case DW_TAG_subprogram: // Function 1163353358Sdim if (function_die) 1164353358Sdim *function_die = this; 1165353358Sdim check_children = (block_die != nullptr); 1166353358Sdim break; 1167288943Sdim 1168353358Sdim case DW_TAG_inlined_subroutine: // Inlined Function 1169353358Sdim case DW_TAG_lexical_block: // Block { } in code 1170353358Sdim if (block_die) { 1171353358Sdim *block_die = this; 1172314564Sdim check_children = true; 1173288943Sdim } 1174353358Sdim break; 1175353358Sdim 1176353358Sdim default: 1177353358Sdim check_children = true; 1178353358Sdim break; 1179314564Sdim } 1180353358Sdim } else { 1181353358Sdim check_children = false; 1182254721Semaste } 1183314564Sdim } 1184254721Semaste } 1185314564Sdim 1186314564Sdim if (check_children) { 1187314564Sdim // printf("checking children\n"); 1188314564Sdim DWARFDebugInfoEntry *child = GetFirstChild(); 1189314564Sdim while (child) { 1190353358Sdim if (child->LookupAddress(address, cu, function_die, block_die)) 1191314564Sdim return true; 1192314564Sdim child = child->GetSibling(); 1193314564Sdim } 1194314564Sdim } 1195314564Sdim } 1196314564Sdim return found_address; 1197254721Semaste} 1198254721Semaste 1199353358Sdimlldb::offset_t DWARFDebugInfoEntry::GetFirstAttributeOffset() const { 1200353358Sdim return GetOffset() + llvm::getULEB128Size(m_abbr_idx); 1201353358Sdim} 1202353358Sdim 1203314564Sdimconst DWARFAbbreviationDeclaration * 1204353358SdimDWARFDebugInfoEntry::GetAbbreviationDeclarationPtr(const DWARFUnit *cu) const { 1205353358Sdim if (cu) { 1206314564Sdim const DWARFAbbreviationDeclarationSet *abbrev_set = cu->GetAbbreviations(); 1207353358Sdim if (abbrev_set) 1208353358Sdim return abbrev_set->GetAbbreviationDeclaration(m_abbr_idx); 1209314564Sdim } 1210353358Sdim return nullptr; 1211254721Semaste} 1212254721Semaste 1213341825Sdimbool DWARFDebugInfoEntry::operator==(const DWARFDebugInfoEntry &rhs) const { 1214341825Sdim return m_offset == rhs.m_offset && m_parent_idx == rhs.m_parent_idx && 1215341825Sdim m_sibling_idx == rhs.m_sibling_idx && 1216341825Sdim m_abbr_idx == rhs.m_abbr_idx && m_has_children == rhs.m_has_children && 1217341825Sdim m_tag == rhs.m_tag; 1218341825Sdim} 1219341825Sdim 1220341825Sdimbool DWARFDebugInfoEntry::operator!=(const DWARFDebugInfoEntry &rhs) const { 1221341825Sdim return !(*this == rhs); 1222341825Sdim} 1223