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