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
44using namespace lldb;
45using namespace lldb_private;
46using namespace lldb_private::plugin::dwarf;
47
48char 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
54const SymbolFileDWARFDebugMap::FileRangeMap &
55SymbolFileDWARFDebugMap::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
171namespace lldb_private::plugin {
172namespace dwarf {
173class DebugMapModule : public Module {
174public:
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
225protected:
226  ModuleWP m_exe_module_wp;
227  const uint32_t m_cu_idx;
228};
229} // namespace dwarf
230} // namespace lldb_private::plugin
231
232void SymbolFileDWARFDebugMap::Initialize() {
233  PluginManager::RegisterPlugin(GetPluginNameStatic(),
234                                GetPluginDescriptionStatic(), CreateInstance);
235}
236
237void SymbolFileDWARFDebugMap::Terminate() {
238  PluginManager::UnregisterPlugin(CreateInstance);
239}
240
241llvm::StringRef SymbolFileDWARFDebugMap::GetPluginDescriptionStatic() {
242  return "DWARF and DWARF3 debug symbol file reader (debug map).";
243}
244
245SymbolFile *SymbolFileDWARFDebugMap::CreateInstance(ObjectFileSP objfile_sp) {
246  return new SymbolFileDWARFDebugMap(std::move(objfile_sp));
247}
248
249SymbolFileDWARFDebugMap::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
254SymbolFileDWARFDebugMap::~SymbolFileDWARFDebugMap() = default;
255
256void SymbolFileDWARFDebugMap::InitializeObject() {}
257
258void 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
396Module *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
403Module *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
490bool 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
501ObjectFile *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
508SymbolFileDWARF *
509SymbolFileDWARFDebugMap::GetSymbolFile(const SymbolContext &sc) {
510  return GetSymbolFile(*sc.comp_unit);
511}
512
513SymbolFileDWARF *
514SymbolFileDWARFDebugMap::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
521ObjectFile *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
529uint32_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
541SymbolFileDWARF *
542SymbolFileDWARFDebugMap::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
549SymbolFileDWARF *
550SymbolFileDWARFDebugMap::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
557SymbolFileDWARF *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
564uint32_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
583uint32_t SymbolFileDWARFDebugMap::CalculateNumCompileUnits() {
584  InitOSO();
585  return m_compile_unit_infos.size();
586}
587
588CompUnitSP 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(std::make_shared<CompileUnit>(
602            m_objfile_sp->GetModule(), nullptr,
603            std::make_shared<SupportFile>(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,
619                  std::make_shared<SupportFile>(so_file_spec),
620                  dwarf_cu->GetID(), eLanguageTypeUnknown, eLazyBoolCalculate));
621              cu_info.id_to_index_map.insert(
622                  {dwarf_cu->GetID(), cu_info.compile_units_sps.size() - 1});
623            }
624          }
625        }
626      }
627    }
628    if (!cu_info.compile_units_sps.empty())
629      comp_unit_sp = cu_info.compile_units_sps[0];
630  }
631
632  return comp_unit_sp;
633}
634
635SymbolFileDWARFDebugMap::CompileUnitInfo *
636SymbolFileDWARFDebugMap::GetCompUnitInfo(const SymbolContext &sc) {
637  return GetCompUnitInfo(*sc.comp_unit);
638}
639
640SymbolFileDWARFDebugMap::CompileUnitInfo *
641SymbolFileDWARFDebugMap::GetCompUnitInfo(const CompileUnit &comp_unit) {
642  const uint32_t cu_count = GetNumCompileUnits();
643  for (uint32_t i = 0; i < cu_count; ++i) {
644    auto &id_to_index_map = m_compile_unit_infos[i].id_to_index_map;
645
646    auto it = id_to_index_map.find(comp_unit.GetID());
647    if (it != id_to_index_map.end() &&
648        &comp_unit ==
649            m_compile_unit_infos[i].compile_units_sps[it->getSecond()].get())
650      return &m_compile_unit_infos[i];
651  }
652  return nullptr;
653}
654
655size_t SymbolFileDWARFDebugMap::GetCompUnitInfosForModule(
656    const lldb_private::Module *module,
657    std::vector<CompileUnitInfo *> &cu_infos) {
658  const uint32_t cu_count = GetNumCompileUnits();
659  for (uint32_t i = 0; i < cu_count; ++i) {
660    if (module == GetModuleByCompUnitInfo(&m_compile_unit_infos[i]))
661      cu_infos.push_back(&m_compile_unit_infos[i]);
662  }
663  return cu_infos.size();
664}
665
666lldb::LanguageType
667SymbolFileDWARFDebugMap::ParseLanguage(CompileUnit &comp_unit) {
668  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
669  SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
670  if (oso_dwarf)
671    return oso_dwarf->ParseLanguage(comp_unit);
672  return eLanguageTypeUnknown;
673}
674
675XcodeSDK SymbolFileDWARFDebugMap::ParseXcodeSDK(CompileUnit &comp_unit) {
676  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
677  SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
678  if (oso_dwarf)
679    return oso_dwarf->ParseXcodeSDK(comp_unit);
680  return {};
681}
682
683llvm::SmallSet<lldb::LanguageType, 4>
684SymbolFileDWARFDebugMap::ParseAllLanguages(
685    lldb_private::CompileUnit &comp_unit) {
686  llvm::SmallSet<lldb::LanguageType, 4> langs;
687  auto *info = GetCompUnitInfo(comp_unit);
688  for (auto &comp_unit : info->compile_units_sps) {
689    langs.insert(comp_unit->GetLanguage());
690  }
691  return langs;
692}
693
694size_t SymbolFileDWARFDebugMap::ParseFunctions(CompileUnit &comp_unit) {
695  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
696  SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
697  if (oso_dwarf)
698    return oso_dwarf->ParseFunctions(comp_unit);
699  return 0;
700}
701
702bool SymbolFileDWARFDebugMap::ParseLineTable(CompileUnit &comp_unit) {
703  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
704  SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
705  if (oso_dwarf)
706    return oso_dwarf->ParseLineTable(comp_unit);
707  return false;
708}
709
710bool SymbolFileDWARFDebugMap::ParseDebugMacros(CompileUnit &comp_unit) {
711  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
712  SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
713  if (oso_dwarf)
714    return oso_dwarf->ParseDebugMacros(comp_unit);
715  return false;
716}
717
718bool SymbolFileDWARFDebugMap::ForEachExternalModule(
719    CompileUnit &comp_unit,
720    llvm::DenseSet<lldb_private::SymbolFile *> &visited_symbol_files,
721    llvm::function_ref<bool(Module &)> f) {
722  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
723  SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
724  if (oso_dwarf)
725    return oso_dwarf->ForEachExternalModule(comp_unit, visited_symbol_files, f);
726  return false;
727}
728
729bool SymbolFileDWARFDebugMap::ParseSupportFiles(
730    CompileUnit &comp_unit, SupportFileList &support_files) {
731  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
732  SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
733  if (oso_dwarf)
734    return oso_dwarf->ParseSupportFiles(comp_unit, support_files);
735  return false;
736}
737
738bool SymbolFileDWARFDebugMap::ParseIsOptimized(CompileUnit &comp_unit) {
739  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
740  SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
741  if (oso_dwarf)
742    return oso_dwarf->ParseIsOptimized(comp_unit);
743  return false;
744}
745
746bool SymbolFileDWARFDebugMap::ParseImportedModules(
747    const SymbolContext &sc, std::vector<SourceModule> &imported_modules) {
748  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
749  SymbolFileDWARF *oso_dwarf = GetSymbolFile(sc);
750  if (oso_dwarf)
751    return oso_dwarf->ParseImportedModules(sc, imported_modules);
752  return false;
753}
754
755size_t SymbolFileDWARFDebugMap::ParseBlocksRecursive(Function &func) {
756  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
757  CompileUnit *comp_unit = func.GetCompileUnit();
758  if (!comp_unit)
759    return 0;
760
761  SymbolFileDWARF *oso_dwarf = GetSymbolFile(*comp_unit);
762  if (oso_dwarf)
763    return oso_dwarf->ParseBlocksRecursive(func);
764  return 0;
765}
766
767size_t SymbolFileDWARFDebugMap::ParseTypes(CompileUnit &comp_unit) {
768  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
769  SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
770  if (oso_dwarf)
771    return oso_dwarf->ParseTypes(comp_unit);
772  return 0;
773}
774
775size_t
776SymbolFileDWARFDebugMap::ParseVariablesForContext(const SymbolContext &sc) {
777  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
778  SymbolFileDWARF *oso_dwarf = GetSymbolFile(sc);
779  if (oso_dwarf)
780    return oso_dwarf->ParseVariablesForContext(sc);
781  return 0;
782}
783
784Type *SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid) {
785  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
786  const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid);
787  SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
788  if (oso_dwarf)
789    return oso_dwarf->ResolveTypeUID(type_uid);
790  return nullptr;
791}
792
793std::optional<SymbolFile::ArrayInfo>
794SymbolFileDWARFDebugMap::GetDynamicArrayInfoForUID(
795    lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) {
796  const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid);
797  SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
798  if (oso_dwarf)
799    return oso_dwarf->GetDynamicArrayInfoForUID(type_uid, exe_ctx);
800  return std::nullopt;
801}
802
803bool SymbolFileDWARFDebugMap::CompleteType(CompilerType &compiler_type) {
804  bool success = false;
805  if (compiler_type) {
806    ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
807      if (oso_dwarf->HasForwardDeclForCompilerType(compiler_type)) {
808        oso_dwarf->CompleteType(compiler_type);
809        success = true;
810        return true;
811      }
812      return false;
813    });
814  }
815  return success;
816}
817
818uint32_t
819SymbolFileDWARFDebugMap::ResolveSymbolContext(const Address &exe_so_addr,
820                                              SymbolContextItem resolve_scope,
821                                              SymbolContext &sc) {
822  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
823  uint32_t resolved_flags = 0;
824  Symtab *symtab = m_objfile_sp->GetSymtab();
825  if (symtab) {
826    const addr_t exe_file_addr = exe_so_addr.GetFileAddress();
827
828    const DebugMap::Entry *debug_map_entry =
829        m_debug_map.FindEntryThatContains(exe_file_addr);
830    if (debug_map_entry) {
831
832      sc.symbol =
833          symtab->SymbolAtIndex(debug_map_entry->data.GetExeSymbolIndex());
834
835      if (sc.symbol != nullptr) {
836        resolved_flags |= eSymbolContextSymbol;
837
838        uint32_t oso_idx = 0;
839        CompileUnitInfo *comp_unit_info =
840            GetCompileUnitInfoForSymbolWithID(sc.symbol->GetID(), &oso_idx);
841        if (comp_unit_info) {
842          comp_unit_info->GetFileRangeMap(this);
843          Module *oso_module = GetModuleByCompUnitInfo(comp_unit_info);
844          if (oso_module) {
845            lldb::addr_t oso_file_addr =
846                exe_file_addr - debug_map_entry->GetRangeBase() +
847                debug_map_entry->data.GetOSOFileAddress();
848            Address oso_so_addr;
849            if (oso_module->ResolveFileAddress(oso_file_addr, oso_so_addr)) {
850              resolved_flags |=
851                  oso_module->GetSymbolFile()->ResolveSymbolContext(
852                      oso_so_addr, resolve_scope, sc);
853            }
854          }
855        }
856      }
857    }
858  }
859  return resolved_flags;
860}
861
862uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext(
863    const SourceLocationSpec &src_location_spec,
864    SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
865  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
866  const uint32_t initial = sc_list.GetSize();
867  const uint32_t cu_count = GetNumCompileUnits();
868
869  for (uint32_t i = 0; i < cu_count; ++i) {
870    // If we are checking for inlines, then we need to look through all compile
871    // units no matter if "file_spec" matches.
872    bool resolve = src_location_spec.GetCheckInlines();
873
874    if (!resolve) {
875      FileSpec so_file_spec;
876      if (GetFileSpecForSO(i, so_file_spec))
877        resolve =
878            FileSpec::Match(src_location_spec.GetFileSpec(), so_file_spec);
879    }
880    if (resolve) {
881      SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(i);
882      if (oso_dwarf)
883        oso_dwarf->ResolveSymbolContext(src_location_spec, resolve_scope,
884                                        sc_list);
885    }
886  }
887  return sc_list.GetSize() - initial;
888}
889
890void SymbolFileDWARFDebugMap::PrivateFindGlobalVariables(
891    ConstString name, const CompilerDeclContext &parent_decl_ctx,
892    const std::vector<uint32_t>
893        &indexes, // Indexes into the symbol table that match "name"
894    uint32_t max_matches, VariableList &variables) {
895  const size_t match_count = indexes.size();
896  for (size_t i = 0; i < match_count; ++i) {
897    uint32_t oso_idx;
898    CompileUnitInfo *comp_unit_info =
899        GetCompileUnitInfoForSymbolWithIndex(indexes[i], &oso_idx);
900    if (comp_unit_info) {
901      SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
902      if (oso_dwarf) {
903        oso_dwarf->FindGlobalVariables(name, parent_decl_ctx, max_matches,
904                                       variables);
905        if (variables.GetSize() > max_matches)
906          break;
907      }
908    }
909  }
910}
911
912void SymbolFileDWARFDebugMap::FindGlobalVariables(
913    ConstString name, const CompilerDeclContext &parent_decl_ctx,
914    uint32_t max_matches, VariableList &variables) {
915  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
916  uint32_t total_matches = 0;
917
918  ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
919    const uint32_t old_size = variables.GetSize();
920    oso_dwarf->FindGlobalVariables(name, parent_decl_ctx, max_matches,
921                                   variables);
922    const uint32_t oso_matches = variables.GetSize() - old_size;
923    if (oso_matches > 0) {
924      total_matches += oso_matches;
925
926      // Are we getting all matches?
927      if (max_matches == UINT32_MAX)
928        return false; // Yep, continue getting everything
929
930      // If we have found enough matches, lets get out
931      if (max_matches >= total_matches)
932        return true;
933
934      // Update the max matches for any subsequent calls to find globals in any
935      // other object files with DWARF
936      max_matches -= oso_matches;
937    }
938
939    return false;
940  });
941}
942
943void SymbolFileDWARFDebugMap::FindGlobalVariables(
944    const RegularExpression &regex, uint32_t max_matches,
945    VariableList &variables) {
946  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
947  uint32_t total_matches = 0;
948  ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
949    const uint32_t old_size = variables.GetSize();
950    oso_dwarf->FindGlobalVariables(regex, max_matches, variables);
951
952    const uint32_t oso_matches = variables.GetSize() - old_size;
953    if (oso_matches > 0) {
954      total_matches += oso_matches;
955
956      // Are we getting all matches?
957      if (max_matches == UINT32_MAX)
958        return false; // Yep, continue getting everything
959
960      // If we have found enough matches, lets get out
961      if (max_matches >= total_matches)
962        return true;
963
964      // Update the max matches for any subsequent calls to find globals in any
965      // other object files with DWARF
966      max_matches -= oso_matches;
967    }
968
969    return false;
970  });
971}
972
973int SymbolFileDWARFDebugMap::SymbolContainsSymbolWithIndex(
974    uint32_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info) {
975  const uint32_t symbol_idx = *symbol_idx_ptr;
976
977  if (symbol_idx < comp_unit_info->first_symbol_index)
978    return -1;
979
980  if (symbol_idx <= comp_unit_info->last_symbol_index)
981    return 0;
982
983  return 1;
984}
985
986int SymbolFileDWARFDebugMap::SymbolContainsSymbolWithID(
987    user_id_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info) {
988  const user_id_t symbol_id = *symbol_idx_ptr;
989
990  if (symbol_id < comp_unit_info->first_symbol_id)
991    return -1;
992
993  if (symbol_id <= comp_unit_info->last_symbol_id)
994    return 0;
995
996  return 1;
997}
998
999SymbolFileDWARFDebugMap::CompileUnitInfo *
1000SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithIndex(
1001    uint32_t symbol_idx, uint32_t *oso_idx_ptr) {
1002  const uint32_t oso_index_count = m_compile_unit_infos.size();
1003  CompileUnitInfo *comp_unit_info = nullptr;
1004  if (oso_index_count) {
1005    comp_unit_info = (CompileUnitInfo *)bsearch(
1006        &symbol_idx, &m_compile_unit_infos[0], m_compile_unit_infos.size(),
1007        sizeof(CompileUnitInfo),
1008        (ComparisonFunction)SymbolContainsSymbolWithIndex);
1009  }
1010
1011  if (oso_idx_ptr) {
1012    if (comp_unit_info != nullptr)
1013      *oso_idx_ptr = comp_unit_info - &m_compile_unit_infos[0];
1014    else
1015      *oso_idx_ptr = UINT32_MAX;
1016  }
1017  return comp_unit_info;
1018}
1019
1020SymbolFileDWARFDebugMap::CompileUnitInfo *
1021SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithID(
1022    user_id_t symbol_id, uint32_t *oso_idx_ptr) {
1023  const uint32_t oso_index_count = m_compile_unit_infos.size();
1024  CompileUnitInfo *comp_unit_info = nullptr;
1025  if (oso_index_count) {
1026    comp_unit_info = (CompileUnitInfo *)::bsearch(
1027        &symbol_id, &m_compile_unit_infos[0], m_compile_unit_infos.size(),
1028        sizeof(CompileUnitInfo),
1029        (ComparisonFunction)SymbolContainsSymbolWithID);
1030  }
1031
1032  if (oso_idx_ptr) {
1033    if (comp_unit_info != nullptr)
1034      *oso_idx_ptr = comp_unit_info - &m_compile_unit_infos[0];
1035    else
1036      *oso_idx_ptr = UINT32_MAX;
1037  }
1038  return comp_unit_info;
1039}
1040
1041static void RemoveFunctionsWithModuleNotEqualTo(const ModuleSP &module_sp,
1042                                                SymbolContextList &sc_list,
1043                                                uint32_t start_idx) {
1044  // We found functions in .o files. Not all functions in the .o files will
1045  // have made it into the final output file. The ones that did make it into
1046  // the final output file will have a section whose module matches the module
1047  // from the ObjectFile for this SymbolFile. When the modules don't match,
1048  // then we have something that was in a .o file, but doesn't map to anything
1049  // in the final executable.
1050  uint32_t i = start_idx;
1051  while (i < sc_list.GetSize()) {
1052    SymbolContext sc;
1053    sc_list.GetContextAtIndex(i, sc);
1054    if (sc.function) {
1055      const SectionSP section_sp(
1056          sc.function->GetAddressRange().GetBaseAddress().GetSection());
1057      if (section_sp->GetModule() != module_sp) {
1058        sc_list.RemoveContextAtIndex(i);
1059        continue;
1060      }
1061    }
1062    ++i;
1063  }
1064}
1065
1066void SymbolFileDWARFDebugMap::FindFunctions(
1067    const Module::LookupInfo &lookup_info,
1068    const CompilerDeclContext &parent_decl_ctx, bool include_inlines,
1069    SymbolContextList &sc_list) {
1070  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1071  LLDB_SCOPED_TIMERF("SymbolFileDWARFDebugMap::FindFunctions (name = %s)",
1072                     lookup_info.GetLookupName().GetCString());
1073
1074  ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1075    uint32_t sc_idx = sc_list.GetSize();
1076    oso_dwarf->FindFunctions(lookup_info, parent_decl_ctx, include_inlines,
1077                             sc_list);
1078    if (!sc_list.IsEmpty()) {
1079      RemoveFunctionsWithModuleNotEqualTo(m_objfile_sp->GetModule(), sc_list,
1080                                          sc_idx);
1081    }
1082    return false;
1083  });
1084}
1085
1086void SymbolFileDWARFDebugMap::FindFunctions(const RegularExpression &regex,
1087                                            bool include_inlines,
1088                                            SymbolContextList &sc_list) {
1089  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1090  LLDB_SCOPED_TIMERF("SymbolFileDWARFDebugMap::FindFunctions (regex = '%s')",
1091                     regex.GetText().str().c_str());
1092
1093  ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1094    uint32_t sc_idx = sc_list.GetSize();
1095
1096    oso_dwarf->FindFunctions(regex, include_inlines, sc_list);
1097    if (!sc_list.IsEmpty()) {
1098      RemoveFunctionsWithModuleNotEqualTo(m_objfile_sp->GetModule(), sc_list,
1099                                          sc_idx);
1100    }
1101    return false;
1102  });
1103}
1104
1105void SymbolFileDWARFDebugMap::GetTypes(SymbolContextScope *sc_scope,
1106                                       lldb::TypeClass type_mask,
1107                                       TypeList &type_list) {
1108  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1109  LLDB_SCOPED_TIMERF("SymbolFileDWARFDebugMap::GetTypes (type_mask = 0x%8.8x)",
1110                     type_mask);
1111
1112  SymbolFileDWARF *oso_dwarf = nullptr;
1113  if (sc_scope) {
1114    SymbolContext sc;
1115    sc_scope->CalculateSymbolContext(&sc);
1116
1117    CompileUnitInfo *cu_info = GetCompUnitInfo(sc);
1118    if (cu_info) {
1119      oso_dwarf = GetSymbolFileByCompUnitInfo(cu_info);
1120      if (oso_dwarf)
1121        oso_dwarf->GetTypes(sc_scope, type_mask, type_list);
1122    }
1123  } else {
1124    ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1125      oso_dwarf->GetTypes(sc_scope, type_mask, type_list);
1126      return false;
1127    });
1128  }
1129}
1130
1131std::vector<std::unique_ptr<lldb_private::CallEdge>>
1132SymbolFileDWARFDebugMap::ParseCallEdgesInFunction(
1133    lldb_private::UserID func_id) {
1134  uint32_t oso_idx = GetOSOIndexFromUserID(func_id.GetID());
1135  SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
1136  if (oso_dwarf)
1137    return oso_dwarf->ParseCallEdgesInFunction(func_id);
1138  return {};
1139}
1140
1141TypeSP SymbolFileDWARFDebugMap::FindDefinitionTypeForDWARFDeclContext(
1142    const DWARFDIE &die) {
1143  TypeSP type_sp;
1144  ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1145    type_sp = oso_dwarf->FindDefinitionTypeForDWARFDeclContext(die);
1146    return ((bool)type_sp);
1147  });
1148  return type_sp;
1149}
1150
1151bool SymbolFileDWARFDebugMap::Supports_DW_AT_APPLE_objc_complete_type(
1152    SymbolFileDWARF *skip_dwarf_oso) {
1153  if (m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolCalculate) {
1154    m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolNo;
1155    ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1156      if (skip_dwarf_oso != oso_dwarf &&
1157          oso_dwarf->Supports_DW_AT_APPLE_objc_complete_type(nullptr)) {
1158        m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolYes;
1159        return true;
1160      }
1161      return false;
1162    });
1163  }
1164  return m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolYes;
1165}
1166
1167TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE(
1168    const DWARFDIE &die, ConstString type_name,
1169    bool must_be_implementation) {
1170  // If we have a debug map, we will have an Objective-C symbol whose name is
1171  // the type name and whose type is eSymbolTypeObjCClass. If we can find that
1172  // symbol and find its containing parent, we can locate the .o file that will
1173  // contain the implementation definition since it will be scoped inside the
1174  // N_SO and we can then locate the SymbolFileDWARF that corresponds to that
1175  // N_SO.
1176  SymbolFileDWARF *oso_dwarf = nullptr;
1177  TypeSP type_sp;
1178  ObjectFile *module_objfile = m_objfile_sp->GetModule()->GetObjectFile();
1179  if (module_objfile) {
1180    Symtab *symtab = module_objfile->GetSymtab();
1181    if (symtab) {
1182      Symbol *objc_class_symbol = symtab->FindFirstSymbolWithNameAndType(
1183          type_name, eSymbolTypeObjCClass, Symtab::eDebugAny,
1184          Symtab::eVisibilityAny);
1185      if (objc_class_symbol) {
1186        // Get the N_SO symbol that contains the objective C class symbol as
1187        // this should be the .o file that contains the real definition...
1188        const Symbol *source_file_symbol = symtab->GetParent(objc_class_symbol);
1189
1190        if (source_file_symbol &&
1191            source_file_symbol->GetType() == eSymbolTypeSourceFile) {
1192          const uint32_t source_file_symbol_idx =
1193              symtab->GetIndexForSymbol(source_file_symbol);
1194          if (source_file_symbol_idx != UINT32_MAX) {
1195            CompileUnitInfo *compile_unit_info =
1196                GetCompileUnitInfoForSymbolWithIndex(source_file_symbol_idx,
1197                                                     nullptr);
1198            if (compile_unit_info) {
1199              oso_dwarf = GetSymbolFileByCompUnitInfo(compile_unit_info);
1200              if (oso_dwarf) {
1201                TypeSP type_sp(oso_dwarf->FindCompleteObjCDefinitionTypeForDIE(
1202                    die, type_name, must_be_implementation));
1203                if (type_sp) {
1204                  return type_sp;
1205                }
1206              }
1207            }
1208          }
1209        }
1210      }
1211    }
1212  }
1213
1214  // Only search all .o files for the definition if we don't need the
1215  // implementation because otherwise, with a valid debug map we should have
1216  // the ObjC class symbol and the code above should have found it.
1217  if (!must_be_implementation) {
1218    TypeSP type_sp;
1219
1220    ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1221      type_sp = oso_dwarf->FindCompleteObjCDefinitionTypeForDIE(
1222          die, type_name, must_be_implementation);
1223      return (bool)type_sp;
1224    });
1225
1226    return type_sp;
1227  }
1228  return TypeSP();
1229}
1230
1231void SymbolFileDWARFDebugMap::FindTypes(const TypeQuery &query,
1232                                        TypeResults &results) {
1233  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1234  ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1235    oso_dwarf->FindTypes(query, results);
1236    return !results.Done(query); // Keep iterating if we aren't done.
1237  });
1238}
1239
1240CompilerDeclContext SymbolFileDWARFDebugMap::FindNamespace(
1241    lldb_private::ConstString name, const CompilerDeclContext &parent_decl_ctx,
1242    bool only_root_namespaces) {
1243  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1244  CompilerDeclContext matching_namespace;
1245
1246  ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1247    matching_namespace =
1248        oso_dwarf->FindNamespace(name, parent_decl_ctx, only_root_namespaces);
1249
1250    return (bool)matching_namespace;
1251  });
1252
1253  return matching_namespace;
1254}
1255
1256void SymbolFileDWARFDebugMap::DumpClangAST(Stream &s) {
1257  ForEachSymbolFile([&s](SymbolFileDWARF *oso_dwarf) -> bool {
1258    oso_dwarf->DumpClangAST(s);
1259    // The underlying assumption is that DumpClangAST(...) will obtain the
1260    // AST from the underlying TypeSystem and therefore we only need to do
1261    // this once and can stop after the first iteration hence we return true.
1262    return true;
1263  });
1264}
1265
1266bool SymbolFileDWARFDebugMap::GetSeparateDebugInfo(
1267    lldb_private::StructuredData::Dictionary &d, bool errors_only) {
1268  StructuredData::Array separate_debug_info_files;
1269  const uint32_t cu_count = GetNumCompileUnits();
1270  for (uint32_t cu_idx = 0; cu_idx < cu_count; ++cu_idx) {
1271    const auto &info = m_compile_unit_infos[cu_idx];
1272    StructuredData::DictionarySP oso_data =
1273        std::make_shared<StructuredData::Dictionary>();
1274    oso_data->AddStringItem("so_file", info.so_file.GetPath());
1275    oso_data->AddStringItem("oso_path", info.oso_path);
1276    oso_data->AddIntegerItem("oso_mod_time",
1277                             (uint32_t)llvm::sys::toTimeT(info.oso_mod_time));
1278
1279    bool loaded_successfully = false;
1280    if (GetModuleByOSOIndex(cu_idx)) {
1281      // If we have a valid pointer to the module, we successfully
1282      // loaded the oso if there are no load errors.
1283      if (!info.oso_load_error.Fail()) {
1284        loaded_successfully = true;
1285      }
1286    }
1287    if (!loaded_successfully) {
1288      oso_data->AddStringItem("error", info.oso_load_error.AsCString());
1289    }
1290    oso_data->AddBooleanItem("loaded", loaded_successfully);
1291    if (!errors_only || oso_data->HasKey("error"))
1292      separate_debug_info_files.AddItem(oso_data);
1293  }
1294
1295  d.AddStringItem("type", "oso");
1296  d.AddStringItem("symfile", GetMainObjectFile()->GetFileSpec().GetPath());
1297  d.AddItem("separate-debug-info-files",
1298            std::make_shared<StructuredData::Array>(
1299                std::move(separate_debug_info_files)));
1300  return true;
1301}
1302
1303lldb::CompUnitSP
1304SymbolFileDWARFDebugMap::GetCompileUnit(SymbolFileDWARF *oso_dwarf, DWARFCompileUnit &dwarf_cu) {
1305  if (oso_dwarf) {
1306    const uint32_t cu_count = GetNumCompileUnits();
1307    for (uint32_t cu_idx = 0; cu_idx < cu_count; ++cu_idx) {
1308      SymbolFileDWARF *oso_symfile =
1309          GetSymbolFileByCompUnitInfo(&m_compile_unit_infos[cu_idx]);
1310      if (oso_symfile == oso_dwarf) {
1311        if (m_compile_unit_infos[cu_idx].compile_units_sps.empty())
1312          ParseCompileUnitAtIndex(cu_idx);
1313
1314        auto &id_to_index_map = m_compile_unit_infos[cu_idx].id_to_index_map;
1315        auto it = id_to_index_map.find(dwarf_cu.GetID());
1316        if (it != id_to_index_map.end())
1317          return m_compile_unit_infos[cu_idx]
1318              .compile_units_sps[it->getSecond()];
1319      }
1320    }
1321  }
1322  llvm_unreachable("this shouldn't happen");
1323}
1324
1325SymbolFileDWARFDebugMap::CompileUnitInfo *
1326SymbolFileDWARFDebugMap::GetCompileUnitInfo(SymbolFileDWARF *oso_dwarf) {
1327  if (oso_dwarf) {
1328    const uint32_t cu_count = GetNumCompileUnits();
1329    for (uint32_t cu_idx = 0; cu_idx < cu_count; ++cu_idx) {
1330      SymbolFileDWARF *oso_symfile =
1331          GetSymbolFileByCompUnitInfo(&m_compile_unit_infos[cu_idx]);
1332      if (oso_symfile == oso_dwarf) {
1333        return &m_compile_unit_infos[cu_idx];
1334      }
1335    }
1336  }
1337  return nullptr;
1338}
1339
1340void SymbolFileDWARFDebugMap::SetCompileUnit(SymbolFileDWARF *oso_dwarf,
1341                                             const CompUnitSP &cu_sp) {
1342  if (oso_dwarf) {
1343    const uint32_t cu_count = GetNumCompileUnits();
1344    for (uint32_t cu_idx = 0; cu_idx < cu_count; ++cu_idx) {
1345      SymbolFileDWARF *oso_symfile =
1346          GetSymbolFileByCompUnitInfo(&m_compile_unit_infos[cu_idx]);
1347      if (oso_symfile == oso_dwarf) {
1348        if (!m_compile_unit_infos[cu_idx].compile_units_sps.empty()) {
1349          assert(m_compile_unit_infos[cu_idx].compile_units_sps[0].get() ==
1350                 cu_sp.get());
1351        } else {
1352          assert(cu_sp->GetID() == 0 &&
1353                 "Setting first compile unit but with id different than 0!");
1354          auto &compile_units_sps = m_compile_unit_infos[cu_idx].compile_units_sps;
1355          compile_units_sps.push_back(cu_sp);
1356          m_compile_unit_infos[cu_idx].id_to_index_map.insert(
1357              {cu_sp->GetID(), compile_units_sps.size() - 1});
1358
1359          SetCompileUnitAtIndex(cu_idx, cu_sp);
1360        }
1361      }
1362    }
1363  }
1364}
1365
1366CompilerDeclContext
1367SymbolFileDWARFDebugMap::GetDeclContextForUID(lldb::user_id_t type_uid) {
1368  const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid);
1369  if (SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx))
1370    return oso_dwarf->GetDeclContextForUID(type_uid);
1371  return {};
1372}
1373
1374CompilerDeclContext
1375SymbolFileDWARFDebugMap::GetDeclContextContainingUID(lldb::user_id_t type_uid) {
1376  const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid);
1377  if (SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx))
1378    return oso_dwarf->GetDeclContextContainingUID(type_uid);
1379  return {};
1380}
1381
1382std::vector<CompilerContext>
1383SymbolFileDWARFDebugMap::GetCompilerContextForUID(lldb::user_id_t type_uid) {
1384  const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid);
1385  if (SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx))
1386    return oso_dwarf->GetCompilerContextForUID(type_uid);
1387  return {};
1388}
1389
1390void SymbolFileDWARFDebugMap::ParseDeclsForContext(
1391    lldb_private::CompilerDeclContext decl_ctx) {
1392  ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1393    oso_dwarf->ParseDeclsForContext(decl_ctx);
1394    return true; // Keep iterating
1395  });
1396}
1397
1398bool SymbolFileDWARFDebugMap::AddOSOFileRange(CompileUnitInfo *cu_info,
1399                                              lldb::addr_t exe_file_addr,
1400                                              lldb::addr_t exe_byte_size,
1401                                              lldb::addr_t oso_file_addr,
1402                                              lldb::addr_t oso_byte_size) {
1403  const uint32_t debug_map_idx =
1404      m_debug_map.FindEntryIndexThatContains(exe_file_addr);
1405  if (debug_map_idx != UINT32_MAX) {
1406    DebugMap::Entry *debug_map_entry =
1407        m_debug_map.FindEntryThatContains(exe_file_addr);
1408    debug_map_entry->data.SetOSOFileAddress(oso_file_addr);
1409    addr_t range_size = std::min<addr_t>(exe_byte_size, oso_byte_size);
1410    if (range_size == 0) {
1411      range_size = std::max<addr_t>(exe_byte_size, oso_byte_size);
1412      if (range_size == 0)
1413        range_size = 1;
1414    }
1415    cu_info->file_range_map.Append(
1416        FileRangeMap::Entry(oso_file_addr, range_size, exe_file_addr));
1417    return true;
1418  }
1419  return false;
1420}
1421
1422void SymbolFileDWARFDebugMap::FinalizeOSOFileRanges(CompileUnitInfo *cu_info) {
1423  cu_info->file_range_map.Sort();
1424#if defined(DEBUG_OSO_DMAP)
1425  const FileRangeMap &oso_file_range_map = cu_info->GetFileRangeMap(this);
1426  const size_t n = oso_file_range_map.GetSize();
1427  printf("SymbolFileDWARFDebugMap::FinalizeOSOFileRanges (cu_info = %p) %s\n",
1428         cu_info, cu_info->oso_sp->module_sp->GetFileSpec().GetPath().c_str());
1429  for (size_t i = 0; i < n; ++i) {
1430    const FileRangeMap::Entry &entry = oso_file_range_map.GetEntryRef(i);
1431    printf("oso [0x%16.16" PRIx64 " - 0x%16.16" PRIx64
1432           ") ==> exe [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n",
1433           entry.GetRangeBase(), entry.GetRangeEnd(), entry.data,
1434           entry.data + entry.GetByteSize());
1435  }
1436#endif
1437}
1438
1439lldb::addr_t
1440SymbolFileDWARFDebugMap::LinkOSOFileAddress(SymbolFileDWARF *oso_symfile,
1441                                            lldb::addr_t oso_file_addr) {
1442  CompileUnitInfo *cu_info = GetCompileUnitInfo(oso_symfile);
1443  if (cu_info) {
1444    const FileRangeMap::Entry *oso_range_entry =
1445        cu_info->GetFileRangeMap(this).FindEntryThatContains(oso_file_addr);
1446    if (oso_range_entry) {
1447      const DebugMap::Entry *debug_map_entry =
1448          m_debug_map.FindEntryThatContains(oso_range_entry->data);
1449      if (debug_map_entry) {
1450        const lldb::addr_t offset =
1451            oso_file_addr - oso_range_entry->GetRangeBase();
1452        const lldb::addr_t exe_file_addr =
1453            debug_map_entry->GetRangeBase() + offset;
1454        return exe_file_addr;
1455      }
1456    }
1457  }
1458  return LLDB_INVALID_ADDRESS;
1459}
1460
1461bool SymbolFileDWARFDebugMap::LinkOSOAddress(Address &addr) {
1462  // Make sure this address hasn't been fixed already
1463  Module *exe_module = GetObjectFile()->GetModule().get();
1464  Module *addr_module = addr.GetModule().get();
1465  if (addr_module == exe_module)
1466    return true; // Address is already in terms of the main executable module
1467
1468  CompileUnitInfo *cu_info = GetCompileUnitInfo(
1469      GetSymbolFileAsSymbolFileDWARF(addr_module->GetSymbolFile()));
1470  if (cu_info) {
1471    const lldb::addr_t oso_file_addr = addr.GetFileAddress();
1472    const FileRangeMap::Entry *oso_range_entry =
1473        cu_info->GetFileRangeMap(this).FindEntryThatContains(oso_file_addr);
1474    if (oso_range_entry) {
1475      const DebugMap::Entry *debug_map_entry =
1476          m_debug_map.FindEntryThatContains(oso_range_entry->data);
1477      if (debug_map_entry) {
1478        const lldb::addr_t offset =
1479            oso_file_addr - oso_range_entry->GetRangeBase();
1480        const lldb::addr_t exe_file_addr =
1481            debug_map_entry->GetRangeBase() + offset;
1482        return exe_module->ResolveFileAddress(exe_file_addr, addr);
1483      }
1484    }
1485  }
1486  return true;
1487}
1488
1489LineTable *SymbolFileDWARFDebugMap::LinkOSOLineTable(SymbolFileDWARF *oso_dwarf,
1490                                                     LineTable *line_table) {
1491  CompileUnitInfo *cu_info = GetCompileUnitInfo(oso_dwarf);
1492  if (cu_info)
1493    return line_table->LinkLineTable(cu_info->GetFileRangeMap(this));
1494  return nullptr;
1495}
1496
1497size_t
1498SymbolFileDWARFDebugMap::AddOSOARanges(SymbolFileDWARF *dwarf2Data,
1499                                       DWARFDebugAranges *debug_aranges) {
1500  size_t num_line_entries_added = 0;
1501  if (debug_aranges && dwarf2Data) {
1502    CompileUnitInfo *compile_unit_info = GetCompileUnitInfo(dwarf2Data);
1503    if (compile_unit_info) {
1504      const FileRangeMap &file_range_map =
1505          compile_unit_info->GetFileRangeMap(this);
1506      for (size_t idx = 0; idx < file_range_map.GetSize(); idx++) {
1507        const FileRangeMap::Entry *entry = file_range_map.GetEntryAtIndex(idx);
1508        if (entry) {
1509          debug_aranges->AppendRange(*dwarf2Data->GetFileIndex(),
1510                                     entry->GetRangeBase(),
1511                                     entry->GetRangeEnd());
1512          num_line_entries_added++;
1513        }
1514      }
1515    }
1516  }
1517  return num_line_entries_added;
1518}
1519
1520ModuleList SymbolFileDWARFDebugMap::GetDebugInfoModules() {
1521  ModuleList oso_modules;
1522  ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1523    ObjectFile *oso_objfile = oso_dwarf->GetObjectFile();
1524    if (oso_objfile) {
1525      ModuleSP module_sp = oso_objfile->GetModule();
1526      if (module_sp)
1527        oso_modules.Append(module_sp);
1528    }
1529    return false; // Keep iterating
1530  });
1531  return oso_modules;
1532}
1533
1534Status SymbolFileDWARFDebugMap::CalculateFrameVariableError(StackFrame &frame) {
1535  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1536
1537  // We need to make sure that our PC value from the frame matches the module
1538  // for this object file since we will lookup the PC file address in the debug
1539  // map below.
1540  Address pc_addr = frame.GetFrameCodeAddress();
1541  if (pc_addr.GetModule() == m_objfile_sp->GetModule()) {
1542    Symtab *symtab = m_objfile_sp->GetSymtab();
1543    if (symtab) {
1544      const DebugMap::Entry *debug_map_entry =
1545          m_debug_map.FindEntryThatContains(pc_addr.GetFileAddress());
1546      if (debug_map_entry) {
1547        Symbol *symbol =
1548            symtab->SymbolAtIndex(debug_map_entry->data.GetExeSymbolIndex());
1549        if (symbol) {
1550          uint32_t oso_idx = 0;
1551          CompileUnitInfo *comp_unit_info =
1552              GetCompileUnitInfoForSymbolWithID(symbol->GetID(), &oso_idx);
1553          if (comp_unit_info) {
1554            Module *oso_module = GetModuleByCompUnitInfo(comp_unit_info);
1555            if (oso_module) {
1556              // Check the .o file's DWARF in case it has an error to display.
1557              SymbolFile *oso_sym_file = oso_module->GetSymbolFile();
1558              if (oso_sym_file)
1559                return oso_sym_file->GetFrameVariableError(frame);
1560            }
1561            // If we don't have a valid OSO module here, then something went
1562            // wrong as we have a symbol for the address in the debug map, but
1563            // we weren't able to open the .o file. Display an appropriate
1564            // error
1565            if (comp_unit_info->oso_load_error.Fail())
1566              return comp_unit_info->oso_load_error;
1567            else
1568              return Status("unable to load debug map object file \"%s\" "
1569                            "exist, debug info will not be loaded",
1570                            comp_unit_info->oso_path.GetCString());
1571          }
1572        }
1573      }
1574    }
1575  }
1576  return Status();
1577}
1578
1579void SymbolFileDWARFDebugMap::GetCompileOptions(
1580    std::unordered_map<lldb::CompUnitSP, lldb_private::Args> &args) {
1581
1582  ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1583    oso_dwarf->GetCompileOptions(args);
1584    return false;
1585  });
1586}
1587