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