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