//===-- PluginManager.cpp ---------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "lldb/Core/PluginManager.h" #include #include #include #include "lldb/Core/Error.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/Host.h" #include "lldb/Host/Mutex.h" using namespace lldb; using namespace lldb_private; enum PluginAction { ePluginRegisterInstance, ePluginUnregisterInstance, ePluginGetInstanceAtIndex }; struct PluginInfo { void *plugin_handle; void *plugin_init_callback; void *plugin_term_callback; }; typedef std::map PluginTerminateMap; static Mutex & GetPluginMapMutex () { static Mutex g_plugin_map_mutex (Mutex::eMutexTypeRecursive); return g_plugin_map_mutex; } static PluginTerminateMap & GetPluginMap () { static PluginTerminateMap g_plugin_map; return g_plugin_map; } static bool PluginIsLoaded (const FileSpec &plugin_file_spec) { Mutex::Locker locker (GetPluginMapMutex ()); PluginTerminateMap &plugin_map = GetPluginMap (); return plugin_map.find (plugin_file_spec) != plugin_map.end(); } static void SetPluginInfo (const FileSpec &plugin_file_spec, const PluginInfo &plugin_info) { Mutex::Locker locker (GetPluginMapMutex ()); PluginTerminateMap &plugin_map = GetPluginMap (); assert (plugin_map.find (plugin_file_spec) != plugin_map.end()); plugin_map[plugin_file_spec] = plugin_info; } static FileSpec::EnumerateDirectoryResult LoadPluginCallback ( void *baton, FileSpec::FileType file_type, const FileSpec &file_spec ) { // PluginManager *plugin_manager = (PluginManager *)baton; Error error; // If we have a regular file, a symbolic link or unknown file type, try // and process the file. We must handle unknown as sometimes the directory // enumeration might be enumerating a file system that doesn't have correct // file type information. if (file_type == FileSpec::eFileTypeRegular || file_type == FileSpec::eFileTypeSymbolicLink || file_type == FileSpec::eFileTypeUnknown ) { FileSpec plugin_file_spec (file_spec); plugin_file_spec.ResolvePath(); if (PluginIsLoaded (plugin_file_spec)) return FileSpec::eEnumerateDirectoryResultNext; else { PluginInfo plugin_info = { NULL, NULL, NULL }; uint32_t flags = Host::eDynamicLibraryOpenOptionLazy | Host::eDynamicLibraryOpenOptionLocal | Host::eDynamicLibraryOpenOptionLimitGetSymbol; plugin_info.plugin_handle = Host::DynamicLibraryOpen (plugin_file_spec, flags, error); if (plugin_info.plugin_handle) { bool success = false; plugin_info.plugin_init_callback = Host::DynamicLibraryGetSymbol (plugin_info.plugin_handle, "LLDBPluginInitialize", error); if (plugin_info.plugin_init_callback) { // Call the plug-in "bool LLDBPluginInitialize(void)" function success = ((bool (*)(void))plugin_info.plugin_init_callback)(); } if (success) { // It is ok for the "LLDBPluginTerminate" symbol to be NULL plugin_info.plugin_term_callback = Host::DynamicLibraryGetSymbol (plugin_info.plugin_handle, "LLDBPluginTerminate", error); } else { // The initialize function returned FALSE which means the // plug-in might not be compatible, or might be too new or // too old, or might not want to run on this machine. Host::DynamicLibraryClose (plugin_info.plugin_handle); plugin_info.plugin_handle = NULL; plugin_info.plugin_init_callback = NULL; } // Regardless of success or failure, cache the plug-in load // in our plug-in info so we don't try to load it again and // again. SetPluginInfo (plugin_file_spec, plugin_info); return FileSpec::eEnumerateDirectoryResultNext; } } } if (file_type == FileSpec::eFileTypeUnknown || file_type == FileSpec::eFileTypeDirectory || file_type == FileSpec::eFileTypeSymbolicLink ) { // Try and recurse into anything that a directory or symbolic link. // We must also do this for unknown as sometimes the directory enumeration // might be enurating a file system that doesn't have correct file type // information. return FileSpec::eEnumerateDirectoryResultEnter; } return FileSpec::eEnumerateDirectoryResultNext; } void PluginManager::Initialize () { #if 1 FileSpec dir_spec; const bool find_directories = true; const bool find_files = true; const bool find_other = true; char dir_path[PATH_MAX]; if (Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec)) { if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) { FileSpec::EnumerateDirectory (dir_path, find_directories, find_files, find_other, LoadPluginCallback, NULL); } } if (Host::GetLLDBPath (ePathTypeLLDBUserPlugins, dir_spec)) { if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) { FileSpec::EnumerateDirectory (dir_path, find_directories, find_files, find_other, LoadPluginCallback, NULL); } } #endif } void PluginManager::Terminate () { Mutex::Locker locker (GetPluginMapMutex ()); PluginTerminateMap &plugin_map = GetPluginMap (); PluginTerminateMap::const_iterator pos, end = plugin_map.end(); for (pos = plugin_map.begin(); pos != end; ++pos) { // Call the plug-in "void LLDBPluginTerminate (void)" function if there // is one (if the symbol was not NULL). if (pos->second.plugin_handle) { if (pos->second.plugin_term_callback) ((void (*)(void))pos->second.plugin_term_callback)(); Host::DynamicLibraryClose (pos->second.plugin_handle); } } plugin_map.clear(); } #pragma mark ABI struct ABIInstance { ABIInstance() : name(), description(), create_callback(NULL) { } std::string name; std::string description; ABICreateInstance create_callback; }; typedef std::vector ABIInstances; static Mutex & GetABIInstancesMutex () { static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); return g_instances_mutex; } static ABIInstances & GetABIInstances () { static ABIInstances g_instances; return g_instances; } bool PluginManager::RegisterPlugin ( const char *name, const char *description, ABICreateInstance create_callback ) { if (create_callback) { ABIInstance instance; assert (name && name[0]); instance.name = name; if (description && description[0]) instance.description = description; instance.create_callback = create_callback; Mutex::Locker locker (GetABIInstancesMutex ()); GetABIInstances ().push_back (instance); return true; } return false; } bool PluginManager::UnregisterPlugin (ABICreateInstance create_callback) { if (create_callback) { Mutex::Locker locker (GetABIInstancesMutex ()); ABIInstances &instances = GetABIInstances (); ABIInstances::iterator pos, end = instances.end(); for (pos = instances.begin(); pos != end; ++ pos) { if (pos->create_callback == create_callback) { instances.erase(pos); return true; } } } return false; } ABICreateInstance PluginManager::GetABICreateCallbackAtIndex (uint32_t idx) { Mutex::Locker locker (GetABIInstancesMutex ()); ABIInstances &instances = GetABIInstances (); if (idx < instances.size()) return instances[idx].create_callback; return NULL; } ABICreateInstance PluginManager::GetABICreateCallbackForPluginName (const char *name) { if (name && name[0]) { Mutex::Locker locker (GetABIInstancesMutex ()); std::string ss_name(name); ABIInstances &instances = GetABIInstances (); ABIInstances::iterator pos, end = instances.end(); for (pos = instances.begin(); pos != end; ++ pos) { if (pos->name == ss_name) return pos->create_callback; } } return NULL; } #pragma mark Disassembler struct DisassemblerInstance { DisassemblerInstance() : name(), description(), create_callback(NULL) { } std::string name; std::string description; DisassemblerCreateInstance create_callback; }; typedef std::vector DisassemblerInstances; static bool AccessDisassemblerInstances (PluginAction action, DisassemblerInstance &instance, uint32_t index) { static DisassemblerInstances g_plugin_instances; switch (action) { case ePluginRegisterInstance: if (instance.create_callback) { g_plugin_instances.push_back (instance); return true; } break; case ePluginUnregisterInstance: if (instance.create_callback) { DisassemblerInstances::iterator pos, end = g_plugin_instances.end(); for (pos = g_plugin_instances.begin(); pos != end; ++ pos) { if (pos->create_callback == instance.create_callback) { g_plugin_instances.erase(pos); return true; } } } break; case ePluginGetInstanceAtIndex: if (index < g_plugin_instances.size()) { instance = g_plugin_instances[index]; return true; } break; default: break; } return false; } bool PluginManager::RegisterPlugin ( const char *name, const char *description, DisassemblerCreateInstance create_callback ) { if (create_callback) { DisassemblerInstance instance; assert (name && name[0]); instance.name = name; if (description && description[0]) instance.description = description; instance.create_callback = create_callback; return AccessDisassemblerInstances (ePluginRegisterInstance, instance, 0); } return false; } bool PluginManager::UnregisterPlugin (DisassemblerCreateInstance create_callback) { if (create_callback) { DisassemblerInstance instance; instance.create_callback = create_callback; return AccessDisassemblerInstances (ePluginUnregisterInstance, instance, 0); } return false; } DisassemblerCreateInstance PluginManager::GetDisassemblerCreateCallbackAtIndex (uint32_t idx) { DisassemblerInstance instance; if (AccessDisassemblerInstances (ePluginGetInstanceAtIndex, instance, idx)) return instance.create_callback; return NULL; } DisassemblerCreateInstance PluginManager::GetDisassemblerCreateCallbackForPluginName (const char *name) { if (name && name[0]) { DisassemblerInstance instance; std::string ss_name(name); for (uint32_t idx = 0; AccessDisassemblerInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx) { if (instance.name == ss_name) return instance.create_callback; } } return NULL; } #pragma mark DynamicLoader struct DynamicLoaderInstance { DynamicLoaderInstance() : name(), description(), create_callback(NULL) { } std::string name; std::string description; DynamicLoaderCreateInstance create_callback; }; typedef std::vector DynamicLoaderInstances; static bool AccessDynamicLoaderInstances (PluginAction action, DynamicLoaderInstance &instance, uint32_t index) { static DynamicLoaderInstances g_plugin_instances; switch (action) { case ePluginRegisterInstance: if (instance.create_callback) { g_plugin_instances.push_back (instance); return true; } break; case ePluginUnregisterInstance: if (instance.create_callback) { DynamicLoaderInstances::iterator pos, end = g_plugin_instances.end(); for (pos = g_plugin_instances.begin(); pos != end; ++ pos) { if (pos->create_callback == instance.create_callback) { g_plugin_instances.erase(pos); return true; } } } break; case ePluginGetInstanceAtIndex: if (index < g_plugin_instances.size()) { instance = g_plugin_instances[index]; return true; } break; default: break; } return false; } bool PluginManager::RegisterPlugin ( const char *name, const char *description, DynamicLoaderCreateInstance create_callback ) { if (create_callback) { DynamicLoaderInstance instance; assert (name && name[0]); instance.name = name; if (description && description[0]) instance.description = description; instance.create_callback = create_callback; return AccessDynamicLoaderInstances (ePluginRegisterInstance, instance, 0); } return false; } bool PluginManager::UnregisterPlugin (DynamicLoaderCreateInstance create_callback) { if (create_callback) { DynamicLoaderInstance instance; instance.create_callback = create_callback; return AccessDynamicLoaderInstances (ePluginUnregisterInstance, instance, 0); } return false; } DynamicLoaderCreateInstance PluginManager::GetDynamicLoaderCreateCallbackAtIndex (uint32_t idx) { DynamicLoaderInstance instance; if (AccessDynamicLoaderInstances (ePluginGetInstanceAtIndex, instance, idx)) return instance.create_callback; return NULL; } DynamicLoaderCreateInstance PluginManager::GetDynamicLoaderCreateCallbackForPluginName (const char *name) { if (name && name[0]) { DynamicLoaderInstance instance; std::string ss_name(name); for (uint32_t idx = 0; AccessDynamicLoaderInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx) { if (instance.name == ss_name) return instance.create_callback; } } return NULL; } #pragma mark EmulateInstruction struct EmulateInstructionInstance { EmulateInstructionInstance() : name(), description(), create_callback(NULL) { } std::string name; std::string description; EmulateInstructionCreateInstance create_callback; }; typedef std::vector EmulateInstructionInstances; static bool AccessEmulateInstructionInstances (PluginAction action, EmulateInstructionInstance &instance, uint32_t index) { static EmulateInstructionInstances g_plugin_instances; switch (action) { case ePluginRegisterInstance: if (instance.create_callback) { g_plugin_instances.push_back (instance); return true; } break; case ePluginUnregisterInstance: if (instance.create_callback) { EmulateInstructionInstances::iterator pos, end = g_plugin_instances.end(); for (pos = g_plugin_instances.begin(); pos != end; ++ pos) { if (pos->create_callback == instance.create_callback) { g_plugin_instances.erase(pos); return true; } } } break; case ePluginGetInstanceAtIndex: if (index < g_plugin_instances.size()) { instance = g_plugin_instances[index]; return true; } break; default: break; } return false; } bool PluginManager::RegisterPlugin ( const char *name, const char *description, EmulateInstructionCreateInstance create_callback ) { if (create_callback) { EmulateInstructionInstance instance; assert (name && name[0]); instance.name = name; if (description && description[0]) instance.description = description; instance.create_callback = create_callback; return AccessEmulateInstructionInstances (ePluginRegisterInstance, instance, 0); } return false; } bool PluginManager::UnregisterPlugin (EmulateInstructionCreateInstance create_callback) { if (create_callback) { EmulateInstructionInstance instance; instance.create_callback = create_callback; return AccessEmulateInstructionInstances (ePluginUnregisterInstance, instance, 0); } return false; } EmulateInstructionCreateInstance PluginManager::GetEmulateInstructionCreateCallbackAtIndex (uint32_t idx) { EmulateInstructionInstance instance; if (AccessEmulateInstructionInstances (ePluginGetInstanceAtIndex, instance, idx)) return instance.create_callback; return NULL; } EmulateInstructionCreateInstance PluginManager::GetEmulateInstructionCreateCallbackForPluginName (const char *name) { if (name && name[0]) { EmulateInstructionInstance instance; std::string ss_name(name); for (uint32_t idx = 0; AccessEmulateInstructionInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx) { if (instance.name == ss_name) return instance.create_callback; } } return NULL; } #pragma mark LanguageRuntime struct LanguageRuntimeInstance { LanguageRuntimeInstance() : name(), description(), create_callback(NULL) { } std::string name; std::string description; LanguageRuntimeCreateInstance create_callback; }; typedef std::vector LanguageRuntimeInstances; static bool AccessLanguageRuntimeInstances (PluginAction action, LanguageRuntimeInstance &instance, uint32_t index) { static LanguageRuntimeInstances g_plugin_instances; switch (action) { case ePluginRegisterInstance: if (instance.create_callback) { g_plugin_instances.push_back (instance); return true; } break; case ePluginUnregisterInstance: if (instance.create_callback) { LanguageRuntimeInstances::iterator pos, end = g_plugin_instances.end(); for (pos = g_plugin_instances.begin(); pos != end; ++ pos) { if (pos->create_callback == instance.create_callback) { g_plugin_instances.erase(pos); return true; } } } break; case ePluginGetInstanceAtIndex: if (index < g_plugin_instances.size()) { instance = g_plugin_instances[index]; return true; } break; default: break; } return false; } bool PluginManager::RegisterPlugin ( const char *name, const char *description, LanguageRuntimeCreateInstance create_callback ) { if (create_callback) { LanguageRuntimeInstance instance; assert (name && name[0]); instance.name = name; if (description && description[0]) instance.description = description; instance.create_callback = create_callback; return AccessLanguageRuntimeInstances (ePluginRegisterInstance, instance, 0); } return false; } bool PluginManager::UnregisterPlugin (LanguageRuntimeCreateInstance create_callback) { if (create_callback) { LanguageRuntimeInstance instance; instance.create_callback = create_callback; return AccessLanguageRuntimeInstances (ePluginUnregisterInstance, instance, 0); } return false; } LanguageRuntimeCreateInstance PluginManager::GetLanguageRuntimeCreateCallbackAtIndex (uint32_t idx) { LanguageRuntimeInstance instance; if (AccessLanguageRuntimeInstances (ePluginGetInstanceAtIndex, instance, idx)) return instance.create_callback; return NULL; } LanguageRuntimeCreateInstance PluginManager::GetLanguageRuntimeCreateCallbackForPluginName (const char *name) { if (name && name[0]) { LanguageRuntimeInstance instance; std::string ss_name(name); for (uint32_t idx = 0; AccessLanguageRuntimeInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx) { if (instance.name == ss_name) return instance.create_callback; } } return NULL; } #pragma mark ObjectFile struct ObjectFileInstance { ObjectFileInstance() : name(), description(), create_callback(NULL) { } std::string name; std::string description; ObjectFileCreateInstance create_callback; }; typedef std::vector ObjectFileInstances; static bool AccessObjectFileInstances (PluginAction action, ObjectFileInstance &instance, uint32_t index) { static ObjectFileInstances g_plugin_instances; switch (action) { case ePluginRegisterInstance: if (instance.create_callback) { g_plugin_instances.push_back (instance); return true; } break; case ePluginUnregisterInstance: if (instance.create_callback) { ObjectFileInstances::iterator pos, end = g_plugin_instances.end(); for (pos = g_plugin_instances.begin(); pos != end; ++ pos) { if (pos->create_callback == instance.create_callback) { g_plugin_instances.erase(pos); return true; } } } break; case ePluginGetInstanceAtIndex: if (index < g_plugin_instances.size()) { instance = g_plugin_instances[index]; return true; } break; default: break; } return false; } bool PluginManager::RegisterPlugin ( const char *name, const char *description, ObjectFileCreateInstance create_callback ) { if (create_callback) { ObjectFileInstance instance; assert (name && name[0]); instance.name = name; if (description && description[0]) instance.description = description; instance.create_callback = create_callback; return AccessObjectFileInstances (ePluginRegisterInstance, instance, 0); } return false; } bool PluginManager::UnregisterPlugin (ObjectFileCreateInstance create_callback) { if (create_callback) { ObjectFileInstance instance; instance.create_callback = create_callback; return AccessObjectFileInstances (ePluginUnregisterInstance, instance, 0); } return false; } ObjectFileCreateInstance PluginManager::GetObjectFileCreateCallbackAtIndex (uint32_t idx) { ObjectFileInstance instance; if (AccessObjectFileInstances (ePluginGetInstanceAtIndex, instance, idx)) return instance.create_callback; return NULL; } ObjectFileCreateInstance PluginManager::GetObjectFileCreateCallbackForPluginName (const char *name) { if (name && name[0]) { ObjectFileInstance instance; std::string ss_name(name); for (uint32_t idx = 0; AccessObjectFileInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx) { if (instance.name == ss_name) return instance.create_callback; } } return NULL; } #pragma mark ObjectContainer struct ObjectContainerInstance { ObjectContainerInstance() : name(), description(), create_callback(NULL) { } std::string name; std::string description; ObjectContainerCreateInstance create_callback; }; typedef std::vector ObjectContainerInstances; static bool AccessObjectContainerInstances (PluginAction action, ObjectContainerInstance &instance, uint32_t index) { static ObjectContainerInstances g_plugin_instances; switch (action) { case ePluginRegisterInstance: if (instance.create_callback) { g_plugin_instances.push_back (instance); return true; } break; case ePluginUnregisterInstance: if (instance.create_callback) { ObjectContainerInstances::iterator pos, end = g_plugin_instances.end(); for (pos = g_plugin_instances.begin(); pos != end; ++ pos) { if (pos->create_callback == instance.create_callback) { g_plugin_instances.erase(pos); return true; } } } break; case ePluginGetInstanceAtIndex: if (index < g_plugin_instances.size()) { instance = g_plugin_instances[index]; return true; } break; default: break; } return false; } bool PluginManager::RegisterPlugin ( const char *name, const char *description, ObjectContainerCreateInstance create_callback ) { if (create_callback) { ObjectContainerInstance instance; assert (name && name[0]); instance.name = name; if (description && description[0]) instance.description = description; instance.create_callback = create_callback; return AccessObjectContainerInstances (ePluginRegisterInstance, instance, 0); } return false; } bool PluginManager::UnregisterPlugin (ObjectContainerCreateInstance create_callback) { if (create_callback) { ObjectContainerInstance instance; instance.create_callback = create_callback; return AccessObjectContainerInstances (ePluginUnregisterInstance, instance, 0); } return false; } ObjectContainerCreateInstance PluginManager::GetObjectContainerCreateCallbackAtIndex (uint32_t idx) { ObjectContainerInstance instance; if (AccessObjectContainerInstances (ePluginGetInstanceAtIndex, instance, idx)) return instance.create_callback; return NULL; } ObjectContainerCreateInstance PluginManager::GetObjectContainerCreateCallbackForPluginName (const char *name) { if (name && name[0]) { ObjectContainerInstance instance; std::string ss_name(name); for (uint32_t idx = 0; AccessObjectContainerInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx) { if (instance.name == ss_name) return instance.create_callback; } } return NULL; } #pragma mark LogChannel struct LogChannelInstance { LogChannelInstance() : name(), description(), create_callback(NULL) { } std::string name; std::string description; LogChannelCreateInstance create_callback; }; typedef std::vector LogChannelInstances; static bool AccessLogChannelInstances (PluginAction action, LogChannelInstance &instance, uint32_t index) { static LogChannelInstances g_plugin_instances; switch (action) { case ePluginRegisterInstance: if (instance.create_callback) { g_plugin_instances.push_back (instance); return true; } break; case ePluginUnregisterInstance: if (instance.create_callback) { LogChannelInstances::iterator pos, end = g_plugin_instances.end(); for (pos = g_plugin_instances.begin(); pos != end; ++ pos) { if (pos->create_callback == instance.create_callback) { g_plugin_instances.erase(pos); return true; } } } break; case ePluginGetInstanceAtIndex: if (index < g_plugin_instances.size()) { instance = g_plugin_instances[index]; return true; } break; default: break; } return false; } bool PluginManager::RegisterPlugin ( const char *name, const char *description, LogChannelCreateInstance create_callback ) { if (create_callback) { LogChannelInstance instance; assert (name && name[0]); instance.name = name; if (description && description[0]) instance.description = description; instance.create_callback = create_callback; return AccessLogChannelInstances (ePluginRegisterInstance, instance, 0); } return false; } bool PluginManager::UnregisterPlugin (LogChannelCreateInstance create_callback) { if (create_callback) { LogChannelInstance instance; instance.create_callback = create_callback; return AccessLogChannelInstances (ePluginUnregisterInstance, instance, 0); } return false; } const char * PluginManager::GetLogChannelCreateNameAtIndex (uint32_t idx) { LogChannelInstance instance; if (AccessLogChannelInstances (ePluginGetInstanceAtIndex, instance, idx)) return instance.name.c_str(); return NULL; } LogChannelCreateInstance PluginManager::GetLogChannelCreateCallbackAtIndex (uint32_t idx) { LogChannelInstance instance; if (AccessLogChannelInstances (ePluginGetInstanceAtIndex, instance, idx)) return instance.create_callback; return NULL; } LogChannelCreateInstance PluginManager::GetLogChannelCreateCallbackForPluginName (const char *name) { if (name && name[0]) { LogChannelInstance instance; std::string ss_name(name); for (uint32_t idx = 0; AccessLogChannelInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx) { if (instance.name == ss_name) return instance.create_callback; } } return NULL; } #pragma mark Platform struct PlatformInstance { PlatformInstance() : name(), description(), create_callback(NULL) { } std::string name; std::string description; PlatformCreateInstance create_callback; }; typedef std::vector PlatformInstances; static Mutex & GetPlatformInstancesMutex () { static Mutex g_platform_instances_mutex (Mutex::eMutexTypeRecursive); return g_platform_instances_mutex; } static PlatformInstances & GetPlatformInstances () { static PlatformInstances g_platform_instances; return g_platform_instances; } bool PluginManager::RegisterPlugin (const char *name, const char *description, PlatformCreateInstance create_callback) { if (create_callback) { Mutex::Locker locker (GetPlatformInstancesMutex ()); PlatformInstance instance; assert (name && name[0]); instance.name = name; if (description && description[0]) instance.description = description; instance.create_callback = create_callback; GetPlatformInstances ().push_back (instance); return true; } return false; } const char * PluginManager::GetPlatformPluginNameAtIndex (uint32_t idx) { Mutex::Locker locker (GetPlatformInstancesMutex ()); PlatformInstances &platform_instances = GetPlatformInstances (); if (idx < platform_instances.size()) return platform_instances[idx].name.c_str(); return NULL; } const char * PluginManager::GetPlatformPluginDescriptionAtIndex (uint32_t idx) { Mutex::Locker locker (GetPlatformInstancesMutex ()); PlatformInstances &platform_instances = GetPlatformInstances (); if (idx < platform_instances.size()) return platform_instances[idx].description.c_str(); return NULL; } bool PluginManager::UnregisterPlugin (PlatformCreateInstance create_callback) { if (create_callback) { Mutex::Locker locker (GetPlatformInstancesMutex ()); PlatformInstances &platform_instances = GetPlatformInstances (); PlatformInstances::iterator pos, end = platform_instances.end(); for (pos = platform_instances.begin(); pos != end; ++ pos) { if (pos->create_callback == create_callback) { platform_instances.erase(pos); return true; } } } return false; } PlatformCreateInstance PluginManager::GetPlatformCreateCallbackAtIndex (uint32_t idx) { Mutex::Locker locker (GetPlatformInstancesMutex ()); PlatformInstances &platform_instances = GetPlatformInstances (); if (idx < platform_instances.size()) return platform_instances[idx].create_callback; return NULL; } PlatformCreateInstance PluginManager::GetPlatformCreateCallbackForPluginName (const char *name) { if (name && name[0]) { Mutex::Locker locker (GetPlatformInstancesMutex ()); std::string ss_name(name); PlatformInstances &platform_instances = GetPlatformInstances (); PlatformInstances::iterator pos, end = platform_instances.end(); for (pos = platform_instances.begin(); pos != end; ++ pos) { if (pos->name == ss_name) return pos->create_callback; } } return NULL; } #pragma mark Process struct ProcessInstance { ProcessInstance() : name(), description(), create_callback(NULL) { } std::string name; std::string description; ProcessCreateInstance create_callback; }; typedef std::vector ProcessInstances; static bool AccessProcessInstances (PluginAction action, ProcessInstance &instance, uint32_t index) { static ProcessInstances g_plugin_instances; switch (action) { case ePluginRegisterInstance: if (instance.create_callback) { g_plugin_instances.push_back (instance); return true; } break; case ePluginUnregisterInstance: if (instance.create_callback) { ProcessInstances::iterator pos, end = g_plugin_instances.end(); for (pos = g_plugin_instances.begin(); pos != end; ++ pos) { if (pos->create_callback == instance.create_callback) { g_plugin_instances.erase(pos); return true; } } } break; case ePluginGetInstanceAtIndex: if (index < g_plugin_instances.size()) { instance = g_plugin_instances[index]; return true; } break; default: break; } return false; } bool PluginManager::RegisterPlugin ( const char *name, const char *description, ProcessCreateInstance create_callback ) { if (create_callback) { ProcessInstance instance; assert (name && name[0]); instance.name = name; if (description && description[0]) instance.description = description; instance.create_callback = create_callback; return AccessProcessInstances (ePluginRegisterInstance, instance, 0); } return false; } const char * PluginManager::GetProcessPluginNameAtIndex (uint32_t idx) { ProcessInstance instance; if (AccessProcessInstances (ePluginGetInstanceAtIndex, instance, idx)) return instance.name.c_str(); return NULL; } const char * PluginManager::GetProcessPluginDescriptionAtIndex (uint32_t idx) { ProcessInstance instance; if (AccessProcessInstances (ePluginGetInstanceAtIndex, instance, idx)) return instance.description.c_str(); return NULL; } bool PluginManager::UnregisterPlugin (ProcessCreateInstance create_callback) { if (create_callback) { ProcessInstance instance; instance.create_callback = create_callback; return AccessProcessInstances (ePluginUnregisterInstance, instance, 0); } return false; } ProcessCreateInstance PluginManager::GetProcessCreateCallbackAtIndex (uint32_t idx) { ProcessInstance instance; if (AccessProcessInstances (ePluginGetInstanceAtIndex, instance, idx)) return instance.create_callback; return NULL; } ProcessCreateInstance PluginManager::GetProcessCreateCallbackForPluginName (const char *name) { if (name && name[0]) { ProcessInstance instance; std::string ss_name(name); for (uint32_t idx = 0; AccessProcessInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx) { if (instance.name == ss_name) return instance.create_callback; } } return NULL; } #pragma mark SymbolFile struct SymbolFileInstance { SymbolFileInstance() : name(), description(), create_callback(NULL) { } std::string name; std::string description; SymbolFileCreateInstance create_callback; }; typedef std::vector SymbolFileInstances; static bool AccessSymbolFileInstances (PluginAction action, SymbolFileInstance &instance, uint32_t index) { static SymbolFileInstances g_plugin_instances; switch (action) { case ePluginRegisterInstance: if (instance.create_callback) { g_plugin_instances.push_back (instance); return true; } break; case ePluginUnregisterInstance: if (instance.create_callback) { SymbolFileInstances::iterator pos, end = g_plugin_instances.end(); for (pos = g_plugin_instances.begin(); pos != end; ++ pos) { if (pos->create_callback == instance.create_callback) { g_plugin_instances.erase(pos); return true; } } } break; case ePluginGetInstanceAtIndex: if (index < g_plugin_instances.size()) { instance = g_plugin_instances[index]; return true; } break; default: break; } return false; } bool PluginManager::RegisterPlugin ( const char *name, const char *description, SymbolFileCreateInstance create_callback ) { if (create_callback) { SymbolFileInstance instance; assert (name && name[0]); instance.name = name; if (description && description[0]) instance.description = description; instance.create_callback = create_callback; return AccessSymbolFileInstances (ePluginRegisterInstance, instance, 0); } return false; } bool PluginManager::UnregisterPlugin (SymbolFileCreateInstance create_callback) { if (create_callback) { SymbolFileInstance instance; instance.create_callback = create_callback; return AccessSymbolFileInstances (ePluginUnregisterInstance, instance, 0); } return false; } SymbolFileCreateInstance PluginManager::GetSymbolFileCreateCallbackAtIndex (uint32_t idx) { SymbolFileInstance instance; if (AccessSymbolFileInstances (ePluginGetInstanceAtIndex, instance, idx)) return instance.create_callback; return NULL; } SymbolFileCreateInstance PluginManager::GetSymbolFileCreateCallbackForPluginName (const char *name) { if (name && name[0]) { SymbolFileInstance instance; std::string ss_name(name); for (uint32_t idx = 0; AccessSymbolFileInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx) { if (instance.name == ss_name) return instance.create_callback; } } return NULL; } #pragma mark SymbolVendor struct SymbolVendorInstance { SymbolVendorInstance() : name(), description(), create_callback(NULL) { } std::string name; std::string description; SymbolVendorCreateInstance create_callback; }; typedef std::vector SymbolVendorInstances; static bool AccessSymbolVendorInstances (PluginAction action, SymbolVendorInstance &instance, uint32_t index) { static SymbolVendorInstances g_plugin_instances; switch (action) { case ePluginRegisterInstance: if (instance.create_callback) { g_plugin_instances.push_back (instance); return true; } break; case ePluginUnregisterInstance: if (instance.create_callback) { SymbolVendorInstances::iterator pos, end = g_plugin_instances.end(); for (pos = g_plugin_instances.begin(); pos != end; ++ pos) { if (pos->create_callback == instance.create_callback) { g_plugin_instances.erase(pos); return true; } } } break; case ePluginGetInstanceAtIndex: if (index < g_plugin_instances.size()) { instance = g_plugin_instances[index]; return true; } break; default: break; } return false; } bool PluginManager::RegisterPlugin ( const char *name, const char *description, SymbolVendorCreateInstance create_callback ) { if (create_callback) { SymbolVendorInstance instance; assert (name && name[0]); instance.name = name; if (description && description[0]) instance.description = description; instance.create_callback = create_callback; return AccessSymbolVendorInstances (ePluginRegisterInstance, instance, 0); } return false; } bool PluginManager::UnregisterPlugin (SymbolVendorCreateInstance create_callback) { if (create_callback) { SymbolVendorInstance instance; instance.create_callback = create_callback; return AccessSymbolVendorInstances (ePluginUnregisterInstance, instance, 0); } return false; } SymbolVendorCreateInstance PluginManager::GetSymbolVendorCreateCallbackAtIndex (uint32_t idx) { SymbolVendorInstance instance; if (AccessSymbolVendorInstances (ePluginGetInstanceAtIndex, instance, idx)) return instance.create_callback; return NULL; } SymbolVendorCreateInstance PluginManager::GetSymbolVendorCreateCallbackForPluginName (const char *name) { if (name && name[0]) { SymbolVendorInstance instance; std::string ss_name(name); for (uint32_t idx = 0; AccessSymbolVendorInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx) { if (instance.name == ss_name) return instance.create_callback; } } return NULL; } #pragma mark UnwindAssemblyProfiler struct UnwindAssemblyProfilerInstance { UnwindAssemblyProfilerInstance() : name(), description(), create_callback(NULL) { } std::string name; std::string description; UnwindAssemblyProfilerCreateInstance create_callback; }; typedef std::vector UnwindAssemblyProfilerInstances; static bool AccessUnwindAssemblyProfilerInstances (PluginAction action, UnwindAssemblyProfilerInstance &instance, uint32_t index) { static UnwindAssemblyProfilerInstances g_plugin_instances; switch (action) { case ePluginRegisterInstance: if (instance.create_callback) { g_plugin_instances.push_back (instance); return true; } break; case ePluginUnregisterInstance: if (instance.create_callback) { UnwindAssemblyProfilerInstances::iterator pos, end = g_plugin_instances.end(); for (pos = g_plugin_instances.begin(); pos != end; ++ pos) { if (pos->create_callback == instance.create_callback) { g_plugin_instances.erase(pos); return true; } } } break; case ePluginGetInstanceAtIndex: if (index < g_plugin_instances.size()) { instance = g_plugin_instances[index]; return true; } break; default: break; } return false; } bool PluginManager::RegisterPlugin ( const char *name, const char *description, UnwindAssemblyProfilerCreateInstance create_callback ) { if (create_callback) { UnwindAssemblyProfilerInstance instance; assert (name && name[0]); instance.name = name; if (description && description[0]) instance.description = description; instance.create_callback = create_callback; return AccessUnwindAssemblyProfilerInstances (ePluginRegisterInstance, instance, 0); } return false; } bool PluginManager::UnregisterPlugin (UnwindAssemblyProfilerCreateInstance create_callback) { if (create_callback) { UnwindAssemblyProfilerInstance instance; instance.create_callback = create_callback; return AccessUnwindAssemblyProfilerInstances (ePluginUnregisterInstance, instance, 0); } return false; } UnwindAssemblyProfilerCreateInstance PluginManager::GetUnwindAssemblyProfilerCreateCallbackAtIndex (uint32_t idx) { UnwindAssemblyProfilerInstance instance; if (AccessUnwindAssemblyProfilerInstances (ePluginGetInstanceAtIndex, instance, idx)) return instance.create_callback; return NULL; } UnwindAssemblyProfilerCreateInstance PluginManager::GetUnwindAssemblyProfilerCreateCallbackForPluginName (const char *name) { if (name && name[0]) { UnwindAssemblyProfilerInstance instance; std::string ss_name(name); for (uint32_t idx = 0; AccessUnwindAssemblyProfilerInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx) { if (instance.name == ss_name) return instance.create_callback; } } return NULL; } #pragma mark ArchDefaultUnwindPlan struct ArchDefaultUnwindPlanInstance { ArchDefaultUnwindPlanInstance() : name(), description(), create_callback(NULL) { } std::string name; std::string description; ArchDefaultUnwindPlanCreateInstance create_callback; }; typedef std::vector ArchDefaultUnwindPlanInstances; static bool AccessArchDefaultUnwindPlanInstances (PluginAction action, ArchDefaultUnwindPlanInstance &instance, uint32_t index) { static ArchDefaultUnwindPlanInstances g_plugin_instances; switch (action) { case ePluginRegisterInstance: if (instance.create_callback) { g_plugin_instances.push_back (instance); return true; } break; case ePluginUnregisterInstance: if (instance.create_callback) { ArchDefaultUnwindPlanInstances::iterator pos, end = g_plugin_instances.end(); for (pos = g_plugin_instances.begin(); pos != end; ++ pos) { if (pos->create_callback == instance.create_callback) { g_plugin_instances.erase(pos); return true; } } } break; case ePluginGetInstanceAtIndex: if (index < g_plugin_instances.size()) { instance = g_plugin_instances[index]; return true; } break; default: break; } return false; } bool PluginManager::RegisterPlugin ( const char *name, const char *description, ArchDefaultUnwindPlanCreateInstance create_callback ) { if (create_callback) { ArchDefaultUnwindPlanInstance instance; assert (name && name[0]); instance.name = name; if (description && description[0]) instance.description = description; instance.create_callback = create_callback; return AccessArchDefaultUnwindPlanInstances (ePluginRegisterInstance, instance, 0); } return false; } bool PluginManager::UnregisterPlugin (ArchDefaultUnwindPlanCreateInstance create_callback) { if (create_callback) { ArchDefaultUnwindPlanInstance instance; instance.create_callback = create_callback; return AccessArchDefaultUnwindPlanInstances (ePluginUnregisterInstance, instance, 0); } return false; } ArchDefaultUnwindPlanCreateInstance PluginManager::GetArchDefaultUnwindPlanCreateCallbackAtIndex (uint32_t idx) { ArchDefaultUnwindPlanInstance instance; if (AccessArchDefaultUnwindPlanInstances (ePluginGetInstanceAtIndex, instance, idx)) return instance.create_callback; return NULL; } ArchDefaultUnwindPlanCreateInstance PluginManager::GetArchDefaultUnwindPlanCreateCallbackForPluginName (const char *name) { if (name && name[0]) { ArchDefaultUnwindPlanInstance instance; std::string ss_name(name); for (uint32_t idx = 0; AccessArchDefaultUnwindPlanInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx) { if (instance.name == ss_name) return instance.create_callback; } } return NULL; } #pragma mark ArchVolatileRegs struct ArchVolatileRegsInstance { ArchVolatileRegsInstance() : name(), description(), create_callback(NULL) { } std::string name; std::string description; ArchVolatileRegsCreateInstance create_callback; }; typedef std::vector ArchVolatileRegsInstances; static bool AccessArchVolatileRegsInstances (PluginAction action, ArchVolatileRegsInstance &instance, uint32_t index) { static ArchVolatileRegsInstances g_plugin_instances; switch (action) { case ePluginRegisterInstance: if (instance.create_callback) { g_plugin_instances.push_back (instance); return true; } break; case ePluginUnregisterInstance: if (instance.create_callback) { ArchVolatileRegsInstances::iterator pos, end = g_plugin_instances.end(); for (pos = g_plugin_instances.begin(); pos != end; ++ pos) { if (pos->create_callback == instance.create_callback) { g_plugin_instances.erase(pos); return true; } } } break; case ePluginGetInstanceAtIndex: if (index < g_plugin_instances.size()) { instance = g_plugin_instances[index]; return true; } break; default: break; } return false; } bool PluginManager::RegisterPlugin ( const char *name, const char *description, ArchVolatileRegsCreateInstance create_callback ) { if (create_callback) { ArchVolatileRegsInstance instance; assert (name && name[0]); instance.name = name; if (description && description[0]) instance.description = description; instance.create_callback = create_callback; return AccessArchVolatileRegsInstances (ePluginRegisterInstance, instance, 0); } return false; } bool PluginManager::UnregisterPlugin (ArchVolatileRegsCreateInstance create_callback) { if (create_callback) { ArchVolatileRegsInstance instance; instance.create_callback = create_callback; return AccessArchVolatileRegsInstances (ePluginUnregisterInstance, instance, 0); } return false; } ArchVolatileRegsCreateInstance PluginManager::GetArchVolatileRegsCreateCallbackAtIndex (uint32_t idx) { ArchVolatileRegsInstance instance; if (AccessArchVolatileRegsInstances (ePluginGetInstanceAtIndex, instance, idx)) return instance.create_callback; return NULL; } ArchVolatileRegsCreateInstance PluginManager::GetArchVolatileRegsCreateCallbackForPluginName (const char *name) { if (name && name[0]) { ArchVolatileRegsInstance instance; std::string ss_name(name); for (uint32_t idx = 0; AccessArchVolatileRegsInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx) { if (instance.name == ss_name) return instance.create_callback; } } return NULL; }