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