1 //===-- SymbolVendorMacOSX.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 "SymbolVendorMacOSX.h"
11 
12 #include <AvailabilityMacros.h>
13 
14 #include "lldb/Core/Module.h"
15 #include "lldb/Core/PluginManager.h"
16 #include "lldb/Core/Section.h"
17 #include "lldb/Core/Timer.h"
18 #include "lldb/Host/Symbols.h"
19 #include "lldb/Symbol/ObjectFile.h"
20 
21 using namespace lldb;
22 using namespace lldb_private;
23 
24 //----------------------------------------------------------------------
25 // SymbolVendorMacOSX constructor
26 //----------------------------------------------------------------------
27 SymbolVendorMacOSX::SymbolVendorMacOSX(Module *module) :
28     SymbolVendor(module)
29 {
30 }
31 
32 //----------------------------------------------------------------------
33 // Destructor
34 //----------------------------------------------------------------------
35 SymbolVendorMacOSX::~SymbolVendorMacOSX()
36 {
37 }
38 
39 
40 static bool
41 UUIDsMatch(Module *module, ObjectFile *ofile)
42 {
43     if (module && ofile)
44     {
45         // Make sure the UUIDs match
46         lldb_private::UUID dsym_uuid;
47         if (ofile->GetUUID(&dsym_uuid))
48             return dsym_uuid == module->GetUUID();
49     }
50     return false;
51 }
52 
53 static void
54 ReplaceDSYMSectionsWithExecutableSections (ObjectFile *exec_objfile, ObjectFile *dsym_objfile)
55 {
56     // We need both the executable and the dSYM to live off of the
57     // same section lists. So we take all of the sections from the
58     // executable, and replace them in the dSYM. This allows section
59     // offset addresses that come from the dSYM to automatically
60     // get updated as images (shared libraries) get loaded and
61     // unloaded.
62     SectionList *exec_section_list = exec_objfile->GetSectionList();
63     SectionList *dsym_section_list = dsym_objfile->GetSectionList();
64     if (exec_section_list && dsym_section_list)
65     {
66         const uint32_t num_exec_sections = dsym_section_list->GetSize();
67         uint32_t exec_sect_idx;
68         for (exec_sect_idx = 0; exec_sect_idx < num_exec_sections; ++exec_sect_idx)
69         {
70             SectionSP exec_sect_sp(exec_section_list->GetSectionAtIndex(exec_sect_idx));
71             if (exec_sect_sp.get())
72             {
73                 // Try and replace any sections that exist in both the executable
74                 // and in the dSYM with those from the executable. If we fail to
75                 // replace the one in the dSYM, then add the executable section to
76                 // the dSYM.
77                 if (dsym_section_list->ReplaceSection(exec_sect_sp->GetID(), exec_sect_sp, 0) == false)
78                     dsym_section_list->AddSection(exec_sect_sp);
79             }
80         }
81     }
82 }
83 
84 void
85 SymbolVendorMacOSX::Initialize()
86 {
87     PluginManager::RegisterPlugin (GetPluginNameStatic(),
88                                    GetPluginDescriptionStatic(),
89                                    CreateInstance);
90 }
91 
92 void
93 SymbolVendorMacOSX::Terminate()
94 {
95     PluginManager::UnregisterPlugin (CreateInstance);
96 }
97 
98 
99 const char *
100 SymbolVendorMacOSX::GetPluginNameStatic()
101 {
102     return "symbol-vendor.macosx";
103 }
104 
105 const char *
106 SymbolVendorMacOSX::GetPluginDescriptionStatic()
107 {
108     return "Symbol vendor for MacOSX that looks for dSYM files that match executables.";
109 }
110 
111 
112 
113 //----------------------------------------------------------------------
114 // CreateInstance
115 //
116 // Platforms can register a callback to use when creating symbol
117 // vendors to allow for complex debug information file setups, and to
118 // also allow for finding separate debug information files.
119 //----------------------------------------------------------------------
120 SymbolVendor*
121 SymbolVendorMacOSX::CreateInstance(Module* module)
122 {
123     Timer scoped_timer (__PRETTY_FUNCTION__,
124                         "SymbolVendorMacOSX::CreateInstance (module = %s/%s)",
125                         module->GetFileSpec().GetDirectory().AsCString(),
126                         module->GetFileSpec().GetFilename().AsCString());
127     SymbolVendorMacOSX* symbol_vendor = new SymbolVendorMacOSX(module);
128     if (symbol_vendor)
129     {
130         char path[PATH_MAX];
131         path[0] = '\0';
132 
133         // Try and locate the dSYM file on Mac OS X
134         ObjectFile * obj_file = module->GetObjectFile();
135         if (obj_file)
136         {
137             Timer scoped_timer2 ("SymbolVendorMacOSX::CreateInstance () locate dSYM",
138                                  "SymbolVendorMacOSX::CreateInstance (module = %s/%s) locate dSYM",
139                                  module->GetFileSpec().GetDirectory().AsCString(),
140                                  module->GetFileSpec().GetFilename().AsCString());
141 
142             FileSpec dsym_fspec;
143             ObjectFileSP dsym_objfile_sp;
144             const FileSpec &file_spec = obj_file->GetFileSpec();
145             if (file_spec)
146             {
147                 dsym_fspec = Symbols::LocateExecutableSymbolFile (&file_spec, &module->GetArchitecture(), &module->GetUUID());
148 
149                 if (dsym_fspec)
150                 {
151                     dsym_objfile_sp = ObjectFile::FindPlugin(module, &dsym_fspec, 0, dsym_fspec.GetByteSize());
152                     if (UUIDsMatch(module, dsym_objfile_sp.get()))
153                     {
154                         ReplaceDSYMSectionsWithExecutableSections (obj_file, dsym_objfile_sp.get());
155                         symbol_vendor->AddSymbolFileRepresendation(dsym_objfile_sp);
156                         return symbol_vendor;
157                     }
158                 }
159             }
160 
161             // Just create our symbol vendor using the current objfile as this is either
162             // an executable with no dSYM (that we could locate), an executable with
163             // a dSYM that has a UUID that doesn't match.
164             symbol_vendor->AddSymbolFileRepresendation(obj_file->GetSP());
165         }
166     }
167     return symbol_vendor;
168 }
169 
170 
171 
172 //------------------------------------------------------------------
173 // PluginInterface protocol
174 //------------------------------------------------------------------
175 const char *
176 SymbolVendorMacOSX::GetPluginName()
177 {
178     return "SymbolVendorMacOSX";
179 }
180 
181 const char *
182 SymbolVendorMacOSX::GetShortPluginName()
183 {
184     return GetPluginNameStatic();
185 }
186 
187 uint32_t
188 SymbolVendorMacOSX::GetPluginVersion()
189 {
190     return 1;
191 }
192 
193