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