1254721Semaste//===-- DWARFDebugInfo.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 "SymbolFileDWARF.h" 10254721Semaste 11254721Semaste#include <algorithm> 12254721Semaste#include <set> 13254721Semaste 14314564Sdim#include "lldb/Host/PosixApi.h" 15254721Semaste#include "lldb/Symbol/ObjectFile.h" 16321369Sdim#include "lldb/Utility/RegularExpression.h" 17321369Sdim#include "lldb/Utility/Stream.h" 18353358Sdim#include "llvm/Support/Casting.h" 19254721Semaste 20314564Sdim#include "DWARFCompileUnit.h" 21353358Sdim#include "DWARFContext.h" 22254721Semaste#include "DWARFDebugAranges.h" 23254721Semaste#include "DWARFDebugInfo.h" 24254721Semaste#include "DWARFDebugInfoEntry.h" 25254721Semaste#include "DWARFFormValue.h" 26353358Sdim#include "DWARFTypeUnit.h" 27254721Semaste 28254721Semasteusing namespace lldb; 29254721Semasteusing namespace lldb_private; 30254721Semasteusing namespace std; 31254721Semaste 32254721Semaste// Constructor 33353358SdimDWARFDebugInfo::DWARFDebugInfo(SymbolFileDWARF &dwarf, 34353358Sdim lldb_private::DWARFContext &context) 35353358Sdim : m_dwarf(dwarf), m_context(context), m_units(), m_cu_aranges_up() {} 36254721Semaste 37353358Sdimllvm::Expected<DWARFDebugAranges &> DWARFDebugInfo::GetCompileUnitAranges() { 38353358Sdim if (m_cu_aranges_up) 39353358Sdim return *m_cu_aranges_up; 40353358Sdim 41360784Sdim m_cu_aranges_up = std::make_unique<DWARFDebugAranges>(); 42353358Sdim const DWARFDataExtractor &debug_aranges_data = 43353358Sdim m_context.getOrLoadArangesData(); 44353358Sdim if (llvm::Error error = m_cu_aranges_up->extract(debug_aranges_data)) 45353358Sdim return std::move(error); 46353358Sdim 47353358Sdim // Make a list of all CUs represented by the arange data in the file. 48353358Sdim std::set<dw_offset_t> cus_with_data; 49353358Sdim for (size_t n = 0; n < m_cu_aranges_up->GetNumRanges(); n++) { 50353358Sdim dw_offset_t offset = m_cu_aranges_up->OffsetAtIndex(n); 51353358Sdim if (offset != DW_INVALID_OFFSET) 52353358Sdim cus_with_data.insert(offset); 53353358Sdim } 54353358Sdim 55353358Sdim // Manually build arange data for everything that wasn't in the 56353358Sdim // .debug_aranges table. 57353358Sdim const size_t num_units = GetNumUnits(); 58353358Sdim for (size_t idx = 0; idx < num_units; ++idx) { 59353358Sdim DWARFUnit *cu = GetUnitAtIndex(idx); 60353358Sdim 61353358Sdim dw_offset_t offset = cu->GetOffset(); 62353358Sdim if (cus_with_data.find(offset) == cus_with_data.end()) 63353358Sdim cu->BuildAddressRangeTable(m_cu_aranges_up.get()); 64353358Sdim } 65353358Sdim 66353358Sdim const bool minimize = true; 67353358Sdim m_cu_aranges_up->Sort(minimize); 68353358Sdim return *m_cu_aranges_up; 69254721Semaste} 70254721Semaste 71353358Sdimvoid DWARFDebugInfo::ParseUnitsFor(DIERef::Section section) { 72353358Sdim DWARFDataExtractor data = section == DIERef::Section::DebugTypes 73353358Sdim ? m_context.getOrLoadDebugTypesData() 74353358Sdim : m_context.getOrLoadDebugInfoData(); 75353358Sdim lldb::offset_t offset = 0; 76353358Sdim while (data.ValidOffset(offset)) { 77353358Sdim llvm::Expected<DWARFUnitSP> unit_sp = 78353358Sdim DWARFUnit::extract(m_dwarf, m_units.size(), data, section, &offset); 79254721Semaste 80353358Sdim if (!unit_sp) { 81353358Sdim // FIXME: Propagate this error up. 82353358Sdim llvm::consumeError(unit_sp.takeError()); 83353358Sdim return; 84314564Sdim } 85254721Semaste 86353358Sdim // If it didn't return an error, then it should be returning a valid Unit. 87353358Sdim assert(*unit_sp); 88353358Sdim m_units.push_back(*unit_sp); 89353358Sdim offset = (*unit_sp)->GetNextUnitOffset(); 90258054Semaste 91353358Sdim if (auto *type_unit = llvm::dyn_cast<DWARFTypeUnit>(unit_sp->get())) { 92353358Sdim m_type_hash_to_unit_index.emplace_back(type_unit->GetTypeHash(), 93353358Sdim unit_sp.get()->GetID()); 94314564Sdim } 95314564Sdim } 96254721Semaste} 97254721Semaste 98353358Sdimvoid DWARFDebugInfo::ParseUnitHeadersIfNeeded() { 99353358Sdim if (!m_units.empty()) 100353358Sdim return; 101254721Semaste 102353358Sdim ParseUnitsFor(DIERef::Section::DebugInfo); 103353358Sdim ParseUnitsFor(DIERef::Section::DebugTypes); 104353358Sdim llvm::sort(m_type_hash_to_unit_index, llvm::less_first()); 105254721Semaste} 106254721Semaste 107353358Sdimsize_t DWARFDebugInfo::GetNumUnits() { 108353358Sdim ParseUnitHeadersIfNeeded(); 109353358Sdim return m_units.size(); 110254721Semaste} 111254721Semaste 112353358SdimDWARFUnit *DWARFDebugInfo::GetUnitAtIndex(user_id_t idx) { 113353358Sdim DWARFUnit *cu = nullptr; 114353358Sdim if (idx < GetNumUnits()) 115353358Sdim cu = m_units[idx].get(); 116314564Sdim return cu; 117254721Semaste} 118254721Semaste 119353358Sdimuint32_t DWARFDebugInfo::FindUnitIndex(DIERef::Section section, 120353358Sdim dw_offset_t offset) { 121353358Sdim ParseUnitHeadersIfNeeded(); 122314564Sdim 123353358Sdim // llvm::lower_bound is not used as for DIE offsets it would still return 124353358Sdim // index +1 and GetOffset() returning index itself would be a special case. 125353358Sdim auto pos = llvm::upper_bound( 126353358Sdim m_units, std::make_pair(section, offset), 127353358Sdim [](const std::pair<DIERef::Section, dw_offset_t> &lhs, 128353358Sdim const DWARFUnitSP &rhs) { 129353358Sdim return lhs < std::make_pair(rhs->GetDebugSection(), rhs->GetOffset()); 130353358Sdim }); 131353358Sdim uint32_t idx = std::distance(m_units.begin(), pos); 132353358Sdim if (idx == 0) 133353358Sdim return DW_INVALID_OFFSET; 134353358Sdim return idx - 1; 135254721Semaste} 136254721Semaste 137353358SdimDWARFUnit *DWARFDebugInfo::GetUnitAtOffset(DIERef::Section section, 138353358Sdim dw_offset_t cu_offset, 139353358Sdim uint32_t *idx_ptr) { 140353358Sdim uint32_t idx = FindUnitIndex(section, cu_offset); 141353358Sdim DWARFUnit *result = GetUnitAtIndex(idx); 142353358Sdim if (result && result->GetOffset() != cu_offset) { 143353358Sdim result = nullptr; 144353358Sdim idx = DW_INVALID_INDEX; 145314564Sdim } 146314564Sdim if (idx_ptr) 147353358Sdim *idx_ptr = idx; 148353358Sdim return result; 149254721Semaste} 150254721Semaste 151353358SdimDWARFUnit *DWARFDebugInfo::GetUnit(const DIERef &die_ref) { 152353358Sdim return GetUnitContainingDIEOffset(die_ref.section(), die_ref.die_offset()); 153309124Sdim} 154296417Sdim 155341825SdimDWARFUnit * 156353358SdimDWARFDebugInfo::GetUnitContainingDIEOffset(DIERef::Section section, 157353358Sdim dw_offset_t die_offset) { 158353358Sdim uint32_t idx = FindUnitIndex(section, die_offset); 159353358Sdim DWARFUnit *result = GetUnitAtIndex(idx); 160353358Sdim if (result && !result->ContainsDIEOffset(die_offset)) 161353358Sdim return nullptr; 162353358Sdim return result; 163353358Sdim} 164309124Sdim 165353358SdimDWARFTypeUnit *DWARFDebugInfo::GetTypeUnitForHash(uint64_t hash) { 166353358Sdim auto pos = llvm::lower_bound(m_type_hash_to_unit_index, 167353358Sdim std::make_pair(hash, 0u), llvm::less_first()); 168353358Sdim if (pos == m_type_hash_to_unit_index.end() || pos->first != hash) 169353358Sdim return nullptr; 170353358Sdim return llvm::cast<DWARFTypeUnit>(GetUnitAtIndex(pos->second)); 171353358Sdim} 172309124Sdim 173353358Sdimbool DWARFDebugInfo::ContainsTypeUnits() { 174353358Sdim ParseUnitHeadersIfNeeded(); 175353358Sdim return !m_type_hash_to_unit_index.empty(); 176254721Semaste} 177254721Semaste 178309124SdimDWARFDIE 179353358SdimDWARFDebugInfo::GetDIEForDIEOffset(DIERef::Section section, 180353358Sdim dw_offset_t die_offset) { 181353358Sdim DWARFUnit *cu = GetUnitContainingDIEOffset(section, die_offset); 182314564Sdim if (cu) 183314564Sdim return cu->GetDIE(die_offset); 184314564Sdim return DWARFDIE(); 185309124Sdim} 186309124Sdim 187254721Semaste// GetDIE() 188254721Semaste// 189254721Semaste// Get the DIE (Debug Information Entry) with the specified offset. 190296417SdimDWARFDIE 191314564SdimDWARFDebugInfo::GetDIE(const DIERef &die_ref) { 192353358Sdim DWARFUnit *cu = GetUnit(die_ref); 193314564Sdim if (cu) 194353358Sdim return cu->GetDIE(die_ref.die_offset()); 195314564Sdim return DWARFDIE(); // Not found 196254721Semaste} 197254721Semaste 198