//===-- DWARFCompileUnit.cpp ----------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "DWARFCompileUnit.h" #include "DWARFDebugAranges.h" #include "SymbolFileDWARFDebugMap.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/LineTable.h" #include "lldb/Utility/Stream.h" using namespace lldb; using namespace lldb_private; using namespace lldb_private::plugin::dwarf; void DWARFCompileUnit::Dump(Stream *s) const { s->Format( "{0:x16}: Compile Unit: length = {1:x8}, version = {2:x}, " "abbr_offset = {3:x8}, addr_size = {4:x2} (next CU at " "[{5:x16}])\n", GetOffset(), GetLength(), GetVersion(), (uint32_t)GetAbbrevOffset(), GetAddressByteSize(), GetNextUnitOffset()); } void DWARFCompileUnit::BuildAddressRangeTable( DWARFDebugAranges *debug_aranges) { // This function is usually called if there in no .debug_aranges section in // order to produce a compile unit level set of address ranges that is // accurate. size_t num_debug_aranges = debug_aranges->GetNumRanges(); // First get the compile unit DIE only and check contains ranges information. const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); const dw_offset_t cu_offset = GetOffset(); if (die) { DWARFRangeList ranges = die->GetAttributeAddressRanges(this, /*check_hi_lo_pc=*/true); for (const DWARFRangeList::Entry &range : ranges) debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), range.GetRangeEnd()); if (!ranges.IsEmpty()) return; } if (debug_aranges->GetNumRanges() == num_debug_aranges) { // We got nothing from the debug info, try to build the arange table from // the debug map OSO aranges. SymbolContext sc; sc.comp_unit = m_dwarf.GetCompUnitForDWARFCompUnit(*this); if (sc.comp_unit) { SymbolFileDWARFDebugMap *debug_map_sym_file = m_dwarf.GetDebugMapSymfile(); if (debug_map_sym_file) { auto *cu_info = debug_map_sym_file->GetCompileUnitInfo(&GetSymbolFileDWARF()); // If there are extra compile units the OSO entries aren't a reliable // source of information. if (cu_info->compile_units_sps.empty()) debug_map_sym_file->AddOSOARanges(&m_dwarf, debug_aranges); } } } if (debug_aranges->GetNumRanges() == num_debug_aranges) { // We got nothing from the functions, maybe we have a line tables only // situation. Check the line tables and build the arange table from this. SymbolContext sc; sc.comp_unit = m_dwarf.GetCompUnitForDWARFCompUnit(*this); if (sc.comp_unit) { if (LineTable *line_table = sc.comp_unit->GetLineTable()) { LineTable::FileAddressRanges file_ranges; const bool append = true; const size_t num_ranges = line_table->GetContiguousFileAddressRanges(file_ranges, append); for (uint32_t idx = 0; idx < num_ranges; ++idx) { const LineTable::FileAddressRanges::Entry &range = file_ranges.GetEntryRef(idx); debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(), range.GetRangeEnd()); } } } } } DWARFCompileUnit &DWARFCompileUnit::GetNonSkeletonUnit() { return llvm::cast(DWARFUnit::GetNonSkeletonUnit()); } DWARFDIE DWARFCompileUnit::LookupAddress(const dw_addr_t address) { if (DIE()) { const DWARFDebugAranges &func_aranges = GetFunctionAranges(); // Re-check the aranges auto pointer contents in case it was created above if (!func_aranges.IsEmpty()) return GetDIE(func_aranges.FindAddress(address)); } return DWARFDIE(); }