xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- SymbolFileDWARFDebugMap.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 "SymbolFileDWARFDebugMap.h"
10*f6aab3d8Srobert #include "DWARFCompileUnit.h"
11061da546Spatrick #include "DWARFDebugAranges.h"
12*f6aab3d8Srobert #include "DWARFDebugInfo.h"
13061da546Spatrick 
14061da546Spatrick #include "lldb/Core/Module.h"
15061da546Spatrick #include "lldb/Core/ModuleList.h"
16061da546Spatrick #include "lldb/Core/PluginManager.h"
17061da546Spatrick #include "lldb/Core/Section.h"
18061da546Spatrick #include "lldb/Host/FileSystem.h"
19061da546Spatrick #include "lldb/Utility/RangeMap.h"
20061da546Spatrick #include "lldb/Utility/RegularExpression.h"
21*f6aab3d8Srobert #include "lldb/Utility/Timer.h"
22*f6aab3d8Srobert #include "lldb/Utility/StreamString.h"
23061da546Spatrick 
24061da546Spatrick //#define DEBUG_OSO_DMAP // DO NOT CHECKIN WITH THIS NOT COMMENTED OUT
25061da546Spatrick #if defined(DEBUG_OSO_DMAP)
26061da546Spatrick #include "lldb/Core/StreamFile.h"
27061da546Spatrick #endif
28061da546Spatrick 
29061da546Spatrick #include "lldb/Symbol/CompileUnit.h"
30061da546Spatrick #include "lldb/Symbol/LineTable.h"
31061da546Spatrick #include "lldb/Symbol/ObjectFile.h"
32061da546Spatrick #include "lldb/Symbol/SymbolVendor.h"
33061da546Spatrick #include "lldb/Symbol/TypeMap.h"
34061da546Spatrick #include "lldb/Symbol/VariableList.h"
35061da546Spatrick #include "llvm/Support/ScopedPrinter.h"
36061da546Spatrick 
37*f6aab3d8Srobert #include "lldb/Target/StackFrame.h"
38*f6aab3d8Srobert 
39061da546Spatrick #include "LogChannelDWARF.h"
40061da546Spatrick #include "SymbolFileDWARF.h"
41061da546Spatrick 
42061da546Spatrick #include <memory>
43*f6aab3d8Srobert #include <optional>
44061da546Spatrick 
45061da546Spatrick using namespace lldb;
46061da546Spatrick using namespace lldb_private;
47061da546Spatrick 
48061da546Spatrick char SymbolFileDWARFDebugMap::ID;
49061da546Spatrick 
50061da546Spatrick // Subclass lldb_private::Module so we can intercept the
51061da546Spatrick // "Module::GetObjectFile()" (so we can fixup the object file sections) and
52061da546Spatrick // also for "Module::GetSymbolFile()" (so we can fixup the symbol file id.
53061da546Spatrick 
54061da546Spatrick const SymbolFileDWARFDebugMap::FileRangeMap &
GetFileRangeMap(SymbolFileDWARFDebugMap * exe_symfile)55061da546Spatrick SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(
56061da546Spatrick     SymbolFileDWARFDebugMap *exe_symfile) {
57061da546Spatrick   if (file_range_map_valid)
58061da546Spatrick     return file_range_map;
59061da546Spatrick 
60061da546Spatrick   file_range_map_valid = true;
61061da546Spatrick 
62061da546Spatrick   Module *oso_module = exe_symfile->GetModuleByCompUnitInfo(this);
63061da546Spatrick   if (!oso_module)
64061da546Spatrick     return file_range_map;
65061da546Spatrick 
66061da546Spatrick   ObjectFile *oso_objfile = oso_module->GetObjectFile();
67061da546Spatrick   if (!oso_objfile)
68061da546Spatrick     return file_range_map;
69061da546Spatrick 
70*f6aab3d8Srobert   Log *log = GetLog(DWARFLog::DebugMap);
71061da546Spatrick   LLDB_LOGF(
72061da546Spatrick       log,
73061da546Spatrick       "%p: SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap ('%s')",
74061da546Spatrick       static_cast<void *>(this),
75061da546Spatrick       oso_module->GetSpecificationDescription().c_str());
76061da546Spatrick 
77061da546Spatrick   std::vector<SymbolFileDWARFDebugMap::CompileUnitInfo *> cu_infos;
78061da546Spatrick   if (exe_symfile->GetCompUnitInfosForModule(oso_module, cu_infos)) {
79061da546Spatrick     for (auto comp_unit_info : cu_infos) {
80061da546Spatrick       Symtab *exe_symtab = exe_symfile->GetObjectFile()->GetSymtab();
81061da546Spatrick       ModuleSP oso_module_sp(oso_objfile->GetModule());
82061da546Spatrick       Symtab *oso_symtab = oso_objfile->GetSymtab();
83061da546Spatrick 
84061da546Spatrick       /// const uint32_t fun_resolve_flags = SymbolContext::Module |
85061da546Spatrick       /// eSymbolContextCompUnit | eSymbolContextFunction;
86061da546Spatrick       // SectionList *oso_sections = oso_objfile->Sections();
87061da546Spatrick       // Now we need to make sections that map from zero based object file
88061da546Spatrick       // addresses to where things ended up in the main executable.
89061da546Spatrick 
90061da546Spatrick       assert(comp_unit_info->first_symbol_index != UINT32_MAX);
91061da546Spatrick       // End index is one past the last valid symbol index
92061da546Spatrick       const uint32_t oso_end_idx = comp_unit_info->last_symbol_index + 1;
93061da546Spatrick       for (uint32_t idx = comp_unit_info->first_symbol_index +
94061da546Spatrick                           2; // Skip the N_SO and N_OSO
95061da546Spatrick            idx < oso_end_idx; ++idx) {
96061da546Spatrick         Symbol *exe_symbol = exe_symtab->SymbolAtIndex(idx);
97061da546Spatrick         if (exe_symbol) {
98061da546Spatrick           if (!exe_symbol->IsDebug())
99061da546Spatrick             continue;
100061da546Spatrick 
101061da546Spatrick           switch (exe_symbol->GetType()) {
102061da546Spatrick           default:
103061da546Spatrick             break;
104061da546Spatrick 
105061da546Spatrick           case eSymbolTypeCode: {
106061da546Spatrick             // For each N_FUN, or function that we run into in the debug map we
107061da546Spatrick             // make a new section that we add to the sections found in the .o
108061da546Spatrick             // file. This new section has the file address set to what the
109061da546Spatrick             // addresses are in the .o file, and the load address is adjusted
110061da546Spatrick             // to match where it ended up in the final executable! We do this
111061da546Spatrick             // before we parse any dwarf info so that when it goes get parsed
112061da546Spatrick             // all section/offset addresses that get registered will resolve
113061da546Spatrick             // correctly to the new addresses in the main executable.
114061da546Spatrick 
115061da546Spatrick             // First we find the original symbol in the .o file's symbol table
116061da546Spatrick             Symbol *oso_fun_symbol = oso_symtab->FindFirstSymbolWithNameAndType(
117dda28197Spatrick                 exe_symbol->GetMangled().GetName(Mangled::ePreferMangled),
118061da546Spatrick                 eSymbolTypeCode, Symtab::eDebugNo, Symtab::eVisibilityAny);
119061da546Spatrick             if (oso_fun_symbol) {
120061da546Spatrick               // Add the inverse OSO file address to debug map entry mapping
121061da546Spatrick               exe_symfile->AddOSOFileRange(
122061da546Spatrick                   this, exe_symbol->GetAddressRef().GetFileAddress(),
123061da546Spatrick                   exe_symbol->GetByteSize(),
124061da546Spatrick                   oso_fun_symbol->GetAddressRef().GetFileAddress(),
125061da546Spatrick                   oso_fun_symbol->GetByteSize());
126061da546Spatrick             }
127061da546Spatrick           } break;
128061da546Spatrick 
129061da546Spatrick           case eSymbolTypeData: {
130061da546Spatrick             // For each N_GSYM we remap the address for the global by making a
131061da546Spatrick             // new section that we add to the sections found in the .o file.
132061da546Spatrick             // This new section has the file address set to what the addresses
133061da546Spatrick             // are in the .o file, and the load address is adjusted to match
134061da546Spatrick             // where it ended up in the final executable! We do this before we
135061da546Spatrick             // parse any dwarf info so that when it goes get parsed all
136061da546Spatrick             // section/offset addresses that get registered will resolve
137061da546Spatrick             // correctly to the new addresses in the main executable. We
138061da546Spatrick             // initially set the section size to be 1 byte, but will need to
139061da546Spatrick             // fix up these addresses further after all globals have been
140061da546Spatrick             // parsed to span the gaps, or we can find the global variable
141061da546Spatrick             // sizes from the DWARF info as we are parsing.
142061da546Spatrick 
143061da546Spatrick             // Next we find the non-stab entry that corresponds to the N_GSYM
144061da546Spatrick             // in the .o file
145061da546Spatrick             Symbol *oso_gsym_symbol =
146061da546Spatrick                 oso_symtab->FindFirstSymbolWithNameAndType(
147dda28197Spatrick                     exe_symbol->GetMangled().GetName(Mangled::ePreferMangled),
148061da546Spatrick                     eSymbolTypeData, Symtab::eDebugNo, Symtab::eVisibilityAny);
149061da546Spatrick             if (exe_symbol && oso_gsym_symbol && exe_symbol->ValueIsAddress() &&
150061da546Spatrick                 oso_gsym_symbol->ValueIsAddress()) {
151061da546Spatrick               // Add the inverse OSO file address to debug map entry mapping
152061da546Spatrick               exe_symfile->AddOSOFileRange(
153061da546Spatrick                   this, exe_symbol->GetAddressRef().GetFileAddress(),
154061da546Spatrick                   exe_symbol->GetByteSize(),
155061da546Spatrick                   oso_gsym_symbol->GetAddressRef().GetFileAddress(),
156061da546Spatrick                   oso_gsym_symbol->GetByteSize());
157061da546Spatrick             }
158061da546Spatrick           } break;
159061da546Spatrick           }
160061da546Spatrick         }
161061da546Spatrick       }
162061da546Spatrick 
163061da546Spatrick       exe_symfile->FinalizeOSOFileRanges(this);
164061da546Spatrick       // We don't need the symbols anymore for the .o files
165061da546Spatrick       oso_objfile->ClearSymtab();
166061da546Spatrick     }
167061da546Spatrick   }
168061da546Spatrick   return file_range_map;
169061da546Spatrick }
170061da546Spatrick 
171061da546Spatrick class DebugMapModule : public Module {
172061da546Spatrick public:
DebugMapModule(const ModuleSP & exe_module_sp,uint32_t cu_idx,const FileSpec & file_spec,const ArchSpec & arch,const ConstString * object_name,off_t object_offset,const llvm::sys::TimePoint<> object_mod_time)173061da546Spatrick   DebugMapModule(const ModuleSP &exe_module_sp, uint32_t cu_idx,
174061da546Spatrick                  const FileSpec &file_spec, const ArchSpec &arch,
175061da546Spatrick                  const ConstString *object_name, off_t object_offset,
176061da546Spatrick                  const llvm::sys::TimePoint<> object_mod_time)
177061da546Spatrick       : Module(file_spec, arch, object_name, object_offset, object_mod_time),
178061da546Spatrick         m_exe_module_wp(exe_module_sp), m_cu_idx(cu_idx) {}
179061da546Spatrick 
180061da546Spatrick   ~DebugMapModule() override = default;
181061da546Spatrick 
182061da546Spatrick   SymbolFile *
GetSymbolFile(bool can_create=true,lldb_private::Stream * feedback_strm=nullptr)183061da546Spatrick   GetSymbolFile(bool can_create = true,
184061da546Spatrick                 lldb_private::Stream *feedback_strm = nullptr) override {
185061da546Spatrick     // Scope for locker
186061da546Spatrick     if (m_symfile_up.get() || !can_create)
187061da546Spatrick       return m_symfile_up ? m_symfile_up->GetSymbolFile() : nullptr;
188061da546Spatrick 
189061da546Spatrick     ModuleSP exe_module_sp(m_exe_module_wp.lock());
190061da546Spatrick     if (exe_module_sp) {
191061da546Spatrick       // Now get the object file outside of a locking scope
192061da546Spatrick       ObjectFile *oso_objfile = GetObjectFile();
193061da546Spatrick       if (oso_objfile) {
194061da546Spatrick         std::lock_guard<std::recursive_mutex> guard(m_mutex);
195061da546Spatrick         if (SymbolFile *symfile =
196061da546Spatrick                 Module::GetSymbolFile(can_create, feedback_strm)) {
197061da546Spatrick           // Set a pointer to this class to set our OSO DWARF file know that
198061da546Spatrick           // the DWARF is being used along with a debug map and that it will
199061da546Spatrick           // have the remapped sections that we do below.
200061da546Spatrick           SymbolFileDWARF *oso_symfile =
201061da546Spatrick               SymbolFileDWARFDebugMap::GetSymbolFileAsSymbolFileDWARF(symfile);
202061da546Spatrick 
203061da546Spatrick           if (!oso_symfile)
204061da546Spatrick             return nullptr;
205061da546Spatrick 
206061da546Spatrick           ObjectFile *exe_objfile = exe_module_sp->GetObjectFile();
207061da546Spatrick           SymbolFile *exe_symfile = exe_module_sp->GetSymbolFile();
208061da546Spatrick 
209061da546Spatrick           if (exe_objfile && exe_symfile) {
210061da546Spatrick             oso_symfile->SetDebugMapModule(exe_module_sp);
211061da546Spatrick             // Set the ID of the symbol file DWARF to the index of the OSO
212061da546Spatrick             // shifted left by 32 bits to provide a unique prefix for any
213061da546Spatrick             // UserID's that get created in the symbol file.
214061da546Spatrick             oso_symfile->SetID(((uint64_t)m_cu_idx + 1ull) << 32ull);
215061da546Spatrick           }
216061da546Spatrick           return symfile;
217061da546Spatrick         }
218061da546Spatrick       }
219061da546Spatrick     }
220061da546Spatrick     return nullptr;
221061da546Spatrick   }
222061da546Spatrick 
223061da546Spatrick protected:
224061da546Spatrick   ModuleWP m_exe_module_wp;
225061da546Spatrick   const uint32_t m_cu_idx;
226061da546Spatrick };
227061da546Spatrick 
Initialize()228061da546Spatrick void SymbolFileDWARFDebugMap::Initialize() {
229061da546Spatrick   PluginManager::RegisterPlugin(GetPluginNameStatic(),
230061da546Spatrick                                 GetPluginDescriptionStatic(), CreateInstance);
231061da546Spatrick }
232061da546Spatrick 
Terminate()233061da546Spatrick void SymbolFileDWARFDebugMap::Terminate() {
234061da546Spatrick   PluginManager::UnregisterPlugin(CreateInstance);
235061da546Spatrick }
236061da546Spatrick 
GetPluginDescriptionStatic()237*f6aab3d8Srobert llvm::StringRef SymbolFileDWARFDebugMap::GetPluginDescriptionStatic() {
238061da546Spatrick   return "DWARF and DWARF3 debug symbol file reader (debug map).";
239061da546Spatrick }
240061da546Spatrick 
CreateInstance(ObjectFileSP objfile_sp)241061da546Spatrick SymbolFile *SymbolFileDWARFDebugMap::CreateInstance(ObjectFileSP objfile_sp) {
242061da546Spatrick   return new SymbolFileDWARFDebugMap(std::move(objfile_sp));
243061da546Spatrick }
244061da546Spatrick 
SymbolFileDWARFDebugMap(ObjectFileSP objfile_sp)245061da546Spatrick SymbolFileDWARFDebugMap::SymbolFileDWARFDebugMap(ObjectFileSP objfile_sp)
246*f6aab3d8Srobert     : SymbolFileCommon(std::move(objfile_sp)), m_flags(), m_compile_unit_infos(),
247061da546Spatrick       m_func_indexes(), m_glob_indexes(),
248061da546Spatrick       m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate) {}
249061da546Spatrick 
250be691f3bSpatrick SymbolFileDWARFDebugMap::~SymbolFileDWARFDebugMap() = default;
251061da546Spatrick 
InitializeObject()252061da546Spatrick void SymbolFileDWARFDebugMap::InitializeObject() {}
253061da546Spatrick 
InitOSO()254061da546Spatrick void SymbolFileDWARFDebugMap::InitOSO() {
255061da546Spatrick   if (m_flags.test(kHaveInitializedOSOs))
256061da546Spatrick     return;
257061da546Spatrick 
258061da546Spatrick   m_flags.set(kHaveInitializedOSOs);
259061da546Spatrick 
260061da546Spatrick   // If the object file has been stripped, there is no sense in looking further
261061da546Spatrick   // as all of the debug symbols for the debug map will not be available
262061da546Spatrick   if (m_objfile_sp->IsStripped())
263061da546Spatrick     return;
264061da546Spatrick 
265061da546Spatrick   // Also make sure the file type is some sort of executable. Core files, debug
266061da546Spatrick   // info files (dSYM), object files (.o files), and stub libraries all can
267061da546Spatrick   switch (m_objfile_sp->GetType()) {
268061da546Spatrick   case ObjectFile::eTypeInvalid:
269061da546Spatrick   case ObjectFile::eTypeCoreFile:
270061da546Spatrick   case ObjectFile::eTypeDebugInfo:
271061da546Spatrick   case ObjectFile::eTypeObjectFile:
272061da546Spatrick   case ObjectFile::eTypeStubLibrary:
273061da546Spatrick   case ObjectFile::eTypeUnknown:
274061da546Spatrick   case ObjectFile::eTypeJIT:
275061da546Spatrick     return;
276061da546Spatrick 
277061da546Spatrick   case ObjectFile::eTypeExecutable:
278061da546Spatrick   case ObjectFile::eTypeDynamicLinker:
279061da546Spatrick   case ObjectFile::eTypeSharedLibrary:
280061da546Spatrick     break;
281061da546Spatrick   }
282061da546Spatrick 
283061da546Spatrick   // In order to get the abilities of this plug-in, we look at the list of
284061da546Spatrick   // N_OSO entries (object files) from the symbol table and make sure that
285061da546Spatrick   // these files exist and also contain valid DWARF. If we get any of that then
286061da546Spatrick   // we return the abilities of the first N_OSO's DWARF.
287061da546Spatrick 
288061da546Spatrick   Symtab *symtab = m_objfile_sp->GetSymtab();
289061da546Spatrick   if (symtab) {
290*f6aab3d8Srobert     Log *log = GetLog(DWARFLog::DebugMap);
291061da546Spatrick 
292061da546Spatrick     std::vector<uint32_t> oso_indexes;
293061da546Spatrick     // When a mach-o symbol is encoded, the n_type field is encoded in bits
294061da546Spatrick     // 23:16, and the n_desc field is encoded in bits 15:0.
295061da546Spatrick     //
296061da546Spatrick     // To find all N_OSO entries that are part of the DWARF + debug map we find
297061da546Spatrick     // only object file symbols with the flags value as follows: bits 23:16 ==
298061da546Spatrick     // 0x66 (N_OSO) bits 15: 0 == 0x0001 (specifies this is a debug map object
299061da546Spatrick     // file)
300061da546Spatrick     const uint32_t k_oso_symbol_flags_value = 0x660001u;
301061da546Spatrick 
302061da546Spatrick     const uint32_t oso_index_count =
303061da546Spatrick         symtab->AppendSymbolIndexesWithTypeAndFlagsValue(
304061da546Spatrick             eSymbolTypeObjectFile, k_oso_symbol_flags_value, oso_indexes);
305061da546Spatrick 
306061da546Spatrick     if (oso_index_count > 0) {
307061da546Spatrick       symtab->AppendSymbolIndexesWithType(eSymbolTypeCode, Symtab::eDebugYes,
308061da546Spatrick                                           Symtab::eVisibilityAny,
309061da546Spatrick                                           m_func_indexes);
310061da546Spatrick       symtab->AppendSymbolIndexesWithType(eSymbolTypeData, Symtab::eDebugYes,
311061da546Spatrick                                           Symtab::eVisibilityAny,
312061da546Spatrick                                           m_glob_indexes);
313061da546Spatrick 
314061da546Spatrick       symtab->SortSymbolIndexesByValue(m_func_indexes, true);
315061da546Spatrick       symtab->SortSymbolIndexesByValue(m_glob_indexes, true);
316061da546Spatrick 
317061da546Spatrick       for (uint32_t sym_idx : m_func_indexes) {
318061da546Spatrick         const Symbol *symbol = symtab->SymbolAtIndex(sym_idx);
319061da546Spatrick         lldb::addr_t file_addr = symbol->GetAddressRef().GetFileAddress();
320061da546Spatrick         lldb::addr_t byte_size = symbol->GetByteSize();
321061da546Spatrick         DebugMap::Entry debug_map_entry(
322061da546Spatrick             file_addr, byte_size, OSOEntry(sym_idx, LLDB_INVALID_ADDRESS));
323061da546Spatrick         m_debug_map.Append(debug_map_entry);
324061da546Spatrick       }
325061da546Spatrick       for (uint32_t sym_idx : m_glob_indexes) {
326061da546Spatrick         const Symbol *symbol = symtab->SymbolAtIndex(sym_idx);
327061da546Spatrick         lldb::addr_t file_addr = symbol->GetAddressRef().GetFileAddress();
328061da546Spatrick         lldb::addr_t byte_size = symbol->GetByteSize();
329061da546Spatrick         DebugMap::Entry debug_map_entry(
330061da546Spatrick             file_addr, byte_size, OSOEntry(sym_idx, LLDB_INVALID_ADDRESS));
331061da546Spatrick         m_debug_map.Append(debug_map_entry);
332061da546Spatrick       }
333061da546Spatrick       m_debug_map.Sort();
334061da546Spatrick 
335061da546Spatrick       m_compile_unit_infos.resize(oso_index_count);
336061da546Spatrick 
337061da546Spatrick       for (uint32_t i = 0; i < oso_index_count; ++i) {
338061da546Spatrick         const uint32_t so_idx = oso_indexes[i] - 1;
339061da546Spatrick         const uint32_t oso_idx = oso_indexes[i];
340061da546Spatrick         const Symbol *so_symbol = symtab->SymbolAtIndex(so_idx);
341061da546Spatrick         const Symbol *oso_symbol = symtab->SymbolAtIndex(oso_idx);
342061da546Spatrick         if (so_symbol && oso_symbol &&
343061da546Spatrick             so_symbol->GetType() == eSymbolTypeSourceFile &&
344061da546Spatrick             oso_symbol->GetType() == eSymbolTypeObjectFile) {
345061da546Spatrick           m_compile_unit_infos[i].so_file.SetFile(
346061da546Spatrick               so_symbol->GetName().AsCString(), FileSpec::Style::native);
347061da546Spatrick           m_compile_unit_infos[i].oso_path = oso_symbol->GetName();
348061da546Spatrick           m_compile_unit_infos[i].oso_mod_time =
349061da546Spatrick               llvm::sys::toTimePoint(oso_symbol->GetIntegerValue(0));
350061da546Spatrick           uint32_t sibling_idx = so_symbol->GetSiblingIndex();
351061da546Spatrick           // The sibling index can't be less that or equal to the current index
352061da546Spatrick           // "i"
353061da546Spatrick           if (sibling_idx == UINT32_MAX) {
354061da546Spatrick             m_objfile_sp->GetModule()->ReportError(
355*f6aab3d8Srobert                 "N_SO in symbol with UID {0} has invalid sibling in debug "
356*f6aab3d8Srobert                 "map, "
357061da546Spatrick                 "please file a bug and attach the binary listed in this error",
358061da546Spatrick                 so_symbol->GetID());
359061da546Spatrick           } else {
360061da546Spatrick             const Symbol *last_symbol = symtab->SymbolAtIndex(sibling_idx - 1);
361061da546Spatrick             m_compile_unit_infos[i].first_symbol_index = so_idx;
362061da546Spatrick             m_compile_unit_infos[i].last_symbol_index = sibling_idx - 1;
363061da546Spatrick             m_compile_unit_infos[i].first_symbol_id = so_symbol->GetID();
364061da546Spatrick             m_compile_unit_infos[i].last_symbol_id = last_symbol->GetID();
365061da546Spatrick 
366061da546Spatrick             LLDB_LOGF(log, "Initialized OSO 0x%8.8x: file=%s", i,
367061da546Spatrick                       oso_symbol->GetName().GetCString());
368061da546Spatrick           }
369061da546Spatrick         } else {
370061da546Spatrick           if (oso_symbol == nullptr)
371061da546Spatrick             m_objfile_sp->GetModule()->ReportError(
372*f6aab3d8Srobert                 "N_OSO symbol[{0}] can't be found, please file a bug and "
373*f6aab3d8Srobert                 "attach "
374061da546Spatrick                 "the binary listed in this error",
375061da546Spatrick                 oso_idx);
376061da546Spatrick           else if (so_symbol == nullptr)
377061da546Spatrick             m_objfile_sp->GetModule()->ReportError(
378*f6aab3d8Srobert                 "N_SO not found for N_OSO symbol[{0}], please file a bug and "
379061da546Spatrick                 "attach the binary listed in this error",
380061da546Spatrick                 oso_idx);
381061da546Spatrick           else if (so_symbol->GetType() != eSymbolTypeSourceFile)
382061da546Spatrick             m_objfile_sp->GetModule()->ReportError(
383*f6aab3d8Srobert                 "N_SO has incorrect symbol type ({0}) for N_OSO "
384*f6aab3d8Srobert                 "symbol[{1}], "
385061da546Spatrick                 "please file a bug and attach the binary listed in this error",
386061da546Spatrick                 so_symbol->GetType(), oso_idx);
387061da546Spatrick           else if (oso_symbol->GetType() != eSymbolTypeSourceFile)
388061da546Spatrick             m_objfile_sp->GetModule()->ReportError(
389*f6aab3d8Srobert                 "N_OSO has incorrect symbol type ({0}) for N_OSO "
390*f6aab3d8Srobert                 "symbol[{1}], "
391061da546Spatrick                 "please file a bug and attach the binary listed in this error",
392061da546Spatrick                 oso_symbol->GetType(), oso_idx);
393061da546Spatrick         }
394061da546Spatrick       }
395061da546Spatrick     }
396061da546Spatrick   }
397061da546Spatrick }
398061da546Spatrick 
GetModuleByOSOIndex(uint32_t oso_idx)399061da546Spatrick Module *SymbolFileDWARFDebugMap::GetModuleByOSOIndex(uint32_t oso_idx) {
400061da546Spatrick   const uint32_t cu_count = GetNumCompileUnits();
401061da546Spatrick   if (oso_idx < cu_count)
402061da546Spatrick     return GetModuleByCompUnitInfo(&m_compile_unit_infos[oso_idx]);
403061da546Spatrick   return nullptr;
404061da546Spatrick }
405061da546Spatrick 
GetModuleByCompUnitInfo(CompileUnitInfo * comp_unit_info)406061da546Spatrick Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo(
407061da546Spatrick     CompileUnitInfo *comp_unit_info) {
408061da546Spatrick   if (!comp_unit_info->oso_sp) {
409061da546Spatrick     auto pos = m_oso_map.find(
410061da546Spatrick         {comp_unit_info->oso_path, comp_unit_info->oso_mod_time});
411061da546Spatrick     if (pos != m_oso_map.end()) {
412061da546Spatrick       comp_unit_info->oso_sp = pos->second;
413061da546Spatrick     } else {
414061da546Spatrick       ObjectFile *obj_file = GetObjectFile();
415061da546Spatrick       comp_unit_info->oso_sp = std::make_shared<OSOInfo>();
416061da546Spatrick       m_oso_map[{comp_unit_info->oso_path, comp_unit_info->oso_mod_time}] =
417061da546Spatrick           comp_unit_info->oso_sp;
418061da546Spatrick       const char *oso_path = comp_unit_info->oso_path.GetCString();
419061da546Spatrick       FileSpec oso_file(oso_path);
420061da546Spatrick       ConstString oso_object;
421061da546Spatrick       if (FileSystem::Instance().Exists(oso_file)) {
422061da546Spatrick         // The modification time returned by the FS can have a higher precision
423061da546Spatrick         // than the one from the CU.
424061da546Spatrick         auto oso_mod_time = std::chrono::time_point_cast<std::chrono::seconds>(
425061da546Spatrick             FileSystem::Instance().GetModificationTime(oso_file));
426061da546Spatrick         // A timestamp of 0 means that the linker was in deterministic mode. In
427061da546Spatrick         // that case, we should skip the check against the filesystem last
428061da546Spatrick         // modification timestamp, since it will never match.
429061da546Spatrick         if (comp_unit_info->oso_mod_time != llvm::sys::TimePoint<>() &&
430061da546Spatrick             oso_mod_time != comp_unit_info->oso_mod_time) {
431*f6aab3d8Srobert           comp_unit_info->oso_load_error.SetErrorStringWithFormat(
432*f6aab3d8Srobert               "debug map object file \"%s\" changed (actual: 0x%8.8x, debug "
433*f6aab3d8Srobert               "map: 0x%8.8x) since this executable was linked, debug info "
434*f6aab3d8Srobert               "will not be loaded", oso_file.GetPath().c_str(),
435*f6aab3d8Srobert               (uint32_t)llvm::sys::toTimeT(oso_mod_time),
436*f6aab3d8Srobert               (uint32_t)llvm::sys::toTimeT(comp_unit_info->oso_mod_time));
437061da546Spatrick           obj_file->GetModule()->ReportError(
438*f6aab3d8Srobert               "{0}", comp_unit_info->oso_load_error.AsCString());
439061da546Spatrick           return nullptr;
440061da546Spatrick         }
441061da546Spatrick 
442061da546Spatrick       } else {
443061da546Spatrick         const bool must_exist = true;
444061da546Spatrick 
445061da546Spatrick         if (!ObjectFile::SplitArchivePathWithObject(oso_path, oso_file,
446061da546Spatrick                                                     oso_object, must_exist)) {
447*f6aab3d8Srobert           comp_unit_info->oso_load_error.SetErrorStringWithFormat(
448*f6aab3d8Srobert               "debug map object file \"%s\" containing debug info does not "
449*f6aab3d8Srobert               "exist, debug info will not be loaded",
450*f6aab3d8Srobert               comp_unit_info->oso_path.GetCString());
451061da546Spatrick           return nullptr;
452061da546Spatrick         }
453061da546Spatrick       }
454061da546Spatrick       // Always create a new module for .o files. Why? Because we use the debug
455061da546Spatrick       // map, to add new sections to each .o file and even though a .o file
456061da546Spatrick       // might not have changed, the sections that get added to the .o file can
457061da546Spatrick       // change.
458061da546Spatrick       ArchSpec oso_arch;
459061da546Spatrick       // Only adopt the architecture from the module (not the vendor or OS)
460061da546Spatrick       // since .o files for "i386-apple-ios" will historically show up as "i386
461061da546Spatrick       // -apple-macosx" due to the lack of a LC_VERSION_MIN_MACOSX or
462061da546Spatrick       // LC_VERSION_MIN_IPHONEOS load command...
463061da546Spatrick       oso_arch.SetTriple(m_objfile_sp->GetModule()
464061da546Spatrick                              ->GetArchitecture()
465061da546Spatrick                              .GetTriple()
466061da546Spatrick                              .getArchName()
467061da546Spatrick                              .str()
468061da546Spatrick                              .c_str());
469061da546Spatrick       comp_unit_info->oso_sp->module_sp = std::make_shared<DebugMapModule>(
470061da546Spatrick           obj_file->GetModule(), GetCompUnitInfoIndex(comp_unit_info), oso_file,
471061da546Spatrick           oso_arch, oso_object ? &oso_object : nullptr, 0,
472061da546Spatrick           oso_object ? comp_unit_info->oso_mod_time : llvm::sys::TimePoint<>());
473*f6aab3d8Srobert 
474*f6aab3d8Srobert       if (!comp_unit_info->oso_sp->module_sp || !comp_unit_info->oso_sp->module_sp->GetObjectFile()) {
475*f6aab3d8Srobert         if (oso_object && FileSystem::Instance().Exists(oso_file)) {
476*f6aab3d8Srobert           // If we are loading a .o file from a .a file the "oso_object" will
477*f6aab3d8Srobert           // have a valid value name and if the .a file exists, either the .o
478*f6aab3d8Srobert           // file didn't exist in the .a file or the mod time didn't match.
479*f6aab3d8Srobert           comp_unit_info->oso_load_error.SetErrorStringWithFormat(
480*f6aab3d8Srobert               "\"%s\" object from the \"%s\" archive: "
481*f6aab3d8Srobert               "either the .o file doesn't exist in the archive or the "
482*f6aab3d8Srobert               "modification time (0x%8.8x) of the .o file doesn't match",
483*f6aab3d8Srobert               oso_object.AsCString(), oso_file.GetPath().c_str(),
484*f6aab3d8Srobert               (uint32_t)llvm::sys::toTimeT(comp_unit_info->oso_mod_time));
485*f6aab3d8Srobert         }
486*f6aab3d8Srobert       }
487061da546Spatrick     }
488061da546Spatrick   }
489061da546Spatrick   if (comp_unit_info->oso_sp)
490061da546Spatrick     return comp_unit_info->oso_sp->module_sp.get();
491061da546Spatrick   return nullptr;
492061da546Spatrick }
493061da546Spatrick 
GetFileSpecForSO(uint32_t oso_idx,FileSpec & file_spec)494061da546Spatrick bool SymbolFileDWARFDebugMap::GetFileSpecForSO(uint32_t oso_idx,
495061da546Spatrick                                                FileSpec &file_spec) {
496061da546Spatrick   if (oso_idx < m_compile_unit_infos.size()) {
497061da546Spatrick     if (m_compile_unit_infos[oso_idx].so_file) {
498061da546Spatrick       file_spec = m_compile_unit_infos[oso_idx].so_file;
499061da546Spatrick       return true;
500061da546Spatrick     }
501061da546Spatrick   }
502061da546Spatrick   return false;
503061da546Spatrick }
504061da546Spatrick 
GetObjectFileByOSOIndex(uint32_t oso_idx)505061da546Spatrick ObjectFile *SymbolFileDWARFDebugMap::GetObjectFileByOSOIndex(uint32_t oso_idx) {
506061da546Spatrick   Module *oso_module = GetModuleByOSOIndex(oso_idx);
507061da546Spatrick   if (oso_module)
508061da546Spatrick     return oso_module->GetObjectFile();
509061da546Spatrick   return nullptr;
510061da546Spatrick }
511061da546Spatrick 
512061da546Spatrick SymbolFileDWARF *
GetSymbolFile(const SymbolContext & sc)513061da546Spatrick SymbolFileDWARFDebugMap::GetSymbolFile(const SymbolContext &sc) {
514061da546Spatrick   return GetSymbolFile(*sc.comp_unit);
515061da546Spatrick }
516061da546Spatrick 
517061da546Spatrick SymbolFileDWARF *
GetSymbolFile(const CompileUnit & comp_unit)518061da546Spatrick SymbolFileDWARFDebugMap::GetSymbolFile(const CompileUnit &comp_unit) {
519061da546Spatrick   CompileUnitInfo *comp_unit_info = GetCompUnitInfo(comp_unit);
520061da546Spatrick   if (comp_unit_info)
521061da546Spatrick     return GetSymbolFileByCompUnitInfo(comp_unit_info);
522061da546Spatrick   return nullptr;
523061da546Spatrick }
524061da546Spatrick 
GetObjectFileByCompUnitInfo(CompileUnitInfo * comp_unit_info)525061da546Spatrick ObjectFile *SymbolFileDWARFDebugMap::GetObjectFileByCompUnitInfo(
526061da546Spatrick     CompileUnitInfo *comp_unit_info) {
527061da546Spatrick   Module *oso_module = GetModuleByCompUnitInfo(comp_unit_info);
528061da546Spatrick   if (oso_module)
529061da546Spatrick     return oso_module->GetObjectFile();
530061da546Spatrick   return nullptr;
531061da546Spatrick }
532061da546Spatrick 
GetCompUnitInfoIndex(const CompileUnitInfo * comp_unit_info)533061da546Spatrick uint32_t SymbolFileDWARFDebugMap::GetCompUnitInfoIndex(
534061da546Spatrick     const CompileUnitInfo *comp_unit_info) {
535061da546Spatrick   if (!m_compile_unit_infos.empty()) {
536061da546Spatrick     const CompileUnitInfo *first_comp_unit_info = &m_compile_unit_infos.front();
537061da546Spatrick     const CompileUnitInfo *last_comp_unit_info = &m_compile_unit_infos.back();
538061da546Spatrick     if (first_comp_unit_info <= comp_unit_info &&
539061da546Spatrick         comp_unit_info <= last_comp_unit_info)
540061da546Spatrick       return comp_unit_info - first_comp_unit_info;
541061da546Spatrick   }
542061da546Spatrick   return UINT32_MAX;
543061da546Spatrick }
544061da546Spatrick 
545061da546Spatrick SymbolFileDWARF *
GetSymbolFileByOSOIndex(uint32_t oso_idx)546061da546Spatrick SymbolFileDWARFDebugMap::GetSymbolFileByOSOIndex(uint32_t oso_idx) {
547061da546Spatrick   unsigned size = m_compile_unit_infos.size();
548061da546Spatrick   if (oso_idx < size)
549061da546Spatrick     return GetSymbolFileByCompUnitInfo(&m_compile_unit_infos[oso_idx]);
550061da546Spatrick   return nullptr;
551061da546Spatrick }
552061da546Spatrick 
553061da546Spatrick SymbolFileDWARF *
GetSymbolFileAsSymbolFileDWARF(SymbolFile * sym_file)554061da546Spatrick SymbolFileDWARFDebugMap::GetSymbolFileAsSymbolFileDWARF(SymbolFile *sym_file) {
555061da546Spatrick   if (sym_file &&
556061da546Spatrick       sym_file->GetPluginName() == SymbolFileDWARF::GetPluginNameStatic())
557dda28197Spatrick     return static_cast<SymbolFileDWARF *>(sym_file);
558061da546Spatrick   return nullptr;
559061da546Spatrick }
560061da546Spatrick 
GetSymbolFileByCompUnitInfo(CompileUnitInfo * comp_unit_info)561061da546Spatrick SymbolFileDWARF *SymbolFileDWARFDebugMap::GetSymbolFileByCompUnitInfo(
562061da546Spatrick     CompileUnitInfo *comp_unit_info) {
563061da546Spatrick   if (Module *oso_module = GetModuleByCompUnitInfo(comp_unit_info))
564061da546Spatrick     return GetSymbolFileAsSymbolFileDWARF(oso_module->GetSymbolFile());
565061da546Spatrick   return nullptr;
566061da546Spatrick }
567061da546Spatrick 
CalculateAbilities()568061da546Spatrick uint32_t SymbolFileDWARFDebugMap::CalculateAbilities() {
569061da546Spatrick   // In order to get the abilities of this plug-in, we look at the list of
570061da546Spatrick   // N_OSO entries (object files) from the symbol table and make sure that
571061da546Spatrick   // these files exist and also contain valid DWARF. If we get any of that then
572061da546Spatrick   // we return the abilities of the first N_OSO's DWARF.
573061da546Spatrick 
574061da546Spatrick   const uint32_t oso_index_count = GetNumCompileUnits();
575061da546Spatrick   if (oso_index_count > 0) {
576061da546Spatrick     InitOSO();
577061da546Spatrick     if (!m_compile_unit_infos.empty()) {
578061da546Spatrick       return SymbolFile::CompileUnits | SymbolFile::Functions |
579061da546Spatrick              SymbolFile::Blocks | SymbolFile::GlobalVariables |
580061da546Spatrick              SymbolFile::LocalVariables | SymbolFile::VariableTypes |
581061da546Spatrick              SymbolFile::LineTables;
582061da546Spatrick     }
583061da546Spatrick   }
584061da546Spatrick   return 0;
585061da546Spatrick }
586061da546Spatrick 
CalculateNumCompileUnits()587061da546Spatrick uint32_t SymbolFileDWARFDebugMap::CalculateNumCompileUnits() {
588061da546Spatrick   InitOSO();
589061da546Spatrick   return m_compile_unit_infos.size();
590061da546Spatrick }
591061da546Spatrick 
ParseCompileUnitAtIndex(uint32_t cu_idx)592061da546Spatrick CompUnitSP SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx) {
593061da546Spatrick   CompUnitSP comp_unit_sp;
594061da546Spatrick   const uint32_t cu_count = GetNumCompileUnits();
595061da546Spatrick 
596061da546Spatrick   if (cu_idx < cu_count) {
597*f6aab3d8Srobert     auto &cu_info = m_compile_unit_infos[cu_idx];
598*f6aab3d8Srobert     Module *oso_module = GetModuleByCompUnitInfo(&cu_info);
599061da546Spatrick     if (oso_module) {
600061da546Spatrick       FileSpec so_file_spec;
601061da546Spatrick       if (GetFileSpecForSO(cu_idx, so_file_spec)) {
602061da546Spatrick         // User zero as the ID to match the compile unit at offset zero in each
603*f6aab3d8Srobert         // .o file.
604061da546Spatrick         lldb::user_id_t cu_id = 0;
605*f6aab3d8Srobert         cu_info.compile_units_sps.push_back(
606061da546Spatrick             std::make_shared<CompileUnit>(
607061da546Spatrick                 m_objfile_sp->GetModule(), nullptr, so_file_spec, cu_id,
608*f6aab3d8Srobert                 eLanguageTypeUnknown, eLazyBoolCalculate));
609*f6aab3d8Srobert         cu_info.id_to_index_map.insert({0, 0});
610*f6aab3d8Srobert         SetCompileUnitAtIndex(cu_idx, cu_info.compile_units_sps[0]);
611*f6aab3d8Srobert         // If there's a symbol file also register all the extra compile units.
612*f6aab3d8Srobert         if (SymbolFileDWARF *oso_symfile =
613*f6aab3d8Srobert                 GetSymbolFileByCompUnitInfo(&cu_info)) {
614*f6aab3d8Srobert           auto num_dwarf_units = oso_symfile->DebugInfo().GetNumUnits();
615*f6aab3d8Srobert           for (size_t i = 0; i < num_dwarf_units; ++i) {
616*f6aab3d8Srobert             auto *dwarf_unit = oso_symfile->DebugInfo().GetUnitAtIndex(i);
617*f6aab3d8Srobert             if (auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(dwarf_unit)) {
618*f6aab3d8Srobert               // The "main" one was already registered.
619*f6aab3d8Srobert               if (dwarf_cu->GetID() == 0)
620*f6aab3d8Srobert                 continue;
621*f6aab3d8Srobert               cu_info.compile_units_sps.push_back(std::make_shared<CompileUnit>(
622*f6aab3d8Srobert                   m_objfile_sp->GetModule(), nullptr, so_file_spec,
623*f6aab3d8Srobert                   dwarf_cu->GetID(), eLanguageTypeUnknown, eLazyBoolCalculate));
624*f6aab3d8Srobert               cu_info.id_to_index_map.insert(
625*f6aab3d8Srobert                   {dwarf_cu->GetID(), cu_info.compile_units_sps.size() - 1});
626061da546Spatrick             }
627061da546Spatrick           }
628061da546Spatrick         }
629*f6aab3d8Srobert       }
630*f6aab3d8Srobert     }
631*f6aab3d8Srobert     if (!cu_info.compile_units_sps.empty())
632*f6aab3d8Srobert       comp_unit_sp = cu_info.compile_units_sps[0];
633061da546Spatrick   }
634061da546Spatrick 
635061da546Spatrick   return comp_unit_sp;
636061da546Spatrick }
637061da546Spatrick 
638061da546Spatrick SymbolFileDWARFDebugMap::CompileUnitInfo *
GetCompUnitInfo(const SymbolContext & sc)639061da546Spatrick SymbolFileDWARFDebugMap::GetCompUnitInfo(const SymbolContext &sc) {
640061da546Spatrick   return GetCompUnitInfo(*sc.comp_unit);
641061da546Spatrick }
642061da546Spatrick 
643061da546Spatrick SymbolFileDWARFDebugMap::CompileUnitInfo *
GetCompUnitInfo(const CompileUnit & comp_unit)644061da546Spatrick SymbolFileDWARFDebugMap::GetCompUnitInfo(const CompileUnit &comp_unit) {
645061da546Spatrick   const uint32_t cu_count = GetNumCompileUnits();
646061da546Spatrick   for (uint32_t i = 0; i < cu_count; ++i) {
647*f6aab3d8Srobert     auto &id_to_index_map = m_compile_unit_infos[i].id_to_index_map;
648*f6aab3d8Srobert 
649*f6aab3d8Srobert     auto it = id_to_index_map.find(comp_unit.GetID());
650*f6aab3d8Srobert     if (it != id_to_index_map.end() &&
651*f6aab3d8Srobert         &comp_unit ==
652*f6aab3d8Srobert             m_compile_unit_infos[i].compile_units_sps[it->getSecond()].get())
653061da546Spatrick       return &m_compile_unit_infos[i];
654061da546Spatrick   }
655061da546Spatrick   return nullptr;
656061da546Spatrick }
657061da546Spatrick 
GetCompUnitInfosForModule(const lldb_private::Module * module,std::vector<CompileUnitInfo * > & cu_infos)658061da546Spatrick size_t SymbolFileDWARFDebugMap::GetCompUnitInfosForModule(
659061da546Spatrick     const lldb_private::Module *module,
660061da546Spatrick     std::vector<CompileUnitInfo *> &cu_infos) {
661061da546Spatrick   const uint32_t cu_count = GetNumCompileUnits();
662061da546Spatrick   for (uint32_t i = 0; i < cu_count; ++i) {
663061da546Spatrick     if (module == GetModuleByCompUnitInfo(&m_compile_unit_infos[i]))
664061da546Spatrick       cu_infos.push_back(&m_compile_unit_infos[i]);
665061da546Spatrick   }
666061da546Spatrick   return cu_infos.size();
667061da546Spatrick }
668061da546Spatrick 
669061da546Spatrick lldb::LanguageType
ParseLanguage(CompileUnit & comp_unit)670061da546Spatrick SymbolFileDWARFDebugMap::ParseLanguage(CompileUnit &comp_unit) {
671061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
672061da546Spatrick   SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
673061da546Spatrick   if (oso_dwarf)
674061da546Spatrick     return oso_dwarf->ParseLanguage(comp_unit);
675061da546Spatrick   return eLanguageTypeUnknown;
676061da546Spatrick }
677061da546Spatrick 
ParseXcodeSDK(CompileUnit & comp_unit)678dda28197Spatrick XcodeSDK SymbolFileDWARFDebugMap::ParseXcodeSDK(CompileUnit &comp_unit) {
679dda28197Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
680dda28197Spatrick   SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
681dda28197Spatrick   if (oso_dwarf)
682dda28197Spatrick     return oso_dwarf->ParseXcodeSDK(comp_unit);
683dda28197Spatrick   return {};
684dda28197Spatrick }
685dda28197Spatrick 
ParseFunctions(CompileUnit & comp_unit)686061da546Spatrick size_t SymbolFileDWARFDebugMap::ParseFunctions(CompileUnit &comp_unit) {
687061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
688061da546Spatrick   SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
689061da546Spatrick   if (oso_dwarf)
690061da546Spatrick     return oso_dwarf->ParseFunctions(comp_unit);
691061da546Spatrick   return 0;
692061da546Spatrick }
693061da546Spatrick 
ParseLineTable(CompileUnit & comp_unit)694061da546Spatrick bool SymbolFileDWARFDebugMap::ParseLineTable(CompileUnit &comp_unit) {
695061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
696061da546Spatrick   SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
697061da546Spatrick   if (oso_dwarf)
698061da546Spatrick     return oso_dwarf->ParseLineTable(comp_unit);
699061da546Spatrick   return false;
700061da546Spatrick }
701061da546Spatrick 
ParseDebugMacros(CompileUnit & comp_unit)702061da546Spatrick bool SymbolFileDWARFDebugMap::ParseDebugMacros(CompileUnit &comp_unit) {
703061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
704061da546Spatrick   SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
705061da546Spatrick   if (oso_dwarf)
706061da546Spatrick     return oso_dwarf->ParseDebugMacros(comp_unit);
707061da546Spatrick   return false;
708061da546Spatrick }
709061da546Spatrick 
ForEachExternalModule(CompileUnit & comp_unit,llvm::DenseSet<lldb_private::SymbolFile * > & visited_symbol_files,llvm::function_ref<bool (Module &)> f)710061da546Spatrick bool SymbolFileDWARFDebugMap::ForEachExternalModule(
711061da546Spatrick     CompileUnit &comp_unit,
712061da546Spatrick     llvm::DenseSet<lldb_private::SymbolFile *> &visited_symbol_files,
713061da546Spatrick     llvm::function_ref<bool(Module &)> f) {
714061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
715061da546Spatrick   SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
716061da546Spatrick   if (oso_dwarf)
717061da546Spatrick     return oso_dwarf->ForEachExternalModule(comp_unit, visited_symbol_files, f);
718061da546Spatrick   return false;
719061da546Spatrick }
720061da546Spatrick 
ParseSupportFiles(CompileUnit & comp_unit,FileSpecList & support_files)721061da546Spatrick bool SymbolFileDWARFDebugMap::ParseSupportFiles(CompileUnit &comp_unit,
722061da546Spatrick                                                 FileSpecList &support_files) {
723061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
724061da546Spatrick   SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
725061da546Spatrick   if (oso_dwarf)
726061da546Spatrick     return oso_dwarf->ParseSupportFiles(comp_unit, support_files);
727061da546Spatrick   return false;
728061da546Spatrick }
729061da546Spatrick 
ParseIsOptimized(CompileUnit & comp_unit)730061da546Spatrick bool SymbolFileDWARFDebugMap::ParseIsOptimized(CompileUnit &comp_unit) {
731061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
732061da546Spatrick   SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
733061da546Spatrick   if (oso_dwarf)
734061da546Spatrick     return oso_dwarf->ParseIsOptimized(comp_unit);
735061da546Spatrick   return false;
736061da546Spatrick }
737061da546Spatrick 
ParseImportedModules(const SymbolContext & sc,std::vector<SourceModule> & imported_modules)738061da546Spatrick bool SymbolFileDWARFDebugMap::ParseImportedModules(
739061da546Spatrick     const SymbolContext &sc, std::vector<SourceModule> &imported_modules) {
740061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
741061da546Spatrick   SymbolFileDWARF *oso_dwarf = GetSymbolFile(sc);
742061da546Spatrick   if (oso_dwarf)
743061da546Spatrick     return oso_dwarf->ParseImportedModules(sc, imported_modules);
744061da546Spatrick   return false;
745061da546Spatrick }
746061da546Spatrick 
ParseBlocksRecursive(Function & func)747061da546Spatrick size_t SymbolFileDWARFDebugMap::ParseBlocksRecursive(Function &func) {
748061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
749061da546Spatrick   CompileUnit *comp_unit = func.GetCompileUnit();
750061da546Spatrick   if (!comp_unit)
751061da546Spatrick     return 0;
752061da546Spatrick 
753061da546Spatrick   SymbolFileDWARF *oso_dwarf = GetSymbolFile(*comp_unit);
754061da546Spatrick   if (oso_dwarf)
755061da546Spatrick     return oso_dwarf->ParseBlocksRecursive(func);
756061da546Spatrick   return 0;
757061da546Spatrick }
758061da546Spatrick 
ParseTypes(CompileUnit & comp_unit)759061da546Spatrick size_t SymbolFileDWARFDebugMap::ParseTypes(CompileUnit &comp_unit) {
760061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
761061da546Spatrick   SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
762061da546Spatrick   if (oso_dwarf)
763061da546Spatrick     return oso_dwarf->ParseTypes(comp_unit);
764061da546Spatrick   return 0;
765061da546Spatrick }
766061da546Spatrick 
767061da546Spatrick size_t
ParseVariablesForContext(const SymbolContext & sc)768061da546Spatrick SymbolFileDWARFDebugMap::ParseVariablesForContext(const SymbolContext &sc) {
769061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
770061da546Spatrick   SymbolFileDWARF *oso_dwarf = GetSymbolFile(sc);
771061da546Spatrick   if (oso_dwarf)
772061da546Spatrick     return oso_dwarf->ParseVariablesForContext(sc);
773061da546Spatrick   return 0;
774061da546Spatrick }
775061da546Spatrick 
ResolveTypeUID(lldb::user_id_t type_uid)776061da546Spatrick Type *SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid) {
777061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
778061da546Spatrick   const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid);
779061da546Spatrick   SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
780061da546Spatrick   if (oso_dwarf)
781061da546Spatrick     return oso_dwarf->ResolveTypeUID(type_uid);
782061da546Spatrick   return nullptr;
783061da546Spatrick }
784061da546Spatrick 
785*f6aab3d8Srobert std::optional<SymbolFile::ArrayInfo>
GetDynamicArrayInfoForUID(lldb::user_id_t type_uid,const lldb_private::ExecutionContext * exe_ctx)786061da546Spatrick SymbolFileDWARFDebugMap::GetDynamicArrayInfoForUID(
787061da546Spatrick     lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) {
788061da546Spatrick   const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid);
789061da546Spatrick   SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
790061da546Spatrick   if (oso_dwarf)
791061da546Spatrick     return oso_dwarf->GetDynamicArrayInfoForUID(type_uid, exe_ctx);
792*f6aab3d8Srobert   return std::nullopt;
793061da546Spatrick }
794061da546Spatrick 
CompleteType(CompilerType & compiler_type)795061da546Spatrick bool SymbolFileDWARFDebugMap::CompleteType(CompilerType &compiler_type) {
796061da546Spatrick   bool success = false;
797061da546Spatrick   if (compiler_type) {
798061da546Spatrick     ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
799061da546Spatrick       if (oso_dwarf->HasForwardDeclForClangType(compiler_type)) {
800061da546Spatrick         oso_dwarf->CompleteType(compiler_type);
801061da546Spatrick         success = true;
802061da546Spatrick         return true;
803061da546Spatrick       }
804061da546Spatrick       return false;
805061da546Spatrick     });
806061da546Spatrick   }
807061da546Spatrick   return success;
808061da546Spatrick }
809061da546Spatrick 
810061da546Spatrick uint32_t
ResolveSymbolContext(const Address & exe_so_addr,SymbolContextItem resolve_scope,SymbolContext & sc)811061da546Spatrick SymbolFileDWARFDebugMap::ResolveSymbolContext(const Address &exe_so_addr,
812061da546Spatrick                                               SymbolContextItem resolve_scope,
813061da546Spatrick                                               SymbolContext &sc) {
814061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
815061da546Spatrick   uint32_t resolved_flags = 0;
816061da546Spatrick   Symtab *symtab = m_objfile_sp->GetSymtab();
817061da546Spatrick   if (symtab) {
818061da546Spatrick     const addr_t exe_file_addr = exe_so_addr.GetFileAddress();
819061da546Spatrick 
820061da546Spatrick     const DebugMap::Entry *debug_map_entry =
821061da546Spatrick         m_debug_map.FindEntryThatContains(exe_file_addr);
822061da546Spatrick     if (debug_map_entry) {
823061da546Spatrick 
824061da546Spatrick       sc.symbol =
825061da546Spatrick           symtab->SymbolAtIndex(debug_map_entry->data.GetExeSymbolIndex());
826061da546Spatrick 
827061da546Spatrick       if (sc.symbol != nullptr) {
828061da546Spatrick         resolved_flags |= eSymbolContextSymbol;
829061da546Spatrick 
830061da546Spatrick         uint32_t oso_idx = 0;
831061da546Spatrick         CompileUnitInfo *comp_unit_info =
832061da546Spatrick             GetCompileUnitInfoForSymbolWithID(sc.symbol->GetID(), &oso_idx);
833061da546Spatrick         if (comp_unit_info) {
834061da546Spatrick           comp_unit_info->GetFileRangeMap(this);
835061da546Spatrick           Module *oso_module = GetModuleByCompUnitInfo(comp_unit_info);
836061da546Spatrick           if (oso_module) {
837061da546Spatrick             lldb::addr_t oso_file_addr =
838061da546Spatrick                 exe_file_addr - debug_map_entry->GetRangeBase() +
839061da546Spatrick                 debug_map_entry->data.GetOSOFileAddress();
840061da546Spatrick             Address oso_so_addr;
841061da546Spatrick             if (oso_module->ResolveFileAddress(oso_file_addr, oso_so_addr)) {
842061da546Spatrick               resolved_flags |=
843061da546Spatrick                   oso_module->GetSymbolFile()->ResolveSymbolContext(
844061da546Spatrick                       oso_so_addr, resolve_scope, sc);
845061da546Spatrick             }
846061da546Spatrick           }
847061da546Spatrick         }
848061da546Spatrick       }
849061da546Spatrick     }
850061da546Spatrick   }
851061da546Spatrick   return resolved_flags;
852061da546Spatrick }
853061da546Spatrick 
ResolveSymbolContext(const SourceLocationSpec & src_location_spec,SymbolContextItem resolve_scope,SymbolContextList & sc_list)854061da546Spatrick uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext(
855be691f3bSpatrick     const SourceLocationSpec &src_location_spec,
856061da546Spatrick     SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
857061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
858061da546Spatrick   const uint32_t initial = sc_list.GetSize();
859061da546Spatrick   const uint32_t cu_count = GetNumCompileUnits();
860061da546Spatrick 
861061da546Spatrick   for (uint32_t i = 0; i < cu_count; ++i) {
862061da546Spatrick     // If we are checking for inlines, then we need to look through all compile
863061da546Spatrick     // units no matter if "file_spec" matches.
864be691f3bSpatrick     bool resolve = src_location_spec.GetCheckInlines();
865061da546Spatrick 
866061da546Spatrick     if (!resolve) {
867061da546Spatrick       FileSpec so_file_spec;
868061da546Spatrick       if (GetFileSpecForSO(i, so_file_spec))
869be691f3bSpatrick         resolve =
870be691f3bSpatrick             FileSpec::Match(src_location_spec.GetFileSpec(), so_file_spec);
871061da546Spatrick     }
872061da546Spatrick     if (resolve) {
873061da546Spatrick       SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(i);
874061da546Spatrick       if (oso_dwarf)
875be691f3bSpatrick         oso_dwarf->ResolveSymbolContext(src_location_spec, resolve_scope,
876be691f3bSpatrick                                         sc_list);
877061da546Spatrick     }
878061da546Spatrick   }
879061da546Spatrick   return sc_list.GetSize() - initial;
880061da546Spatrick }
881061da546Spatrick 
PrivateFindGlobalVariables(ConstString name,const CompilerDeclContext & parent_decl_ctx,const std::vector<uint32_t> & indexes,uint32_t max_matches,VariableList & variables)882061da546Spatrick void SymbolFileDWARFDebugMap::PrivateFindGlobalVariables(
883dda28197Spatrick     ConstString name, const CompilerDeclContext &parent_decl_ctx,
884061da546Spatrick     const std::vector<uint32_t>
885061da546Spatrick         &indexes, // Indexes into the symbol table that match "name"
886061da546Spatrick     uint32_t max_matches, VariableList &variables) {
887061da546Spatrick   const size_t match_count = indexes.size();
888061da546Spatrick   for (size_t i = 0; i < match_count; ++i) {
889061da546Spatrick     uint32_t oso_idx;
890061da546Spatrick     CompileUnitInfo *comp_unit_info =
891061da546Spatrick         GetCompileUnitInfoForSymbolWithIndex(indexes[i], &oso_idx);
892061da546Spatrick     if (comp_unit_info) {
893061da546Spatrick       SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
894061da546Spatrick       if (oso_dwarf) {
895061da546Spatrick         oso_dwarf->FindGlobalVariables(name, parent_decl_ctx, max_matches,
896061da546Spatrick                                        variables);
897061da546Spatrick         if (variables.GetSize() > max_matches)
898061da546Spatrick           break;
899061da546Spatrick       }
900061da546Spatrick     }
901061da546Spatrick   }
902061da546Spatrick }
903061da546Spatrick 
FindGlobalVariables(ConstString name,const CompilerDeclContext & parent_decl_ctx,uint32_t max_matches,VariableList & variables)904061da546Spatrick void SymbolFileDWARFDebugMap::FindGlobalVariables(
905dda28197Spatrick     ConstString name, const CompilerDeclContext &parent_decl_ctx,
906061da546Spatrick     uint32_t max_matches, VariableList &variables) {
907061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
908061da546Spatrick   uint32_t total_matches = 0;
909061da546Spatrick 
910061da546Spatrick   ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
911061da546Spatrick     const uint32_t old_size = variables.GetSize();
912061da546Spatrick     oso_dwarf->FindGlobalVariables(name, parent_decl_ctx, max_matches,
913061da546Spatrick                                    variables);
914061da546Spatrick     const uint32_t oso_matches = variables.GetSize() - old_size;
915061da546Spatrick     if (oso_matches > 0) {
916061da546Spatrick       total_matches += oso_matches;
917061da546Spatrick 
918061da546Spatrick       // Are we getting all matches?
919061da546Spatrick       if (max_matches == UINT32_MAX)
920061da546Spatrick         return false; // Yep, continue getting everything
921061da546Spatrick 
922061da546Spatrick       // If we have found enough matches, lets get out
923061da546Spatrick       if (max_matches >= total_matches)
924061da546Spatrick         return true;
925061da546Spatrick 
926061da546Spatrick       // Update the max matches for any subsequent calls to find globals in any
927061da546Spatrick       // other object files with DWARF
928061da546Spatrick       max_matches -= oso_matches;
929061da546Spatrick     }
930061da546Spatrick 
931061da546Spatrick     return false;
932061da546Spatrick   });
933061da546Spatrick }
934061da546Spatrick 
FindGlobalVariables(const RegularExpression & regex,uint32_t max_matches,VariableList & variables)935061da546Spatrick void SymbolFileDWARFDebugMap::FindGlobalVariables(
936061da546Spatrick     const RegularExpression &regex, uint32_t max_matches,
937061da546Spatrick     VariableList &variables) {
938061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
939061da546Spatrick   uint32_t total_matches = 0;
940061da546Spatrick   ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
941061da546Spatrick     const uint32_t old_size = variables.GetSize();
942061da546Spatrick     oso_dwarf->FindGlobalVariables(regex, max_matches, variables);
943061da546Spatrick 
944061da546Spatrick     const uint32_t oso_matches = variables.GetSize() - old_size;
945061da546Spatrick     if (oso_matches > 0) {
946061da546Spatrick       total_matches += oso_matches;
947061da546Spatrick 
948061da546Spatrick       // Are we getting all matches?
949061da546Spatrick       if (max_matches == UINT32_MAX)
950061da546Spatrick         return false; // Yep, continue getting everything
951061da546Spatrick 
952061da546Spatrick       // If we have found enough matches, lets get out
953061da546Spatrick       if (max_matches >= total_matches)
954061da546Spatrick         return true;
955061da546Spatrick 
956061da546Spatrick       // Update the max matches for any subsequent calls to find globals in any
957061da546Spatrick       // other object files with DWARF
958061da546Spatrick       max_matches -= oso_matches;
959061da546Spatrick     }
960061da546Spatrick 
961061da546Spatrick     return false;
962061da546Spatrick   });
963061da546Spatrick }
964061da546Spatrick 
SymbolContainsSymbolWithIndex(uint32_t * symbol_idx_ptr,const CompileUnitInfo * comp_unit_info)965061da546Spatrick int SymbolFileDWARFDebugMap::SymbolContainsSymbolWithIndex(
966061da546Spatrick     uint32_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info) {
967061da546Spatrick   const uint32_t symbol_idx = *symbol_idx_ptr;
968061da546Spatrick 
969061da546Spatrick   if (symbol_idx < comp_unit_info->first_symbol_index)
970061da546Spatrick     return -1;
971061da546Spatrick 
972061da546Spatrick   if (symbol_idx <= comp_unit_info->last_symbol_index)
973061da546Spatrick     return 0;
974061da546Spatrick 
975061da546Spatrick   return 1;
976061da546Spatrick }
977061da546Spatrick 
SymbolContainsSymbolWithID(user_id_t * symbol_idx_ptr,const CompileUnitInfo * comp_unit_info)978061da546Spatrick int SymbolFileDWARFDebugMap::SymbolContainsSymbolWithID(
979061da546Spatrick     user_id_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info) {
980061da546Spatrick   const user_id_t symbol_id = *symbol_idx_ptr;
981061da546Spatrick 
982061da546Spatrick   if (symbol_id < comp_unit_info->first_symbol_id)
983061da546Spatrick     return -1;
984061da546Spatrick 
985061da546Spatrick   if (symbol_id <= comp_unit_info->last_symbol_id)
986061da546Spatrick     return 0;
987061da546Spatrick 
988061da546Spatrick   return 1;
989061da546Spatrick }
990061da546Spatrick 
991061da546Spatrick SymbolFileDWARFDebugMap::CompileUnitInfo *
GetCompileUnitInfoForSymbolWithIndex(uint32_t symbol_idx,uint32_t * oso_idx_ptr)992061da546Spatrick SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithIndex(
993061da546Spatrick     uint32_t symbol_idx, uint32_t *oso_idx_ptr) {
994061da546Spatrick   const uint32_t oso_index_count = m_compile_unit_infos.size();
995061da546Spatrick   CompileUnitInfo *comp_unit_info = nullptr;
996061da546Spatrick   if (oso_index_count) {
997061da546Spatrick     comp_unit_info = (CompileUnitInfo *)bsearch(
998061da546Spatrick         &symbol_idx, &m_compile_unit_infos[0], m_compile_unit_infos.size(),
999061da546Spatrick         sizeof(CompileUnitInfo),
1000061da546Spatrick         (ComparisonFunction)SymbolContainsSymbolWithIndex);
1001061da546Spatrick   }
1002061da546Spatrick 
1003061da546Spatrick   if (oso_idx_ptr) {
1004061da546Spatrick     if (comp_unit_info != nullptr)
1005061da546Spatrick       *oso_idx_ptr = comp_unit_info - &m_compile_unit_infos[0];
1006061da546Spatrick     else
1007061da546Spatrick       *oso_idx_ptr = UINT32_MAX;
1008061da546Spatrick   }
1009061da546Spatrick   return comp_unit_info;
1010061da546Spatrick }
1011061da546Spatrick 
1012061da546Spatrick SymbolFileDWARFDebugMap::CompileUnitInfo *
GetCompileUnitInfoForSymbolWithID(user_id_t symbol_id,uint32_t * oso_idx_ptr)1013061da546Spatrick SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithID(
1014061da546Spatrick     user_id_t symbol_id, uint32_t *oso_idx_ptr) {
1015061da546Spatrick   const uint32_t oso_index_count = m_compile_unit_infos.size();
1016061da546Spatrick   CompileUnitInfo *comp_unit_info = nullptr;
1017061da546Spatrick   if (oso_index_count) {
1018061da546Spatrick     comp_unit_info = (CompileUnitInfo *)::bsearch(
1019061da546Spatrick         &symbol_id, &m_compile_unit_infos[0], m_compile_unit_infos.size(),
1020061da546Spatrick         sizeof(CompileUnitInfo),
1021061da546Spatrick         (ComparisonFunction)SymbolContainsSymbolWithID);
1022061da546Spatrick   }
1023061da546Spatrick 
1024061da546Spatrick   if (oso_idx_ptr) {
1025061da546Spatrick     if (comp_unit_info != nullptr)
1026061da546Spatrick       *oso_idx_ptr = comp_unit_info - &m_compile_unit_infos[0];
1027061da546Spatrick     else
1028061da546Spatrick       *oso_idx_ptr = UINT32_MAX;
1029061da546Spatrick   }
1030061da546Spatrick   return comp_unit_info;
1031061da546Spatrick }
1032061da546Spatrick 
RemoveFunctionsWithModuleNotEqualTo(const ModuleSP & module_sp,SymbolContextList & sc_list,uint32_t start_idx)1033061da546Spatrick static void RemoveFunctionsWithModuleNotEqualTo(const ModuleSP &module_sp,
1034061da546Spatrick                                                 SymbolContextList &sc_list,
1035061da546Spatrick                                                 uint32_t start_idx) {
1036061da546Spatrick   // We found functions in .o files. Not all functions in the .o files will
1037061da546Spatrick   // have made it into the final output file. The ones that did make it into
1038061da546Spatrick   // the final output file will have a section whose module matches the module
1039061da546Spatrick   // from the ObjectFile for this SymbolFile. When the modules don't match,
1040061da546Spatrick   // then we have something that was in a .o file, but doesn't map to anything
1041061da546Spatrick   // in the final executable.
1042061da546Spatrick   uint32_t i = start_idx;
1043061da546Spatrick   while (i < sc_list.GetSize()) {
1044061da546Spatrick     SymbolContext sc;
1045061da546Spatrick     sc_list.GetContextAtIndex(i, sc);
1046061da546Spatrick     if (sc.function) {
1047061da546Spatrick       const SectionSP section_sp(
1048061da546Spatrick           sc.function->GetAddressRange().GetBaseAddress().GetSection());
1049061da546Spatrick       if (section_sp->GetModule() != module_sp) {
1050061da546Spatrick         sc_list.RemoveContextAtIndex(i);
1051061da546Spatrick         continue;
1052061da546Spatrick       }
1053061da546Spatrick     }
1054061da546Spatrick     ++i;
1055061da546Spatrick   }
1056061da546Spatrick }
1057061da546Spatrick 
FindFunctions(const Module::LookupInfo & lookup_info,const CompilerDeclContext & parent_decl_ctx,bool include_inlines,SymbolContextList & sc_list)1058061da546Spatrick void SymbolFileDWARFDebugMap::FindFunctions(
1059*f6aab3d8Srobert     const Module::LookupInfo &lookup_info,
1060*f6aab3d8Srobert     const CompilerDeclContext &parent_decl_ctx, bool include_inlines,
1061061da546Spatrick     SymbolContextList &sc_list) {
1062061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1063be691f3bSpatrick   LLDB_SCOPED_TIMERF("SymbolFileDWARFDebugMap::FindFunctions (name = %s)",
1064*f6aab3d8Srobert                      lookup_info.GetLookupName().GetCString());
1065061da546Spatrick 
1066061da546Spatrick   ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1067061da546Spatrick     uint32_t sc_idx = sc_list.GetSize();
1068*f6aab3d8Srobert     oso_dwarf->FindFunctions(lookup_info, parent_decl_ctx, include_inlines,
1069*f6aab3d8Srobert                              sc_list);
1070061da546Spatrick     if (!sc_list.IsEmpty()) {
1071061da546Spatrick       RemoveFunctionsWithModuleNotEqualTo(m_objfile_sp->GetModule(), sc_list,
1072061da546Spatrick                                           sc_idx);
1073061da546Spatrick     }
1074061da546Spatrick     return false;
1075061da546Spatrick   });
1076061da546Spatrick }
1077061da546Spatrick 
FindFunctions(const RegularExpression & regex,bool include_inlines,SymbolContextList & sc_list)1078061da546Spatrick void SymbolFileDWARFDebugMap::FindFunctions(const RegularExpression &regex,
1079061da546Spatrick                                             bool include_inlines,
1080061da546Spatrick                                             SymbolContextList &sc_list) {
1081061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1082be691f3bSpatrick   LLDB_SCOPED_TIMERF("SymbolFileDWARFDebugMap::FindFunctions (regex = '%s')",
1083061da546Spatrick                      regex.GetText().str().c_str());
1084061da546Spatrick 
1085061da546Spatrick   ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1086061da546Spatrick     uint32_t sc_idx = sc_list.GetSize();
1087061da546Spatrick 
1088061da546Spatrick     oso_dwarf->FindFunctions(regex, include_inlines, sc_list);
1089061da546Spatrick     if (!sc_list.IsEmpty()) {
1090061da546Spatrick       RemoveFunctionsWithModuleNotEqualTo(m_objfile_sp->GetModule(), sc_list,
1091061da546Spatrick                                           sc_idx);
1092061da546Spatrick     }
1093061da546Spatrick     return false;
1094061da546Spatrick   });
1095061da546Spatrick }
1096061da546Spatrick 
GetTypes(SymbolContextScope * sc_scope,lldb::TypeClass type_mask,TypeList & type_list)1097061da546Spatrick void SymbolFileDWARFDebugMap::GetTypes(SymbolContextScope *sc_scope,
1098061da546Spatrick                                        lldb::TypeClass type_mask,
1099061da546Spatrick                                        TypeList &type_list) {
1100061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1101be691f3bSpatrick   LLDB_SCOPED_TIMERF("SymbolFileDWARFDebugMap::GetTypes (type_mask = 0x%8.8x)",
1102061da546Spatrick                      type_mask);
1103061da546Spatrick 
1104061da546Spatrick   SymbolFileDWARF *oso_dwarf = nullptr;
1105061da546Spatrick   if (sc_scope) {
1106061da546Spatrick     SymbolContext sc;
1107061da546Spatrick     sc_scope->CalculateSymbolContext(&sc);
1108061da546Spatrick 
1109061da546Spatrick     CompileUnitInfo *cu_info = GetCompUnitInfo(sc);
1110061da546Spatrick     if (cu_info) {
1111061da546Spatrick       oso_dwarf = GetSymbolFileByCompUnitInfo(cu_info);
1112061da546Spatrick       if (oso_dwarf)
1113061da546Spatrick         oso_dwarf->GetTypes(sc_scope, type_mask, type_list);
1114061da546Spatrick     }
1115061da546Spatrick   } else {
1116061da546Spatrick     ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1117061da546Spatrick       oso_dwarf->GetTypes(sc_scope, type_mask, type_list);
1118061da546Spatrick       return false;
1119061da546Spatrick     });
1120061da546Spatrick   }
1121061da546Spatrick }
1122061da546Spatrick 
1123061da546Spatrick std::vector<std::unique_ptr<lldb_private::CallEdge>>
ParseCallEdgesInFunction(UserID func_id)1124061da546Spatrick SymbolFileDWARFDebugMap::ParseCallEdgesInFunction(UserID func_id) {
1125061da546Spatrick   uint32_t oso_idx = GetOSOIndexFromUserID(func_id.GetID());
1126061da546Spatrick   SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
1127061da546Spatrick   if (oso_dwarf)
1128061da546Spatrick     return oso_dwarf->ParseCallEdgesInFunction(func_id);
1129061da546Spatrick   return {};
1130061da546Spatrick }
1131061da546Spatrick 
FindDefinitionTypeForDWARFDeclContext(const DWARFDIE & die)1132061da546Spatrick TypeSP SymbolFileDWARFDebugMap::FindDefinitionTypeForDWARFDeclContext(
1133*f6aab3d8Srobert     const DWARFDIE &die) {
1134061da546Spatrick   TypeSP type_sp;
1135061da546Spatrick   ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1136*f6aab3d8Srobert     type_sp = oso_dwarf->FindDefinitionTypeForDWARFDeclContext(die);
1137061da546Spatrick     return ((bool)type_sp);
1138061da546Spatrick   });
1139061da546Spatrick   return type_sp;
1140061da546Spatrick }
1141061da546Spatrick 
Supports_DW_AT_APPLE_objc_complete_type(SymbolFileDWARF * skip_dwarf_oso)1142061da546Spatrick bool SymbolFileDWARFDebugMap::Supports_DW_AT_APPLE_objc_complete_type(
1143061da546Spatrick     SymbolFileDWARF *skip_dwarf_oso) {
1144061da546Spatrick   if (m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolCalculate) {
1145061da546Spatrick     m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolNo;
1146061da546Spatrick     ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1147061da546Spatrick       if (skip_dwarf_oso != oso_dwarf &&
1148061da546Spatrick           oso_dwarf->Supports_DW_AT_APPLE_objc_complete_type(nullptr)) {
1149061da546Spatrick         m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolYes;
1150061da546Spatrick         return true;
1151061da546Spatrick       }
1152061da546Spatrick       return false;
1153061da546Spatrick     });
1154061da546Spatrick   }
1155061da546Spatrick   return m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolYes;
1156061da546Spatrick }
1157061da546Spatrick 
FindCompleteObjCDefinitionTypeForDIE(const DWARFDIE & die,ConstString type_name,bool must_be_implementation)1158061da546Spatrick TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE(
1159061da546Spatrick     const DWARFDIE &die, ConstString type_name,
1160061da546Spatrick     bool must_be_implementation) {
1161061da546Spatrick   // If we have a debug map, we will have an Objective-C symbol whose name is
1162061da546Spatrick   // the type name and whose type is eSymbolTypeObjCClass. If we can find that
1163061da546Spatrick   // symbol and find its containing parent, we can locate the .o file that will
1164061da546Spatrick   // contain the implementation definition since it will be scoped inside the
1165061da546Spatrick   // N_SO and we can then locate the SymbolFileDWARF that corresponds to that
1166061da546Spatrick   // N_SO.
1167061da546Spatrick   SymbolFileDWARF *oso_dwarf = nullptr;
1168061da546Spatrick   TypeSP type_sp;
1169061da546Spatrick   ObjectFile *module_objfile = m_objfile_sp->GetModule()->GetObjectFile();
1170061da546Spatrick   if (module_objfile) {
1171061da546Spatrick     Symtab *symtab = module_objfile->GetSymtab();
1172061da546Spatrick     if (symtab) {
1173061da546Spatrick       Symbol *objc_class_symbol = symtab->FindFirstSymbolWithNameAndType(
1174061da546Spatrick           type_name, eSymbolTypeObjCClass, Symtab::eDebugAny,
1175061da546Spatrick           Symtab::eVisibilityAny);
1176061da546Spatrick       if (objc_class_symbol) {
1177061da546Spatrick         // Get the N_SO symbol that contains the objective C class symbol as
1178061da546Spatrick         // this should be the .o file that contains the real definition...
1179061da546Spatrick         const Symbol *source_file_symbol = symtab->GetParent(objc_class_symbol);
1180061da546Spatrick 
1181061da546Spatrick         if (source_file_symbol &&
1182061da546Spatrick             source_file_symbol->GetType() == eSymbolTypeSourceFile) {
1183061da546Spatrick           const uint32_t source_file_symbol_idx =
1184061da546Spatrick               symtab->GetIndexForSymbol(source_file_symbol);
1185061da546Spatrick           if (source_file_symbol_idx != UINT32_MAX) {
1186061da546Spatrick             CompileUnitInfo *compile_unit_info =
1187061da546Spatrick                 GetCompileUnitInfoForSymbolWithIndex(source_file_symbol_idx,
1188061da546Spatrick                                                      nullptr);
1189061da546Spatrick             if (compile_unit_info) {
1190061da546Spatrick               oso_dwarf = GetSymbolFileByCompUnitInfo(compile_unit_info);
1191061da546Spatrick               if (oso_dwarf) {
1192061da546Spatrick                 TypeSP type_sp(oso_dwarf->FindCompleteObjCDefinitionTypeForDIE(
1193061da546Spatrick                     die, type_name, must_be_implementation));
1194061da546Spatrick                 if (type_sp) {
1195061da546Spatrick                   return type_sp;
1196061da546Spatrick                 }
1197061da546Spatrick               }
1198061da546Spatrick             }
1199061da546Spatrick           }
1200061da546Spatrick         }
1201061da546Spatrick       }
1202061da546Spatrick     }
1203061da546Spatrick   }
1204061da546Spatrick 
1205061da546Spatrick   // Only search all .o files for the definition if we don't need the
1206061da546Spatrick   // implementation because otherwise, with a valid debug map we should have
1207061da546Spatrick   // the ObjC class symbol and the code above should have found it.
1208061da546Spatrick   if (!must_be_implementation) {
1209061da546Spatrick     TypeSP type_sp;
1210061da546Spatrick 
1211061da546Spatrick     ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1212061da546Spatrick       type_sp = oso_dwarf->FindCompleteObjCDefinitionTypeForDIE(
1213061da546Spatrick           die, type_name, must_be_implementation);
1214061da546Spatrick       return (bool)type_sp;
1215061da546Spatrick     });
1216061da546Spatrick 
1217061da546Spatrick     return type_sp;
1218061da546Spatrick   }
1219061da546Spatrick   return TypeSP();
1220061da546Spatrick }
1221061da546Spatrick 
FindTypes(ConstString name,const CompilerDeclContext & parent_decl_ctx,uint32_t max_matches,llvm::DenseSet<lldb_private::SymbolFile * > & searched_symbol_files,TypeMap & types)1222061da546Spatrick void SymbolFileDWARFDebugMap::FindTypes(
1223dda28197Spatrick     ConstString name, const CompilerDeclContext &parent_decl_ctx,
1224061da546Spatrick     uint32_t max_matches,
1225061da546Spatrick     llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
1226061da546Spatrick     TypeMap &types) {
1227061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1228061da546Spatrick   ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1229061da546Spatrick     oso_dwarf->FindTypes(name, parent_decl_ctx, max_matches,
1230061da546Spatrick                          searched_symbol_files, types);
1231061da546Spatrick     return types.GetSize() >= max_matches;
1232061da546Spatrick   });
1233061da546Spatrick }
1234061da546Spatrick 
FindTypes(llvm::ArrayRef<CompilerContext> context,LanguageSet languages,llvm::DenseSet<lldb_private::SymbolFile * > & searched_symbol_files,TypeMap & types)1235061da546Spatrick void SymbolFileDWARFDebugMap::FindTypes(
1236061da546Spatrick     llvm::ArrayRef<CompilerContext> context, LanguageSet languages,
1237061da546Spatrick     llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
1238061da546Spatrick     TypeMap &types) {
1239*f6aab3d8Srobert   LLDB_SCOPED_TIMER();
1240061da546Spatrick   ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1241061da546Spatrick     oso_dwarf->FindTypes(context, languages, searched_symbol_files, types);
1242061da546Spatrick     return false;
1243061da546Spatrick   });
1244061da546Spatrick }
1245061da546Spatrick 
FindNamespace(lldb_private::ConstString name,const CompilerDeclContext & parent_decl_ctx)1246061da546Spatrick CompilerDeclContext SymbolFileDWARFDebugMap::FindNamespace(
1247061da546Spatrick     lldb_private::ConstString name,
1248dda28197Spatrick     const CompilerDeclContext &parent_decl_ctx) {
1249061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1250061da546Spatrick   CompilerDeclContext matching_namespace;
1251061da546Spatrick 
1252061da546Spatrick   ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1253061da546Spatrick     matching_namespace = oso_dwarf->FindNamespace(name, parent_decl_ctx);
1254061da546Spatrick 
1255061da546Spatrick     return (bool)matching_namespace;
1256061da546Spatrick   });
1257061da546Spatrick 
1258061da546Spatrick   return matching_namespace;
1259061da546Spatrick }
1260061da546Spatrick 
DumpClangAST(Stream & s)1261061da546Spatrick void SymbolFileDWARFDebugMap::DumpClangAST(Stream &s) {
1262061da546Spatrick   ForEachSymbolFile([&s](SymbolFileDWARF *oso_dwarf) -> bool {
1263061da546Spatrick     oso_dwarf->DumpClangAST(s);
1264dda28197Spatrick     // The underlying assumption is that DumpClangAST(...) will obtain the
1265dda28197Spatrick     // AST from the underlying TypeSystem and therefore we only need to do
1266dda28197Spatrick     // this once and can stop after the first iteration hence we return true.
1267061da546Spatrick     return true;
1268061da546Spatrick   });
1269061da546Spatrick }
1270061da546Spatrick 
1271061da546Spatrick lldb::CompUnitSP
GetCompileUnit(SymbolFileDWARF * oso_dwarf,DWARFCompileUnit & dwarf_cu)1272*f6aab3d8Srobert SymbolFileDWARFDebugMap::GetCompileUnit(SymbolFileDWARF *oso_dwarf, DWARFCompileUnit &dwarf_cu) {
1273061da546Spatrick   if (oso_dwarf) {
1274061da546Spatrick     const uint32_t cu_count = GetNumCompileUnits();
1275061da546Spatrick     for (uint32_t cu_idx = 0; cu_idx < cu_count; ++cu_idx) {
1276061da546Spatrick       SymbolFileDWARF *oso_symfile =
1277061da546Spatrick           GetSymbolFileByCompUnitInfo(&m_compile_unit_infos[cu_idx]);
1278061da546Spatrick       if (oso_symfile == oso_dwarf) {
1279*f6aab3d8Srobert         if (m_compile_unit_infos[cu_idx].compile_units_sps.empty())
1280061da546Spatrick           ParseCompileUnitAtIndex(cu_idx);
1281061da546Spatrick 
1282*f6aab3d8Srobert         auto &id_to_index_map = m_compile_unit_infos[cu_idx].id_to_index_map;
1283*f6aab3d8Srobert         auto it = id_to_index_map.find(dwarf_cu.GetID());
1284*f6aab3d8Srobert         if (it != id_to_index_map.end())
1285*f6aab3d8Srobert           return m_compile_unit_infos[cu_idx]
1286*f6aab3d8Srobert               .compile_units_sps[it->getSecond()];
1287061da546Spatrick       }
1288061da546Spatrick     }
1289061da546Spatrick   }
1290061da546Spatrick   llvm_unreachable("this shouldn't happen");
1291061da546Spatrick }
1292061da546Spatrick 
1293061da546Spatrick SymbolFileDWARFDebugMap::CompileUnitInfo *
GetCompileUnitInfo(SymbolFileDWARF * oso_dwarf)1294061da546Spatrick SymbolFileDWARFDebugMap::GetCompileUnitInfo(SymbolFileDWARF *oso_dwarf) {
1295061da546Spatrick   if (oso_dwarf) {
1296061da546Spatrick     const uint32_t cu_count = GetNumCompileUnits();
1297061da546Spatrick     for (uint32_t cu_idx = 0; cu_idx < cu_count; ++cu_idx) {
1298061da546Spatrick       SymbolFileDWARF *oso_symfile =
1299061da546Spatrick           GetSymbolFileByCompUnitInfo(&m_compile_unit_infos[cu_idx]);
1300061da546Spatrick       if (oso_symfile == oso_dwarf) {
1301061da546Spatrick         return &m_compile_unit_infos[cu_idx];
1302061da546Spatrick       }
1303061da546Spatrick     }
1304061da546Spatrick   }
1305061da546Spatrick   return nullptr;
1306061da546Spatrick }
1307061da546Spatrick 
SetCompileUnit(SymbolFileDWARF * oso_dwarf,const CompUnitSP & cu_sp)1308061da546Spatrick void SymbolFileDWARFDebugMap::SetCompileUnit(SymbolFileDWARF *oso_dwarf,
1309061da546Spatrick                                              const CompUnitSP &cu_sp) {
1310061da546Spatrick   if (oso_dwarf) {
1311061da546Spatrick     const uint32_t cu_count = GetNumCompileUnits();
1312061da546Spatrick     for (uint32_t cu_idx = 0; cu_idx < cu_count; ++cu_idx) {
1313061da546Spatrick       SymbolFileDWARF *oso_symfile =
1314061da546Spatrick           GetSymbolFileByCompUnitInfo(&m_compile_unit_infos[cu_idx]);
1315061da546Spatrick       if (oso_symfile == oso_dwarf) {
1316*f6aab3d8Srobert         if (!m_compile_unit_infos[cu_idx].compile_units_sps.empty()) {
1317*f6aab3d8Srobert           assert(m_compile_unit_infos[cu_idx].compile_units_sps[0].get() ==
1318061da546Spatrick                  cu_sp.get());
1319061da546Spatrick         } else {
1320*f6aab3d8Srobert           assert(cu_sp->GetID() == 0 &&
1321*f6aab3d8Srobert                  "Setting first compile unit but with id different than 0!");
1322*f6aab3d8Srobert           auto &compile_units_sps = m_compile_unit_infos[cu_idx].compile_units_sps;
1323*f6aab3d8Srobert           compile_units_sps.push_back(cu_sp);
1324*f6aab3d8Srobert           m_compile_unit_infos[cu_idx].id_to_index_map.insert(
1325*f6aab3d8Srobert               {cu_sp->GetID(), compile_units_sps.size() - 1});
1326*f6aab3d8Srobert 
1327061da546Spatrick           SetCompileUnitAtIndex(cu_idx, cu_sp);
1328061da546Spatrick         }
1329061da546Spatrick       }
1330061da546Spatrick     }
1331061da546Spatrick   }
1332061da546Spatrick }
1333061da546Spatrick 
1334061da546Spatrick CompilerDeclContext
GetDeclContextForUID(lldb::user_id_t type_uid)1335061da546Spatrick SymbolFileDWARFDebugMap::GetDeclContextForUID(lldb::user_id_t type_uid) {
1336061da546Spatrick   const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid);
1337061da546Spatrick   SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
1338061da546Spatrick   if (oso_dwarf)
1339061da546Spatrick     return oso_dwarf->GetDeclContextForUID(type_uid);
1340061da546Spatrick   return CompilerDeclContext();
1341061da546Spatrick }
1342061da546Spatrick 
1343061da546Spatrick CompilerDeclContext
GetDeclContextContainingUID(lldb::user_id_t type_uid)1344061da546Spatrick SymbolFileDWARFDebugMap::GetDeclContextContainingUID(lldb::user_id_t type_uid) {
1345061da546Spatrick   const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid);
1346061da546Spatrick   SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
1347061da546Spatrick   if (oso_dwarf)
1348061da546Spatrick     return oso_dwarf->GetDeclContextContainingUID(type_uid);
1349061da546Spatrick   return CompilerDeclContext();
1350061da546Spatrick }
1351061da546Spatrick 
ParseDeclsForContext(lldb_private::CompilerDeclContext decl_ctx)1352061da546Spatrick void SymbolFileDWARFDebugMap::ParseDeclsForContext(
1353061da546Spatrick     lldb_private::CompilerDeclContext decl_ctx) {
1354061da546Spatrick   ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1355061da546Spatrick     oso_dwarf->ParseDeclsForContext(decl_ctx);
1356061da546Spatrick     return true; // Keep iterating
1357061da546Spatrick   });
1358061da546Spatrick }
1359061da546Spatrick 
AddOSOFileRange(CompileUnitInfo * cu_info,lldb::addr_t exe_file_addr,lldb::addr_t exe_byte_size,lldb::addr_t oso_file_addr,lldb::addr_t oso_byte_size)1360061da546Spatrick bool SymbolFileDWARFDebugMap::AddOSOFileRange(CompileUnitInfo *cu_info,
1361061da546Spatrick                                               lldb::addr_t exe_file_addr,
1362061da546Spatrick                                               lldb::addr_t exe_byte_size,
1363061da546Spatrick                                               lldb::addr_t oso_file_addr,
1364061da546Spatrick                                               lldb::addr_t oso_byte_size) {
1365061da546Spatrick   const uint32_t debug_map_idx =
1366061da546Spatrick       m_debug_map.FindEntryIndexThatContains(exe_file_addr);
1367061da546Spatrick   if (debug_map_idx != UINT32_MAX) {
1368061da546Spatrick     DebugMap::Entry *debug_map_entry =
1369061da546Spatrick         m_debug_map.FindEntryThatContains(exe_file_addr);
1370061da546Spatrick     debug_map_entry->data.SetOSOFileAddress(oso_file_addr);
1371061da546Spatrick     addr_t range_size = std::min<addr_t>(exe_byte_size, oso_byte_size);
1372061da546Spatrick     if (range_size == 0) {
1373061da546Spatrick       range_size = std::max<addr_t>(exe_byte_size, oso_byte_size);
1374061da546Spatrick       if (range_size == 0)
1375061da546Spatrick         range_size = 1;
1376061da546Spatrick     }
1377061da546Spatrick     cu_info->file_range_map.Append(
1378061da546Spatrick         FileRangeMap::Entry(oso_file_addr, range_size, exe_file_addr));
1379061da546Spatrick     return true;
1380061da546Spatrick   }
1381061da546Spatrick   return false;
1382061da546Spatrick }
1383061da546Spatrick 
FinalizeOSOFileRanges(CompileUnitInfo * cu_info)1384061da546Spatrick void SymbolFileDWARFDebugMap::FinalizeOSOFileRanges(CompileUnitInfo *cu_info) {
1385061da546Spatrick   cu_info->file_range_map.Sort();
1386061da546Spatrick #if defined(DEBUG_OSO_DMAP)
1387061da546Spatrick   const FileRangeMap &oso_file_range_map = cu_info->GetFileRangeMap(this);
1388061da546Spatrick   const size_t n = oso_file_range_map.GetSize();
1389061da546Spatrick   printf("SymbolFileDWARFDebugMap::FinalizeOSOFileRanges (cu_info = %p) %s\n",
1390061da546Spatrick          cu_info, cu_info->oso_sp->module_sp->GetFileSpec().GetPath().c_str());
1391061da546Spatrick   for (size_t i = 0; i < n; ++i) {
1392061da546Spatrick     const FileRangeMap::Entry &entry = oso_file_range_map.GetEntryRef(i);
1393061da546Spatrick     printf("oso [0x%16.16" PRIx64 " - 0x%16.16" PRIx64
1394061da546Spatrick            ") ==> exe [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n",
1395061da546Spatrick            entry.GetRangeBase(), entry.GetRangeEnd(), entry.data,
1396061da546Spatrick            entry.data + entry.GetByteSize());
1397061da546Spatrick   }
1398061da546Spatrick #endif
1399061da546Spatrick }
1400061da546Spatrick 
1401061da546Spatrick lldb::addr_t
LinkOSOFileAddress(SymbolFileDWARF * oso_symfile,lldb::addr_t oso_file_addr)1402061da546Spatrick SymbolFileDWARFDebugMap::LinkOSOFileAddress(SymbolFileDWARF *oso_symfile,
1403061da546Spatrick                                             lldb::addr_t oso_file_addr) {
1404061da546Spatrick   CompileUnitInfo *cu_info = GetCompileUnitInfo(oso_symfile);
1405061da546Spatrick   if (cu_info) {
1406061da546Spatrick     const FileRangeMap::Entry *oso_range_entry =
1407061da546Spatrick         cu_info->GetFileRangeMap(this).FindEntryThatContains(oso_file_addr);
1408061da546Spatrick     if (oso_range_entry) {
1409061da546Spatrick       const DebugMap::Entry *debug_map_entry =
1410061da546Spatrick           m_debug_map.FindEntryThatContains(oso_range_entry->data);
1411061da546Spatrick       if (debug_map_entry) {
1412061da546Spatrick         const lldb::addr_t offset =
1413061da546Spatrick             oso_file_addr - oso_range_entry->GetRangeBase();
1414061da546Spatrick         const lldb::addr_t exe_file_addr =
1415061da546Spatrick             debug_map_entry->GetRangeBase() + offset;
1416061da546Spatrick         return exe_file_addr;
1417061da546Spatrick       }
1418061da546Spatrick     }
1419061da546Spatrick   }
1420061da546Spatrick   return LLDB_INVALID_ADDRESS;
1421061da546Spatrick }
1422061da546Spatrick 
LinkOSOAddress(Address & addr)1423061da546Spatrick bool SymbolFileDWARFDebugMap::LinkOSOAddress(Address &addr) {
1424061da546Spatrick   // Make sure this address hasn't been fixed already
1425061da546Spatrick   Module *exe_module = GetObjectFile()->GetModule().get();
1426061da546Spatrick   Module *addr_module = addr.GetModule().get();
1427061da546Spatrick   if (addr_module == exe_module)
1428061da546Spatrick     return true; // Address is already in terms of the main executable module
1429061da546Spatrick 
1430061da546Spatrick   CompileUnitInfo *cu_info = GetCompileUnitInfo(
1431061da546Spatrick       GetSymbolFileAsSymbolFileDWARF(addr_module->GetSymbolFile()));
1432061da546Spatrick   if (cu_info) {
1433061da546Spatrick     const lldb::addr_t oso_file_addr = addr.GetFileAddress();
1434061da546Spatrick     const FileRangeMap::Entry *oso_range_entry =
1435061da546Spatrick         cu_info->GetFileRangeMap(this).FindEntryThatContains(oso_file_addr);
1436061da546Spatrick     if (oso_range_entry) {
1437061da546Spatrick       const DebugMap::Entry *debug_map_entry =
1438061da546Spatrick           m_debug_map.FindEntryThatContains(oso_range_entry->data);
1439061da546Spatrick       if (debug_map_entry) {
1440061da546Spatrick         const lldb::addr_t offset =
1441061da546Spatrick             oso_file_addr - oso_range_entry->GetRangeBase();
1442061da546Spatrick         const lldb::addr_t exe_file_addr =
1443061da546Spatrick             debug_map_entry->GetRangeBase() + offset;
1444061da546Spatrick         return exe_module->ResolveFileAddress(exe_file_addr, addr);
1445061da546Spatrick       }
1446061da546Spatrick     }
1447061da546Spatrick   }
1448061da546Spatrick   return true;
1449061da546Spatrick }
1450061da546Spatrick 
LinkOSOLineTable(SymbolFileDWARF * oso_dwarf,LineTable * line_table)1451061da546Spatrick LineTable *SymbolFileDWARFDebugMap::LinkOSOLineTable(SymbolFileDWARF *oso_dwarf,
1452061da546Spatrick                                                      LineTable *line_table) {
1453061da546Spatrick   CompileUnitInfo *cu_info = GetCompileUnitInfo(oso_dwarf);
1454061da546Spatrick   if (cu_info)
1455061da546Spatrick     return line_table->LinkLineTable(cu_info->GetFileRangeMap(this));
1456061da546Spatrick   return nullptr;
1457061da546Spatrick }
1458061da546Spatrick 
1459061da546Spatrick size_t
AddOSOARanges(SymbolFileDWARF * dwarf2Data,DWARFDebugAranges * debug_aranges)1460061da546Spatrick SymbolFileDWARFDebugMap::AddOSOARanges(SymbolFileDWARF *dwarf2Data,
1461061da546Spatrick                                        DWARFDebugAranges *debug_aranges) {
1462061da546Spatrick   size_t num_line_entries_added = 0;
1463061da546Spatrick   if (debug_aranges && dwarf2Data) {
1464061da546Spatrick     CompileUnitInfo *compile_unit_info = GetCompileUnitInfo(dwarf2Data);
1465061da546Spatrick     if (compile_unit_info) {
1466061da546Spatrick       const FileRangeMap &file_range_map =
1467061da546Spatrick           compile_unit_info->GetFileRangeMap(this);
1468061da546Spatrick       for (size_t idx = 0; idx < file_range_map.GetSize(); idx++) {
1469061da546Spatrick         const FileRangeMap::Entry *entry = file_range_map.GetEntryAtIndex(idx);
1470061da546Spatrick         if (entry) {
1471061da546Spatrick           debug_aranges->AppendRange(dwarf2Data->GetID(), entry->GetRangeBase(),
1472061da546Spatrick                                      entry->GetRangeEnd());
1473061da546Spatrick           num_line_entries_added++;
1474061da546Spatrick         }
1475061da546Spatrick       }
1476061da546Spatrick     }
1477061da546Spatrick   }
1478061da546Spatrick   return num_line_entries_added;
1479061da546Spatrick }
1480*f6aab3d8Srobert 
GetDebugInfoModules()1481*f6aab3d8Srobert ModuleList SymbolFileDWARFDebugMap::GetDebugInfoModules() {
1482*f6aab3d8Srobert   ModuleList oso_modules;
1483*f6aab3d8Srobert   ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1484*f6aab3d8Srobert     ObjectFile *oso_objfile = oso_dwarf->GetObjectFile();
1485*f6aab3d8Srobert     if (oso_objfile) {
1486*f6aab3d8Srobert       ModuleSP module_sp = oso_objfile->GetModule();
1487*f6aab3d8Srobert       if (module_sp)
1488*f6aab3d8Srobert         oso_modules.Append(module_sp);
1489*f6aab3d8Srobert     }
1490*f6aab3d8Srobert     return false; // Keep iterating
1491*f6aab3d8Srobert   });
1492*f6aab3d8Srobert   return oso_modules;
1493*f6aab3d8Srobert }
1494*f6aab3d8Srobert 
CalculateFrameVariableError(StackFrame & frame)1495*f6aab3d8Srobert Status SymbolFileDWARFDebugMap::CalculateFrameVariableError(StackFrame &frame) {
1496*f6aab3d8Srobert   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1497*f6aab3d8Srobert 
1498*f6aab3d8Srobert   // We need to make sure that our PC value from the frame matches the module
1499*f6aab3d8Srobert   // for this object file since we will lookup the PC file address in the debug
1500*f6aab3d8Srobert   // map below.
1501*f6aab3d8Srobert   Address pc_addr = frame.GetFrameCodeAddress();
1502*f6aab3d8Srobert   if (pc_addr.GetModule() == m_objfile_sp->GetModule()) {
1503*f6aab3d8Srobert     Symtab *symtab = m_objfile_sp->GetSymtab();
1504*f6aab3d8Srobert     if (symtab) {
1505*f6aab3d8Srobert       const DebugMap::Entry *debug_map_entry =
1506*f6aab3d8Srobert           m_debug_map.FindEntryThatContains(pc_addr.GetFileAddress());
1507*f6aab3d8Srobert       if (debug_map_entry) {
1508*f6aab3d8Srobert         Symbol *symbol =
1509*f6aab3d8Srobert             symtab->SymbolAtIndex(debug_map_entry->data.GetExeSymbolIndex());
1510*f6aab3d8Srobert         if (symbol) {
1511*f6aab3d8Srobert           uint32_t oso_idx = 0;
1512*f6aab3d8Srobert           CompileUnitInfo *comp_unit_info =
1513*f6aab3d8Srobert               GetCompileUnitInfoForSymbolWithID(symbol->GetID(), &oso_idx);
1514*f6aab3d8Srobert           if (comp_unit_info) {
1515*f6aab3d8Srobert             Module *oso_module = GetModuleByCompUnitInfo(comp_unit_info);
1516*f6aab3d8Srobert             if (oso_module) {
1517*f6aab3d8Srobert               // Check the .o file's DWARF in case it has an error to display.
1518*f6aab3d8Srobert               SymbolFile *oso_sym_file = oso_module->GetSymbolFile();
1519*f6aab3d8Srobert               if (oso_sym_file)
1520*f6aab3d8Srobert                 return oso_sym_file->GetFrameVariableError(frame);
1521*f6aab3d8Srobert             }
1522*f6aab3d8Srobert             // If we don't have a valid OSO module here, then something went
1523*f6aab3d8Srobert             // wrong as we have a symbol for the address in the debug map, but
1524*f6aab3d8Srobert             // we weren't able to open the .o file. Display an appropriate
1525*f6aab3d8Srobert             // error
1526*f6aab3d8Srobert             if (comp_unit_info->oso_load_error.Fail())
1527*f6aab3d8Srobert               return comp_unit_info->oso_load_error;
1528*f6aab3d8Srobert             else
1529*f6aab3d8Srobert               return Status("unable to load debug map object file \"%s\" "
1530*f6aab3d8Srobert                             "exist, debug info will not be loaded",
1531*f6aab3d8Srobert                             comp_unit_info->oso_path.GetCString());
1532*f6aab3d8Srobert           }
1533*f6aab3d8Srobert         }
1534*f6aab3d8Srobert       }
1535*f6aab3d8Srobert     }
1536*f6aab3d8Srobert   }
1537*f6aab3d8Srobert   return Status();
1538*f6aab3d8Srobert }
1539