15ffd83dbSDimitry Andric //===-- DWARFDebugInfoEntry.cpp -------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "DWARFDebugInfoEntry.h" 100b57cec5SDimitry Andric 11fe6060f1SDimitry Andric #include <cassert> 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include <algorithm> 14*0fca6ea1SDimitry Andric #include <limits> 15bdd1243dSDimitry Andric #include <optional> 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric #include "llvm/Support/LEB128.h" 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric #include "lldb/Core/Module.h" 200b57cec5SDimitry Andric #include "lldb/Expression/DWARFExpression.h" 210b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h" 220b57cec5SDimitry Andric #include "lldb/Utility/Stream.h" 23bdd1243dSDimitry Andric #include "lldb/Utility/StreamString.h" 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric #include "DWARFCompileUnit.h" 260b57cec5SDimitry Andric #include "DWARFDebugAranges.h" 270b57cec5SDimitry Andric #include "DWARFDebugInfo.h" 280b57cec5SDimitry Andric #include "DWARFDebugRanges.h" 290b57cec5SDimitry Andric #include "DWARFDeclContext.h" 300b57cec5SDimitry Andric #include "DWARFFormValue.h" 310b57cec5SDimitry Andric #include "DWARFUnit.h" 320b57cec5SDimitry Andric #include "SymbolFileDWARF.h" 330b57cec5SDimitry Andric #include "SymbolFileDWARFDwo.h" 340b57cec5SDimitry Andric 355f757f3fSDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" 365f757f3fSDimitry Andric 370b57cec5SDimitry Andric using namespace lldb_private; 3881ad6265SDimitry Andric using namespace lldb_private::dwarf; 395f757f3fSDimitry Andric using namespace lldb_private::plugin::dwarf; 400b57cec5SDimitry Andric extern int g_verbose; 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric // Extract a debug info entry for a given DWARFUnit from the data 430b57cec5SDimitry Andric // starting at the offset in offset_ptr 440b57cec5SDimitry Andric bool DWARFDebugInfoEntry::Extract(const DWARFDataExtractor &data, 45*0fca6ea1SDimitry Andric const DWARFUnit &unit, 460b57cec5SDimitry Andric lldb::offset_t *offset_ptr) { 470b57cec5SDimitry Andric m_offset = *offset_ptr; 48*0fca6ea1SDimitry Andric auto report_error = [&](const char *fmt, const auto &...vals) { 49*0fca6ea1SDimitry Andric unit.GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( 50*0fca6ea1SDimitry Andric "[{0:x16}]: {1}, please file a bug and " 51*0fca6ea1SDimitry Andric "attach the file at the start of this error message", 52*0fca6ea1SDimitry Andric static_cast<uint64_t>(m_offset), llvm::formatv(fmt, vals...)); 53*0fca6ea1SDimitry Andric *offset_ptr = std::numeric_limits<lldb::offset_t>::max(); 54*0fca6ea1SDimitry Andric return false; 55*0fca6ea1SDimitry Andric }; 56*0fca6ea1SDimitry Andric 570b57cec5SDimitry Andric m_parent_idx = 0; 580b57cec5SDimitry Andric m_sibling_idx = 0; 590b57cec5SDimitry Andric const uint64_t abbr_idx = data.GetULEB128(offset_ptr); 60*0fca6ea1SDimitry Andric if (abbr_idx > std::numeric_limits<uint16_t>::max()) 61*0fca6ea1SDimitry Andric return report_error("abbreviation code {0} too big", abbr_idx); 620b57cec5SDimitry Andric m_abbr_idx = abbr_idx; 630b57cec5SDimitry Andric 64fe6060f1SDimitry Andric if (m_abbr_idx == 0) { 65fe6060f1SDimitry Andric m_tag = llvm::dwarf::DW_TAG_null; 66fe6060f1SDimitry Andric m_has_children = false; 67fe6060f1SDimitry Andric return true; // NULL debug tag entry 68fe6060f1SDimitry Andric } 69fe6060f1SDimitry Andric 70*0fca6ea1SDimitry Andric const auto *abbrevDecl = GetAbbreviationDeclarationPtr(&unit); 71*0fca6ea1SDimitry Andric if (abbrevDecl == nullptr) 72*0fca6ea1SDimitry Andric return report_error("invalid abbreviation code {0}", abbr_idx); 73*0fca6ea1SDimitry Andric 7406c3fb27SDimitry Andric m_tag = abbrevDecl->getTag(); 7506c3fb27SDimitry Andric m_has_children = abbrevDecl->hasChildren(); 760b57cec5SDimitry Andric // Skip all data in the .debug_info or .debug_types for the attributes 7706c3fb27SDimitry Andric for (const auto &attribute : abbrevDecl->attributes()) { 78*0fca6ea1SDimitry Andric if (DWARFFormValue::SkipValue(attribute.Form, data, offset_ptr, &unit)) 795f757f3fSDimitry Andric continue; 800b57cec5SDimitry Andric 81*0fca6ea1SDimitry Andric return report_error("Unsupported DW_FORM_{1:x}", attribute.Form); 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric return true; 840b57cec5SDimitry Andric } 850b57cec5SDimitry Andric 86480093f4SDimitry Andric static DWARFRangeList GetRangesOrReportError(DWARFUnit &unit, 870b57cec5SDimitry Andric const DWARFDebugInfoEntry &die, 880b57cec5SDimitry Andric const DWARFFormValue &value) { 890b57cec5SDimitry Andric llvm::Expected<DWARFRangeList> expected_ranges = 900b57cec5SDimitry Andric (value.Form() == DW_FORM_rnglistx) 910b57cec5SDimitry Andric ? unit.FindRnglistFromIndex(value.Unsigned()) 920b57cec5SDimitry Andric : unit.FindRnglistFromOffset(value.Unsigned()); 930b57cec5SDimitry Andric if (expected_ranges) 940b57cec5SDimitry Andric return std::move(*expected_ranges); 95bdd1243dSDimitry Andric 960b57cec5SDimitry Andric unit.GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( 97bdd1243dSDimitry Andric "[{0:x16}]: DIE has DW_AT_ranges({1} {2:x16}) attribute, but " 98bdd1243dSDimitry Andric "range extraction failed ({3}), please file a bug " 990b57cec5SDimitry Andric "and attach the file at the start of this error message", 100fe6060f1SDimitry Andric die.GetOffset(), 101fe6060f1SDimitry Andric llvm::dwarf::FormEncodingString(value.Form()).str().c_str(), 102fe6060f1SDimitry Andric value.Unsigned(), toString(expected_ranges.takeError()).c_str()); 1030b57cec5SDimitry Andric return DWARFRangeList(); 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric 10606c3fb27SDimitry Andric static void ExtractAttrAndFormValue( 10706c3fb27SDimitry Andric const llvm::DWARFAbbreviationDeclaration::AttributeSpec &attr_spec, 10806c3fb27SDimitry Andric dw_attr_t &attr, DWARFFormValue &form_value) { 10906c3fb27SDimitry Andric attr = attr_spec.Attr; 11006c3fb27SDimitry Andric form_value.FormRef() = attr_spec.Form; 11106c3fb27SDimitry Andric if (attr_spec.isImplicitConst()) 11206c3fb27SDimitry Andric form_value.SetSigned(attr_spec.getImplicitConstValue()); 11306c3fb27SDimitry Andric } 11406c3fb27SDimitry Andric 1150b57cec5SDimitry Andric // GetDIENamesAndRanges 1160b57cec5SDimitry Andric // 1170b57cec5SDimitry Andric // Gets the valid address ranges for a given DIE by looking for a 1180b57cec5SDimitry Andric // DW_AT_low_pc/DW_AT_high_pc pair, DW_AT_entry_pc, or DW_AT_ranges attributes. 1190b57cec5SDimitry Andric bool DWARFDebugInfoEntry::GetDIENamesAndRanges( 120480093f4SDimitry Andric DWARFUnit *cu, const char *&name, const char *&mangled, 12106c3fb27SDimitry Andric DWARFRangeList &ranges, std::optional<int> &decl_file, 12206c3fb27SDimitry Andric std::optional<int> &decl_line, std::optional<int> &decl_column, 12306c3fb27SDimitry Andric std::optional<int> &call_file, std::optional<int> &call_line, 12406c3fb27SDimitry Andric std::optional<int> &call_column, DWARFExpressionList *frame_base) const { 1250b57cec5SDimitry Andric dw_addr_t lo_pc = LLDB_INVALID_ADDRESS; 1260b57cec5SDimitry Andric dw_addr_t hi_pc = LLDB_INVALID_ADDRESS; 1270b57cec5SDimitry Andric std::vector<DWARFDIE> dies; 1280b57cec5SDimitry Andric bool set_frame_base_loclist_addr = false; 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric SymbolFileDWARF &dwarf = cu->GetSymbolFileDWARF(); 1310b57cec5SDimitry Andric lldb::ModuleSP module = dwarf.GetObjectFile()->GetModule(); 1320b57cec5SDimitry Andric 13306c3fb27SDimitry Andric if (const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu)) { 1340b57cec5SDimitry Andric const DWARFDataExtractor &data = cu->GetData(); 1350b57cec5SDimitry Andric lldb::offset_t offset = GetFirstAttributeOffset(); 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric if (!data.ValidOffset(offset)) 1380b57cec5SDimitry Andric return false; 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric bool do_offset = false; 1410b57cec5SDimitry Andric 14206c3fb27SDimitry Andric for (const auto &attribute : abbrevDecl->attributes()) { 1430b57cec5SDimitry Andric DWARFFormValue form_value(cu); 1440b57cec5SDimitry Andric dw_attr_t attr; 14506c3fb27SDimitry Andric ExtractAttrAndFormValue(attribute, attr, form_value); 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric if (form_value.ExtractValue(data, &offset)) { 1480b57cec5SDimitry Andric switch (attr) { 1490b57cec5SDimitry Andric case DW_AT_low_pc: 1500b57cec5SDimitry Andric lo_pc = form_value.Address(); 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric if (do_offset) 1530b57cec5SDimitry Andric hi_pc += lo_pc; 1540b57cec5SDimitry Andric do_offset = false; 1550b57cec5SDimitry Andric break; 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric case DW_AT_entry_pc: 1580b57cec5SDimitry Andric lo_pc = form_value.Address(); 1590b57cec5SDimitry Andric break; 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric case DW_AT_high_pc: 1620b57cec5SDimitry Andric if (form_value.Form() == DW_FORM_addr || 1630b57cec5SDimitry Andric form_value.Form() == DW_FORM_addrx || 1640b57cec5SDimitry Andric form_value.Form() == DW_FORM_GNU_addr_index) { 1650b57cec5SDimitry Andric hi_pc = form_value.Address(); 1660b57cec5SDimitry Andric } else { 1670b57cec5SDimitry Andric hi_pc = form_value.Unsigned(); 1680b57cec5SDimitry Andric if (lo_pc == LLDB_INVALID_ADDRESS) 1690b57cec5SDimitry Andric do_offset = hi_pc != LLDB_INVALID_ADDRESS; 1700b57cec5SDimitry Andric else 1710b57cec5SDimitry Andric hi_pc += lo_pc; // DWARF 4 introduces <offset-from-lo-pc> to save 1720b57cec5SDimitry Andric // on relocations 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric break; 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric case DW_AT_ranges: 1770b57cec5SDimitry Andric ranges = GetRangesOrReportError(*cu, *this, form_value); 1780b57cec5SDimitry Andric break; 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric case DW_AT_name: 1810b57cec5SDimitry Andric if (name == nullptr) 1820b57cec5SDimitry Andric name = form_value.AsCString(); 1830b57cec5SDimitry Andric break; 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric case DW_AT_MIPS_linkage_name: 1860b57cec5SDimitry Andric case DW_AT_linkage_name: 1870b57cec5SDimitry Andric if (mangled == nullptr) 1880b57cec5SDimitry Andric mangled = form_value.AsCString(); 1890b57cec5SDimitry Andric break; 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric case DW_AT_abstract_origin: 1920b57cec5SDimitry Andric dies.push_back(form_value.Reference()); 1930b57cec5SDimitry Andric break; 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric case DW_AT_specification: 1960b57cec5SDimitry Andric dies.push_back(form_value.Reference()); 1970b57cec5SDimitry Andric break; 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric case DW_AT_decl_file: 20006c3fb27SDimitry Andric if (!decl_file) 2010b57cec5SDimitry Andric decl_file = form_value.Unsigned(); 2020b57cec5SDimitry Andric break; 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric case DW_AT_decl_line: 20506c3fb27SDimitry Andric if (!decl_line) 2060b57cec5SDimitry Andric decl_line = form_value.Unsigned(); 2070b57cec5SDimitry Andric break; 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andric case DW_AT_decl_column: 21006c3fb27SDimitry Andric if (!decl_column) 2110b57cec5SDimitry Andric decl_column = form_value.Unsigned(); 2120b57cec5SDimitry Andric break; 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric case DW_AT_call_file: 21506c3fb27SDimitry Andric if (!call_file) 2160b57cec5SDimitry Andric call_file = form_value.Unsigned(); 2170b57cec5SDimitry Andric break; 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric case DW_AT_call_line: 22006c3fb27SDimitry Andric if (!call_line) 2210b57cec5SDimitry Andric call_line = form_value.Unsigned(); 2220b57cec5SDimitry Andric break; 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric case DW_AT_call_column: 22506c3fb27SDimitry Andric if (!call_column) 2260b57cec5SDimitry Andric call_column = form_value.Unsigned(); 2270b57cec5SDimitry Andric break; 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric case DW_AT_frame_base: 2300b57cec5SDimitry Andric if (frame_base) { 2310b57cec5SDimitry Andric if (form_value.BlockData()) { 2320b57cec5SDimitry Andric uint32_t block_offset = 2330b57cec5SDimitry Andric form_value.BlockData() - data.GetDataStart(); 2340b57cec5SDimitry Andric uint32_t block_length = form_value.Unsigned(); 235753f127fSDimitry Andric *frame_base = 236753f127fSDimitry Andric DWARFExpressionList(module, 237753f127fSDimitry Andric DWARFExpression(DataExtractor( 238753f127fSDimitry Andric data, block_offset, block_length)), 239753f127fSDimitry Andric cu); 2400b57cec5SDimitry Andric } else { 241480093f4SDimitry Andric DataExtractor data = cu->GetLocationData(); 2429dba64beSDimitry Andric const dw_offset_t offset = form_value.Unsigned(); 2439dba64beSDimitry Andric if (data.ValidOffset(offset)) { 2449dba64beSDimitry Andric data = DataExtractor(data, offset, data.GetByteSize() - offset); 2450b57cec5SDimitry Andric if (lo_pc != LLDB_INVALID_ADDRESS) { 2460b57cec5SDimitry Andric assert(lo_pc >= cu->GetBaseAddress()); 247753f127fSDimitry Andric DWARFExpression::ParseDWARFLocationList(cu, data, frame_base); 248753f127fSDimitry Andric frame_base->SetFuncFileAddress(lo_pc); 249753f127fSDimitry Andric } else 2500b57cec5SDimitry Andric set_frame_base_loclist_addr = true; 2510b57cec5SDimitry Andric } 2520b57cec5SDimitry Andric } 2530b57cec5SDimitry Andric } 2540b57cec5SDimitry Andric break; 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric default: 2570b57cec5SDimitry Andric break; 2580b57cec5SDimitry Andric } 2590b57cec5SDimitry Andric } 2600b57cec5SDimitry Andric } 2610b57cec5SDimitry Andric } 2620b57cec5SDimitry Andric 2630b57cec5SDimitry Andric if (ranges.IsEmpty()) { 2640b57cec5SDimitry Andric if (lo_pc != LLDB_INVALID_ADDRESS) { 2650b57cec5SDimitry Andric if (hi_pc != LLDB_INVALID_ADDRESS && hi_pc > lo_pc) 2660b57cec5SDimitry Andric ranges.Append(DWARFRangeList::Entry(lo_pc, hi_pc - lo_pc)); 2670b57cec5SDimitry Andric else 2680b57cec5SDimitry Andric ranges.Append(DWARFRangeList::Entry(lo_pc, 0)); 2690b57cec5SDimitry Andric } 2700b57cec5SDimitry Andric } 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric if (set_frame_base_loclist_addr) { 2730b57cec5SDimitry Andric dw_addr_t lowest_range_pc = ranges.GetMinRangeBase(0); 2740b57cec5SDimitry Andric assert(lowest_range_pc >= cu->GetBaseAddress()); 275753f127fSDimitry Andric frame_base->SetFuncFileAddress(lowest_range_pc); 2760b57cec5SDimitry Andric } 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric if (ranges.IsEmpty() || name == nullptr || mangled == nullptr) { 2790b57cec5SDimitry Andric for (const DWARFDIE &die : dies) { 2800b57cec5SDimitry Andric if (die) { 2810b57cec5SDimitry Andric die.GetDIE()->GetDIENamesAndRanges(die.GetCU(), name, mangled, ranges, 2820b57cec5SDimitry Andric decl_file, decl_line, decl_column, 2830b57cec5SDimitry Andric call_file, call_line, call_column); 2840b57cec5SDimitry Andric } 2850b57cec5SDimitry Andric } 2860b57cec5SDimitry Andric } 2870b57cec5SDimitry Andric return !ranges.IsEmpty(); 2880b57cec5SDimitry Andric } 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric // Get all attribute values for a given DIE, including following any 2910b57cec5SDimitry Andric // specification or abstract origin attributes and including those in the 2920b57cec5SDimitry Andric // results. Any duplicate attributes will have the first instance take 2930b57cec5SDimitry Andric // precedence (this can happen for declaration attributes). 29406c3fb27SDimitry Andric void DWARFDebugInfoEntry::GetAttributes(DWARFUnit *cu, 2955ffd83dbSDimitry Andric DWARFAttributes &attributes, 2965ffd83dbSDimitry Andric Recurse recurse, 2970b57cec5SDimitry Andric uint32_t curr_depth) const { 2980b57cec5SDimitry Andric const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu); 29906c3fb27SDimitry Andric if (!abbrevDecl) { 30006c3fb27SDimitry Andric attributes.Clear(); 30106c3fb27SDimitry Andric return; 30206c3fb27SDimitry Andric } 30306c3fb27SDimitry Andric 3040b57cec5SDimitry Andric const DWARFDataExtractor &data = cu->GetData(); 3050b57cec5SDimitry Andric lldb::offset_t offset = GetFirstAttributeOffset(); 3060b57cec5SDimitry Andric 30706c3fb27SDimitry Andric for (const auto &attribute : abbrevDecl->attributes()) { 3080b57cec5SDimitry Andric DWARFFormValue form_value(cu); 3090b57cec5SDimitry Andric dw_attr_t attr; 31006c3fb27SDimitry Andric ExtractAttrAndFormValue(attribute, attr, form_value); 3110b57cec5SDimitry Andric 3120b57cec5SDimitry Andric // If we are tracking down DW_AT_specification or DW_AT_abstract_origin 3130b57cec5SDimitry Andric // attributes, the depth will be non-zero. We need to omit certain 3140b57cec5SDimitry Andric // attributes that don't make sense. 3150b57cec5SDimitry Andric switch (attr) { 3160b57cec5SDimitry Andric case DW_AT_sibling: 3170b57cec5SDimitry Andric case DW_AT_declaration: 3180b57cec5SDimitry Andric if (curr_depth > 0) { 3190b57cec5SDimitry Andric // This attribute doesn't make sense when combined with the DIE that 3200b57cec5SDimitry Andric // references this DIE. We know a DIE is referencing this DIE because 3210b57cec5SDimitry Andric // curr_depth is not zero 3220b57cec5SDimitry Andric break; 3230b57cec5SDimitry Andric } 324bdd1243dSDimitry Andric [[fallthrough]]; 3250b57cec5SDimitry Andric default: 326fe6060f1SDimitry Andric attributes.Append(form_value, offset, attr); 3270b57cec5SDimitry Andric break; 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric 3305ffd83dbSDimitry Andric if (recurse == Recurse::yes && 3315ffd83dbSDimitry Andric ((attr == DW_AT_specification) || (attr == DW_AT_abstract_origin))) { 3320b57cec5SDimitry Andric if (form_value.ExtractValue(data, &offset)) { 3330b57cec5SDimitry Andric DWARFDIE spec_die = form_value.Reference(); 3340b57cec5SDimitry Andric if (spec_die) 3355ffd83dbSDimitry Andric spec_die.GetDIE()->GetAttributes(spec_die.GetCU(), attributes, 3365ffd83dbSDimitry Andric recurse, curr_depth + 1); 3370b57cec5SDimitry Andric } 3380b57cec5SDimitry Andric } else { 33906c3fb27SDimitry Andric const dw_form_t form = form_value.Form(); 340bdd1243dSDimitry Andric std::optional<uint8_t> fixed_skip_size = 341bdd1243dSDimitry Andric DWARFFormValue::GetFixedSize(form, cu); 3420b57cec5SDimitry Andric if (fixed_skip_size) 3430b57cec5SDimitry Andric offset += *fixed_skip_size; 3440b57cec5SDimitry Andric else 3450b57cec5SDimitry Andric DWARFFormValue::SkipValue(form, data, &offset, cu); 3460b57cec5SDimitry Andric } 3470b57cec5SDimitry Andric } 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric // GetAttributeValue 3510b57cec5SDimitry Andric // 3520b57cec5SDimitry Andric // Get the value of an attribute and return the .debug_info or .debug_types 3530b57cec5SDimitry Andric // offset of the attribute if it was properly extracted into form_value, 3540b57cec5SDimitry Andric // or zero if we fail since an offset of zero is invalid for an attribute (it 3550b57cec5SDimitry Andric // would be a compile unit header). 3560b57cec5SDimitry Andric dw_offset_t DWARFDebugInfoEntry::GetAttributeValue( 3570b57cec5SDimitry Andric const DWARFUnit *cu, const dw_attr_t attr, DWARFFormValue &form_value, 3580b57cec5SDimitry Andric dw_offset_t *end_attr_offset_ptr, 3590b57cec5SDimitry Andric bool check_specification_or_abstract_origin) const { 3600b57cec5SDimitry Andric if (const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu)) { 36106c3fb27SDimitry Andric std::optional<uint32_t> attr_idx = abbrevDecl->findAttributeIndex(attr); 3620b57cec5SDimitry Andric 36306c3fb27SDimitry Andric if (attr_idx) { 3640b57cec5SDimitry Andric const DWARFDataExtractor &data = cu->GetData(); 3650b57cec5SDimitry Andric lldb::offset_t offset = GetFirstAttributeOffset(); 3660b57cec5SDimitry Andric 3670b57cec5SDimitry Andric uint32_t idx = 0; 36806c3fb27SDimitry Andric while (idx < *attr_idx) 36906c3fb27SDimitry Andric DWARFFormValue::SkipValue(abbrevDecl->getFormByIndex(idx++), data, 37006c3fb27SDimitry Andric &offset, cu); 3710b57cec5SDimitry Andric 3720b57cec5SDimitry Andric const dw_offset_t attr_offset = offset; 3730b57cec5SDimitry Andric form_value.SetUnit(cu); 37406c3fb27SDimitry Andric form_value.SetForm(abbrevDecl->getFormByIndex(idx)); 3750b57cec5SDimitry Andric if (form_value.ExtractValue(data, &offset)) { 3760b57cec5SDimitry Andric if (end_attr_offset_ptr) 3770b57cec5SDimitry Andric *end_attr_offset_ptr = offset; 3780b57cec5SDimitry Andric return attr_offset; 3790b57cec5SDimitry Andric } 3800b57cec5SDimitry Andric } 3810b57cec5SDimitry Andric } 3820b57cec5SDimitry Andric 3830b57cec5SDimitry Andric if (check_specification_or_abstract_origin) { 3840b57cec5SDimitry Andric if (GetAttributeValue(cu, DW_AT_specification, form_value)) { 3850b57cec5SDimitry Andric DWARFDIE die = form_value.Reference(); 3860b57cec5SDimitry Andric if (die) { 3870b57cec5SDimitry Andric dw_offset_t die_offset = die.GetDIE()->GetAttributeValue( 3880b57cec5SDimitry Andric die.GetCU(), attr, form_value, end_attr_offset_ptr, false); 3890b57cec5SDimitry Andric if (die_offset) 3900b57cec5SDimitry Andric return die_offset; 3910b57cec5SDimitry Andric } 3920b57cec5SDimitry Andric } 3930b57cec5SDimitry Andric 3940b57cec5SDimitry Andric if (GetAttributeValue(cu, DW_AT_abstract_origin, form_value)) { 3950b57cec5SDimitry Andric DWARFDIE die = form_value.Reference(); 3960b57cec5SDimitry Andric if (die) { 3970b57cec5SDimitry Andric dw_offset_t die_offset = die.GetDIE()->GetAttributeValue( 3980b57cec5SDimitry Andric die.GetCU(), attr, form_value, end_attr_offset_ptr, false); 3990b57cec5SDimitry Andric if (die_offset) 4000b57cec5SDimitry Andric return die_offset; 4010b57cec5SDimitry Andric } 4020b57cec5SDimitry Andric } 4030b57cec5SDimitry Andric } 4040b57cec5SDimitry Andric return 0; 4050b57cec5SDimitry Andric } 4060b57cec5SDimitry Andric 4070b57cec5SDimitry Andric // GetAttributeValueAsString 4080b57cec5SDimitry Andric // 4090b57cec5SDimitry Andric // Get the value of an attribute as a string return it. The resulting pointer 4100b57cec5SDimitry Andric // to the string data exists within the supplied SymbolFileDWARF and will only 4110b57cec5SDimitry Andric // be available as long as the SymbolFileDWARF is still around and it's content 4120b57cec5SDimitry Andric // doesn't change. 4130b57cec5SDimitry Andric const char *DWARFDebugInfoEntry::GetAttributeValueAsString( 4140b57cec5SDimitry Andric const DWARFUnit *cu, const dw_attr_t attr, const char *fail_value, 4150b57cec5SDimitry Andric bool check_specification_or_abstract_origin) const { 4160b57cec5SDimitry Andric DWARFFormValue form_value; 4170b57cec5SDimitry Andric if (GetAttributeValue(cu, attr, form_value, nullptr, 4180b57cec5SDimitry Andric check_specification_or_abstract_origin)) 4190b57cec5SDimitry Andric return form_value.AsCString(); 4200b57cec5SDimitry Andric return fail_value; 4210b57cec5SDimitry Andric } 4220b57cec5SDimitry Andric 4230b57cec5SDimitry Andric // GetAttributeValueAsUnsigned 4240b57cec5SDimitry Andric // 4250b57cec5SDimitry Andric // Get the value of an attribute as unsigned and return it. 4260b57cec5SDimitry Andric uint64_t DWARFDebugInfoEntry::GetAttributeValueAsUnsigned( 4270b57cec5SDimitry Andric const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value, 4280b57cec5SDimitry Andric bool check_specification_or_abstract_origin) const { 4290b57cec5SDimitry Andric DWARFFormValue form_value; 4300b57cec5SDimitry Andric if (GetAttributeValue(cu, attr, form_value, nullptr, 4310b57cec5SDimitry Andric check_specification_or_abstract_origin)) 4320b57cec5SDimitry Andric return form_value.Unsigned(); 4330b57cec5SDimitry Andric return fail_value; 4340b57cec5SDimitry Andric } 4350b57cec5SDimitry Andric 436bdd1243dSDimitry Andric std::optional<uint64_t> 437bdd1243dSDimitry Andric DWARFDebugInfoEntry::GetAttributeValueAsOptionalUnsigned( 438bdd1243dSDimitry Andric const DWARFUnit *cu, const dw_attr_t attr, 439bdd1243dSDimitry Andric bool check_specification_or_abstract_origin) const { 440bdd1243dSDimitry Andric DWARFFormValue form_value; 441bdd1243dSDimitry Andric if (GetAttributeValue(cu, attr, form_value, nullptr, 442bdd1243dSDimitry Andric check_specification_or_abstract_origin)) 443bdd1243dSDimitry Andric return form_value.Unsigned(); 444bdd1243dSDimitry Andric return std::nullopt; 445bdd1243dSDimitry Andric } 446bdd1243dSDimitry Andric 4470b57cec5SDimitry Andric // GetAttributeValueAsReference 4480b57cec5SDimitry Andric // 4490b57cec5SDimitry Andric // Get the value of an attribute as reference and fix up and compile unit 4500b57cec5SDimitry Andric // relative offsets as needed. 4510b57cec5SDimitry Andric DWARFDIE DWARFDebugInfoEntry::GetAttributeValueAsReference( 4520b57cec5SDimitry Andric const DWARFUnit *cu, const dw_attr_t attr, 4530b57cec5SDimitry Andric bool check_specification_or_abstract_origin) const { 4540b57cec5SDimitry Andric DWARFFormValue form_value; 4550b57cec5SDimitry Andric if (GetAttributeValue(cu, attr, form_value, nullptr, 4560b57cec5SDimitry Andric check_specification_or_abstract_origin)) 4570b57cec5SDimitry Andric return form_value.Reference(); 4580b57cec5SDimitry Andric return {}; 4590b57cec5SDimitry Andric } 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric uint64_t DWARFDebugInfoEntry::GetAttributeValueAsAddress( 4620b57cec5SDimitry Andric const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value, 4630b57cec5SDimitry Andric bool check_specification_or_abstract_origin) const { 4640b57cec5SDimitry Andric DWARFFormValue form_value; 4650b57cec5SDimitry Andric if (GetAttributeValue(cu, attr, form_value, nullptr, 4660b57cec5SDimitry Andric check_specification_or_abstract_origin)) 4670b57cec5SDimitry Andric return form_value.Address(); 4680b57cec5SDimitry Andric return fail_value; 4690b57cec5SDimitry Andric } 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric // GetAttributeHighPC 4720b57cec5SDimitry Andric // 4730b57cec5SDimitry Andric // Get the hi_pc, adding hi_pc to lo_pc when specified as an <offset-from-low- 4740b57cec5SDimitry Andric // pc>. 4750b57cec5SDimitry Andric // 4760b57cec5SDimitry Andric // Returns the hi_pc or fail_value. 4770b57cec5SDimitry Andric dw_addr_t DWARFDebugInfoEntry::GetAttributeHighPC( 4780b57cec5SDimitry Andric const DWARFUnit *cu, dw_addr_t lo_pc, uint64_t fail_value, 4790b57cec5SDimitry Andric bool check_specification_or_abstract_origin) const { 4800b57cec5SDimitry Andric DWARFFormValue form_value; 4810b57cec5SDimitry Andric if (GetAttributeValue(cu, DW_AT_high_pc, form_value, nullptr, 4820b57cec5SDimitry Andric check_specification_or_abstract_origin)) { 4830b57cec5SDimitry Andric dw_form_t form = form_value.Form(); 4840b57cec5SDimitry Andric if (form == DW_FORM_addr || form == DW_FORM_addrx || 4850b57cec5SDimitry Andric form == DW_FORM_GNU_addr_index) 4860b57cec5SDimitry Andric return form_value.Address(); 4870b57cec5SDimitry Andric 4880b57cec5SDimitry Andric // DWARF4 can specify the hi_pc as an <offset-from-lowpc> 4890b57cec5SDimitry Andric return lo_pc + form_value.Unsigned(); 4900b57cec5SDimitry Andric } 4910b57cec5SDimitry Andric return fail_value; 4920b57cec5SDimitry Andric } 4930b57cec5SDimitry Andric 4940b57cec5SDimitry Andric // GetAttributeAddressRange 4950b57cec5SDimitry Andric // 4960b57cec5SDimitry Andric // Get the lo_pc and hi_pc, adding hi_pc to lo_pc when specified as an <offset- 4970b57cec5SDimitry Andric // from-low-pc>. 4980b57cec5SDimitry Andric // 4990b57cec5SDimitry Andric // Returns true or sets lo_pc and hi_pc to fail_value. 5000b57cec5SDimitry Andric bool DWARFDebugInfoEntry::GetAttributeAddressRange( 5010b57cec5SDimitry Andric const DWARFUnit *cu, dw_addr_t &lo_pc, dw_addr_t &hi_pc, 5020b57cec5SDimitry Andric uint64_t fail_value, bool check_specification_or_abstract_origin) const { 5030b57cec5SDimitry Andric lo_pc = GetAttributeValueAsAddress(cu, DW_AT_low_pc, fail_value, 5040b57cec5SDimitry Andric check_specification_or_abstract_origin); 5050b57cec5SDimitry Andric if (lo_pc != fail_value) { 5060b57cec5SDimitry Andric hi_pc = GetAttributeHighPC(cu, lo_pc, fail_value, 5070b57cec5SDimitry Andric check_specification_or_abstract_origin); 5080b57cec5SDimitry Andric if (hi_pc != fail_value) 5090b57cec5SDimitry Andric return true; 5100b57cec5SDimitry Andric } 5110b57cec5SDimitry Andric lo_pc = fail_value; 5120b57cec5SDimitry Andric hi_pc = fail_value; 5130b57cec5SDimitry Andric return false; 5140b57cec5SDimitry Andric } 5150b57cec5SDimitry Andric 51606c3fb27SDimitry Andric DWARFRangeList DWARFDebugInfoEntry::GetAttributeAddressRanges( 51706c3fb27SDimitry Andric DWARFUnit *cu, bool check_hi_lo_pc, 5180b57cec5SDimitry Andric bool check_specification_or_abstract_origin) const { 5190b57cec5SDimitry Andric 5200b57cec5SDimitry Andric DWARFFormValue form_value; 52106c3fb27SDimitry Andric if (GetAttributeValue(cu, DW_AT_ranges, form_value)) 52206c3fb27SDimitry Andric return GetRangesOrReportError(*cu, *this, form_value); 52306c3fb27SDimitry Andric 52406c3fb27SDimitry Andric DWARFRangeList ranges; 52506c3fb27SDimitry Andric if (check_hi_lo_pc) { 5260b57cec5SDimitry Andric dw_addr_t lo_pc = LLDB_INVALID_ADDRESS; 5270b57cec5SDimitry Andric dw_addr_t hi_pc = LLDB_INVALID_ADDRESS; 5280b57cec5SDimitry Andric if (GetAttributeAddressRange(cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS, 5290b57cec5SDimitry Andric check_specification_or_abstract_origin)) { 5300b57cec5SDimitry Andric if (lo_pc < hi_pc) 5310b57cec5SDimitry Andric ranges.Append(DWARFRangeList::Entry(lo_pc, hi_pc - lo_pc)); 5320b57cec5SDimitry Andric } 5330b57cec5SDimitry Andric } 53406c3fb27SDimitry Andric return ranges; 5350b57cec5SDimitry Andric } 5360b57cec5SDimitry Andric 5370b57cec5SDimitry Andric // GetName 5380b57cec5SDimitry Andric // 5390b57cec5SDimitry Andric // Get value of the DW_AT_name attribute and return it if one exists, else 5400b57cec5SDimitry Andric // return NULL. 5410b57cec5SDimitry Andric const char *DWARFDebugInfoEntry::GetName(const DWARFUnit *cu) const { 5420b57cec5SDimitry Andric return GetAttributeValueAsString(cu, DW_AT_name, nullptr, true); 5430b57cec5SDimitry Andric } 5440b57cec5SDimitry Andric 5450b57cec5SDimitry Andric // GetMangledName 5460b57cec5SDimitry Andric // 5470b57cec5SDimitry Andric // Get value of the DW_AT_MIPS_linkage_name attribute and return it if one 5480b57cec5SDimitry Andric // exists, else return the value of the DW_AT_name attribute 5490b57cec5SDimitry Andric const char * 5500b57cec5SDimitry Andric DWARFDebugInfoEntry::GetMangledName(const DWARFUnit *cu, 5510b57cec5SDimitry Andric bool substitute_name_allowed) const { 5520b57cec5SDimitry Andric const char *name = nullptr; 5530b57cec5SDimitry Andric 5540b57cec5SDimitry Andric name = GetAttributeValueAsString(cu, DW_AT_MIPS_linkage_name, nullptr, true); 5550b57cec5SDimitry Andric if (name) 5560b57cec5SDimitry Andric return name; 5570b57cec5SDimitry Andric 5580b57cec5SDimitry Andric name = GetAttributeValueAsString(cu, DW_AT_linkage_name, nullptr, true); 5590b57cec5SDimitry Andric if (name) 5600b57cec5SDimitry Andric return name; 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric if (!substitute_name_allowed) 5630b57cec5SDimitry Andric return nullptr; 5640b57cec5SDimitry Andric 5650b57cec5SDimitry Andric name = GetAttributeValueAsString(cu, DW_AT_name, nullptr, true); 5660b57cec5SDimitry Andric return name; 5670b57cec5SDimitry Andric } 5680b57cec5SDimitry Andric 5690b57cec5SDimitry Andric // GetPubname 5700b57cec5SDimitry Andric // 5710b57cec5SDimitry Andric // Get value the name for a DIE as it should appear for a .debug_pubnames or 5720b57cec5SDimitry Andric // .debug_pubtypes section. 5730b57cec5SDimitry Andric const char *DWARFDebugInfoEntry::GetPubname(const DWARFUnit *cu) const { 5740b57cec5SDimitry Andric const char *name = nullptr; 5750b57cec5SDimitry Andric if (!cu) 5760b57cec5SDimitry Andric return name; 5770b57cec5SDimitry Andric 5780b57cec5SDimitry Andric name = GetAttributeValueAsString(cu, DW_AT_MIPS_linkage_name, nullptr, true); 5790b57cec5SDimitry Andric if (name) 5800b57cec5SDimitry Andric return name; 5810b57cec5SDimitry Andric 5820b57cec5SDimitry Andric name = GetAttributeValueAsString(cu, DW_AT_linkage_name, nullptr, true); 5830b57cec5SDimitry Andric if (name) 5840b57cec5SDimitry Andric return name; 5850b57cec5SDimitry Andric 5860b57cec5SDimitry Andric name = GetAttributeValueAsString(cu, DW_AT_name, nullptr, true); 5870b57cec5SDimitry Andric return name; 5880b57cec5SDimitry Andric } 5890b57cec5SDimitry Andric 5905ffd83dbSDimitry Andric /// This function is builds a table very similar to the standard .debug_aranges 5915ffd83dbSDimitry Andric /// table, except that the actual DIE offset for the function is placed in the 5925ffd83dbSDimitry Andric /// table instead of the compile unit offset. 5930b57cec5SDimitry Andric void DWARFDebugInfoEntry::BuildFunctionAddressRangeTable( 594e8d8bef9SDimitry Andric DWARFUnit *cu, DWARFDebugAranges *debug_aranges) const { 5950b57cec5SDimitry Andric if (m_tag) { 5960b57cec5SDimitry Andric if (m_tag == DW_TAG_subprogram) { 59706c3fb27SDimitry Andric DWARFRangeList ranges = 59806c3fb27SDimitry Andric GetAttributeAddressRanges(cu, /*check_hi_lo_pc=*/true); 599e8d8bef9SDimitry Andric for (const auto &r : ranges) { 600e8d8bef9SDimitry Andric debug_aranges->AppendRange(GetOffset(), r.GetRangeBase(), 601e8d8bef9SDimitry Andric r.GetRangeEnd()); 6020b57cec5SDimitry Andric } 6030b57cec5SDimitry Andric } 6040b57cec5SDimitry Andric 6050b57cec5SDimitry Andric const DWARFDebugInfoEntry *child = GetFirstChild(); 6060b57cec5SDimitry Andric while (child) { 6070b57cec5SDimitry Andric child->BuildFunctionAddressRangeTable(cu, debug_aranges); 6080b57cec5SDimitry Andric child = child->GetSibling(); 6090b57cec5SDimitry Andric } 6100b57cec5SDimitry Andric } 6110b57cec5SDimitry Andric } 6120b57cec5SDimitry Andric 6130b57cec5SDimitry Andric lldb::offset_t DWARFDebugInfoEntry::GetFirstAttributeOffset() const { 6140b57cec5SDimitry Andric return GetOffset() + llvm::getULEB128Size(m_abbr_idx); 6150b57cec5SDimitry Andric } 6160b57cec5SDimitry Andric 6175f757f3fSDimitry Andric const llvm::DWARFAbbreviationDeclaration * 6180b57cec5SDimitry Andric DWARFDebugInfoEntry::GetAbbreviationDeclarationPtr(const DWARFUnit *cu) const { 61906c3fb27SDimitry Andric if (!cu) 6200b57cec5SDimitry Andric return nullptr; 62106c3fb27SDimitry Andric 6225f757f3fSDimitry Andric const llvm::DWARFAbbreviationDeclarationSet *abbrev_set = 6235f757f3fSDimitry Andric cu->GetAbbreviations(); 62406c3fb27SDimitry Andric if (!abbrev_set) 62506c3fb27SDimitry Andric return nullptr; 62606c3fb27SDimitry Andric 62706c3fb27SDimitry Andric return abbrev_set->getAbbreviationDeclaration(m_abbr_idx); 6280b57cec5SDimitry Andric } 6290b57cec5SDimitry Andric 6305ffd83dbSDimitry Andric bool DWARFDebugInfoEntry::IsGlobalOrStaticScopeVariable() const { 6315ffd83dbSDimitry Andric if (Tag() != DW_TAG_variable) 6325ffd83dbSDimitry Andric return false; 6335ffd83dbSDimitry Andric const DWARFDebugInfoEntry *parent_die = GetParent(); 6345ffd83dbSDimitry Andric while (parent_die != nullptr) { 6355ffd83dbSDimitry Andric switch (parent_die->Tag()) { 6365ffd83dbSDimitry Andric case DW_TAG_subprogram: 6375ffd83dbSDimitry Andric case DW_TAG_lexical_block: 6385ffd83dbSDimitry Andric case DW_TAG_inlined_subroutine: 6395ffd83dbSDimitry Andric return false; 6405ffd83dbSDimitry Andric 6415ffd83dbSDimitry Andric case DW_TAG_compile_unit: 6425ffd83dbSDimitry Andric case DW_TAG_partial_unit: 6435ffd83dbSDimitry Andric return true; 6445ffd83dbSDimitry Andric 6455ffd83dbSDimitry Andric default: 6465ffd83dbSDimitry Andric break; 6475ffd83dbSDimitry Andric } 6485ffd83dbSDimitry Andric parent_die = parent_die->GetParent(); 6495ffd83dbSDimitry Andric } 6505ffd83dbSDimitry Andric return false; 6515ffd83dbSDimitry Andric } 6525ffd83dbSDimitry Andric 6530b57cec5SDimitry Andric bool DWARFDebugInfoEntry::operator==(const DWARFDebugInfoEntry &rhs) const { 6540b57cec5SDimitry Andric return m_offset == rhs.m_offset && m_parent_idx == rhs.m_parent_idx && 6550b57cec5SDimitry Andric m_sibling_idx == rhs.m_sibling_idx && 6560b57cec5SDimitry Andric m_abbr_idx == rhs.m_abbr_idx && m_has_children == rhs.m_has_children && 6570b57cec5SDimitry Andric m_tag == rhs.m_tag; 6580b57cec5SDimitry Andric } 6590b57cec5SDimitry Andric 6600b57cec5SDimitry Andric bool DWARFDebugInfoEntry::operator!=(const DWARFDebugInfoEntry &rhs) const { 6610b57cec5SDimitry Andric return !(*this == rhs); 6620b57cec5SDimitry Andric } 663