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