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