diff options
Diffstat (limited to 'lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp')
-rw-r--r-- | lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp b/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp new file mode 100644 index 00000000000..270d7ed0f5d --- /dev/null +++ b/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp @@ -0,0 +1,339 @@ +//===-- SymbolVendorMacOSX.cpp ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "SymbolVendorMacOSX.h" + +#include <mach/machine.h> // DebugSymbols needs this on Leopard... + +#include <AvailabilityMacros.h> + +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Section.h" +#include "lldb/Core/Timer.h" +#include "lldb/Host/Symbols.h" +#include "lldb/Symbol/ObjectFile.h" + +using namespace lldb; +using namespace lldb_private; + +//---------------------------------------------------------------------- +// SymbolVendorMacOSX constructor +//---------------------------------------------------------------------- +SymbolVendorMacOSX::SymbolVendorMacOSX(Module *module) : + SymbolVendor(module) +{ +} + +//---------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------- +SymbolVendorMacOSX::~SymbolVendorMacOSX() +{ +} + + +static bool +UUIDsMatch(Module *module, ObjectFile *ofile) +{ + if (module && ofile) + { + // Make sure the UUIDs match + UUID dsym_uuid; + if (ofile->GetUUID(&dsym_uuid)) + return dsym_uuid == module->GetUUID(); + } + return false; +} + + +//ObjectFile * +//LocateDSYMMachFileInDSYMBundle (Module* module, FileSpec& dsym_fspec) +//{ +// ObjectFile *dsym_objfile = NULL; +// +// char path[PATH_MAX]; +// +// if (dsym_fspec.GetPath(path, sizeof(path))) +// { +// size_t path_len = strlen(path); +// const char *bundle_subpath = "/Contents/Resources/DWARF/"; +// if (path_len > 0) +// { +// if (path[path_len-1] == '/') +// ::strncat (path, bundle_subpath + 1, sizeof(path)); +// else +// ::strncat (path, bundle_subpath, sizeof(path)); +// ::strncat (path, dsym_fspec.GetFilename().AsCString(), sizeof(path)); +// +// path_len = strlen(path); +// +// if (::strcasecmp (&path[path_len - strlen(".dSYM")], ".dSYM") == 0) +// { +// path[path_len - ::strlen(".dSYM")] = '\0'; +// dsym_fspec.SetFile(path); +// dsym_objfile = ObjectFile::FindPlugin(module, &dsym_fspec, 0); +// } +// } +// } +// return dsym_objfile; +//} +// +//CFURLRef DBGCopyFullDSYMURLForUUID (CFUUIDRef uuid, CFURLRef exec_url) __attribute__((weak_import)); + + +//ObjectFile * +//FindDSYMUsingDebugSymbols (Module* module, FileSpec& dsym_fspec) +//{ +// Timer scoped_locate("FindDSYMUsingDebugSymbols"); +// dsym_fspec.Clear(); +// ObjectFile *dsym_objfile = NULL; +// if (module->GetUUID().IsValid()) +// { +// // Try and locate the dSYM file using DebugSymbols first +// const UInt8 *module_uuid = (const UInt8 *)module->GetUUID().GetBytes(); +// if (module_uuid != NULL) +// { +// CFUUIDRef module_uuid_ref; +// module_uuid_ref = ::CFUUIDCreateWithBytes ( NULL, +// module_uuid[0], +// module_uuid[1], +// module_uuid[2], +// module_uuid[3], +// module_uuid[4], +// module_uuid[5], +// module_uuid[6], +// module_uuid[7], +// module_uuid[8], +// module_uuid[9], +// module_uuid[10], +// module_uuid[11], +// module_uuid[12], +// module_uuid[13], +// module_uuid[14], +// module_uuid[15]); +// +// if (module_uuid_ref) +// { +// CFURLRef dsym_url = NULL; +// CFURLRef exec_url = NULL; +// +// // if (DBGCopyFullDSYMURLForUUID) +// { +// char exec_path[PATH_MAX]; +// if (module->GetFileSpec().GetPath(exec_path, sizeof(exec_path))) +// { +// exec_url = CFURLCreateFromFileSystemRepresentation ( NULL, +// (const UInt8 *)exec_path, +// strlen(exec_path), +// FALSE); +// } +// +// dsym_url = DBGCopyFullDSYMURLForUUID(module_uuid_ref, exec_url); +// } +// // else +// // { +// // dsym_url = DBGCopyDSYMURLForUUID(module_uuid_ref); +// // } +// +// if (exec_url) +// { +// ::CFRelease (exec_url); +// exec_url = NULL; +// } +// +// ::CFRelease(module_uuid_ref); +// module_uuid_ref = NULL; +// +// if (dsym_url) +// { +// char dsym_path[PATH_MAX]; +// Boolean success = CFURLGetFileSystemRepresentation (dsym_url, true, (UInt8*)dsym_path, sizeof(dsym_path)-1); +// +// ::CFRelease(dsym_url), dsym_url = NULL; +// +// if (success) +// { +// dsym_fspec.SetFile(dsym_path); +// +// // Some newer versions of DebugSymbols will return a full path into a dSYM bundle +// // that points to the correct mach file within the dSYM bundle (MH_DSYM mach file +// // type). +// dsym_objfile = ObjectFile::FindPlugin(module, &dsym_fspec, 0); +// +// // Olders versions of DebugSymbols will return a path to a dSYM bundle. +// if (dsym_objfile == NULL) +// dsym_objfile = LocateDSYMMachFileInDSYMBundle (module, dsym_fspec); +// } +// } +// } +// } +// } +// return dsym_objfile; +//} + +static void +ReplaceDSYMSectionsWithExecutableSections (ObjectFile *exec_objfile, ObjectFile *dsym_objfile) +{ + // We need both the executable and the dSYM to live off of the + // same section lists. So we take all of the sections from the + // executable, and replace them in the dSYM. This allows section + // offset addresses that come from the dSYM to automatically + // get updated as images (shared libraries) get loaded and + // unloaded. + SectionList *exec_section_list = exec_objfile->GetSectionList(); + SectionList *dsym_section_list = dsym_objfile->GetSectionList(); + if (exec_section_list && dsym_section_list) + { + const uint32_t num_exec_sections = dsym_section_list->GetSize(); + uint32_t exec_sect_idx; + for (exec_sect_idx = 0; exec_sect_idx < num_exec_sections; ++exec_sect_idx) + { + SectionSP exec_sect_sp(exec_section_list->GetSectionAtIndex(exec_sect_idx)); + if (exec_sect_sp.get()) + { + // Try and replace any sections that exist in both the executable + // and in the dSYM with those from the executable. If we fail to + // replace the one in the dSYM, then add the executable section to + // the dSYM. + if (dsym_section_list->ReplaceSection(exec_sect_sp->GetID(), exec_sect_sp, 0) == false) + dsym_section_list->AddSection(exec_sect_sp); + } + } + } +} + +void +SymbolVendorMacOSX::Initialize() +{ + PluginManager::RegisterPlugin (GetPluginNameStatic(), + GetPluginDescriptionStatic(), + CreateInstance); +} + +void +SymbolVendorMacOSX::Terminate() +{ + PluginManager::UnregisterPlugin (CreateInstance); +} + + +const char * +SymbolVendorMacOSX::GetPluginNameStatic() +{ + return "symbol-vendor.macosx"; +} + +const char * +SymbolVendorMacOSX::GetPluginDescriptionStatic() +{ + return "Symbol vendor for MacOSX that looks for dSYM files that match executables."; +} + + + +//---------------------------------------------------------------------- +// CreateInstance +// +// Platforms can register a callback to use when creating symbol +// vendors to allow for complex debug information file setups, and to +// also allow for finding separate debug information files. +//---------------------------------------------------------------------- +SymbolVendor* +SymbolVendorMacOSX::CreateInstance(Module* module) +{ + Timer scoped_timer (__PRETTY_FUNCTION__, + "SymbolVendorMacOSX::CreateInstance (module = %s/%s)", + module->GetFileSpec().GetDirectory().AsCString(), + module->GetFileSpec().GetFilename().AsCString()); + SymbolVendorMacOSX* symbol_vendor = new SymbolVendorMacOSX(module); + if (symbol_vendor) + { + char path[PATH_MAX]; + path[0] = '\0'; + + // Try and locate the dSYM file on Mac OS X + ObjectFile * obj_file = module->GetObjectFile(); + if (obj_file) + { + Timer scoped_timer2 ("SymbolVendorMacOSX::CreateInstance () locate dSYM", + "SymbolVendorMacOSX::CreateInstance (module = %s/%s) locate dSYM", + module->GetFileSpec().GetDirectory().AsCString(), + module->GetFileSpec().GetFilename().AsCString()); + + FileSpec dsym_fspec; + std::auto_ptr<ObjectFile> dsym_objfile_ap; + const FileSpec &file_spec = obj_file->GetFileSpec(); + if (file_spec) + { + dsym_fspec = Symbols::LocateExecutableSymbolFile (&file_spec, &module->GetArchitecture(), &module->GetUUID()); + + if (dsym_fspec) + { + dsym_objfile_ap.reset(ObjectFile::FindPlugin(module, &dsym_fspec, 0, dsym_fspec.GetByteSize())); + if (UUIDsMatch(module, dsym_objfile_ap.get())) + { + ReplaceDSYMSectionsWithExecutableSections (obj_file, dsym_objfile_ap.get()); + symbol_vendor->AddSymbolFileRepresendation(dsym_objfile_ap.release()); + return symbol_vendor; + } + } + } + + // Just create our symbol vendor using the current objfile as this is either + // an executable with no dSYM (that we could locate), and executable with + // a dSYM that has a UUID that doesn't match, or it is a dSYM file itself. + symbol_vendor->AddSymbolFileRepresendation(obj_file); + } + } + return symbol_vendor; +} + + + +//------------------------------------------------------------------ +// PluginInterface protocol +//------------------------------------------------------------------ +const char * +SymbolVendorMacOSX::GetPluginName() +{ + return "SymbolVendorMacOSX"; +} + +const char * +SymbolVendorMacOSX::GetShortPluginName() +{ + return GetPluginNameStatic(); +} + +uint32_t +SymbolVendorMacOSX::GetPluginVersion() +{ + return 1; +} + +void +SymbolVendorMacOSX::GetPluginCommandHelp (const char *command, Stream *strm) +{ +} + +Error +SymbolVendorMacOSX::ExecutePluginCommand (Args &command, Stream *strm) +{ + Error error; + error.SetErrorString("No plug-in command are currently supported."); + return error; +} + +Log * +SymbolVendorMacOSX::EnablePluginLogging (Stream *strm, Args &command) +{ + return NULL; +} + |