1 //===-- DWARFDebugInfo.cpp ------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "SymbolFileDWARF.h"
14 #include "lldb/Host/PosixApi.h"
15 #include "lldb/Symbol/ObjectFile.h"
16 #include "lldb/Utility/RegularExpression.h"
17 #include "lldb/Utility/Stream.h"
18 #include "llvm/Support/Casting.h"
20 #include "DWARFCompileUnit.h"
21 #include "DWARFContext.h"
22 #include "DWARFDebugAranges.h"
23 #include "DWARFDebugInfo.h"
24 #include "DWARFDebugInfoEntry.h"
25 #include "DWARFFormValue.h"
26 #include "DWARFTypeUnit.h"
27 #include "LogChannelDWARF.h"
30 using namespace lldb_private
;
31 using namespace lldb_private::plugin::dwarf
;
34 DWARFDebugInfo::DWARFDebugInfo(SymbolFileDWARF
&dwarf
, DWARFContext
&context
)
35 : m_dwarf(dwarf
), m_context(context
), m_units(), m_cu_aranges_up() {}
37 const DWARFDebugAranges
&DWARFDebugInfo::GetCompileUnitAranges() {
39 return *m_cu_aranges_up
;
41 m_cu_aranges_up
= std::make_unique
<DWARFDebugAranges
>();
42 const DWARFDataExtractor
&debug_aranges_data
=
43 m_context
.getOrLoadArangesData();
45 // Extract what we can from the .debug_aranges first.
46 m_cu_aranges_up
->extract(debug_aranges_data
);
48 // Make a list of all CUs represented by the .debug_aranges data.
49 std::set
<dw_offset_t
> cus_with_data
;
50 for (size_t n
= 0; n
< m_cu_aranges_up
->GetNumRanges(); n
++) {
51 dw_offset_t offset
= m_cu_aranges_up
->OffsetAtIndex(n
);
52 if (offset
!= DW_INVALID_OFFSET
)
53 cus_with_data
.insert(offset
);
56 // Manually build arange data for everything that wasn't in .debug_aranges.
57 // The .debug_aranges accelerator is not guaranteed to be complete.
58 // Tools such as dsymutil can provide stronger guarantees than required by the
59 // standard. Without that guarantee, we have to iterate over every CU in the
60 // .debug_info and make sure there's a corresponding entry in the table and if
61 // not, add one for every subprogram.
62 ObjectFile
*OF
= m_dwarf
.GetObjectFile();
63 if (!OF
|| !OF
->CanTrustAddressRanges()) {
64 const size_t num_units
= GetNumUnits();
65 for (size_t idx
= 0; idx
< num_units
; ++idx
) {
66 DWARFUnit
*cu
= GetUnitAtIndex(idx
);
68 dw_offset_t offset
= cu
->GetOffset();
69 if (cus_with_data
.find(offset
) == cus_with_data
.end())
70 cu
->BuildAddressRangeTable(m_cu_aranges_up
.get());
74 const bool minimize
= true;
75 m_cu_aranges_up
->Sort(minimize
);
76 return *m_cu_aranges_up
;
79 void DWARFDebugInfo::ParseUnitsFor(DIERef::Section section
) {
80 DWARFDataExtractor data
= section
== DIERef::Section::DebugTypes
81 ? m_context
.getOrLoadDebugTypesData()
82 : m_context
.getOrLoadDebugInfoData();
83 lldb::offset_t offset
= 0;
84 while (data
.ValidOffset(offset
)) {
85 const lldb::offset_t unit_header_offset
= offset
;
86 llvm::Expected
<DWARFUnitSP
> expected_unit_sp
=
87 DWARFUnit::extract(m_dwarf
, m_units
.size(), data
, section
, &offset
);
89 if (!expected_unit_sp
) {
90 Log
*log
= GetLog(DWARFLog::DebugInfo
);
92 LLDB_LOG(log
, "Unable to extract DWARFUnitHeader at {0:x}: {1}",
94 llvm::toString(expected_unit_sp
.takeError()));
96 llvm::consumeError(expected_unit_sp
.takeError());
100 DWARFUnitSP unit_sp
= *expected_unit_sp
;
102 // If it didn't return an error, then it should be returning a valid Unit.
103 assert((bool)unit_sp
);
105 // Keep a map of DWO ID back to the skeleton units. Sometimes accelerator
106 // table lookups can cause the DWO files to be accessed before the skeleton
107 // compile unit is parsed, so we keep a map to allow us to match up the DWO
108 // file to the back to the skeleton compile units.
109 if (unit_sp
->GetUnitType() == lldb_private::dwarf::DW_UT_skeleton
) {
110 if (std::optional
<uint64_t> unit_dwo_id
= unit_sp
->GetHeaderDWOId())
111 m_dwarf5_dwo_id_to_skeleton_unit
[*unit_dwo_id
] = unit_sp
.get();
114 m_units
.push_back(unit_sp
);
115 offset
= unit_sp
->GetNextUnitOffset();
117 if (auto *type_unit
= llvm::dyn_cast
<DWARFTypeUnit
>(unit_sp
.get())) {
118 m_type_hash_to_unit_index
.emplace_back(type_unit
->GetTypeHash(),
124 DWARFUnit
*DWARFDebugInfo::GetSkeletonUnit(DWARFUnit
*dwo_unit
) {
125 // If this isn't a DWO unit, don't try and find the skeleton unit.
126 if (!dwo_unit
->IsDWOUnit())
129 auto dwo_id
= dwo_unit
->GetDWOId();
130 if (!dwo_id
.has_value())
133 // Parse the unit headers so that m_dwarf5_dwo_id_to_skeleton_unit is filled
134 // in with all of the DWARF5 skeleton compile units DWO IDs since it is easy
135 // to access the DWO IDs in the DWARFUnitHeader for each DWARFUnit.
136 ParseUnitHeadersIfNeeded();
138 // Find the value in our cache and return it we we find it. This cache may
139 // only contain DWARF5 units.
140 auto iter
= m_dwarf5_dwo_id_to_skeleton_unit
.find(*dwo_id
);
141 if (iter
!= m_dwarf5_dwo_id_to_skeleton_unit
.end())
144 // DWARF5 unit headers have the DWO ID and should have already been in the map
145 // so if it wasn't found in the above find() call, then we didn't find it and
146 // don't need to do the more expensive DWARF4 search.
147 if (dwo_unit
->GetVersion() >= 5)
150 // Parse all DWO IDs from all DWARF4 and earlier compile units that have DWO
151 // IDs. It is more expensive to get the DWO IDs from DWARF4 compile units as
152 // we need to parse the unit DIE and extract the DW_AT_dwo_id or
153 // DW_AT_GNU_dwo_id attribute values, so do this only if we didn't find our
154 // match above search and only for DWARF4 and earlier compile units.
155 llvm::call_once(m_dwarf4_dwo_id_to_skeleton_unit_once_flag
, [this]() {
156 for (uint32_t i
= 0, num
= GetNumUnits(); i
< num
; ++i
) {
157 if (DWARFUnit
*unit
= GetUnitAtIndex(i
)) {
158 if (unit
->GetVersion() < 5) {
159 if (std::optional
<uint64_t> unit_dwo_id
= unit
->GetDWOId())
160 m_dwarf4_dwo_id_to_skeleton_unit
[*unit_dwo_id
] = unit
;
166 // Search the DWARF4 DWO results that we parsed lazily.
167 iter
= m_dwarf4_dwo_id_to_skeleton_unit
.find(*dwo_id
);
168 if (iter
!= m_dwarf4_dwo_id_to_skeleton_unit
.end())
173 void DWARFDebugInfo::ParseUnitHeadersIfNeeded() {
174 llvm::call_once(m_units_once_flag
, [&] {
175 ParseUnitsFor(DIERef::Section::DebugInfo
);
176 ParseUnitsFor(DIERef::Section::DebugTypes
);
177 llvm::sort(m_type_hash_to_unit_index
, llvm::less_first());
181 size_t DWARFDebugInfo::GetNumUnits() {
182 ParseUnitHeadersIfNeeded();
183 return m_units
.size();
186 DWARFUnit
*DWARFDebugInfo::GetUnitAtIndex(size_t idx
) {
187 DWARFUnit
*cu
= nullptr;
188 if (idx
< GetNumUnits())
189 cu
= m_units
[idx
].get();
193 uint32_t DWARFDebugInfo::FindUnitIndex(DIERef::Section section
,
194 dw_offset_t offset
) {
195 ParseUnitHeadersIfNeeded();
197 // llvm::lower_bound is not used as for DIE offsets it would still return
198 // index +1 and GetOffset() returning index itself would be a special case.
199 auto pos
= llvm::upper_bound(
200 m_units
, std::make_pair(section
, offset
),
201 [](const std::pair
<DIERef::Section
, dw_offset_t
> &lhs
,
202 const DWARFUnitSP
&rhs
) {
203 return lhs
< std::make_pair(rhs
->GetDebugSection(), rhs
->GetOffset());
205 uint32_t idx
= std::distance(m_units
.begin(), pos
);
207 return DW_INVALID_INDEX
;
211 DWARFUnit
*DWARFDebugInfo::GetUnitAtOffset(DIERef::Section section
,
212 dw_offset_t cu_offset
,
214 uint32_t idx
= FindUnitIndex(section
, cu_offset
);
215 DWARFUnit
*result
= GetUnitAtIndex(idx
);
216 if (result
&& result
->GetOffset() != cu_offset
) {
218 idx
= DW_INVALID_INDEX
;
226 DWARFDebugInfo::GetUnitContainingDIEOffset(DIERef::Section section
,
227 dw_offset_t die_offset
) {
228 uint32_t idx
= FindUnitIndex(section
, die_offset
);
229 DWARFUnit
*result
= GetUnitAtIndex(idx
);
230 if (result
&& !result
->ContainsDIEOffset(die_offset
))
235 const std::shared_ptr
<SymbolFileDWARFDwo
> &DWARFDebugInfo::GetDwpSymbolFile() {
236 return m_dwarf
.GetDwpSymbolFile();
239 DWARFTypeUnit
*DWARFDebugInfo::GetTypeUnitForHash(uint64_t hash
) {
240 auto pos
= llvm::lower_bound(m_type_hash_to_unit_index
,
241 std::make_pair(hash
, 0u), llvm::less_first());
242 if (pos
== m_type_hash_to_unit_index
.end() || pos
->first
!= hash
)
244 return llvm::cast
<DWARFTypeUnit
>(GetUnitAtIndex(pos
->second
));
247 bool DWARFDebugInfo::ContainsTypeUnits() {
248 ParseUnitHeadersIfNeeded();
249 return !m_type_hash_to_unit_index
.empty();
254 // Get the DIE (Debug Information Entry) with the specified offset.
256 DWARFDebugInfo::GetDIE(DIERef::Section section
, dw_offset_t die_offset
) {
257 if (DWARFUnit
*cu
= GetUnitContainingDIEOffset(section
, die_offset
))
258 return cu
->GetNonSkeletonUnit().GetDIE(die_offset
);
259 return DWARFDIE(); // Not found