forked from OSchip/llvm-project
338 lines
12 KiB
C++
338 lines
12 KiB
C++
//===-- 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 <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;
|
|
}
|
|
|