15ffd83dbSDimitry Andric //===-- DWARFDebugInfo.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 "SymbolFileDWARF.h" 100b57cec5SDimitry Andric 110b57cec5SDimitry Andric #include <algorithm> 120b57cec5SDimitry Andric #include <set> 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "lldb/Host/PosixApi.h" 150b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h" 160b57cec5SDimitry Andric #include "lldb/Utility/RegularExpression.h" 170b57cec5SDimitry Andric #include "lldb/Utility/Stream.h" 180b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric #include "DWARFCompileUnit.h" 210b57cec5SDimitry Andric #include "DWARFContext.h" 220b57cec5SDimitry Andric #include "DWARFDebugAranges.h" 230b57cec5SDimitry Andric #include "DWARFDebugInfo.h" 240b57cec5SDimitry Andric #include "DWARFDebugInfoEntry.h" 250b57cec5SDimitry Andric #include "DWARFFormValue.h" 260b57cec5SDimitry Andric #include "DWARFTypeUnit.h" 27*0fca6ea1SDimitry Andric #include "LogChannelDWARF.h" 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric using namespace lldb; 300b57cec5SDimitry Andric using namespace lldb_private; 315f757f3fSDimitry Andric using namespace lldb_private::plugin::dwarf; 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric // Constructor 345f757f3fSDimitry Andric DWARFDebugInfo::DWARFDebugInfo(SymbolFileDWARF &dwarf, DWARFContext &context) 350b57cec5SDimitry Andric : m_dwarf(dwarf), m_context(context), m_units(), m_cu_aranges_up() {} 360b57cec5SDimitry Andric 37fe6060f1SDimitry Andric const DWARFDebugAranges &DWARFDebugInfo::GetCompileUnitAranges() { 380b57cec5SDimitry Andric if (m_cu_aranges_up) 390b57cec5SDimitry Andric return *m_cu_aranges_up; 400b57cec5SDimitry Andric 419dba64beSDimitry Andric m_cu_aranges_up = std::make_unique<DWARFDebugAranges>(); 420b57cec5SDimitry Andric const DWARFDataExtractor &debug_aranges_data = 430b57cec5SDimitry Andric m_context.getOrLoadArangesData(); 440b57cec5SDimitry Andric 45fe6060f1SDimitry Andric // Extract what we can from the .debug_aranges first. 46fe6060f1SDimitry Andric m_cu_aranges_up->extract(debug_aranges_data); 47fe6060f1SDimitry Andric 48fe6060f1SDimitry Andric // Make a list of all CUs represented by the .debug_aranges data. 490b57cec5SDimitry Andric std::set<dw_offset_t> cus_with_data; 500b57cec5SDimitry Andric for (size_t n = 0; n < m_cu_aranges_up->GetNumRanges(); n++) { 510b57cec5SDimitry Andric dw_offset_t offset = m_cu_aranges_up->OffsetAtIndex(n); 520b57cec5SDimitry Andric if (offset != DW_INVALID_OFFSET) 530b57cec5SDimitry Andric cus_with_data.insert(offset); 540b57cec5SDimitry Andric } 550b57cec5SDimitry Andric 56fe6060f1SDimitry Andric // Manually build arange data for everything that wasn't in .debug_aranges. 57bdd1243dSDimitry Andric // The .debug_aranges accelerator is not guaranteed to be complete. 58bdd1243dSDimitry Andric // Tools such as dsymutil can provide stronger guarantees than required by the 59bdd1243dSDimitry Andric // standard. Without that guarantee, we have to iterate over every CU in the 60bdd1243dSDimitry Andric // .debug_info and make sure there's a corresponding entry in the table and if 61bdd1243dSDimitry Andric // not, add one for every subprogram. 62bdd1243dSDimitry Andric ObjectFile *OF = m_dwarf.GetObjectFile(); 63bdd1243dSDimitry Andric if (!OF || !OF->CanTrustAddressRanges()) { 640b57cec5SDimitry Andric const size_t num_units = GetNumUnits(); 650b57cec5SDimitry Andric for (size_t idx = 0; idx < num_units; ++idx) { 660b57cec5SDimitry Andric DWARFUnit *cu = GetUnitAtIndex(idx); 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric dw_offset_t offset = cu->GetOffset(); 690b57cec5SDimitry Andric if (cus_with_data.find(offset) == cus_with_data.end()) 700b57cec5SDimitry Andric cu->BuildAddressRangeTable(m_cu_aranges_up.get()); 710b57cec5SDimitry Andric } 72bdd1243dSDimitry Andric } 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric const bool minimize = true; 750b57cec5SDimitry Andric m_cu_aranges_up->Sort(minimize); 760b57cec5SDimitry Andric return *m_cu_aranges_up; 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric void DWARFDebugInfo::ParseUnitsFor(DIERef::Section section) { 800b57cec5SDimitry Andric DWARFDataExtractor data = section == DIERef::Section::DebugTypes 810b57cec5SDimitry Andric ? m_context.getOrLoadDebugTypesData() 820b57cec5SDimitry Andric : m_context.getOrLoadDebugInfoData(); 830b57cec5SDimitry Andric lldb::offset_t offset = 0; 840b57cec5SDimitry Andric while (data.ValidOffset(offset)) { 85*0fca6ea1SDimitry Andric const lldb::offset_t unit_header_offset = offset; 86*0fca6ea1SDimitry Andric llvm::Expected<DWARFUnitSP> expected_unit_sp = 87*0fca6ea1SDimitry Andric DWARFUnit::extract(m_dwarf, m_units.size(), data, section, &offset); 880b57cec5SDimitry Andric 89*0fca6ea1SDimitry Andric if (!expected_unit_sp) { 90*0fca6ea1SDimitry Andric Log *log = GetLog(DWARFLog::DebugInfo); 91*0fca6ea1SDimitry Andric if (log) 92*0fca6ea1SDimitry Andric LLDB_LOG(log, "Unable to extract DWARFUnitHeader at {0:x}: {1}", 93*0fca6ea1SDimitry Andric unit_header_offset, 94*0fca6ea1SDimitry Andric llvm::toString(expected_unit_sp.takeError())); 95*0fca6ea1SDimitry Andric else 96*0fca6ea1SDimitry Andric llvm::consumeError(expected_unit_sp.takeError()); 970b57cec5SDimitry Andric return; 980b57cec5SDimitry Andric } 990b57cec5SDimitry Andric 100*0fca6ea1SDimitry Andric DWARFUnitSP unit_sp = *expected_unit_sp; 1010b57cec5SDimitry Andric 102*0fca6ea1SDimitry Andric // If it didn't return an error, then it should be returning a valid Unit. 103*0fca6ea1SDimitry Andric assert((bool)unit_sp); 104*0fca6ea1SDimitry Andric 105*0fca6ea1SDimitry Andric // Keep a map of DWO ID back to the skeleton units. Sometimes accelerator 106*0fca6ea1SDimitry Andric // table lookups can cause the DWO files to be accessed before the skeleton 107*0fca6ea1SDimitry Andric // compile unit is parsed, so we keep a map to allow us to match up the DWO 108*0fca6ea1SDimitry Andric // file to the back to the skeleton compile units. 109*0fca6ea1SDimitry Andric if (unit_sp->GetUnitType() == lldb_private::dwarf::DW_UT_skeleton) { 110*0fca6ea1SDimitry Andric if (std::optional<uint64_t> unit_dwo_id = unit_sp->GetHeaderDWOId()) 111*0fca6ea1SDimitry Andric m_dwarf5_dwo_id_to_skeleton_unit[*unit_dwo_id] = unit_sp.get(); 112*0fca6ea1SDimitry Andric } 113*0fca6ea1SDimitry Andric 114*0fca6ea1SDimitry Andric m_units.push_back(unit_sp); 115*0fca6ea1SDimitry Andric offset = unit_sp->GetNextUnitOffset(); 116*0fca6ea1SDimitry Andric 117*0fca6ea1SDimitry Andric if (auto *type_unit = llvm::dyn_cast<DWARFTypeUnit>(unit_sp.get())) { 1180b57cec5SDimitry Andric m_type_hash_to_unit_index.emplace_back(type_unit->GetTypeHash(), 119*0fca6ea1SDimitry Andric unit_sp->GetID()); 1200b57cec5SDimitry Andric } 1210b57cec5SDimitry Andric } 1220b57cec5SDimitry Andric } 1230b57cec5SDimitry Andric 124*0fca6ea1SDimitry Andric DWARFUnit *DWARFDebugInfo::GetSkeletonUnit(DWARFUnit *dwo_unit) { 125*0fca6ea1SDimitry Andric // If this isn't a DWO unit, don't try and find the skeleton unit. 126*0fca6ea1SDimitry Andric if (!dwo_unit->IsDWOUnit()) 127*0fca6ea1SDimitry Andric return nullptr; 128*0fca6ea1SDimitry Andric 129*0fca6ea1SDimitry Andric auto dwo_id = dwo_unit->GetDWOId(); 130*0fca6ea1SDimitry Andric if (!dwo_id.has_value()) 131*0fca6ea1SDimitry Andric return nullptr; 132*0fca6ea1SDimitry Andric 133*0fca6ea1SDimitry Andric // Parse the unit headers so that m_dwarf5_dwo_id_to_skeleton_unit is filled 134*0fca6ea1SDimitry Andric // in with all of the DWARF5 skeleton compile units DWO IDs since it is easy 135*0fca6ea1SDimitry Andric // to access the DWO IDs in the DWARFUnitHeader for each DWARFUnit. 136*0fca6ea1SDimitry Andric ParseUnitHeadersIfNeeded(); 137*0fca6ea1SDimitry Andric 138*0fca6ea1SDimitry Andric // Find the value in our cache and return it we we find it. This cache may 139*0fca6ea1SDimitry Andric // only contain DWARF5 units. 140*0fca6ea1SDimitry Andric auto iter = m_dwarf5_dwo_id_to_skeleton_unit.find(*dwo_id); 141*0fca6ea1SDimitry Andric if (iter != m_dwarf5_dwo_id_to_skeleton_unit.end()) 142*0fca6ea1SDimitry Andric return iter->second; 143*0fca6ea1SDimitry Andric 144*0fca6ea1SDimitry Andric // DWARF5 unit headers have the DWO ID and should have already been in the map 145*0fca6ea1SDimitry Andric // so if it wasn't found in the above find() call, then we didn't find it and 146*0fca6ea1SDimitry Andric // don't need to do the more expensive DWARF4 search. 147*0fca6ea1SDimitry Andric if (dwo_unit->GetVersion() >= 5) 148*0fca6ea1SDimitry Andric return nullptr; 149*0fca6ea1SDimitry Andric 150*0fca6ea1SDimitry Andric // Parse all DWO IDs from all DWARF4 and earlier compile units that have DWO 151*0fca6ea1SDimitry Andric // IDs. It is more expensive to get the DWO IDs from DWARF4 compile units as 152*0fca6ea1SDimitry Andric // we need to parse the unit DIE and extract the DW_AT_dwo_id or 153*0fca6ea1SDimitry Andric // DW_AT_GNU_dwo_id attribute values, so do this only if we didn't find our 154*0fca6ea1SDimitry Andric // match above search and only for DWARF4 and earlier compile units. 155*0fca6ea1SDimitry Andric llvm::call_once(m_dwarf4_dwo_id_to_skeleton_unit_once_flag, [this]() { 156*0fca6ea1SDimitry Andric for (uint32_t i = 0, num = GetNumUnits(); i < num; ++i) { 157*0fca6ea1SDimitry Andric if (DWARFUnit *unit = GetUnitAtIndex(i)) { 158*0fca6ea1SDimitry Andric if (unit->GetVersion() < 5) { 159*0fca6ea1SDimitry Andric if (std::optional<uint64_t> unit_dwo_id = unit->GetDWOId()) 160*0fca6ea1SDimitry Andric m_dwarf4_dwo_id_to_skeleton_unit[*unit_dwo_id] = unit; 161*0fca6ea1SDimitry Andric } 162*0fca6ea1SDimitry Andric } 163*0fca6ea1SDimitry Andric } 164*0fca6ea1SDimitry Andric }); 165*0fca6ea1SDimitry Andric 166*0fca6ea1SDimitry Andric // Search the DWARF4 DWO results that we parsed lazily. 167*0fca6ea1SDimitry Andric iter = m_dwarf4_dwo_id_to_skeleton_unit.find(*dwo_id); 168*0fca6ea1SDimitry Andric if (iter != m_dwarf4_dwo_id_to_skeleton_unit.end()) 169*0fca6ea1SDimitry Andric return iter->second; 170*0fca6ea1SDimitry Andric return nullptr; 171*0fca6ea1SDimitry Andric } 172*0fca6ea1SDimitry Andric 1730b57cec5SDimitry Andric void DWARFDebugInfo::ParseUnitHeadersIfNeeded() { 1745ffd83dbSDimitry Andric llvm::call_once(m_units_once_flag, [&] { 1750b57cec5SDimitry Andric ParseUnitsFor(DIERef::Section::DebugInfo); 1760b57cec5SDimitry Andric ParseUnitsFor(DIERef::Section::DebugTypes); 1770b57cec5SDimitry Andric llvm::sort(m_type_hash_to_unit_index, llvm::less_first()); 1785ffd83dbSDimitry Andric }); 1790b57cec5SDimitry Andric } 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric size_t DWARFDebugInfo::GetNumUnits() { 1820b57cec5SDimitry Andric ParseUnitHeadersIfNeeded(); 1830b57cec5SDimitry Andric return m_units.size(); 1840b57cec5SDimitry Andric } 1850b57cec5SDimitry Andric 1865ffd83dbSDimitry Andric DWARFUnit *DWARFDebugInfo::GetUnitAtIndex(size_t idx) { 1870b57cec5SDimitry Andric DWARFUnit *cu = nullptr; 1880b57cec5SDimitry Andric if (idx < GetNumUnits()) 1890b57cec5SDimitry Andric cu = m_units[idx].get(); 1900b57cec5SDimitry Andric return cu; 1910b57cec5SDimitry Andric } 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric uint32_t DWARFDebugInfo::FindUnitIndex(DIERef::Section section, 1940b57cec5SDimitry Andric dw_offset_t offset) { 1950b57cec5SDimitry Andric ParseUnitHeadersIfNeeded(); 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric // llvm::lower_bound is not used as for DIE offsets it would still return 1980b57cec5SDimitry Andric // index +1 and GetOffset() returning index itself would be a special case. 1990b57cec5SDimitry Andric auto pos = llvm::upper_bound( 2000b57cec5SDimitry Andric m_units, std::make_pair(section, offset), 2010b57cec5SDimitry Andric [](const std::pair<DIERef::Section, dw_offset_t> &lhs, 2020b57cec5SDimitry Andric const DWARFUnitSP &rhs) { 2030b57cec5SDimitry Andric return lhs < std::make_pair(rhs->GetDebugSection(), rhs->GetOffset()); 2040b57cec5SDimitry Andric }); 2050b57cec5SDimitry Andric uint32_t idx = std::distance(m_units.begin(), pos); 2060b57cec5SDimitry Andric if (idx == 0) 20706c3fb27SDimitry Andric return DW_INVALID_INDEX; 2080b57cec5SDimitry Andric return idx - 1; 2090b57cec5SDimitry Andric } 2100b57cec5SDimitry Andric 2110b57cec5SDimitry Andric DWARFUnit *DWARFDebugInfo::GetUnitAtOffset(DIERef::Section section, 2120b57cec5SDimitry Andric dw_offset_t cu_offset, 2130b57cec5SDimitry Andric uint32_t *idx_ptr) { 2140b57cec5SDimitry Andric uint32_t idx = FindUnitIndex(section, cu_offset); 2150b57cec5SDimitry Andric DWARFUnit *result = GetUnitAtIndex(idx); 2160b57cec5SDimitry Andric if (result && result->GetOffset() != cu_offset) { 2170b57cec5SDimitry Andric result = nullptr; 2180b57cec5SDimitry Andric idx = DW_INVALID_INDEX; 2190b57cec5SDimitry Andric } 2200b57cec5SDimitry Andric if (idx_ptr) 2210b57cec5SDimitry Andric *idx_ptr = idx; 2220b57cec5SDimitry Andric return result; 2230b57cec5SDimitry Andric } 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric DWARFUnit * 2260b57cec5SDimitry Andric DWARFDebugInfo::GetUnitContainingDIEOffset(DIERef::Section section, 2270b57cec5SDimitry Andric dw_offset_t die_offset) { 2280b57cec5SDimitry Andric uint32_t idx = FindUnitIndex(section, die_offset); 2290b57cec5SDimitry Andric DWARFUnit *result = GetUnitAtIndex(idx); 2300b57cec5SDimitry Andric if (result && !result->ContainsDIEOffset(die_offset)) 2310b57cec5SDimitry Andric return nullptr; 2320b57cec5SDimitry Andric return result; 2330b57cec5SDimitry Andric } 2340b57cec5SDimitry Andric 235*0fca6ea1SDimitry Andric const std::shared_ptr<SymbolFileDWARFDwo> &DWARFDebugInfo::GetDwpSymbolFile() { 236*0fca6ea1SDimitry Andric return m_dwarf.GetDwpSymbolFile(); 237*0fca6ea1SDimitry Andric } 238*0fca6ea1SDimitry Andric 2390b57cec5SDimitry Andric DWARFTypeUnit *DWARFDebugInfo::GetTypeUnitForHash(uint64_t hash) { 2400b57cec5SDimitry Andric auto pos = llvm::lower_bound(m_type_hash_to_unit_index, 2410b57cec5SDimitry Andric std::make_pair(hash, 0u), llvm::less_first()); 2420b57cec5SDimitry Andric if (pos == m_type_hash_to_unit_index.end() || pos->first != hash) 2430b57cec5SDimitry Andric return nullptr; 2440b57cec5SDimitry Andric return llvm::cast<DWARFTypeUnit>(GetUnitAtIndex(pos->second)); 2450b57cec5SDimitry Andric } 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric bool DWARFDebugInfo::ContainsTypeUnits() { 2480b57cec5SDimitry Andric ParseUnitHeadersIfNeeded(); 2490b57cec5SDimitry Andric return !m_type_hash_to_unit_index.empty(); 2500b57cec5SDimitry Andric } 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric // GetDIE() 2530b57cec5SDimitry Andric // 2540b57cec5SDimitry Andric // Get the DIE (Debug Information Entry) with the specified offset. 2550b57cec5SDimitry Andric DWARFDIE 256*0fca6ea1SDimitry Andric DWARFDebugInfo::GetDIE(DIERef::Section section, dw_offset_t die_offset) { 257*0fca6ea1SDimitry Andric if (DWARFUnit *cu = GetUnitContainingDIEOffset(section, die_offset)) 258*0fca6ea1SDimitry Andric return cu->GetNonSkeletonUnit().GetDIE(die_offset); 2590b57cec5SDimitry Andric return DWARFDIE(); // Not found 2600b57cec5SDimitry Andric } 261