1 //===-- SymbolFileDWARFDebugMap.cpp ---------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "SymbolFileDWARFDebugMap.h"
10 #include "DWARFCompileUnit.h"
11 #include "DWARFDebugAranges.h"
12 #include "DWARFDebugInfo.h"
13 
14 #include "lldb/Core/Module.h"
15 #include "lldb/Core/ModuleList.h"
16 #include "lldb/Core/PluginManager.h"
17 #include "lldb/Core/Section.h"
18 #include "lldb/Host/FileSystem.h"
19 #include "lldb/Utility/RangeMap.h"
20 #include "lldb/Utility/RegularExpression.h"
21 #include "lldb/Utility/Timer.h"
22 #include "lldb/Utility/StreamString.h"
23 
24 //#define DEBUG_OSO_DMAP // DO NOT CHECKIN WITH THIS NOT COMMENTED OUT
25 #if defined(DEBUG_OSO_DMAP)
26 #include "lldb/Core/StreamFile.h"
27 #endif
28 
29 #include "lldb/Symbol/CompileUnit.h"
30 #include "lldb/Symbol/LineTable.h"
31 #include "lldb/Symbol/ObjectFile.h"
32 #include "lldb/Symbol/SymbolVendor.h"
33 #include "lldb/Symbol/TypeMap.h"
34 #include "lldb/Symbol/VariableList.h"
35 #include "llvm/Support/ScopedPrinter.h"
36 
37 #include "lldb/Target/StackFrame.h"
38 
39 #include "LogChannelDWARF.h"
40 #include "SymbolFileDWARF.h"
41 
42 #include <memory>
43 #include <optional>
44 
45 using namespace lldb;
46 using namespace lldb_private;
47 
48 char SymbolFileDWARFDebugMap::ID;
49 
50 // Subclass lldb_private::Module so we can intercept the
51 // "Module::GetObjectFile()" (so we can fixup the object file sections) and
52 // also for "Module::GetSymbolFile()" (so we can fixup the symbol file id.
53 
54 const SymbolFileDWARFDebugMap::FileRangeMap &
55 SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(
56     SymbolFileDWARFDebugMap *exe_symfile) {
57   if (file_range_map_valid)
58     return file_range_map;
59 
60   file_range_map_valid = true;
61 
62   Module *oso_module = exe_symfile->GetModuleByCompUnitInfo(this);
63   if (!oso_module)
64     return file_range_map;
65 
66   ObjectFile *oso_objfile = oso_module->GetObjectFile();
67   if (!oso_objfile)
68     return file_range_map;
69 
70   Log *log = GetLog(DWARFLog::DebugMap);
71   LLDB_LOGF(
72       log,
73       "%p: SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap ('%s')",
74       static_cast<void *>(this),
75       oso_module->GetSpecificationDescription().c_str());
76 
77   std::vector<SymbolFileDWARFDebugMap::CompileUnitInfo *> cu_infos;
78   if (exe_symfile->GetCompUnitInfosForModule(oso_module, cu_infos)) {
79     for (auto comp_unit_info : cu_infos) {
80       Symtab *exe_symtab = exe_symfile->GetObjectFile()->GetSymtab();
81       ModuleSP oso_module_sp(oso_objfile->GetModule());
82       Symtab *oso_symtab = oso_objfile->GetSymtab();
83 
84       /// const uint32_t fun_resolve_flags = SymbolContext::Module |
85       /// eSymbolContextCompUnit | eSymbolContextFunction;
86       // SectionList *oso_sections = oso_objfile->Sections();
87       // Now we need to make sections that map from zero based object file
88       // addresses to where things ended up in the main executable.
89 
90       assert(comp_unit_info->first_symbol_index != UINT32_MAX);
91       // End index is one past the last valid symbol index
92       const uint32_t oso_end_idx = comp_unit_info->last_symbol_index + 1;
93       for (uint32_t idx = comp_unit_info->first_symbol_index +
94                           2; // Skip the N_SO and N_OSO
95            idx < oso_end_idx; ++idx) {
96         Symbol *exe_symbol = exe_symtab->SymbolAtIndex(idx);
97         if (exe_symbol) {
98           if (!exe_symbol->IsDebug())
99             continue;
100 
101           switch (exe_symbol->GetType()) {
102           default:
103             break;
104 
105           case eSymbolTypeCode: {
106             // For each N_FUN, or function that we run into in the debug map we
107             // make a new section that we add to the sections found in the .o
108             // file. This new section has the file address set to what the
109             // addresses are in the .o file, and the load address is adjusted
110             // to match where it ended up in the final executable! We do this
111             // before we parse any dwarf info so that when it goes get parsed
112             // all section/offset addresses that get registered will resolve
113             // correctly to the new addresses in the main executable.
114 
115             // First we find the original symbol in the .o file's symbol table
116             Symbol *oso_fun_symbol = oso_symtab->FindFirstSymbolWithNameAndType(
117                 exe_symbol->GetMangled().GetName(Mangled::ePreferMangled),
118                 eSymbolTypeCode, Symtab::eDebugNo, Symtab::eVisibilityAny);
119             if (oso_fun_symbol) {
120               // Add the inverse OSO file address to debug map entry mapping
121               exe_symfile->AddOSOFileRange(
122                   this, exe_symbol->GetAddressRef().GetFileAddress(),
123                   exe_symbol->GetByteSize(),
124                   oso_fun_symbol->GetAddressRef().GetFileAddress(),
125                   oso_fun_symbol->GetByteSize());
126             }
127           } break;
128 
129           case eSymbolTypeData: {
130             // For each N_GSYM we remap the address for the global by making a
131             // new section that we add to the sections found in the .o file.
132             // This new section has the file address set to what the addresses
133             // are in the .o file, and the load address is adjusted to match
134             // where it ended up in the final executable! We do this before we
135             // parse any dwarf info so that when it goes get parsed all
136             // section/offset addresses that get registered will resolve
137             // correctly to the new addresses in the main executable. We
138             // initially set the section size to be 1 byte, but will need to
139             // fix up these addresses further after all globals have been
140             // parsed to span the gaps, or we can find the global variable
141             // sizes from the DWARF info as we are parsing.
142 
143             // Next we find the non-stab entry that corresponds to the N_GSYM
144             // in the .o file
145             Symbol *oso_gsym_symbol =
146                 oso_symtab->FindFirstSymbolWithNameAndType(
147                     exe_symbol->GetMangled().GetName(Mangled::ePreferMangled),
148                     eSymbolTypeData, Symtab::eDebugNo, Symtab::eVisibilityAny);
149             if (exe_symbol && oso_gsym_symbol && exe_symbol->ValueIsAddress() &&
150                 oso_gsym_symbol->ValueIsAddress()) {
151               // Add the inverse OSO file address to debug map entry mapping
152               exe_symfile->AddOSOFileRange(
153                   this, exe_symbol->GetAddressRef().GetFileAddress(),
154                   exe_symbol->GetByteSize(),
155                   oso_gsym_symbol->GetAddressRef().GetFileAddress(),
156                   oso_gsym_symbol->GetByteSize());
157             }
158           } break;
159           }
160         }
161       }
162 
163       exe_symfile->FinalizeOSOFileRanges(this);
164       // We don't need the symbols anymore for the .o files
165       oso_objfile->ClearSymtab();
166     }
167   }
168   return file_range_map;
169 }
170 
171 class DebugMapModule : public Module {
172 public:
173   DebugMapModule(const ModuleSP &exe_module_sp, uint32_t cu_idx,
174                  const FileSpec &file_spec, const ArchSpec &arch,
175                  const ConstString *object_name, off_t object_offset,
176                  const llvm::sys::TimePoint<> object_mod_time)
177       : Module(file_spec, arch, object_name, object_offset, object_mod_time),
178         m_exe_module_wp(exe_module_sp), m_cu_idx(cu_idx) {}
179 
180   ~DebugMapModule() override = default;
181 
182   SymbolFile *
183   GetSymbolFile(bool can_create = true,
184                 lldb_private::Stream *feedback_strm = nullptr) override {
185     // Scope for locker
186     if (m_symfile_up.get() || !can_create)
187       return m_symfile_up ? m_symfile_up->GetSymbolFile() : nullptr;
188 
189     ModuleSP exe_module_sp(m_exe_module_wp.lock());
190     if (exe_module_sp) {
191       // Now get the object file outside of a locking scope
192       ObjectFile *oso_objfile = GetObjectFile();
193       if (oso_objfile) {
194         std::lock_guard<std::recursive_mutex> guard(m_mutex);
195         if (SymbolFile *symfile =
196                 Module::GetSymbolFile(can_create, feedback_strm)) {
197           // Set a pointer to this class to set our OSO DWARF file know that
198           // the DWARF is being used along with a debug map and that it will
199           // have the remapped sections that we do below.
200           SymbolFileDWARF *oso_symfile =
201               SymbolFileDWARFDebugMap::GetSymbolFileAsSymbolFileDWARF(symfile);
202 
203           if (!oso_symfile)
204             return nullptr;
205 
206           ObjectFile *exe_objfile = exe_module_sp->GetObjectFile();
207           SymbolFile *exe_symfile = exe_module_sp->GetSymbolFile();
208 
209           if (exe_objfile && exe_symfile) {
210             oso_symfile->SetDebugMapModule(exe_module_sp);
211             // Set the ID of the symbol file DWARF to the index of the OSO
212             // shifted left by 32 bits to provide a unique prefix for any
213             // UserID's that get created in the symbol file.
214             oso_symfile->SetID(((uint64_t)m_cu_idx + 1ull) << 32ull);
215           }
216           return symfile;
217         }
218       }
219     }
220     return nullptr;
221   }
222 
223 protected:
224   ModuleWP m_exe_module_wp;
225   const uint32_t m_cu_idx;
226 };
227 
228 void SymbolFileDWARFDebugMap::Initialize() {
229   PluginManager::RegisterPlugin(GetPluginNameStatic(),
230                                 GetPluginDescriptionStatic(), CreateInstance);
231 }
232 
233 void SymbolFileDWARFDebugMap::Terminate() {
234   PluginManager::UnregisterPlugin(CreateInstance);
235 }
236 
237 llvm::StringRef SymbolFileDWARFDebugMap::GetPluginDescriptionStatic() {
238   return "DWARF and DWARF3 debug symbol file reader (debug map).";
239 }
240 
241 SymbolFile *SymbolFileDWARFDebugMap::CreateInstance(ObjectFileSP objfile_sp) {
242   return new SymbolFileDWARFDebugMap(std::move(objfile_sp));
243 }
244 
245 SymbolFileDWARFDebugMap::SymbolFileDWARFDebugMap(ObjectFileSP objfile_sp)
246     : SymbolFileCommon(std::move(objfile_sp)), m_flags(), m_compile_unit_infos(),
247       m_func_indexes(), m_glob_indexes(),
248       m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate) {}
249 
250 SymbolFileDWARFDebugMap::~SymbolFileDWARFDebugMap() = default;
251 
252 void SymbolFileDWARFDebugMap::InitializeObject() {}
253 
254 void SymbolFileDWARFDebugMap::InitOSO() {
255   if (m_flags.test(kHaveInitializedOSOs))
256     return;
257 
258   m_flags.set(kHaveInitializedOSOs);
259 
260   // If the object file has been stripped, there is no sense in looking further
261   // as all of the debug symbols for the debug map will not be available
262   if (m_objfile_sp->IsStripped())
263     return;
264 
265   // Also make sure the file type is some sort of executable. Core files, debug
266   // info files (dSYM), object files (.o files), and stub libraries all can
267   switch (m_objfile_sp->GetType()) {
268   case ObjectFile::eTypeInvalid:
269   case ObjectFile::eTypeCoreFile:
270   case ObjectFile::eTypeDebugInfo:
271   case ObjectFile::eTypeObjectFile:
272   case ObjectFile::eTypeStubLibrary:
273   case ObjectFile::eTypeUnknown:
274   case ObjectFile::eTypeJIT:
275     return;
276 
277   case ObjectFile::eTypeExecutable:
278   case ObjectFile::eTypeDynamicLinker:
279   case ObjectFile::eTypeSharedLibrary:
280     break;
281   }
282 
283   // In order to get the abilities of this plug-in, we look at the list of
284   // N_OSO entries (object files) from the symbol table and make sure that
285   // these files exist and also contain valid DWARF. If we get any of that then
286   // we return the abilities of the first N_OSO's DWARF.
287 
288   Symtab *symtab = m_objfile_sp->GetSymtab();
289   if (symtab) {
290     Log *log = GetLog(DWARFLog::DebugMap);
291 
292     std::vector<uint32_t> oso_indexes;
293     // When a mach-o symbol is encoded, the n_type field is encoded in bits
294     // 23:16, and the n_desc field is encoded in bits 15:0.
295     //
296     // To find all N_OSO entries that are part of the DWARF + debug map we find
297     // only object file symbols with the flags value as follows: bits 23:16 ==
298     // 0x66 (N_OSO) bits 15: 0 == 0x0001 (specifies this is a debug map object
299     // file)
300     const uint32_t k_oso_symbol_flags_value = 0x660001u;
301 
302     const uint32_t oso_index_count =
303         symtab->AppendSymbolIndexesWithTypeAndFlagsValue(
304             eSymbolTypeObjectFile, k_oso_symbol_flags_value, oso_indexes);
305 
306     if (oso_index_count > 0) {
307       symtab->AppendSymbolIndexesWithType(eSymbolTypeCode, Symtab::eDebugYes,
308                                           Symtab::eVisibilityAny,
309                                           m_func_indexes);
310       symtab->AppendSymbolIndexesWithType(eSymbolTypeData, Symtab::eDebugYes,
311                                           Symtab::eVisibilityAny,
312                                           m_glob_indexes);
313 
314       symtab->SortSymbolIndexesByValue(m_func_indexes, true);
315       symtab->SortSymbolIndexesByValue(m_glob_indexes, true);
316 
317       for (uint32_t sym_idx : m_func_indexes) {
318         const Symbol *symbol = symtab->SymbolAtIndex(sym_idx);
319         lldb::addr_t file_addr = symbol->GetAddressRef().GetFileAddress();
320         lldb::addr_t byte_size = symbol->GetByteSize();
321         DebugMap::Entry debug_map_entry(
322             file_addr, byte_size, OSOEntry(sym_idx, LLDB_INVALID_ADDRESS));
323         m_debug_map.Append(debug_map_entry);
324       }
325       for (uint32_t sym_idx : m_glob_indexes) {
326         const Symbol *symbol = symtab->SymbolAtIndex(sym_idx);
327         lldb::addr_t file_addr = symbol->GetAddressRef().GetFileAddress();
328         lldb::addr_t byte_size = symbol->GetByteSize();
329         DebugMap::Entry debug_map_entry(
330             file_addr, byte_size, OSOEntry(sym_idx, LLDB_INVALID_ADDRESS));
331         m_debug_map.Append(debug_map_entry);
332       }
333       m_debug_map.Sort();
334 
335       m_compile_unit_infos.resize(oso_index_count);
336 
337       for (uint32_t i = 0; i < oso_index_count; ++i) {
338         const uint32_t so_idx = oso_indexes[i] - 1;
339         const uint32_t oso_idx = oso_indexes[i];
340         const Symbol *so_symbol = symtab->SymbolAtIndex(so_idx);
341         const Symbol *oso_symbol = symtab->SymbolAtIndex(oso_idx);
342         if (so_symbol && oso_symbol &&
343             so_symbol->GetType() == eSymbolTypeSourceFile &&
344             oso_symbol->GetType() == eSymbolTypeObjectFile) {
345           m_compile_unit_infos[i].so_file.SetFile(
346               so_symbol->GetName().AsCString(), FileSpec::Style::native);
347           m_compile_unit_infos[i].oso_path = oso_symbol->GetName();
348           m_compile_unit_infos[i].oso_mod_time =
349               llvm::sys::toTimePoint(oso_symbol->GetIntegerValue(0));
350           uint32_t sibling_idx = so_symbol->GetSiblingIndex();
351           // The sibling index can't be less that or equal to the current index
352           // "i"
353           if (sibling_idx == UINT32_MAX) {
354             m_objfile_sp->GetModule()->ReportError(
355                 "N_SO in symbol with UID {0} has invalid sibling in debug "
356                 "map, "
357                 "please file a bug and attach the binary listed in this error",
358                 so_symbol->GetID());
359           } else {
360             const Symbol *last_symbol = symtab->SymbolAtIndex(sibling_idx - 1);
361             m_compile_unit_infos[i].first_symbol_index = so_idx;
362             m_compile_unit_infos[i].last_symbol_index = sibling_idx - 1;
363             m_compile_unit_infos[i].first_symbol_id = so_symbol->GetID();
364             m_compile_unit_infos[i].last_symbol_id = last_symbol->GetID();
365 
366             LLDB_LOGF(log, "Initialized OSO 0x%8.8x: file=%s", i,
367                       oso_symbol->GetName().GetCString());
368           }
369         } else {
370           if (oso_symbol == nullptr)
371             m_objfile_sp->GetModule()->ReportError(
372                 "N_OSO symbol[{0}] can't be found, please file a bug and "
373                 "attach "
374                 "the binary listed in this error",
375                 oso_idx);
376           else if (so_symbol == nullptr)
377             m_objfile_sp->GetModule()->ReportError(
378                 "N_SO not found for N_OSO symbol[{0}], please file a bug and "
379                 "attach the binary listed in this error",
380                 oso_idx);
381           else if (so_symbol->GetType() != eSymbolTypeSourceFile)
382             m_objfile_sp->GetModule()->ReportError(
383                 "N_SO has incorrect symbol type ({0}) for N_OSO "
384                 "symbol[{1}], "
385                 "please file a bug and attach the binary listed in this error",
386                 so_symbol->GetType(), oso_idx);
387           else if (oso_symbol->GetType() != eSymbolTypeSourceFile)
388             m_objfile_sp->GetModule()->ReportError(
389                 "N_OSO has incorrect symbol type ({0}) for N_OSO "
390                 "symbol[{1}], "
391                 "please file a bug and attach the binary listed in this error",
392                 oso_symbol->GetType(), oso_idx);
393         }
394       }
395     }
396   }
397 }
398 
399 Module *SymbolFileDWARFDebugMap::GetModuleByOSOIndex(uint32_t oso_idx) {
400   const uint32_t cu_count = GetNumCompileUnits();
401   if (oso_idx < cu_count)
402     return GetModuleByCompUnitInfo(&m_compile_unit_infos[oso_idx]);
403   return nullptr;
404 }
405 
406 Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo(
407     CompileUnitInfo *comp_unit_info) {
408   if (!comp_unit_info->oso_sp) {
409     auto pos = m_oso_map.find(
410         {comp_unit_info->oso_path, comp_unit_info->oso_mod_time});
411     if (pos != m_oso_map.end()) {
412       comp_unit_info->oso_sp = pos->second;
413     } else {
414       ObjectFile *obj_file = GetObjectFile();
415       comp_unit_info->oso_sp = std::make_shared<OSOInfo>();
416       m_oso_map[{comp_unit_info->oso_path, comp_unit_info->oso_mod_time}] =
417           comp_unit_info->oso_sp;
418       const char *oso_path = comp_unit_info->oso_path.GetCString();
419       FileSpec oso_file(oso_path);
420       ConstString oso_object;
421       if (FileSystem::Instance().Exists(oso_file)) {
422         // The modification time returned by the FS can have a higher precision
423         // than the one from the CU.
424         auto oso_mod_time = std::chrono::time_point_cast<std::chrono::seconds>(
425             FileSystem::Instance().GetModificationTime(oso_file));
426         // A timestamp of 0 means that the linker was in deterministic mode. In
427         // that case, we should skip the check against the filesystem last
428         // modification timestamp, since it will never match.
429         if (comp_unit_info->oso_mod_time != llvm::sys::TimePoint<>() &&
430             oso_mod_time != comp_unit_info->oso_mod_time) {
431           comp_unit_info->oso_load_error.SetErrorStringWithFormat(
432               "debug map object file \"%s\" changed (actual: 0x%8.8x, debug "
433               "map: 0x%8.8x) since this executable was linked, debug info "
434               "will not be loaded", oso_file.GetPath().c_str(),
435               (uint32_t)llvm::sys::toTimeT(oso_mod_time),
436               (uint32_t)llvm::sys::toTimeT(comp_unit_info->oso_mod_time));
437           obj_file->GetModule()->ReportError(
438               "{0}", comp_unit_info->oso_load_error.AsCString());
439           return nullptr;
440         }
441 
442       } else {
443         const bool must_exist = true;
444 
445         if (!ObjectFile::SplitArchivePathWithObject(oso_path, oso_file,
446                                                     oso_object, must_exist)) {
447           comp_unit_info->oso_load_error.SetErrorStringWithFormat(
448               "debug map object file \"%s\" containing debug info does not "
449               "exist, debug info will not be loaded",
450               comp_unit_info->oso_path.GetCString());
451           return nullptr;
452         }
453       }
454       // Always create a new module for .o files. Why? Because we use the debug
455       // map, to add new sections to each .o file and even though a .o file
456       // might not have changed, the sections that get added to the .o file can
457       // change.
458       ArchSpec oso_arch;
459       // Only adopt the architecture from the module (not the vendor or OS)
460       // since .o files for "i386-apple-ios" will historically show up as "i386
461       // -apple-macosx" due to the lack of a LC_VERSION_MIN_MACOSX or
462       // LC_VERSION_MIN_IPHONEOS load command...
463       oso_arch.SetTriple(m_objfile_sp->GetModule()
464                              ->GetArchitecture()
465                              .GetTriple()
466                              .getArchName()
467                              .str()
468                              .c_str());
469       comp_unit_info->oso_sp->module_sp = std::make_shared<DebugMapModule>(
470           obj_file->GetModule(), GetCompUnitInfoIndex(comp_unit_info), oso_file,
471           oso_arch, oso_object ? &oso_object : nullptr, 0,
472           oso_object ? comp_unit_info->oso_mod_time : llvm::sys::TimePoint<>());
473 
474       if (!comp_unit_info->oso_sp->module_sp || !comp_unit_info->oso_sp->module_sp->GetObjectFile()) {
475         if (oso_object && FileSystem::Instance().Exists(oso_file)) {
476           // If we are loading a .o file from a .a file the "oso_object" will
477           // have a valid value name and if the .a file exists, either the .o
478           // file didn't exist in the .a file or the mod time didn't match.
479           comp_unit_info->oso_load_error.SetErrorStringWithFormat(
480               "\"%s\" object from the \"%s\" archive: "
481               "either the .o file doesn't exist in the archive or the "
482               "modification time (0x%8.8x) of the .o file doesn't match",
483               oso_object.AsCString(), oso_file.GetPath().c_str(),
484               (uint32_t)llvm::sys::toTimeT(comp_unit_info->oso_mod_time));
485         }
486       }
487     }
488   }
489   if (comp_unit_info->oso_sp)
490     return comp_unit_info->oso_sp->module_sp.get();
491   return nullptr;
492 }
493 
494 bool SymbolFileDWARFDebugMap::GetFileSpecForSO(uint32_t oso_idx,
495                                                FileSpec &file_spec) {
496   if (oso_idx < m_compile_unit_infos.size()) {
497     if (m_compile_unit_infos[oso_idx].so_file) {
498       file_spec = m_compile_unit_infos[oso_idx].so_file;
499       return true;
500     }
501   }
502   return false;
503 }
504 
505 ObjectFile *SymbolFileDWARFDebugMap::GetObjectFileByOSOIndex(uint32_t oso_idx) {
506   Module *oso_module = GetModuleByOSOIndex(oso_idx);
507   if (oso_module)
508     return oso_module->GetObjectFile();
509   return nullptr;
510 }
511 
512 SymbolFileDWARF *
513 SymbolFileDWARFDebugMap::GetSymbolFile(const SymbolContext &sc) {
514   return GetSymbolFile(*sc.comp_unit);
515 }
516 
517 SymbolFileDWARF *
518 SymbolFileDWARFDebugMap::GetSymbolFile(const CompileUnit &comp_unit) {
519   CompileUnitInfo *comp_unit_info = GetCompUnitInfo(comp_unit);
520   if (comp_unit_info)
521     return GetSymbolFileByCompUnitInfo(comp_unit_info);
522   return nullptr;
523 }
524 
525 ObjectFile *SymbolFileDWARFDebugMap::GetObjectFileByCompUnitInfo(
526     CompileUnitInfo *comp_unit_info) {
527   Module *oso_module = GetModuleByCompUnitInfo(comp_unit_info);
528   if (oso_module)
529     return oso_module->GetObjectFile();
530   return nullptr;
531 }
532 
533 uint32_t SymbolFileDWARFDebugMap::GetCompUnitInfoIndex(
534     const CompileUnitInfo *comp_unit_info) {
535   if (!m_compile_unit_infos.empty()) {
536     const CompileUnitInfo *first_comp_unit_info = &m_compile_unit_infos.front();
537     const CompileUnitInfo *last_comp_unit_info = &m_compile_unit_infos.back();
538     if (first_comp_unit_info <= comp_unit_info &&
539         comp_unit_info <= last_comp_unit_info)
540       return comp_unit_info - first_comp_unit_info;
541   }
542   return UINT32_MAX;
543 }
544 
545 SymbolFileDWARF *
546 SymbolFileDWARFDebugMap::GetSymbolFileByOSOIndex(uint32_t oso_idx) {
547   unsigned size = m_compile_unit_infos.size();
548   if (oso_idx < size)
549     return GetSymbolFileByCompUnitInfo(&m_compile_unit_infos[oso_idx]);
550   return nullptr;
551 }
552 
553 SymbolFileDWARF *
554 SymbolFileDWARFDebugMap::GetSymbolFileAsSymbolFileDWARF(SymbolFile *sym_file) {
555   if (sym_file &&
556       sym_file->GetPluginName() == SymbolFileDWARF::GetPluginNameStatic())
557     return static_cast<SymbolFileDWARF *>(sym_file);
558   return nullptr;
559 }
560 
561 SymbolFileDWARF *SymbolFileDWARFDebugMap::GetSymbolFileByCompUnitInfo(
562     CompileUnitInfo *comp_unit_info) {
563   if (Module *oso_module = GetModuleByCompUnitInfo(comp_unit_info))
564     return GetSymbolFileAsSymbolFileDWARF(oso_module->GetSymbolFile());
565   return nullptr;
566 }
567 
568 uint32_t SymbolFileDWARFDebugMap::CalculateAbilities() {
569   // In order to get the abilities of this plug-in, we look at the list of
570   // N_OSO entries (object files) from the symbol table and make sure that
571   // these files exist and also contain valid DWARF. If we get any of that then
572   // we return the abilities of the first N_OSO's DWARF.
573 
574   const uint32_t oso_index_count = GetNumCompileUnits();
575   if (oso_index_count > 0) {
576     InitOSO();
577     if (!m_compile_unit_infos.empty()) {
578       return SymbolFile::CompileUnits | SymbolFile::Functions |
579              SymbolFile::Blocks | SymbolFile::GlobalVariables |
580              SymbolFile::LocalVariables | SymbolFile::VariableTypes |
581              SymbolFile::LineTables;
582     }
583   }
584   return 0;
585 }
586 
587 uint32_t SymbolFileDWARFDebugMap::CalculateNumCompileUnits() {
588   InitOSO();
589   return m_compile_unit_infos.size();
590 }
591 
592 CompUnitSP SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx) {
593   CompUnitSP comp_unit_sp;
594   const uint32_t cu_count = GetNumCompileUnits();
595 
596   if (cu_idx < cu_count) {
597     auto &cu_info = m_compile_unit_infos[cu_idx];
598     Module *oso_module = GetModuleByCompUnitInfo(&cu_info);
599     if (oso_module) {
600       FileSpec so_file_spec;
601       if (GetFileSpecForSO(cu_idx, so_file_spec)) {
602         // User zero as the ID to match the compile unit at offset zero in each
603         // .o file.
604         lldb::user_id_t cu_id = 0;
605         cu_info.compile_units_sps.push_back(
606             std::make_shared<CompileUnit>(
607                 m_objfile_sp->GetModule(), nullptr, so_file_spec, cu_id,
608                 eLanguageTypeUnknown, eLazyBoolCalculate));
609         cu_info.id_to_index_map.insert({0, 0});
610         SetCompileUnitAtIndex(cu_idx, cu_info.compile_units_sps[0]);
611         // If there's a symbol file also register all the extra compile units.
612         if (SymbolFileDWARF *oso_symfile =
613                 GetSymbolFileByCompUnitInfo(&cu_info)) {
614           auto num_dwarf_units = oso_symfile->DebugInfo().GetNumUnits();
615           for (size_t i = 0; i < num_dwarf_units; ++i) {
616             auto *dwarf_unit = oso_symfile->DebugInfo().GetUnitAtIndex(i);
617             if (auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(dwarf_unit)) {
618               // The "main" one was already registered.
619               if (dwarf_cu->GetID() == 0)
620                 continue;
621               cu_info.compile_units_sps.push_back(std::make_shared<CompileUnit>(
622                   m_objfile_sp->GetModule(), nullptr, so_file_spec,
623                   dwarf_cu->GetID(), eLanguageTypeUnknown, eLazyBoolCalculate));
624               cu_info.id_to_index_map.insert(
625                   {dwarf_cu->GetID(), cu_info.compile_units_sps.size() - 1});
626             }
627           }
628         }
629       }
630     }
631     if (!cu_info.compile_units_sps.empty())
632       comp_unit_sp = cu_info.compile_units_sps[0];
633   }
634 
635   return comp_unit_sp;
636 }
637 
638 SymbolFileDWARFDebugMap::CompileUnitInfo *
639 SymbolFileDWARFDebugMap::GetCompUnitInfo(const SymbolContext &sc) {
640   return GetCompUnitInfo(*sc.comp_unit);
641 }
642 
643 SymbolFileDWARFDebugMap::CompileUnitInfo *
644 SymbolFileDWARFDebugMap::GetCompUnitInfo(const CompileUnit &comp_unit) {
645   const uint32_t cu_count = GetNumCompileUnits();
646   for (uint32_t i = 0; i < cu_count; ++i) {
647     auto &id_to_index_map = m_compile_unit_infos[i].id_to_index_map;
648 
649     auto it = id_to_index_map.find(comp_unit.GetID());
650     if (it != id_to_index_map.end() &&
651         &comp_unit ==
652             m_compile_unit_infos[i].compile_units_sps[it->getSecond()].get())
653       return &m_compile_unit_infos[i];
654   }
655   return nullptr;
656 }
657 
658 size_t SymbolFileDWARFDebugMap::GetCompUnitInfosForModule(
659     const lldb_private::Module *module,
660     std::vector<CompileUnitInfo *> &cu_infos) {
661   const uint32_t cu_count = GetNumCompileUnits();
662   for (uint32_t i = 0; i < cu_count; ++i) {
663     if (module == GetModuleByCompUnitInfo(&m_compile_unit_infos[i]))
664       cu_infos.push_back(&m_compile_unit_infos[i]);
665   }
666   return cu_infos.size();
667 }
668 
669 lldb::LanguageType
670 SymbolFileDWARFDebugMap::ParseLanguage(CompileUnit &comp_unit) {
671   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
672   SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
673   if (oso_dwarf)
674     return oso_dwarf->ParseLanguage(comp_unit);
675   return eLanguageTypeUnknown;
676 }
677 
678 XcodeSDK SymbolFileDWARFDebugMap::ParseXcodeSDK(CompileUnit &comp_unit) {
679   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
680   SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
681   if (oso_dwarf)
682     return oso_dwarf->ParseXcodeSDK(comp_unit);
683   return {};
684 }
685 
686 size_t SymbolFileDWARFDebugMap::ParseFunctions(CompileUnit &comp_unit) {
687   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
688   SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
689   if (oso_dwarf)
690     return oso_dwarf->ParseFunctions(comp_unit);
691   return 0;
692 }
693 
694 bool SymbolFileDWARFDebugMap::ParseLineTable(CompileUnit &comp_unit) {
695   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
696   SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
697   if (oso_dwarf)
698     return oso_dwarf->ParseLineTable(comp_unit);
699   return false;
700 }
701 
702 bool SymbolFileDWARFDebugMap::ParseDebugMacros(CompileUnit &comp_unit) {
703   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
704   SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
705   if (oso_dwarf)
706     return oso_dwarf->ParseDebugMacros(comp_unit);
707   return false;
708 }
709 
710 bool SymbolFileDWARFDebugMap::ForEachExternalModule(
711     CompileUnit &comp_unit,
712     llvm::DenseSet<lldb_private::SymbolFile *> &visited_symbol_files,
713     llvm::function_ref<bool(Module &)> f) {
714   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
715   SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
716   if (oso_dwarf)
717     return oso_dwarf->ForEachExternalModule(comp_unit, visited_symbol_files, f);
718   return false;
719 }
720 
721 bool SymbolFileDWARFDebugMap::ParseSupportFiles(CompileUnit &comp_unit,
722                                                 FileSpecList &support_files) {
723   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
724   SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
725   if (oso_dwarf)
726     return oso_dwarf->ParseSupportFiles(comp_unit, support_files);
727   return false;
728 }
729 
730 bool SymbolFileDWARFDebugMap::ParseIsOptimized(CompileUnit &comp_unit) {
731   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
732   SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
733   if (oso_dwarf)
734     return oso_dwarf->ParseIsOptimized(comp_unit);
735   return false;
736 }
737 
738 bool SymbolFileDWARFDebugMap::ParseImportedModules(
739     const SymbolContext &sc, std::vector<SourceModule> &imported_modules) {
740   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
741   SymbolFileDWARF *oso_dwarf = GetSymbolFile(sc);
742   if (oso_dwarf)
743     return oso_dwarf->ParseImportedModules(sc, imported_modules);
744   return false;
745 }
746 
747 size_t SymbolFileDWARFDebugMap::ParseBlocksRecursive(Function &func) {
748   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
749   CompileUnit *comp_unit = func.GetCompileUnit();
750   if (!comp_unit)
751     return 0;
752 
753   SymbolFileDWARF *oso_dwarf = GetSymbolFile(*comp_unit);
754   if (oso_dwarf)
755     return oso_dwarf->ParseBlocksRecursive(func);
756   return 0;
757 }
758 
759 size_t SymbolFileDWARFDebugMap::ParseTypes(CompileUnit &comp_unit) {
760   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
761   SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
762   if (oso_dwarf)
763     return oso_dwarf->ParseTypes(comp_unit);
764   return 0;
765 }
766 
767 size_t
768 SymbolFileDWARFDebugMap::ParseVariablesForContext(const SymbolContext &sc) {
769   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
770   SymbolFileDWARF *oso_dwarf = GetSymbolFile(sc);
771   if (oso_dwarf)
772     return oso_dwarf->ParseVariablesForContext(sc);
773   return 0;
774 }
775 
776 Type *SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid) {
777   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
778   const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid);
779   SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
780   if (oso_dwarf)
781     return oso_dwarf->ResolveTypeUID(type_uid);
782   return nullptr;
783 }
784 
785 std::optional<SymbolFile::ArrayInfo>
786 SymbolFileDWARFDebugMap::GetDynamicArrayInfoForUID(
787     lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) {
788   const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid);
789   SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
790   if (oso_dwarf)
791     return oso_dwarf->GetDynamicArrayInfoForUID(type_uid, exe_ctx);
792   return std::nullopt;
793 }
794 
795 bool SymbolFileDWARFDebugMap::CompleteType(CompilerType &compiler_type) {
796   bool success = false;
797   if (compiler_type) {
798     ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
799       if (oso_dwarf->HasForwardDeclForClangType(compiler_type)) {
800         oso_dwarf->CompleteType(compiler_type);
801         success = true;
802         return true;
803       }
804       return false;
805     });
806   }
807   return success;
808 }
809 
810 uint32_t
811 SymbolFileDWARFDebugMap::ResolveSymbolContext(const Address &exe_so_addr,
812                                               SymbolContextItem resolve_scope,
813                                               SymbolContext &sc) {
814   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
815   uint32_t resolved_flags = 0;
816   Symtab *symtab = m_objfile_sp->GetSymtab();
817   if (symtab) {
818     const addr_t exe_file_addr = exe_so_addr.GetFileAddress();
819 
820     const DebugMap::Entry *debug_map_entry =
821         m_debug_map.FindEntryThatContains(exe_file_addr);
822     if (debug_map_entry) {
823 
824       sc.symbol =
825           symtab->SymbolAtIndex(debug_map_entry->data.GetExeSymbolIndex());
826 
827       if (sc.symbol != nullptr) {
828         resolved_flags |= eSymbolContextSymbol;
829 
830         uint32_t oso_idx = 0;
831         CompileUnitInfo *comp_unit_info =
832             GetCompileUnitInfoForSymbolWithID(sc.symbol->GetID(), &oso_idx);
833         if (comp_unit_info) {
834           comp_unit_info->GetFileRangeMap(this);
835           Module *oso_module = GetModuleByCompUnitInfo(comp_unit_info);
836           if (oso_module) {
837             lldb::addr_t oso_file_addr =
838                 exe_file_addr - debug_map_entry->GetRangeBase() +
839                 debug_map_entry->data.GetOSOFileAddress();
840             Address oso_so_addr;
841             if (oso_module->ResolveFileAddress(oso_file_addr, oso_so_addr)) {
842               resolved_flags |=
843                   oso_module->GetSymbolFile()->ResolveSymbolContext(
844                       oso_so_addr, resolve_scope, sc);
845             }
846           }
847         }
848       }
849     }
850   }
851   return resolved_flags;
852 }
853 
854 uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext(
855     const SourceLocationSpec &src_location_spec,
856     SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
857   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
858   const uint32_t initial = sc_list.GetSize();
859   const uint32_t cu_count = GetNumCompileUnits();
860 
861   for (uint32_t i = 0; i < cu_count; ++i) {
862     // If we are checking for inlines, then we need to look through all compile
863     // units no matter if "file_spec" matches.
864     bool resolve = src_location_spec.GetCheckInlines();
865 
866     if (!resolve) {
867       FileSpec so_file_spec;
868       if (GetFileSpecForSO(i, so_file_spec))
869         resolve =
870             FileSpec::Match(src_location_spec.GetFileSpec(), so_file_spec);
871     }
872     if (resolve) {
873       SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(i);
874       if (oso_dwarf)
875         oso_dwarf->ResolveSymbolContext(src_location_spec, resolve_scope,
876                                         sc_list);
877     }
878   }
879   return sc_list.GetSize() - initial;
880 }
881 
882 void SymbolFileDWARFDebugMap::PrivateFindGlobalVariables(
883     ConstString name, const CompilerDeclContext &parent_decl_ctx,
884     const std::vector<uint32_t>
885         &indexes, // Indexes into the symbol table that match "name"
886     uint32_t max_matches, VariableList &variables) {
887   const size_t match_count = indexes.size();
888   for (size_t i = 0; i < match_count; ++i) {
889     uint32_t oso_idx;
890     CompileUnitInfo *comp_unit_info =
891         GetCompileUnitInfoForSymbolWithIndex(indexes[i], &oso_idx);
892     if (comp_unit_info) {
893       SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
894       if (oso_dwarf) {
895         oso_dwarf->FindGlobalVariables(name, parent_decl_ctx, max_matches,
896                                        variables);
897         if (variables.GetSize() > max_matches)
898           break;
899       }
900     }
901   }
902 }
903 
904 void SymbolFileDWARFDebugMap::FindGlobalVariables(
905     ConstString name, const CompilerDeclContext &parent_decl_ctx,
906     uint32_t max_matches, VariableList &variables) {
907   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
908   uint32_t total_matches = 0;
909 
910   ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
911     const uint32_t old_size = variables.GetSize();
912     oso_dwarf->FindGlobalVariables(name, parent_decl_ctx, max_matches,
913                                    variables);
914     const uint32_t oso_matches = variables.GetSize() - old_size;
915     if (oso_matches > 0) {
916       total_matches += oso_matches;
917 
918       // Are we getting all matches?
919       if (max_matches == UINT32_MAX)
920         return false; // Yep, continue getting everything
921 
922       // If we have found enough matches, lets get out
923       if (max_matches >= total_matches)
924         return true;
925 
926       // Update the max matches for any subsequent calls to find globals in any
927       // other object files with DWARF
928       max_matches -= oso_matches;
929     }
930 
931     return false;
932   });
933 }
934 
935 void SymbolFileDWARFDebugMap::FindGlobalVariables(
936     const RegularExpression &regex, uint32_t max_matches,
937     VariableList &variables) {
938   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
939   uint32_t total_matches = 0;
940   ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
941     const uint32_t old_size = variables.GetSize();
942     oso_dwarf->FindGlobalVariables(regex, max_matches, variables);
943 
944     const uint32_t oso_matches = variables.GetSize() - old_size;
945     if (oso_matches > 0) {
946       total_matches += oso_matches;
947 
948       // Are we getting all matches?
949       if (max_matches == UINT32_MAX)
950         return false; // Yep, continue getting everything
951 
952       // If we have found enough matches, lets get out
953       if (max_matches >= total_matches)
954         return true;
955 
956       // Update the max matches for any subsequent calls to find globals in any
957       // other object files with DWARF
958       max_matches -= oso_matches;
959     }
960 
961     return false;
962   });
963 }
964 
965 int SymbolFileDWARFDebugMap::SymbolContainsSymbolWithIndex(
966     uint32_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info) {
967   const uint32_t symbol_idx = *symbol_idx_ptr;
968 
969   if (symbol_idx < comp_unit_info->first_symbol_index)
970     return -1;
971 
972   if (symbol_idx <= comp_unit_info->last_symbol_index)
973     return 0;
974 
975   return 1;
976 }
977 
978 int SymbolFileDWARFDebugMap::SymbolContainsSymbolWithID(
979     user_id_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info) {
980   const user_id_t symbol_id = *symbol_idx_ptr;
981 
982   if (symbol_id < comp_unit_info->first_symbol_id)
983     return -1;
984 
985   if (symbol_id <= comp_unit_info->last_symbol_id)
986     return 0;
987 
988   return 1;
989 }
990 
991 SymbolFileDWARFDebugMap::CompileUnitInfo *
992 SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithIndex(
993     uint32_t symbol_idx, uint32_t *oso_idx_ptr) {
994   const uint32_t oso_index_count = m_compile_unit_infos.size();
995   CompileUnitInfo *comp_unit_info = nullptr;
996   if (oso_index_count) {
997     comp_unit_info = (CompileUnitInfo *)bsearch(
998         &symbol_idx, &m_compile_unit_infos[0], m_compile_unit_infos.size(),
999         sizeof(CompileUnitInfo),
1000         (ComparisonFunction)SymbolContainsSymbolWithIndex);
1001   }
1002 
1003   if (oso_idx_ptr) {
1004     if (comp_unit_info != nullptr)
1005       *oso_idx_ptr = comp_unit_info - &m_compile_unit_infos[0];
1006     else
1007       *oso_idx_ptr = UINT32_MAX;
1008   }
1009   return comp_unit_info;
1010 }
1011 
1012 SymbolFileDWARFDebugMap::CompileUnitInfo *
1013 SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithID(
1014     user_id_t symbol_id, uint32_t *oso_idx_ptr) {
1015   const uint32_t oso_index_count = m_compile_unit_infos.size();
1016   CompileUnitInfo *comp_unit_info = nullptr;
1017   if (oso_index_count) {
1018     comp_unit_info = (CompileUnitInfo *)::bsearch(
1019         &symbol_id, &m_compile_unit_infos[0], m_compile_unit_infos.size(),
1020         sizeof(CompileUnitInfo),
1021         (ComparisonFunction)SymbolContainsSymbolWithID);
1022   }
1023 
1024   if (oso_idx_ptr) {
1025     if (comp_unit_info != nullptr)
1026       *oso_idx_ptr = comp_unit_info - &m_compile_unit_infos[0];
1027     else
1028       *oso_idx_ptr = UINT32_MAX;
1029   }
1030   return comp_unit_info;
1031 }
1032 
1033 static void RemoveFunctionsWithModuleNotEqualTo(const ModuleSP &module_sp,
1034                                                 SymbolContextList &sc_list,
1035                                                 uint32_t start_idx) {
1036   // We found functions in .o files. Not all functions in the .o files will
1037   // have made it into the final output file. The ones that did make it into
1038   // the final output file will have a section whose module matches the module
1039   // from the ObjectFile for this SymbolFile. When the modules don't match,
1040   // then we have something that was in a .o file, but doesn't map to anything
1041   // in the final executable.
1042   uint32_t i = start_idx;
1043   while (i < sc_list.GetSize()) {
1044     SymbolContext sc;
1045     sc_list.GetContextAtIndex(i, sc);
1046     if (sc.function) {
1047       const SectionSP section_sp(
1048           sc.function->GetAddressRange().GetBaseAddress().GetSection());
1049       if (section_sp->GetModule() != module_sp) {
1050         sc_list.RemoveContextAtIndex(i);
1051         continue;
1052       }
1053     }
1054     ++i;
1055   }
1056 }
1057 
1058 void SymbolFileDWARFDebugMap::FindFunctions(
1059     const Module::LookupInfo &lookup_info,
1060     const CompilerDeclContext &parent_decl_ctx, bool include_inlines,
1061     SymbolContextList &sc_list) {
1062   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1063   LLDB_SCOPED_TIMERF("SymbolFileDWARFDebugMap::FindFunctions (name = %s)",
1064                      lookup_info.GetLookupName().GetCString());
1065 
1066   ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1067     uint32_t sc_idx = sc_list.GetSize();
1068     oso_dwarf->FindFunctions(lookup_info, parent_decl_ctx, include_inlines,
1069                              sc_list);
1070     if (!sc_list.IsEmpty()) {
1071       RemoveFunctionsWithModuleNotEqualTo(m_objfile_sp->GetModule(), sc_list,
1072                                           sc_idx);
1073     }
1074     return false;
1075   });
1076 }
1077 
1078 void SymbolFileDWARFDebugMap::FindFunctions(const RegularExpression &regex,
1079                                             bool include_inlines,
1080                                             SymbolContextList &sc_list) {
1081   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1082   LLDB_SCOPED_TIMERF("SymbolFileDWARFDebugMap::FindFunctions (regex = '%s')",
1083                      regex.GetText().str().c_str());
1084 
1085   ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1086     uint32_t sc_idx = sc_list.GetSize();
1087 
1088     oso_dwarf->FindFunctions(regex, include_inlines, sc_list);
1089     if (!sc_list.IsEmpty()) {
1090       RemoveFunctionsWithModuleNotEqualTo(m_objfile_sp->GetModule(), sc_list,
1091                                           sc_idx);
1092     }
1093     return false;
1094   });
1095 }
1096 
1097 void SymbolFileDWARFDebugMap::GetTypes(SymbolContextScope *sc_scope,
1098                                        lldb::TypeClass type_mask,
1099                                        TypeList &type_list) {
1100   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1101   LLDB_SCOPED_TIMERF("SymbolFileDWARFDebugMap::GetTypes (type_mask = 0x%8.8x)",
1102                      type_mask);
1103 
1104   SymbolFileDWARF *oso_dwarf = nullptr;
1105   if (sc_scope) {
1106     SymbolContext sc;
1107     sc_scope->CalculateSymbolContext(&sc);
1108 
1109     CompileUnitInfo *cu_info = GetCompUnitInfo(sc);
1110     if (cu_info) {
1111       oso_dwarf = GetSymbolFileByCompUnitInfo(cu_info);
1112       if (oso_dwarf)
1113         oso_dwarf->GetTypes(sc_scope, type_mask, type_list);
1114     }
1115   } else {
1116     ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1117       oso_dwarf->GetTypes(sc_scope, type_mask, type_list);
1118       return false;
1119     });
1120   }
1121 }
1122 
1123 std::vector<std::unique_ptr<lldb_private::CallEdge>>
1124 SymbolFileDWARFDebugMap::ParseCallEdgesInFunction(UserID func_id) {
1125   uint32_t oso_idx = GetOSOIndexFromUserID(func_id.GetID());
1126   SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
1127   if (oso_dwarf)
1128     return oso_dwarf->ParseCallEdgesInFunction(func_id);
1129   return {};
1130 }
1131 
1132 TypeSP SymbolFileDWARFDebugMap::FindDefinitionTypeForDWARFDeclContext(
1133     const DWARFDIE &die) {
1134   TypeSP type_sp;
1135   ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1136     type_sp = oso_dwarf->FindDefinitionTypeForDWARFDeclContext(die);
1137     return ((bool)type_sp);
1138   });
1139   return type_sp;
1140 }
1141 
1142 bool SymbolFileDWARFDebugMap::Supports_DW_AT_APPLE_objc_complete_type(
1143     SymbolFileDWARF *skip_dwarf_oso) {
1144   if (m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolCalculate) {
1145     m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolNo;
1146     ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1147       if (skip_dwarf_oso != oso_dwarf &&
1148           oso_dwarf->Supports_DW_AT_APPLE_objc_complete_type(nullptr)) {
1149         m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolYes;
1150         return true;
1151       }
1152       return false;
1153     });
1154   }
1155   return m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolYes;
1156 }
1157 
1158 TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE(
1159     const DWARFDIE &die, ConstString type_name,
1160     bool must_be_implementation) {
1161   // If we have a debug map, we will have an Objective-C symbol whose name is
1162   // the type name and whose type is eSymbolTypeObjCClass. If we can find that
1163   // symbol and find its containing parent, we can locate the .o file that will
1164   // contain the implementation definition since it will be scoped inside the
1165   // N_SO and we can then locate the SymbolFileDWARF that corresponds to that
1166   // N_SO.
1167   SymbolFileDWARF *oso_dwarf = nullptr;
1168   TypeSP type_sp;
1169   ObjectFile *module_objfile = m_objfile_sp->GetModule()->GetObjectFile();
1170   if (module_objfile) {
1171     Symtab *symtab = module_objfile->GetSymtab();
1172     if (symtab) {
1173       Symbol *objc_class_symbol = symtab->FindFirstSymbolWithNameAndType(
1174           type_name, eSymbolTypeObjCClass, Symtab::eDebugAny,
1175           Symtab::eVisibilityAny);
1176       if (objc_class_symbol) {
1177         // Get the N_SO symbol that contains the objective C class symbol as
1178         // this should be the .o file that contains the real definition...
1179         const Symbol *source_file_symbol = symtab->GetParent(objc_class_symbol);
1180 
1181         if (source_file_symbol &&
1182             source_file_symbol->GetType() == eSymbolTypeSourceFile) {
1183           const uint32_t source_file_symbol_idx =
1184               symtab->GetIndexForSymbol(source_file_symbol);
1185           if (source_file_symbol_idx != UINT32_MAX) {
1186             CompileUnitInfo *compile_unit_info =
1187                 GetCompileUnitInfoForSymbolWithIndex(source_file_symbol_idx,
1188                                                      nullptr);
1189             if (compile_unit_info) {
1190               oso_dwarf = GetSymbolFileByCompUnitInfo(compile_unit_info);
1191               if (oso_dwarf) {
1192                 TypeSP type_sp(oso_dwarf->FindCompleteObjCDefinitionTypeForDIE(
1193                     die, type_name, must_be_implementation));
1194                 if (type_sp) {
1195                   return type_sp;
1196                 }
1197               }
1198             }
1199           }
1200         }
1201       }
1202     }
1203   }
1204 
1205   // Only search all .o files for the definition if we don't need the
1206   // implementation because otherwise, with a valid debug map we should have
1207   // the ObjC class symbol and the code above should have found it.
1208   if (!must_be_implementation) {
1209     TypeSP type_sp;
1210 
1211     ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1212       type_sp = oso_dwarf->FindCompleteObjCDefinitionTypeForDIE(
1213           die, type_name, must_be_implementation);
1214       return (bool)type_sp;
1215     });
1216 
1217     return type_sp;
1218   }
1219   return TypeSP();
1220 }
1221 
1222 void SymbolFileDWARFDebugMap::FindTypes(
1223     ConstString name, const CompilerDeclContext &parent_decl_ctx,
1224     uint32_t max_matches,
1225     llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
1226     TypeMap &types) {
1227   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1228   ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1229     oso_dwarf->FindTypes(name, parent_decl_ctx, max_matches,
1230                          searched_symbol_files, types);
1231     return types.GetSize() >= max_matches;
1232   });
1233 }
1234 
1235 void SymbolFileDWARFDebugMap::FindTypes(
1236     llvm::ArrayRef<CompilerContext> context, LanguageSet languages,
1237     llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
1238     TypeMap &types) {
1239   LLDB_SCOPED_TIMER();
1240   ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1241     oso_dwarf->FindTypes(context, languages, searched_symbol_files, types);
1242     return false;
1243   });
1244 }
1245 
1246 CompilerDeclContext SymbolFileDWARFDebugMap::FindNamespace(
1247     lldb_private::ConstString name,
1248     const CompilerDeclContext &parent_decl_ctx) {
1249   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1250   CompilerDeclContext matching_namespace;
1251 
1252   ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1253     matching_namespace = oso_dwarf->FindNamespace(name, parent_decl_ctx);
1254 
1255     return (bool)matching_namespace;
1256   });
1257 
1258   return matching_namespace;
1259 }
1260 
1261 void SymbolFileDWARFDebugMap::DumpClangAST(Stream &s) {
1262   ForEachSymbolFile([&s](SymbolFileDWARF *oso_dwarf) -> bool {
1263     oso_dwarf->DumpClangAST(s);
1264     // The underlying assumption is that DumpClangAST(...) will obtain the
1265     // AST from the underlying TypeSystem and therefore we only need to do
1266     // this once and can stop after the first iteration hence we return true.
1267     return true;
1268   });
1269 }
1270 
1271 lldb::CompUnitSP
1272 SymbolFileDWARFDebugMap::GetCompileUnit(SymbolFileDWARF *oso_dwarf, DWARFCompileUnit &dwarf_cu) {
1273   if (oso_dwarf) {
1274     const uint32_t cu_count = GetNumCompileUnits();
1275     for (uint32_t cu_idx = 0; cu_idx < cu_count; ++cu_idx) {
1276       SymbolFileDWARF *oso_symfile =
1277           GetSymbolFileByCompUnitInfo(&m_compile_unit_infos[cu_idx]);
1278       if (oso_symfile == oso_dwarf) {
1279         if (m_compile_unit_infos[cu_idx].compile_units_sps.empty())
1280           ParseCompileUnitAtIndex(cu_idx);
1281 
1282         auto &id_to_index_map = m_compile_unit_infos[cu_idx].id_to_index_map;
1283         auto it = id_to_index_map.find(dwarf_cu.GetID());
1284         if (it != id_to_index_map.end())
1285           return m_compile_unit_infos[cu_idx]
1286               .compile_units_sps[it->getSecond()];
1287       }
1288     }
1289   }
1290   llvm_unreachable("this shouldn't happen");
1291 }
1292 
1293 SymbolFileDWARFDebugMap::CompileUnitInfo *
1294 SymbolFileDWARFDebugMap::GetCompileUnitInfo(SymbolFileDWARF *oso_dwarf) {
1295   if (oso_dwarf) {
1296     const uint32_t cu_count = GetNumCompileUnits();
1297     for (uint32_t cu_idx = 0; cu_idx < cu_count; ++cu_idx) {
1298       SymbolFileDWARF *oso_symfile =
1299           GetSymbolFileByCompUnitInfo(&m_compile_unit_infos[cu_idx]);
1300       if (oso_symfile == oso_dwarf) {
1301         return &m_compile_unit_infos[cu_idx];
1302       }
1303     }
1304   }
1305   return nullptr;
1306 }
1307 
1308 void SymbolFileDWARFDebugMap::SetCompileUnit(SymbolFileDWARF *oso_dwarf,
1309                                              const CompUnitSP &cu_sp) {
1310   if (oso_dwarf) {
1311     const uint32_t cu_count = GetNumCompileUnits();
1312     for (uint32_t cu_idx = 0; cu_idx < cu_count; ++cu_idx) {
1313       SymbolFileDWARF *oso_symfile =
1314           GetSymbolFileByCompUnitInfo(&m_compile_unit_infos[cu_idx]);
1315       if (oso_symfile == oso_dwarf) {
1316         if (!m_compile_unit_infos[cu_idx].compile_units_sps.empty()) {
1317           assert(m_compile_unit_infos[cu_idx].compile_units_sps[0].get() ==
1318                  cu_sp.get());
1319         } else {
1320           assert(cu_sp->GetID() == 0 &&
1321                  "Setting first compile unit but with id different than 0!");
1322           auto &compile_units_sps = m_compile_unit_infos[cu_idx].compile_units_sps;
1323           compile_units_sps.push_back(cu_sp);
1324           m_compile_unit_infos[cu_idx].id_to_index_map.insert(
1325               {cu_sp->GetID(), compile_units_sps.size() - 1});
1326 
1327           SetCompileUnitAtIndex(cu_idx, cu_sp);
1328         }
1329       }
1330     }
1331   }
1332 }
1333 
1334 CompilerDeclContext
1335 SymbolFileDWARFDebugMap::GetDeclContextForUID(lldb::user_id_t type_uid) {
1336   const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid);
1337   SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
1338   if (oso_dwarf)
1339     return oso_dwarf->GetDeclContextForUID(type_uid);
1340   return CompilerDeclContext();
1341 }
1342 
1343 CompilerDeclContext
1344 SymbolFileDWARFDebugMap::GetDeclContextContainingUID(lldb::user_id_t type_uid) {
1345   const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid);
1346   SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
1347   if (oso_dwarf)
1348     return oso_dwarf->GetDeclContextContainingUID(type_uid);
1349   return CompilerDeclContext();
1350 }
1351 
1352 void SymbolFileDWARFDebugMap::ParseDeclsForContext(
1353     lldb_private::CompilerDeclContext decl_ctx) {
1354   ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1355     oso_dwarf->ParseDeclsForContext(decl_ctx);
1356     return true; // Keep iterating
1357   });
1358 }
1359 
1360 bool SymbolFileDWARFDebugMap::AddOSOFileRange(CompileUnitInfo *cu_info,
1361                                               lldb::addr_t exe_file_addr,
1362                                               lldb::addr_t exe_byte_size,
1363                                               lldb::addr_t oso_file_addr,
1364                                               lldb::addr_t oso_byte_size) {
1365   const uint32_t debug_map_idx =
1366       m_debug_map.FindEntryIndexThatContains(exe_file_addr);
1367   if (debug_map_idx != UINT32_MAX) {
1368     DebugMap::Entry *debug_map_entry =
1369         m_debug_map.FindEntryThatContains(exe_file_addr);
1370     debug_map_entry->data.SetOSOFileAddress(oso_file_addr);
1371     addr_t range_size = std::min<addr_t>(exe_byte_size, oso_byte_size);
1372     if (range_size == 0) {
1373       range_size = std::max<addr_t>(exe_byte_size, oso_byte_size);
1374       if (range_size == 0)
1375         range_size = 1;
1376     }
1377     cu_info->file_range_map.Append(
1378         FileRangeMap::Entry(oso_file_addr, range_size, exe_file_addr));
1379     return true;
1380   }
1381   return false;
1382 }
1383 
1384 void SymbolFileDWARFDebugMap::FinalizeOSOFileRanges(CompileUnitInfo *cu_info) {
1385   cu_info->file_range_map.Sort();
1386 #if defined(DEBUG_OSO_DMAP)
1387   const FileRangeMap &oso_file_range_map = cu_info->GetFileRangeMap(this);
1388   const size_t n = oso_file_range_map.GetSize();
1389   printf("SymbolFileDWARFDebugMap::FinalizeOSOFileRanges (cu_info = %p) %s\n",
1390          cu_info, cu_info->oso_sp->module_sp->GetFileSpec().GetPath().c_str());
1391   for (size_t i = 0; i < n; ++i) {
1392     const FileRangeMap::Entry &entry = oso_file_range_map.GetEntryRef(i);
1393     printf("oso [0x%16.16" PRIx64 " - 0x%16.16" PRIx64
1394            ") ==> exe [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n",
1395            entry.GetRangeBase(), entry.GetRangeEnd(), entry.data,
1396            entry.data + entry.GetByteSize());
1397   }
1398 #endif
1399 }
1400 
1401 lldb::addr_t
1402 SymbolFileDWARFDebugMap::LinkOSOFileAddress(SymbolFileDWARF *oso_symfile,
1403                                             lldb::addr_t oso_file_addr) {
1404   CompileUnitInfo *cu_info = GetCompileUnitInfo(oso_symfile);
1405   if (cu_info) {
1406     const FileRangeMap::Entry *oso_range_entry =
1407         cu_info->GetFileRangeMap(this).FindEntryThatContains(oso_file_addr);
1408     if (oso_range_entry) {
1409       const DebugMap::Entry *debug_map_entry =
1410           m_debug_map.FindEntryThatContains(oso_range_entry->data);
1411       if (debug_map_entry) {
1412         const lldb::addr_t offset =
1413             oso_file_addr - oso_range_entry->GetRangeBase();
1414         const lldb::addr_t exe_file_addr =
1415             debug_map_entry->GetRangeBase() + offset;
1416         return exe_file_addr;
1417       }
1418     }
1419   }
1420   return LLDB_INVALID_ADDRESS;
1421 }
1422 
1423 bool SymbolFileDWARFDebugMap::LinkOSOAddress(Address &addr) {
1424   // Make sure this address hasn't been fixed already
1425   Module *exe_module = GetObjectFile()->GetModule().get();
1426   Module *addr_module = addr.GetModule().get();
1427   if (addr_module == exe_module)
1428     return true; // Address is already in terms of the main executable module
1429 
1430   CompileUnitInfo *cu_info = GetCompileUnitInfo(
1431       GetSymbolFileAsSymbolFileDWARF(addr_module->GetSymbolFile()));
1432   if (cu_info) {
1433     const lldb::addr_t oso_file_addr = addr.GetFileAddress();
1434     const FileRangeMap::Entry *oso_range_entry =
1435         cu_info->GetFileRangeMap(this).FindEntryThatContains(oso_file_addr);
1436     if (oso_range_entry) {
1437       const DebugMap::Entry *debug_map_entry =
1438           m_debug_map.FindEntryThatContains(oso_range_entry->data);
1439       if (debug_map_entry) {
1440         const lldb::addr_t offset =
1441             oso_file_addr - oso_range_entry->GetRangeBase();
1442         const lldb::addr_t exe_file_addr =
1443             debug_map_entry->GetRangeBase() + offset;
1444         return exe_module->ResolveFileAddress(exe_file_addr, addr);
1445       }
1446     }
1447   }
1448   return true;
1449 }
1450 
1451 LineTable *SymbolFileDWARFDebugMap::LinkOSOLineTable(SymbolFileDWARF *oso_dwarf,
1452                                                      LineTable *line_table) {
1453   CompileUnitInfo *cu_info = GetCompileUnitInfo(oso_dwarf);
1454   if (cu_info)
1455     return line_table->LinkLineTable(cu_info->GetFileRangeMap(this));
1456   return nullptr;
1457 }
1458 
1459 size_t
1460 SymbolFileDWARFDebugMap::AddOSOARanges(SymbolFileDWARF *dwarf2Data,
1461                                        DWARFDebugAranges *debug_aranges) {
1462   size_t num_line_entries_added = 0;
1463   if (debug_aranges && dwarf2Data) {
1464     CompileUnitInfo *compile_unit_info = GetCompileUnitInfo(dwarf2Data);
1465     if (compile_unit_info) {
1466       const FileRangeMap &file_range_map =
1467           compile_unit_info->GetFileRangeMap(this);
1468       for (size_t idx = 0; idx < file_range_map.GetSize(); idx++) {
1469         const FileRangeMap::Entry *entry = file_range_map.GetEntryAtIndex(idx);
1470         if (entry) {
1471           debug_aranges->AppendRange(dwarf2Data->GetID(), entry->GetRangeBase(),
1472                                      entry->GetRangeEnd());
1473           num_line_entries_added++;
1474         }
1475       }
1476     }
1477   }
1478   return num_line_entries_added;
1479 }
1480 
1481 ModuleList SymbolFileDWARFDebugMap::GetDebugInfoModules() {
1482   ModuleList oso_modules;
1483   ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1484     ObjectFile *oso_objfile = oso_dwarf->GetObjectFile();
1485     if (oso_objfile) {
1486       ModuleSP module_sp = oso_objfile->GetModule();
1487       if (module_sp)
1488         oso_modules.Append(module_sp);
1489     }
1490     return false; // Keep iterating
1491   });
1492   return oso_modules;
1493 }
1494 
1495 Status SymbolFileDWARFDebugMap::CalculateFrameVariableError(StackFrame &frame) {
1496   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1497 
1498   // We need to make sure that our PC value from the frame matches the module
1499   // for this object file since we will lookup the PC file address in the debug
1500   // map below.
1501   Address pc_addr = frame.GetFrameCodeAddress();
1502   if (pc_addr.GetModule() == m_objfile_sp->GetModule()) {
1503     Symtab *symtab = m_objfile_sp->GetSymtab();
1504     if (symtab) {
1505       const DebugMap::Entry *debug_map_entry =
1506           m_debug_map.FindEntryThatContains(pc_addr.GetFileAddress());
1507       if (debug_map_entry) {
1508         Symbol *symbol =
1509             symtab->SymbolAtIndex(debug_map_entry->data.GetExeSymbolIndex());
1510         if (symbol) {
1511           uint32_t oso_idx = 0;
1512           CompileUnitInfo *comp_unit_info =
1513               GetCompileUnitInfoForSymbolWithID(symbol->GetID(), &oso_idx);
1514           if (comp_unit_info) {
1515             Module *oso_module = GetModuleByCompUnitInfo(comp_unit_info);
1516             if (oso_module) {
1517               // Check the .o file's DWARF in case it has an error to display.
1518               SymbolFile *oso_sym_file = oso_module->GetSymbolFile();
1519               if (oso_sym_file)
1520                 return oso_sym_file->GetFrameVariableError(frame);
1521             }
1522             // If we don't have a valid OSO module here, then something went
1523             // wrong as we have a symbol for the address in the debug map, but
1524             // we weren't able to open the .o file. Display an appropriate
1525             // error
1526             if (comp_unit_info->oso_load_error.Fail())
1527               return comp_unit_info->oso_load_error;
1528             else
1529               return Status("unable to load debug map object file \"%s\" "
1530                             "exist, debug info will not be loaded",
1531                             comp_unit_info->oso_path.GetCString());
1532           }
1533         }
1534       }
1535     }
1536   }
1537   return Status();
1538 }
1539