//===-- 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" #include "llvm/ADT/StringRef.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.assign (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 ()); llvm::StringRef name_sref(name); ABIInstances &instances = GetABIInstances (); ABIInstances::iterator pos, end = instances.end(); for (pos = instances.begin(); pos != end; ++ pos) { if (name_sref.equals (pos->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 Mutex & GetDisassemblerMutex () { static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); return g_instances_mutex; } static DisassemblerInstances & GetDisassemblerInstances () { static DisassemblerInstances g_instances; return g_instances; } 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; Mutex::Locker locker (GetDisassemblerMutex ()); GetDisassemblerInstances ().push_back (instance); return true; } return false; } bool PluginManager::UnregisterPlugin (DisassemblerCreateInstance create_callback) { if (create_callback) { Mutex::Locker locker (GetDisassemblerMutex ()); DisassemblerInstances &instances = GetDisassemblerInstances (); DisassemblerInstances::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; } DisassemblerCreateInstance PluginManager::GetDisassemblerCreateCallbackAtIndex (uint32_t idx) { Mutex::Locker locker (GetDisassemblerMutex ()); DisassemblerInstances &instances = GetDisassemblerInstances (); if (idx < instances.size()) return instances[idx].create_callback; return NULL; } DisassemblerCreateInstance PluginManager::GetDisassemblerCreateCallbackForPluginName (const char *name) { if (name && name[0]) { llvm::StringRef name_sref(name); Mutex::Locker locker (GetDisassemblerMutex ()); DisassemblerInstances &instances = GetDisassemblerInstances (); DisassemblerInstances::iterator pos, end = instances.end(); for (pos = instances.begin(); pos != end; ++ pos) { if (name_sref.equals (pos->name)) return pos->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 Mutex & GetDynamicLoaderMutex () { static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); return g_instances_mutex; } static DynamicLoaderInstances & GetDynamicLoaderInstances () { static DynamicLoaderInstances g_instances; return g_instances; } 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; Mutex::Locker locker (GetDynamicLoaderMutex ()); GetDynamicLoaderInstances ().push_back (instance); } return false; } bool PluginManager::UnregisterPlugin (DynamicLoaderCreateInstance create_callback) { if (create_callback) { Mutex::Locker locker (GetDynamicLoaderMutex ()); DynamicLoaderInstances &instances = GetDynamicLoaderInstances (); DynamicLoaderInstances::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; } DynamicLoaderCreateInstance PluginManager::GetDynamicLoaderCreateCallbackAtIndex (uint32_t idx) { Mutex::Locker locker (GetDynamicLoaderMutex ()); DynamicLoaderInstances &instances = GetDynamicLoaderInstances (); if (idx < instances.size()) return instances[idx].create_callback; return NULL; } DynamicLoaderCreateInstance PluginManager::GetDynamicLoaderCreateCallbackForPluginName (const char *name) { if (name && name[0]) { llvm::StringRef name_sref(name); Mutex::Locker locker (GetDynamicLoaderMutex ()); DynamicLoaderInstances &instances = GetDynamicLoaderInstances (); DynamicLoaderInstances::iterator pos, end = instances.end(); for (pos = instances.begin(); pos != end; ++ pos) { if (name_sref.equals (pos->name)) return pos->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 Mutex & GetEmulateInstructionMutex () { static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); return g_instances_mutex; } static EmulateInstructionInstances & GetEmulateInstructionInstances () { static EmulateInstructionInstances g_instances; return g_instances; } 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; Mutex::Locker locker (GetEmulateInstructionMutex ()); GetEmulateInstructionInstances ().push_back (instance); } return false; } bool PluginManager::UnregisterPlugin (EmulateInstructionCreateInstance create_callback) { if (create_callback) { Mutex::Locker locker (GetEmulateInstructionMutex ()); EmulateInstructionInstances &instances = GetEmulateInstructionInstances (); EmulateInstructionInstances::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; } EmulateInstructionCreateInstance PluginManager::GetEmulateInstructionCreateCallbackAtIndex (uint32_t idx) { Mutex::Locker locker (GetEmulateInstructionMutex ()); EmulateInstructionInstances &instances = GetEmulateInstructionInstances (); if (idx < instances.size()) return instances[idx].create_callback; return NULL; } EmulateInstructionCreateInstance PluginManager::GetEmulateInstructionCreateCallbackForPluginName (const char *name) { if (name && name[0]) { llvm::StringRef name_sref(name); Mutex::Locker locker (GetEmulateInstructionMutex ()); EmulateInstructionInstances &instances = GetEmulateInstructionInstances (); EmulateInstructionInstances::iterator pos, end = instances.end(); for (pos = instances.begin(); pos != end; ++ pos) { if (name_sref.equals (pos->name)) return pos->create_callback; } } return NULL; } #pragma mark OperatingSystem struct OperatingSystemInstance { OperatingSystemInstance() : name(), description(), create_callback(NULL) { } std::string name; std::string description; OperatingSystemCreateInstance create_callback; }; typedef std::vector OperatingSystemInstances; static Mutex & GetOperatingSystemMutex () { static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); return g_instances_mutex; } static OperatingSystemInstances & GetOperatingSystemInstances () { static OperatingSystemInstances g_instances; return g_instances; } bool PluginManager::RegisterPlugin ( const char *name, const char *description, OperatingSystemCreateInstance create_callback ) { if (create_callback) { OperatingSystemInstance instance; assert (name && name[0]); instance.name = name; if (description && description[0]) instance.description = description; instance.create_callback = create_callback; Mutex::Locker locker (GetOperatingSystemMutex ()); GetOperatingSystemInstances ().push_back (instance); } return false; } bool PluginManager::UnregisterPlugin (OperatingSystemCreateInstance create_callback) { if (create_callback) { Mutex::Locker locker (GetOperatingSystemMutex ()); OperatingSystemInstances &instances = GetOperatingSystemInstances (); OperatingSystemInstances::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; } OperatingSystemCreateInstance PluginManager::GetOperatingSystemCreateCallbackAtIndex (uint32_t idx) { Mutex::Locker locker (GetOperatingSystemMutex ()); OperatingSystemInstances &instances = GetOperatingSystemInstances (); if (idx < instances.size()) return instances[idx].create_callback; return NULL; } OperatingSystemCreateInstance PluginManager::GetOperatingSystemCreateCallbackForPluginName (const char *name) { if (name && name[0]) { llvm::StringRef name_sref(name); Mutex::Locker locker (GetOperatingSystemMutex ()); OperatingSystemInstances &instances = GetOperatingSystemInstances (); OperatingSystemInstances::iterator pos, end = instances.end(); for (pos = instances.begin(); pos != end; ++ pos) { if (name_sref.equals (pos->name)) return pos->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 Mutex & GetLanguageRuntimeMutex () { static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); return g_instances_mutex; } static LanguageRuntimeInstances & GetLanguageRuntimeInstances () { static LanguageRuntimeInstances g_instances; return g_instances; } 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; Mutex::Locker locker (GetLanguageRuntimeMutex ()); GetLanguageRuntimeInstances ().push_back (instance); } return false; } bool PluginManager::UnregisterPlugin (LanguageRuntimeCreateInstance create_callback) { if (create_callback) { Mutex::Locker locker (GetLanguageRuntimeMutex ()); LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances (); LanguageRuntimeInstances::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; } LanguageRuntimeCreateInstance PluginManager::GetLanguageRuntimeCreateCallbackAtIndex (uint32_t idx) { Mutex::Locker locker (GetLanguageRuntimeMutex ()); LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances (); if (idx < instances.size()) return instances[idx].create_callback; return NULL; } LanguageRuntimeCreateInstance PluginManager::GetLanguageRuntimeCreateCallbackForPluginName (const char *name) { if (name && name[0]) { llvm::StringRef name_sref(name); Mutex::Locker locker (GetLanguageRuntimeMutex ()); LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances (); LanguageRuntimeInstances::iterator pos, end = instances.end(); for (pos = instances.begin(); pos != end; ++ pos) { if (name_sref.equals (pos->name)) return pos->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 Mutex & GetObjectFileMutex () { static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); return g_instances_mutex; } static ObjectFileInstances & GetObjectFileInstances () { static ObjectFileInstances g_instances; return g_instances; } 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; Mutex::Locker locker (GetObjectFileMutex ()); GetObjectFileInstances ().push_back (instance); } return false; } bool PluginManager::UnregisterPlugin (ObjectFileCreateInstance create_callback) { if (create_callback) { Mutex::Locker locker (GetObjectFileMutex ()); ObjectFileInstances &instances = GetObjectFileInstances (); ObjectFileInstances::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; } ObjectFileCreateInstance PluginManager::GetObjectFileCreateCallbackAtIndex (uint32_t idx) { Mutex::Locker locker (GetObjectFileMutex ()); ObjectFileInstances &instances = GetObjectFileInstances (); if (idx < instances.size()) return instances[idx].create_callback; return NULL; } ObjectFileCreateInstance PluginManager::GetObjectFileCreateCallbackForPluginName (const char *name) { if (name && name[0]) { llvm::StringRef name_sref(name); Mutex::Locker locker (GetObjectFileMutex ()); ObjectFileInstances &instances = GetObjectFileInstances (); ObjectFileInstances::iterator pos, end = instances.end(); for (pos = instances.begin(); pos != end; ++ pos) { if (name_sref.equals (pos->name)) return pos->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 Mutex & GetObjectContainerMutex () { static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); return g_instances_mutex; } static ObjectContainerInstances & GetObjectContainerInstances () { static ObjectContainerInstances g_instances; return g_instances; } 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; Mutex::Locker locker (GetObjectContainerMutex ()); GetObjectContainerInstances ().push_back (instance); } return false; } bool PluginManager::UnregisterPlugin (ObjectContainerCreateInstance create_callback) { if (create_callback) { Mutex::Locker locker (GetObjectContainerMutex ()); ObjectContainerInstances &instances = GetObjectContainerInstances (); ObjectContainerInstances::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; } ObjectContainerCreateInstance PluginManager::GetObjectContainerCreateCallbackAtIndex (uint32_t idx) { Mutex::Locker locker (GetObjectContainerMutex ()); ObjectContainerInstances &instances = GetObjectContainerInstances (); if (idx < instances.size()) return instances[idx].create_callback; return NULL; } ObjectContainerCreateInstance PluginManager::GetObjectContainerCreateCallbackForPluginName (const char *name) { if (name && name[0]) { llvm::StringRef name_sref(name); Mutex::Locker locker (GetObjectContainerMutex ()); ObjectContainerInstances &instances = GetObjectContainerInstances (); ObjectContainerInstances::iterator pos, end = instances.end(); for (pos = instances.begin(); pos != end; ++ pos) { if (name_sref.equals (pos->name)) return pos->create_callback; } } return NULL; } #pragma mark LogChannel struct LogInstance { LogInstance() : name(), description(), create_callback(NULL) { } std::string name; std::string description; LogChannelCreateInstance create_callback; }; typedef std::vector LogInstances; static Mutex & GetLogMutex () { static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); return g_instances_mutex; } static LogInstances & GetLogInstances () { static LogInstances g_instances; return g_instances; } bool PluginManager::RegisterPlugin ( const char *name, const char *description, LogChannelCreateInstance create_callback ) { if (create_callback) { LogInstance instance; assert (name && name[0]); instance.name = name; if (description && description[0]) instance.description = description; instance.create_callback = create_callback; Mutex::Locker locker (GetLogMutex ()); GetLogInstances ().push_back (instance); } return false; } bool PluginManager::UnregisterPlugin (LogChannelCreateInstance create_callback) { if (create_callback) { Mutex::Locker locker (GetLogMutex ()); LogInstances &instances = GetLogInstances (); LogInstances::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; } const char * PluginManager::GetLogChannelCreateNameAtIndex (uint32_t idx) { Mutex::Locker locker (GetLogMutex ()); LogInstances &instances = GetLogInstances (); if (idx < instances.size()) return instances[idx].name.c_str(); return NULL; } LogChannelCreateInstance PluginManager::GetLogChannelCreateCallbackAtIndex (uint32_t idx) { Mutex::Locker locker (GetLogMutex ()); LogInstances &instances = GetLogInstances (); if (idx < instances.size()) return instances[idx].create_callback; return NULL; } LogChannelCreateInstance PluginManager::GetLogChannelCreateCallbackForPluginName (const char *name) { if (name && name[0]) { llvm::StringRef name_sref(name); Mutex::Locker locker (GetLogMutex ()); LogInstances &instances = GetLogInstances (); LogInstances::iterator pos, end = instances.end(); for (pos = instances.begin(); pos != end; ++ pos) { if (name_sref.equals (pos->name)) return pos->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 &instances = GetPlatformInstances (); if (idx < instances.size()) return instances[idx].name.c_str(); return NULL; } const char * PluginManager::GetPlatformPluginDescriptionAtIndex (uint32_t idx) { Mutex::Locker locker (GetPlatformInstancesMutex ()); PlatformInstances &instances = GetPlatformInstances (); if (idx < instances.size()) return instances[idx].description.c_str(); return NULL; } bool PluginManager::UnregisterPlugin (PlatformCreateInstance create_callback) { if (create_callback) { Mutex::Locker locker (GetPlatformInstancesMutex ()); PlatformInstances &instances = GetPlatformInstances (); PlatformInstances::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; } PlatformCreateInstance PluginManager::GetPlatformCreateCallbackAtIndex (uint32_t idx) { Mutex::Locker locker (GetPlatformInstancesMutex ()); PlatformInstances &instances = GetPlatformInstances (); if (idx < instances.size()) return instances[idx].create_callback; return NULL; } PlatformCreateInstance PluginManager::GetPlatformCreateCallbackForPluginName (const char *name) { if (name && name[0]) { Mutex::Locker locker (GetPlatformInstancesMutex ()); PlatformInstances &instances = GetPlatformInstances (); llvm::StringRef name_sref(name); PlatformInstances::iterator pos, end = instances.end(); for (pos = instances.begin(); pos != end; ++ pos) { if (name_sref.equals (pos->name)) return pos->create_callback; } } return NULL; } uint32_t PluginManager::AutoCompletePlatformName (const char *name, StringList &matches) { if (name && name[0]) { Mutex::Locker locker (GetPlatformInstancesMutex ()); PlatformInstances &instances = GetPlatformInstances (); llvm::StringRef name_sref(name); PlatformInstances::iterator pos, end = instances.end(); for (pos = instances.begin(); pos != end; ++ pos) { llvm::StringRef plugin_name (pos->name); if (plugin_name.startswith(name_sref)) matches.AppendString (plugin_name.data()); } } return matches.GetSize(); } #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 Mutex & GetProcessMutex () { static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); return g_instances_mutex; } static ProcessInstances & GetProcessInstances () { static ProcessInstances g_instances; return g_instances; } 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; Mutex::Locker locker (GetProcessMutex ()); GetProcessInstances ().push_back (instance); } return false; } const char * PluginManager::GetProcessPluginNameAtIndex (uint32_t idx) { Mutex::Locker locker (GetProcessMutex ()); ProcessInstances &instances = GetProcessInstances (); if (idx < instances.size()) return instances[idx].name.c_str(); return NULL; } const char * PluginManager::GetProcessPluginDescriptionAtIndex (uint32_t idx) { Mutex::Locker locker (GetProcessMutex ()); ProcessInstances &instances = GetProcessInstances (); if (idx < instances.size()) return instances[idx].description.c_str(); return NULL; } bool PluginManager::UnregisterPlugin (ProcessCreateInstance create_callback) { if (create_callback) { Mutex::Locker locker (GetProcessMutex ()); ProcessInstances &instances = GetProcessInstances (); ProcessInstances::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; } ProcessCreateInstance PluginManager::GetProcessCreateCallbackAtIndex (uint32_t idx) { Mutex::Locker locker (GetProcessMutex ()); ProcessInstances &instances = GetProcessInstances (); if (idx < instances.size()) return instances[idx].create_callback; return NULL; } ProcessCreateInstance PluginManager::GetProcessCreateCallbackForPluginName (const char *name) { if (name && name[0]) { llvm::StringRef name_sref(name); Mutex::Locker locker (GetProcessMutex ()); ProcessInstances &instances = GetProcessInstances (); ProcessInstances::iterator pos, end = instances.end(); for (pos = instances.begin(); pos != end; ++ pos) { if (name_sref.equals (pos->name)) return pos->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 Mutex & GetSymbolFileMutex () { static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); return g_instances_mutex; } static SymbolFileInstances & GetSymbolFileInstances () { static SymbolFileInstances g_instances; return g_instances; } 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; Mutex::Locker locker (GetSymbolFileMutex ()); GetSymbolFileInstances ().push_back (instance); } return false; } bool PluginManager::UnregisterPlugin (SymbolFileCreateInstance create_callback) { if (create_callback) { Mutex::Locker locker (GetSymbolFileMutex ()); SymbolFileInstances &instances = GetSymbolFileInstances (); SymbolFileInstances::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; } SymbolFileCreateInstance PluginManager::GetSymbolFileCreateCallbackAtIndex (uint32_t idx) { Mutex::Locker locker (GetSymbolFileMutex ()); SymbolFileInstances &instances = GetSymbolFileInstances (); if (idx < instances.size()) return instances[idx].create_callback; return NULL; } SymbolFileCreateInstance PluginManager::GetSymbolFileCreateCallbackForPluginName (const char *name) { if (name && name[0]) { llvm::StringRef name_sref(name); Mutex::Locker locker (GetSymbolFileMutex ()); SymbolFileInstances &instances = GetSymbolFileInstances (); SymbolFileInstances::iterator pos, end = instances.end(); for (pos = instances.begin(); pos != end; ++ pos) { if (name_sref.equals (pos->name)) return pos->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 Mutex & GetSymbolVendorMutex () { static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); return g_instances_mutex; } static SymbolVendorInstances & GetSymbolVendorInstances () { static SymbolVendorInstances g_instances; return g_instances; } 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; Mutex::Locker locker (GetSymbolVendorMutex ()); GetSymbolVendorInstances ().push_back (instance); } return false; } bool PluginManager::UnregisterPlugin (SymbolVendorCreateInstance create_callback) { if (create_callback) { Mutex::Locker locker (GetSymbolVendorMutex ()); SymbolVendorInstances &instances = GetSymbolVendorInstances (); SymbolVendorInstances::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; } SymbolVendorCreateInstance PluginManager::GetSymbolVendorCreateCallbackAtIndex (uint32_t idx) { Mutex::Locker locker (GetSymbolVendorMutex ()); SymbolVendorInstances &instances = GetSymbolVendorInstances (); if (idx < instances.size()) return instances[idx].create_callback; return NULL; } SymbolVendorCreateInstance PluginManager::GetSymbolVendorCreateCallbackForPluginName (const char *name) { if (name && name[0]) { llvm::StringRef name_sref(name); Mutex::Locker locker (GetSymbolVendorMutex ()); SymbolVendorInstances &instances = GetSymbolVendorInstances (); SymbolVendorInstances::iterator pos, end = instances.end(); for (pos = instances.begin(); pos != end; ++ pos) { if (name_sref.equals (pos->name)) return pos->create_callback; } } return NULL; } #pragma mark UnwindAssembly struct UnwindAssemblyInstance { UnwindAssemblyInstance() : name(), description(), create_callback(NULL) { } std::string name; std::string description; UnwindAssemblyCreateInstance create_callback; }; typedef std::vector UnwindAssemblyInstances; static Mutex & GetUnwindAssemblyMutex () { static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); return g_instances_mutex; } static UnwindAssemblyInstances & GetUnwindAssemblyInstances () { static UnwindAssemblyInstances g_instances; return g_instances; } bool PluginManager::RegisterPlugin ( const char *name, const char *description, UnwindAssemblyCreateInstance create_callback ) { if (create_callback) { UnwindAssemblyInstance instance; assert (name && name[0]); instance.name = name; if (description && description[0]) instance.description = description; instance.create_callback = create_callback; Mutex::Locker locker (GetUnwindAssemblyMutex ()); GetUnwindAssemblyInstances ().push_back (instance); } return false; } bool PluginManager::UnregisterPlugin (UnwindAssemblyCreateInstance create_callback) { if (create_callback) { Mutex::Locker locker (GetUnwindAssemblyMutex ()); UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances (); UnwindAssemblyInstances::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; } UnwindAssemblyCreateInstance PluginManager::GetUnwindAssemblyCreateCallbackAtIndex (uint32_t idx) { Mutex::Locker locker (GetUnwindAssemblyMutex ()); UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances (); if (idx < instances.size()) return instances[idx].create_callback; return NULL; } UnwindAssemblyCreateInstance PluginManager::GetUnwindAssemblyCreateCallbackForPluginName (const char *name) { if (name && name[0]) { llvm::StringRef name_sref(name); Mutex::Locker locker (GetUnwindAssemblyMutex ()); UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances (); UnwindAssemblyInstances::iterator pos, end = instances.end(); for (pos = instances.begin(); pos != end; ++ pos) { if (name_sref.equals (pos->name)) return pos->create_callback; } } return NULL; }