xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- SymbolFileDWARF.cpp -----------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "SymbolFileDWARF.h"
10061da546Spatrick 
11*f6aab3d8Srobert #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
12061da546Spatrick #include "llvm/Support/Casting.h"
13061da546Spatrick #include "llvm/Support/Threading.h"
14061da546Spatrick 
15061da546Spatrick #include "lldb/Core/Module.h"
16061da546Spatrick #include "lldb/Core/ModuleList.h"
17061da546Spatrick #include "lldb/Core/ModuleSpec.h"
18061da546Spatrick #include "lldb/Core/PluginManager.h"
19be691f3bSpatrick #include "lldb/Core/Progress.h"
20061da546Spatrick #include "lldb/Core/Section.h"
21061da546Spatrick #include "lldb/Core/StreamFile.h"
22061da546Spatrick #include "lldb/Core/Value.h"
23061da546Spatrick #include "lldb/Utility/ArchSpec.h"
24*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
25061da546Spatrick #include "lldb/Utility/RegularExpression.h"
26061da546Spatrick #include "lldb/Utility/Scalar.h"
27061da546Spatrick #include "lldb/Utility/StreamString.h"
28061da546Spatrick #include "lldb/Utility/Timer.h"
29061da546Spatrick 
30061da546Spatrick #include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h"
31061da546Spatrick #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
32061da546Spatrick 
33061da546Spatrick #include "lldb/Host/FileSystem.h"
34061da546Spatrick #include "lldb/Host/Host.h"
35061da546Spatrick 
36061da546Spatrick #include "lldb/Interpreter/OptionValueFileSpecList.h"
37061da546Spatrick #include "lldb/Interpreter/OptionValueProperties.h"
38061da546Spatrick 
39dda28197Spatrick #include "Plugins/ExpressionParser/Clang/ClangUtil.h"
40be691f3bSpatrick #include "Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h"
41dda28197Spatrick #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
42061da546Spatrick #include "lldb/Symbol/Block.h"
43061da546Spatrick #include "lldb/Symbol/CompileUnit.h"
44061da546Spatrick #include "lldb/Symbol/CompilerDecl.h"
45061da546Spatrick #include "lldb/Symbol/CompilerDeclContext.h"
46061da546Spatrick #include "lldb/Symbol/DebugMacros.h"
47061da546Spatrick #include "lldb/Symbol/LineTable.h"
48061da546Spatrick #include "lldb/Symbol/LocateSymbolFile.h"
49061da546Spatrick #include "lldb/Symbol/ObjectFile.h"
50061da546Spatrick #include "lldb/Symbol/SymbolFile.h"
51061da546Spatrick #include "lldb/Symbol/TypeMap.h"
52061da546Spatrick #include "lldb/Symbol/TypeSystem.h"
53061da546Spatrick #include "lldb/Symbol/VariableList.h"
54061da546Spatrick 
55061da546Spatrick #include "lldb/Target/Language.h"
56061da546Spatrick #include "lldb/Target/Target.h"
57061da546Spatrick 
58061da546Spatrick #include "AppleDWARFIndex.h"
59061da546Spatrick #include "DWARFASTParser.h"
60061da546Spatrick #include "DWARFASTParserClang.h"
61061da546Spatrick #include "DWARFCompileUnit.h"
62061da546Spatrick #include "DWARFDebugAbbrev.h"
63061da546Spatrick #include "DWARFDebugAranges.h"
64061da546Spatrick #include "DWARFDebugInfo.h"
65061da546Spatrick #include "DWARFDebugMacro.h"
66061da546Spatrick #include "DWARFDebugRanges.h"
67061da546Spatrick #include "DWARFDeclContext.h"
68061da546Spatrick #include "DWARFFormValue.h"
69061da546Spatrick #include "DWARFTypeUnit.h"
70061da546Spatrick #include "DWARFUnit.h"
71061da546Spatrick #include "DebugNamesDWARFIndex.h"
72061da546Spatrick #include "LogChannelDWARF.h"
73061da546Spatrick #include "ManualDWARFIndex.h"
74061da546Spatrick #include "SymbolFileDWARFDebugMap.h"
75061da546Spatrick #include "SymbolFileDWARFDwo.h"
76061da546Spatrick 
77061da546Spatrick #include "llvm/DebugInfo/DWARF/DWARFContext.h"
78061da546Spatrick #include "llvm/Support/FileSystem.h"
79be691f3bSpatrick #include "llvm/Support/FormatVariadic.h"
80061da546Spatrick 
81061da546Spatrick #include <algorithm>
82061da546Spatrick #include <map>
83061da546Spatrick #include <memory>
84*f6aab3d8Srobert #include <optional>
85061da546Spatrick 
86be691f3bSpatrick #include <cctype>
87be691f3bSpatrick #include <cstring>
88061da546Spatrick 
89061da546Spatrick //#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN
90061da546Spatrick 
91061da546Spatrick #ifdef ENABLE_DEBUG_PRINTF
92be691f3bSpatrick #include <cstdio>
93061da546Spatrick #define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
94061da546Spatrick #else
95061da546Spatrick #define DEBUG_PRINTF(fmt, ...)
96061da546Spatrick #endif
97061da546Spatrick 
98061da546Spatrick using namespace lldb;
99061da546Spatrick using namespace lldb_private;
100*f6aab3d8Srobert using namespace lldb_private::dwarf;
101061da546Spatrick 
102dda28197Spatrick LLDB_PLUGIN_DEFINE(SymbolFileDWARF)
103dda28197Spatrick 
104061da546Spatrick char SymbolFileDWARF::ID;
105061da546Spatrick 
106061da546Spatrick namespace {
107061da546Spatrick 
108061da546Spatrick #define LLDB_PROPERTIES_symbolfiledwarf
109061da546Spatrick #include "SymbolFileDWARFProperties.inc"
110061da546Spatrick 
111061da546Spatrick enum {
112061da546Spatrick #define LLDB_PROPERTIES_symbolfiledwarf
113061da546Spatrick #include "SymbolFileDWARFPropertiesEnum.inc"
114061da546Spatrick };
115061da546Spatrick 
116061da546Spatrick class PluginProperties : public Properties {
117061da546Spatrick public:
GetSettingName()118061da546Spatrick   static ConstString GetSettingName() {
119*f6aab3d8Srobert     return ConstString(SymbolFileDWARF::GetPluginNameStatic());
120061da546Spatrick   }
121061da546Spatrick 
PluginProperties()122061da546Spatrick   PluginProperties() {
123061da546Spatrick     m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
124061da546Spatrick     m_collection_sp->Initialize(g_symbolfiledwarf_properties);
125061da546Spatrick   }
126061da546Spatrick 
IgnoreFileIndexes() const127061da546Spatrick   bool IgnoreFileIndexes() const {
128061da546Spatrick     return m_collection_sp->GetPropertyAtIndexAsBoolean(
129061da546Spatrick         nullptr, ePropertyIgnoreIndexes, false);
130061da546Spatrick   }
131061da546Spatrick };
132061da546Spatrick 
133061da546Spatrick } // namespace
134061da546Spatrick 
GetGlobalPluginProperties()135*f6aab3d8Srobert static PluginProperties &GetGlobalPluginProperties() {
136*f6aab3d8Srobert   static PluginProperties g_settings;
137*f6aab3d8Srobert   return g_settings;
138*f6aab3d8Srobert }
139*f6aab3d8Srobert 
140061da546Spatrick static const llvm::DWARFDebugLine::LineTable *
ParseLLVMLineTable(lldb_private::DWARFContext & context,llvm::DWARFDebugLine & line,dw_offset_t line_offset,dw_offset_t unit_offset)141061da546Spatrick ParseLLVMLineTable(lldb_private::DWARFContext &context,
142061da546Spatrick                    llvm::DWARFDebugLine &line, dw_offset_t line_offset,
143061da546Spatrick                    dw_offset_t unit_offset) {
144*f6aab3d8Srobert   Log *log = GetLog(DWARFLog::DebugInfo);
145061da546Spatrick 
146061da546Spatrick   llvm::DWARFDataExtractor data = context.getOrLoadLineData().GetAsLLVM();
147061da546Spatrick   llvm::DWARFContext &ctx = context.GetAsLLVM();
148061da546Spatrick   llvm::Expected<const llvm::DWARFDebugLine::LineTable *> line_table =
149061da546Spatrick       line.getOrParseLineTable(
150061da546Spatrick           data, line_offset, ctx, nullptr, [&](llvm::Error e) {
151dda28197Spatrick             LLDB_LOG_ERROR(
152dda28197Spatrick                 log, std::move(e),
153dda28197Spatrick                 "SymbolFileDWARF::ParseLineTable failed to parse: {0}");
154061da546Spatrick           });
155061da546Spatrick 
156061da546Spatrick   if (!line_table) {
157061da546Spatrick     LLDB_LOG_ERROR(log, line_table.takeError(),
158dda28197Spatrick                    "SymbolFileDWARF::ParseLineTable failed to parse: {0}");
159061da546Spatrick     return nullptr;
160061da546Spatrick   }
161061da546Spatrick   return *line_table;
162061da546Spatrick }
163061da546Spatrick 
ParseLLVMLineTablePrologue(lldb_private::DWARFContext & context,llvm::DWARFDebugLine::Prologue & prologue,dw_offset_t line_offset,dw_offset_t unit_offset)164dda28197Spatrick static bool ParseLLVMLineTablePrologue(lldb_private::DWARFContext &context,
165dda28197Spatrick                                        llvm::DWARFDebugLine::Prologue &prologue,
166dda28197Spatrick                                        dw_offset_t line_offset,
167dda28197Spatrick                                        dw_offset_t unit_offset) {
168*f6aab3d8Srobert   Log *log = GetLog(DWARFLog::DebugInfo);
169dda28197Spatrick   bool success = true;
170dda28197Spatrick   llvm::DWARFDataExtractor data = context.getOrLoadLineData().GetAsLLVM();
171dda28197Spatrick   llvm::DWARFContext &ctx = context.GetAsLLVM();
172dda28197Spatrick   uint64_t offset = line_offset;
173dda28197Spatrick   llvm::Error error = prologue.parse(
174dda28197Spatrick       data, &offset,
175dda28197Spatrick       [&](llvm::Error e) {
176dda28197Spatrick         success = false;
177dda28197Spatrick         LLDB_LOG_ERROR(log, std::move(e),
178dda28197Spatrick                        "SymbolFileDWARF::ParseSupportFiles failed to parse "
179dda28197Spatrick                        "line table prologue: {0}");
180dda28197Spatrick       },
181dda28197Spatrick       ctx, nullptr);
182dda28197Spatrick   if (error) {
183dda28197Spatrick     LLDB_LOG_ERROR(log, std::move(error),
184dda28197Spatrick                    "SymbolFileDWARF::ParseSupportFiles failed to parse line "
185dda28197Spatrick                    "table prologue: {0}");
186dda28197Spatrick     return false;
187dda28197Spatrick   }
188dda28197Spatrick   return success;
189dda28197Spatrick }
190dda28197Spatrick 
191*f6aab3d8Srobert static std::optional<std::string>
GetFileByIndex(const llvm::DWARFDebugLine::Prologue & prologue,size_t idx,llvm::StringRef compile_dir,FileSpec::Style style)192061da546Spatrick GetFileByIndex(const llvm::DWARFDebugLine::Prologue &prologue, size_t idx,
193061da546Spatrick                llvm::StringRef compile_dir, FileSpec::Style style) {
194061da546Spatrick   // Try to get an absolute path first.
195061da546Spatrick   std::string abs_path;
196061da546Spatrick   auto absolute = llvm::DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath;
197061da546Spatrick   if (prologue.getFileNameByIndex(idx, compile_dir, absolute, abs_path, style))
198061da546Spatrick     return std::move(abs_path);
199061da546Spatrick 
200061da546Spatrick   // Otherwise ask for a relative path.
201061da546Spatrick   std::string rel_path;
202dda28197Spatrick   auto relative = llvm::DILineInfoSpecifier::FileLineInfoKind::RawValue;
203061da546Spatrick   if (!prologue.getFileNameByIndex(idx, compile_dir, relative, rel_path, style))
204061da546Spatrick     return {};
205061da546Spatrick   return std::move(rel_path);
206061da546Spatrick }
207061da546Spatrick 
208061da546Spatrick static FileSpecList
ParseSupportFilesFromPrologue(const lldb::ModuleSP & module,const llvm::DWARFDebugLine::Prologue & prologue,FileSpec::Style style,llvm::StringRef compile_dir={})209061da546Spatrick ParseSupportFilesFromPrologue(const lldb::ModuleSP &module,
210061da546Spatrick                               const llvm::DWARFDebugLine::Prologue &prologue,
211061da546Spatrick                               FileSpec::Style style,
212061da546Spatrick                               llvm::StringRef compile_dir = {}) {
213061da546Spatrick   FileSpecList support_files;
214061da546Spatrick   size_t first_file = 0;
215061da546Spatrick   if (prologue.getVersion() <= 4) {
216061da546Spatrick     // File index 0 is not valid before DWARF v5. Add a dummy entry to ensure
217061da546Spatrick     // support file list indices match those we get from the debug info and line
218061da546Spatrick     // tables.
219061da546Spatrick     support_files.Append(FileSpec());
220061da546Spatrick     first_file = 1;
221061da546Spatrick   }
222061da546Spatrick 
223061da546Spatrick   const size_t number_of_files = prologue.FileNames.size();
224061da546Spatrick   for (size_t idx = first_file; idx <= number_of_files; ++idx) {
225061da546Spatrick     std::string remapped_file;
226be691f3bSpatrick     if (auto file_path = GetFileByIndex(prologue, idx, compile_dir, style)) {
227be691f3bSpatrick       if (auto remapped = module->RemapSourceFile(llvm::StringRef(*file_path)))
228be691f3bSpatrick         remapped_file = *remapped;
229be691f3bSpatrick       else
230061da546Spatrick         remapped_file = std::move(*file_path);
231be691f3bSpatrick     }
232061da546Spatrick 
233061da546Spatrick     // Unconditionally add an entry, so the indices match up.
234061da546Spatrick     support_files.EmplaceBack(remapped_file, style);
235061da546Spatrick   }
236061da546Spatrick 
237061da546Spatrick   return support_files;
238061da546Spatrick }
239061da546Spatrick 
Initialize()240061da546Spatrick void SymbolFileDWARF::Initialize() {
241061da546Spatrick   LogChannelDWARF::Initialize();
242061da546Spatrick   PluginManager::RegisterPlugin(GetPluginNameStatic(),
243061da546Spatrick                                 GetPluginDescriptionStatic(), CreateInstance,
244061da546Spatrick                                 DebuggerInitialize);
245dda28197Spatrick   SymbolFileDWARFDebugMap::Initialize();
246061da546Spatrick }
247061da546Spatrick 
DebuggerInitialize(Debugger & debugger)248061da546Spatrick void SymbolFileDWARF::DebuggerInitialize(Debugger &debugger) {
249061da546Spatrick   if (!PluginManager::GetSettingForSymbolFilePlugin(
250061da546Spatrick           debugger, PluginProperties::GetSettingName())) {
251061da546Spatrick     const bool is_global_setting = true;
252061da546Spatrick     PluginManager::CreateSettingForSymbolFilePlugin(
253*f6aab3d8Srobert         debugger, GetGlobalPluginProperties().GetValueProperties(),
254061da546Spatrick         ConstString("Properties for the dwarf symbol-file plug-in."),
255061da546Spatrick         is_global_setting);
256061da546Spatrick   }
257061da546Spatrick }
258061da546Spatrick 
Terminate()259061da546Spatrick void SymbolFileDWARF::Terminate() {
260dda28197Spatrick   SymbolFileDWARFDebugMap::Terminate();
261061da546Spatrick   PluginManager::UnregisterPlugin(CreateInstance);
262061da546Spatrick   LogChannelDWARF::Terminate();
263061da546Spatrick }
264061da546Spatrick 
GetPluginDescriptionStatic()265*f6aab3d8Srobert llvm::StringRef SymbolFileDWARF::GetPluginDescriptionStatic() {
266061da546Spatrick   return "DWARF and DWARF3 debug symbol file reader.";
267061da546Spatrick }
268061da546Spatrick 
CreateInstance(ObjectFileSP objfile_sp)269061da546Spatrick SymbolFile *SymbolFileDWARF::CreateInstance(ObjectFileSP objfile_sp) {
270061da546Spatrick   return new SymbolFileDWARF(std::move(objfile_sp),
271061da546Spatrick                              /*dwo_section_list*/ nullptr);
272061da546Spatrick }
273061da546Spatrick 
GetTypeList()274061da546Spatrick TypeList &SymbolFileDWARF::GetTypeList() {
275061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
276061da546Spatrick   if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile())
277061da546Spatrick     return debug_map_symfile->GetTypeList();
278*f6aab3d8Srobert   return SymbolFileCommon::GetTypeList();
279061da546Spatrick }
GetTypes(const DWARFDIE & die,dw_offset_t min_die_offset,dw_offset_t max_die_offset,uint32_t type_mask,TypeSet & type_set)280061da546Spatrick void SymbolFileDWARF::GetTypes(const DWARFDIE &die, dw_offset_t min_die_offset,
281061da546Spatrick                                dw_offset_t max_die_offset, uint32_t type_mask,
282061da546Spatrick                                TypeSet &type_set) {
283061da546Spatrick   if (die) {
284061da546Spatrick     const dw_offset_t die_offset = die.GetOffset();
285061da546Spatrick 
286061da546Spatrick     if (die_offset >= max_die_offset)
287061da546Spatrick       return;
288061da546Spatrick 
289061da546Spatrick     if (die_offset >= min_die_offset) {
290061da546Spatrick       const dw_tag_t tag = die.Tag();
291061da546Spatrick 
292061da546Spatrick       bool add_type = false;
293061da546Spatrick 
294061da546Spatrick       switch (tag) {
295061da546Spatrick       case DW_TAG_array_type:
296061da546Spatrick         add_type = (type_mask & eTypeClassArray) != 0;
297061da546Spatrick         break;
298061da546Spatrick       case DW_TAG_unspecified_type:
299061da546Spatrick       case DW_TAG_base_type:
300061da546Spatrick         add_type = (type_mask & eTypeClassBuiltin) != 0;
301061da546Spatrick         break;
302061da546Spatrick       case DW_TAG_class_type:
303061da546Spatrick         add_type = (type_mask & eTypeClassClass) != 0;
304061da546Spatrick         break;
305061da546Spatrick       case DW_TAG_structure_type:
306061da546Spatrick         add_type = (type_mask & eTypeClassStruct) != 0;
307061da546Spatrick         break;
308061da546Spatrick       case DW_TAG_union_type:
309061da546Spatrick         add_type = (type_mask & eTypeClassUnion) != 0;
310061da546Spatrick         break;
311061da546Spatrick       case DW_TAG_enumeration_type:
312061da546Spatrick         add_type = (type_mask & eTypeClassEnumeration) != 0;
313061da546Spatrick         break;
314061da546Spatrick       case DW_TAG_subroutine_type:
315061da546Spatrick       case DW_TAG_subprogram:
316061da546Spatrick       case DW_TAG_inlined_subroutine:
317061da546Spatrick         add_type = (type_mask & eTypeClassFunction) != 0;
318061da546Spatrick         break;
319061da546Spatrick       case DW_TAG_pointer_type:
320061da546Spatrick         add_type = (type_mask & eTypeClassPointer) != 0;
321061da546Spatrick         break;
322061da546Spatrick       case DW_TAG_rvalue_reference_type:
323061da546Spatrick       case DW_TAG_reference_type:
324061da546Spatrick         add_type = (type_mask & eTypeClassReference) != 0;
325061da546Spatrick         break;
326061da546Spatrick       case DW_TAG_typedef:
327061da546Spatrick         add_type = (type_mask & eTypeClassTypedef) != 0;
328061da546Spatrick         break;
329061da546Spatrick       case DW_TAG_ptr_to_member_type:
330061da546Spatrick         add_type = (type_mask & eTypeClassMemberPointer) != 0;
331061da546Spatrick         break;
332061da546Spatrick       default:
333061da546Spatrick         break;
334061da546Spatrick       }
335061da546Spatrick 
336061da546Spatrick       if (add_type) {
337061da546Spatrick         const bool assert_not_being_parsed = true;
338061da546Spatrick         Type *type = ResolveTypeUID(die, assert_not_being_parsed);
339dda28197Spatrick         if (type)
340061da546Spatrick           type_set.insert(type);
341061da546Spatrick       }
342061da546Spatrick     }
343061da546Spatrick 
344be691f3bSpatrick     for (DWARFDIE child_die : die.children()) {
345061da546Spatrick       GetTypes(child_die, min_die_offset, max_die_offset, type_mask, type_set);
346061da546Spatrick     }
347061da546Spatrick   }
348061da546Spatrick }
349061da546Spatrick 
GetTypes(SymbolContextScope * sc_scope,TypeClass type_mask,TypeList & type_list)350061da546Spatrick void SymbolFileDWARF::GetTypes(SymbolContextScope *sc_scope,
351061da546Spatrick                                TypeClass type_mask, TypeList &type_list)
352061da546Spatrick 
353061da546Spatrick {
354061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
355061da546Spatrick   TypeSet type_set;
356061da546Spatrick 
357061da546Spatrick   CompileUnit *comp_unit = nullptr;
358061da546Spatrick   if (sc_scope)
359061da546Spatrick     comp_unit = sc_scope->CalculateSymbolContextCompileUnit();
360061da546Spatrick 
361be691f3bSpatrick   const auto &get = [&](DWARFUnit *unit) {
362be691f3bSpatrick     if (!unit)
363061da546Spatrick       return;
364be691f3bSpatrick     unit = &unit->GetNonSkeletonUnit();
365be691f3bSpatrick     GetTypes(unit->DIE(), unit->GetOffset(), unit->GetNextUnitOffset(),
366be691f3bSpatrick              type_mask, type_set);
367be691f3bSpatrick   };
368be691f3bSpatrick   if (comp_unit) {
369be691f3bSpatrick     get(GetDWARFCompileUnit(comp_unit));
370061da546Spatrick   } else {
371dda28197Spatrick     DWARFDebugInfo &info = DebugInfo();
372dda28197Spatrick     const size_t num_cus = info.GetNumUnits();
373be691f3bSpatrick     for (size_t cu_idx = 0; cu_idx < num_cus; ++cu_idx)
374be691f3bSpatrick       get(info.GetUnitAtIndex(cu_idx));
375061da546Spatrick   }
376061da546Spatrick 
377061da546Spatrick   std::set<CompilerType> compiler_type_set;
378061da546Spatrick   for (Type *type : type_set) {
379061da546Spatrick     CompilerType compiler_type = type->GetForwardCompilerType();
380061da546Spatrick     if (compiler_type_set.find(compiler_type) == compiler_type_set.end()) {
381061da546Spatrick       compiler_type_set.insert(compiler_type);
382061da546Spatrick       type_list.Insert(type->shared_from_this());
383061da546Spatrick     }
384061da546Spatrick   }
385061da546Spatrick }
386061da546Spatrick 
387061da546Spatrick // Gets the first parent that is a lexical block, function or inlined
388061da546Spatrick // subroutine, or compile unit.
389061da546Spatrick DWARFDIE
GetParentSymbolContextDIE(const DWARFDIE & child_die)390061da546Spatrick SymbolFileDWARF::GetParentSymbolContextDIE(const DWARFDIE &child_die) {
391061da546Spatrick   DWARFDIE die;
392061da546Spatrick   for (die = child_die.GetParent(); die; die = die.GetParent()) {
393061da546Spatrick     dw_tag_t tag = die.Tag();
394061da546Spatrick 
395061da546Spatrick     switch (tag) {
396061da546Spatrick     case DW_TAG_compile_unit:
397061da546Spatrick     case DW_TAG_partial_unit:
398061da546Spatrick     case DW_TAG_subprogram:
399061da546Spatrick     case DW_TAG_inlined_subroutine:
400061da546Spatrick     case DW_TAG_lexical_block:
401061da546Spatrick       return die;
402061da546Spatrick     default:
403061da546Spatrick       break;
404061da546Spatrick     }
405061da546Spatrick   }
406061da546Spatrick   return DWARFDIE();
407061da546Spatrick }
408061da546Spatrick 
SymbolFileDWARF(ObjectFileSP objfile_sp,SectionList * dwo_section_list)409061da546Spatrick SymbolFileDWARF::SymbolFileDWARF(ObjectFileSP objfile_sp,
410061da546Spatrick                                  SectionList *dwo_section_list)
411*f6aab3d8Srobert     : SymbolFileCommon(std::move(objfile_sp)),
412061da546Spatrick       UserID(0x7fffffff00000000), // Used by SymbolFileDWARFDebugMap to
413061da546Spatrick                                   // when this class parses .o files to
414061da546Spatrick                                   // contain the .o file index/ID
415061da546Spatrick       m_debug_map_module_wp(), m_debug_map_symfile(nullptr),
416061da546Spatrick       m_context(m_objfile_sp->GetModule()->GetSectionList(), dwo_section_list),
417dda28197Spatrick       m_fetched_external_modules(false),
418dda28197Spatrick       m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate) {}
419061da546Spatrick 
420be691f3bSpatrick SymbolFileDWARF::~SymbolFileDWARF() = default;
421061da546Spatrick 
GetDWARFMachOSegmentName()422061da546Spatrick static ConstString GetDWARFMachOSegmentName() {
423061da546Spatrick   static ConstString g_dwarf_section_name("__DWARF");
424061da546Spatrick   return g_dwarf_section_name;
425061da546Spatrick }
426061da546Spatrick 
GetUniqueDWARFASTTypeMap()427061da546Spatrick UniqueDWARFASTTypeMap &SymbolFileDWARF::GetUniqueDWARFASTTypeMap() {
428061da546Spatrick   SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
429061da546Spatrick   if (debug_map_symfile)
430061da546Spatrick     return debug_map_symfile->GetUniqueDWARFASTTypeMap();
431061da546Spatrick   else
432061da546Spatrick     return m_unique_ast_type_map;
433061da546Spatrick }
434061da546Spatrick 
435*f6aab3d8Srobert llvm::Expected<lldb::TypeSystemSP>
GetTypeSystemForLanguage(LanguageType language)436061da546Spatrick SymbolFileDWARF::GetTypeSystemForLanguage(LanguageType language) {
437061da546Spatrick   if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile())
438061da546Spatrick     return debug_map_symfile->GetTypeSystemForLanguage(language);
439061da546Spatrick 
440061da546Spatrick   auto type_system_or_err =
441061da546Spatrick       m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language);
442*f6aab3d8Srobert   if (type_system_or_err)
443*f6aab3d8Srobert     if (auto ts = *type_system_or_err)
444*f6aab3d8Srobert       ts->SetSymbolFile(this);
445061da546Spatrick   return type_system_or_err;
446061da546Spatrick }
447061da546Spatrick 
InitializeObject()448061da546Spatrick void SymbolFileDWARF::InitializeObject() {
449*f6aab3d8Srobert   Log *log = GetLog(DWARFLog::DebugInfo);
450061da546Spatrick 
451*f6aab3d8Srobert   InitializeFirstCodeAddress();
452*f6aab3d8Srobert 
453*f6aab3d8Srobert   if (!GetGlobalPluginProperties().IgnoreFileIndexes()) {
454be691f3bSpatrick     StreamString module_desc;
455be691f3bSpatrick     GetObjectFile()->GetModule()->GetDescription(module_desc.AsRawOstream(),
456be691f3bSpatrick                                                  lldb::eDescriptionLevelBrief);
457061da546Spatrick     DWARFDataExtractor apple_names, apple_namespaces, apple_types, apple_objc;
458061da546Spatrick     LoadSectionData(eSectionTypeDWARFAppleNames, apple_names);
459061da546Spatrick     LoadSectionData(eSectionTypeDWARFAppleNamespaces, apple_namespaces);
460061da546Spatrick     LoadSectionData(eSectionTypeDWARFAppleTypes, apple_types);
461061da546Spatrick     LoadSectionData(eSectionTypeDWARFAppleObjC, apple_objc);
462061da546Spatrick 
463be691f3bSpatrick     if (apple_names.GetByteSize() > 0 || apple_namespaces.GetByteSize() > 0 ||
464be691f3bSpatrick         apple_types.GetByteSize() > 0 || apple_objc.GetByteSize() > 0) {
465be691f3bSpatrick       Progress progress(llvm::formatv("Loading Apple DWARF index for {0}",
466be691f3bSpatrick                                       module_desc.GetData()));
467061da546Spatrick       m_index = AppleDWARFIndex::Create(
468061da546Spatrick           *GetObjectFile()->GetModule(), apple_names, apple_namespaces,
469061da546Spatrick           apple_types, apple_objc, m_context.getOrLoadStrData());
470061da546Spatrick 
471061da546Spatrick       if (m_index)
472061da546Spatrick         return;
473be691f3bSpatrick     }
474061da546Spatrick 
475061da546Spatrick     DWARFDataExtractor debug_names;
476061da546Spatrick     LoadSectionData(eSectionTypeDWARFDebugNames, debug_names);
477061da546Spatrick     if (debug_names.GetByteSize() > 0) {
478be691f3bSpatrick       Progress progress(
479be691f3bSpatrick           llvm::formatv("Loading DWARF5 index for {0}", module_desc.GetData()));
480061da546Spatrick       llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>> index_or =
481dda28197Spatrick           DebugNamesDWARFIndex::Create(*GetObjectFile()->GetModule(),
482dda28197Spatrick                                        debug_names,
483dda28197Spatrick                                        m_context.getOrLoadStrData(), *this);
484061da546Spatrick       if (index_or) {
485061da546Spatrick         m_index = std::move(*index_or);
486061da546Spatrick         return;
487061da546Spatrick       }
488061da546Spatrick       LLDB_LOG_ERROR(log, index_or.takeError(),
489061da546Spatrick                      "Unable to read .debug_names data: {0}");
490061da546Spatrick     }
491061da546Spatrick   }
492061da546Spatrick 
493dda28197Spatrick   m_index =
494dda28197Spatrick       std::make_unique<ManualDWARFIndex>(*GetObjectFile()->GetModule(), *this);
495061da546Spatrick }
496061da546Spatrick 
InitializeFirstCodeAddress()497*f6aab3d8Srobert void SymbolFileDWARF::InitializeFirstCodeAddress() {
498*f6aab3d8Srobert   InitializeFirstCodeAddressRecursive(
499*f6aab3d8Srobert       *m_objfile_sp->GetModule()->GetSectionList());
500*f6aab3d8Srobert   if (m_first_code_address == LLDB_INVALID_ADDRESS)
501*f6aab3d8Srobert     m_first_code_address = 0;
502*f6aab3d8Srobert }
503*f6aab3d8Srobert 
InitializeFirstCodeAddressRecursive(const lldb_private::SectionList & section_list)504*f6aab3d8Srobert void SymbolFileDWARF::InitializeFirstCodeAddressRecursive(
505*f6aab3d8Srobert     const lldb_private::SectionList &section_list) {
506*f6aab3d8Srobert   for (SectionSP section_sp : section_list) {
507*f6aab3d8Srobert     if (section_sp->GetChildren().GetSize() > 0) {
508*f6aab3d8Srobert       InitializeFirstCodeAddressRecursive(section_sp->GetChildren());
509*f6aab3d8Srobert     } else if (section_sp->GetType() == eSectionTypeCode) {
510*f6aab3d8Srobert       m_first_code_address =
511*f6aab3d8Srobert           std::min(m_first_code_address, section_sp->GetFileAddress());
512*f6aab3d8Srobert     }
513*f6aab3d8Srobert   }
514*f6aab3d8Srobert }
515*f6aab3d8Srobert 
SupportedVersion(uint16_t version)516061da546Spatrick bool SymbolFileDWARF::SupportedVersion(uint16_t version) {
517061da546Spatrick   return version >= 2 && version <= 5;
518061da546Spatrick }
519061da546Spatrick 
CalculateAbilities()520061da546Spatrick uint32_t SymbolFileDWARF::CalculateAbilities() {
521061da546Spatrick   uint32_t abilities = 0;
522061da546Spatrick   if (m_objfile_sp != nullptr) {
523061da546Spatrick     const Section *section = nullptr;
524061da546Spatrick     const SectionList *section_list = m_objfile_sp->GetSectionList();
525061da546Spatrick     if (section_list == nullptr)
526061da546Spatrick       return 0;
527061da546Spatrick 
528061da546Spatrick     uint64_t debug_abbrev_file_size = 0;
529061da546Spatrick     uint64_t debug_info_file_size = 0;
530061da546Spatrick     uint64_t debug_line_file_size = 0;
531061da546Spatrick 
532061da546Spatrick     section = section_list->FindSectionByName(GetDWARFMachOSegmentName()).get();
533061da546Spatrick 
534061da546Spatrick     if (section)
535061da546Spatrick       section_list = &section->GetChildren();
536061da546Spatrick 
537061da546Spatrick     section =
538061da546Spatrick         section_list->FindSectionByType(eSectionTypeDWARFDebugInfo, true).get();
539061da546Spatrick     if (section != nullptr) {
540061da546Spatrick       debug_info_file_size = section->GetFileSize();
541061da546Spatrick 
542061da546Spatrick       section =
543061da546Spatrick           section_list->FindSectionByType(eSectionTypeDWARFDebugAbbrev, true)
544061da546Spatrick               .get();
545061da546Spatrick       if (section)
546061da546Spatrick         debug_abbrev_file_size = section->GetFileSize();
547061da546Spatrick 
548061da546Spatrick       DWARFDebugAbbrev *abbrev = DebugAbbrev();
549061da546Spatrick       if (abbrev) {
550061da546Spatrick         std::set<dw_form_t> invalid_forms;
551061da546Spatrick         abbrev->GetUnsupportedForms(invalid_forms);
552061da546Spatrick         if (!invalid_forms.empty()) {
553061da546Spatrick           StreamString error;
554061da546Spatrick           error.Printf("unsupported DW_FORM value%s:",
555061da546Spatrick                        invalid_forms.size() > 1 ? "s" : "");
556061da546Spatrick           for (auto form : invalid_forms)
557061da546Spatrick             error.Printf(" %#x", form);
558061da546Spatrick           m_objfile_sp->GetModule()->ReportWarning(
559*f6aab3d8Srobert               "{0}", error.GetString().str().c_str());
560061da546Spatrick           return 0;
561061da546Spatrick         }
562061da546Spatrick       }
563061da546Spatrick 
564061da546Spatrick       section =
565061da546Spatrick           section_list->FindSectionByType(eSectionTypeDWARFDebugLine, true)
566061da546Spatrick               .get();
567061da546Spatrick       if (section)
568061da546Spatrick         debug_line_file_size = section->GetFileSize();
569061da546Spatrick     } else {
570*f6aab3d8Srobert       llvm::StringRef symfile_dir =
571*f6aab3d8Srobert           m_objfile_sp->GetFileSpec().GetDirectory().GetStringRef();
572*f6aab3d8Srobert       if (symfile_dir.contains_insensitive(".dsym")) {
573061da546Spatrick         if (m_objfile_sp->GetType() == ObjectFile::eTypeDebugInfo) {
574061da546Spatrick           // We have a dSYM file that didn't have a any debug info. If the
575061da546Spatrick           // string table has a size of 1, then it was made from an
576061da546Spatrick           // executable with no debug info, or from an executable that was
577061da546Spatrick           // stripped.
578061da546Spatrick           section =
579061da546Spatrick               section_list->FindSectionByType(eSectionTypeDWARFDebugStr, true)
580061da546Spatrick                   .get();
581061da546Spatrick           if (section && section->GetFileSize() == 1) {
582061da546Spatrick             m_objfile_sp->GetModule()->ReportWarning(
583061da546Spatrick                 "empty dSYM file detected, dSYM was created with an "
584061da546Spatrick                 "executable with no debug info.");
585061da546Spatrick           }
586061da546Spatrick         }
587061da546Spatrick       }
588061da546Spatrick     }
589061da546Spatrick 
590061da546Spatrick     if (debug_abbrev_file_size > 0 && debug_info_file_size > 0)
591061da546Spatrick       abilities |= CompileUnits | Functions | Blocks | GlobalVariables |
592061da546Spatrick                    LocalVariables | VariableTypes;
593061da546Spatrick 
594061da546Spatrick     if (debug_line_file_size > 0)
595061da546Spatrick       abilities |= LineTables;
596061da546Spatrick   }
597061da546Spatrick   return abilities;
598061da546Spatrick }
599061da546Spatrick 
LoadSectionData(lldb::SectionType sect_type,DWARFDataExtractor & data)600061da546Spatrick void SymbolFileDWARF::LoadSectionData(lldb::SectionType sect_type,
601061da546Spatrick                                       DWARFDataExtractor &data) {
602061da546Spatrick   ModuleSP module_sp(m_objfile_sp->GetModule());
603061da546Spatrick   const SectionList *section_list = module_sp->GetSectionList();
604061da546Spatrick   if (!section_list)
605061da546Spatrick     return;
606061da546Spatrick 
607061da546Spatrick   SectionSP section_sp(section_list->FindSectionByType(sect_type, true));
608061da546Spatrick   if (!section_sp)
609061da546Spatrick     return;
610061da546Spatrick 
611061da546Spatrick   data.Clear();
612061da546Spatrick   m_objfile_sp->ReadSectionData(section_sp.get(), data);
613061da546Spatrick }
614061da546Spatrick 
DebugAbbrev()615061da546Spatrick DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() {
616061da546Spatrick   if (m_abbr)
617061da546Spatrick     return m_abbr.get();
618061da546Spatrick 
619061da546Spatrick   const DWARFDataExtractor &debug_abbrev_data = m_context.getOrLoadAbbrevData();
620061da546Spatrick   if (debug_abbrev_data.GetByteSize() == 0)
621061da546Spatrick     return nullptr;
622061da546Spatrick 
623061da546Spatrick   auto abbr = std::make_unique<DWARFDebugAbbrev>();
624061da546Spatrick   llvm::Error error = abbr->parse(debug_abbrev_data);
625061da546Spatrick   if (error) {
626*f6aab3d8Srobert     Log *log = GetLog(DWARFLog::DebugInfo);
627061da546Spatrick     LLDB_LOG_ERROR(log, std::move(error),
628061da546Spatrick                    "Unable to read .debug_abbrev section: {0}");
629061da546Spatrick     return nullptr;
630061da546Spatrick   }
631061da546Spatrick 
632061da546Spatrick   m_abbr = std::move(abbr);
633061da546Spatrick   return m_abbr.get();
634061da546Spatrick }
635061da546Spatrick 
DebugInfo()636dda28197Spatrick DWARFDebugInfo &SymbolFileDWARF::DebugInfo() {
637dda28197Spatrick   llvm::call_once(m_info_once_flag, [&] {
638be691f3bSpatrick     LLDB_SCOPED_TIMERF("%s this = %p", LLVM_PRETTY_FUNCTION,
639061da546Spatrick                        static_cast<void *>(this));
640061da546Spatrick     m_info = std::make_unique<DWARFDebugInfo>(*this, m_context);
641dda28197Spatrick   });
642dda28197Spatrick   return *m_info;
643061da546Spatrick }
644061da546Spatrick 
GetDWARFCompileUnit(CompileUnit * comp_unit)645be691f3bSpatrick DWARFCompileUnit *SymbolFileDWARF::GetDWARFCompileUnit(CompileUnit *comp_unit) {
646061da546Spatrick   if (!comp_unit)
647061da546Spatrick     return nullptr;
648061da546Spatrick 
649061da546Spatrick   // The compile unit ID is the index of the DWARF unit.
650dda28197Spatrick   DWARFUnit *dwarf_cu = DebugInfo().GetUnitAtIndex(comp_unit->GetID());
651061da546Spatrick   if (dwarf_cu && dwarf_cu->GetUserData() == nullptr)
652061da546Spatrick     dwarf_cu->SetUserData(comp_unit);
653be691f3bSpatrick 
654be691f3bSpatrick   // It must be DWARFCompileUnit when it created a CompileUnit.
655be691f3bSpatrick   return llvm::cast_or_null<DWARFCompileUnit>(dwarf_cu);
656061da546Spatrick }
657061da546Spatrick 
GetDebugRanges()658061da546Spatrick DWARFDebugRanges *SymbolFileDWARF::GetDebugRanges() {
659061da546Spatrick   if (!m_ranges) {
660be691f3bSpatrick     LLDB_SCOPED_TIMERF("%s this = %p", LLVM_PRETTY_FUNCTION,
661061da546Spatrick                        static_cast<void *>(this));
662061da546Spatrick 
663061da546Spatrick     if (m_context.getOrLoadRangesData().GetByteSize() > 0)
664dda28197Spatrick       m_ranges = std::make_unique<DWARFDebugRanges>();
665061da546Spatrick 
666061da546Spatrick     if (m_ranges)
667061da546Spatrick       m_ranges->Extract(m_context);
668061da546Spatrick   }
669061da546Spatrick   return m_ranges.get();
670061da546Spatrick }
671061da546Spatrick 
672dda28197Spatrick /// Make an absolute path out of \p file_spec and remap it using the
673dda28197Spatrick /// module's source remapping dictionary.
MakeAbsoluteAndRemap(FileSpec & file_spec,DWARFUnit & dwarf_cu,const ModuleSP & module_sp)674dda28197Spatrick static void MakeAbsoluteAndRemap(FileSpec &file_spec, DWARFUnit &dwarf_cu,
675dda28197Spatrick                                  const ModuleSP &module_sp) {
676dda28197Spatrick   if (!file_spec)
677dda28197Spatrick     return;
678dda28197Spatrick   // If we have a full path to the compile unit, we don't need to
679dda28197Spatrick   // resolve the file.  This can be expensive e.g. when the source
680dda28197Spatrick   // files are NFS mounted.
681dda28197Spatrick   file_spec.MakeAbsolute(dwarf_cu.GetCompilationDirectory());
682dda28197Spatrick 
683be691f3bSpatrick   if (auto remapped_file = module_sp->RemapSourceFile(file_spec.GetPath()))
684be691f3bSpatrick     file_spec.SetFile(*remapped_file, FileSpec::Style::native);
685dda28197Spatrick }
686dda28197Spatrick 
687*f6aab3d8Srobert /// Return the DW_AT_(GNU_)dwo_name.
GetDWOName(DWARFCompileUnit & dwarf_cu,const DWARFDebugInfoEntry & cu_die)688*f6aab3d8Srobert static const char *GetDWOName(DWARFCompileUnit &dwarf_cu,
689*f6aab3d8Srobert                               const DWARFDebugInfoEntry &cu_die) {
690*f6aab3d8Srobert   const char *dwo_name =
691*f6aab3d8Srobert       cu_die.GetAttributeValueAsString(&dwarf_cu, DW_AT_GNU_dwo_name, nullptr);
692*f6aab3d8Srobert   if (!dwo_name)
693*f6aab3d8Srobert     dwo_name =
694*f6aab3d8Srobert         cu_die.GetAttributeValueAsString(&dwarf_cu, DW_AT_dwo_name, nullptr);
695*f6aab3d8Srobert   return dwo_name;
696*f6aab3d8Srobert }
697*f6aab3d8Srobert 
ParseCompileUnit(DWARFCompileUnit & dwarf_cu)698061da546Spatrick lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
699061da546Spatrick   CompUnitSP cu_sp;
700061da546Spatrick   CompileUnit *comp_unit = (CompileUnit *)dwarf_cu.GetUserData();
701061da546Spatrick   if (comp_unit) {
702061da546Spatrick     // We already parsed this compile unit, had out a shared pointer to it
703061da546Spatrick     cu_sp = comp_unit->shared_from_this();
704061da546Spatrick   } else {
705*f6aab3d8Srobert     if (GetDebugMapSymfile()) {
706061da546Spatrick       // Let the debug map create the compile unit
707*f6aab3d8Srobert       cu_sp = m_debug_map_symfile->GetCompileUnit(this, dwarf_cu);
708061da546Spatrick       dwarf_cu.SetUserData(cu_sp.get());
709061da546Spatrick     } else {
710061da546Spatrick       ModuleSP module_sp(m_objfile_sp->GetModule());
711061da546Spatrick       if (module_sp) {
712*f6aab3d8Srobert         auto initialize_cu = [&](const FileSpec &file_spec,
713*f6aab3d8Srobert                                  LanguageType cu_language) {
714061da546Spatrick           BuildCuTranslationTable();
715061da546Spatrick           cu_sp = std::make_shared<CompileUnit>(
716*f6aab3d8Srobert               module_sp, &dwarf_cu, file_spec,
717061da546Spatrick               *GetDWARFUnitIndex(dwarf_cu.GetID()), cu_language,
718*f6aab3d8Srobert               eLazyBoolCalculate);
719061da546Spatrick 
720061da546Spatrick           dwarf_cu.SetUserData(cu_sp.get());
721061da546Spatrick 
722061da546Spatrick           SetCompileUnitAtIndex(dwarf_cu.GetID(), cu_sp);
723*f6aab3d8Srobert         };
724*f6aab3d8Srobert 
725*f6aab3d8Srobert         auto lazy_initialize_cu = [&]() {
726*f6aab3d8Srobert           // If the version is < 5, we can't do lazy initialization.
727*f6aab3d8Srobert           if (dwarf_cu.GetVersion() < 5)
728*f6aab3d8Srobert             return false;
729*f6aab3d8Srobert 
730*f6aab3d8Srobert           // If there is no DWO, there is no reason to initialize
731*f6aab3d8Srobert           // lazily; we will do eager initialization in that case.
732*f6aab3d8Srobert           if (GetDebugMapSymfile())
733*f6aab3d8Srobert             return false;
734*f6aab3d8Srobert           const DWARFBaseDIE cu_die = dwarf_cu.GetUnitDIEOnly();
735*f6aab3d8Srobert           if (!cu_die)
736*f6aab3d8Srobert             return false;
737*f6aab3d8Srobert           if (!GetDWOName(dwarf_cu, *cu_die.GetDIE()))
738*f6aab3d8Srobert             return false;
739*f6aab3d8Srobert 
740*f6aab3d8Srobert           // With DWARFv5 we can assume that the first support
741*f6aab3d8Srobert           // file is also the name of the compile unit. This
742*f6aab3d8Srobert           // allows us to avoid loading the non-skeleton unit,
743*f6aab3d8Srobert           // which may be in a separate DWO file.
744*f6aab3d8Srobert           FileSpecList support_files;
745*f6aab3d8Srobert           if (!ParseSupportFiles(dwarf_cu, module_sp, support_files))
746*f6aab3d8Srobert             return false;
747*f6aab3d8Srobert           if (support_files.GetSize() == 0)
748*f6aab3d8Srobert             return false;
749*f6aab3d8Srobert 
750*f6aab3d8Srobert           initialize_cu(support_files.GetFileSpecAtIndex(0),
751*f6aab3d8Srobert                         eLanguageTypeUnknown);
752*f6aab3d8Srobert           cu_sp->SetSupportFiles(std::move(support_files));
753*f6aab3d8Srobert           return true;
754*f6aab3d8Srobert         };
755*f6aab3d8Srobert 
756*f6aab3d8Srobert         if (!lazy_initialize_cu()) {
757*f6aab3d8Srobert           // Eagerly initialize compile unit
758*f6aab3d8Srobert           const DWARFBaseDIE cu_die =
759*f6aab3d8Srobert               dwarf_cu.GetNonSkeletonUnit().GetUnitDIEOnly();
760*f6aab3d8Srobert           if (cu_die) {
761*f6aab3d8Srobert             LanguageType cu_language = SymbolFileDWARF::LanguageTypeFromDWARF(
762*f6aab3d8Srobert                 dwarf_cu.GetDWARFLanguageType());
763*f6aab3d8Srobert 
764*f6aab3d8Srobert             FileSpec cu_file_spec(cu_die.GetName(), dwarf_cu.GetPathStyle());
765*f6aab3d8Srobert 
766*f6aab3d8Srobert             // Path needs to be remapped in this case. In the support files
767*f6aab3d8Srobert             // case ParseSupportFiles takes care of the remapping.
768*f6aab3d8Srobert             MakeAbsoluteAndRemap(cu_file_spec, dwarf_cu, module_sp);
769*f6aab3d8Srobert 
770*f6aab3d8Srobert             initialize_cu(cu_file_spec, cu_language);
771*f6aab3d8Srobert           }
772061da546Spatrick         }
773061da546Spatrick       }
774061da546Spatrick     }
775061da546Spatrick   }
776061da546Spatrick   return cu_sp;
777061da546Spatrick }
778061da546Spatrick 
BuildCuTranslationTable()779061da546Spatrick void SymbolFileDWARF::BuildCuTranslationTable() {
780061da546Spatrick   if (!m_lldb_cu_to_dwarf_unit.empty())
781061da546Spatrick     return;
782061da546Spatrick 
783dda28197Spatrick   DWARFDebugInfo &info = DebugInfo();
784dda28197Spatrick   if (!info.ContainsTypeUnits()) {
785061da546Spatrick     // We can use a 1-to-1 mapping. No need to build a translation table.
786061da546Spatrick     return;
787061da546Spatrick   }
788dda28197Spatrick   for (uint32_t i = 0, num = info.GetNumUnits(); i < num; ++i) {
789dda28197Spatrick     if (auto *cu = llvm::dyn_cast<DWARFCompileUnit>(info.GetUnitAtIndex(i))) {
790061da546Spatrick       cu->SetID(m_lldb_cu_to_dwarf_unit.size());
791061da546Spatrick       m_lldb_cu_to_dwarf_unit.push_back(i);
792061da546Spatrick     }
793061da546Spatrick   }
794061da546Spatrick }
795061da546Spatrick 
GetDWARFUnitIndex(uint32_t cu_idx)796*f6aab3d8Srobert std::optional<uint32_t> SymbolFileDWARF::GetDWARFUnitIndex(uint32_t cu_idx) {
797061da546Spatrick   BuildCuTranslationTable();
798061da546Spatrick   if (m_lldb_cu_to_dwarf_unit.empty())
799061da546Spatrick     return cu_idx;
800061da546Spatrick   if (cu_idx >= m_lldb_cu_to_dwarf_unit.size())
801*f6aab3d8Srobert     return std::nullopt;
802061da546Spatrick   return m_lldb_cu_to_dwarf_unit[cu_idx];
803061da546Spatrick }
804061da546Spatrick 
CalculateNumCompileUnits()805061da546Spatrick uint32_t SymbolFileDWARF::CalculateNumCompileUnits() {
806061da546Spatrick   BuildCuTranslationTable();
807dda28197Spatrick   return m_lldb_cu_to_dwarf_unit.empty() ? DebugInfo().GetNumUnits()
808061da546Spatrick                                          : m_lldb_cu_to_dwarf_unit.size();
809061da546Spatrick }
810061da546Spatrick 
ParseCompileUnitAtIndex(uint32_t cu_idx)811061da546Spatrick CompUnitSP SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx) {
812061da546Spatrick   ASSERT_MODULE_LOCK(this);
813*f6aab3d8Srobert   if (std::optional<uint32_t> dwarf_idx = GetDWARFUnitIndex(cu_idx)) {
814061da546Spatrick     if (auto *dwarf_cu = llvm::cast_or_null<DWARFCompileUnit>(
815dda28197Spatrick             DebugInfo().GetUnitAtIndex(*dwarf_idx)))
816061da546Spatrick       return ParseCompileUnit(*dwarf_cu);
817061da546Spatrick   }
818061da546Spatrick   return {};
819061da546Spatrick }
820061da546Spatrick 
ParseFunction(CompileUnit & comp_unit,const DWARFDIE & die)821061da546Spatrick Function *SymbolFileDWARF::ParseFunction(CompileUnit &comp_unit,
822061da546Spatrick                                          const DWARFDIE &die) {
823061da546Spatrick   ASSERT_MODULE_LOCK(this);
824061da546Spatrick   if (!die.IsValid())
825061da546Spatrick     return nullptr;
826061da546Spatrick 
827dda28197Spatrick   auto type_system_or_err = GetTypeSystemForLanguage(GetLanguage(*die.GetCU()));
828061da546Spatrick   if (auto err = type_system_or_err.takeError()) {
829*f6aab3d8Srobert     LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
830*f6aab3d8Srobert                    "Unable to parse function");
831061da546Spatrick     return nullptr;
832061da546Spatrick   }
833*f6aab3d8Srobert   auto ts = *type_system_or_err;
834*f6aab3d8Srobert   if (!ts)
835*f6aab3d8Srobert     return nullptr;
836*f6aab3d8Srobert   DWARFASTParser *dwarf_ast = ts->GetDWARFParser();
837061da546Spatrick   if (!dwarf_ast)
838061da546Spatrick     return nullptr;
839061da546Spatrick 
840*f6aab3d8Srobert   DWARFRangeList ranges;
841*f6aab3d8Srobert   if (die.GetDIE()->GetAttributeAddressRanges(die.GetCU(), ranges,
842*f6aab3d8Srobert                                               /*check_hi_lo_pc=*/true) == 0)
843*f6aab3d8Srobert     return nullptr;
844*f6aab3d8Srobert 
845*f6aab3d8Srobert   // Union of all ranges in the function DIE (if the function is
846*f6aab3d8Srobert   // discontiguous)
847*f6aab3d8Srobert   lldb::addr_t lowest_func_addr = ranges.GetMinRangeBase(0);
848*f6aab3d8Srobert   lldb::addr_t highest_func_addr = ranges.GetMaxRangeEnd(0);
849*f6aab3d8Srobert   if (lowest_func_addr == LLDB_INVALID_ADDRESS ||
850*f6aab3d8Srobert       lowest_func_addr >= highest_func_addr ||
851*f6aab3d8Srobert       lowest_func_addr < m_first_code_address)
852*f6aab3d8Srobert     return nullptr;
853*f6aab3d8Srobert 
854*f6aab3d8Srobert   ModuleSP module_sp(die.GetModule());
855*f6aab3d8Srobert   AddressRange func_range;
856*f6aab3d8Srobert   func_range.GetBaseAddress().ResolveAddressUsingFileSections(
857*f6aab3d8Srobert       lowest_func_addr, module_sp->GetSectionList());
858*f6aab3d8Srobert   if (!func_range.GetBaseAddress().IsValid())
859*f6aab3d8Srobert     return nullptr;
860*f6aab3d8Srobert 
861*f6aab3d8Srobert   func_range.SetByteSize(highest_func_addr - lowest_func_addr);
862*f6aab3d8Srobert   if (!FixupAddress(func_range.GetBaseAddress()))
863*f6aab3d8Srobert     return nullptr;
864*f6aab3d8Srobert 
865*f6aab3d8Srobert   return dwarf_ast->ParseFunctionFromDWARF(comp_unit, die, func_range);
866*f6aab3d8Srobert }
867*f6aab3d8Srobert 
868*f6aab3d8Srobert ConstString
ConstructFunctionDemangledName(const DWARFDIE & die)869*f6aab3d8Srobert SymbolFileDWARF::ConstructFunctionDemangledName(const DWARFDIE &die) {
870*f6aab3d8Srobert   ASSERT_MODULE_LOCK(this);
871*f6aab3d8Srobert   if (!die.IsValid()) {
872*f6aab3d8Srobert     return ConstString();
873*f6aab3d8Srobert   }
874*f6aab3d8Srobert 
875*f6aab3d8Srobert   auto type_system_or_err = GetTypeSystemForLanguage(GetLanguage(*die.GetCU()));
876*f6aab3d8Srobert   if (auto err = type_system_or_err.takeError()) {
877*f6aab3d8Srobert     LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
878*f6aab3d8Srobert                    "Unable to construct demangled name for function");
879*f6aab3d8Srobert     return ConstString();
880*f6aab3d8Srobert   }
881*f6aab3d8Srobert 
882*f6aab3d8Srobert   auto ts = *type_system_or_err;
883*f6aab3d8Srobert   if (!ts) {
884*f6aab3d8Srobert     LLDB_LOG(GetLog(LLDBLog::Symbols), "Type system no longer live");
885*f6aab3d8Srobert     return ConstString();
886*f6aab3d8Srobert   }
887*f6aab3d8Srobert   DWARFASTParser *dwarf_ast = ts->GetDWARFParser();
888*f6aab3d8Srobert   if (!dwarf_ast)
889*f6aab3d8Srobert     return ConstString();
890*f6aab3d8Srobert 
891*f6aab3d8Srobert   return dwarf_ast->ConstructDemangledNameFromDWARF(die);
892061da546Spatrick }
893061da546Spatrick 
FixupAddress(lldb::addr_t file_addr)894dda28197Spatrick lldb::addr_t SymbolFileDWARF::FixupAddress(lldb::addr_t file_addr) {
895dda28197Spatrick   SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
896dda28197Spatrick   if (debug_map_symfile)
897dda28197Spatrick     return debug_map_symfile->LinkOSOFileAddress(this, file_addr);
898dda28197Spatrick   return file_addr;
899dda28197Spatrick }
900dda28197Spatrick 
FixupAddress(Address & addr)901061da546Spatrick bool SymbolFileDWARF::FixupAddress(Address &addr) {
902061da546Spatrick   SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
903061da546Spatrick   if (debug_map_symfile) {
904061da546Spatrick     return debug_map_symfile->LinkOSOAddress(addr);
905061da546Spatrick   }
906061da546Spatrick   // This is a normal DWARF file, no address fixups need to happen
907061da546Spatrick   return true;
908061da546Spatrick }
ParseLanguage(CompileUnit & comp_unit)909061da546Spatrick lldb::LanguageType SymbolFileDWARF::ParseLanguage(CompileUnit &comp_unit) {
910061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
911061da546Spatrick   DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
912061da546Spatrick   if (dwarf_cu)
913*f6aab3d8Srobert     return GetLanguage(dwarf_cu->GetNonSkeletonUnit());
914061da546Spatrick   else
915061da546Spatrick     return eLanguageTypeUnknown;
916061da546Spatrick }
917061da546Spatrick 
ParseXcodeSDK(CompileUnit & comp_unit)918dda28197Spatrick XcodeSDK SymbolFileDWARF::ParseXcodeSDK(CompileUnit &comp_unit) {
919dda28197Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
920dda28197Spatrick   DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
921dda28197Spatrick   if (!dwarf_cu)
922dda28197Spatrick     return {};
923dda28197Spatrick   const DWARFBaseDIE cu_die = dwarf_cu->GetNonSkeletonUnit().GetUnitDIEOnly();
924dda28197Spatrick   if (!cu_die)
925dda28197Spatrick     return {};
926dda28197Spatrick   const char *sdk = cu_die.GetAttributeValueAsString(DW_AT_APPLE_sdk, nullptr);
927dda28197Spatrick   if (!sdk)
928dda28197Spatrick     return {};
929dda28197Spatrick   const char *sysroot =
930dda28197Spatrick       cu_die.GetAttributeValueAsString(DW_AT_LLVM_sysroot, "");
931dda28197Spatrick   // Register the sysroot path remapping with the module belonging to
932dda28197Spatrick   // the CU as well as the one belonging to the symbol file. The two
933dda28197Spatrick   // would be different if this is an OSO object and module is the
934dda28197Spatrick   // corresponding debug map, in which case both should be updated.
935dda28197Spatrick   ModuleSP module_sp = comp_unit.GetModule();
936dda28197Spatrick   if (module_sp)
937dda28197Spatrick     module_sp->RegisterXcodeSDK(sdk, sysroot);
938dda28197Spatrick 
939dda28197Spatrick   ModuleSP local_module_sp = m_objfile_sp->GetModule();
940dda28197Spatrick   if (local_module_sp && local_module_sp != module_sp)
941dda28197Spatrick     local_module_sp->RegisterXcodeSDK(sdk, sysroot);
942dda28197Spatrick 
943dda28197Spatrick   return {sdk};
944dda28197Spatrick }
945dda28197Spatrick 
ParseFunctions(CompileUnit & comp_unit)946061da546Spatrick size_t SymbolFileDWARF::ParseFunctions(CompileUnit &comp_unit) {
947be691f3bSpatrick   LLDB_SCOPED_TIMER();
948061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
949061da546Spatrick   DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
950061da546Spatrick   if (!dwarf_cu)
951061da546Spatrick     return 0;
952061da546Spatrick 
953061da546Spatrick   size_t functions_added = 0;
954061da546Spatrick   dwarf_cu = &dwarf_cu->GetNonSkeletonUnit();
955061da546Spatrick   for (DWARFDebugInfoEntry &entry : dwarf_cu->dies()) {
956061da546Spatrick     if (entry.Tag() != DW_TAG_subprogram)
957061da546Spatrick       continue;
958061da546Spatrick 
959061da546Spatrick     DWARFDIE die(dwarf_cu, &entry);
960061da546Spatrick     if (comp_unit.FindFunctionByUID(die.GetID()))
961061da546Spatrick       continue;
962061da546Spatrick     if (ParseFunction(comp_unit, die))
963061da546Spatrick       ++functions_added;
964061da546Spatrick   }
965061da546Spatrick   // FixupTypes();
966061da546Spatrick   return functions_added;
967061da546Spatrick }
968061da546Spatrick 
ForEachExternalModule(CompileUnit & comp_unit,llvm::DenseSet<lldb_private::SymbolFile * > & visited_symbol_files,llvm::function_ref<bool (Module &)> lambda)969061da546Spatrick bool SymbolFileDWARF::ForEachExternalModule(
970061da546Spatrick     CompileUnit &comp_unit,
971061da546Spatrick     llvm::DenseSet<lldb_private::SymbolFile *> &visited_symbol_files,
972061da546Spatrick     llvm::function_ref<bool(Module &)> lambda) {
973061da546Spatrick   // Only visit each symbol file once.
974061da546Spatrick   if (!visited_symbol_files.insert(this).second)
975061da546Spatrick     return false;
976061da546Spatrick 
977061da546Spatrick   UpdateExternalModuleListIfNeeded();
978061da546Spatrick   for (auto &p : m_external_type_modules) {
979061da546Spatrick     ModuleSP module = p.second;
980061da546Spatrick     if (!module)
981061da546Spatrick       continue;
982061da546Spatrick 
983061da546Spatrick     // Invoke the action and potentially early-exit.
984061da546Spatrick     if (lambda(*module))
985061da546Spatrick       return true;
986061da546Spatrick 
987061da546Spatrick     for (std::size_t i = 0; i < module->GetNumCompileUnits(); ++i) {
988061da546Spatrick       auto cu = module->GetCompileUnitAtIndex(i);
989061da546Spatrick       bool early_exit = cu->ForEachExternalModule(visited_symbol_files, lambda);
990061da546Spatrick       if (early_exit)
991061da546Spatrick         return true;
992061da546Spatrick     }
993061da546Spatrick   }
994061da546Spatrick   return false;
995061da546Spatrick }
996061da546Spatrick 
ParseSupportFiles(CompileUnit & comp_unit,FileSpecList & support_files)997061da546Spatrick bool SymbolFileDWARF::ParseSupportFiles(CompileUnit &comp_unit,
998061da546Spatrick                                         FileSpecList &support_files) {
999dda28197Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1000dda28197Spatrick   DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
1001dda28197Spatrick   if (!dwarf_cu)
1002dda28197Spatrick     return false;
1003dda28197Spatrick 
1004*f6aab3d8Srobert   if (!ParseSupportFiles(*dwarf_cu, comp_unit.GetModule(), support_files))
1005*f6aab3d8Srobert     return false;
1006*f6aab3d8Srobert 
1007*f6aab3d8Srobert   comp_unit.SetSupportFiles(support_files);
1008*f6aab3d8Srobert   return true;
1009*f6aab3d8Srobert }
1010*f6aab3d8Srobert 
ParseSupportFiles(DWARFUnit & dwarf_cu,const ModuleSP & module,FileSpecList & support_files)1011*f6aab3d8Srobert bool SymbolFileDWARF::ParseSupportFiles(DWARFUnit &dwarf_cu,
1012*f6aab3d8Srobert                                         const ModuleSP &module,
1013*f6aab3d8Srobert                                         FileSpecList &support_files) {
1014*f6aab3d8Srobert 
1015*f6aab3d8Srobert   dw_offset_t offset = dwarf_cu.GetLineTableOffset();
1016dda28197Spatrick   if (offset == DW_INVALID_OFFSET)
1017dda28197Spatrick     return false;
1018dda28197Spatrick 
1019*f6aab3d8Srobert   ElapsedTime elapsed(m_parse_time);
1020dda28197Spatrick   llvm::DWARFDebugLine::Prologue prologue;
1021dda28197Spatrick   if (!ParseLLVMLineTablePrologue(m_context, prologue, offset,
1022*f6aab3d8Srobert                                   dwarf_cu.GetOffset()))
1023dda28197Spatrick     return false;
1024dda28197Spatrick 
1025*f6aab3d8Srobert   std::string comp_dir = dwarf_cu.GetCompilationDirectory().GetPath();
1026*f6aab3d8Srobert   support_files = ParseSupportFilesFromPrologue(
1027*f6aab3d8Srobert       module, prologue, dwarf_cu.GetPathStyle(), comp_dir);
1028061da546Spatrick   return true;
1029061da546Spatrick }
1030061da546Spatrick 
GetFile(DWARFUnit & unit,size_t file_idx)1031061da546Spatrick FileSpec SymbolFileDWARF::GetFile(DWARFUnit &unit, size_t file_idx) {
1032061da546Spatrick   if (auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(&unit)) {
1033061da546Spatrick     if (CompileUnit *lldb_cu = GetCompUnitForDWARFCompUnit(*dwarf_cu))
1034061da546Spatrick       return lldb_cu->GetSupportFiles().GetFileSpecAtIndex(file_idx);
1035061da546Spatrick     return FileSpec();
1036061da546Spatrick   }
1037061da546Spatrick 
1038061da546Spatrick   auto &tu = llvm::cast<DWARFTypeUnit>(unit);
1039061da546Spatrick   return GetTypeUnitSupportFiles(tu).GetFileSpecAtIndex(file_idx);
1040061da546Spatrick }
1041061da546Spatrick 
1042061da546Spatrick const FileSpecList &
GetTypeUnitSupportFiles(DWARFTypeUnit & tu)1043061da546Spatrick SymbolFileDWARF::GetTypeUnitSupportFiles(DWARFTypeUnit &tu) {
1044061da546Spatrick   static FileSpecList empty_list;
1045061da546Spatrick 
1046061da546Spatrick   dw_offset_t offset = tu.GetLineTableOffset();
1047061da546Spatrick   if (offset == DW_INVALID_OFFSET ||
1048061da546Spatrick       offset == llvm::DenseMapInfo<dw_offset_t>::getEmptyKey() ||
1049061da546Spatrick       offset == llvm::DenseMapInfo<dw_offset_t>::getTombstoneKey())
1050061da546Spatrick     return empty_list;
1051061da546Spatrick 
1052061da546Spatrick   // Many type units can share a line table, so parse the support file list
1053061da546Spatrick   // once, and cache it based on the offset field.
1054061da546Spatrick   auto iter_bool = m_type_unit_support_files.try_emplace(offset);
1055061da546Spatrick   FileSpecList &list = iter_bool.first->second;
1056061da546Spatrick   if (iter_bool.second) {
1057061da546Spatrick     uint64_t line_table_offset = offset;
1058061da546Spatrick     llvm::DWARFDataExtractor data = m_context.getOrLoadLineData().GetAsLLVM();
1059061da546Spatrick     llvm::DWARFContext &ctx = m_context.GetAsLLVM();
1060061da546Spatrick     llvm::DWARFDebugLine::Prologue prologue;
1061dda28197Spatrick     auto report = [](llvm::Error error) {
1062*f6aab3d8Srobert       Log *log = GetLog(DWARFLog::DebugInfo);
1063061da546Spatrick       LLDB_LOG_ERROR(log, std::move(error),
1064061da546Spatrick                      "SymbolFileDWARF::GetTypeUnitSupportFiles failed to parse "
1065061da546Spatrick                      "the line table prologue");
1066dda28197Spatrick     };
1067*f6aab3d8Srobert     ElapsedTime elapsed(m_parse_time);
1068dda28197Spatrick     llvm::Error error = prologue.parse(data, &line_table_offset, report, ctx);
1069dda28197Spatrick     if (error) {
1070dda28197Spatrick       report(std::move(error));
1071061da546Spatrick     } else {
1072061da546Spatrick       list = ParseSupportFilesFromPrologue(GetObjectFile()->GetModule(),
1073061da546Spatrick                                            prologue, tu.GetPathStyle());
1074061da546Spatrick     }
1075061da546Spatrick   }
1076061da546Spatrick   return list;
1077061da546Spatrick }
1078061da546Spatrick 
ParseIsOptimized(CompileUnit & comp_unit)1079061da546Spatrick bool SymbolFileDWARF::ParseIsOptimized(CompileUnit &comp_unit) {
1080061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1081061da546Spatrick   DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
1082061da546Spatrick   if (dwarf_cu)
1083*f6aab3d8Srobert     return dwarf_cu->GetNonSkeletonUnit().GetIsOptimized();
1084061da546Spatrick   return false;
1085061da546Spatrick }
1086061da546Spatrick 
ParseImportedModules(const lldb_private::SymbolContext & sc,std::vector<SourceModule> & imported_modules)1087061da546Spatrick bool SymbolFileDWARF::ParseImportedModules(
1088061da546Spatrick     const lldb_private::SymbolContext &sc,
1089061da546Spatrick     std::vector<SourceModule> &imported_modules) {
1090061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1091061da546Spatrick   assert(sc.comp_unit);
1092061da546Spatrick   DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
1093061da546Spatrick   if (!dwarf_cu)
1094061da546Spatrick     return false;
1095061da546Spatrick   if (!ClangModulesDeclVendor::LanguageSupportsClangModules(
1096061da546Spatrick           sc.comp_unit->GetLanguage()))
1097061da546Spatrick     return false;
1098061da546Spatrick   UpdateExternalModuleListIfNeeded();
1099061da546Spatrick 
1100061da546Spatrick   const DWARFDIE die = dwarf_cu->DIE();
1101061da546Spatrick   if (!die)
1102061da546Spatrick     return false;
1103061da546Spatrick 
1104be691f3bSpatrick   for (DWARFDIE child_die : die.children()) {
1105061da546Spatrick     if (child_die.Tag() != DW_TAG_imported_declaration)
1106061da546Spatrick       continue;
1107061da546Spatrick 
1108061da546Spatrick     DWARFDIE module_die = child_die.GetReferencedDIE(DW_AT_import);
1109061da546Spatrick     if (module_die.Tag() != DW_TAG_module)
1110061da546Spatrick       continue;
1111061da546Spatrick 
1112061da546Spatrick     if (const char *name =
1113061da546Spatrick             module_die.GetAttributeValueAsString(DW_AT_name, nullptr)) {
1114061da546Spatrick       SourceModule module;
1115061da546Spatrick       module.path.push_back(ConstString(name));
1116061da546Spatrick 
1117061da546Spatrick       DWARFDIE parent_die = module_die;
1118061da546Spatrick       while ((parent_die = parent_die.GetParent())) {
1119061da546Spatrick         if (parent_die.Tag() != DW_TAG_module)
1120061da546Spatrick           break;
1121061da546Spatrick         if (const char *name =
1122061da546Spatrick                 parent_die.GetAttributeValueAsString(DW_AT_name, nullptr))
1123061da546Spatrick           module.path.push_back(ConstString(name));
1124061da546Spatrick       }
1125061da546Spatrick       std::reverse(module.path.begin(), module.path.end());
1126061da546Spatrick       if (const char *include_path = module_die.GetAttributeValueAsString(
1127dda28197Spatrick               DW_AT_LLVM_include_path, nullptr)) {
1128dda28197Spatrick         FileSpec include_spec(include_path, dwarf_cu->GetPathStyle());
1129*f6aab3d8Srobert         MakeAbsoluteAndRemap(include_spec, *dwarf_cu,
1130*f6aab3d8Srobert                              m_objfile_sp->GetModule());
1131dda28197Spatrick         module.search_path = ConstString(include_spec.GetPath());
1132dda28197Spatrick       }
1133dda28197Spatrick       if (const char *sysroot = dwarf_cu->DIE().GetAttributeValueAsString(
1134061da546Spatrick               DW_AT_LLVM_sysroot, nullptr))
1135061da546Spatrick         module.sysroot = ConstString(sysroot);
1136061da546Spatrick       imported_modules.push_back(module);
1137061da546Spatrick     }
1138061da546Spatrick   }
1139061da546Spatrick   return true;
1140061da546Spatrick }
1141061da546Spatrick 
ParseLineTable(CompileUnit & comp_unit)1142061da546Spatrick bool SymbolFileDWARF::ParseLineTable(CompileUnit &comp_unit) {
1143061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1144061da546Spatrick   if (comp_unit.GetLineTable() != nullptr)
1145061da546Spatrick     return true;
1146061da546Spatrick 
1147061da546Spatrick   DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
1148061da546Spatrick   if (!dwarf_cu)
1149061da546Spatrick     return false;
1150061da546Spatrick 
1151dda28197Spatrick   dw_offset_t offset = dwarf_cu->GetLineTableOffset();
1152dda28197Spatrick   if (offset == DW_INVALID_OFFSET)
1153061da546Spatrick     return false;
1154061da546Spatrick 
1155*f6aab3d8Srobert   ElapsedTime elapsed(m_parse_time);
1156061da546Spatrick   llvm::DWARFDebugLine line;
1157dda28197Spatrick   const llvm::DWARFDebugLine::LineTable *line_table =
1158dda28197Spatrick       ParseLLVMLineTable(m_context, line, offset, dwarf_cu->GetOffset());
1159061da546Spatrick 
1160061da546Spatrick   if (!line_table)
1161061da546Spatrick     return false;
1162061da546Spatrick 
1163061da546Spatrick   // FIXME: Rather than parsing the whole line table and then copying it over
1164061da546Spatrick   // into LLDB, we should explore using a callback to populate the line table
1165061da546Spatrick   // while we parse to reduce memory usage.
1166dda28197Spatrick   std::vector<std::unique_ptr<LineSequence>> sequences;
1167dda28197Spatrick   // The Sequences view contains only valid line sequences. Don't iterate over
1168dda28197Spatrick   // the Rows directly.
1169dda28197Spatrick   for (const llvm::DWARFDebugLine::Sequence &seq : line_table->Sequences) {
1170*f6aab3d8Srobert     // Ignore line sequences that do not start after the first code address.
1171*f6aab3d8Srobert     // All addresses generated in a sequence are incremental so we only need
1172*f6aab3d8Srobert     // to check the first one of the sequence. Check the comment at the
1173*f6aab3d8Srobert     // m_first_code_address declaration for more details on this.
1174*f6aab3d8Srobert     if (seq.LowPC < m_first_code_address)
1175*f6aab3d8Srobert       continue;
1176dda28197Spatrick     std::unique_ptr<LineSequence> sequence =
1177dda28197Spatrick         LineTable::CreateLineSequenceContainer();
1178dda28197Spatrick     for (unsigned idx = seq.FirstRowIndex; idx < seq.LastRowIndex; ++idx) {
1179dda28197Spatrick       const llvm::DWARFDebugLine::Row &row = line_table->Rows[idx];
1180dda28197Spatrick       LineTable::AppendLineEntryToSequence(
1181dda28197Spatrick           sequence.get(), row.Address.Address, row.Line, row.Column, row.File,
1182061da546Spatrick           row.IsStmt, row.BasicBlock, row.PrologueEnd, row.EpilogueBegin,
1183061da546Spatrick           row.EndSequence);
1184061da546Spatrick     }
1185dda28197Spatrick     sequences.push_back(std::move(sequence));
1186061da546Spatrick   }
1187061da546Spatrick 
1188dda28197Spatrick   std::unique_ptr<LineTable> line_table_up =
1189dda28197Spatrick       std::make_unique<LineTable>(&comp_unit, std::move(sequences));
1190dda28197Spatrick 
1191061da546Spatrick   if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile()) {
1192061da546Spatrick     // We have an object file that has a line table with addresses that are not
1193061da546Spatrick     // linked. We need to link the line table and convert the addresses that
1194061da546Spatrick     // are relative to the .o file into addresses for the main executable.
1195061da546Spatrick     comp_unit.SetLineTable(
1196061da546Spatrick         debug_map_symfile->LinkOSOLineTable(this, line_table_up.get()));
1197061da546Spatrick   } else {
1198061da546Spatrick     comp_unit.SetLineTable(line_table_up.release());
1199061da546Spatrick   }
1200061da546Spatrick 
1201061da546Spatrick   return true;
1202061da546Spatrick }
1203061da546Spatrick 
1204061da546Spatrick lldb_private::DebugMacrosSP
ParseDebugMacros(lldb::offset_t * offset)1205061da546Spatrick SymbolFileDWARF::ParseDebugMacros(lldb::offset_t *offset) {
1206061da546Spatrick   auto iter = m_debug_macros_map.find(*offset);
1207061da546Spatrick   if (iter != m_debug_macros_map.end())
1208061da546Spatrick     return iter->second;
1209061da546Spatrick 
1210*f6aab3d8Srobert   ElapsedTime elapsed(m_parse_time);
1211061da546Spatrick   const DWARFDataExtractor &debug_macro_data = m_context.getOrLoadMacroData();
1212061da546Spatrick   if (debug_macro_data.GetByteSize() == 0)
1213061da546Spatrick     return DebugMacrosSP();
1214061da546Spatrick 
1215061da546Spatrick   lldb_private::DebugMacrosSP debug_macros_sp(new lldb_private::DebugMacros());
1216061da546Spatrick   m_debug_macros_map[*offset] = debug_macros_sp;
1217061da546Spatrick 
1218061da546Spatrick   const DWARFDebugMacroHeader &header =
1219061da546Spatrick       DWARFDebugMacroHeader::ParseHeader(debug_macro_data, offset);
1220061da546Spatrick   DWARFDebugMacroEntry::ReadMacroEntries(
1221061da546Spatrick       debug_macro_data, m_context.getOrLoadStrData(), header.OffsetIs64Bit(),
1222061da546Spatrick       offset, this, debug_macros_sp);
1223061da546Spatrick 
1224061da546Spatrick   return debug_macros_sp;
1225061da546Spatrick }
1226061da546Spatrick 
ParseDebugMacros(CompileUnit & comp_unit)1227061da546Spatrick bool SymbolFileDWARF::ParseDebugMacros(CompileUnit &comp_unit) {
1228061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1229061da546Spatrick 
1230061da546Spatrick   DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
1231061da546Spatrick   if (dwarf_cu == nullptr)
1232061da546Spatrick     return false;
1233061da546Spatrick 
1234061da546Spatrick   const DWARFBaseDIE dwarf_cu_die = dwarf_cu->GetUnitDIEOnly();
1235061da546Spatrick   if (!dwarf_cu_die)
1236061da546Spatrick     return false;
1237061da546Spatrick 
1238061da546Spatrick   lldb::offset_t sect_offset =
1239061da546Spatrick       dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_macros, DW_INVALID_OFFSET);
1240061da546Spatrick   if (sect_offset == DW_INVALID_OFFSET)
1241061da546Spatrick     sect_offset = dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_macros,
1242061da546Spatrick                                                            DW_INVALID_OFFSET);
1243061da546Spatrick   if (sect_offset == DW_INVALID_OFFSET)
1244061da546Spatrick     return false;
1245061da546Spatrick 
1246061da546Spatrick   comp_unit.SetDebugMacros(ParseDebugMacros(&sect_offset));
1247061da546Spatrick 
1248061da546Spatrick   return true;
1249061da546Spatrick }
1250061da546Spatrick 
ParseBlocksRecursive(lldb_private::CompileUnit & comp_unit,Block * parent_block,const DWARFDIE & orig_die,addr_t subprogram_low_pc,uint32_t depth)1251061da546Spatrick size_t SymbolFileDWARF::ParseBlocksRecursive(
1252061da546Spatrick     lldb_private::CompileUnit &comp_unit, Block *parent_block,
1253061da546Spatrick     const DWARFDIE &orig_die, addr_t subprogram_low_pc, uint32_t depth) {
1254061da546Spatrick   size_t blocks_added = 0;
1255061da546Spatrick   DWARFDIE die = orig_die;
1256061da546Spatrick   while (die) {
1257061da546Spatrick     dw_tag_t tag = die.Tag();
1258061da546Spatrick 
1259061da546Spatrick     switch (tag) {
1260061da546Spatrick     case DW_TAG_inlined_subroutine:
1261061da546Spatrick     case DW_TAG_subprogram:
1262061da546Spatrick     case DW_TAG_lexical_block: {
1263061da546Spatrick       Block *block = nullptr;
1264061da546Spatrick       if (tag == DW_TAG_subprogram) {
1265061da546Spatrick         // Skip any DW_TAG_subprogram DIEs that are inside of a normal or
1266061da546Spatrick         // inlined functions. These will be parsed on their own as separate
1267061da546Spatrick         // entities.
1268061da546Spatrick 
1269061da546Spatrick         if (depth > 0)
1270061da546Spatrick           break;
1271061da546Spatrick 
1272061da546Spatrick         block = parent_block;
1273061da546Spatrick       } else {
1274061da546Spatrick         BlockSP block_sp(new Block(die.GetID()));
1275061da546Spatrick         parent_block->AddChild(block_sp);
1276061da546Spatrick         block = block_sp.get();
1277061da546Spatrick       }
1278061da546Spatrick       DWARFRangeList ranges;
1279061da546Spatrick       const char *name = nullptr;
1280061da546Spatrick       const char *mangled_name = nullptr;
1281061da546Spatrick 
1282061da546Spatrick       int decl_file = 0;
1283061da546Spatrick       int decl_line = 0;
1284061da546Spatrick       int decl_column = 0;
1285061da546Spatrick       int call_file = 0;
1286061da546Spatrick       int call_line = 0;
1287061da546Spatrick       int call_column = 0;
1288061da546Spatrick       if (die.GetDIENamesAndRanges(name, mangled_name, ranges, decl_file,
1289061da546Spatrick                                    decl_line, decl_column, call_file, call_line,
1290061da546Spatrick                                    call_column, nullptr)) {
1291061da546Spatrick         if (tag == DW_TAG_subprogram) {
1292061da546Spatrick           assert(subprogram_low_pc == LLDB_INVALID_ADDRESS);
1293061da546Spatrick           subprogram_low_pc = ranges.GetMinRangeBase(0);
1294061da546Spatrick         } else if (tag == DW_TAG_inlined_subroutine) {
1295061da546Spatrick           // We get called here for inlined subroutines in two ways. The first
1296061da546Spatrick           // time is when we are making the Function object for this inlined
1297061da546Spatrick           // concrete instance.  Since we're creating a top level block at
1298061da546Spatrick           // here, the subprogram_low_pc will be LLDB_INVALID_ADDRESS.  So we
1299061da546Spatrick           // need to adjust the containing address. The second time is when we
1300061da546Spatrick           // are parsing the blocks inside the function that contains the
1301061da546Spatrick           // inlined concrete instance.  Since these will be blocks inside the
1302061da546Spatrick           // containing "real" function the offset will be for that function.
1303061da546Spatrick           if (subprogram_low_pc == LLDB_INVALID_ADDRESS) {
1304061da546Spatrick             subprogram_low_pc = ranges.GetMinRangeBase(0);
1305061da546Spatrick           }
1306061da546Spatrick         }
1307061da546Spatrick 
1308061da546Spatrick         const size_t num_ranges = ranges.GetSize();
1309061da546Spatrick         for (size_t i = 0; i < num_ranges; ++i) {
1310061da546Spatrick           const DWARFRangeList::Entry &range = ranges.GetEntryRef(i);
1311061da546Spatrick           const addr_t range_base = range.GetRangeBase();
1312061da546Spatrick           if (range_base >= subprogram_low_pc)
1313061da546Spatrick             block->AddRange(Block::Range(range_base - subprogram_low_pc,
1314061da546Spatrick                                          range.GetByteSize()));
1315061da546Spatrick           else {
1316061da546Spatrick             GetObjectFile()->GetModule()->ReportError(
1317*f6aab3d8Srobert                 "{0x:+8}: adding range [{1:x16}-{2:x16}) which has a base "
1318*f6aab3d8Srobert                 "that is less than the function's low PC {3:x16}. Please file "
1319*f6aab3d8Srobert                 "a bug and attach the file at the "
1320061da546Spatrick                 "start of this error message",
1321061da546Spatrick                 block->GetID(), range_base, range.GetRangeEnd(),
1322061da546Spatrick                 subprogram_low_pc);
1323061da546Spatrick           }
1324061da546Spatrick         }
1325061da546Spatrick         block->FinalizeRanges();
1326061da546Spatrick 
1327061da546Spatrick         if (tag != DW_TAG_subprogram &&
1328061da546Spatrick             (name != nullptr || mangled_name != nullptr)) {
1329061da546Spatrick           std::unique_ptr<Declaration> decl_up;
1330061da546Spatrick           if (decl_file != 0 || decl_line != 0 || decl_column != 0)
1331dda28197Spatrick             decl_up = std::make_unique<Declaration>(
1332061da546Spatrick                 comp_unit.GetSupportFiles().GetFileSpecAtIndex(decl_file),
1333dda28197Spatrick                 decl_line, decl_column);
1334061da546Spatrick 
1335061da546Spatrick           std::unique_ptr<Declaration> call_up;
1336061da546Spatrick           if (call_file != 0 || call_line != 0 || call_column != 0)
1337dda28197Spatrick             call_up = std::make_unique<Declaration>(
1338061da546Spatrick                 comp_unit.GetSupportFiles().GetFileSpecAtIndex(call_file),
1339dda28197Spatrick                 call_line, call_column);
1340061da546Spatrick 
1341061da546Spatrick           block->SetInlinedFunctionInfo(name, mangled_name, decl_up.get(),
1342061da546Spatrick                                         call_up.get());
1343061da546Spatrick         }
1344061da546Spatrick 
1345061da546Spatrick         ++blocks_added;
1346061da546Spatrick 
1347061da546Spatrick         if (die.HasChildren()) {
1348061da546Spatrick           blocks_added +=
1349061da546Spatrick               ParseBlocksRecursive(comp_unit, block, die.GetFirstChild(),
1350061da546Spatrick                                    subprogram_low_pc, depth + 1);
1351061da546Spatrick         }
1352061da546Spatrick       }
1353061da546Spatrick     } break;
1354061da546Spatrick     default:
1355061da546Spatrick       break;
1356061da546Spatrick     }
1357061da546Spatrick 
1358061da546Spatrick     // Only parse siblings of the block if we are not at depth zero. A depth of
1359061da546Spatrick     // zero indicates we are currently parsing the top level DW_TAG_subprogram
1360061da546Spatrick     // DIE
1361061da546Spatrick 
1362061da546Spatrick     if (depth == 0)
1363061da546Spatrick       die.Clear();
1364061da546Spatrick     else
1365061da546Spatrick       die = die.GetSibling();
1366061da546Spatrick   }
1367061da546Spatrick   return blocks_added;
1368061da546Spatrick }
1369061da546Spatrick 
ClassOrStructIsVirtual(const DWARFDIE & parent_die)1370061da546Spatrick bool SymbolFileDWARF::ClassOrStructIsVirtual(const DWARFDIE &parent_die) {
1371061da546Spatrick   if (parent_die) {
1372be691f3bSpatrick     for (DWARFDIE die : parent_die.children()) {
1373061da546Spatrick       dw_tag_t tag = die.Tag();
1374061da546Spatrick       bool check_virtuality = false;
1375061da546Spatrick       switch (tag) {
1376061da546Spatrick       case DW_TAG_inheritance:
1377061da546Spatrick       case DW_TAG_subprogram:
1378061da546Spatrick         check_virtuality = true;
1379061da546Spatrick         break;
1380061da546Spatrick       default:
1381061da546Spatrick         break;
1382061da546Spatrick       }
1383061da546Spatrick       if (check_virtuality) {
1384061da546Spatrick         if (die.GetAttributeValueAsUnsigned(DW_AT_virtuality, 0) != 0)
1385061da546Spatrick           return true;
1386061da546Spatrick       }
1387061da546Spatrick     }
1388061da546Spatrick   }
1389061da546Spatrick   return false;
1390061da546Spatrick }
1391061da546Spatrick 
ParseDeclsForContext(CompilerDeclContext decl_ctx)1392061da546Spatrick void SymbolFileDWARF::ParseDeclsForContext(CompilerDeclContext decl_ctx) {
1393061da546Spatrick   auto *type_system = decl_ctx.GetTypeSystem();
1394061da546Spatrick   if (type_system != nullptr)
1395061da546Spatrick     type_system->GetDWARFParser()->EnsureAllDIEsInDeclContextHaveBeenParsed(
1396061da546Spatrick         decl_ctx);
1397061da546Spatrick }
1398061da546Spatrick 
GetUID(DIERef ref)1399061da546Spatrick user_id_t SymbolFileDWARF::GetUID(DIERef ref) {
1400061da546Spatrick   if (GetDebugMapSymfile())
1401061da546Spatrick     return GetID() | ref.die_offset();
1402061da546Spatrick 
1403*f6aab3d8Srobert   lldbassert(GetDwoNum().value_or(0) <= 0x3fffffff);
1404*f6aab3d8Srobert   return user_id_t(GetDwoNum().value_or(0)) << 32 | ref.die_offset() |
1405*f6aab3d8Srobert          lldb::user_id_t(GetDwoNum().has_value()) << 62 |
1406be691f3bSpatrick          lldb::user_id_t(ref.section() == DIERef::Section::DebugTypes) << 63;
1407061da546Spatrick }
1408061da546Spatrick 
1409*f6aab3d8Srobert std::optional<SymbolFileDWARF::DecodedUID>
DecodeUID(lldb::user_id_t uid)1410061da546Spatrick SymbolFileDWARF::DecodeUID(lldb::user_id_t uid) {
1411061da546Spatrick   // This method can be called without going through the symbol vendor so we
1412061da546Spatrick   // need to lock the module.
1413061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1414061da546Spatrick   // Anytime we get a "lldb::user_id_t" from an lldb_private::SymbolFile API we
1415061da546Spatrick   // must make sure we use the correct DWARF file when resolving things. On
1416061da546Spatrick   // MacOSX, when using SymbolFileDWARFDebugMap, we will use multiple
1417061da546Spatrick   // SymbolFileDWARF classes, one for each .o file. We can often end up with
1418061da546Spatrick   // references to other DWARF objects and we must be ready to receive a
1419061da546Spatrick   // "lldb::user_id_t" that specifies a DIE from another SymbolFileDWARF
1420061da546Spatrick   // instance.
1421061da546Spatrick   if (SymbolFileDWARFDebugMap *debug_map = GetDebugMapSymfile()) {
1422061da546Spatrick     SymbolFileDWARF *dwarf = debug_map->GetSymbolFileByOSOIndex(
1423061da546Spatrick         debug_map->GetOSOIndexFromUserID(uid));
1424061da546Spatrick     return DecodedUID{
1425*f6aab3d8Srobert         *dwarf, {std::nullopt, DIERef::Section::DebugInfo, dw_offset_t(uid)}};
1426061da546Spatrick   }
1427061da546Spatrick   dw_offset_t die_offset = uid;
1428061da546Spatrick   if (die_offset == DW_INVALID_OFFSET)
1429*f6aab3d8Srobert     return std::nullopt;
1430061da546Spatrick 
1431061da546Spatrick   DIERef::Section section =
1432061da546Spatrick       uid >> 63 ? DIERef::Section::DebugTypes : DIERef::Section::DebugInfo;
1433061da546Spatrick 
1434*f6aab3d8Srobert   std::optional<uint32_t> dwo_num;
1435be691f3bSpatrick   bool dwo_valid = uid >> 62 & 1;
1436be691f3bSpatrick   if (dwo_valid)
1437be691f3bSpatrick     dwo_num = uid >> 32 & 0x3fffffff;
1438061da546Spatrick 
1439061da546Spatrick   return DecodedUID{*this, {dwo_num, section, die_offset}};
1440061da546Spatrick }
1441061da546Spatrick 
1442061da546Spatrick DWARFDIE
GetDIE(lldb::user_id_t uid)1443061da546Spatrick SymbolFileDWARF::GetDIE(lldb::user_id_t uid) {
1444061da546Spatrick   // This method can be called without going through the symbol vendor so we
1445061da546Spatrick   // need to lock the module.
1446061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1447061da546Spatrick 
1448*f6aab3d8Srobert   std::optional<DecodedUID> decoded = DecodeUID(uid);
1449061da546Spatrick 
1450061da546Spatrick   if (decoded)
1451061da546Spatrick     return decoded->dwarf.GetDIE(decoded->ref);
1452061da546Spatrick 
1453061da546Spatrick   return DWARFDIE();
1454061da546Spatrick }
1455061da546Spatrick 
GetDeclForUID(lldb::user_id_t type_uid)1456061da546Spatrick CompilerDecl SymbolFileDWARF::GetDeclForUID(lldb::user_id_t type_uid) {
1457061da546Spatrick   // This method can be called without going through the symbol vendor so we
1458061da546Spatrick   // need to lock the module.
1459061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1460061da546Spatrick   // Anytime we have a lldb::user_id_t, we must get the DIE by calling
1461061da546Spatrick   // SymbolFileDWARF::GetDIE(). See comments inside the
1462061da546Spatrick   // SymbolFileDWARF::GetDIE() for details.
1463061da546Spatrick   if (DWARFDIE die = GetDIE(type_uid))
1464dda28197Spatrick     return GetDecl(die);
1465061da546Spatrick   return CompilerDecl();
1466061da546Spatrick }
1467061da546Spatrick 
1468061da546Spatrick CompilerDeclContext
GetDeclContextForUID(lldb::user_id_t type_uid)1469061da546Spatrick SymbolFileDWARF::GetDeclContextForUID(lldb::user_id_t type_uid) {
1470061da546Spatrick   // This method can be called without going through the symbol vendor so we
1471061da546Spatrick   // need to lock the module.
1472061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1473061da546Spatrick   // Anytime we have a lldb::user_id_t, we must get the DIE by calling
1474061da546Spatrick   // SymbolFileDWARF::GetDIE(). See comments inside the
1475061da546Spatrick   // SymbolFileDWARF::GetDIE() for details.
1476061da546Spatrick   if (DWARFDIE die = GetDIE(type_uid))
1477dda28197Spatrick     return GetDeclContext(die);
1478061da546Spatrick   return CompilerDeclContext();
1479061da546Spatrick }
1480061da546Spatrick 
1481061da546Spatrick CompilerDeclContext
GetDeclContextContainingUID(lldb::user_id_t type_uid)1482061da546Spatrick SymbolFileDWARF::GetDeclContextContainingUID(lldb::user_id_t type_uid) {
1483061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1484061da546Spatrick   // Anytime we have a lldb::user_id_t, we must get the DIE by calling
1485061da546Spatrick   // SymbolFileDWARF::GetDIE(). See comments inside the
1486061da546Spatrick   // SymbolFileDWARF::GetDIE() for details.
1487061da546Spatrick   if (DWARFDIE die = GetDIE(type_uid))
1488dda28197Spatrick     return GetContainingDeclContext(die);
1489061da546Spatrick   return CompilerDeclContext();
1490061da546Spatrick }
1491061da546Spatrick 
ResolveTypeUID(lldb::user_id_t type_uid)1492061da546Spatrick Type *SymbolFileDWARF::ResolveTypeUID(lldb::user_id_t type_uid) {
1493061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1494061da546Spatrick   // Anytime we have a lldb::user_id_t, we must get the DIE by calling
1495061da546Spatrick   // SymbolFileDWARF::GetDIE(). See comments inside the
1496061da546Spatrick   // SymbolFileDWARF::GetDIE() for details.
1497061da546Spatrick   if (DWARFDIE type_die = GetDIE(type_uid))
1498061da546Spatrick     return type_die.ResolveType();
1499061da546Spatrick   else
1500061da546Spatrick     return nullptr;
1501061da546Spatrick }
1502061da546Spatrick 
GetDynamicArrayInfoForUID(lldb::user_id_t type_uid,const lldb_private::ExecutionContext * exe_ctx)1503*f6aab3d8Srobert std::optional<SymbolFile::ArrayInfo> SymbolFileDWARF::GetDynamicArrayInfoForUID(
1504061da546Spatrick     lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) {
1505061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1506061da546Spatrick   if (DWARFDIE type_die = GetDIE(type_uid))
1507061da546Spatrick     return DWARFASTParser::ParseChildArrayInfo(type_die, exe_ctx);
1508061da546Spatrick   else
1509*f6aab3d8Srobert     return std::nullopt;
1510061da546Spatrick }
1511061da546Spatrick 
ResolveTypeUID(const DIERef & die_ref)1512061da546Spatrick Type *SymbolFileDWARF::ResolveTypeUID(const DIERef &die_ref) {
1513061da546Spatrick   return ResolveType(GetDIE(die_ref), true);
1514061da546Spatrick }
1515061da546Spatrick 
ResolveTypeUID(const DWARFDIE & die,bool assert_not_being_parsed)1516061da546Spatrick Type *SymbolFileDWARF::ResolveTypeUID(const DWARFDIE &die,
1517061da546Spatrick                                       bool assert_not_being_parsed) {
1518061da546Spatrick   if (die) {
1519*f6aab3d8Srobert     Log *log = GetLog(DWARFLog::DebugInfo);
1520061da546Spatrick     if (log)
1521061da546Spatrick       GetObjectFile()->GetModule()->LogMessage(
1522*f6aab3d8Srobert           log, "SymbolFileDWARF::ResolveTypeUID (die = {0:x16}) {1} '{2}'",
1523061da546Spatrick           die.GetOffset(), die.GetTagAsCString(), die.GetName());
1524061da546Spatrick 
1525061da546Spatrick     // We might be coming in in the middle of a type tree (a class within a
1526061da546Spatrick     // class, an enum within a class), so parse any needed parent DIEs before
1527061da546Spatrick     // we get to this one...
1528061da546Spatrick     DWARFDIE decl_ctx_die = GetDeclContextDIEContainingDIE(die);
1529061da546Spatrick     if (decl_ctx_die) {
1530061da546Spatrick       if (log) {
1531061da546Spatrick         switch (decl_ctx_die.Tag()) {
1532061da546Spatrick         case DW_TAG_structure_type:
1533061da546Spatrick         case DW_TAG_union_type:
1534061da546Spatrick         case DW_TAG_class_type: {
1535061da546Spatrick           // Get the type, which could be a forward declaration
1536061da546Spatrick           if (log)
1537061da546Spatrick             GetObjectFile()->GetModule()->LogMessage(
1538061da546Spatrick                 log,
1539*f6aab3d8Srobert                 "SymbolFileDWARF::ResolveTypeUID (die = {0:x16}) "
1540*f6aab3d8Srobert                 "{1} '{2}' "
1541*f6aab3d8Srobert                 "resolve parent forward type for {3:x16})",
1542061da546Spatrick                 die.GetOffset(), die.GetTagAsCString(), die.GetName(),
1543061da546Spatrick                 decl_ctx_die.GetOffset());
1544061da546Spatrick         } break;
1545061da546Spatrick 
1546061da546Spatrick         default:
1547061da546Spatrick           break;
1548061da546Spatrick         }
1549061da546Spatrick       }
1550061da546Spatrick     }
1551061da546Spatrick     return ResolveType(die);
1552061da546Spatrick   }
1553061da546Spatrick   return nullptr;
1554061da546Spatrick }
1555061da546Spatrick 
1556061da546Spatrick // This function is used when SymbolFileDWARFDebugMap owns a bunch of
1557061da546Spatrick // SymbolFileDWARF objects to detect if this DWARF file is the one that can
1558061da546Spatrick // resolve a compiler_type.
HasForwardDeclForClangType(const CompilerType & compiler_type)1559061da546Spatrick bool SymbolFileDWARF::HasForwardDeclForClangType(
1560061da546Spatrick     const CompilerType &compiler_type) {
1561061da546Spatrick   CompilerType compiler_type_no_qualifiers =
1562061da546Spatrick       ClangUtil::RemoveFastQualifiers(compiler_type);
1563061da546Spatrick   if (GetForwardDeclClangTypeToDie().count(
1564061da546Spatrick           compiler_type_no_qualifiers.GetOpaqueQualType())) {
1565061da546Spatrick     return true;
1566061da546Spatrick   }
1567*f6aab3d8Srobert   auto type_system = compiler_type.GetTypeSystem();
1568*f6aab3d8Srobert   auto clang_type_system = type_system.dyn_cast_or_null<TypeSystemClang>();
1569061da546Spatrick   if (!clang_type_system)
1570061da546Spatrick     return false;
1571061da546Spatrick   DWARFASTParserClang *ast_parser =
1572061da546Spatrick       static_cast<DWARFASTParserClang *>(clang_type_system->GetDWARFParser());
1573061da546Spatrick   return ast_parser->GetClangASTImporter().CanImport(compiler_type);
1574061da546Spatrick }
1575061da546Spatrick 
CompleteType(CompilerType & compiler_type)1576061da546Spatrick bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) {
1577061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1578*f6aab3d8Srobert   auto clang_type_system =
1579*f6aab3d8Srobert       compiler_type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>();
1580061da546Spatrick   if (clang_type_system) {
1581061da546Spatrick     DWARFASTParserClang *ast_parser =
1582061da546Spatrick         static_cast<DWARFASTParserClang *>(clang_type_system->GetDWARFParser());
1583061da546Spatrick     if (ast_parser &&
1584061da546Spatrick         ast_parser->GetClangASTImporter().CanImport(compiler_type))
1585061da546Spatrick       return ast_parser->GetClangASTImporter().CompleteType(compiler_type);
1586061da546Spatrick   }
1587061da546Spatrick 
1588061da546Spatrick   // We have a struct/union/class/enum that needs to be fully resolved.
1589061da546Spatrick   CompilerType compiler_type_no_qualifiers =
1590061da546Spatrick       ClangUtil::RemoveFastQualifiers(compiler_type);
1591061da546Spatrick   auto die_it = GetForwardDeclClangTypeToDie().find(
1592061da546Spatrick       compiler_type_no_qualifiers.GetOpaqueQualType());
1593061da546Spatrick   if (die_it == GetForwardDeclClangTypeToDie().end()) {
1594061da546Spatrick     // We have already resolved this type...
1595061da546Spatrick     return true;
1596061da546Spatrick   }
1597061da546Spatrick 
1598061da546Spatrick   DWARFDIE dwarf_die = GetDIE(die_it->getSecond());
1599061da546Spatrick   if (dwarf_die) {
1600061da546Spatrick     // Once we start resolving this type, remove it from the forward
1601061da546Spatrick     // declaration map in case anyone child members or other types require this
1602061da546Spatrick     // type to get resolved. The type will get resolved when all of the calls
1603061da546Spatrick     // to SymbolFileDWARF::ResolveClangOpaqueTypeDefinition are done.
1604061da546Spatrick     GetForwardDeclClangTypeToDie().erase(die_it);
1605061da546Spatrick 
1606061da546Spatrick     Type *type = GetDIEToType().lookup(dwarf_die.GetDIE());
1607061da546Spatrick 
1608*f6aab3d8Srobert     Log *log = GetLog(DWARFLog::DebugInfo | DWARFLog::TypeCompletion);
1609061da546Spatrick     if (log)
1610061da546Spatrick       GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
1611*f6aab3d8Srobert           log, "{0:x8}: {1} '{2}' resolving forward declaration...",
1612061da546Spatrick           dwarf_die.GetID(), dwarf_die.GetTagAsCString(),
1613061da546Spatrick           type->GetName().AsCString());
1614061da546Spatrick     assert(compiler_type);
1615dda28197Spatrick     if (DWARFASTParser *dwarf_ast = GetDWARFParser(*dwarf_die.GetCU()))
1616061da546Spatrick       return dwarf_ast->CompleteTypeFromDWARF(dwarf_die, type, compiler_type);
1617061da546Spatrick   }
1618061da546Spatrick   return false;
1619061da546Spatrick }
1620061da546Spatrick 
ResolveType(const DWARFDIE & die,bool assert_not_being_parsed,bool resolve_function_context)1621061da546Spatrick Type *SymbolFileDWARF::ResolveType(const DWARFDIE &die,
1622061da546Spatrick                                    bool assert_not_being_parsed,
1623061da546Spatrick                                    bool resolve_function_context) {
1624061da546Spatrick   if (die) {
1625061da546Spatrick     Type *type = GetTypeForDIE(die, resolve_function_context).get();
1626061da546Spatrick 
1627061da546Spatrick     if (assert_not_being_parsed) {
1628061da546Spatrick       if (type != DIE_IS_BEING_PARSED)
1629061da546Spatrick         return type;
1630061da546Spatrick 
1631061da546Spatrick       GetObjectFile()->GetModule()->ReportError(
1632*f6aab3d8Srobert           "Parsing a die that is being parsed die: {0:x16}: {1} {2}",
1633061da546Spatrick           die.GetOffset(), die.GetTagAsCString(), die.GetName());
1634061da546Spatrick 
1635061da546Spatrick     } else
1636061da546Spatrick       return type;
1637061da546Spatrick   }
1638061da546Spatrick   return nullptr;
1639061da546Spatrick }
1640061da546Spatrick 
1641061da546Spatrick CompileUnit *
GetCompUnitForDWARFCompUnit(DWARFCompileUnit & dwarf_cu)1642061da546Spatrick SymbolFileDWARF::GetCompUnitForDWARFCompUnit(DWARFCompileUnit &dwarf_cu) {
1643dda28197Spatrick   if (dwarf_cu.IsDWOUnit()) {
1644dda28197Spatrick     DWARFCompileUnit *non_dwo_cu =
1645dda28197Spatrick         static_cast<DWARFCompileUnit *>(dwarf_cu.GetUserData());
1646dda28197Spatrick     assert(non_dwo_cu);
1647dda28197Spatrick     return non_dwo_cu->GetSymbolFileDWARF().GetCompUnitForDWARFCompUnit(
1648dda28197Spatrick         *non_dwo_cu);
1649dda28197Spatrick   }
1650061da546Spatrick   // Check if the symbol vendor already knows about this compile unit?
1651061da546Spatrick   if (dwarf_cu.GetUserData() == nullptr) {
1652061da546Spatrick     // The symbol vendor doesn't know about this compile unit, we need to parse
1653061da546Spatrick     // and add it to the symbol vendor object.
1654061da546Spatrick     return ParseCompileUnit(dwarf_cu).get();
1655061da546Spatrick   }
1656dda28197Spatrick   return static_cast<CompileUnit *>(dwarf_cu.GetUserData());
1657061da546Spatrick }
1658061da546Spatrick 
GetObjCMethods(ConstString class_name,llvm::function_ref<bool (DWARFDIE die)> callback)1659dda28197Spatrick void SymbolFileDWARF::GetObjCMethods(
1660dda28197Spatrick     ConstString class_name, llvm::function_ref<bool(DWARFDIE die)> callback) {
1661dda28197Spatrick   m_index->GetObjCMethods(class_name, callback);
1662061da546Spatrick }
1663061da546Spatrick 
GetFunction(const DWARFDIE & die,SymbolContext & sc)1664061da546Spatrick bool SymbolFileDWARF::GetFunction(const DWARFDIE &die, SymbolContext &sc) {
1665061da546Spatrick   sc.Clear(false);
1666061da546Spatrick 
1667061da546Spatrick   if (die && llvm::isa<DWARFCompileUnit>(die.GetCU())) {
1668061da546Spatrick     // Check if the symbol vendor already knows about this compile unit?
1669061da546Spatrick     sc.comp_unit =
1670061da546Spatrick         GetCompUnitForDWARFCompUnit(llvm::cast<DWARFCompileUnit>(*die.GetCU()));
1671061da546Spatrick 
1672061da546Spatrick     sc.function = sc.comp_unit->FindFunctionByUID(die.GetID()).get();
1673061da546Spatrick     if (sc.function == nullptr)
1674061da546Spatrick       sc.function = ParseFunction(*sc.comp_unit, die);
1675061da546Spatrick 
1676061da546Spatrick     if (sc.function) {
1677061da546Spatrick       sc.module_sp = sc.function->CalculateSymbolContextModule();
1678061da546Spatrick       return true;
1679061da546Spatrick     }
1680061da546Spatrick   }
1681061da546Spatrick 
1682061da546Spatrick   return false;
1683061da546Spatrick }
1684061da546Spatrick 
GetExternalModule(ConstString name)1685061da546Spatrick lldb::ModuleSP SymbolFileDWARF::GetExternalModule(ConstString name) {
1686061da546Spatrick   UpdateExternalModuleListIfNeeded();
1687061da546Spatrick   const auto &pos = m_external_type_modules.find(name);
1688061da546Spatrick   if (pos != m_external_type_modules.end())
1689061da546Spatrick     return pos->second;
1690061da546Spatrick   else
1691061da546Spatrick     return lldb::ModuleSP();
1692061da546Spatrick }
1693061da546Spatrick 
1694061da546Spatrick DWARFDIE
GetDIE(const DIERef & die_ref)1695061da546Spatrick SymbolFileDWARF::GetDIE(const DIERef &die_ref) {
1696061da546Spatrick   if (die_ref.dwo_num()) {
1697dda28197Spatrick     SymbolFileDWARF *dwarf = *die_ref.dwo_num() == 0x3fffffff
1698dda28197Spatrick                                  ? m_dwp_symfile.get()
1699dda28197Spatrick                                  : this->DebugInfo()
1700dda28197Spatrick                                        .GetUnitAtIndex(*die_ref.dwo_num())
1701dda28197Spatrick                                        ->GetDwoSymbolFile();
1702dda28197Spatrick     return dwarf->DebugInfo().GetDIE(die_ref);
1703061da546Spatrick   }
1704061da546Spatrick 
1705dda28197Spatrick   return DebugInfo().GetDIE(die_ref);
1706061da546Spatrick }
1707061da546Spatrick 
1708061da546Spatrick /// Return the DW_AT_(GNU_)dwo_id.
GetDWOId(DWARFCompileUnit & dwarf_cu,const DWARFDebugInfoEntry & cu_die)1709*f6aab3d8Srobert static std::optional<uint64_t> GetDWOId(DWARFCompileUnit &dwarf_cu,
1710061da546Spatrick                                         const DWARFDebugInfoEntry &cu_die) {
1711*f6aab3d8Srobert   std::optional<uint64_t> dwo_id =
1712*f6aab3d8Srobert       cu_die.GetAttributeValueAsOptionalUnsigned(&dwarf_cu, DW_AT_GNU_dwo_id);
1713*f6aab3d8Srobert   if (dwo_id)
1714061da546Spatrick     return dwo_id;
1715*f6aab3d8Srobert   return cu_die.GetAttributeValueAsOptionalUnsigned(&dwarf_cu, DW_AT_dwo_id);
1716061da546Spatrick }
1717061da546Spatrick 
GetDWOId()1718*f6aab3d8Srobert std::optional<uint64_t> SymbolFileDWARF::GetDWOId() {
1719061da546Spatrick   if (GetNumCompileUnits() == 1) {
1720061da546Spatrick     if (auto comp_unit = GetCompileUnitAtIndex(0))
1721be691f3bSpatrick       if (DWARFCompileUnit *cu = GetDWARFCompileUnit(comp_unit.get()))
1722061da546Spatrick         if (DWARFDebugInfoEntry *cu_die = cu->DIE().GetDIE())
1723*f6aab3d8Srobert           return ::GetDWOId(*cu, *cu_die);
1724061da546Spatrick   }
1725061da546Spatrick   return {};
1726061da546Spatrick }
1727061da546Spatrick 
1728dda28197Spatrick std::shared_ptr<SymbolFileDWARFDwo>
GetDwoSymbolFileForCompileUnit(DWARFUnit & unit,const DWARFDebugInfoEntry & cu_die)1729061da546Spatrick SymbolFileDWARF::GetDwoSymbolFileForCompileUnit(
1730061da546Spatrick     DWARFUnit &unit, const DWARFDebugInfoEntry &cu_die) {
1731061da546Spatrick   // If this is a Darwin-style debug map (non-.dSYM) symbol file,
1732061da546Spatrick   // never attempt to load ELF-style DWO files since the -gmodules
1733*f6aab3d8Srobert   // support uses the same DWO mechanism to specify full debug info
1734061da546Spatrick   // files for modules. This is handled in
1735061da546Spatrick   // UpdateExternalModuleListIfNeeded().
1736061da546Spatrick   if (GetDebugMapSymfile())
1737061da546Spatrick     return nullptr;
1738061da546Spatrick 
1739061da546Spatrick   DWARFCompileUnit *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(&unit);
1740*f6aab3d8Srobert   // Only compile units can be split into two parts and we should only
1741*f6aab3d8Srobert   // look for a DWO file if there is a valid DWO ID.
1742*f6aab3d8Srobert   if (!dwarf_cu || !dwarf_cu->GetDWOId().has_value())
1743061da546Spatrick     return nullptr;
1744061da546Spatrick 
1745061da546Spatrick   const char *dwo_name = GetDWOName(*dwarf_cu, cu_die);
1746*f6aab3d8Srobert   if (!dwo_name) {
1747*f6aab3d8Srobert     unit.SetDwoError(Status::createWithFormat(
1748*f6aab3d8Srobert         "missing DWO name in skeleton DIE {0:x16}", cu_die.GetOffset()));
1749061da546Spatrick     return nullptr;
1750*f6aab3d8Srobert   }
1751061da546Spatrick 
1752dda28197Spatrick   if (std::shared_ptr<SymbolFileDWARFDwo> dwp_sp = GetDwpSymbolFile())
1753dda28197Spatrick     return dwp_sp;
1754061da546Spatrick 
1755*f6aab3d8Srobert   const char *comp_dir = nullptr;
1756061da546Spatrick   FileSpec dwo_file(dwo_name);
1757061da546Spatrick   FileSystem::Instance().Resolve(dwo_file);
1758061da546Spatrick   if (dwo_file.IsRelative()) {
1759*f6aab3d8Srobert     comp_dir = cu_die.GetAttributeValueAsString(dwarf_cu, DW_AT_comp_dir,
1760*f6aab3d8Srobert                                                 nullptr);
1761*f6aab3d8Srobert     if (!comp_dir) {
1762*f6aab3d8Srobert       unit.SetDwoError(Status::createWithFormat(
1763*f6aab3d8Srobert           "unable to locate relative .dwo debug file \"{0}\" for "
1764*f6aab3d8Srobert           "skeleton DIE {1:x16} without valid DW_AT_comp_dir "
1765*f6aab3d8Srobert           "attribute",
1766*f6aab3d8Srobert           dwo_name, cu_die.GetOffset()));
1767061da546Spatrick       return nullptr;
1768*f6aab3d8Srobert     }
1769061da546Spatrick 
1770061da546Spatrick     dwo_file.SetFile(comp_dir, FileSpec::Style::native);
1771be691f3bSpatrick     if (dwo_file.IsRelative()) {
1772be691f3bSpatrick       // if DW_AT_comp_dir is relative, it should be relative to the location
1773be691f3bSpatrick       // of the executable, not to the location from which the debugger was
1774be691f3bSpatrick       // launched.
1775be691f3bSpatrick       dwo_file.PrependPathComponent(
1776be691f3bSpatrick           m_objfile_sp->GetFileSpec().GetDirectory().GetStringRef());
1777be691f3bSpatrick     }
1778061da546Spatrick     FileSystem::Instance().Resolve(dwo_file);
1779061da546Spatrick     dwo_file.AppendPathComponent(dwo_name);
1780061da546Spatrick   }
1781061da546Spatrick 
1782*f6aab3d8Srobert   if (!FileSystem::Instance().Exists(dwo_file)) {
1783*f6aab3d8Srobert     unit.SetDwoError(Status::createWithFormat(
1784*f6aab3d8Srobert         "unable to locate .dwo debug file \"{0}\" for skeleton DIE "
1785*f6aab3d8Srobert         "{1:x16}",
1786*f6aab3d8Srobert         dwo_file.GetPath().c_str(), cu_die.GetOffset()));
1787*f6aab3d8Srobert 
1788*f6aab3d8Srobert     if (m_dwo_warning_issued.test_and_set(std::memory_order_relaxed) == false) {
1789*f6aab3d8Srobert       GetObjectFile()->GetModule()->ReportWarning(
1790*f6aab3d8Srobert           "unable to locate separate debug file (dwo, dwp). Debugging will be "
1791*f6aab3d8Srobert           "degraded.");
1792*f6aab3d8Srobert     }
1793061da546Spatrick     return nullptr;
1794*f6aab3d8Srobert   }
1795061da546Spatrick 
1796061da546Spatrick   const lldb::offset_t file_offset = 0;
1797061da546Spatrick   DataBufferSP dwo_file_data_sp;
1798061da546Spatrick   lldb::offset_t dwo_file_data_offset = 0;
1799061da546Spatrick   ObjectFileSP dwo_obj_file = ObjectFile::FindPlugin(
1800061da546Spatrick       GetObjectFile()->GetModule(), &dwo_file, file_offset,
1801061da546Spatrick       FileSystem::Instance().GetByteSize(dwo_file), dwo_file_data_sp,
1802061da546Spatrick       dwo_file_data_offset);
1803*f6aab3d8Srobert   if (dwo_obj_file == nullptr) {
1804*f6aab3d8Srobert     unit.SetDwoError(Status::createWithFormat(
1805*f6aab3d8Srobert         "unable to load object file for .dwo debug file \"{0}\" for "
1806*f6aab3d8Srobert         "unit DIE {1:x16}",
1807*f6aab3d8Srobert         dwo_name, cu_die.GetOffset()));
1808061da546Spatrick     return nullptr;
1809*f6aab3d8Srobert   }
1810061da546Spatrick 
1811dda28197Spatrick   return std::make_shared<SymbolFileDWARFDwo>(*this, dwo_obj_file,
1812dda28197Spatrick                                               dwarf_cu->GetID());
1813061da546Spatrick }
1814061da546Spatrick 
UpdateExternalModuleListIfNeeded()1815061da546Spatrick void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() {
1816061da546Spatrick   if (m_fetched_external_modules)
1817061da546Spatrick     return;
1818061da546Spatrick   m_fetched_external_modules = true;
1819dda28197Spatrick   DWARFDebugInfo &debug_info = DebugInfo();
1820061da546Spatrick 
1821061da546Spatrick   // Follow DWO skeleton unit breadcrumbs.
1822061da546Spatrick   const uint32_t num_compile_units = GetNumCompileUnits();
1823061da546Spatrick   for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
1824061da546Spatrick     auto *dwarf_cu =
1825dda28197Spatrick         llvm::dyn_cast<DWARFCompileUnit>(debug_info.GetUnitAtIndex(cu_idx));
1826061da546Spatrick     if (!dwarf_cu)
1827061da546Spatrick       continue;
1828061da546Spatrick 
1829061da546Spatrick     const DWARFBaseDIE die = dwarf_cu->GetUnitDIEOnly();
1830061da546Spatrick     if (!die || die.HasChildren() || !die.GetDIE())
1831061da546Spatrick       continue;
1832061da546Spatrick 
1833061da546Spatrick     const char *name = die.GetAttributeValueAsString(DW_AT_name, nullptr);
1834061da546Spatrick     if (!name)
1835061da546Spatrick       continue;
1836061da546Spatrick 
1837061da546Spatrick     ConstString const_name(name);
1838061da546Spatrick     ModuleSP &module_sp = m_external_type_modules[const_name];
1839061da546Spatrick     if (module_sp)
1840061da546Spatrick       continue;
1841061da546Spatrick 
1842061da546Spatrick     const char *dwo_path = GetDWOName(*dwarf_cu, *die.GetDIE());
1843061da546Spatrick     if (!dwo_path)
1844061da546Spatrick       continue;
1845061da546Spatrick 
1846061da546Spatrick     ModuleSpec dwo_module_spec;
1847061da546Spatrick     dwo_module_spec.GetFileSpec().SetFile(dwo_path, FileSpec::Style::native);
1848061da546Spatrick     if (dwo_module_spec.GetFileSpec().IsRelative()) {
1849061da546Spatrick       const char *comp_dir =
1850061da546Spatrick           die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr);
1851061da546Spatrick       if (comp_dir) {
1852061da546Spatrick         dwo_module_spec.GetFileSpec().SetFile(comp_dir,
1853061da546Spatrick                                               FileSpec::Style::native);
1854061da546Spatrick         FileSystem::Instance().Resolve(dwo_module_spec.GetFileSpec());
1855061da546Spatrick         dwo_module_spec.GetFileSpec().AppendPathComponent(dwo_path);
1856061da546Spatrick       }
1857061da546Spatrick     }
1858061da546Spatrick     dwo_module_spec.GetArchitecture() =
1859061da546Spatrick         m_objfile_sp->GetModule()->GetArchitecture();
1860061da546Spatrick 
1861061da546Spatrick     // When LLDB loads "external" modules it looks at the presence of
1862061da546Spatrick     // DW_AT_dwo_name. However, when the already created module
1863061da546Spatrick     // (corresponding to .dwo itself) is being processed, it will see
1864061da546Spatrick     // the presence of DW_AT_dwo_name (which contains the name of dwo
1865061da546Spatrick     // file) and will try to call ModuleList::GetSharedModule
1866061da546Spatrick     // again. In some cases (i.e., for empty files) Clang 4.0
1867061da546Spatrick     // generates a *.dwo file which has DW_AT_dwo_name, but no
1868061da546Spatrick     // DW_AT_comp_dir. In this case the method
1869061da546Spatrick     // ModuleList::GetSharedModule will fail and the warning will be
1870061da546Spatrick     // printed. However, as one can notice in this case we don't
1871061da546Spatrick     // actually need to try to load the already loaded module
1872061da546Spatrick     // (corresponding to .dwo) so we simply skip it.
1873061da546Spatrick     if (m_objfile_sp->GetFileSpec().GetFileNameExtension() == ".dwo" &&
1874061da546Spatrick         llvm::StringRef(m_objfile_sp->GetFileSpec().GetPath())
1875061da546Spatrick             .endswith(dwo_module_spec.GetFileSpec().GetPath())) {
1876061da546Spatrick       continue;
1877061da546Spatrick     }
1878061da546Spatrick 
1879061da546Spatrick     Status error = ModuleList::GetSharedModule(dwo_module_spec, module_sp,
1880061da546Spatrick                                                nullptr, nullptr, nullptr);
1881061da546Spatrick     if (!module_sp) {
1882061da546Spatrick       GetObjectFile()->GetModule()->ReportWarning(
1883*f6aab3d8Srobert           "{0:x16}: unable to locate module needed for external types: "
1884*f6aab3d8Srobert           "{1}\nerror: {2}\nDebugging will be degraded due to missing "
1885061da546Spatrick           "types. Rebuilding the project will regenerate the needed "
1886061da546Spatrick           "module files.",
1887061da546Spatrick           die.GetOffset(), dwo_module_spec.GetFileSpec().GetPath().c_str(),
1888061da546Spatrick           error.AsCString("unknown error"));
1889061da546Spatrick       continue;
1890061da546Spatrick     }
1891061da546Spatrick 
1892061da546Spatrick     // Verify the DWO hash.
1893061da546Spatrick     // FIXME: Technically "0" is a valid hash.
1894*f6aab3d8Srobert     std::optional<uint64_t> dwo_id = ::GetDWOId(*dwarf_cu, *die.GetDIE());
1895061da546Spatrick     if (!dwo_id)
1896061da546Spatrick       continue;
1897061da546Spatrick 
1898061da546Spatrick     auto *dwo_symfile =
1899061da546Spatrick         llvm::dyn_cast_or_null<SymbolFileDWARF>(module_sp->GetSymbolFile());
1900061da546Spatrick     if (!dwo_symfile)
1901061da546Spatrick       continue;
1902*f6aab3d8Srobert     std::optional<uint64_t> dwo_dwo_id = dwo_symfile->GetDWOId();
1903061da546Spatrick     if (!dwo_dwo_id)
1904061da546Spatrick       continue;
1905061da546Spatrick 
1906061da546Spatrick     if (dwo_id != dwo_dwo_id) {
1907061da546Spatrick       GetObjectFile()->GetModule()->ReportWarning(
1908*f6aab3d8Srobert           "{0:x16}: Module {1} is out-of-date (hash mismatch). Type "
1909*f6aab3d8Srobert           "information "
1910061da546Spatrick           "from this module may be incomplete or inconsistent with the rest of "
1911061da546Spatrick           "the program. Rebuilding the project will regenerate the needed "
1912061da546Spatrick           "module files.",
1913061da546Spatrick           die.GetOffset(), dwo_module_spec.GetFileSpec().GetPath().c_str());
1914061da546Spatrick     }
1915061da546Spatrick   }
1916061da546Spatrick }
1917061da546Spatrick 
GetGlobalAranges()1918061da546Spatrick SymbolFileDWARF::GlobalVariableMap &SymbolFileDWARF::GetGlobalAranges() {
1919061da546Spatrick   if (!m_global_aranges_up) {
1920dda28197Spatrick     m_global_aranges_up = std::make_unique<GlobalVariableMap>();
1921061da546Spatrick 
1922061da546Spatrick     ModuleSP module_sp = GetObjectFile()->GetModule();
1923061da546Spatrick     if (module_sp) {
1924061da546Spatrick       const size_t num_cus = module_sp->GetNumCompileUnits();
1925061da546Spatrick       for (size_t i = 0; i < num_cus; ++i) {
1926061da546Spatrick         CompUnitSP cu_sp = module_sp->GetCompileUnitAtIndex(i);
1927061da546Spatrick         if (cu_sp) {
1928061da546Spatrick           VariableListSP globals_sp = cu_sp->GetVariableList(true);
1929061da546Spatrick           if (globals_sp) {
1930061da546Spatrick             const size_t num_globals = globals_sp->GetSize();
1931061da546Spatrick             for (size_t g = 0; g < num_globals; ++g) {
1932061da546Spatrick               VariableSP var_sp = globals_sp->GetVariableAtIndex(g);
1933061da546Spatrick               if (var_sp && !var_sp->GetLocationIsConstantValueData()) {
1934*f6aab3d8Srobert                 const DWARFExpressionList &location =
1935*f6aab3d8Srobert                     var_sp->LocationExpressionList();
1936061da546Spatrick                 Value location_result;
1937061da546Spatrick                 Status error;
1938*f6aab3d8Srobert                 ExecutionContext exe_ctx;
1939*f6aab3d8Srobert                 if (location.Evaluate(&exe_ctx, nullptr, LLDB_INVALID_ADDRESS,
1940*f6aab3d8Srobert                                       nullptr, nullptr, location_result,
1941*f6aab3d8Srobert                                       &error)) {
1942061da546Spatrick                   if (location_result.GetValueType() ==
1943be691f3bSpatrick                       Value::ValueType::FileAddress) {
1944061da546Spatrick                     lldb::addr_t file_addr =
1945061da546Spatrick                         location_result.GetScalar().ULongLong();
1946061da546Spatrick                     lldb::addr_t byte_size = 1;
1947061da546Spatrick                     if (var_sp->GetType())
1948061da546Spatrick                       byte_size =
1949*f6aab3d8Srobert                           var_sp->GetType()->GetByteSize(nullptr).value_or(0);
1950061da546Spatrick                     m_global_aranges_up->Append(GlobalVariableMap::Entry(
1951061da546Spatrick                         file_addr, byte_size, var_sp.get()));
1952061da546Spatrick                   }
1953061da546Spatrick                 }
1954061da546Spatrick               }
1955061da546Spatrick             }
1956061da546Spatrick           }
1957061da546Spatrick         }
1958061da546Spatrick       }
1959061da546Spatrick     }
1960061da546Spatrick     m_global_aranges_up->Sort();
1961061da546Spatrick   }
1962061da546Spatrick   return *m_global_aranges_up;
1963061da546Spatrick }
1964061da546Spatrick 
ResolveFunctionAndBlock(lldb::addr_t file_vm_addr,bool lookup_block,SymbolContext & sc)1965dda28197Spatrick void SymbolFileDWARF::ResolveFunctionAndBlock(lldb::addr_t file_vm_addr,
1966dda28197Spatrick                                               bool lookup_block,
1967dda28197Spatrick                                               SymbolContext &sc) {
1968dda28197Spatrick   assert(sc.comp_unit);
1969be691f3bSpatrick   DWARFCompileUnit &cu =
1970be691f3bSpatrick       GetDWARFCompileUnit(sc.comp_unit)->GetNonSkeletonUnit();
1971dda28197Spatrick   DWARFDIE function_die = cu.LookupAddress(file_vm_addr);
1972dda28197Spatrick   DWARFDIE block_die;
1973dda28197Spatrick   if (function_die) {
1974dda28197Spatrick     sc.function = sc.comp_unit->FindFunctionByUID(function_die.GetID()).get();
1975dda28197Spatrick     if (sc.function == nullptr)
1976dda28197Spatrick       sc.function = ParseFunction(*sc.comp_unit, function_die);
1977dda28197Spatrick 
1978dda28197Spatrick     if (sc.function && lookup_block)
1979dda28197Spatrick       block_die = function_die.LookupDeepestBlock(file_vm_addr);
1980dda28197Spatrick   }
1981dda28197Spatrick 
1982dda28197Spatrick   if (!sc.function || !lookup_block)
1983dda28197Spatrick     return;
1984dda28197Spatrick 
1985dda28197Spatrick   Block &block = sc.function->GetBlock(true);
1986dda28197Spatrick   if (block_die)
1987dda28197Spatrick     sc.block = block.FindBlockByID(block_die.GetID());
1988dda28197Spatrick   else
1989dda28197Spatrick     sc.block = block.FindBlockByID(function_die.GetID());
1990dda28197Spatrick }
1991dda28197Spatrick 
ResolveSymbolContext(const Address & so_addr,SymbolContextItem resolve_scope,SymbolContext & sc)1992061da546Spatrick uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr,
1993061da546Spatrick                                                SymbolContextItem resolve_scope,
1994061da546Spatrick                                                SymbolContext &sc) {
1995061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1996be691f3bSpatrick   LLDB_SCOPED_TIMERF("SymbolFileDWARF::"
1997061da546Spatrick                      "ResolveSymbolContext (so_addr = { "
1998061da546Spatrick                      "section = %p, offset = 0x%" PRIx64
1999061da546Spatrick                      " }, resolve_scope = 0x%8.8x)",
2000061da546Spatrick                      static_cast<void *>(so_addr.GetSection().get()),
2001061da546Spatrick                      so_addr.GetOffset(), resolve_scope);
2002061da546Spatrick   uint32_t resolved = 0;
2003061da546Spatrick   if (resolve_scope &
2004061da546Spatrick       (eSymbolContextCompUnit | eSymbolContextFunction | eSymbolContextBlock |
2005061da546Spatrick        eSymbolContextLineEntry | eSymbolContextVariable)) {
2006061da546Spatrick     lldb::addr_t file_vm_addr = so_addr.GetFileAddress();
2007061da546Spatrick 
2008dda28197Spatrick     DWARFDebugInfo &debug_info = DebugInfo();
2009be691f3bSpatrick     const DWARFDebugAranges &aranges = debug_info.GetCompileUnitAranges();
2010be691f3bSpatrick     const dw_offset_t cu_offset = aranges.FindAddress(file_vm_addr);
2011061da546Spatrick     if (cu_offset == DW_INVALID_OFFSET) {
2012dda28197Spatrick       // Global variables are not in the compile unit address ranges. The only
2013dda28197Spatrick       // way to currently find global variables is to iterate over the
2014dda28197Spatrick       // .debug_pubnames or the __apple_names table and find all items in there
2015dda28197Spatrick       // that point to DW_TAG_variable DIEs and then find the address that
2016dda28197Spatrick       // matches.
2017061da546Spatrick       if (resolve_scope & eSymbolContextVariable) {
2018061da546Spatrick         GlobalVariableMap &map = GetGlobalAranges();
2019061da546Spatrick         const GlobalVariableMap::Entry *entry =
2020061da546Spatrick             map.FindEntryThatContains(file_vm_addr);
2021061da546Spatrick         if (entry && entry->data) {
2022061da546Spatrick           Variable *variable = entry->data;
2023061da546Spatrick           SymbolContextScope *scc = variable->GetSymbolContextScope();
2024061da546Spatrick           if (scc) {
2025061da546Spatrick             scc->CalculateSymbolContext(&sc);
2026061da546Spatrick             sc.variable = variable;
2027061da546Spatrick           }
2028061da546Spatrick           return sc.GetResolvedMask();
2029061da546Spatrick         }
2030061da546Spatrick       }
2031061da546Spatrick     } else {
2032061da546Spatrick       uint32_t cu_idx = DW_INVALID_INDEX;
2033061da546Spatrick       if (auto *dwarf_cu = llvm::dyn_cast_or_null<DWARFCompileUnit>(
2034dda28197Spatrick               debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo, cu_offset,
2035dda28197Spatrick                                          &cu_idx))) {
2036061da546Spatrick         sc.comp_unit = GetCompUnitForDWARFCompUnit(*dwarf_cu);
2037061da546Spatrick         if (sc.comp_unit) {
2038061da546Spatrick           resolved |= eSymbolContextCompUnit;
2039061da546Spatrick 
2040061da546Spatrick           bool force_check_line_table = false;
2041dda28197Spatrick           if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock)) {
2042dda28197Spatrick             ResolveFunctionAndBlock(file_vm_addr,
2043dda28197Spatrick                                     resolve_scope & eSymbolContextBlock, sc);
2044dda28197Spatrick             if (sc.function)
2045dda28197Spatrick               resolved |= eSymbolContextFunction;
2046dda28197Spatrick             else {
2047dda28197Spatrick               // We might have had a compile unit that had discontiguous address
2048dda28197Spatrick               // ranges where the gaps are symbols that don't have any debug
2049dda28197Spatrick               // info. Discontiguous compile unit address ranges should only
2050dda28197Spatrick               // happen when there aren't other functions from other compile
2051dda28197Spatrick               // units in these gaps. This helps keep the size of the aranges
2052dda28197Spatrick               // down.
2053061da546Spatrick               force_check_line_table = true;
2054061da546Spatrick             }
2055061da546Spatrick             if (sc.block)
2056061da546Spatrick               resolved |= eSymbolContextBlock;
2057061da546Spatrick           }
2058061da546Spatrick 
2059061da546Spatrick           if ((resolve_scope & eSymbolContextLineEntry) ||
2060061da546Spatrick               force_check_line_table) {
2061061da546Spatrick             LineTable *line_table = sc.comp_unit->GetLineTable();
2062061da546Spatrick             if (line_table != nullptr) {
2063dda28197Spatrick               // And address that makes it into this function should be in terms
2064dda28197Spatrick               // of this debug file if there is no debug map, or it will be an
2065dda28197Spatrick               // address in the .o file which needs to be fixed up to be in
2066dda28197Spatrick               // terms of the debug map executable. Either way, calling
2067dda28197Spatrick               // FixupAddress() will work for us.
2068061da546Spatrick               Address exe_so_addr(so_addr);
2069061da546Spatrick               if (FixupAddress(exe_so_addr)) {
2070061da546Spatrick                 if (line_table->FindLineEntryByAddress(exe_so_addr,
2071061da546Spatrick                                                        sc.line_entry)) {
2072061da546Spatrick                   resolved |= eSymbolContextLineEntry;
2073061da546Spatrick                 }
2074061da546Spatrick               }
2075061da546Spatrick             }
2076061da546Spatrick           }
2077061da546Spatrick 
2078dda28197Spatrick           if (force_check_line_table && !(resolved & eSymbolContextLineEntry)) {
2079dda28197Spatrick             // We might have had a compile unit that had discontiguous address
2080dda28197Spatrick             // ranges where the gaps are symbols that don't have any debug info.
2081dda28197Spatrick             // Discontiguous compile unit address ranges should only happen when
2082dda28197Spatrick             // there aren't other functions from other compile units in these
2083dda28197Spatrick             // gaps. This helps keep the size of the aranges down.
2084061da546Spatrick             sc.comp_unit = nullptr;
2085061da546Spatrick             resolved &= ~eSymbolContextCompUnit;
2086061da546Spatrick           }
2087061da546Spatrick         } else {
2088061da546Spatrick           GetObjectFile()->GetModule()->ReportWarning(
2089*f6aab3d8Srobert               "{0:x16}: compile unit {1} failed to create a valid "
2090061da546Spatrick               "lldb_private::CompileUnit class.",
2091061da546Spatrick               cu_offset, cu_idx);
2092061da546Spatrick         }
2093061da546Spatrick       }
2094061da546Spatrick     }
2095061da546Spatrick   }
2096061da546Spatrick   return resolved;
2097061da546Spatrick }
2098061da546Spatrick 
ResolveSymbolContext(const SourceLocationSpec & src_location_spec,SymbolContextItem resolve_scope,SymbolContextList & sc_list)2099be691f3bSpatrick uint32_t SymbolFileDWARF::ResolveSymbolContext(
2100be691f3bSpatrick     const SourceLocationSpec &src_location_spec,
2101be691f3bSpatrick     SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
2102061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2103be691f3bSpatrick   const bool check_inlines = src_location_spec.GetCheckInlines();
2104061da546Spatrick   const uint32_t prev_size = sc_list.GetSize();
2105061da546Spatrick   if (resolve_scope & eSymbolContextCompUnit) {
2106061da546Spatrick     for (uint32_t cu_idx = 0, num_cus = GetNumCompileUnits(); cu_idx < num_cus;
2107061da546Spatrick          ++cu_idx) {
2108061da546Spatrick       CompileUnit *dc_cu = ParseCompileUnitAtIndex(cu_idx).get();
2109061da546Spatrick       if (!dc_cu)
2110061da546Spatrick         continue;
2111061da546Spatrick 
2112be691f3bSpatrick       bool file_spec_matches_cu_file_spec = FileSpec::Match(
2113be691f3bSpatrick           src_location_spec.GetFileSpec(), dc_cu->GetPrimaryFile());
2114061da546Spatrick       if (check_inlines || file_spec_matches_cu_file_spec) {
2115be691f3bSpatrick         dc_cu->ResolveSymbolContext(src_location_spec, resolve_scope, sc_list);
2116061da546Spatrick         if (!check_inlines)
2117061da546Spatrick           break;
2118061da546Spatrick       }
2119061da546Spatrick     }
2120061da546Spatrick   }
2121061da546Spatrick   return sc_list.GetSize() - prev_size;
2122061da546Spatrick }
2123061da546Spatrick 
PreloadSymbols()2124061da546Spatrick void SymbolFileDWARF::PreloadSymbols() {
2125*f6aab3d8Srobert   // Get the symbol table for the symbol file prior to taking the module lock
2126*f6aab3d8Srobert   // so that it is available without needing to take the module lock. The DWARF
2127*f6aab3d8Srobert   // indexing might end up needing to relocate items when DWARF sections are
2128*f6aab3d8Srobert   // loaded as they might end up getting the section contents which can call
2129*f6aab3d8Srobert   // ObjectFileELF::RelocateSection() which in turn will ask for the symbol
2130*f6aab3d8Srobert   // table and can cause deadlocks.
2131*f6aab3d8Srobert   GetSymtab();
2132061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2133061da546Spatrick   m_index->Preload();
2134061da546Spatrick }
2135061da546Spatrick 
GetModuleMutex() const2136061da546Spatrick std::recursive_mutex &SymbolFileDWARF::GetModuleMutex() const {
2137061da546Spatrick   lldb::ModuleSP module_sp(m_debug_map_module_wp.lock());
2138061da546Spatrick   if (module_sp)
2139061da546Spatrick     return module_sp->GetMutex();
2140061da546Spatrick   return GetObjectFile()->GetModule()->GetMutex();
2141061da546Spatrick }
2142061da546Spatrick 
DeclContextMatchesThisSymbolFile(const lldb_private::CompilerDeclContext & decl_ctx)2143061da546Spatrick bool SymbolFileDWARF::DeclContextMatchesThisSymbolFile(
2144dda28197Spatrick     const lldb_private::CompilerDeclContext &decl_ctx) {
2145dda28197Spatrick   if (!decl_ctx.IsValid()) {
2146061da546Spatrick     // Invalid namespace decl which means we aren't matching only things in
2147061da546Spatrick     // this symbol file, so return true to indicate it matches this symbol
2148061da546Spatrick     // file.
2149061da546Spatrick     return true;
2150061da546Spatrick   }
2151061da546Spatrick 
2152dda28197Spatrick   TypeSystem *decl_ctx_type_system = decl_ctx.GetTypeSystem();
2153061da546Spatrick   auto type_system_or_err = GetTypeSystemForLanguage(
2154061da546Spatrick       decl_ctx_type_system->GetMinimumLanguage(nullptr));
2155061da546Spatrick   if (auto err = type_system_or_err.takeError()) {
2156*f6aab3d8Srobert     LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
2157061da546Spatrick                    "Unable to match namespace decl using TypeSystem");
2158061da546Spatrick     return false;
2159061da546Spatrick   }
2160061da546Spatrick 
2161*f6aab3d8Srobert   if (decl_ctx_type_system == type_system_or_err->get())
2162061da546Spatrick     return true; // The type systems match, return true
2163061da546Spatrick 
2164061da546Spatrick   // The namespace AST was valid, and it does not match...
2165*f6aab3d8Srobert   Log *log = GetLog(DWARFLog::Lookups);
2166061da546Spatrick 
2167061da546Spatrick   if (log)
2168061da546Spatrick     GetObjectFile()->GetModule()->LogMessage(
2169061da546Spatrick         log, "Valid namespace does not match symbol file");
2170061da546Spatrick 
2171061da546Spatrick   return false;
2172061da546Spatrick }
2173061da546Spatrick 
FindGlobalVariables(ConstString name,const CompilerDeclContext & parent_decl_ctx,uint32_t max_matches,VariableList & variables)2174061da546Spatrick void SymbolFileDWARF::FindGlobalVariables(
2175dda28197Spatrick     ConstString name, const CompilerDeclContext &parent_decl_ctx,
2176061da546Spatrick     uint32_t max_matches, VariableList &variables) {
2177061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2178*f6aab3d8Srobert   Log *log = GetLog(DWARFLog::Lookups);
2179061da546Spatrick 
2180061da546Spatrick   if (log)
2181061da546Spatrick     GetObjectFile()->GetModule()->LogMessage(
2182061da546Spatrick         log,
2183*f6aab3d8Srobert         "SymbolFileDWARF::FindGlobalVariables (name=\"{0}\", "
2184*f6aab3d8Srobert         "parent_decl_ctx={1:p}, max_matches={2}, variables)",
2185dda28197Spatrick         name.GetCString(), static_cast<const void *>(&parent_decl_ctx),
2186061da546Spatrick         max_matches);
2187061da546Spatrick 
2188061da546Spatrick   if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
2189061da546Spatrick     return;
2190061da546Spatrick 
2191061da546Spatrick   // Remember how many variables are in the list before we search.
2192061da546Spatrick   const uint32_t original_size = variables.GetSize();
2193061da546Spatrick 
2194061da546Spatrick   llvm::StringRef basename;
2195061da546Spatrick   llvm::StringRef context;
2196*f6aab3d8Srobert   bool name_is_mangled = Mangled::GetManglingScheme(name.GetStringRef()) !=
2197*f6aab3d8Srobert                          Mangled::eManglingSchemeNone;
2198061da546Spatrick 
2199061da546Spatrick   if (!CPlusPlusLanguage::ExtractContextAndIdentifier(name.GetCString(),
2200061da546Spatrick                                                       context, basename))
2201061da546Spatrick     basename = name.GetStringRef();
2202061da546Spatrick 
2203061da546Spatrick   // Loop invariant: Variables up to this index have been checked for context
2204061da546Spatrick   // matches.
2205061da546Spatrick   uint32_t pruned_idx = original_size;
2206061da546Spatrick 
2207dda28197Spatrick   SymbolContext sc;
2208dda28197Spatrick   m_index->GetGlobalVariables(ConstString(basename), [&](DWARFDIE die) {
2209dda28197Spatrick     if (!sc.module_sp)
2210dda28197Spatrick       sc.module_sp = m_objfile_sp->GetModule();
2211dda28197Spatrick     assert(sc.module_sp);
2212061da546Spatrick 
2213dda28197Spatrick     if (die.Tag() != DW_TAG_variable)
2214dda28197Spatrick       return true;
2215061da546Spatrick 
2216061da546Spatrick     auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(die.GetCU());
2217061da546Spatrick     if (!dwarf_cu)
2218dda28197Spatrick       return true;
2219061da546Spatrick     sc.comp_unit = GetCompUnitForDWARFCompUnit(*dwarf_cu);
2220061da546Spatrick 
2221061da546Spatrick     if (parent_decl_ctx) {
2222dda28197Spatrick       if (DWARFASTParser *dwarf_ast = GetDWARFParser(*die.GetCU())) {
2223061da546Spatrick         CompilerDeclContext actual_parent_decl_ctx =
2224061da546Spatrick             dwarf_ast->GetDeclContextContainingUIDFromDWARF(die);
2225061da546Spatrick         if (!actual_parent_decl_ctx ||
2226dda28197Spatrick             actual_parent_decl_ctx != parent_decl_ctx)
2227dda28197Spatrick           return true;
2228061da546Spatrick       }
2229061da546Spatrick     }
2230061da546Spatrick 
2231*f6aab3d8Srobert     ParseAndAppendGlobalVariable(sc, die, variables);
2232061da546Spatrick     while (pruned_idx < variables.GetSize()) {
2233061da546Spatrick       VariableSP var_sp = variables.GetVariableAtIndex(pruned_idx);
2234061da546Spatrick       if (name_is_mangled ||
2235061da546Spatrick           var_sp->GetName().GetStringRef().contains(name.GetStringRef()))
2236061da546Spatrick         ++pruned_idx;
2237061da546Spatrick       else
2238061da546Spatrick         variables.RemoveVariableAtIndex(pruned_idx);
2239061da546Spatrick     }
2240061da546Spatrick 
2241dda28197Spatrick     return variables.GetSize() - original_size < max_matches;
2242dda28197Spatrick   });
2243061da546Spatrick 
2244061da546Spatrick   // Return the number of variable that were appended to the list
2245061da546Spatrick   const uint32_t num_matches = variables.GetSize() - original_size;
2246061da546Spatrick   if (log && num_matches > 0) {
2247061da546Spatrick     GetObjectFile()->GetModule()->LogMessage(
2248061da546Spatrick         log,
2249*f6aab3d8Srobert         "SymbolFileDWARF::FindGlobalVariables (name=\"{0}\", "
2250*f6aab3d8Srobert         "parent_decl_ctx={1:p}, max_matches={2}, variables) => {3}",
2251dda28197Spatrick         name.GetCString(), static_cast<const void *>(&parent_decl_ctx),
2252061da546Spatrick         max_matches, num_matches);
2253061da546Spatrick   }
2254061da546Spatrick }
2255061da546Spatrick 
FindGlobalVariables(const RegularExpression & regex,uint32_t max_matches,VariableList & variables)2256061da546Spatrick void SymbolFileDWARF::FindGlobalVariables(const RegularExpression &regex,
2257061da546Spatrick                                           uint32_t max_matches,
2258061da546Spatrick                                           VariableList &variables) {
2259061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2260*f6aab3d8Srobert   Log *log = GetLog(DWARFLog::Lookups);
2261061da546Spatrick 
2262061da546Spatrick   if (log) {
2263061da546Spatrick     GetObjectFile()->GetModule()->LogMessage(
2264061da546Spatrick         log,
2265*f6aab3d8Srobert         "SymbolFileDWARF::FindGlobalVariables (regex=\"{0}\", "
2266*f6aab3d8Srobert         "max_matches={1}, variables)",
2267061da546Spatrick         regex.GetText().str().c_str(), max_matches);
2268061da546Spatrick   }
2269061da546Spatrick 
2270061da546Spatrick   // Remember how many variables are in the list before we search.
2271061da546Spatrick   const uint32_t original_size = variables.GetSize();
2272061da546Spatrick 
2273061da546Spatrick   SymbolContext sc;
2274dda28197Spatrick   m_index->GetGlobalVariables(regex, [&](DWARFDIE die) {
2275dda28197Spatrick     if (!sc.module_sp)
2276061da546Spatrick       sc.module_sp = m_objfile_sp->GetModule();
2277061da546Spatrick     assert(sc.module_sp);
2278061da546Spatrick 
2279dda28197Spatrick     DWARFCompileUnit *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(die.GetCU());
2280061da546Spatrick     if (!dwarf_cu)
2281dda28197Spatrick       return true;
2282061da546Spatrick     sc.comp_unit = GetCompUnitForDWARFCompUnit(*dwarf_cu);
2283061da546Spatrick 
2284*f6aab3d8Srobert     ParseAndAppendGlobalVariable(sc, die, variables);
2285061da546Spatrick 
2286dda28197Spatrick     return variables.GetSize() - original_size < max_matches;
2287dda28197Spatrick   });
2288061da546Spatrick }
2289061da546Spatrick 
ResolveFunction(const DWARFDIE & orig_die,bool include_inlines,SymbolContextList & sc_list)2290061da546Spatrick bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die,
2291061da546Spatrick                                       bool include_inlines,
2292061da546Spatrick                                       SymbolContextList &sc_list) {
2293061da546Spatrick   SymbolContext sc;
2294061da546Spatrick 
2295061da546Spatrick   if (!orig_die)
2296061da546Spatrick     return false;
2297061da546Spatrick 
2298061da546Spatrick   // If we were passed a die that is not a function, just return false...
2299061da546Spatrick   if (!(orig_die.Tag() == DW_TAG_subprogram ||
2300061da546Spatrick         (include_inlines && orig_die.Tag() == DW_TAG_inlined_subroutine)))
2301061da546Spatrick     return false;
2302061da546Spatrick 
2303061da546Spatrick   DWARFDIE die = orig_die;
2304061da546Spatrick   DWARFDIE inlined_die;
2305061da546Spatrick   if (die.Tag() == DW_TAG_inlined_subroutine) {
2306061da546Spatrick     inlined_die = die;
2307061da546Spatrick 
2308061da546Spatrick     while (true) {
2309061da546Spatrick       die = die.GetParent();
2310061da546Spatrick 
2311061da546Spatrick       if (die) {
2312061da546Spatrick         if (die.Tag() == DW_TAG_subprogram)
2313061da546Spatrick           break;
2314061da546Spatrick       } else
2315061da546Spatrick         break;
2316061da546Spatrick     }
2317061da546Spatrick   }
2318061da546Spatrick   assert(die && die.Tag() == DW_TAG_subprogram);
2319061da546Spatrick   if (GetFunction(die, sc)) {
2320061da546Spatrick     Address addr;
2321061da546Spatrick     // Parse all blocks if needed
2322061da546Spatrick     if (inlined_die) {
2323061da546Spatrick       Block &function_block = sc.function->GetBlock(true);
2324061da546Spatrick       sc.block = function_block.FindBlockByID(inlined_die.GetID());
2325061da546Spatrick       if (sc.block == nullptr)
2326061da546Spatrick         sc.block = function_block.FindBlockByID(inlined_die.GetOffset());
2327061da546Spatrick       if (sc.block == nullptr || !sc.block->GetStartAddress(addr))
2328061da546Spatrick         addr.Clear();
2329061da546Spatrick     } else {
2330061da546Spatrick       sc.block = nullptr;
2331061da546Spatrick       addr = sc.function->GetAddressRange().GetBaseAddress();
2332061da546Spatrick     }
2333061da546Spatrick 
2334061da546Spatrick     sc_list.Append(sc);
2335061da546Spatrick     return true;
2336061da546Spatrick   }
2337061da546Spatrick 
2338061da546Spatrick   return false;
2339061da546Spatrick }
2340061da546Spatrick 
DIEInDeclContext(const CompilerDeclContext & decl_ctx,const DWARFDIE & die)2341dda28197Spatrick bool SymbolFileDWARF::DIEInDeclContext(const CompilerDeclContext &decl_ctx,
2342061da546Spatrick                                        const DWARFDIE &die) {
2343061da546Spatrick   // If we have no parent decl context to match this DIE matches, and if the
2344061da546Spatrick   // parent decl context isn't valid, we aren't trying to look for any
2345061da546Spatrick   // particular decl context so any die matches.
2346dda28197Spatrick   if (!decl_ctx.IsValid())
2347061da546Spatrick     return true;
2348061da546Spatrick 
2349061da546Spatrick   if (die) {
2350dda28197Spatrick     if (DWARFASTParser *dwarf_ast = GetDWARFParser(*die.GetCU())) {
2351dda28197Spatrick       if (CompilerDeclContext actual_decl_ctx =
2352dda28197Spatrick               dwarf_ast->GetDeclContextContainingUIDFromDWARF(die))
2353dda28197Spatrick         return decl_ctx.IsContainedInLookup(actual_decl_ctx);
2354061da546Spatrick     }
2355061da546Spatrick   }
2356061da546Spatrick   return false;
2357061da546Spatrick }
2358061da546Spatrick 
FindFunctions(const Module::LookupInfo & lookup_info,const CompilerDeclContext & parent_decl_ctx,bool include_inlines,SymbolContextList & sc_list)2359*f6aab3d8Srobert void SymbolFileDWARF::FindFunctions(const Module::LookupInfo &lookup_info,
2360dda28197Spatrick                                     const CompilerDeclContext &parent_decl_ctx,
2361061da546Spatrick                                     bool include_inlines,
2362061da546Spatrick                                     SymbolContextList &sc_list) {
2363061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2364*f6aab3d8Srobert   ConstString name = lookup_info.GetLookupName();
2365*f6aab3d8Srobert   FunctionNameType name_type_mask = lookup_info.GetNameTypeMask();
2366061da546Spatrick 
2367061da546Spatrick   // eFunctionNameTypeAuto should be pre-resolved by a call to
2368061da546Spatrick   // Module::LookupInfo::LookupInfo()
2369061da546Spatrick   assert((name_type_mask & eFunctionNameTypeAuto) == 0);
2370061da546Spatrick 
2371*f6aab3d8Srobert   Log *log = GetLog(DWARFLog::Lookups);
2372061da546Spatrick 
2373061da546Spatrick   if (log) {
2374061da546Spatrick     GetObjectFile()->GetModule()->LogMessage(
2375061da546Spatrick         log,
2376*f6aab3d8Srobert         "SymbolFileDWARF::FindFunctions (name=\"{0}\", name_type_mask={1:x}, "
2377*f6aab3d8Srobert         "sc_list)",
2378061da546Spatrick         name.GetCString(), name_type_mask);
2379061da546Spatrick   }
2380061da546Spatrick 
2381061da546Spatrick   if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
2382061da546Spatrick     return;
2383061da546Spatrick 
2384061da546Spatrick   // If name is empty then we won't find anything.
2385061da546Spatrick   if (name.IsEmpty())
2386061da546Spatrick     return;
2387061da546Spatrick 
2388061da546Spatrick   // Remember how many sc_list are in the list before we search in case we are
2389061da546Spatrick   // appending the results to a variable list.
2390061da546Spatrick 
2391061da546Spatrick   const uint32_t original_size = sc_list.GetSize();
2392061da546Spatrick 
2393061da546Spatrick   llvm::DenseSet<const DWARFDebugInfoEntry *> resolved_dies;
2394061da546Spatrick 
2395*f6aab3d8Srobert   m_index->GetFunctions(lookup_info, *this, parent_decl_ctx, [&](DWARFDIE die) {
2396061da546Spatrick     if (resolved_dies.insert(die.GetDIE()).second)
2397061da546Spatrick       ResolveFunction(die, include_inlines, sc_list);
2398dda28197Spatrick     return true;
2399dda28197Spatrick   });
2400*f6aab3d8Srobert   // With -gsimple-template-names, a templated type's DW_AT_name will not
2401*f6aab3d8Srobert   // contain the template parameters. Try again stripping '<' and anything
2402*f6aab3d8Srobert   // after, filtering out entries with template parameters that don't match.
2403*f6aab3d8Srobert   {
2404*f6aab3d8Srobert     const llvm::StringRef name_ref = name.GetStringRef();
2405*f6aab3d8Srobert     auto it = name_ref.find('<');
2406*f6aab3d8Srobert     if (it != llvm::StringRef::npos) {
2407*f6aab3d8Srobert       const llvm::StringRef name_no_template_params = name_ref.slice(0, it);
2408*f6aab3d8Srobert 
2409*f6aab3d8Srobert       Module::LookupInfo no_tp_lookup_info(lookup_info);
2410*f6aab3d8Srobert       no_tp_lookup_info.SetLookupName(ConstString(name_no_template_params));
2411*f6aab3d8Srobert       m_index->GetFunctions(no_tp_lookup_info, *this, parent_decl_ctx, [&](DWARFDIE die) {
2412*f6aab3d8Srobert         if (resolved_dies.insert(die.GetDIE()).second)
2413*f6aab3d8Srobert           ResolveFunction(die, include_inlines, sc_list);
2414*f6aab3d8Srobert         return true;
2415*f6aab3d8Srobert       });
2416*f6aab3d8Srobert     }
2417*f6aab3d8Srobert   }
2418061da546Spatrick 
2419061da546Spatrick   // Return the number of variable that were appended to the list
2420061da546Spatrick   const uint32_t num_matches = sc_list.GetSize() - original_size;
2421061da546Spatrick 
2422061da546Spatrick   if (log && num_matches > 0) {
2423061da546Spatrick     GetObjectFile()->GetModule()->LogMessage(
2424061da546Spatrick         log,
2425*f6aab3d8Srobert         "SymbolFileDWARF::FindFunctions (name=\"{0}\", "
2426*f6aab3d8Srobert         "name_type_mask={1:x}, include_inlines={2:d}, sc_list) => {3}",
2427*f6aab3d8Srobert         name.GetCString(), name_type_mask, include_inlines, num_matches);
2428061da546Spatrick   }
2429061da546Spatrick }
2430061da546Spatrick 
FindFunctions(const RegularExpression & regex,bool include_inlines,SymbolContextList & sc_list)2431061da546Spatrick void SymbolFileDWARF::FindFunctions(const RegularExpression &regex,
2432061da546Spatrick                                     bool include_inlines,
2433061da546Spatrick                                     SymbolContextList &sc_list) {
2434061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2435be691f3bSpatrick   LLDB_SCOPED_TIMERF("SymbolFileDWARF::FindFunctions (regex = '%s')",
2436061da546Spatrick                      regex.GetText().str().c_str());
2437061da546Spatrick 
2438*f6aab3d8Srobert   Log *log = GetLog(DWARFLog::Lookups);
2439061da546Spatrick 
2440061da546Spatrick   if (log) {
2441061da546Spatrick     GetObjectFile()->GetModule()->LogMessage(
2442*f6aab3d8Srobert         log, "SymbolFileDWARF::FindFunctions (regex=\"{0}\", sc_list)",
2443061da546Spatrick         regex.GetText().str().c_str());
2444061da546Spatrick   }
2445061da546Spatrick 
2446061da546Spatrick   llvm::DenseSet<const DWARFDebugInfoEntry *> resolved_dies;
2447dda28197Spatrick   m_index->GetFunctions(regex, [&](DWARFDIE die) {
2448061da546Spatrick     if (resolved_dies.insert(die.GetDIE()).second)
2449061da546Spatrick       ResolveFunction(die, include_inlines, sc_list);
2450dda28197Spatrick     return true;
2451dda28197Spatrick   });
2452061da546Spatrick }
2453061da546Spatrick 
GetMangledNamesForFunction(const std::string & scope_qualified_name,std::vector<ConstString> & mangled_names)2454061da546Spatrick void SymbolFileDWARF::GetMangledNamesForFunction(
2455061da546Spatrick     const std::string &scope_qualified_name,
2456061da546Spatrick     std::vector<ConstString> &mangled_names) {
2457dda28197Spatrick   DWARFDebugInfo &info = DebugInfo();
2458dda28197Spatrick   uint32_t num_comp_units = info.GetNumUnits();
2459061da546Spatrick   for (uint32_t i = 0; i < num_comp_units; i++) {
2460dda28197Spatrick     DWARFUnit *cu = info.GetUnitAtIndex(i);
2461061da546Spatrick     if (cu == nullptr)
2462061da546Spatrick       continue;
2463061da546Spatrick 
2464061da546Spatrick     SymbolFileDWARFDwo *dwo = cu->GetDwoSymbolFile();
2465061da546Spatrick     if (dwo)
2466061da546Spatrick       dwo->GetMangledNamesForFunction(scope_qualified_name, mangled_names);
2467061da546Spatrick   }
2468061da546Spatrick 
2469dda28197Spatrick   for (DIERef die_ref :
2470061da546Spatrick        m_function_scope_qualified_name_map.lookup(scope_qualified_name)) {
2471dda28197Spatrick     DWARFDIE die = GetDIE(die_ref);
2472061da546Spatrick     mangled_names.push_back(ConstString(die.GetMangledName()));
2473061da546Spatrick   }
2474061da546Spatrick }
2475061da546Spatrick 
FindTypes(ConstString name,const CompilerDeclContext & parent_decl_ctx,uint32_t max_matches,llvm::DenseSet<lldb_private::SymbolFile * > & searched_symbol_files,TypeMap & types)2476061da546Spatrick void SymbolFileDWARF::FindTypes(
2477dda28197Spatrick     ConstString name, const CompilerDeclContext &parent_decl_ctx,
2478061da546Spatrick     uint32_t max_matches,
2479061da546Spatrick     llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
2480061da546Spatrick     TypeMap &types) {
2481061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2482061da546Spatrick   // Make sure we haven't already searched this SymbolFile before.
2483061da546Spatrick   if (!searched_symbol_files.insert(this).second)
2484061da546Spatrick     return;
2485061da546Spatrick 
2486*f6aab3d8Srobert   Log *log = GetLog(DWARFLog::Lookups);
2487061da546Spatrick 
2488061da546Spatrick   if (log) {
2489061da546Spatrick     if (parent_decl_ctx)
2490061da546Spatrick       GetObjectFile()->GetModule()->LogMessage(
2491061da546Spatrick           log,
2492*f6aab3d8Srobert           "SymbolFileDWARF::FindTypes (sc, name=\"{0}\", parent_decl_ctx = "
2493*f6aab3d8Srobert           "{1:p} (\"{2}\"), max_matches={3}, type_list)",
2494dda28197Spatrick           name.GetCString(), static_cast<const void *>(&parent_decl_ctx),
2495dda28197Spatrick           parent_decl_ctx.GetName().AsCString("<NULL>"), max_matches);
2496061da546Spatrick     else
2497061da546Spatrick       GetObjectFile()->GetModule()->LogMessage(
2498061da546Spatrick           log,
2499*f6aab3d8Srobert           "SymbolFileDWARF::FindTypes (sc, name=\"{0}\", parent_decl_ctx = "
2500*f6aab3d8Srobert           "NULL, max_matches={1}, type_list)",
2501061da546Spatrick           name.GetCString(), max_matches);
2502061da546Spatrick   }
2503061da546Spatrick 
2504061da546Spatrick   if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
2505061da546Spatrick     return;
2506061da546Spatrick 
2507*f6aab3d8Srobert   // Unlike FindFunctions(), FindTypes() following cannot produce false
2508*f6aab3d8Srobert   // positives.
2509*f6aab3d8Srobert 
2510*f6aab3d8Srobert   const llvm::StringRef name_ref = name.GetStringRef();
2511*f6aab3d8Srobert   auto name_bracket_index = name_ref.find('<');
2512dda28197Spatrick   m_index->GetTypes(name, [&](DWARFDIE die) {
2513061da546Spatrick     if (!DIEInDeclContext(parent_decl_ctx, die))
2514dda28197Spatrick       return true; // The containing decl contexts don't match
2515061da546Spatrick 
2516061da546Spatrick     Type *matching_type = ResolveType(die, true, true);
2517dda28197Spatrick     if (!matching_type)
2518dda28197Spatrick       return true;
2519dda28197Spatrick 
2520*f6aab3d8Srobert     // With -gsimple-template-names, a templated type's DW_AT_name will not
2521*f6aab3d8Srobert     // contain the template parameters. Make sure that if the original query
2522*f6aab3d8Srobert     // didn't contain a '<', we filter out entries with template parameters.
2523*f6aab3d8Srobert     if (name_bracket_index == llvm::StringRef::npos &&
2524*f6aab3d8Srobert         matching_type->IsTemplateType())
2525*f6aab3d8Srobert       return true;
2526*f6aab3d8Srobert 
2527061da546Spatrick     // We found a type pointer, now find the shared pointer form our type
2528061da546Spatrick     // list
2529061da546Spatrick     types.InsertUnique(matching_type->shared_from_this());
2530dda28197Spatrick     return types.GetSize() < max_matches;
2531dda28197Spatrick   });
2532061da546Spatrick 
2533*f6aab3d8Srobert   // With -gsimple-template-names, a templated type's DW_AT_name will not
2534*f6aab3d8Srobert   // contain the template parameters. Try again stripping '<' and anything
2535*f6aab3d8Srobert   // after, filtering out entries with template parameters that don't match.
2536*f6aab3d8Srobert   if (types.GetSize() < max_matches) {
2537*f6aab3d8Srobert     if (name_bracket_index != llvm::StringRef::npos) {
2538*f6aab3d8Srobert       const llvm::StringRef name_no_template_params =
2539*f6aab3d8Srobert           name_ref.slice(0, name_bracket_index);
2540*f6aab3d8Srobert       const llvm::StringRef template_params =
2541*f6aab3d8Srobert           name_ref.slice(name_bracket_index, name_ref.size());
2542*f6aab3d8Srobert       m_index->GetTypes(ConstString(name_no_template_params), [&](DWARFDIE die) {
2543*f6aab3d8Srobert         if (!DIEInDeclContext(parent_decl_ctx, die))
2544*f6aab3d8Srobert           return true; // The containing decl contexts don't match
2545*f6aab3d8Srobert 
2546*f6aab3d8Srobert         const llvm::StringRef base_name = GetTypeForDIE(die)->GetBaseName().AsCString();
2547*f6aab3d8Srobert         auto it = base_name.find('<');
2548*f6aab3d8Srobert         // If the candidate qualified name doesn't have '<', it doesn't have
2549*f6aab3d8Srobert         // template params to compare.
2550*f6aab3d8Srobert         if (it == llvm::StringRef::npos)
2551*f6aab3d8Srobert           return true;
2552*f6aab3d8Srobert 
2553*f6aab3d8Srobert         // Filter out non-matching instantiations by comparing template params.
2554*f6aab3d8Srobert         const llvm::StringRef base_name_template_params =
2555*f6aab3d8Srobert             base_name.slice(it, base_name.size());
2556*f6aab3d8Srobert 
2557*f6aab3d8Srobert         if (template_params != base_name_template_params)
2558*f6aab3d8Srobert           return true;
2559*f6aab3d8Srobert 
2560*f6aab3d8Srobert         Type *matching_type = ResolveType(die, true, true);
2561*f6aab3d8Srobert         if (!matching_type)
2562*f6aab3d8Srobert           return true;
2563*f6aab3d8Srobert 
2564*f6aab3d8Srobert         // We found a type pointer, now find the shared pointer form our type
2565*f6aab3d8Srobert         // list.
2566*f6aab3d8Srobert         types.InsertUnique(matching_type->shared_from_this());
2567*f6aab3d8Srobert         return types.GetSize() < max_matches;
2568*f6aab3d8Srobert       });
2569*f6aab3d8Srobert     }
2570*f6aab3d8Srobert   }
2571*f6aab3d8Srobert 
2572061da546Spatrick   // Next search through the reachable Clang modules. This only applies for
2573061da546Spatrick   // DWARF objects compiled with -gmodules that haven't been processed by
2574061da546Spatrick   // dsymutil.
2575dda28197Spatrick   if (types.GetSize() < max_matches) {
2576061da546Spatrick     UpdateExternalModuleListIfNeeded();
2577061da546Spatrick 
2578061da546Spatrick     for (const auto &pair : m_external_type_modules)
2579061da546Spatrick       if (ModuleSP external_module_sp = pair.second)
2580061da546Spatrick         if (SymbolFile *sym_file = external_module_sp->GetSymbolFile())
2581061da546Spatrick           sym_file->FindTypes(name, parent_decl_ctx, max_matches,
2582061da546Spatrick                               searched_symbol_files, types);
2583061da546Spatrick   }
2584061da546Spatrick 
2585061da546Spatrick   if (log && types.GetSize()) {
2586061da546Spatrick     if (parent_decl_ctx) {
2587061da546Spatrick       GetObjectFile()->GetModule()->LogMessage(
2588061da546Spatrick           log,
2589*f6aab3d8Srobert           "SymbolFileDWARF::FindTypes (sc, name=\"{0}\", parent_decl_ctx "
2590*f6aab3d8Srobert           "= {1:p} (\"{2}\"), max_matches={3}, type_list) => {4}",
2591dda28197Spatrick           name.GetCString(), static_cast<const void *>(&parent_decl_ctx),
2592dda28197Spatrick           parent_decl_ctx.GetName().AsCString("<NULL>"), max_matches,
2593061da546Spatrick           types.GetSize());
2594061da546Spatrick     } else {
2595061da546Spatrick       GetObjectFile()->GetModule()->LogMessage(
2596061da546Spatrick           log,
2597*f6aab3d8Srobert           "SymbolFileDWARF::FindTypes (sc, name=\"{0}\", parent_decl_ctx "
2598*f6aab3d8Srobert           "= NULL, max_matches={1}, type_list) => {2}",
2599061da546Spatrick           name.GetCString(), max_matches, types.GetSize());
2600061da546Spatrick     }
2601061da546Spatrick   }
2602061da546Spatrick }
2603061da546Spatrick 
FindTypes(llvm::ArrayRef<CompilerContext> pattern,LanguageSet languages,llvm::DenseSet<SymbolFile * > & searched_symbol_files,TypeMap & types)2604061da546Spatrick void SymbolFileDWARF::FindTypes(
2605061da546Spatrick     llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
2606061da546Spatrick     llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {
2607061da546Spatrick   // Make sure we haven't already searched this SymbolFile before.
2608061da546Spatrick   if (!searched_symbol_files.insert(this).second)
2609061da546Spatrick     return;
2610061da546Spatrick 
2611061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2612061da546Spatrick   if (pattern.empty())
2613061da546Spatrick     return;
2614061da546Spatrick 
2615061da546Spatrick   ConstString name = pattern.back().name;
2616061da546Spatrick 
2617061da546Spatrick   if (!name)
2618061da546Spatrick     return;
2619061da546Spatrick 
2620dda28197Spatrick   m_index->GetTypes(name, [&](DWARFDIE die) {
2621be691f3bSpatrick     if (!languages[GetLanguageFamily(*die.GetCU())])
2622dda28197Spatrick       return true;
2623061da546Spatrick 
2624061da546Spatrick     llvm::SmallVector<CompilerContext, 4> die_context;
2625061da546Spatrick     die.GetDeclContext(die_context);
2626061da546Spatrick     if (!contextMatches(die_context, pattern))
2627dda28197Spatrick       return true;
2628061da546Spatrick 
2629061da546Spatrick     if (Type *matching_type = ResolveType(die, true, true)) {
2630061da546Spatrick       // We found a type pointer, now find the shared pointer form our type
2631061da546Spatrick       // list.
2632061da546Spatrick       types.InsertUnique(matching_type->shared_from_this());
2633061da546Spatrick     }
2634dda28197Spatrick     return true;
2635dda28197Spatrick   });
2636061da546Spatrick 
2637061da546Spatrick   // Next search through the reachable Clang modules. This only applies for
2638061da546Spatrick   // DWARF objects compiled with -gmodules that haven't been processed by
2639061da546Spatrick   // dsymutil.
2640061da546Spatrick   UpdateExternalModuleListIfNeeded();
2641061da546Spatrick 
2642061da546Spatrick   for (const auto &pair : m_external_type_modules)
2643061da546Spatrick     if (ModuleSP external_module_sp = pair.second)
2644061da546Spatrick       external_module_sp->FindTypes(pattern, languages, searched_symbol_files,
2645061da546Spatrick                                     types);
2646061da546Spatrick }
2647061da546Spatrick 
2648061da546Spatrick CompilerDeclContext
FindNamespace(ConstString name,const CompilerDeclContext & parent_decl_ctx)2649061da546Spatrick SymbolFileDWARF::FindNamespace(ConstString name,
2650dda28197Spatrick                                const CompilerDeclContext &parent_decl_ctx) {
2651061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2652*f6aab3d8Srobert   Log *log = GetLog(DWARFLog::Lookups);
2653061da546Spatrick 
2654061da546Spatrick   if (log) {
2655061da546Spatrick     GetObjectFile()->GetModule()->LogMessage(
2656*f6aab3d8Srobert         log, "SymbolFileDWARF::FindNamespace (sc, name=\"{0}\")",
2657061da546Spatrick         name.GetCString());
2658061da546Spatrick   }
2659061da546Spatrick 
2660061da546Spatrick   CompilerDeclContext namespace_decl_ctx;
2661061da546Spatrick 
2662061da546Spatrick   if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
2663061da546Spatrick     return namespace_decl_ctx;
2664061da546Spatrick 
2665dda28197Spatrick   m_index->GetNamespaces(name, [&](DWARFDIE die) {
2666061da546Spatrick     if (!DIEInDeclContext(parent_decl_ctx, die))
2667dda28197Spatrick       return true; // The containing decl contexts don't match
2668061da546Spatrick 
2669dda28197Spatrick     DWARFASTParser *dwarf_ast = GetDWARFParser(*die.GetCU());
2670dda28197Spatrick     if (!dwarf_ast)
2671dda28197Spatrick       return true;
2672dda28197Spatrick 
2673061da546Spatrick     namespace_decl_ctx = dwarf_ast->GetDeclContextForUIDFromDWARF(die);
2674dda28197Spatrick     return !namespace_decl_ctx.IsValid();
2675dda28197Spatrick   });
2676dda28197Spatrick 
2677061da546Spatrick   if (log && namespace_decl_ctx) {
2678061da546Spatrick     GetObjectFile()->GetModule()->LogMessage(
2679061da546Spatrick         log,
2680*f6aab3d8Srobert         "SymbolFileDWARF::FindNamespace (sc, name=\"{0}\") => "
2681*f6aab3d8Srobert         "CompilerDeclContext({1:p}/{2:p}) \"{3}\"",
2682061da546Spatrick         name.GetCString(),
2683061da546Spatrick         static_cast<const void *>(namespace_decl_ctx.GetTypeSystem()),
2684061da546Spatrick         static_cast<const void *>(namespace_decl_ctx.GetOpaqueDeclContext()),
2685061da546Spatrick         namespace_decl_ctx.GetName().AsCString("<NULL>"));
2686061da546Spatrick   }
2687061da546Spatrick 
2688061da546Spatrick   return namespace_decl_ctx;
2689061da546Spatrick }
2690061da546Spatrick 
GetTypeForDIE(const DWARFDIE & die,bool resolve_function_context)2691061da546Spatrick TypeSP SymbolFileDWARF::GetTypeForDIE(const DWARFDIE &die,
2692061da546Spatrick                                       bool resolve_function_context) {
2693061da546Spatrick   TypeSP type_sp;
2694061da546Spatrick   if (die) {
2695061da546Spatrick     Type *type_ptr = GetDIEToType().lookup(die.GetDIE());
2696061da546Spatrick     if (type_ptr == nullptr) {
2697061da546Spatrick       SymbolContextScope *scope;
2698061da546Spatrick       if (auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(die.GetCU()))
2699061da546Spatrick         scope = GetCompUnitForDWARFCompUnit(*dwarf_cu);
2700061da546Spatrick       else
2701061da546Spatrick         scope = GetObjectFile()->GetModule().get();
2702061da546Spatrick       assert(scope);
2703061da546Spatrick       SymbolContext sc(scope);
2704061da546Spatrick       const DWARFDebugInfoEntry *parent_die = die.GetParent().GetDIE();
2705061da546Spatrick       while (parent_die != nullptr) {
2706061da546Spatrick         if (parent_die->Tag() == DW_TAG_subprogram)
2707061da546Spatrick           break;
2708061da546Spatrick         parent_die = parent_die->GetParent();
2709061da546Spatrick       }
2710061da546Spatrick       SymbolContext sc_backup = sc;
2711061da546Spatrick       if (resolve_function_context && parent_die != nullptr &&
2712061da546Spatrick           !GetFunction(DWARFDIE(die.GetCU(), parent_die), sc))
2713061da546Spatrick         sc = sc_backup;
2714061da546Spatrick 
2715061da546Spatrick       type_sp = ParseType(sc, die, nullptr);
2716061da546Spatrick     } else if (type_ptr != DIE_IS_BEING_PARSED) {
2717*f6aab3d8Srobert       // Get the original shared pointer for this type
2718061da546Spatrick       type_sp = type_ptr->shared_from_this();
2719061da546Spatrick     }
2720061da546Spatrick   }
2721061da546Spatrick   return type_sp;
2722061da546Spatrick }
2723061da546Spatrick 
2724061da546Spatrick DWARFDIE
GetDeclContextDIEContainingDIE(const DWARFDIE & orig_die)2725061da546Spatrick SymbolFileDWARF::GetDeclContextDIEContainingDIE(const DWARFDIE &orig_die) {
2726061da546Spatrick   if (orig_die) {
2727061da546Spatrick     DWARFDIE die = orig_die;
2728061da546Spatrick 
2729061da546Spatrick     while (die) {
2730061da546Spatrick       // If this is the original DIE that we are searching for a declaration
2731061da546Spatrick       // for, then don't look in the cache as we don't want our own decl
2732061da546Spatrick       // context to be our decl context...
2733061da546Spatrick       if (orig_die != die) {
2734061da546Spatrick         switch (die.Tag()) {
2735061da546Spatrick         case DW_TAG_compile_unit:
2736061da546Spatrick         case DW_TAG_partial_unit:
2737061da546Spatrick         case DW_TAG_namespace:
2738061da546Spatrick         case DW_TAG_structure_type:
2739061da546Spatrick         case DW_TAG_union_type:
2740061da546Spatrick         case DW_TAG_class_type:
2741061da546Spatrick         case DW_TAG_lexical_block:
2742061da546Spatrick         case DW_TAG_subprogram:
2743061da546Spatrick           return die;
2744061da546Spatrick         case DW_TAG_inlined_subroutine: {
2745061da546Spatrick           DWARFDIE abs_die = die.GetReferencedDIE(DW_AT_abstract_origin);
2746061da546Spatrick           if (abs_die) {
2747061da546Spatrick             return abs_die;
2748061da546Spatrick           }
2749061da546Spatrick           break;
2750061da546Spatrick         }
2751061da546Spatrick         default:
2752061da546Spatrick           break;
2753061da546Spatrick         }
2754061da546Spatrick       }
2755061da546Spatrick 
2756061da546Spatrick       DWARFDIE spec_die = die.GetReferencedDIE(DW_AT_specification);
2757061da546Spatrick       if (spec_die) {
2758061da546Spatrick         DWARFDIE decl_ctx_die = GetDeclContextDIEContainingDIE(spec_die);
2759061da546Spatrick         if (decl_ctx_die)
2760061da546Spatrick           return decl_ctx_die;
2761061da546Spatrick       }
2762061da546Spatrick 
2763061da546Spatrick       DWARFDIE abs_die = die.GetReferencedDIE(DW_AT_abstract_origin);
2764061da546Spatrick       if (abs_die) {
2765061da546Spatrick         DWARFDIE decl_ctx_die = GetDeclContextDIEContainingDIE(abs_die);
2766061da546Spatrick         if (decl_ctx_die)
2767061da546Spatrick           return decl_ctx_die;
2768061da546Spatrick       }
2769061da546Spatrick 
2770061da546Spatrick       die = die.GetParent();
2771061da546Spatrick     }
2772061da546Spatrick   }
2773061da546Spatrick   return DWARFDIE();
2774061da546Spatrick }
2775061da546Spatrick 
GetObjCClassSymbol(ConstString objc_class_name)2776061da546Spatrick Symbol *SymbolFileDWARF::GetObjCClassSymbol(ConstString objc_class_name) {
2777061da546Spatrick   Symbol *objc_class_symbol = nullptr;
2778061da546Spatrick   if (m_objfile_sp) {
2779061da546Spatrick     Symtab *symtab = m_objfile_sp->GetSymtab();
2780061da546Spatrick     if (symtab) {
2781061da546Spatrick       objc_class_symbol = symtab->FindFirstSymbolWithNameAndType(
2782061da546Spatrick           objc_class_name, eSymbolTypeObjCClass, Symtab::eDebugNo,
2783061da546Spatrick           Symtab::eVisibilityAny);
2784061da546Spatrick     }
2785061da546Spatrick   }
2786061da546Spatrick   return objc_class_symbol;
2787061da546Spatrick }
2788061da546Spatrick 
2789061da546Spatrick // Some compilers don't emit the DW_AT_APPLE_objc_complete_type attribute. If
2790061da546Spatrick // they don't then we can end up looking through all class types for a complete
2791061da546Spatrick // type and never find the full definition. We need to know if this attribute
2792061da546Spatrick // is supported, so we determine this here and cache th result. We also need to
2793061da546Spatrick // worry about the debug map
2794061da546Spatrick // DWARF file
2795061da546Spatrick // if we are doing darwin DWARF in .o file debugging.
Supports_DW_AT_APPLE_objc_complete_type(DWARFUnit * cu)2796061da546Spatrick bool SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type(DWARFUnit *cu) {
2797061da546Spatrick   if (m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolCalculate) {
2798061da546Spatrick     m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolNo;
2799061da546Spatrick     if (cu && cu->Supports_DW_AT_APPLE_objc_complete_type())
2800061da546Spatrick       m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolYes;
2801061da546Spatrick     else {
2802dda28197Spatrick       DWARFDebugInfo &debug_info = DebugInfo();
2803061da546Spatrick       const uint32_t num_compile_units = GetNumCompileUnits();
2804061da546Spatrick       for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
2805dda28197Spatrick         DWARFUnit *dwarf_cu = debug_info.GetUnitAtIndex(cu_idx);
2806061da546Spatrick         if (dwarf_cu != cu &&
2807061da546Spatrick             dwarf_cu->Supports_DW_AT_APPLE_objc_complete_type()) {
2808061da546Spatrick           m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolYes;
2809061da546Spatrick           break;
2810061da546Spatrick         }
2811061da546Spatrick       }
2812061da546Spatrick     }
2813061da546Spatrick     if (m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolNo &&
2814061da546Spatrick         GetDebugMapSymfile())
2815061da546Spatrick       return m_debug_map_symfile->Supports_DW_AT_APPLE_objc_complete_type(this);
2816061da546Spatrick   }
2817061da546Spatrick   return m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolYes;
2818061da546Spatrick }
2819061da546Spatrick 
2820061da546Spatrick // This function can be used when a DIE is found that is a forward declaration
2821061da546Spatrick // DIE and we want to try and find a type that has the complete definition.
FindCompleteObjCDefinitionTypeForDIE(const DWARFDIE & die,ConstString type_name,bool must_be_implementation)2822061da546Spatrick TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE(
2823061da546Spatrick     const DWARFDIE &die, ConstString type_name, bool must_be_implementation) {
2824061da546Spatrick 
2825061da546Spatrick   TypeSP type_sp;
2826061da546Spatrick 
2827061da546Spatrick   if (!type_name || (must_be_implementation && !GetObjCClassSymbol(type_name)))
2828061da546Spatrick     return type_sp;
2829061da546Spatrick 
2830dda28197Spatrick   m_index->GetCompleteObjCClass(
2831dda28197Spatrick       type_name, must_be_implementation, [&](DWARFDIE type_die) {
2832061da546Spatrick         bool try_resolving_type = false;
2833061da546Spatrick 
2834061da546Spatrick         // Don't try and resolve the DIE we are looking for with the DIE
2835061da546Spatrick         // itself!
2836061da546Spatrick         if (type_die != die) {
2837061da546Spatrick           switch (type_die.Tag()) {
2838061da546Spatrick           case DW_TAG_class_type:
2839061da546Spatrick           case DW_TAG_structure_type:
2840061da546Spatrick             try_resolving_type = true;
2841061da546Spatrick             break;
2842061da546Spatrick           default:
2843061da546Spatrick             break;
2844061da546Spatrick           }
2845061da546Spatrick         }
2846dda28197Spatrick         if (!try_resolving_type)
2847dda28197Spatrick           return true;
2848061da546Spatrick 
2849061da546Spatrick         if (must_be_implementation &&
2850061da546Spatrick             type_die.Supports_DW_AT_APPLE_objc_complete_type())
2851061da546Spatrick           try_resolving_type = type_die.GetAttributeValueAsUnsigned(
2852061da546Spatrick               DW_AT_APPLE_objc_complete_type, 0);
2853dda28197Spatrick         if (!try_resolving_type)
2854dda28197Spatrick           return true;
2855061da546Spatrick 
2856061da546Spatrick         Type *resolved_type = ResolveType(type_die, false, true);
2857dda28197Spatrick         if (!resolved_type || resolved_type == DIE_IS_BEING_PARSED)
2858dda28197Spatrick           return true;
2859dda28197Spatrick 
2860dda28197Spatrick         DEBUG_PRINTF(
2861dda28197Spatrick             "resolved 0x%8.8" PRIx64 " from %s to 0x%8.8" PRIx64
2862061da546Spatrick             " (cu 0x%8.8" PRIx64 ")\n",
2863061da546Spatrick             die.GetID(),
2864dda28197Spatrick             m_objfile_sp->GetFileSpec().GetFilename().AsCString("<Unknown>"),
2865061da546Spatrick             type_die.GetID(), type_cu->GetID());
2866061da546Spatrick 
2867061da546Spatrick         if (die)
2868061da546Spatrick           GetDIEToType()[die.GetDIE()] = resolved_type;
2869061da546Spatrick         type_sp = resolved_type->shared_from_this();
2870dda28197Spatrick         return false;
2871dda28197Spatrick       });
2872061da546Spatrick   return type_sp;
2873061da546Spatrick }
2874061da546Spatrick 
2875061da546Spatrick // This function helps to ensure that the declaration contexts match for two
2876061da546Spatrick // different DIEs. Often times debug information will refer to a forward
2877061da546Spatrick // declaration of a type (the equivalent of "struct my_struct;". There will
2878061da546Spatrick // often be a declaration of that type elsewhere that has the full definition.
2879061da546Spatrick // When we go looking for the full type "my_struct", we will find one or more
2880061da546Spatrick // matches in the accelerator tables and we will then need to make sure the
2881061da546Spatrick // type was in the same declaration context as the original DIE. This function
2882061da546Spatrick // can efficiently compare two DIEs and will return true when the declaration
2883061da546Spatrick // context matches, and false when they don't.
DIEDeclContextsMatch(const DWARFDIE & die1,const DWARFDIE & die2)2884061da546Spatrick bool SymbolFileDWARF::DIEDeclContextsMatch(const DWARFDIE &die1,
2885061da546Spatrick                                            const DWARFDIE &die2) {
2886061da546Spatrick   if (die1 == die2)
2887061da546Spatrick     return true;
2888061da546Spatrick 
2889061da546Spatrick   std::vector<DWARFDIE> decl_ctx_1;
2890061da546Spatrick   std::vector<DWARFDIE> decl_ctx_2;
2891061da546Spatrick   // The declaration DIE stack is a stack of the declaration context DIEs all
2892061da546Spatrick   // the way back to the compile unit. If a type "T" is declared inside a class
2893061da546Spatrick   // "B", and class "B" is declared inside a class "A" and class "A" is in a
2894061da546Spatrick   // namespace "lldb", and the namespace is in a compile unit, there will be a
2895061da546Spatrick   // stack of DIEs:
2896061da546Spatrick   //
2897061da546Spatrick   //   [0] DW_TAG_class_type for "B"
2898061da546Spatrick   //   [1] DW_TAG_class_type for "A"
2899061da546Spatrick   //   [2] DW_TAG_namespace  for "lldb"
2900061da546Spatrick   //   [3] DW_TAG_compile_unit or DW_TAG_partial_unit for the source file.
2901061da546Spatrick   //
2902061da546Spatrick   // We grab both contexts and make sure that everything matches all the way
2903061da546Spatrick   // back to the compiler unit.
2904061da546Spatrick 
2905061da546Spatrick   // First lets grab the decl contexts for both DIEs
2906061da546Spatrick   decl_ctx_1 = die1.GetDeclContextDIEs();
2907061da546Spatrick   decl_ctx_2 = die2.GetDeclContextDIEs();
2908061da546Spatrick   // Make sure the context arrays have the same size, otherwise we are done
2909061da546Spatrick   const size_t count1 = decl_ctx_1.size();
2910061da546Spatrick   const size_t count2 = decl_ctx_2.size();
2911061da546Spatrick   if (count1 != count2)
2912061da546Spatrick     return false;
2913061da546Spatrick 
2914061da546Spatrick   // Make sure the DW_TAG values match all the way back up the compile unit. If
2915061da546Spatrick   // they don't, then we are done.
2916061da546Spatrick   DWARFDIE decl_ctx_die1;
2917061da546Spatrick   DWARFDIE decl_ctx_die2;
2918061da546Spatrick   size_t i;
2919061da546Spatrick   for (i = 0; i < count1; i++) {
2920061da546Spatrick     decl_ctx_die1 = decl_ctx_1[i];
2921061da546Spatrick     decl_ctx_die2 = decl_ctx_2[i];
2922061da546Spatrick     if (decl_ctx_die1.Tag() != decl_ctx_die2.Tag())
2923061da546Spatrick       return false;
2924061da546Spatrick   }
2925061da546Spatrick #ifndef NDEBUG
2926061da546Spatrick 
2927061da546Spatrick   // Make sure the top item in the decl context die array is always
2928061da546Spatrick   // DW_TAG_compile_unit or DW_TAG_partial_unit. If it isn't then
2929061da546Spatrick   // something went wrong in the DWARFDIE::GetDeclContextDIEs()
2930061da546Spatrick   // function.
2931061da546Spatrick   dw_tag_t cu_tag = decl_ctx_1[count1 - 1].Tag();
2932061da546Spatrick   UNUSED_IF_ASSERT_DISABLED(cu_tag);
2933061da546Spatrick   assert(cu_tag == DW_TAG_compile_unit || cu_tag == DW_TAG_partial_unit);
2934061da546Spatrick 
2935061da546Spatrick #endif
2936061da546Spatrick   // Always skip the compile unit when comparing by only iterating up to "count
2937061da546Spatrick   // - 1". Here we compare the names as we go.
2938061da546Spatrick   for (i = 0; i < count1 - 1; i++) {
2939061da546Spatrick     decl_ctx_die1 = decl_ctx_1[i];
2940061da546Spatrick     decl_ctx_die2 = decl_ctx_2[i];
2941061da546Spatrick     const char *name1 = decl_ctx_die1.GetName();
2942061da546Spatrick     const char *name2 = decl_ctx_die2.GetName();
2943061da546Spatrick     // If the string was from a DW_FORM_strp, then the pointer will often be
2944061da546Spatrick     // the same!
2945061da546Spatrick     if (name1 == name2)
2946061da546Spatrick       continue;
2947061da546Spatrick 
2948061da546Spatrick     // Name pointers are not equal, so only compare the strings if both are not
2949061da546Spatrick     // NULL.
2950061da546Spatrick     if (name1 && name2) {
2951061da546Spatrick       // If the strings don't compare, we are done...
2952061da546Spatrick       if (strcmp(name1, name2) != 0)
2953061da546Spatrick         return false;
2954061da546Spatrick     } else {
2955061da546Spatrick       // One name was NULL while the other wasn't
2956061da546Spatrick       return false;
2957061da546Spatrick     }
2958061da546Spatrick   }
2959061da546Spatrick   // We made it through all of the checks and the declaration contexts are
2960061da546Spatrick   // equal.
2961061da546Spatrick   return true;
2962061da546Spatrick }
2963061da546Spatrick 
2964*f6aab3d8Srobert TypeSP
FindDefinitionTypeForDWARFDeclContext(const DWARFDIE & die)2965*f6aab3d8Srobert SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die) {
2966061da546Spatrick   TypeSP type_sp;
2967061da546Spatrick 
2968*f6aab3d8Srobert   if (die.GetName()) {
2969*f6aab3d8Srobert     const dw_tag_t tag = die.Tag();
2970061da546Spatrick 
2971*f6aab3d8Srobert     Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);
2972061da546Spatrick     if (log) {
2973061da546Spatrick       GetObjectFile()->GetModule()->LogMessage(
2974061da546Spatrick           log,
2975061da546Spatrick           "SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%"
2976*f6aab3d8Srobert           "s, name='{0}')",
2977*f6aab3d8Srobert           DW_TAG_value_to_name(tag), die.GetName());
2978061da546Spatrick     }
2979061da546Spatrick 
2980061da546Spatrick     // Get the type system that we are looking to find a type for. We will
2981061da546Spatrick     // use this to ensure any matches we find are in a language that this
2982061da546Spatrick     // type system supports
2983*f6aab3d8Srobert     const LanguageType language = GetLanguage(*die.GetCU());
2984*f6aab3d8Srobert     TypeSystemSP type_system = nullptr;
2985061da546Spatrick     if (language != eLanguageTypeUnknown) {
2986061da546Spatrick       auto type_system_or_err = GetTypeSystemForLanguage(language);
2987061da546Spatrick       if (auto err = type_system_or_err.takeError()) {
2988*f6aab3d8Srobert         LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
2989*f6aab3d8Srobert                        "Cannot get TypeSystem for language {}",
2990061da546Spatrick                        Language::GetNameForLanguageType(language));
2991061da546Spatrick       } else {
2992*f6aab3d8Srobert         type_system = *type_system_or_err;
2993061da546Spatrick       }
2994061da546Spatrick     }
2995061da546Spatrick 
2996*f6aab3d8Srobert     // See comments below about -gsimple-template-names for why we attempt to
2997*f6aab3d8Srobert     // compute missing template parameter names.
2998*f6aab3d8Srobert     ConstString template_params;
2999*f6aab3d8Srobert     if (type_system) {
3000*f6aab3d8Srobert       DWARFASTParser *dwarf_ast = type_system->GetDWARFParser();
3001*f6aab3d8Srobert       if (dwarf_ast)
3002*f6aab3d8Srobert         template_params = dwarf_ast->GetDIEClassTemplateParams(die);
3003*f6aab3d8Srobert     }
3004*f6aab3d8Srobert 
3005*f6aab3d8Srobert     m_index->GetTypes(GetDWARFDeclContext(die), [&](DWARFDIE type_die) {
3006*f6aab3d8Srobert       // Make sure type_die's language matches the type system we are
3007061da546Spatrick       // looking for. We don't want to find a "Foo" type from Java if we
3008061da546Spatrick       // are looking for a "Foo" type for C, C++, ObjC, or ObjC++.
3009061da546Spatrick       if (type_system &&
3010dda28197Spatrick           !type_system->SupportsLanguage(GetLanguage(*type_die.GetCU())))
3011dda28197Spatrick         return true;
3012061da546Spatrick       bool try_resolving_type = false;
3013061da546Spatrick 
3014061da546Spatrick       // Don't try and resolve the DIE we are looking for with the DIE
3015061da546Spatrick       // itself!
3016061da546Spatrick       const dw_tag_t type_tag = type_die.Tag();
3017061da546Spatrick       // Make sure the tags match
3018061da546Spatrick       if (type_tag == tag) {
3019061da546Spatrick         // The tags match, lets try resolving this type
3020061da546Spatrick         try_resolving_type = true;
3021061da546Spatrick       } else {
3022061da546Spatrick         // The tags don't match, but we need to watch our for a forward
3023061da546Spatrick         // declaration for a struct and ("struct foo") ends up being a
3024061da546Spatrick         // class ("class foo { ... };") or vice versa.
3025061da546Spatrick         switch (type_tag) {
3026061da546Spatrick         case DW_TAG_class_type:
3027061da546Spatrick           // We had a "class foo", see if we ended up with a "struct foo
3028061da546Spatrick           // { ... };"
3029061da546Spatrick           try_resolving_type = (tag == DW_TAG_structure_type);
3030061da546Spatrick           break;
3031061da546Spatrick         case DW_TAG_structure_type:
3032061da546Spatrick           // We had a "struct foo", see if we ended up with a "class foo
3033061da546Spatrick           // { ... };"
3034061da546Spatrick           try_resolving_type = (tag == DW_TAG_class_type);
3035061da546Spatrick           break;
3036061da546Spatrick         default:
3037061da546Spatrick           // Tags don't match, don't event try to resolve using this type
3038061da546Spatrick           // whose name matches....
3039061da546Spatrick           break;
3040061da546Spatrick         }
3041061da546Spatrick       }
3042061da546Spatrick 
3043dda28197Spatrick       if (!try_resolving_type) {
3044dda28197Spatrick         if (log) {
3045dda28197Spatrick           GetObjectFile()->GetModule()->LogMessage(
3046dda28197Spatrick               log,
3047dda28197Spatrick               "SymbolFileDWARF::"
3048*f6aab3d8Srobert               "FindDefinitionTypeForDWARFDeclContext(tag={0}, "
3049*f6aab3d8Srobert               "name='{1}') ignoring die={2:x16} ({3})",
3050*f6aab3d8Srobert               DW_TAG_value_to_name(tag), die.GetName(), type_die.GetOffset(),
3051*f6aab3d8Srobert               type_die.GetName());
3052dda28197Spatrick         }
3053dda28197Spatrick         return true;
3054dda28197Spatrick       }
3055dda28197Spatrick 
3056dda28197Spatrick       DWARFDeclContext type_dwarf_decl_ctx = GetDWARFDeclContext(type_die);
3057061da546Spatrick 
3058061da546Spatrick       if (log) {
3059061da546Spatrick         GetObjectFile()->GetModule()->LogMessage(
3060061da546Spatrick             log,
3061061da546Spatrick             "SymbolFileDWARF::"
3062*f6aab3d8Srobert             "FindDefinitionTypeForDWARFDeclContext(tag={0}, "
3063*f6aab3d8Srobert             "name='{1}') trying die={2:x16} ({3})",
3064*f6aab3d8Srobert             DW_TAG_value_to_name(tag), die.GetName(), type_die.GetOffset(),
3065061da546Spatrick             type_dwarf_decl_ctx.GetQualifiedName());
3066061da546Spatrick       }
3067061da546Spatrick 
3068061da546Spatrick       // Make sure the decl contexts match all the way up
3069*f6aab3d8Srobert       if (GetDWARFDeclContext(die) != type_dwarf_decl_ctx)
3070dda28197Spatrick         return true;
3071dda28197Spatrick 
3072061da546Spatrick       Type *resolved_type = ResolveType(type_die, false);
3073dda28197Spatrick       if (!resolved_type || resolved_type == DIE_IS_BEING_PARSED)
3074dda28197Spatrick         return true;
3075dda28197Spatrick 
3076*f6aab3d8Srobert       // With -gsimple-template-names, the DIE name may not contain the template
3077*f6aab3d8Srobert       // parameters. If the declaration has template parameters but doesn't
3078*f6aab3d8Srobert       // contain '<', check that the child template parameters match.
3079*f6aab3d8Srobert       if (template_params) {
3080*f6aab3d8Srobert         llvm::StringRef test_base_name =
3081*f6aab3d8Srobert             GetTypeForDIE(type_die)->GetBaseName().GetStringRef();
3082*f6aab3d8Srobert         auto i = test_base_name.find('<');
3083*f6aab3d8Srobert 
3084*f6aab3d8Srobert         // Full name from clang AST doesn't contain '<' so this type_die isn't
3085*f6aab3d8Srobert         // a template parameter, but we're expecting template parameters, so
3086*f6aab3d8Srobert         // bail.
3087*f6aab3d8Srobert         if (i == llvm::StringRef::npos)
3088*f6aab3d8Srobert           return true;
3089*f6aab3d8Srobert 
3090*f6aab3d8Srobert         llvm::StringRef test_template_params =
3091*f6aab3d8Srobert             test_base_name.slice(i, test_base_name.size());
3092*f6aab3d8Srobert         // Bail if template parameters don't match.
3093*f6aab3d8Srobert         if (test_template_params != template_params.GetStringRef())
3094*f6aab3d8Srobert           return true;
3095*f6aab3d8Srobert       }
3096*f6aab3d8Srobert 
3097061da546Spatrick       type_sp = resolved_type->shared_from_this();
3098dda28197Spatrick       return false;
3099dda28197Spatrick     });
3100061da546Spatrick   }
3101061da546Spatrick   return type_sp;
3102061da546Spatrick }
3103061da546Spatrick 
ParseType(const SymbolContext & sc,const DWARFDIE & die,bool * type_is_new_ptr)3104061da546Spatrick TypeSP SymbolFileDWARF::ParseType(const SymbolContext &sc, const DWARFDIE &die,
3105061da546Spatrick                                   bool *type_is_new_ptr) {
3106061da546Spatrick   if (!die)
3107061da546Spatrick     return {};
3108061da546Spatrick 
3109dda28197Spatrick   auto type_system_or_err = GetTypeSystemForLanguage(GetLanguage(*die.GetCU()));
3110061da546Spatrick   if (auto err = type_system_or_err.takeError()) {
3111*f6aab3d8Srobert     LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
3112*f6aab3d8Srobert                    "Unable to parse type");
3113061da546Spatrick     return {};
3114061da546Spatrick   }
3115*f6aab3d8Srobert   auto ts = *type_system_or_err;
3116*f6aab3d8Srobert   if (!ts)
3117*f6aab3d8Srobert     return {};
3118061da546Spatrick 
3119*f6aab3d8Srobert   DWARFASTParser *dwarf_ast = ts->GetDWARFParser();
3120061da546Spatrick   if (!dwarf_ast)
3121061da546Spatrick     return {};
3122061da546Spatrick 
3123061da546Spatrick   TypeSP type_sp = dwarf_ast->ParseTypeFromDWARF(sc, die, type_is_new_ptr);
3124061da546Spatrick   if (type_sp) {
3125061da546Spatrick     if (die.Tag() == DW_TAG_subprogram) {
3126061da546Spatrick       std::string scope_qualified_name(GetDeclContextForUID(die.GetID())
3127061da546Spatrick                                            .GetScopeQualifiedName()
3128061da546Spatrick                                            .AsCString(""));
3129061da546Spatrick       if (scope_qualified_name.size()) {
3130061da546Spatrick         m_function_scope_qualified_name_map[scope_qualified_name].insert(
3131dda28197Spatrick             *die.GetDIERef());
3132061da546Spatrick       }
3133061da546Spatrick     }
3134061da546Spatrick   }
3135061da546Spatrick 
3136061da546Spatrick   return type_sp;
3137061da546Spatrick }
3138061da546Spatrick 
ParseTypes(const SymbolContext & sc,const DWARFDIE & orig_die,bool parse_siblings,bool parse_children)3139061da546Spatrick size_t SymbolFileDWARF::ParseTypes(const SymbolContext &sc,
3140061da546Spatrick                                    const DWARFDIE &orig_die,
3141061da546Spatrick                                    bool parse_siblings, bool parse_children) {
3142061da546Spatrick   size_t types_added = 0;
3143061da546Spatrick   DWARFDIE die = orig_die;
3144061da546Spatrick 
3145061da546Spatrick   while (die) {
3146061da546Spatrick     const dw_tag_t tag = die.Tag();
3147061da546Spatrick     bool type_is_new = false;
3148061da546Spatrick 
3149061da546Spatrick     Tag dwarf_tag = static_cast<Tag>(tag);
3150061da546Spatrick 
3151061da546Spatrick     // TODO: Currently ParseTypeFromDWARF(...) which is called by ParseType(...)
3152061da546Spatrick     // does not handle DW_TAG_subrange_type. It is not clear if this is a bug or
3153061da546Spatrick     // not.
3154061da546Spatrick     if (isType(dwarf_tag) && tag != DW_TAG_subrange_type)
3155061da546Spatrick       ParseType(sc, die, &type_is_new);
3156061da546Spatrick 
3157061da546Spatrick     if (type_is_new)
3158061da546Spatrick       ++types_added;
3159061da546Spatrick 
3160061da546Spatrick     if (parse_children && die.HasChildren()) {
3161061da546Spatrick       if (die.Tag() == DW_TAG_subprogram) {
3162061da546Spatrick         SymbolContext child_sc(sc);
3163061da546Spatrick         child_sc.function = sc.comp_unit->FindFunctionByUID(die.GetID()).get();
3164061da546Spatrick         types_added += ParseTypes(child_sc, die.GetFirstChild(), true, true);
3165061da546Spatrick       } else
3166061da546Spatrick         types_added += ParseTypes(sc, die.GetFirstChild(), true, true);
3167061da546Spatrick     }
3168061da546Spatrick 
3169061da546Spatrick     if (parse_siblings)
3170061da546Spatrick       die = die.GetSibling();
3171061da546Spatrick     else
3172061da546Spatrick       die.Clear();
3173061da546Spatrick   }
3174061da546Spatrick   return types_added;
3175061da546Spatrick }
3176061da546Spatrick 
ParseBlocksRecursive(Function & func)3177061da546Spatrick size_t SymbolFileDWARF::ParseBlocksRecursive(Function &func) {
3178061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
3179061da546Spatrick   CompileUnit *comp_unit = func.GetCompileUnit();
3180061da546Spatrick   lldbassert(comp_unit);
3181061da546Spatrick 
3182061da546Spatrick   DWARFUnit *dwarf_cu = GetDWARFCompileUnit(comp_unit);
3183061da546Spatrick   if (!dwarf_cu)
3184061da546Spatrick     return 0;
3185061da546Spatrick 
3186061da546Spatrick   size_t functions_added = 0;
3187061da546Spatrick   const dw_offset_t function_die_offset = func.GetID();
3188dda28197Spatrick   DWARFDIE function_die =
3189dda28197Spatrick       dwarf_cu->GetNonSkeletonUnit().GetDIE(function_die_offset);
3190061da546Spatrick   if (function_die) {
3191061da546Spatrick     ParseBlocksRecursive(*comp_unit, &func.GetBlock(false), function_die,
3192061da546Spatrick                          LLDB_INVALID_ADDRESS, 0);
3193061da546Spatrick   }
3194061da546Spatrick 
3195061da546Spatrick   return functions_added;
3196061da546Spatrick }
3197061da546Spatrick 
ParseTypes(CompileUnit & comp_unit)3198061da546Spatrick size_t SymbolFileDWARF::ParseTypes(CompileUnit &comp_unit) {
3199061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
3200061da546Spatrick   size_t types_added = 0;
3201061da546Spatrick   DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
3202061da546Spatrick   if (dwarf_cu) {
3203061da546Spatrick     DWARFDIE dwarf_cu_die = dwarf_cu->DIE();
3204061da546Spatrick     if (dwarf_cu_die && dwarf_cu_die.HasChildren()) {
3205061da546Spatrick       SymbolContext sc;
3206061da546Spatrick       sc.comp_unit = &comp_unit;
3207061da546Spatrick       types_added = ParseTypes(sc, dwarf_cu_die.GetFirstChild(), true, true);
3208061da546Spatrick     }
3209061da546Spatrick   }
3210061da546Spatrick 
3211061da546Spatrick   return types_added;
3212061da546Spatrick }
3213061da546Spatrick 
ParseVariablesForContext(const SymbolContext & sc)3214061da546Spatrick size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) {
3215061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
3216061da546Spatrick   if (sc.comp_unit != nullptr) {
3217061da546Spatrick     if (sc.function) {
3218061da546Spatrick       DWARFDIE function_die = GetDIE(sc.function->GetID());
3219061da546Spatrick 
3220be691f3bSpatrick       dw_addr_t func_lo_pc = LLDB_INVALID_ADDRESS;
3221be691f3bSpatrick       DWARFRangeList ranges;
3222be691f3bSpatrick       if (function_die.GetDIE()->GetAttributeAddressRanges(
3223be691f3bSpatrick               function_die.GetCU(), ranges,
3224be691f3bSpatrick               /*check_hi_lo_pc=*/true))
3225be691f3bSpatrick         func_lo_pc = ranges.GetMinRangeBase(0);
3226061da546Spatrick       if (func_lo_pc != LLDB_INVALID_ADDRESS) {
3227*f6aab3d8Srobert         const size_t num_variables =
3228*f6aab3d8Srobert             ParseVariablesInFunctionContext(sc, function_die, func_lo_pc);
3229061da546Spatrick 
3230061da546Spatrick         // Let all blocks know they have parse all their variables
3231061da546Spatrick         sc.function->GetBlock(false).SetDidParseVariables(true, true);
3232061da546Spatrick         return num_variables;
3233061da546Spatrick       }
3234061da546Spatrick     } else if (sc.comp_unit) {
3235dda28197Spatrick       DWARFUnit *dwarf_cu = DebugInfo().GetUnitAtIndex(sc.comp_unit->GetID());
3236061da546Spatrick 
3237061da546Spatrick       if (dwarf_cu == nullptr)
3238061da546Spatrick         return 0;
3239061da546Spatrick 
3240061da546Spatrick       uint32_t vars_added = 0;
3241061da546Spatrick       VariableListSP variables(sc.comp_unit->GetVariableList(false));
3242061da546Spatrick 
3243061da546Spatrick       if (variables.get() == nullptr) {
3244061da546Spatrick         variables = std::make_shared<VariableList>();
3245061da546Spatrick         sc.comp_unit->SetVariableList(variables);
3246061da546Spatrick 
3247*f6aab3d8Srobert         m_index->GetGlobalVariables(*dwarf_cu, [&](DWARFDIE die) {
3248*f6aab3d8Srobert           VariableSP var_sp(ParseVariableDIECached(sc, die));
3249061da546Spatrick           if (var_sp) {
3250061da546Spatrick             variables->AddVariableIfUnique(var_sp);
3251061da546Spatrick             ++vars_added;
3252061da546Spatrick           }
3253dda28197Spatrick           return true;
3254dda28197Spatrick         });
3255061da546Spatrick       }
3256061da546Spatrick       return vars_added;
3257061da546Spatrick     }
3258061da546Spatrick   }
3259061da546Spatrick   return 0;
3260061da546Spatrick }
3261061da546Spatrick 
ParseVariableDIECached(const SymbolContext & sc,const DWARFDIE & die)3262*f6aab3d8Srobert VariableSP SymbolFileDWARF::ParseVariableDIECached(const SymbolContext &sc,
3263*f6aab3d8Srobert                                                    const DWARFDIE &die) {
3264*f6aab3d8Srobert   if (!die)
3265*f6aab3d8Srobert     return nullptr;
3266*f6aab3d8Srobert 
3267*f6aab3d8Srobert   DIEToVariableSP &die_to_variable = die.GetDWARF()->GetDIEToVariable();
3268*f6aab3d8Srobert 
3269*f6aab3d8Srobert   VariableSP var_sp = die_to_variable[die.GetDIE()];
3270*f6aab3d8Srobert   if (var_sp)
3271*f6aab3d8Srobert     return var_sp;
3272*f6aab3d8Srobert 
3273*f6aab3d8Srobert   var_sp = ParseVariableDIE(sc, die, LLDB_INVALID_ADDRESS);
3274*f6aab3d8Srobert   if (var_sp) {
3275*f6aab3d8Srobert     die_to_variable[die.GetDIE()] = var_sp;
3276*f6aab3d8Srobert     if (DWARFDIE spec_die = die.GetReferencedDIE(DW_AT_specification))
3277*f6aab3d8Srobert       die_to_variable[spec_die.GetDIE()] = var_sp;
3278*f6aab3d8Srobert   }
3279*f6aab3d8Srobert   return var_sp;
3280*f6aab3d8Srobert }
3281*f6aab3d8Srobert 
ParseVariableDIE(const SymbolContext & sc,const DWARFDIE & die,const lldb::addr_t func_low_pc)3282061da546Spatrick VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
3283061da546Spatrick                                              const DWARFDIE &die,
3284061da546Spatrick                                              const lldb::addr_t func_low_pc) {
3285061da546Spatrick   if (die.GetDWARF() != this)
3286061da546Spatrick     return die.GetDWARF()->ParseVariableDIE(sc, die, func_low_pc);
3287061da546Spatrick 
3288061da546Spatrick   if (!die)
3289be691f3bSpatrick     return nullptr;
3290061da546Spatrick 
3291061da546Spatrick   const dw_tag_t tag = die.Tag();
3292061da546Spatrick   ModuleSP module = GetObjectFile()->GetModule();
3293061da546Spatrick 
3294be691f3bSpatrick   if (tag != DW_TAG_variable && tag != DW_TAG_constant &&
3295be691f3bSpatrick       (tag != DW_TAG_formal_parameter || !sc.function))
3296be691f3bSpatrick     return nullptr;
3297be691f3bSpatrick 
3298061da546Spatrick   DWARFAttributes attributes;
3299061da546Spatrick   const size_t num_attributes = die.GetAttributes(attributes);
3300061da546Spatrick   const char *name = nullptr;
3301061da546Spatrick   const char *mangled = nullptr;
3302061da546Spatrick   Declaration decl;
3303061da546Spatrick   DWARFFormValue type_die_form;
3304*f6aab3d8Srobert   DWARFExpressionList location_list(module, DWARFExpression(), die.GetCU());
3305061da546Spatrick   bool is_external = false;
3306061da546Spatrick   bool is_artificial = false;
3307be691f3bSpatrick   DWARFFormValue const_value_form, location_form;
3308061da546Spatrick   Variable::RangeList scope_ranges;
3309061da546Spatrick 
3310be691f3bSpatrick   for (size_t i = 0; i < num_attributes; ++i) {
3311061da546Spatrick     dw_attr_t attr = attributes.AttributeAtIndex(i);
3312061da546Spatrick     DWARFFormValue form_value;
3313061da546Spatrick 
3314be691f3bSpatrick     if (!attributes.ExtractFormValueAtIndex(i, form_value))
3315be691f3bSpatrick       continue;
3316061da546Spatrick     switch (attr) {
3317061da546Spatrick     case DW_AT_decl_file:
3318be691f3bSpatrick       decl.SetFile(
3319be691f3bSpatrick           attributes.CompileUnitAtIndex(i)->GetFile(form_value.Unsigned()));
3320061da546Spatrick       break;
3321061da546Spatrick     case DW_AT_decl_line:
3322061da546Spatrick       decl.SetLine(form_value.Unsigned());
3323061da546Spatrick       break;
3324061da546Spatrick     case DW_AT_decl_column:
3325061da546Spatrick       decl.SetColumn(form_value.Unsigned());
3326061da546Spatrick       break;
3327061da546Spatrick     case DW_AT_name:
3328061da546Spatrick       name = form_value.AsCString();
3329061da546Spatrick       break;
3330061da546Spatrick     case DW_AT_linkage_name:
3331061da546Spatrick     case DW_AT_MIPS_linkage_name:
3332061da546Spatrick       mangled = form_value.AsCString();
3333061da546Spatrick       break;
3334061da546Spatrick     case DW_AT_type:
3335061da546Spatrick       type_die_form = form_value;
3336061da546Spatrick       break;
3337061da546Spatrick     case DW_AT_external:
3338061da546Spatrick       is_external = form_value.Boolean();
3339061da546Spatrick       break;
3340061da546Spatrick     case DW_AT_const_value:
3341be691f3bSpatrick       const_value_form = form_value;
3342061da546Spatrick       break;
3343be691f3bSpatrick     case DW_AT_location:
3344be691f3bSpatrick       location_form = form_value;
3345be691f3bSpatrick       break;
3346061da546Spatrick     case DW_AT_start_scope:
3347061da546Spatrick       // TODO: Implement this.
3348061da546Spatrick       break;
3349061da546Spatrick     case DW_AT_artificial:
3350061da546Spatrick       is_artificial = form_value.Boolean();
3351061da546Spatrick       break;
3352061da546Spatrick     case DW_AT_declaration:
3353061da546Spatrick     case DW_AT_description:
3354061da546Spatrick     case DW_AT_endianity:
3355061da546Spatrick     case DW_AT_segment:
3356*f6aab3d8Srobert     case DW_AT_specification:
3357061da546Spatrick     case DW_AT_visibility:
3358061da546Spatrick     default:
3359061da546Spatrick     case DW_AT_abstract_origin:
3360061da546Spatrick     case DW_AT_sibling:
3361061da546Spatrick       break;
3362061da546Spatrick     }
3363061da546Spatrick   }
3364be691f3bSpatrick 
3365be691f3bSpatrick   // Prefer DW_AT_location over DW_AT_const_value. Both can be emitted e.g.
3366be691f3bSpatrick   // for static constexpr member variables -- DW_AT_const_value will be
3367be691f3bSpatrick   // present in the class declaration and DW_AT_location in the DIE defining
3368be691f3bSpatrick   // the member.
3369be691f3bSpatrick   bool location_is_const_value_data = false;
3370*f6aab3d8Srobert   bool has_explicit_location = location_form.IsValid();
3371be691f3bSpatrick   bool use_type_size_for_value = false;
3372be691f3bSpatrick   if (location_form.IsValid()) {
3373be691f3bSpatrick     if (DWARFFormValue::IsBlockForm(location_form.Form())) {
3374be691f3bSpatrick       const DWARFDataExtractor &data = die.GetData();
3375be691f3bSpatrick 
3376be691f3bSpatrick       uint32_t block_offset = location_form.BlockData() - data.GetDataStart();
3377be691f3bSpatrick       uint32_t block_length = location_form.Unsigned();
3378*f6aab3d8Srobert       location_list = DWARFExpressionList(
3379be691f3bSpatrick           module, DataExtractor(data, block_offset, block_length), die.GetCU());
3380be691f3bSpatrick     } else {
3381be691f3bSpatrick       DataExtractor data = die.GetCU()->GetLocationData();
3382be691f3bSpatrick       dw_offset_t offset = location_form.Unsigned();
3383be691f3bSpatrick       if (location_form.Form() == DW_FORM_loclistx)
3384*f6aab3d8Srobert         offset = die.GetCU()->GetLoclistOffset(offset).value_or(-1);
3385be691f3bSpatrick       if (data.ValidOffset(offset)) {
3386be691f3bSpatrick         data = DataExtractor(data, offset, data.GetByteSize() - offset);
3387*f6aab3d8Srobert         const DWARFUnit *dwarf_cu = location_form.GetUnit();
3388*f6aab3d8Srobert         if (DWARFExpression::ParseDWARFLocationList(dwarf_cu, data,
3389*f6aab3d8Srobert                                                     &location_list))
3390*f6aab3d8Srobert           location_list.SetFuncFileAddress(func_low_pc);
3391be691f3bSpatrick       }
3392be691f3bSpatrick     }
3393be691f3bSpatrick   } else if (const_value_form.IsValid()) {
3394be691f3bSpatrick     location_is_const_value_data = true;
3395be691f3bSpatrick     // The constant value will be either a block, a data value or a
3396be691f3bSpatrick     // string.
3397be691f3bSpatrick     const DWARFDataExtractor &debug_info_data = die.GetData();
3398be691f3bSpatrick     if (DWARFFormValue::IsBlockForm(const_value_form.Form())) {
3399be691f3bSpatrick       // Retrieve the value as a block expression.
3400be691f3bSpatrick       uint32_t block_offset =
3401be691f3bSpatrick           const_value_form.BlockData() - debug_info_data.GetDataStart();
3402be691f3bSpatrick       uint32_t block_length = const_value_form.Unsigned();
3403*f6aab3d8Srobert       location_list = DWARFExpressionList(
3404be691f3bSpatrick           module, DataExtractor(debug_info_data, block_offset, block_length),
3405be691f3bSpatrick           die.GetCU());
3406be691f3bSpatrick     } else if (DWARFFormValue::IsDataForm(const_value_form.Form())) {
3407be691f3bSpatrick       // Constant value size does not have to match the size of the
3408be691f3bSpatrick       // variable. We will fetch the size of the type after we create
3409be691f3bSpatrick       // it.
3410be691f3bSpatrick       use_type_size_for_value = true;
3411be691f3bSpatrick     } else if (const char *str = const_value_form.AsCString()) {
3412be691f3bSpatrick       uint32_t string_length = strlen(str) + 1;
3413*f6aab3d8Srobert       location_list = DWARFExpressionList(
3414be691f3bSpatrick           module,
3415be691f3bSpatrick           DataExtractor(str, string_length, die.GetCU()->GetByteOrder(),
3416be691f3bSpatrick                         die.GetCU()->GetAddressByteSize()),
3417be691f3bSpatrick           die.GetCU());
3418be691f3bSpatrick     }
3419061da546Spatrick   }
3420061da546Spatrick 
3421061da546Spatrick   const DWARFDIE parent_context_die = GetDeclContextDIEContainingDIE(die);
3422*f6aab3d8Srobert   const DWARFDIE sc_parent_die = GetParentSymbolContextDIE(die);
3423*f6aab3d8Srobert   const dw_tag_t parent_tag = sc_parent_die.Tag();
3424be691f3bSpatrick   bool is_static_member = (parent_tag == DW_TAG_compile_unit ||
3425061da546Spatrick                            parent_tag == DW_TAG_partial_unit) &&
3426061da546Spatrick                           (parent_context_die.Tag() == DW_TAG_class_type ||
3427061da546Spatrick                            parent_context_die.Tag() == DW_TAG_structure_type);
3428061da546Spatrick 
3429061da546Spatrick   ValueType scope = eValueTypeInvalid;
3430061da546Spatrick   SymbolContextScope *symbol_context_scope = nullptr;
3431061da546Spatrick 
3432061da546Spatrick   bool has_explicit_mangled = mangled != nullptr;
3433061da546Spatrick   if (!mangled) {
3434061da546Spatrick     // LLDB relies on the mangled name (DW_TAG_linkage_name or
3435061da546Spatrick     // DW_AT_MIPS_linkage_name) to generate fully qualified names
3436061da546Spatrick     // of global variables with commands like "frame var j". For
3437061da546Spatrick     // example, if j were an int variable holding a value 4 and
3438061da546Spatrick     // declared in a namespace B which in turn is contained in a
3439061da546Spatrick     // namespace A, the command "frame var j" returns
3440061da546Spatrick     //   "(int) A::B::j = 4".
3441061da546Spatrick     // If the compiler does not emit a linkage name, we should be
3442061da546Spatrick     // able to generate a fully qualified name from the
3443061da546Spatrick     // declaration context.
3444061da546Spatrick     if ((parent_tag == DW_TAG_compile_unit ||
3445061da546Spatrick          parent_tag == DW_TAG_partial_unit) &&
3446dda28197Spatrick         Language::LanguageIsCPlusPlus(GetLanguage(*die.GetCU())))
3447be691f3bSpatrick       mangled =
3448be691f3bSpatrick           GetDWARFDeclContext(die).GetQualifiedNameAsConstString().GetCString();
3449061da546Spatrick   }
3450061da546Spatrick 
3451061da546Spatrick   if (tag == DW_TAG_formal_parameter)
3452061da546Spatrick     scope = eValueTypeVariableArgument;
3453061da546Spatrick   else {
3454061da546Spatrick     // DWARF doesn't specify if a DW_TAG_variable is a local, global
3455061da546Spatrick     // or static variable, so we have to do a little digging:
3456061da546Spatrick     // 1) DW_AT_linkage_name implies static lifetime (but may be missing)
3457061da546Spatrick     // 2) An empty DW_AT_location is an (optimized-out) static lifetime var.
3458061da546Spatrick     // 3) DW_AT_location containing a DW_OP_addr implies static lifetime.
3459061da546Spatrick     // Clang likes to combine small global variables into the same symbol
3460061da546Spatrick     // with locations like: DW_OP_addr(0x1000), DW_OP_constu(2), DW_OP_plus
3461061da546Spatrick     // so we need to look through the whole expression.
3462061da546Spatrick     bool is_static_lifetime =
3463*f6aab3d8Srobert         has_explicit_mangled ||
3464*f6aab3d8Srobert         (has_explicit_location && !location_list.IsValid());
3465061da546Spatrick     // Check if the location has a DW_OP_addr with any address value...
3466061da546Spatrick     lldb::addr_t location_DW_OP_addr = LLDB_INVALID_ADDRESS;
3467061da546Spatrick     if (!location_is_const_value_data) {
3468061da546Spatrick       bool op_error = false;
3469*f6aab3d8Srobert       const DWARFExpression* location = location_list.GetAlwaysValidExpr();
3470*f6aab3d8Srobert       if (location)
3471*f6aab3d8Srobert         location_DW_OP_addr = location->GetLocation_DW_OP_addr(
3472*f6aab3d8Srobert             location_form.GetUnit(), 0, op_error);
3473061da546Spatrick       if (op_error) {
3474061da546Spatrick         StreamString strm;
3475*f6aab3d8Srobert         location->DumpLocation(&strm, eDescriptionLevelFull, nullptr);
3476061da546Spatrick         GetObjectFile()->GetModule()->ReportError(
3477*f6aab3d8Srobert             "{0:x16}: {1} has an invalid location: {2}", die.GetOffset(),
3478061da546Spatrick             die.GetTagAsCString(), strm.GetData());
3479061da546Spatrick       }
3480061da546Spatrick       if (location_DW_OP_addr != LLDB_INVALID_ADDRESS)
3481061da546Spatrick         is_static_lifetime = true;
3482061da546Spatrick     }
3483061da546Spatrick     SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
3484061da546Spatrick     if (debug_map_symfile)
3485061da546Spatrick       // Set the module of the expression to the linked module
3486*f6aab3d8Srobert       // instead of the object file so the relocated address can be
3487061da546Spatrick       // found there.
3488*f6aab3d8Srobert       location_list.SetModule(debug_map_symfile->GetObjectFile()->GetModule());
3489061da546Spatrick 
3490061da546Spatrick     if (is_static_lifetime) {
3491061da546Spatrick       if (is_external)
3492061da546Spatrick         scope = eValueTypeVariableGlobal;
3493061da546Spatrick       else
3494061da546Spatrick         scope = eValueTypeVariableStatic;
3495061da546Spatrick 
3496061da546Spatrick       if (debug_map_symfile) {
3497061da546Spatrick         // When leaving the DWARF in the .o files on darwin, when we have a
3498061da546Spatrick         // global variable that wasn't initialized, the .o file might not
3499061da546Spatrick         // have allocated a virtual address for the global variable. In
3500061da546Spatrick         // this case it will have created a symbol for the global variable
3501061da546Spatrick         // that is undefined/data and external and the value will be the
3502061da546Spatrick         // byte size of the variable. When we do the address map in
3503061da546Spatrick         // SymbolFileDWARFDebugMap we rely on having an address, we need to
3504061da546Spatrick         // do some magic here so we can get the correct address for our
3505061da546Spatrick         // global variable. The address for all of these entries will be
3506061da546Spatrick         // zero, and there will be an undefined symbol in this object file,
3507061da546Spatrick         // and the executable will have a matching symbol with a good
3508061da546Spatrick         // address. So here we dig up the correct address and replace it in
3509061da546Spatrick         // the location for the variable, and set the variable's symbol
3510061da546Spatrick         // context scope to be that of the main executable so the file
3511061da546Spatrick         // address will resolve correctly.
3512061da546Spatrick         bool linked_oso_file_addr = false;
3513061da546Spatrick         if (is_external && location_DW_OP_addr == 0) {
3514061da546Spatrick           // we have a possible uninitialized extern global
3515061da546Spatrick           ConstString const_name(mangled ? mangled : name);
3516be691f3bSpatrick           ObjectFile *debug_map_objfile = debug_map_symfile->GetObjectFile();
3517061da546Spatrick           if (debug_map_objfile) {
3518061da546Spatrick             Symtab *debug_map_symtab = debug_map_objfile->GetSymtab();
3519061da546Spatrick             if (debug_map_symtab) {
3520061da546Spatrick               Symbol *exe_symbol =
3521061da546Spatrick                   debug_map_symtab->FindFirstSymbolWithNameAndType(
3522061da546Spatrick                       const_name, eSymbolTypeData, Symtab::eDebugYes,
3523061da546Spatrick                       Symtab::eVisibilityExtern);
3524061da546Spatrick               if (exe_symbol) {
3525061da546Spatrick                 if (exe_symbol->ValueIsAddress()) {
3526061da546Spatrick                   const addr_t exe_file_addr =
3527061da546Spatrick                       exe_symbol->GetAddressRef().GetFileAddress();
3528061da546Spatrick                   if (exe_file_addr != LLDB_INVALID_ADDRESS) {
3529*f6aab3d8Srobert                     DWARFExpression *location =
3530*f6aab3d8Srobert                         location_list.GetMutableExpressionAtAddress();
3531*f6aab3d8Srobert                     if (location->Update_DW_OP_addr(die.GetCU(),
3532*f6aab3d8Srobert                                                     exe_file_addr)) {
3533061da546Spatrick                       linked_oso_file_addr = true;
3534061da546Spatrick                       symbol_context_scope = exe_symbol;
3535061da546Spatrick                     }
3536061da546Spatrick                   }
3537061da546Spatrick                 }
3538061da546Spatrick               }
3539061da546Spatrick             }
3540061da546Spatrick           }
3541061da546Spatrick         }
3542061da546Spatrick 
3543061da546Spatrick         if (!linked_oso_file_addr) {
3544061da546Spatrick           // The DW_OP_addr is not zero, but it contains a .o file address
3545061da546Spatrick           // which needs to be linked up correctly.
3546061da546Spatrick           const lldb::addr_t exe_file_addr =
3547be691f3bSpatrick               debug_map_symfile->LinkOSOFileAddress(this, location_DW_OP_addr);
3548061da546Spatrick           if (exe_file_addr != LLDB_INVALID_ADDRESS) {
3549061da546Spatrick             // Update the file address for this variable
3550*f6aab3d8Srobert             DWARFExpression *location =
3551*f6aab3d8Srobert                 location_list.GetMutableExpressionAtAddress();
3552*f6aab3d8Srobert             location->Update_DW_OP_addr(die.GetCU(), exe_file_addr);
3553061da546Spatrick           } else {
3554061da546Spatrick             // Variable didn't make it into the final executable
3555*f6aab3d8Srobert             return nullptr;
3556061da546Spatrick           }
3557061da546Spatrick         }
3558061da546Spatrick       }
3559061da546Spatrick     } else {
3560dda28197Spatrick       if (location_is_const_value_data &&
3561dda28197Spatrick           die.GetDIE()->IsGlobalOrStaticScopeVariable())
3562061da546Spatrick         scope = eValueTypeVariableStatic;
3563061da546Spatrick       else {
3564061da546Spatrick         scope = eValueTypeVariableLocal;
3565061da546Spatrick         if (debug_map_symfile) {
3566061da546Spatrick           // We need to check for TLS addresses that we need to fixup
3567*f6aab3d8Srobert           if (location_list.ContainsThreadLocalStorage()) {
3568*f6aab3d8Srobert             location_list.LinkThreadLocalStorage(
3569061da546Spatrick                 debug_map_symfile->GetObjectFile()->GetModule(),
3570061da546Spatrick                 [this, debug_map_symfile](
3571061da546Spatrick                     lldb::addr_t unlinked_file_addr) -> lldb::addr_t {
3572061da546Spatrick                   return debug_map_symfile->LinkOSOFileAddress(
3573061da546Spatrick                       this, unlinked_file_addr);
3574061da546Spatrick                 });
3575061da546Spatrick             scope = eValueTypeVariableThreadLocal;
3576061da546Spatrick           }
3577061da546Spatrick         }
3578061da546Spatrick       }
3579061da546Spatrick     }
3580061da546Spatrick   }
3581061da546Spatrick 
3582061da546Spatrick   if (symbol_context_scope == nullptr) {
3583061da546Spatrick     switch (parent_tag) {
3584061da546Spatrick     case DW_TAG_subprogram:
3585061da546Spatrick     case DW_TAG_inlined_subroutine:
3586061da546Spatrick     case DW_TAG_lexical_block:
3587061da546Spatrick       if (sc.function) {
3588be691f3bSpatrick         symbol_context_scope =
3589be691f3bSpatrick             sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID());
3590061da546Spatrick         if (symbol_context_scope == nullptr)
3591061da546Spatrick           symbol_context_scope = sc.function;
3592061da546Spatrick       }
3593061da546Spatrick       break;
3594061da546Spatrick 
3595061da546Spatrick     default:
3596061da546Spatrick       symbol_context_scope = sc.comp_unit;
3597061da546Spatrick       break;
3598061da546Spatrick     }
3599061da546Spatrick   }
3600061da546Spatrick 
3601*f6aab3d8Srobert   if (!symbol_context_scope) {
3602061da546Spatrick     // Not ready to parse this variable yet. It might be a global or static
3603061da546Spatrick     // variable that is in a function scope and the function in the symbol
3604061da546Spatrick     // context wasn't filled in yet
3605*f6aab3d8Srobert     return nullptr;
3606061da546Spatrick   }
3607be691f3bSpatrick 
3608*f6aab3d8Srobert   auto type_sp = std::make_shared<SymbolFileType>(
3609*f6aab3d8Srobert       *this, GetUID(type_die_form.Reference()));
3610*f6aab3d8Srobert 
3611*f6aab3d8Srobert   if (use_type_size_for_value && type_sp->GetType()) {
3612*f6aab3d8Srobert     DWARFExpression *location = location_list.GetMutableExpressionAtAddress();
3613*f6aab3d8Srobert     location->UpdateValue(const_value_form.Unsigned(),
3614*f6aab3d8Srobert                           type_sp->GetType()->GetByteSize(nullptr).value_or(0),
3615*f6aab3d8Srobert                           die.GetCU()->GetAddressByteSize());
3616*f6aab3d8Srobert   }
3617*f6aab3d8Srobert 
3618*f6aab3d8Srobert   return std::make_shared<Variable>(
3619*f6aab3d8Srobert       die.GetID(), name, mangled, type_sp, scope, symbol_context_scope,
3620*f6aab3d8Srobert       scope_ranges, &decl, location_list, is_external, is_artificial,
3621*f6aab3d8Srobert       location_is_const_value_data, is_static_member);
3622061da546Spatrick }
3623061da546Spatrick 
3624061da546Spatrick DWARFDIE
FindBlockContainingSpecification(const DIERef & func_die_ref,dw_offset_t spec_block_die_offset)3625061da546Spatrick SymbolFileDWARF::FindBlockContainingSpecification(
3626061da546Spatrick     const DIERef &func_die_ref, dw_offset_t spec_block_die_offset) {
3627061da546Spatrick   // Give the concrete function die specified by "func_die_offset", find the
3628061da546Spatrick   // concrete block whose DW_AT_specification or DW_AT_abstract_origin points
3629061da546Spatrick   // to "spec_block_die_offset"
3630dda28197Spatrick   return FindBlockContainingSpecification(DebugInfo().GetDIE(func_die_ref),
3631061da546Spatrick                                           spec_block_die_offset);
3632061da546Spatrick }
3633061da546Spatrick 
3634061da546Spatrick DWARFDIE
FindBlockContainingSpecification(const DWARFDIE & die,dw_offset_t spec_block_die_offset)3635061da546Spatrick SymbolFileDWARF::FindBlockContainingSpecification(
3636061da546Spatrick     const DWARFDIE &die, dw_offset_t spec_block_die_offset) {
3637061da546Spatrick   if (die) {
3638061da546Spatrick     switch (die.Tag()) {
3639061da546Spatrick     case DW_TAG_subprogram:
3640061da546Spatrick     case DW_TAG_inlined_subroutine:
3641061da546Spatrick     case DW_TAG_lexical_block: {
3642061da546Spatrick       if (die.GetReferencedDIE(DW_AT_specification).GetOffset() ==
3643061da546Spatrick           spec_block_die_offset)
3644061da546Spatrick         return die;
3645061da546Spatrick 
3646061da546Spatrick       if (die.GetReferencedDIE(DW_AT_abstract_origin).GetOffset() ==
3647061da546Spatrick           spec_block_die_offset)
3648061da546Spatrick         return die;
3649061da546Spatrick     } break;
3650061da546Spatrick     default:
3651061da546Spatrick       break;
3652061da546Spatrick     }
3653061da546Spatrick 
3654061da546Spatrick     // Give the concrete function die specified by "func_die_offset", find the
3655061da546Spatrick     // concrete block whose DW_AT_specification or DW_AT_abstract_origin points
3656061da546Spatrick     // to "spec_block_die_offset"
3657be691f3bSpatrick     for (DWARFDIE child_die : die.children()) {
3658061da546Spatrick       DWARFDIE result_die =
3659061da546Spatrick           FindBlockContainingSpecification(child_die, spec_block_die_offset);
3660061da546Spatrick       if (result_die)
3661061da546Spatrick         return result_die;
3662061da546Spatrick     }
3663061da546Spatrick   }
3664061da546Spatrick 
3665061da546Spatrick   return DWARFDIE();
3666061da546Spatrick }
3667061da546Spatrick 
ParseAndAppendGlobalVariable(const SymbolContext & sc,const DWARFDIE & die,VariableList & cc_variable_list)3668*f6aab3d8Srobert void SymbolFileDWARF::ParseAndAppendGlobalVariable(
3669*f6aab3d8Srobert     const SymbolContext &sc, const DWARFDIE &die,
3670*f6aab3d8Srobert     VariableList &cc_variable_list) {
3671*f6aab3d8Srobert   if (!die)
3672*f6aab3d8Srobert     return;
3673061da546Spatrick 
3674061da546Spatrick   dw_tag_t tag = die.Tag();
3675*f6aab3d8Srobert   if (tag != DW_TAG_variable && tag != DW_TAG_constant)
3676*f6aab3d8Srobert     return;
3677061da546Spatrick 
3678061da546Spatrick   // Check to see if we have already parsed this variable or constant?
3679061da546Spatrick   VariableSP var_sp = GetDIEToVariable()[die.GetDIE()];
3680061da546Spatrick   if (var_sp) {
3681*f6aab3d8Srobert     cc_variable_list.AddVariableIfUnique(var_sp);
3682*f6aab3d8Srobert     return;
3683*f6aab3d8Srobert   }
3684*f6aab3d8Srobert 
3685*f6aab3d8Srobert   // We haven't parsed the variable yet, lets do that now. Also, let us include
3686*f6aab3d8Srobert   // the variable in the relevant compilation unit's variable list, if it
3687*f6aab3d8Srobert   // exists.
3688*f6aab3d8Srobert   VariableListSP variable_list_sp;
3689*f6aab3d8Srobert   DWARFDIE sc_parent_die = GetParentSymbolContextDIE(die);
3690061da546Spatrick   dw_tag_t parent_tag = sc_parent_die.Tag();
3691061da546Spatrick   switch (parent_tag) {
3692061da546Spatrick   case DW_TAG_compile_unit:
3693061da546Spatrick   case DW_TAG_partial_unit:
3694061da546Spatrick     if (sc.comp_unit != nullptr) {
3695061da546Spatrick       variable_list_sp = sc.comp_unit->GetVariableList(false);
3696061da546Spatrick     } else {
3697061da546Spatrick       GetObjectFile()->GetModule()->ReportError(
3698*f6aab3d8Srobert           "parent {0:x8} {1} with no valid compile unit in "
3699*f6aab3d8Srobert           "symbol context for {2:x8} {3}.\n",
3700*f6aab3d8Srobert           sc_parent_die.GetID(), sc_parent_die.GetTagAsCString(), die.GetID(),
3701*f6aab3d8Srobert           die.GetTagAsCString());
3702*f6aab3d8Srobert       return;
3703061da546Spatrick     }
3704061da546Spatrick     break;
3705061da546Spatrick 
3706061da546Spatrick   default:
3707061da546Spatrick     GetObjectFile()->GetModule()->ReportError(
3708*f6aab3d8Srobert         "didn't find appropriate parent DIE for variable list for {0:x8} "
3709*f6aab3d8Srobert         "{1}.\n",
3710*f6aab3d8Srobert         die.GetID(), die.GetTagAsCString());
3711*f6aab3d8Srobert     return;
3712*f6aab3d8Srobert   }
3713*f6aab3d8Srobert 
3714*f6aab3d8Srobert   var_sp = ParseVariableDIECached(sc, die);
3715*f6aab3d8Srobert   if (!var_sp)
3716*f6aab3d8Srobert     return;
3717*f6aab3d8Srobert 
3718*f6aab3d8Srobert   cc_variable_list.AddVariableIfUnique(var_sp);
3719*f6aab3d8Srobert   if (variable_list_sp)
3720*f6aab3d8Srobert     variable_list_sp->AddVariableIfUnique(var_sp);
3721*f6aab3d8Srobert }
3722*f6aab3d8Srobert 
3723*f6aab3d8Srobert DIEArray
MergeBlockAbstractParameters(const DWARFDIE & block_die,DIEArray && variable_dies)3724*f6aab3d8Srobert SymbolFileDWARF::MergeBlockAbstractParameters(const DWARFDIE &block_die,
3725*f6aab3d8Srobert                                               DIEArray &&variable_dies) {
3726*f6aab3d8Srobert   // DW_TAG_inline_subroutine objects may omit DW_TAG_formal_parameter in
3727*f6aab3d8Srobert   // instances of the function when they are unused (i.e., the parameter's
3728*f6aab3d8Srobert   // location list would be empty). The current DW_TAG_inline_subroutine may
3729*f6aab3d8Srobert   // refer to another DW_TAG_subprogram that might actually have the definitions
3730*f6aab3d8Srobert   // of the parameters and we need to include these so they show up in the
3731*f6aab3d8Srobert   // variables for this function (for example, in a stack trace). Let us try to
3732*f6aab3d8Srobert   // find the abstract subprogram that might contain the parameter definitions
3733*f6aab3d8Srobert   // and merge with the concrete parameters.
3734*f6aab3d8Srobert 
3735*f6aab3d8Srobert   // Nothing to merge if the block is not an inlined function.
3736*f6aab3d8Srobert   if (block_die.Tag() != DW_TAG_inlined_subroutine) {
3737*f6aab3d8Srobert     return std::move(variable_dies);
3738*f6aab3d8Srobert   }
3739*f6aab3d8Srobert 
3740*f6aab3d8Srobert   // Nothing to merge if the block does not have abstract parameters.
3741*f6aab3d8Srobert   DWARFDIE abs_die = block_die.GetReferencedDIE(DW_AT_abstract_origin);
3742*f6aab3d8Srobert   if (!abs_die || abs_die.Tag() != DW_TAG_subprogram ||
3743*f6aab3d8Srobert       !abs_die.HasChildren()) {
3744*f6aab3d8Srobert     return std::move(variable_dies);
3745*f6aab3d8Srobert   }
3746*f6aab3d8Srobert 
3747*f6aab3d8Srobert   // For each abstract parameter, if we have its concrete counterpart, insert
3748*f6aab3d8Srobert   // it. Otherwise, insert the abstract parameter.
3749*f6aab3d8Srobert   DIEArray::iterator concrete_it = variable_dies.begin();
3750*f6aab3d8Srobert   DWARFDIE abstract_child = abs_die.GetFirstChild();
3751*f6aab3d8Srobert   DIEArray merged;
3752*f6aab3d8Srobert   bool did_merge_abstract = false;
3753*f6aab3d8Srobert   for (; abstract_child; abstract_child = abstract_child.GetSibling()) {
3754*f6aab3d8Srobert     if (abstract_child.Tag() == DW_TAG_formal_parameter) {
3755*f6aab3d8Srobert       if (concrete_it == variable_dies.end() ||
3756*f6aab3d8Srobert           GetDIE(*concrete_it).Tag() != DW_TAG_formal_parameter) {
3757*f6aab3d8Srobert         // We arrived at the end of the concrete parameter list, so all
3758*f6aab3d8Srobert         // the remaining abstract parameters must have been omitted.
3759*f6aab3d8Srobert         // Let us insert them to the merged list here.
3760*f6aab3d8Srobert         merged.push_back(*abstract_child.GetDIERef());
3761*f6aab3d8Srobert         did_merge_abstract = true;
3762*f6aab3d8Srobert         continue;
3763*f6aab3d8Srobert       }
3764*f6aab3d8Srobert 
3765*f6aab3d8Srobert       DWARFDIE origin_of_concrete =
3766*f6aab3d8Srobert           GetDIE(*concrete_it).GetReferencedDIE(DW_AT_abstract_origin);
3767*f6aab3d8Srobert       if (origin_of_concrete == abstract_child) {
3768*f6aab3d8Srobert         // The current abstract parameter is the origin of the current
3769*f6aab3d8Srobert         // concrete parameter, just push the concrete parameter.
3770*f6aab3d8Srobert         merged.push_back(*concrete_it);
3771*f6aab3d8Srobert         ++concrete_it;
3772*f6aab3d8Srobert       } else {
3773*f6aab3d8Srobert         // Otherwise, the parameter must have been omitted from the concrete
3774*f6aab3d8Srobert         // function, so insert the abstract one.
3775*f6aab3d8Srobert         merged.push_back(*abstract_child.GetDIERef());
3776*f6aab3d8Srobert         did_merge_abstract = true;
3777*f6aab3d8Srobert       }
3778*f6aab3d8Srobert     }
3779*f6aab3d8Srobert   }
3780*f6aab3d8Srobert 
3781*f6aab3d8Srobert   // Shortcut if no merging happened.
3782*f6aab3d8Srobert   if (!did_merge_abstract)
3783*f6aab3d8Srobert     return std::move(variable_dies);
3784*f6aab3d8Srobert 
3785*f6aab3d8Srobert   // We inserted all the abstract parameters (or their concrete counterparts).
3786*f6aab3d8Srobert   // Let us insert all the remaining concrete variables to the merged list.
3787*f6aab3d8Srobert   // During the insertion, let us check there are no remaining concrete
3788*f6aab3d8Srobert   // formal parameters. If that's the case, then just bailout from the merge -
3789*f6aab3d8Srobert   // the variable list is malformed.
3790*f6aab3d8Srobert   for (; concrete_it != variable_dies.end(); ++concrete_it) {
3791*f6aab3d8Srobert     if (GetDIE(*concrete_it).Tag() == DW_TAG_formal_parameter) {
3792*f6aab3d8Srobert       return std::move(variable_dies);
3793*f6aab3d8Srobert     }
3794*f6aab3d8Srobert     merged.push_back(*concrete_it);
3795*f6aab3d8Srobert   }
3796*f6aab3d8Srobert   return merged;
3797*f6aab3d8Srobert }
3798*f6aab3d8Srobert 
ParseVariablesInFunctionContext(const SymbolContext & sc,const DWARFDIE & die,const lldb::addr_t func_low_pc)3799*f6aab3d8Srobert size_t SymbolFileDWARF::ParseVariablesInFunctionContext(
3800*f6aab3d8Srobert     const SymbolContext &sc, const DWARFDIE &die,
3801*f6aab3d8Srobert     const lldb::addr_t func_low_pc) {
3802*f6aab3d8Srobert   if (!die || !sc.function)
3803*f6aab3d8Srobert     return 0;
3804*f6aab3d8Srobert 
3805*f6aab3d8Srobert   DIEArray dummy_block_variables; // The recursive call should not add anything
3806*f6aab3d8Srobert                                   // to this vector because |die| should be a
3807*f6aab3d8Srobert                                   // subprogram, so all variables will be added
3808*f6aab3d8Srobert                                   // to the subprogram's list.
3809*f6aab3d8Srobert   return ParseVariablesInFunctionContextRecursive(sc, die, func_low_pc,
3810*f6aab3d8Srobert                                                   dummy_block_variables);
3811*f6aab3d8Srobert }
3812*f6aab3d8Srobert 
3813*f6aab3d8Srobert // This method parses all the variables in the blocks in the subtree of |die|,
3814*f6aab3d8Srobert // and inserts them to the variable list for all the nested blocks.
3815*f6aab3d8Srobert // The uninserted variables for the current block are accumulated in
3816*f6aab3d8Srobert // |accumulator|.
ParseVariablesInFunctionContextRecursive(const lldb_private::SymbolContext & sc,const DWARFDIE & die,lldb::addr_t func_low_pc,DIEArray & accumulator)3817*f6aab3d8Srobert size_t SymbolFileDWARF::ParseVariablesInFunctionContextRecursive(
3818*f6aab3d8Srobert     const lldb_private::SymbolContext &sc, const DWARFDIE &die,
3819*f6aab3d8Srobert     lldb::addr_t func_low_pc, DIEArray &accumulator) {
3820*f6aab3d8Srobert   size_t vars_added = 0;
3821*f6aab3d8Srobert   dw_tag_t tag = die.Tag();
3822*f6aab3d8Srobert 
3823*f6aab3d8Srobert   if ((tag == DW_TAG_variable) || (tag == DW_TAG_constant) ||
3824*f6aab3d8Srobert       (tag == DW_TAG_formal_parameter)) {
3825*f6aab3d8Srobert     accumulator.push_back(*die.GetDIERef());
3826*f6aab3d8Srobert   }
3827*f6aab3d8Srobert 
3828*f6aab3d8Srobert   switch (tag) {
3829*f6aab3d8Srobert   case DW_TAG_subprogram:
3830*f6aab3d8Srobert   case DW_TAG_inlined_subroutine:
3831*f6aab3d8Srobert   case DW_TAG_lexical_block: {
3832*f6aab3d8Srobert     // If we start a new block, compute a new block variable list and recurse.
3833*f6aab3d8Srobert     Block *block =
3834*f6aab3d8Srobert         sc.function->GetBlock(/*can_create=*/true).FindBlockByID(die.GetID());
3835*f6aab3d8Srobert     if (block == nullptr) {
3836*f6aab3d8Srobert       // This must be a specification or abstract origin with a
3837*f6aab3d8Srobert       // concrete block counterpart in the current function. We need
3838*f6aab3d8Srobert       // to find the concrete block so we can correctly add the
3839*f6aab3d8Srobert       // variable to it.
3840*f6aab3d8Srobert       const DWARFDIE concrete_block_die = FindBlockContainingSpecification(
3841*f6aab3d8Srobert           GetDIE(sc.function->GetID()), die.GetOffset());
3842*f6aab3d8Srobert       if (concrete_block_die)
3843*f6aab3d8Srobert         block = sc.function->GetBlock(/*can_create=*/true)
3844*f6aab3d8Srobert                     .FindBlockByID(concrete_block_die.GetID());
3845*f6aab3d8Srobert     }
3846*f6aab3d8Srobert 
3847*f6aab3d8Srobert     if (block == nullptr)
3848*f6aab3d8Srobert       return 0;
3849*f6aab3d8Srobert 
3850*f6aab3d8Srobert     const bool can_create = false;
3851*f6aab3d8Srobert     VariableListSP block_variable_list_sp =
3852*f6aab3d8Srobert         block->GetBlockVariableList(can_create);
3853*f6aab3d8Srobert     if (block_variable_list_sp.get() == nullptr) {
3854*f6aab3d8Srobert       block_variable_list_sp = std::make_shared<VariableList>();
3855*f6aab3d8Srobert       block->SetVariableList(block_variable_list_sp);
3856*f6aab3d8Srobert     }
3857*f6aab3d8Srobert 
3858*f6aab3d8Srobert     DIEArray block_variables;
3859*f6aab3d8Srobert     for (DWARFDIE child = die.GetFirstChild(); child;
3860*f6aab3d8Srobert          child = child.GetSibling()) {
3861*f6aab3d8Srobert       vars_added += ParseVariablesInFunctionContextRecursive(
3862*f6aab3d8Srobert           sc, child, func_low_pc, block_variables);
3863*f6aab3d8Srobert     }
3864*f6aab3d8Srobert     block_variables =
3865*f6aab3d8Srobert         MergeBlockAbstractParameters(die, std::move(block_variables));
3866*f6aab3d8Srobert     vars_added += PopulateBlockVariableList(*block_variable_list_sp, sc,
3867*f6aab3d8Srobert                                             block_variables, func_low_pc);
3868061da546Spatrick     break;
3869061da546Spatrick   }
3870*f6aab3d8Srobert 
3871*f6aab3d8Srobert   default:
3872*f6aab3d8Srobert     // Recurse to children with the same variable accumulator.
3873*f6aab3d8Srobert     for (DWARFDIE child = die.GetFirstChild(); child;
3874*f6aab3d8Srobert          child = child.GetSibling()) {
3875*f6aab3d8Srobert       vars_added += ParseVariablesInFunctionContextRecursive(
3876*f6aab3d8Srobert           sc, child, func_low_pc, accumulator);
3877*f6aab3d8Srobert     }
3878*f6aab3d8Srobert     break;
3879061da546Spatrick   }
3880061da546Spatrick 
3881061da546Spatrick   return vars_added;
3882061da546Spatrick }
3883061da546Spatrick 
PopulateBlockVariableList(VariableList & variable_list,const lldb_private::SymbolContext & sc,llvm::ArrayRef<DIERef> variable_dies,lldb::addr_t func_low_pc)3884*f6aab3d8Srobert size_t SymbolFileDWARF::PopulateBlockVariableList(
3885*f6aab3d8Srobert     VariableList &variable_list, const lldb_private::SymbolContext &sc,
3886*f6aab3d8Srobert     llvm::ArrayRef<DIERef> variable_dies, lldb::addr_t func_low_pc) {
3887*f6aab3d8Srobert   // Parse the variable DIEs and insert them to the list.
3888*f6aab3d8Srobert   for (auto &die : variable_dies) {
3889*f6aab3d8Srobert     if (VariableSP var_sp = ParseVariableDIE(sc, GetDIE(die), func_low_pc)) {
3890*f6aab3d8Srobert       variable_list.AddVariableIfUnique(var_sp);
3891*f6aab3d8Srobert     }
3892*f6aab3d8Srobert   }
3893*f6aab3d8Srobert   return variable_dies.size();
3894*f6aab3d8Srobert }
3895*f6aab3d8Srobert 
3896061da546Spatrick /// Collect call site parameters in a DW_TAG_call_site DIE.
3897061da546Spatrick static CallSiteParameterArray
CollectCallSiteParameters(ModuleSP module,DWARFDIE call_site_die)3898061da546Spatrick CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) {
3899061da546Spatrick   CallSiteParameterArray parameters;
3900be691f3bSpatrick   for (DWARFDIE child : call_site_die.children()) {
3901dda28197Spatrick     if (child.Tag() != DW_TAG_call_site_parameter &&
3902dda28197Spatrick         child.Tag() != DW_TAG_GNU_call_site_parameter)
3903061da546Spatrick       continue;
3904061da546Spatrick 
3905*f6aab3d8Srobert     std::optional<DWARFExpressionList> LocationInCallee;
3906*f6aab3d8Srobert     std::optional<DWARFExpressionList> LocationInCaller;
3907061da546Spatrick 
3908061da546Spatrick     DWARFAttributes attributes;
3909061da546Spatrick     const size_t num_attributes = child.GetAttributes(attributes);
3910061da546Spatrick 
3911061da546Spatrick     // Parse the location at index \p attr_index within this call site parameter
3912*f6aab3d8Srobert     // DIE, or return std::nullopt on failure.
3913061da546Spatrick     auto parse_simple_location =
3914*f6aab3d8Srobert         [&](int attr_index) -> std::optional<DWARFExpressionList> {
3915061da546Spatrick       DWARFFormValue form_value;
3916061da546Spatrick       if (!attributes.ExtractFormValueAtIndex(attr_index, form_value))
3917061da546Spatrick         return {};
3918061da546Spatrick       if (!DWARFFormValue::IsBlockForm(form_value.Form()))
3919061da546Spatrick         return {};
3920061da546Spatrick       auto data = child.GetData();
3921061da546Spatrick       uint32_t block_offset = form_value.BlockData() - data.GetDataStart();
3922061da546Spatrick       uint32_t block_length = form_value.Unsigned();
3923*f6aab3d8Srobert       return DWARFExpressionList(
3924*f6aab3d8Srobert           module, DataExtractor(data, block_offset, block_length),
3925061da546Spatrick           child.GetCU());
3926061da546Spatrick     };
3927061da546Spatrick 
3928061da546Spatrick     for (size_t i = 0; i < num_attributes; ++i) {
3929061da546Spatrick       dw_attr_t attr = attributes.AttributeAtIndex(i);
3930061da546Spatrick       if (attr == DW_AT_location)
3931061da546Spatrick         LocationInCallee = parse_simple_location(i);
3932dda28197Spatrick       if (attr == DW_AT_call_value || attr == DW_AT_GNU_call_site_value)
3933061da546Spatrick         LocationInCaller = parse_simple_location(i);
3934061da546Spatrick     }
3935061da546Spatrick 
3936061da546Spatrick     if (LocationInCallee && LocationInCaller) {
3937061da546Spatrick       CallSiteParameter param = {*LocationInCallee, *LocationInCaller};
3938061da546Spatrick       parameters.push_back(param);
3939061da546Spatrick     }
3940061da546Spatrick   }
3941061da546Spatrick   return parameters;
3942061da546Spatrick }
3943061da546Spatrick 
3944061da546Spatrick /// Collect call graph edges present in a function DIE.
3945dda28197Spatrick std::vector<std::unique_ptr<lldb_private::CallEdge>>
CollectCallEdges(ModuleSP module,DWARFDIE function_die)3946dda28197Spatrick SymbolFileDWARF::CollectCallEdges(ModuleSP module, DWARFDIE function_die) {
3947061da546Spatrick   // Check if the function has a supported call site-related attribute.
3948061da546Spatrick   // TODO: In the future it may be worthwhile to support call_all_source_calls.
3949dda28197Spatrick   bool has_call_edges =
3950dda28197Spatrick       function_die.GetAttributeValueAsUnsigned(DW_AT_call_all_calls, 0) ||
3951dda28197Spatrick       function_die.GetAttributeValueAsUnsigned(DW_AT_GNU_all_call_sites, 0);
3952061da546Spatrick   if (!has_call_edges)
3953061da546Spatrick     return {};
3954061da546Spatrick 
3955*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Step);
3956061da546Spatrick   LLDB_LOG(log, "CollectCallEdges: Found call site info in {0}",
3957061da546Spatrick            function_die.GetPubname());
3958061da546Spatrick 
3959061da546Spatrick   // Scan the DIE for TAG_call_site entries.
3960061da546Spatrick   // TODO: A recursive scan of all blocks in the subprogram is needed in order
3961061da546Spatrick   // to be DWARF5-compliant. This may need to be done lazily to be performant.
3962061da546Spatrick   // For now, assume that all entries are nested directly under the subprogram
3963061da546Spatrick   // (this is the kind of DWARF LLVM produces) and parse them eagerly.
3964061da546Spatrick   std::vector<std::unique_ptr<CallEdge>> call_edges;
3965be691f3bSpatrick   for (DWARFDIE child : function_die.children()) {
3966dda28197Spatrick     if (child.Tag() != DW_TAG_call_site && child.Tag() != DW_TAG_GNU_call_site)
3967061da546Spatrick       continue;
3968061da546Spatrick 
3969*f6aab3d8Srobert     std::optional<DWARFDIE> call_origin;
3970*f6aab3d8Srobert     std::optional<DWARFExpressionList> call_target;
3971061da546Spatrick     addr_t return_pc = LLDB_INVALID_ADDRESS;
3972dda28197Spatrick     addr_t call_inst_pc = LLDB_INVALID_ADDRESS;
3973dda28197Spatrick     addr_t low_pc = LLDB_INVALID_ADDRESS;
3974dda28197Spatrick     bool tail_call = false;
3975061da546Spatrick 
3976dda28197Spatrick     // Second DW_AT_low_pc may come from DW_TAG_subprogram referenced by
3977dda28197Spatrick     // DW_TAG_GNU_call_site's DW_AT_abstract_origin overwriting our 'low_pc'.
3978dda28197Spatrick     // So do not inherit attributes from DW_AT_abstract_origin.
3979061da546Spatrick     DWARFAttributes attributes;
3980dda28197Spatrick     const size_t num_attributes =
3981dda28197Spatrick         child.GetAttributes(attributes, DWARFDIE::Recurse::no);
3982061da546Spatrick     for (size_t i = 0; i < num_attributes; ++i) {
3983061da546Spatrick       DWARFFormValue form_value;
3984061da546Spatrick       if (!attributes.ExtractFormValueAtIndex(i, form_value)) {
3985061da546Spatrick         LLDB_LOG(log, "CollectCallEdges: Could not extract TAG_call_site form");
3986061da546Spatrick         break;
3987061da546Spatrick       }
3988061da546Spatrick 
3989061da546Spatrick       dw_attr_t attr = attributes.AttributeAtIndex(i);
3990061da546Spatrick 
3991dda28197Spatrick       if (attr == DW_AT_call_tail_call || attr == DW_AT_GNU_tail_call)
3992dda28197Spatrick         tail_call = form_value.Boolean();
3993dda28197Spatrick 
3994061da546Spatrick       // Extract DW_AT_call_origin (the call target's DIE).
3995dda28197Spatrick       if (attr == DW_AT_call_origin || attr == DW_AT_abstract_origin) {
3996061da546Spatrick         call_origin = form_value.Reference();
3997061da546Spatrick         if (!call_origin->IsValid()) {
3998061da546Spatrick           LLDB_LOG(log, "CollectCallEdges: Invalid call origin in {0}",
3999061da546Spatrick                    function_die.GetPubname());
4000061da546Spatrick           break;
4001061da546Spatrick         }
4002061da546Spatrick       }
4003061da546Spatrick 
4004dda28197Spatrick       if (attr == DW_AT_low_pc)
4005dda28197Spatrick         low_pc = form_value.Address();
4006dda28197Spatrick 
4007061da546Spatrick       // Extract DW_AT_call_return_pc (the PC the call returns to) if it's
4008061da546Spatrick       // available. It should only ever be unavailable for tail call edges, in
4009061da546Spatrick       // which case use LLDB_INVALID_ADDRESS.
4010061da546Spatrick       if (attr == DW_AT_call_return_pc)
4011061da546Spatrick         return_pc = form_value.Address();
4012061da546Spatrick 
4013dda28197Spatrick       // Extract DW_AT_call_pc (the PC at the call/branch instruction). It
4014dda28197Spatrick       // should only ever be unavailable for non-tail calls, in which case use
4015dda28197Spatrick       // LLDB_INVALID_ADDRESS.
4016dda28197Spatrick       if (attr == DW_AT_call_pc)
4017dda28197Spatrick         call_inst_pc = form_value.Address();
4018dda28197Spatrick 
4019061da546Spatrick       // Extract DW_AT_call_target (the location of the address of the indirect
4020061da546Spatrick       // call).
4021dda28197Spatrick       if (attr == DW_AT_call_target || attr == DW_AT_GNU_call_site_target) {
4022061da546Spatrick         if (!DWARFFormValue::IsBlockForm(form_value.Form())) {
4023061da546Spatrick           LLDB_LOG(log,
4024061da546Spatrick                    "CollectCallEdges: AT_call_target does not have block form");
4025061da546Spatrick           break;
4026061da546Spatrick         }
4027061da546Spatrick 
4028061da546Spatrick         auto data = child.GetData();
4029061da546Spatrick         uint32_t block_offset = form_value.BlockData() - data.GetDataStart();
4030061da546Spatrick         uint32_t block_length = form_value.Unsigned();
4031*f6aab3d8Srobert         call_target = DWARFExpressionList(
4032061da546Spatrick             module, DataExtractor(data, block_offset, block_length),
4033061da546Spatrick             child.GetCU());
4034061da546Spatrick       }
4035061da546Spatrick     }
4036061da546Spatrick     if (!call_origin && !call_target) {
4037061da546Spatrick       LLDB_LOG(log, "CollectCallEdges: call site without any call target");
4038061da546Spatrick       continue;
4039061da546Spatrick     }
4040061da546Spatrick 
4041dda28197Spatrick     addr_t caller_address;
4042dda28197Spatrick     CallEdge::AddrType caller_address_type;
4043dda28197Spatrick     if (return_pc != LLDB_INVALID_ADDRESS) {
4044dda28197Spatrick       caller_address = return_pc;
4045dda28197Spatrick       caller_address_type = CallEdge::AddrType::AfterCall;
4046dda28197Spatrick     } else if (low_pc != LLDB_INVALID_ADDRESS) {
4047dda28197Spatrick       caller_address = low_pc;
4048dda28197Spatrick       caller_address_type = CallEdge::AddrType::AfterCall;
4049dda28197Spatrick     } else if (call_inst_pc != LLDB_INVALID_ADDRESS) {
4050dda28197Spatrick       caller_address = call_inst_pc;
4051dda28197Spatrick       caller_address_type = CallEdge::AddrType::Call;
4052dda28197Spatrick     } else {
4053dda28197Spatrick       LLDB_LOG(log, "CollectCallEdges: No caller address");
4054dda28197Spatrick       continue;
4055dda28197Spatrick     }
4056dda28197Spatrick     // Adjust any PC forms. It needs to be fixed up if the main executable
4057dda28197Spatrick     // contains a debug map (i.e. pointers to object files), because we need a
4058dda28197Spatrick     // file address relative to the executable's text section.
4059dda28197Spatrick     caller_address = FixupAddress(caller_address);
4060dda28197Spatrick 
4061061da546Spatrick     // Extract call site parameters.
4062061da546Spatrick     CallSiteParameterArray parameters =
4063061da546Spatrick         CollectCallSiteParameters(module, child);
4064061da546Spatrick 
4065061da546Spatrick     std::unique_ptr<CallEdge> edge;
4066061da546Spatrick     if (call_origin) {
4067dda28197Spatrick       LLDB_LOG(log,
4068dda28197Spatrick                "CollectCallEdges: Found call origin: {0} (retn-PC: {1:x}) "
4069dda28197Spatrick                "(call-PC: {2:x})",
4070dda28197Spatrick                call_origin->GetPubname(), return_pc, call_inst_pc);
4071dda28197Spatrick       edge = std::make_unique<DirectCallEdge>(
4072dda28197Spatrick           call_origin->GetMangledName(), caller_address_type, caller_address,
4073dda28197Spatrick           tail_call, std::move(parameters));
4074061da546Spatrick     } else {
4075061da546Spatrick       if (log) {
4076061da546Spatrick         StreamString call_target_desc;
4077061da546Spatrick         call_target->GetDescription(&call_target_desc, eDescriptionLevelBrief,
4078*f6aab3d8Srobert                                     nullptr);
4079061da546Spatrick         LLDB_LOG(log, "CollectCallEdges: Found indirect call target: {0}",
4080061da546Spatrick                  call_target_desc.GetString());
4081061da546Spatrick       }
4082dda28197Spatrick       edge = std::make_unique<IndirectCallEdge>(
4083dda28197Spatrick           *call_target, caller_address_type, caller_address, tail_call,
4084061da546Spatrick           std::move(parameters));
4085061da546Spatrick     }
4086061da546Spatrick 
4087061da546Spatrick     if (log && parameters.size()) {
4088061da546Spatrick       for (const CallSiteParameter &param : parameters) {
4089061da546Spatrick         StreamString callee_loc_desc, caller_loc_desc;
4090061da546Spatrick         param.LocationInCallee.GetDescription(&callee_loc_desc,
4091*f6aab3d8Srobert                                               eDescriptionLevelBrief, nullptr);
4092061da546Spatrick         param.LocationInCaller.GetDescription(&caller_loc_desc,
4093*f6aab3d8Srobert                                               eDescriptionLevelBrief, nullptr);
4094061da546Spatrick         LLDB_LOG(log, "CollectCallEdges: \tparam: {0} => {1}",
4095061da546Spatrick                  callee_loc_desc.GetString(), caller_loc_desc.GetString());
4096061da546Spatrick       }
4097061da546Spatrick     }
4098061da546Spatrick 
4099061da546Spatrick     call_edges.push_back(std::move(edge));
4100061da546Spatrick   }
4101061da546Spatrick   return call_edges;
4102061da546Spatrick }
4103061da546Spatrick 
4104061da546Spatrick std::vector<std::unique_ptr<lldb_private::CallEdge>>
ParseCallEdgesInFunction(UserID func_id)4105061da546Spatrick SymbolFileDWARF::ParseCallEdgesInFunction(UserID func_id) {
4106dda28197Spatrick   // ParseCallEdgesInFunction must be called at the behest of an exclusively
4107dda28197Spatrick   // locked lldb::Function instance. Storage for parsed call edges is owned by
4108dda28197Spatrick   // the lldb::Function instance: locking at the SymbolFile level would be too
4109dda28197Spatrick   // late, because the act of storing results from ParseCallEdgesInFunction
4110dda28197Spatrick   // would be racy.
4111061da546Spatrick   DWARFDIE func_die = GetDIE(func_id.GetID());
4112061da546Spatrick   if (func_die.IsValid())
4113061da546Spatrick     return CollectCallEdges(GetObjectFile()->GetModule(), func_die);
4114061da546Spatrick   return {};
4115061da546Spatrick }
4116061da546Spatrick 
Dump(lldb_private::Stream & s)4117061da546Spatrick void SymbolFileDWARF::Dump(lldb_private::Stream &s) {
4118*f6aab3d8Srobert   SymbolFileCommon::Dump(s);
4119061da546Spatrick   m_index->Dump(s);
4120061da546Spatrick }
4121061da546Spatrick 
DumpClangAST(Stream & s)4122061da546Spatrick void SymbolFileDWARF::DumpClangAST(Stream &s) {
4123061da546Spatrick   auto ts_or_err = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus);
4124061da546Spatrick   if (!ts_or_err)
4125061da546Spatrick     return;
4126*f6aab3d8Srobert   auto ts = *ts_or_err;
4127*f6aab3d8Srobert   TypeSystemClang *clang = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
4128061da546Spatrick   if (!clang)
4129061da546Spatrick     return;
4130*f6aab3d8Srobert   clang->Dump(s.AsRawOstream());
4131061da546Spatrick }
4132061da546Spatrick 
GetDebugMapSymfile()4133061da546Spatrick SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() {
4134be691f3bSpatrick   if (m_debug_map_symfile == nullptr) {
4135061da546Spatrick     lldb::ModuleSP module_sp(m_debug_map_module_wp.lock());
4136061da546Spatrick     if (module_sp) {
4137*f6aab3d8Srobert       m_debug_map_symfile = llvm::cast<SymbolFileDWARFDebugMap>(
4138*f6aab3d8Srobert           module_sp->GetSymbolFile()->GetBackingSymbolFile());
4139061da546Spatrick     }
4140061da546Spatrick   }
4141061da546Spatrick   return m_debug_map_symfile;
4142061da546Spatrick }
4143061da546Spatrick 
GetDwpSymbolFile()4144dda28197Spatrick const std::shared_ptr<SymbolFileDWARFDwo> &SymbolFileDWARF::GetDwpSymbolFile() {
4145061da546Spatrick   llvm::call_once(m_dwp_symfile_once_flag, [this]() {
4146061da546Spatrick     ModuleSpec module_spec;
4147061da546Spatrick     module_spec.GetFileSpec() = m_objfile_sp->GetFileSpec();
4148061da546Spatrick     module_spec.GetSymbolFileSpec() =
4149dda28197Spatrick         FileSpec(m_objfile_sp->GetModule()->GetFileSpec().GetPath() + ".dwp");
4150061da546Spatrick 
4151061da546Spatrick     FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
4152061da546Spatrick     FileSpec dwp_filespec =
4153061da546Spatrick         Symbols::LocateExecutableSymbolFile(module_spec, search_paths);
4154061da546Spatrick     if (FileSystem::Instance().Exists(dwp_filespec)) {
4155dda28197Spatrick       DataBufferSP dwp_file_data_sp;
4156dda28197Spatrick       lldb::offset_t dwp_file_data_offset = 0;
4157dda28197Spatrick       ObjectFileSP dwp_obj_file = ObjectFile::FindPlugin(
4158dda28197Spatrick           GetObjectFile()->GetModule(), &dwp_filespec, 0,
4159dda28197Spatrick           FileSystem::Instance().GetByteSize(dwp_filespec), dwp_file_data_sp,
4160dda28197Spatrick           dwp_file_data_offset);
4161dda28197Spatrick       if (!dwp_obj_file)
4162dda28197Spatrick         return;
4163dda28197Spatrick       m_dwp_symfile =
4164dda28197Spatrick           std::make_shared<SymbolFileDWARFDwo>(*this, dwp_obj_file, 0x3fffffff);
4165061da546Spatrick     }
4166061da546Spatrick   });
4167dda28197Spatrick   return m_dwp_symfile;
4168dda28197Spatrick }
4169dda28197Spatrick 
4170*f6aab3d8Srobert llvm::Expected<lldb::TypeSystemSP>
GetTypeSystem(DWARFUnit & unit)4171*f6aab3d8Srobert SymbolFileDWARF::GetTypeSystem(DWARFUnit &unit) {
4172dda28197Spatrick   return unit.GetSymbolFileDWARF().GetTypeSystemForLanguage(GetLanguage(unit));
4173dda28197Spatrick }
4174dda28197Spatrick 
GetDWARFParser(DWARFUnit & unit)4175dda28197Spatrick DWARFASTParser *SymbolFileDWARF::GetDWARFParser(DWARFUnit &unit) {
4176dda28197Spatrick   auto type_system_or_err = GetTypeSystem(unit);
4177dda28197Spatrick   if (auto err = type_system_or_err.takeError()) {
4178*f6aab3d8Srobert     LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
4179*f6aab3d8Srobert                    "Unable to get DWARFASTParser");
4180dda28197Spatrick     return nullptr;
4181dda28197Spatrick   }
4182*f6aab3d8Srobert   if (auto ts = *type_system_or_err)
4183*f6aab3d8Srobert     return ts->GetDWARFParser();
4184*f6aab3d8Srobert   return nullptr;
4185dda28197Spatrick }
4186dda28197Spatrick 
GetDecl(const DWARFDIE & die)4187dda28197Spatrick CompilerDecl SymbolFileDWARF::GetDecl(const DWARFDIE &die) {
4188dda28197Spatrick   if (DWARFASTParser *dwarf_ast = GetDWARFParser(*die.GetCU()))
4189dda28197Spatrick     return dwarf_ast->GetDeclForUIDFromDWARF(die);
4190dda28197Spatrick   return CompilerDecl();
4191dda28197Spatrick }
4192dda28197Spatrick 
GetDeclContext(const DWARFDIE & die)4193dda28197Spatrick CompilerDeclContext SymbolFileDWARF::GetDeclContext(const DWARFDIE &die) {
4194dda28197Spatrick   if (DWARFASTParser *dwarf_ast = GetDWARFParser(*die.GetCU()))
4195dda28197Spatrick     return dwarf_ast->GetDeclContextForUIDFromDWARF(die);
4196dda28197Spatrick   return CompilerDeclContext();
4197dda28197Spatrick }
4198dda28197Spatrick 
4199dda28197Spatrick CompilerDeclContext
GetContainingDeclContext(const DWARFDIE & die)4200dda28197Spatrick SymbolFileDWARF::GetContainingDeclContext(const DWARFDIE &die) {
4201dda28197Spatrick   if (DWARFASTParser *dwarf_ast = GetDWARFParser(*die.GetCU()))
4202dda28197Spatrick     return dwarf_ast->GetDeclContextContainingUIDFromDWARF(die);
4203dda28197Spatrick   return CompilerDeclContext();
4204dda28197Spatrick }
4205dda28197Spatrick 
GetDWARFDeclContext(const DWARFDIE & die)4206dda28197Spatrick DWARFDeclContext SymbolFileDWARF::GetDWARFDeclContext(const DWARFDIE &die) {
4207dda28197Spatrick   if (!die.IsValid())
4208dda28197Spatrick     return {};
4209dda28197Spatrick   DWARFDeclContext dwarf_decl_ctx =
4210dda28197Spatrick       die.GetDIE()->GetDWARFDeclContext(die.GetCU());
4211dda28197Spatrick   return dwarf_decl_ctx;
4212dda28197Spatrick }
4213dda28197Spatrick 
LanguageTypeFromDWARF(uint64_t val)4214dda28197Spatrick LanguageType SymbolFileDWARF::LanguageTypeFromDWARF(uint64_t val) {
4215dda28197Spatrick   // Note: user languages between lo_user and hi_user must be handled
4216dda28197Spatrick   // explicitly here.
4217dda28197Spatrick   switch (val) {
4218dda28197Spatrick   case DW_LANG_Mips_Assembler:
4219dda28197Spatrick     return eLanguageTypeMipsAssembler;
4220dda28197Spatrick   case DW_LANG_GOOGLE_RenderScript:
4221dda28197Spatrick     return eLanguageTypeExtRenderScript;
4222dda28197Spatrick   default:
4223dda28197Spatrick     return static_cast<LanguageType>(val);
4224dda28197Spatrick   }
4225dda28197Spatrick }
4226dda28197Spatrick 
GetLanguage(DWARFUnit & unit)4227dda28197Spatrick LanguageType SymbolFileDWARF::GetLanguage(DWARFUnit &unit) {
4228dda28197Spatrick   return LanguageTypeFromDWARF(unit.GetDWARFLanguageType());
4229061da546Spatrick }
4230be691f3bSpatrick 
GetLanguageFamily(DWARFUnit & unit)4231be691f3bSpatrick LanguageType SymbolFileDWARF::GetLanguageFamily(DWARFUnit &unit) {
4232be691f3bSpatrick   auto lang = (llvm::dwarf::SourceLanguage)unit.GetDWARFLanguageType();
4233be691f3bSpatrick   if (llvm::dwarf::isCPlusPlus(lang))
4234be691f3bSpatrick     lang = DW_LANG_C_plus_plus;
4235be691f3bSpatrick   return LanguageTypeFromDWARF(lang);
4236be691f3bSpatrick }
4237*f6aab3d8Srobert 
GetDebugInfoIndexTime()4238*f6aab3d8Srobert StatsDuration::Duration SymbolFileDWARF::GetDebugInfoIndexTime() {
4239*f6aab3d8Srobert   if (m_index)
4240*f6aab3d8Srobert     return m_index->GetIndexTime();
4241*f6aab3d8Srobert   return {};
4242*f6aab3d8Srobert }
4243*f6aab3d8Srobert 
CalculateFrameVariableError(StackFrame & frame)4244*f6aab3d8Srobert Status SymbolFileDWARF::CalculateFrameVariableError(StackFrame &frame) {
4245*f6aab3d8Srobert   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
4246*f6aab3d8Srobert   CompileUnit *cu = frame.GetSymbolContext(eSymbolContextCompUnit).comp_unit;
4247*f6aab3d8Srobert   if (!cu)
4248*f6aab3d8Srobert     return Status();
4249*f6aab3d8Srobert 
4250*f6aab3d8Srobert   DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(cu);
4251*f6aab3d8Srobert   if (!dwarf_cu)
4252*f6aab3d8Srobert     return Status();
4253*f6aab3d8Srobert 
4254*f6aab3d8Srobert   // Check if we have a skeleton compile unit that had issues trying to load
4255*f6aab3d8Srobert   // its .dwo/.dwp file. First pares the Unit DIE to make sure we see any .dwo
4256*f6aab3d8Srobert   // related errors.
4257*f6aab3d8Srobert   dwarf_cu->ExtractUnitDIEIfNeeded();
4258*f6aab3d8Srobert   const Status &dwo_error = dwarf_cu->GetDwoError();
4259*f6aab3d8Srobert   if (dwo_error.Fail())
4260*f6aab3d8Srobert     return dwo_error;
4261*f6aab3d8Srobert 
4262*f6aab3d8Srobert   // Don't return an error for assembly files as they typically don't have
4263*f6aab3d8Srobert   // varaible information.
4264*f6aab3d8Srobert   if (dwarf_cu->GetDWARFLanguageType() == DW_LANG_Mips_Assembler)
4265*f6aab3d8Srobert     return Status();
4266*f6aab3d8Srobert 
4267*f6aab3d8Srobert   // Check if this compile unit has any variable DIEs. If it doesn't then there
4268*f6aab3d8Srobert   // is not variable information for the entire compile unit.
4269*f6aab3d8Srobert   if (dwarf_cu->HasAny({DW_TAG_variable, DW_TAG_formal_parameter}))
4270*f6aab3d8Srobert     return Status();
4271*f6aab3d8Srobert 
4272*f6aab3d8Srobert   return Status("no variable information is available in debug info for this "
4273*f6aab3d8Srobert                 "compile unit");
4274*f6aab3d8Srobert }
4275