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
37using namespace lldb;
38using 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
47const SymbolFileDWARFDebugMap::FileRangeMap &
48SymbolFileDWARFDebugMap::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
179class DebugMapModule : public Module
180{
181public:
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
196    ~DebugMapModule ()
197    {
198    }
199
200
201    virtual SymbolVendor*
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
252protected:
253    ModuleWP m_exe_module_wp;
254    const uint32_t m_cu_idx;
255};
256
257void
258SymbolFileDWARFDebugMap::Initialize()
259{
260    PluginManager::RegisterPlugin (GetPluginNameStatic(),
261                                   GetPluginDescriptionStatic(),
262                                   CreateInstance);
263}
264
265void
266SymbolFileDWARFDebugMap::Terminate()
267{
268    PluginManager::UnregisterPlugin (CreateInstance);
269}
270
271
272lldb_private::ConstString
273SymbolFileDWARFDebugMap::GetPluginNameStatic()
274{
275    static ConstString g_name("dwarf-debugmap");
276    return g_name;
277}
278
279const char *
280SymbolFileDWARFDebugMap::GetPluginDescriptionStatic()
281{
282    return "DWARF and DWARF3 debug symbol file reader (debug map).";
283}
284
285SymbolFile*
286SymbolFileDWARFDebugMap::CreateInstance (ObjectFile* obj_file)
287{
288    return new SymbolFileDWARFDebugMap (obj_file);
289}
290
291
292SymbolFileDWARFDebugMap::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
303SymbolFileDWARFDebugMap::~SymbolFileDWARFDebugMap()
304{
305}
306
307void
308SymbolFileDWARFDebugMap::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
321void
322SymbolFileDWARFDebugMap::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
452Module *
453SymbolFileDWARFDebugMap::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
461Module *
462SymbolFileDWARFDebugMap::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
523bool
524SymbolFileDWARFDebugMap::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
539ObjectFile *
540SymbolFileDWARFDebugMap::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
548SymbolFileDWARF *
549SymbolFileDWARFDebugMap::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
557ObjectFile *
558SymbolFileDWARFDebugMap::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
567uint32_t
568SymbolFileDWARFDebugMap::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
580SymbolFileDWARF *
581SymbolFileDWARFDebugMap::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
588SymbolFileDWARF *
589SymbolFileDWARFDebugMap::GetSymbolFileAsSymbolFileDWARF (SymbolFile *sym_file)
590{
591    if (sym_file && sym_file->GetPluginName() == SymbolFileDWARF::GetPluginNameStatic())
592        return (SymbolFileDWARF *)sym_file;
593    return NULL;
594}
595
596SymbolFileDWARF *
597SymbolFileDWARFDebugMap::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
609uint32_t
610SymbolFileDWARFDebugMap::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
635uint32_t
636SymbolFileDWARFDebugMap::GetNumCompileUnits()
637{
638    InitOSO ();
639    return m_compile_unit_infos.size();
640}
641
642
643CompUnitSP
644SymbolFileDWARFDebugMap::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
680SymbolFileDWARFDebugMap::CompileUnitInfo *
681SymbolFileDWARFDebugMap::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
693size_t
694SymbolFileDWARFDebugMap::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
705lldb::LanguageType
706SymbolFileDWARFDebugMap::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
714size_t
715SymbolFileDWARFDebugMap::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
723bool
724SymbolFileDWARFDebugMap::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
732bool
733SymbolFileDWARFDebugMap::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
742size_t
743SymbolFileDWARFDebugMap::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
752size_t
753SymbolFileDWARFDebugMap::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
762size_t
763SymbolFileDWARFDebugMap::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
773Type*
774SymbolFileDWARFDebugMap::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
783bool
784SymbolFileDWARFDebugMap::ResolveClangOpaqueTypeDefinition (ClangASTType& clang_type)
785{
786    // We have a struct/union/class/enum that needs to be fully resolved.
787    return false;
788}
789
790uint32_t
791SymbolFileDWARFDebugMap::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
832uint32_t
833SymbolFileDWARFDebugMap::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
864uint32_t
865SymbolFileDWARFDebugMap::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
894uint32_t
895SymbolFileDWARFDebugMap::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
937uint32_t
938SymbolFileDWARFDebugMap::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
978int
979SymbolFileDWARFDebugMap::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
993int
994SymbolFileDWARFDebugMap::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
1008SymbolFileDWARFDebugMap::CompileUnitInfo*
1009SymbolFileDWARFDebugMap::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
1032SymbolFileDWARFDebugMap::CompileUnitInfo*
1033SymbolFileDWARFDebugMap::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
1057static void
1058RemoveFunctionsWithModuleNotEqualTo (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
1084uint32_t
1085SymbolFileDWARFDebugMap::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
1112uint32_t
1113SymbolFileDWARFDebugMap::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
1140size_t
1141SymbolFileDWARFDebugMap::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
1177TypeSP
1178SymbolFileDWARFDebugMap::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
1193bool
1194SymbolFileDWARFDebugMap::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
1212TypeSP
1213SymbolFileDWARFDebugMap::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
1228uint32_t
1229SymbolFileDWARFDebugMap::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
1272ClangNamespaceDecl
1273SymbolFileDWARFDebugMap::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//------------------------------------------------------------------
1305lldb_private::ConstString
1306SymbolFileDWARFDebugMap::GetPluginName()
1307{
1308    return GetPluginNameStatic();
1309}
1310
1311uint32_t
1312SymbolFileDWARFDebugMap::GetPluginVersion()
1313{
1314    return 1;
1315}
1316
1317lldb::CompUnitSP
1318SymbolFileDWARFDebugMap::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
1339SymbolFileDWARFDebugMap::CompileUnitInfo *
1340SymbolFileDWARFDebugMap::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
1358void
1359SymbolFileDWARFDebugMap::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
1384void
1385SymbolFileDWARFDebugMap::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
1404void
1405SymbolFileDWARFDebugMap::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
1424bool
1425SymbolFileDWARFDebugMap::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
1445clang::DeclContext*
1446SymbolFileDWARFDebugMap::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
1455clang::DeclContext*
1456SymbolFileDWARFDebugMap::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
1465bool
1466SymbolFileDWARFDebugMap::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
1482void
1483SymbolFileDWARFDebugMap::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
1502lldb::addr_t
1503SymbolFileDWARFDebugMap::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
1523bool
1524SymbolFileDWARFDebugMap::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
1551LineTable *
1552SymbolFileDWARFDebugMap::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
1560size_t
1561SymbolFileDWARFDebugMap::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