Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 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 <mach/machine.h> // DebugSymbols needs this on Leopard... |
| 13 | |
| 14 | #include <AvailabilityMacros.h> |
| 15 | |
| 16 | #include "lldb/Core/Module.h" |
| 17 | #include "lldb/Core/PluginManager.h" |
| 18 | #include "lldb/Core/Section.h" |
| 19 | #include "lldb/Core/Timer.h" |
| 20 | #include "lldb/Host/Symbols.h" |
| 21 | #include "lldb/Symbol/ObjectFile.h" |
| 22 | |
| 23 | using namespace lldb; |
| 24 | using namespace lldb_private; |
| 25 | |
| 26 | //---------------------------------------------------------------------- |
| 27 | // SymbolVendorMacOSX constructor |
| 28 | //---------------------------------------------------------------------- |
| 29 | SymbolVendorMacOSX::SymbolVendorMacOSX(Module *module) : |
| 30 | SymbolVendor(module) |
| 31 | { |
| 32 | } |
| 33 | |
| 34 | //---------------------------------------------------------------------- |
| 35 | // Destructor |
| 36 | //---------------------------------------------------------------------- |
| 37 | SymbolVendorMacOSX::~SymbolVendorMacOSX() |
| 38 | { |
| 39 | } |
| 40 | |
| 41 | |
| 42 | static bool |
| 43 | UUIDsMatch(Module *module, ObjectFile *ofile) |
| 44 | { |
| 45 | if (module && ofile) |
| 46 | { |
| 47 | // Make sure the UUIDs match |
| 48 | UUID dsym_uuid; |
| 49 | if (ofile->GetUUID(&dsym_uuid)) |
| 50 | return dsym_uuid == module->GetUUID(); |
| 51 | } |
| 52 | return false; |
| 53 | } |
| 54 | |
| 55 | |
| 56 | //ObjectFile * |
| 57 | //LocateDSYMMachFileInDSYMBundle (Module* module, FileSpec& dsym_fspec) |
| 58 | //{ |
| 59 | // ObjectFile *dsym_objfile = NULL; |
| 60 | // |
| 61 | // char path[PATH_MAX]; |
| 62 | // |
| 63 | // if (dsym_fspec.GetPath(path, sizeof(path))) |
| 64 | // { |
| 65 | // size_t path_len = strlen(path); |
| 66 | // const char *bundle_subpath = "/Contents/Resources/DWARF/"; |
| 67 | // if (path_len > 0) |
| 68 | // { |
| 69 | // if (path[path_len-1] == '/') |
| 70 | // ::strncat (path, bundle_subpath + 1, sizeof(path)); |
| 71 | // else |
| 72 | // ::strncat (path, bundle_subpath, sizeof(path)); |
| 73 | // ::strncat (path, dsym_fspec.GetFilename().AsCString(), sizeof(path)); |
| 74 | // |
| 75 | // path_len = strlen(path); |
| 76 | // |
| 77 | // if (::strcasecmp (&path[path_len - strlen(".dSYM")], ".dSYM") == 0) |
| 78 | // { |
| 79 | // path[path_len - ::strlen(".dSYM")] = '\0'; |
| 80 | // dsym_fspec.SetFile(path); |
| 81 | // dsym_objfile = ObjectFile::FindPlugin(module, &dsym_fspec, 0); |
| 82 | // } |
| 83 | // } |
| 84 | // } |
| 85 | // return dsym_objfile; |
| 86 | //} |
| 87 | // |
| 88 | //CFURLRef DBGCopyFullDSYMURLForUUID (CFUUIDRef uuid, CFURLRef exec_url) __attribute__((weak_import)); |
| 89 | |
| 90 | |
| 91 | //ObjectFile * |
| 92 | //FindDSYMUsingDebugSymbols (Module* module, FileSpec& dsym_fspec) |
| 93 | //{ |
| 94 | // Timer scoped_locate("FindDSYMUsingDebugSymbols"); |
| 95 | // dsym_fspec.Clear(); |
| 96 | // ObjectFile *dsym_objfile = NULL; |
| 97 | // if (module->GetUUID().IsValid()) |
| 98 | // { |
| 99 | // // Try and locate the dSYM file using DebugSymbols first |
| 100 | // const UInt8 *module_uuid = (const UInt8 *)module->GetUUID().GetBytes(); |
| 101 | // if (module_uuid != NULL) |
| 102 | // { |
| 103 | // CFUUIDRef module_uuid_ref; |
| 104 | // module_uuid_ref = ::CFUUIDCreateWithBytes ( NULL, |
| 105 | // module_uuid[0], |
| 106 | // module_uuid[1], |
| 107 | // module_uuid[2], |
| 108 | // module_uuid[3], |
| 109 | // module_uuid[4], |
| 110 | // module_uuid[5], |
| 111 | // module_uuid[6], |
| 112 | // module_uuid[7], |
| 113 | // module_uuid[8], |
| 114 | // module_uuid[9], |
| 115 | // module_uuid[10], |
| 116 | // module_uuid[11], |
| 117 | // module_uuid[12], |
| 118 | // module_uuid[13], |
| 119 | // module_uuid[14], |
| 120 | // module_uuid[15]); |
| 121 | // |
| 122 | // if (module_uuid_ref) |
| 123 | // { |
| 124 | // CFURLRef dsym_url = NULL; |
| 125 | // CFURLRef exec_url = NULL; |
| 126 | // |
| 127 | // // if (DBGCopyFullDSYMURLForUUID) |
| 128 | // { |
| 129 | // char exec_path[PATH_MAX]; |
| 130 | // if (module->GetFileSpec().GetPath(exec_path, sizeof(exec_path))) |
| 131 | // { |
| 132 | // exec_url = CFURLCreateFromFileSystemRepresentation ( NULL, |
| 133 | // (const UInt8 *)exec_path, |
| 134 | // strlen(exec_path), |
| 135 | // FALSE); |
| 136 | // } |
| 137 | // |
| 138 | // dsym_url = DBGCopyFullDSYMURLForUUID(module_uuid_ref, exec_url); |
| 139 | // } |
| 140 | // // else |
| 141 | // // { |
| 142 | // // dsym_url = DBGCopyDSYMURLForUUID(module_uuid_ref); |
| 143 | // // } |
| 144 | // |
| 145 | // if (exec_url) |
| 146 | // { |
| 147 | // ::CFRelease (exec_url); |
| 148 | // exec_url = NULL; |
| 149 | // } |
| 150 | // |
| 151 | // ::CFRelease(module_uuid_ref); |
| 152 | // module_uuid_ref = NULL; |
| 153 | // |
| 154 | // if (dsym_url) |
| 155 | // { |
| 156 | // char dsym_path[PATH_MAX]; |
| 157 | // Boolean success = CFURLGetFileSystemRepresentation (dsym_url, true, (UInt8*)dsym_path, sizeof(dsym_path)-1); |
| 158 | // |
| 159 | // ::CFRelease(dsym_url), dsym_url = NULL; |
| 160 | // |
| 161 | // if (success) |
| 162 | // { |
| 163 | // dsym_fspec.SetFile(dsym_path); |
| 164 | // |
| 165 | // // Some newer versions of DebugSymbols will return a full path into a dSYM bundle |
| 166 | // // that points to the correct mach file within the dSYM bundle (MH_DSYM mach file |
| 167 | // // type). |
| 168 | // dsym_objfile = ObjectFile::FindPlugin(module, &dsym_fspec, 0); |
| 169 | // |
| 170 | // // Olders versions of DebugSymbols will return a path to a dSYM bundle. |
| 171 | // if (dsym_objfile == NULL) |
| 172 | // dsym_objfile = LocateDSYMMachFileInDSYMBundle (module, dsym_fspec); |
| 173 | // } |
| 174 | // } |
| 175 | // } |
| 176 | // } |
| 177 | // } |
| 178 | // return dsym_objfile; |
| 179 | //} |
| 180 | |
| 181 | static void |
| 182 | ReplaceDSYMSectionsWithExecutableSections (ObjectFile *exec_objfile, ObjectFile *dsym_objfile) |
| 183 | { |
| 184 | // We need both the executable and the dSYM to live off of the |
| 185 | // same section lists. So we take all of the sections from the |
| 186 | // executable, and replace them in the dSYM. This allows section |
| 187 | // offset addresses that come from the dSYM to automatically |
| 188 | // get updated as images (shared libraries) get loaded and |
| 189 | // unloaded. |
| 190 | SectionList *exec_section_list = exec_objfile->GetSectionList(); |
| 191 | SectionList *dsym_section_list = dsym_objfile->GetSectionList(); |
| 192 | if (exec_section_list && dsym_section_list) |
| 193 | { |
| 194 | const uint32_t num_exec_sections = dsym_section_list->GetSize(); |
| 195 | uint32_t exec_sect_idx; |
| 196 | for (exec_sect_idx = 0; exec_sect_idx < num_exec_sections; ++exec_sect_idx) |
| 197 | { |
| 198 | SectionSP exec_sect_sp(exec_section_list->GetSectionAtIndex(exec_sect_idx)); |
| 199 | if (exec_sect_sp.get()) |
| 200 | { |
| 201 | // Try and replace any sections that exist in both the executable |
| 202 | // and in the dSYM with those from the executable. If we fail to |
| 203 | // replace the one in the dSYM, then add the executable section to |
| 204 | // the dSYM. |
| 205 | if (dsym_section_list->ReplaceSection(exec_sect_sp->GetID(), exec_sect_sp, 0) == false) |
| 206 | dsym_section_list->AddSection(exec_sect_sp); |
| 207 | } |
| 208 | } |
| 209 | } |
| 210 | } |
| 211 | |
| 212 | void |
| 213 | SymbolVendorMacOSX::Initialize() |
| 214 | { |
| 215 | PluginManager::RegisterPlugin (GetPluginNameStatic(), |
| 216 | GetPluginDescriptionStatic(), |
| 217 | CreateInstance); |
| 218 | } |
| 219 | |
| 220 | void |
| 221 | SymbolVendorMacOSX::Terminate() |
| 222 | { |
| 223 | PluginManager::UnregisterPlugin (CreateInstance); |
| 224 | } |
| 225 | |
| 226 | |
| 227 | const char * |
| 228 | SymbolVendorMacOSX::GetPluginNameStatic() |
| 229 | { |
| 230 | return "symbol-vendor.macosx"; |
| 231 | } |
| 232 | |
| 233 | const char * |
| 234 | SymbolVendorMacOSX::GetPluginDescriptionStatic() |
| 235 | { |
| 236 | return "Symbol vendor for MacOSX that looks for dSYM files that match executables."; |
| 237 | } |
| 238 | |
| 239 | |
| 240 | |
| 241 | //---------------------------------------------------------------------- |
| 242 | // CreateInstance |
| 243 | // |
| 244 | // Platforms can register a callback to use when creating symbol |
| 245 | // vendors to allow for complex debug information file setups, and to |
| 246 | // also allow for finding separate debug information files. |
| 247 | //---------------------------------------------------------------------- |
| 248 | SymbolVendor* |
| 249 | SymbolVendorMacOSX::CreateInstance(Module* module) |
| 250 | { |
| 251 | Timer scoped_timer (__PRETTY_FUNCTION__, |
| 252 | "SymbolVendorMacOSX::CreateInstance (module = %s/%s)", |
| 253 | module->GetFileSpec().GetDirectory().AsCString(), |
| 254 | module->GetFileSpec().GetFilename().AsCString()); |
| 255 | SymbolVendorMacOSX* symbol_vendor = new SymbolVendorMacOSX(module); |
| 256 | if (symbol_vendor) |
| 257 | { |
| 258 | char path[PATH_MAX]; |
| 259 | path[0] = '\0'; |
| 260 | |
| 261 | // Try and locate the dSYM file on Mac OS X |
| 262 | ObjectFile * obj_file = module->GetObjectFile(); |
| 263 | if (obj_file) |
| 264 | { |
| 265 | Timer scoped_timer2 ("SymbolVendorMacOSX::CreateInstance () locate dSYM", |
| 266 | "SymbolVendorMacOSX::CreateInstance (module = %s/%s) locate dSYM", |
| 267 | module->GetFileSpec().GetDirectory().AsCString(), |
| 268 | module->GetFileSpec().GetFilename().AsCString()); |
| 269 | |
| 270 | FileSpec dsym_fspec; |
| 271 | std::auto_ptr<ObjectFile> dsym_objfile_ap; |
| 272 | const FileSpec &file_spec = obj_file->GetFileSpec(); |
| 273 | if (file_spec) |
| 274 | { |
| 275 | dsym_fspec = Symbols::LocateExecutableSymbolFile (&file_spec, &module->GetArchitecture(), &module->GetUUID()); |
| 276 | |
| 277 | if (dsym_fspec) |
| 278 | { |
| 279 | dsym_objfile_ap.reset(ObjectFile::FindPlugin(module, &dsym_fspec, 0, dsym_fspec.GetByteSize())); |
| 280 | if (UUIDsMatch(module, dsym_objfile_ap.get())) |
| 281 | { |
| 282 | ReplaceDSYMSectionsWithExecutableSections (obj_file, dsym_objfile_ap.get()); |
| 283 | symbol_vendor->AddSymbolFileRepresendation(dsym_objfile_ap.release()); |
| 284 | return symbol_vendor; |
| 285 | } |
| 286 | } |
| 287 | } |
| 288 | |
| 289 | // Just create our symbol vendor using the current objfile as this is either |
| 290 | // an executable with no dSYM (that we could locate), and executable with |
| 291 | // a dSYM that has a UUID that doesn't match, or it is a dSYM file itself. |
| 292 | symbol_vendor->AddSymbolFileRepresendation(obj_file); |
| 293 | } |
| 294 | } |
| 295 | return symbol_vendor; |
| 296 | } |
| 297 | |
| 298 | |
| 299 | |
| 300 | //------------------------------------------------------------------ |
| 301 | // PluginInterface protocol |
| 302 | //------------------------------------------------------------------ |
| 303 | const char * |
| 304 | SymbolVendorMacOSX::GetPluginName() |
| 305 | { |
| 306 | return "SymbolVendorMacOSX"; |
| 307 | } |
| 308 | |
| 309 | const char * |
| 310 | SymbolVendorMacOSX::GetShortPluginName() |
| 311 | { |
| 312 | return GetPluginNameStatic(); |
| 313 | } |
| 314 | |
| 315 | uint32_t |
| 316 | SymbolVendorMacOSX::GetPluginVersion() |
| 317 | { |
| 318 | return 1; |
| 319 | } |
| 320 | |
| 321 | void |
| 322 | SymbolVendorMacOSX::GetPluginCommandHelp (const char *command, Stream *strm) |
| 323 | { |
| 324 | } |
| 325 | |
| 326 | Error |
| 327 | SymbolVendorMacOSX::ExecutePluginCommand (Args &command, Stream *strm) |
| 328 | { |
| 329 | Error error; |
| 330 | error.SetErrorString("No plug-in command are currently supported."); |
| 331 | return error; |
| 332 | } |
| 333 | |
| 334 | Log * |
| 335 | SymbolVendorMacOSX::EnablePluginLogging (Stream *strm, Args &command) |
| 336 | { |
| 337 | return NULL; |
| 338 | } |
| 339 | |