llvm-project/lldb/source/Core/PluginManager.cpp

2551 lines
83 KiB
C++
Raw Normal View History

//===-- 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"
// C Includes
// C++ Includes
#include <climits>
#include <mutex>
#include <string>
#include <vector>
// Other libraries and framework includes
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DynamicLibrary.h"
// Project includes
#include "lldb/Core/Debugger.h"
Modified the PluginManager to be ready for loading plug-ins from a system LLDB plugin directory and a user LLDB plugin directory. We currently still need to work out at what layer the plug-ins will be, but at least we are prepared for plug-ins. Plug-ins will attempt to be loaded from the "/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Plugins" folder, and from the "~/Library/Application Support/LLDB/Plugins" folder on MacOSX. Each plugin will be scanned for: extern "C" bool LLDBPluginInitialize(void); extern "C" void LLDBPluginTerminate(void); If at least LLDBPluginInitialize is found, the plug-in will be loaded. The LLDBPluginInitialize function returns a bool that indicates if the plug-in should stay loaded or not (plug-ins might check the current OS, current hardware, or anything else and determine they don't want to run on the current host). The plug-in is uniqued by path and added to a static loaded plug-in map. The plug-in scanning happens during "lldb_private::Initialize()" which calls to the PluginManager::Initialize() function. Likewise with termination lldb_private::Terminate() calls PluginManager::Terminate(). The paths for the plug-in directories is fetched through new Host calls: bool Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec); bool Host::GetLLDBPath (ePathTypeLLDBUserPlugins, dir_spec); This way linux and other systems can define their own appropriate locations for plug-ins to be loaded. To allow dynamic shared library loading, the Host layer has also been modified to include shared library open, close and get symbol: static void * Host::DynamicLibraryOpen (const FileSpec &file_spec, Error &error); static Error Host::DynamicLibraryClose (void *dynamic_library_handle); static void * Host::DynamicLibraryGetSymbol (void *dynamic_library_handle, const char *symbol_name, Error &error); lldb_private::FileSpec also has been modified to support directory enumeration in an attempt to abstract the directory enumeration into one spot in the code. The directory enumertion function is static and takes a callback: typedef enum EnumerateDirectoryResult { eEnumerateDirectoryResultNext, // Enumerate next entry in the current directory eEnumerateDirectoryResultEnter, // Recurse into the current entry if it is a directory or symlink, or next if not eEnumerateDirectoryResultExit, // Exit from the current directory at the current level. eEnumerateDirectoryResultQuit // Stop directory enumerations at any level }; typedef FileSpec::EnumerateDirectoryResult (*EnumerateDirectoryCallbackType) (void *baton, FileSpec::FileType file_type, const FileSpec &spec); static FileSpec::EnumerateDirectoryResult FileSpec::EnumerateDirectory (const char *dir_path, bool find_directories, bool find_files, bool find_other, EnumerateDirectoryCallbackType callback, void *callback_baton); This allow clients to specify the directory to search, and specifies if only files, directories or other (pipe, symlink, fifo, etc) files will cause the callback to be called. The callback also gets to return with the action that should be performed after this directory entry. eEnumerateDirectoryResultNext specifies to continue enumerating through a directory with the next entry. eEnumerateDirectoryResultEnter specifies to recurse down into a directory entry, or if the file is not a directory or symlink/alias to a directory, then just iterate to the next entry. eEnumerateDirectoryResultExit specifies to exit the current directory and skip any entries that might be remaining, yet continue enumerating to the next entry in the parent directory. And finally eEnumerateDirectoryResultQuit means to abort all directory enumerations at all levels. Modified the Declaration class to not include column information currently since we don't have any compilers that currently support column based declaration information. Columns support can be re-enabled with the additions of a #define. Added the ability to find an EmulateInstruction plug-in given a target triple and optional plug-in name in the plug-in manager. Fixed a few cases where opendir/readdir was being used, but yet not closedir was being used. Soon these will be deprecated in favor of the new directory enumeration call that was added to the FileSpec class. llvm-svn: 124716
2011-02-02 10:24:04 +08:00
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Utility/Error.h"
#include "lldb/Utility/FileSpec.h"
Modified the PluginManager to be ready for loading plug-ins from a system LLDB plugin directory and a user LLDB plugin directory. We currently still need to work out at what layer the plug-ins will be, but at least we are prepared for plug-ins. Plug-ins will attempt to be loaded from the "/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Plugins" folder, and from the "~/Library/Application Support/LLDB/Plugins" folder on MacOSX. Each plugin will be scanned for: extern "C" bool LLDBPluginInitialize(void); extern "C" void LLDBPluginTerminate(void); If at least LLDBPluginInitialize is found, the plug-in will be loaded. The LLDBPluginInitialize function returns a bool that indicates if the plug-in should stay loaded or not (plug-ins might check the current OS, current hardware, or anything else and determine they don't want to run on the current host). The plug-in is uniqued by path and added to a static loaded plug-in map. The plug-in scanning happens during "lldb_private::Initialize()" which calls to the PluginManager::Initialize() function. Likewise with termination lldb_private::Terminate() calls PluginManager::Terminate(). The paths for the plug-in directories is fetched through new Host calls: bool Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec); bool Host::GetLLDBPath (ePathTypeLLDBUserPlugins, dir_spec); This way linux and other systems can define their own appropriate locations for plug-ins to be loaded. To allow dynamic shared library loading, the Host layer has also been modified to include shared library open, close and get symbol: static void * Host::DynamicLibraryOpen (const FileSpec &file_spec, Error &error); static Error Host::DynamicLibraryClose (void *dynamic_library_handle); static void * Host::DynamicLibraryGetSymbol (void *dynamic_library_handle, const char *symbol_name, Error &error); lldb_private::FileSpec also has been modified to support directory enumeration in an attempt to abstract the directory enumeration into one spot in the code. The directory enumertion function is static and takes a callback: typedef enum EnumerateDirectoryResult { eEnumerateDirectoryResultNext, // Enumerate next entry in the current directory eEnumerateDirectoryResultEnter, // Recurse into the current entry if it is a directory or symlink, or next if not eEnumerateDirectoryResultExit, // Exit from the current directory at the current level. eEnumerateDirectoryResultQuit // Stop directory enumerations at any level }; typedef FileSpec::EnumerateDirectoryResult (*EnumerateDirectoryCallbackType) (void *baton, FileSpec::FileType file_type, const FileSpec &spec); static FileSpec::EnumerateDirectoryResult FileSpec::EnumerateDirectory (const char *dir_path, bool find_directories, bool find_files, bool find_other, EnumerateDirectoryCallbackType callback, void *callback_baton); This allow clients to specify the directory to search, and specifies if only files, directories or other (pipe, symlink, fifo, etc) files will cause the callback to be called. The callback also gets to return with the action that should be performed after this directory entry. eEnumerateDirectoryResultNext specifies to continue enumerating through a directory with the next entry. eEnumerateDirectoryResultEnter specifies to recurse down into a directory entry, or if the file is not a directory or symlink/alias to a directory, then just iterate to the next entry. eEnumerateDirectoryResultExit specifies to exit the current directory and skip any entries that might be remaining, yet continue enumerating to the next entry in the parent directory. And finally eEnumerateDirectoryResultQuit means to abort all directory enumerations at all levels. Modified the Declaration class to not include column information currently since we don't have any compilers that currently support column based declaration information. Columns support can be re-enabled with the additions of a #define. Added the ability to find an EmulateInstruction plug-in given a target triple and optional plug-in name in the plug-in manager. Fixed a few cases where opendir/readdir was being used, but yet not closedir was being used. Soon these will be deprecated in favor of the new directory enumeration call that was added to the FileSpec class. llvm-svn: 124716
2011-02-02 10:24:04 +08:00
using namespace lldb;
using namespace lldb_private;
enum PluginAction {
ePluginRegisterInstance,
ePluginUnregisterInstance,
ePluginGetInstanceAtIndex
};
typedef bool (*PluginInitCallback)();
typedef void (*PluginTermCallback)();
struct PluginInfo {
PluginInfo() : plugin_init_callback(nullptr), plugin_term_callback(nullptr) {}
llvm::sys::DynamicLibrary library;
PluginInitCallback plugin_init_callback;
PluginTermCallback plugin_term_callback;
Modified the PluginManager to be ready for loading plug-ins from a system LLDB plugin directory and a user LLDB plugin directory. We currently still need to work out at what layer the plug-ins will be, but at least we are prepared for plug-ins. Plug-ins will attempt to be loaded from the "/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Plugins" folder, and from the "~/Library/Application Support/LLDB/Plugins" folder on MacOSX. Each plugin will be scanned for: extern "C" bool LLDBPluginInitialize(void); extern "C" void LLDBPluginTerminate(void); If at least LLDBPluginInitialize is found, the plug-in will be loaded. The LLDBPluginInitialize function returns a bool that indicates if the plug-in should stay loaded or not (plug-ins might check the current OS, current hardware, or anything else and determine they don't want to run on the current host). The plug-in is uniqued by path and added to a static loaded plug-in map. The plug-in scanning happens during "lldb_private::Initialize()" which calls to the PluginManager::Initialize() function. Likewise with termination lldb_private::Terminate() calls PluginManager::Terminate(). The paths for the plug-in directories is fetched through new Host calls: bool Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec); bool Host::GetLLDBPath (ePathTypeLLDBUserPlugins, dir_spec); This way linux and other systems can define their own appropriate locations for plug-ins to be loaded. To allow dynamic shared library loading, the Host layer has also been modified to include shared library open, close and get symbol: static void * Host::DynamicLibraryOpen (const FileSpec &file_spec, Error &error); static Error Host::DynamicLibraryClose (void *dynamic_library_handle); static void * Host::DynamicLibraryGetSymbol (void *dynamic_library_handle, const char *symbol_name, Error &error); lldb_private::FileSpec also has been modified to support directory enumeration in an attempt to abstract the directory enumeration into one spot in the code. The directory enumertion function is static and takes a callback: typedef enum EnumerateDirectoryResult { eEnumerateDirectoryResultNext, // Enumerate next entry in the current directory eEnumerateDirectoryResultEnter, // Recurse into the current entry if it is a directory or symlink, or next if not eEnumerateDirectoryResultExit, // Exit from the current directory at the current level. eEnumerateDirectoryResultQuit // Stop directory enumerations at any level }; typedef FileSpec::EnumerateDirectoryResult (*EnumerateDirectoryCallbackType) (void *baton, FileSpec::FileType file_type, const FileSpec &spec); static FileSpec::EnumerateDirectoryResult FileSpec::EnumerateDirectory (const char *dir_path, bool find_directories, bool find_files, bool find_other, EnumerateDirectoryCallbackType callback, void *callback_baton); This allow clients to specify the directory to search, and specifies if only files, directories or other (pipe, symlink, fifo, etc) files will cause the callback to be called. The callback also gets to return with the action that should be performed after this directory entry. eEnumerateDirectoryResultNext specifies to continue enumerating through a directory with the next entry. eEnumerateDirectoryResultEnter specifies to recurse down into a directory entry, or if the file is not a directory or symlink/alias to a directory, then just iterate to the next entry. eEnumerateDirectoryResultExit specifies to exit the current directory and skip any entries that might be remaining, yet continue enumerating to the next entry in the parent directory. And finally eEnumerateDirectoryResultQuit means to abort all directory enumerations at all levels. Modified the Declaration class to not include column information currently since we don't have any compilers that currently support column based declaration information. Columns support can be re-enabled with the additions of a #define. Added the ability to find an EmulateInstruction plug-in given a target triple and optional plug-in name in the plug-in manager. Fixed a few cases where opendir/readdir was being used, but yet not closedir was being used. Soon these will be deprecated in favor of the new directory enumeration call that was added to the FileSpec class. llvm-svn: 124716
2011-02-02 10:24:04 +08:00
};
typedef std::map<FileSpec, PluginInfo> PluginTerminateMap;
static std::recursive_mutex &GetPluginMapMutex() {
static std::recursive_mutex g_plugin_map_mutex;
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) {
std::lock_guard<std::recursive_mutex> guard(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) {
std::lock_guard<std::recursive_mutex> guard(GetPluginMapMutex());
PluginTerminateMap &plugin_map = GetPluginMap();
assert(plugin_map.find(plugin_file_spec) == plugin_map.end());
plugin_map[plugin_file_spec] = plugin_info;
}
template <typename FPtrTy> static FPtrTy CastToFPtr(void *VPtr) {
return reinterpret_cast<FPtrTy>(reinterpret_cast<intptr_t>(VPtr));
}
static FileSpec::EnumerateDirectoryResult
LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
const FileSpec &file_spec) {
// PluginManager *plugin_manager = (PluginManager *)baton;
Error error;
namespace fs = llvm::sys::fs;
// 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 (ft == fs::file_type::regular_file || ft == fs::file_type::symlink_file ||
ft == fs::file_type::type_unknown) {
FileSpec plugin_file_spec(file_spec);
plugin_file_spec.ResolvePath();
if (PluginIsLoaded(plugin_file_spec))
return FileSpec::eEnumerateDirectoryResultNext;
else {
PluginInfo plugin_info;
std::string pluginLoadError;
plugin_info.library = llvm::sys::DynamicLibrary::getPermanentLibrary(
plugin_file_spec.GetPath().c_str(), &pluginLoadError);
if (plugin_info.library.isValid()) {
bool success = false;
plugin_info.plugin_init_callback = CastToFPtr<PluginInitCallback>(
plugin_info.library.getAddressOfSymbol("LLDBPluginInitialize"));
if (plugin_info.plugin_init_callback) {
// Call the plug-in "bool LLDBPluginInitialize(void)" function
success = plugin_info.plugin_init_callback();
}
if (success) {
// It is ok for the "LLDBPluginTerminate" symbol to be nullptr
plugin_info.plugin_term_callback = CastToFPtr<PluginTermCallback>(
plugin_info.library.getAddressOfSymbol("LLDBPluginTerminate"));
} 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. Set it to a default-constructed instance to invalidate
// it.
plugin_info = PluginInfo();
}
// 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 (ft == fs::file_type::directory_file ||
ft == fs::file_type::symlink_file || ft == fs::file_type::type_unknown) {
// 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 enumerating 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 (HostInfo::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, nullptr);
}
}
if (HostInfo::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, nullptr);
}
}
#endif
Modified the PluginManager to be ready for loading plug-ins from a system LLDB plugin directory and a user LLDB plugin directory. We currently still need to work out at what layer the plug-ins will be, but at least we are prepared for plug-ins. Plug-ins will attempt to be loaded from the "/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Plugins" folder, and from the "~/Library/Application Support/LLDB/Plugins" folder on MacOSX. Each plugin will be scanned for: extern "C" bool LLDBPluginInitialize(void); extern "C" void LLDBPluginTerminate(void); If at least LLDBPluginInitialize is found, the plug-in will be loaded. The LLDBPluginInitialize function returns a bool that indicates if the plug-in should stay loaded or not (plug-ins might check the current OS, current hardware, or anything else and determine they don't want to run on the current host). The plug-in is uniqued by path and added to a static loaded plug-in map. The plug-in scanning happens during "lldb_private::Initialize()" which calls to the PluginManager::Initialize() function. Likewise with termination lldb_private::Terminate() calls PluginManager::Terminate(). The paths for the plug-in directories is fetched through new Host calls: bool Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec); bool Host::GetLLDBPath (ePathTypeLLDBUserPlugins, dir_spec); This way linux and other systems can define their own appropriate locations for plug-ins to be loaded. To allow dynamic shared library loading, the Host layer has also been modified to include shared library open, close and get symbol: static void * Host::DynamicLibraryOpen (const FileSpec &file_spec, Error &error); static Error Host::DynamicLibraryClose (void *dynamic_library_handle); static void * Host::DynamicLibraryGetSymbol (void *dynamic_library_handle, const char *symbol_name, Error &error); lldb_private::FileSpec also has been modified to support directory enumeration in an attempt to abstract the directory enumeration into one spot in the code. The directory enumertion function is static and takes a callback: typedef enum EnumerateDirectoryResult { eEnumerateDirectoryResultNext, // Enumerate next entry in the current directory eEnumerateDirectoryResultEnter, // Recurse into the current entry if it is a directory or symlink, or next if not eEnumerateDirectoryResultExit, // Exit from the current directory at the current level. eEnumerateDirectoryResultQuit // Stop directory enumerations at any level }; typedef FileSpec::EnumerateDirectoryResult (*EnumerateDirectoryCallbackType) (void *baton, FileSpec::FileType file_type, const FileSpec &spec); static FileSpec::EnumerateDirectoryResult FileSpec::EnumerateDirectory (const char *dir_path, bool find_directories, bool find_files, bool find_other, EnumerateDirectoryCallbackType callback, void *callback_baton); This allow clients to specify the directory to search, and specifies if only files, directories or other (pipe, symlink, fifo, etc) files will cause the callback to be called. The callback also gets to return with the action that should be performed after this directory entry. eEnumerateDirectoryResultNext specifies to continue enumerating through a directory with the next entry. eEnumerateDirectoryResultEnter specifies to recurse down into a directory entry, or if the file is not a directory or symlink/alias to a directory, then just iterate to the next entry. eEnumerateDirectoryResultExit specifies to exit the current directory and skip any entries that might be remaining, yet continue enumerating to the next entry in the parent directory. And finally eEnumerateDirectoryResultQuit means to abort all directory enumerations at all levels. Modified the Declaration class to not include column information currently since we don't have any compilers that currently support column based declaration information. Columns support can be re-enabled with the additions of a #define. Added the ability to find an EmulateInstruction plug-in given a target triple and optional plug-in name in the plug-in manager. Fixed a few cases where opendir/readdir was being used, but yet not closedir was being used. Soon these will be deprecated in favor of the new directory enumeration call that was added to the FileSpec class. llvm-svn: 124716
2011-02-02 10:24:04 +08:00
}
void PluginManager::Terminate() {
std::lock_guard<std::recursive_mutex> guard(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 nullptr).
if (pos->second.library.isValid()) {
if (pos->second.plugin_term_callback)
pos->second.plugin_term_callback();
Modified the PluginManager to be ready for loading plug-ins from a system LLDB plugin directory and a user LLDB plugin directory. We currently still need to work out at what layer the plug-ins will be, but at least we are prepared for plug-ins. Plug-ins will attempt to be loaded from the "/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Plugins" folder, and from the "~/Library/Application Support/LLDB/Plugins" folder on MacOSX. Each plugin will be scanned for: extern "C" bool LLDBPluginInitialize(void); extern "C" void LLDBPluginTerminate(void); If at least LLDBPluginInitialize is found, the plug-in will be loaded. The LLDBPluginInitialize function returns a bool that indicates if the plug-in should stay loaded or not (plug-ins might check the current OS, current hardware, or anything else and determine they don't want to run on the current host). The plug-in is uniqued by path and added to a static loaded plug-in map. The plug-in scanning happens during "lldb_private::Initialize()" which calls to the PluginManager::Initialize() function. Likewise with termination lldb_private::Terminate() calls PluginManager::Terminate(). The paths for the plug-in directories is fetched through new Host calls: bool Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec); bool Host::GetLLDBPath (ePathTypeLLDBUserPlugins, dir_spec); This way linux and other systems can define their own appropriate locations for plug-ins to be loaded. To allow dynamic shared library loading, the Host layer has also been modified to include shared library open, close and get symbol: static void * Host::DynamicLibraryOpen (const FileSpec &file_spec, Error &error); static Error Host::DynamicLibraryClose (void *dynamic_library_handle); static void * Host::DynamicLibraryGetSymbol (void *dynamic_library_handle, const char *symbol_name, Error &error); lldb_private::FileSpec also has been modified to support directory enumeration in an attempt to abstract the directory enumeration into one spot in the code. The directory enumertion function is static and takes a callback: typedef enum EnumerateDirectoryResult { eEnumerateDirectoryResultNext, // Enumerate next entry in the current directory eEnumerateDirectoryResultEnter, // Recurse into the current entry if it is a directory or symlink, or next if not eEnumerateDirectoryResultExit, // Exit from the current directory at the current level. eEnumerateDirectoryResultQuit // Stop directory enumerations at any level }; typedef FileSpec::EnumerateDirectoryResult (*EnumerateDirectoryCallbackType) (void *baton, FileSpec::FileType file_type, const FileSpec &spec); static FileSpec::EnumerateDirectoryResult FileSpec::EnumerateDirectory (const char *dir_path, bool find_directories, bool find_files, bool find_other, EnumerateDirectoryCallbackType callback, void *callback_baton); This allow clients to specify the directory to search, and specifies if only files, directories or other (pipe, symlink, fifo, etc) files will cause the callback to be called. The callback also gets to return with the action that should be performed after this directory entry. eEnumerateDirectoryResultNext specifies to continue enumerating through a directory with the next entry. eEnumerateDirectoryResultEnter specifies to recurse down into a directory entry, or if the file is not a directory or symlink/alias to a directory, then just iterate to the next entry. eEnumerateDirectoryResultExit specifies to exit the current directory and skip any entries that might be remaining, yet continue enumerating to the next entry in the parent directory. And finally eEnumerateDirectoryResultQuit means to abort all directory enumerations at all levels. Modified the Declaration class to not include column information currently since we don't have any compilers that currently support column based declaration information. Columns support can be re-enabled with the additions of a #define. Added the ability to find an EmulateInstruction plug-in given a target triple and optional plug-in name in the plug-in manager. Fixed a few cases where opendir/readdir was being used, but yet not closedir was being used. Soon these will be deprecated in favor of the new directory enumeration call that was added to the FileSpec class. llvm-svn: 124716
2011-02-02 10:24:04 +08:00
}
}
plugin_map.clear();
Modified the PluginManager to be ready for loading plug-ins from a system LLDB plugin directory and a user LLDB plugin directory. We currently still need to work out at what layer the plug-ins will be, but at least we are prepared for plug-ins. Plug-ins will attempt to be loaded from the "/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Plugins" folder, and from the "~/Library/Application Support/LLDB/Plugins" folder on MacOSX. Each plugin will be scanned for: extern "C" bool LLDBPluginInitialize(void); extern "C" void LLDBPluginTerminate(void); If at least LLDBPluginInitialize is found, the plug-in will be loaded. The LLDBPluginInitialize function returns a bool that indicates if the plug-in should stay loaded or not (plug-ins might check the current OS, current hardware, or anything else and determine they don't want to run on the current host). The plug-in is uniqued by path and added to a static loaded plug-in map. The plug-in scanning happens during "lldb_private::Initialize()" which calls to the PluginManager::Initialize() function. Likewise with termination lldb_private::Terminate() calls PluginManager::Terminate(). The paths for the plug-in directories is fetched through new Host calls: bool Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec); bool Host::GetLLDBPath (ePathTypeLLDBUserPlugins, dir_spec); This way linux and other systems can define their own appropriate locations for plug-ins to be loaded. To allow dynamic shared library loading, the Host layer has also been modified to include shared library open, close and get symbol: static void * Host::DynamicLibraryOpen (const FileSpec &file_spec, Error &error); static Error Host::DynamicLibraryClose (void *dynamic_library_handle); static void * Host::DynamicLibraryGetSymbol (void *dynamic_library_handle, const char *symbol_name, Error &error); lldb_private::FileSpec also has been modified to support directory enumeration in an attempt to abstract the directory enumeration into one spot in the code. The directory enumertion function is static and takes a callback: typedef enum EnumerateDirectoryResult { eEnumerateDirectoryResultNext, // Enumerate next entry in the current directory eEnumerateDirectoryResultEnter, // Recurse into the current entry if it is a directory or symlink, or next if not eEnumerateDirectoryResultExit, // Exit from the current directory at the current level. eEnumerateDirectoryResultQuit // Stop directory enumerations at any level }; typedef FileSpec::EnumerateDirectoryResult (*EnumerateDirectoryCallbackType) (void *baton, FileSpec::FileType file_type, const FileSpec &spec); static FileSpec::EnumerateDirectoryResult FileSpec::EnumerateDirectory (const char *dir_path, bool find_directories, bool find_files, bool find_other, EnumerateDirectoryCallbackType callback, void *callback_baton); This allow clients to specify the directory to search, and specifies if only files, directories or other (pipe, symlink, fifo, etc) files will cause the callback to be called. The callback also gets to return with the action that should be performed after this directory entry. eEnumerateDirectoryResultNext specifies to continue enumerating through a directory with the next entry. eEnumerateDirectoryResultEnter specifies to recurse down into a directory entry, or if the file is not a directory or symlink/alias to a directory, then just iterate to the next entry. eEnumerateDirectoryResultExit specifies to exit the current directory and skip any entries that might be remaining, yet continue enumerating to the next entry in the parent directory. And finally eEnumerateDirectoryResultQuit means to abort all directory enumerations at all levels. Modified the Declaration class to not include column information currently since we don't have any compilers that currently support column based declaration information. Columns support can be re-enabled with the additions of a #define. Added the ability to find an EmulateInstruction plug-in given a target triple and optional plug-in name in the plug-in manager. Fixed a few cases where opendir/readdir was being used, but yet not closedir was being used. Soon these will be deprecated in favor of the new directory enumeration call that was added to the FileSpec class. llvm-svn: 124716
2011-02-02 10:24:04 +08:00
}
#pragma mark ABI
struct ABIInstance {
ABIInstance() : name(), description(), create_callback(nullptr) {}
ConstString name;
std::string description;
ABICreateInstance create_callback;
};
typedef std::vector<ABIInstance> ABIInstances;
static std::recursive_mutex &GetABIInstancesMutex() {
static std::recursive_mutex g_instances_mutex;
return g_instances_mutex;
}
static ABIInstances &GetABIInstances() {
static ABIInstances g_instances;
return g_instances;
}
bool PluginManager::RegisterPlugin(const ConstString &name,
const char *description,
ABICreateInstance create_callback) {
if (create_callback) {
ABIInstance instance;
assert((bool)name);
instance.name = name;
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
std::lock_guard<std::recursive_mutex> guard(GetABIInstancesMutex());
GetABIInstances().push_back(instance);
return true;
}
return false;
}
bool PluginManager::UnregisterPlugin(ABICreateInstance create_callback) {
if (create_callback) {
std::lock_guard<std::recursive_mutex> guard(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);
Added more platform support. There are now some new commands: platform status -- gets status information for the selected platform platform create <platform-name> -- creates a new instance of a remote platform platform list -- list all available platforms platform select -- select a platform instance as the current platform (not working yet) When using "platform create" it will create a remote platform and make it the selected platform. For instances for iPhone OS debugging on Mac OS X one can do: (lldb) platform create remote-ios --sdk-version=4.0 Remote platform: iOS platform SDK version: 4.0 SDK path: "/Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.0" Not connected to a remote device. (lldb) file ~/Documents/a.out Current executable set to '~/Documents/a.out' (armv6). (lldb) image list [ 0] /Volumes/work/gclayton/Documents/devb/attach/a.out [ 1] /Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.0/Symbols/usr/lib/dyld [ 2] /Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.0/Symbols/usr/lib/libSystem.B.dylib Note that this is all happening prior to running _or_ connecting to a remote platform. Once connected to a remote platform the OS version might change which means we will need to update our dependecies. Also once we run, we will need to match up the actualy binaries with the actualy UUID's to files in the SDK, or download and cache them locally. This is just the start of the remote platforms, but this modification is the first iteration in getting the platforms really doing something. llvm-svn: 127934
2011-03-19 09:12:21 +08:00
return true;
}
}
}
return false;
}
ABICreateInstance PluginManager::GetABICreateCallbackAtIndex(uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(GetABIInstancesMutex());
ABIInstances &instances = GetABIInstances();
if (idx < instances.size())
return instances[idx].create_callback;
return nullptr;
}
ABICreateInstance
PluginManager::GetABICreateCallbackForPluginName(const ConstString &name) {
if (name) {
std::lock_guard<std::recursive_mutex> guard(GetABIInstancesMutex());
ABIInstances &instances = GetABIInstances();
ABIInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (name == pos->name)
return pos->create_callback;
}
}
return nullptr;
}
#pragma mark Disassembler
struct DisassemblerInstance {
DisassemblerInstance() : name(), description(), create_callback(nullptr) {}
ConstString name;
std::string description;
DisassemblerCreateInstance create_callback;
};
typedef std::vector<DisassemblerInstance> DisassemblerInstances;
static std::recursive_mutex &GetDisassemblerMutex() {
static std::recursive_mutex g_instances_mutex;
return g_instances_mutex;
}
static DisassemblerInstances &GetDisassemblerInstances() {
static DisassemblerInstances g_instances;
return g_instances;
}
bool PluginManager::RegisterPlugin(const ConstString &name,
const char *description,
DisassemblerCreateInstance create_callback) {
if (create_callback) {
DisassemblerInstance instance;
assert((bool)name);
instance.name = name;
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
std::lock_guard<std::recursive_mutex> guard(GetDisassemblerMutex());
GetDisassemblerInstances().push_back(instance);
return true;
}
return false;
}
bool PluginManager::UnregisterPlugin(
DisassemblerCreateInstance create_callback) {
if (create_callback) {
std::lock_guard<std::recursive_mutex> guard(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) {
std::lock_guard<std::recursive_mutex> guard(GetDisassemblerMutex());
DisassemblerInstances &instances = GetDisassemblerInstances();
if (idx < instances.size())
return instances[idx].create_callback;
return nullptr;
}
DisassemblerCreateInstance
PluginManager::GetDisassemblerCreateCallbackForPluginName(
const ConstString &name) {
if (name) {
std::lock_guard<std::recursive_mutex> guard(GetDisassemblerMutex());
DisassemblerInstances &instances = GetDisassemblerInstances();
DisassemblerInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (name == pos->name)
return pos->create_callback;
}
}
return nullptr;
}
#pragma mark DynamicLoader
struct DynamicLoaderInstance {
DynamicLoaderInstance()
: name(), description(), create_callback(nullptr),
debugger_init_callback(nullptr) {}
ConstString name;
std::string description;
DynamicLoaderCreateInstance create_callback;
DebuggerInitializeCallback debugger_init_callback;
};
typedef std::vector<DynamicLoaderInstance> DynamicLoaderInstances;
static std::recursive_mutex &GetDynamicLoaderMutex() {
static std::recursive_mutex g_instances_mutex;
return g_instances_mutex;
}
static DynamicLoaderInstances &GetDynamicLoaderInstances() {
static DynamicLoaderInstances g_instances;
return g_instances;
}
bool PluginManager::RegisterPlugin(
const ConstString &name, const char *description,
DynamicLoaderCreateInstance create_callback,
DebuggerInitializeCallback debugger_init_callback) {
if (create_callback) {
DynamicLoaderInstance instance;
assert((bool)name);
instance.name = name;
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
instance.debugger_init_callback = debugger_init_callback;
std::lock_guard<std::recursive_mutex> guard(GetDynamicLoaderMutex());
GetDynamicLoaderInstances().push_back(instance);
}
return false;
}
bool PluginManager::UnregisterPlugin(
DynamicLoaderCreateInstance create_callback) {
if (create_callback) {
std::lock_guard<std::recursive_mutex> guard(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) {
std::lock_guard<std::recursive_mutex> guard(GetDynamicLoaderMutex());
DynamicLoaderInstances &instances = GetDynamicLoaderInstances();
if (idx < instances.size())
return instances[idx].create_callback;
return nullptr;
}
DynamicLoaderCreateInstance
PluginManager::GetDynamicLoaderCreateCallbackForPluginName(
const ConstString &name) {
if (name) {
std::lock_guard<std::recursive_mutex> guard(GetDynamicLoaderMutex());
DynamicLoaderInstances &instances = GetDynamicLoaderInstances();
DynamicLoaderInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (name == pos->name)
return pos->create_callback;
}
}
return nullptr;
}
#pragma mark JITLoader
struct JITLoaderInstance {
JITLoaderInstance()
: name(), description(), create_callback(nullptr),
debugger_init_callback(nullptr) {}
ConstString name;
std::string description;
JITLoaderCreateInstance create_callback;
DebuggerInitializeCallback debugger_init_callback;
};
typedef std::vector<JITLoaderInstance> JITLoaderInstances;
static std::recursive_mutex &GetJITLoaderMutex() {
static std::recursive_mutex g_instances_mutex;
return g_instances_mutex;
}
static JITLoaderInstances &GetJITLoaderInstances() {
static JITLoaderInstances g_instances;
return g_instances;
}
bool PluginManager::RegisterPlugin(
const ConstString &name, const char *description,
JITLoaderCreateInstance create_callback,
DebuggerInitializeCallback debugger_init_callback) {
if (create_callback) {
JITLoaderInstance instance;
assert((bool)name);
instance.name = name;
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
instance.debugger_init_callback = debugger_init_callback;
std::lock_guard<std::recursive_mutex> guard(GetJITLoaderMutex());
GetJITLoaderInstances().push_back(instance);
}
return false;
}
bool PluginManager::UnregisterPlugin(JITLoaderCreateInstance create_callback) {
if (create_callback) {
std::lock_guard<std::recursive_mutex> guard(GetJITLoaderMutex());
JITLoaderInstances &instances = GetJITLoaderInstances();
JITLoaderInstances::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;
}
JITLoaderCreateInstance
PluginManager::GetJITLoaderCreateCallbackAtIndex(uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(GetJITLoaderMutex());
JITLoaderInstances &instances = GetJITLoaderInstances();
if (idx < instances.size())
return instances[idx].create_callback;
return nullptr;
}
JITLoaderCreateInstance PluginManager::GetJITLoaderCreateCallbackForPluginName(
const ConstString &name) {
if (name) {
std::lock_guard<std::recursive_mutex> guard(GetJITLoaderMutex());
JITLoaderInstances &instances = GetJITLoaderInstances();
JITLoaderInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (name == pos->name)
return pos->create_callback;
}
}
return nullptr;
}
#pragma mark EmulateInstruction
struct EmulateInstructionInstance {
EmulateInstructionInstance()
: name(), description(), create_callback(nullptr) {}
ConstString name;
std::string description;
EmulateInstructionCreateInstance create_callback;
};
typedef std::vector<EmulateInstructionInstance> EmulateInstructionInstances;
static std::recursive_mutex &GetEmulateInstructionMutex() {
static std::recursive_mutex g_instances_mutex;
return g_instances_mutex;
}
static EmulateInstructionInstances &GetEmulateInstructionInstances() {
static EmulateInstructionInstances g_instances;
return g_instances;
}
bool PluginManager::RegisterPlugin(
const ConstString &name, const char *description,
EmulateInstructionCreateInstance create_callback) {
if (create_callback) {
EmulateInstructionInstance instance;
assert((bool)name);
instance.name = name;
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
std::lock_guard<std::recursive_mutex> guard(GetEmulateInstructionMutex());
GetEmulateInstructionInstances().push_back(instance);
}
return false;
}
bool PluginManager::UnregisterPlugin(
EmulateInstructionCreateInstance create_callback) {
if (create_callback) {
std::lock_guard<std::recursive_mutex> guard(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) {
std::lock_guard<std::recursive_mutex> guard(GetEmulateInstructionMutex());
EmulateInstructionInstances &instances = GetEmulateInstructionInstances();
if (idx < instances.size())
return instances[idx].create_callback;
return nullptr;
}
EmulateInstructionCreateInstance
PluginManager::GetEmulateInstructionCreateCallbackForPluginName(
const ConstString &name) {
if (name) {
std::lock_guard<std::recursive_mutex> guard(GetEmulateInstructionMutex());
EmulateInstructionInstances &instances = GetEmulateInstructionInstances();
EmulateInstructionInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (name == pos->name)
return pos->create_callback;
}
}
return nullptr;
}
#pragma mark OperatingSystem
struct OperatingSystemInstance {
OperatingSystemInstance()
: name(), description(), create_callback(nullptr),
debugger_init_callback(nullptr) {}
ConstString name;
std::string description;
OperatingSystemCreateInstance create_callback;
DebuggerInitializeCallback debugger_init_callback;
};
typedef std::vector<OperatingSystemInstance> OperatingSystemInstances;
static std::recursive_mutex &GetOperatingSystemMutex() {
static std::recursive_mutex g_instances_mutex;
return g_instances_mutex;
}
static OperatingSystemInstances &GetOperatingSystemInstances() {
static OperatingSystemInstances g_instances;
return g_instances;
}
bool PluginManager::RegisterPlugin(
const ConstString &name, const char *description,
OperatingSystemCreateInstance create_callback,
DebuggerInitializeCallback debugger_init_callback) {
if (create_callback) {
OperatingSystemInstance instance;
assert((bool)name);
instance.name = name;
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
instance.debugger_init_callback = debugger_init_callback;
std::lock_guard<std::recursive_mutex> guard(GetOperatingSystemMutex());
GetOperatingSystemInstances().push_back(instance);
}
return false;
}
bool PluginManager::UnregisterPlugin(
OperatingSystemCreateInstance create_callback) {
if (create_callback) {
std::lock_guard<std::recursive_mutex> guard(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) {
std::lock_guard<std::recursive_mutex> guard(GetOperatingSystemMutex());
OperatingSystemInstances &instances = GetOperatingSystemInstances();
if (idx < instances.size())
return instances[idx].create_callback;
return nullptr;
}
OperatingSystemCreateInstance
PluginManager::GetOperatingSystemCreateCallbackForPluginName(
const ConstString &name) {
if (name) {
std::lock_guard<std::recursive_mutex> guard(GetOperatingSystemMutex());
OperatingSystemInstances &instances = GetOperatingSystemInstances();
OperatingSystemInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (name == pos->name)
return pos->create_callback;
}
}
return nullptr;
}
#pragma mark Language
struct LanguageInstance {
LanguageInstance() : name(), description(), create_callback(nullptr) {}
ConstString name;
std::string description;
LanguageCreateInstance create_callback;
};
typedef std::vector<LanguageInstance> LanguageInstances;
static std::recursive_mutex &GetLanguageMutex() {
static std::recursive_mutex g_instances_mutex;
return g_instances_mutex;
}
static LanguageInstances &GetLanguageInstances() {
static LanguageInstances g_instances;
return g_instances;
}
bool PluginManager::RegisterPlugin(const ConstString &name,
const char *description,
LanguageCreateInstance create_callback) {
if (create_callback) {
LanguageInstance instance;
assert((bool)name);
instance.name = name;
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
std::lock_guard<std::recursive_mutex> guard(GetLanguageMutex());
GetLanguageInstances().push_back(instance);
}
return false;
}
bool PluginManager::UnregisterPlugin(LanguageCreateInstance create_callback) {
if (create_callback) {
std::lock_guard<std::recursive_mutex> guard(GetLanguageMutex());
LanguageInstances &instances = GetLanguageInstances();
LanguageInstances::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;
}
LanguageCreateInstance
PluginManager::GetLanguageCreateCallbackAtIndex(uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(GetLanguageMutex());
LanguageInstances &instances = GetLanguageInstances();
if (idx < instances.size())
return instances[idx].create_callback;
return nullptr;
}
LanguageCreateInstance
PluginManager::GetLanguageCreateCallbackForPluginName(const ConstString &name) {
if (name) {
std::lock_guard<std::recursive_mutex> guard(GetLanguageMutex());
LanguageInstances &instances = GetLanguageInstances();
LanguageInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (name == pos->name)
return pos->create_callback;
}
}
return nullptr;
}
#pragma mark LanguageRuntime
struct LanguageRuntimeInstance {
LanguageRuntimeInstance() : name(), description(), create_callback(nullptr) {}
ConstString name;
std::string description;
LanguageRuntimeCreateInstance create_callback;
LanguageRuntimeGetCommandObject command_callback;
};
typedef std::vector<LanguageRuntimeInstance> LanguageRuntimeInstances;
static std::recursive_mutex &GetLanguageRuntimeMutex() {
static std::recursive_mutex g_instances_mutex;
return g_instances_mutex;
}
static LanguageRuntimeInstances &GetLanguageRuntimeInstances() {
static LanguageRuntimeInstances g_instances;
return g_instances;
}
bool PluginManager::RegisterPlugin(
const ConstString &name, const char *description,
LanguageRuntimeCreateInstance create_callback,
LanguageRuntimeGetCommandObject command_callback) {
if (create_callback) {
LanguageRuntimeInstance instance;
assert((bool)name);
instance.name = name;
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
instance.command_callback = command_callback;
std::lock_guard<std::recursive_mutex> guard(GetLanguageRuntimeMutex());
GetLanguageRuntimeInstances().push_back(instance);
}
return false;
}
bool PluginManager::UnregisterPlugin(
LanguageRuntimeCreateInstance create_callback) {
if (create_callback) {
std::lock_guard<std::recursive_mutex> guard(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) {
std::lock_guard<std::recursive_mutex> guard(GetLanguageRuntimeMutex());
LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances();
if (idx < instances.size())
return instances[idx].create_callback;
return nullptr;
}
LanguageRuntimeGetCommandObject
PluginManager::GetLanguageRuntimeGetCommandObjectAtIndex(uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(GetLanguageRuntimeMutex());
LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances();
if (idx < instances.size())
return instances[idx].command_callback;
return nullptr;
}
LanguageRuntimeCreateInstance
PluginManager::GetLanguageRuntimeCreateCallbackForPluginName(
const ConstString &name) {
if (name) {
std::lock_guard<std::recursive_mutex> guard(GetLanguageRuntimeMutex());
LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances();
LanguageRuntimeInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (name == pos->name)
return pos->create_callback;
}
}
return nullptr;
}
#pragma mark SystemRuntime
struct SystemRuntimeInstance {
SystemRuntimeInstance() : name(), description(), create_callback(nullptr) {}
ConstString name;
std::string description;
SystemRuntimeCreateInstance create_callback;
};
typedef std::vector<SystemRuntimeInstance> SystemRuntimeInstances;
static std::recursive_mutex &GetSystemRuntimeMutex() {
static std::recursive_mutex g_instances_mutex;
return g_instances_mutex;
}
static SystemRuntimeInstances &GetSystemRuntimeInstances() {
static SystemRuntimeInstances g_instances;
return g_instances;
}
bool PluginManager::RegisterPlugin(
const ConstString &name, const char *description,
SystemRuntimeCreateInstance create_callback) {
if (create_callback) {
SystemRuntimeInstance instance;
assert((bool)name);
instance.name = name;
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
std::lock_guard<std::recursive_mutex> guard(GetSystemRuntimeMutex());
GetSystemRuntimeInstances().push_back(instance);
}
return false;
}
bool PluginManager::UnregisterPlugin(
SystemRuntimeCreateInstance create_callback) {
if (create_callback) {
std::lock_guard<std::recursive_mutex> guard(GetSystemRuntimeMutex());
SystemRuntimeInstances &instances = GetSystemRuntimeInstances();
SystemRuntimeInstances::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;
}
SystemRuntimeCreateInstance
PluginManager::GetSystemRuntimeCreateCallbackAtIndex(uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(GetSystemRuntimeMutex());
SystemRuntimeInstances &instances = GetSystemRuntimeInstances();
if (idx < instances.size())
return instances[idx].create_callback;
return nullptr;
}
SystemRuntimeCreateInstance
PluginManager::GetSystemRuntimeCreateCallbackForPluginName(
const ConstString &name) {
if (name) {
std::lock_guard<std::recursive_mutex> guard(GetSystemRuntimeMutex());
SystemRuntimeInstances &instances = GetSystemRuntimeInstances();
SystemRuntimeInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (name == pos->name)
return pos->create_callback;
}
}
return nullptr;
}
#pragma mark ObjectFile
struct ObjectFileInstance {
ObjectFileInstance()
: name(), description(), create_callback(nullptr),
create_memory_callback(nullptr), get_module_specifications(nullptr),
save_core(nullptr) {}
ConstString name;
std::string description;
ObjectFileCreateInstance create_callback;
ObjectFileCreateMemoryInstance create_memory_callback;
ObjectFileGetModuleSpecifications get_module_specifications;
ObjectFileSaveCore save_core;
};
typedef std::vector<ObjectFileInstance> ObjectFileInstances;
static std::recursive_mutex &GetObjectFileMutex() {
static std::recursive_mutex g_instances_mutex;
return g_instances_mutex;
}
static ObjectFileInstances &GetObjectFileInstances() {
static ObjectFileInstances g_instances;
return g_instances;
}
bool PluginManager::RegisterPlugin(
const ConstString &name, const char *description,
ObjectFileCreateInstance create_callback,
ObjectFileCreateMemoryInstance create_memory_callback,
ObjectFileGetModuleSpecifications get_module_specifications,
ObjectFileSaveCore save_core) {
if (create_callback) {
ObjectFileInstance instance;
assert((bool)name);
instance.name = name;
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
instance.create_memory_callback = create_memory_callback;
instance.save_core = save_core;
instance.get_module_specifications = get_module_specifications;
std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex());
GetObjectFileInstances().push_back(instance);
}
return false;
}
bool PluginManager::UnregisterPlugin(ObjectFileCreateInstance create_callback) {
if (create_callback) {
std::lock_guard<std::recursive_mutex> guard(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) {
std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex());
ObjectFileInstances &instances = GetObjectFileInstances();
if (idx < instances.size())
return instances[idx].create_callback;
return nullptr;
}
ObjectFileCreateMemoryInstance
PluginManager::GetObjectFileCreateMemoryCallbackAtIndex(uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex());
ObjectFileInstances &instances = GetObjectFileInstances();
if (idx < instances.size())
return instances[idx].create_memory_callback;
return nullptr;
}
ObjectFileGetModuleSpecifications
PluginManager::GetObjectFileGetModuleSpecificationsCallbackAtIndex(
uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex());
ObjectFileInstances &instances = GetObjectFileInstances();
if (idx < instances.size())
return instances[idx].get_module_specifications;
return nullptr;
}
ObjectFileCreateInstance
PluginManager::GetObjectFileCreateCallbackForPluginName(
const ConstString &name) {
if (name) {
std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex());
ObjectFileInstances &instances = GetObjectFileInstances();
ObjectFileInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (name == pos->name)
return pos->create_callback;
}
}
return nullptr;
}
ObjectFileCreateMemoryInstance
PluginManager::GetObjectFileCreateMemoryCallbackForPluginName(
const ConstString &name) {
if (name) {
std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex());
ObjectFileInstances &instances = GetObjectFileInstances();
ObjectFileInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (name == pos->name)
return pos->create_memory_callback;
}
}
return nullptr;
}
Error PluginManager::SaveCore(const lldb::ProcessSP &process_sp,
const FileSpec &outfile) {
Error error;
std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex());
ObjectFileInstances &instances = GetObjectFileInstances();
ObjectFileInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (pos->save_core && pos->save_core(process_sp, outfile, error))
return error;
}
error.SetErrorString(
"no ObjectFile plugins were able to save a core for this process");
return error;
}
#pragma mark ObjectContainer
struct ObjectContainerInstance {
ObjectContainerInstance()
: name(), description(), create_callback(nullptr),
get_module_specifications(nullptr) {}
ConstString name;
std::string description;
ObjectContainerCreateInstance create_callback;
ObjectFileGetModuleSpecifications get_module_specifications;
};
typedef std::vector<ObjectContainerInstance> ObjectContainerInstances;
static std::recursive_mutex &GetObjectContainerMutex() {
static std::recursive_mutex g_instances_mutex;
return g_instances_mutex;
}
static ObjectContainerInstances &GetObjectContainerInstances() {
static ObjectContainerInstances g_instances;
return g_instances;
}
bool PluginManager::RegisterPlugin(
const ConstString &name, const char *description,
ObjectContainerCreateInstance create_callback,
ObjectFileGetModuleSpecifications get_module_specifications) {
if (create_callback) {
ObjectContainerInstance instance;
assert((bool)name);
instance.name = name;
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
instance.get_module_specifications = get_module_specifications;
std::lock_guard<std::recursive_mutex> guard(GetObjectContainerMutex());
GetObjectContainerInstances().push_back(instance);
}
return false;
}
bool PluginManager::UnregisterPlugin(
ObjectContainerCreateInstance create_callback) {
if (create_callback) {
std::lock_guard<std::recursive_mutex> guard(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) {
std::lock_guard<std::recursive_mutex> guard(GetObjectContainerMutex());
ObjectContainerInstances &instances = GetObjectContainerInstances();
if (idx < instances.size())
return instances[idx].create_callback;
return nullptr;
}
ObjectContainerCreateInstance
PluginManager::GetObjectContainerCreateCallbackForPluginName(
const ConstString &name) {
if (name) {
std::lock_guard<std::recursive_mutex> guard(GetObjectContainerMutex());
ObjectContainerInstances &instances = GetObjectContainerInstances();
ObjectContainerInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (name == pos->name)
return pos->create_callback;
}
}
return nullptr;
}
ObjectFileGetModuleSpecifications
PluginManager::GetObjectContainerGetModuleSpecificationsCallbackAtIndex(
uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(GetObjectContainerMutex());
ObjectContainerInstances &instances = GetObjectContainerInstances();
if (idx < instances.size())
return instances[idx].get_module_specifications;
return nullptr;
}
LLDB now has "Platform" plug-ins. Platform plug-ins are plug-ins that provide an interface to a local or remote debugging platform. By default each host OS that supports LLDB should be registering a "default" platform that will be used unless a new platform is selected. Platforms are responsible for things such as: - getting process information by name or by processs ID - finding platform files. This is useful for remote debugging where there is an SDK with files that might already or need to be cached for debug access. - getting a list of platform supported architectures in the exact order they should be selected. This helps the native x86 platform on MacOSX select the correct x86_64/i386 slice from universal binaries. - Connect to remote platforms for remote debugging - Resolving an executable including finding an executable inside platform specific bundles (macosx uses .app bundles that contain files) and also selecting the appropriate slice of universal files for a given platform. So by default there is always a local platform, but remote platforms can be connected to. I will soon be adding a new "platform" command that will support the following commands: (lldb) platform connect --name machine1 macosx connect://host:port Connected to "machine1" platform. (lldb) platform disconnect macosx This allows LLDB to be well setup to do remote debugging and also once connected process listing and finding for things like: (lldb) process attach --name x<TAB> The currently selected platform plug-in can now auto complete any available processes that start with "x". The responsibilities for the platform plug-in will soon grow and expand. llvm-svn: 127286
2011-03-09 06:40:15 +08:00
#pragma mark Platform
struct PlatformInstance {
PlatformInstance()
: name(), description(), create_callback(nullptr),
debugger_init_callback(nullptr) {}
ConstString name;
std::string description;
PlatformCreateInstance create_callback;
DebuggerInitializeCallback debugger_init_callback;
LLDB now has "Platform" plug-ins. Platform plug-ins are plug-ins that provide an interface to a local or remote debugging platform. By default each host OS that supports LLDB should be registering a "default" platform that will be used unless a new platform is selected. Platforms are responsible for things such as: - getting process information by name or by processs ID - finding platform files. This is useful for remote debugging where there is an SDK with files that might already or need to be cached for debug access. - getting a list of platform supported architectures in the exact order they should be selected. This helps the native x86 platform on MacOSX select the correct x86_64/i386 slice from universal binaries. - Connect to remote platforms for remote debugging - Resolving an executable including finding an executable inside platform specific bundles (macosx uses .app bundles that contain files) and also selecting the appropriate slice of universal files for a given platform. So by default there is always a local platform, but remote platforms can be connected to. I will soon be adding a new "platform" command that will support the following commands: (lldb) platform connect --name machine1 macosx connect://host:port Connected to "machine1" platform. (lldb) platform disconnect macosx This allows LLDB to be well setup to do remote debugging and also once connected process listing and finding for things like: (lldb) process attach --name x<TAB> The currently selected platform plug-in can now auto complete any available processes that start with "x". The responsibilities for the platform plug-in will soon grow and expand. llvm-svn: 127286
2011-03-09 06:40:15 +08:00
};
typedef std::vector<PlatformInstance> PlatformInstances;
static std::recursive_mutex &GetPlatformInstancesMutex() {
static std::recursive_mutex g_platform_instances_mutex;
return g_platform_instances_mutex;
LLDB now has "Platform" plug-ins. Platform plug-ins are plug-ins that provide an interface to a local or remote debugging platform. By default each host OS that supports LLDB should be registering a "default" platform that will be used unless a new platform is selected. Platforms are responsible for things such as: - getting process information by name or by processs ID - finding platform files. This is useful for remote debugging where there is an SDK with files that might already or need to be cached for debug access. - getting a list of platform supported architectures in the exact order they should be selected. This helps the native x86 platform on MacOSX select the correct x86_64/i386 slice from universal binaries. - Connect to remote platforms for remote debugging - Resolving an executable including finding an executable inside platform specific bundles (macosx uses .app bundles that contain files) and also selecting the appropriate slice of universal files for a given platform. So by default there is always a local platform, but remote platforms can be connected to. I will soon be adding a new "platform" command that will support the following commands: (lldb) platform connect --name machine1 macosx connect://host:port Connected to "machine1" platform. (lldb) platform disconnect macosx This allows LLDB to be well setup to do remote debugging and also once connected process listing and finding for things like: (lldb) process attach --name x<TAB> The currently selected platform plug-in can now auto complete any available processes that start with "x". The responsibilities for the platform plug-in will soon grow and expand. llvm-svn: 127286
2011-03-09 06:40:15 +08:00
}
static PlatformInstances &GetPlatformInstances() {
static PlatformInstances g_platform_instances;
return g_platform_instances;
}
bool PluginManager::RegisterPlugin(
const ConstString &name, const char *description,
PlatformCreateInstance create_callback,
DebuggerInitializeCallback debugger_init_callback) {
if (create_callback) {
std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex());
PlatformInstance instance;
assert((bool)name);
instance.name = name;
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
instance.debugger_init_callback = debugger_init_callback;
GetPlatformInstances().push_back(instance);
return true;
}
return false;
}
const char *PluginManager::GetPlatformPluginNameAtIndex(uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex());
PlatformInstances &instances = GetPlatformInstances();
if (idx < instances.size())
return instances[idx].name.GetCString();
return nullptr;
}
const char *PluginManager::GetPlatformPluginDescriptionAtIndex(uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex());
PlatformInstances &instances = GetPlatformInstances();
if (idx < instances.size())
return instances[idx].description.c_str();
return nullptr;
LLDB now has "Platform" plug-ins. Platform plug-ins are plug-ins that provide an interface to a local or remote debugging platform. By default each host OS that supports LLDB should be registering a "default" platform that will be used unless a new platform is selected. Platforms are responsible for things such as: - getting process information by name or by processs ID - finding platform files. This is useful for remote debugging where there is an SDK with files that might already or need to be cached for debug access. - getting a list of platform supported architectures in the exact order they should be selected. This helps the native x86 platform on MacOSX select the correct x86_64/i386 slice from universal binaries. - Connect to remote platforms for remote debugging - Resolving an executable including finding an executable inside platform specific bundles (macosx uses .app bundles that contain files) and also selecting the appropriate slice of universal files for a given platform. So by default there is always a local platform, but remote platforms can be connected to. I will soon be adding a new "platform" command that will support the following commands: (lldb) platform connect --name machine1 macosx connect://host:port Connected to "machine1" platform. (lldb) platform disconnect macosx This allows LLDB to be well setup to do remote debugging and also once connected process listing and finding for things like: (lldb) process attach --name x<TAB> The currently selected platform plug-in can now auto complete any available processes that start with "x". The responsibilities for the platform plug-in will soon grow and expand. llvm-svn: 127286
2011-03-09 06:40:15 +08:00
}
bool PluginManager::UnregisterPlugin(PlatformCreateInstance create_callback) {
if (create_callback) {
std::lock_guard<std::recursive_mutex> guard(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;
}
LLDB now has "Platform" plug-ins. Platform plug-ins are plug-ins that provide an interface to a local or remote debugging platform. By default each host OS that supports LLDB should be registering a "default" platform that will be used unless a new platform is selected. Platforms are responsible for things such as: - getting process information by name or by processs ID - finding platform files. This is useful for remote debugging where there is an SDK with files that might already or need to be cached for debug access. - getting a list of platform supported architectures in the exact order they should be selected. This helps the native x86 platform on MacOSX select the correct x86_64/i386 slice from universal binaries. - Connect to remote platforms for remote debugging - Resolving an executable including finding an executable inside platform specific bundles (macosx uses .app bundles that contain files) and also selecting the appropriate slice of universal files for a given platform. So by default there is always a local platform, but remote platforms can be connected to. I will soon be adding a new "platform" command that will support the following commands: (lldb) platform connect --name machine1 macosx connect://host:port Connected to "machine1" platform. (lldb) platform disconnect macosx This allows LLDB to be well setup to do remote debugging and also once connected process listing and finding for things like: (lldb) process attach --name x<TAB> The currently selected platform plug-in can now auto complete any available processes that start with "x". The responsibilities for the platform plug-in will soon grow and expand. llvm-svn: 127286
2011-03-09 06:40:15 +08:00
}
}
return false;
LLDB now has "Platform" plug-ins. Platform plug-ins are plug-ins that provide an interface to a local or remote debugging platform. By default each host OS that supports LLDB should be registering a "default" platform that will be used unless a new platform is selected. Platforms are responsible for things such as: - getting process information by name or by processs ID - finding platform files. This is useful for remote debugging where there is an SDK with files that might already or need to be cached for debug access. - getting a list of platform supported architectures in the exact order they should be selected. This helps the native x86 platform on MacOSX select the correct x86_64/i386 slice from universal binaries. - Connect to remote platforms for remote debugging - Resolving an executable including finding an executable inside platform specific bundles (macosx uses .app bundles that contain files) and also selecting the appropriate slice of universal files for a given platform. So by default there is always a local platform, but remote platforms can be connected to. I will soon be adding a new "platform" command that will support the following commands: (lldb) platform connect --name machine1 macosx connect://host:port Connected to "machine1" platform. (lldb) platform disconnect macosx This allows LLDB to be well setup to do remote debugging and also once connected process listing and finding for things like: (lldb) process attach --name x<TAB> The currently selected platform plug-in can now auto complete any available processes that start with "x". The responsibilities for the platform plug-in will soon grow and expand. llvm-svn: 127286
2011-03-09 06:40:15 +08:00
}
PlatformCreateInstance
PluginManager::GetPlatformCreateCallbackAtIndex(uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex());
PlatformInstances &instances = GetPlatformInstances();
if (idx < instances.size())
return instances[idx].create_callback;
return nullptr;
LLDB now has "Platform" plug-ins. Platform plug-ins are plug-ins that provide an interface to a local or remote debugging platform. By default each host OS that supports LLDB should be registering a "default" platform that will be used unless a new platform is selected. Platforms are responsible for things such as: - getting process information by name or by processs ID - finding platform files. This is useful for remote debugging where there is an SDK with files that might already or need to be cached for debug access. - getting a list of platform supported architectures in the exact order they should be selected. This helps the native x86 platform on MacOSX select the correct x86_64/i386 slice from universal binaries. - Connect to remote platforms for remote debugging - Resolving an executable including finding an executable inside platform specific bundles (macosx uses .app bundles that contain files) and also selecting the appropriate slice of universal files for a given platform. So by default there is always a local platform, but remote platforms can be connected to. I will soon be adding a new "platform" command that will support the following commands: (lldb) platform connect --name machine1 macosx connect://host:port Connected to "machine1" platform. (lldb) platform disconnect macosx This allows LLDB to be well setup to do remote debugging and also once connected process listing and finding for things like: (lldb) process attach --name x<TAB> The currently selected platform plug-in can now auto complete any available processes that start with "x". The responsibilities for the platform plug-in will soon grow and expand. llvm-svn: 127286
2011-03-09 06:40:15 +08:00
}
PlatformCreateInstance
PluginManager::GetPlatformCreateCallbackForPluginName(const ConstString &name) {
if (name) {
std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex());
PlatformInstances &instances = GetPlatformInstances();
PlatformInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (name == pos->name)
return pos->create_callback;
LLDB now has "Platform" plug-ins. Platform plug-ins are plug-ins that provide an interface to a local or remote debugging platform. By default each host OS that supports LLDB should be registering a "default" platform that will be used unless a new platform is selected. Platforms are responsible for things such as: - getting process information by name or by processs ID - finding platform files. This is useful for remote debugging where there is an SDK with files that might already or need to be cached for debug access. - getting a list of platform supported architectures in the exact order they should be selected. This helps the native x86 platform on MacOSX select the correct x86_64/i386 slice from universal binaries. - Connect to remote platforms for remote debugging - Resolving an executable including finding an executable inside platform specific bundles (macosx uses .app bundles that contain files) and also selecting the appropriate slice of universal files for a given platform. So by default there is always a local platform, but remote platforms can be connected to. I will soon be adding a new "platform" command that will support the following commands: (lldb) platform connect --name machine1 macosx connect://host:port Connected to "machine1" platform. (lldb) platform disconnect macosx This allows LLDB to be well setup to do remote debugging and also once connected process listing and finding for things like: (lldb) process attach --name x<TAB> The currently selected platform plug-in can now auto complete any available processes that start with "x". The responsibilities for the platform plug-in will soon grow and expand. llvm-svn: 127286
2011-03-09 06:40:15 +08:00
}
}
return nullptr;
LLDB now has "Platform" plug-ins. Platform plug-ins are plug-ins that provide an interface to a local or remote debugging platform. By default each host OS that supports LLDB should be registering a "default" platform that will be used unless a new platform is selected. Platforms are responsible for things such as: - getting process information by name or by processs ID - finding platform files. This is useful for remote debugging where there is an SDK with files that might already or need to be cached for debug access. - getting a list of platform supported architectures in the exact order they should be selected. This helps the native x86 platform on MacOSX select the correct x86_64/i386 slice from universal binaries. - Connect to remote platforms for remote debugging - Resolving an executable including finding an executable inside platform specific bundles (macosx uses .app bundles that contain files) and also selecting the appropriate slice of universal files for a given platform. So by default there is always a local platform, but remote platforms can be connected to. I will soon be adding a new "platform" command that will support the following commands: (lldb) platform connect --name machine1 macosx connect://host:port Connected to "machine1" platform. (lldb) platform disconnect macosx This allows LLDB to be well setup to do remote debugging and also once connected process listing and finding for things like: (lldb) process attach --name x<TAB> The currently selected platform plug-in can now auto complete any available processes that start with "x". The responsibilities for the platform plug-in will soon grow and expand. llvm-svn: 127286
2011-03-09 06:40:15 +08:00
}
size_t PluginManager::AutoCompletePlatformName(llvm::StringRef name,
StringList &matches) {
if (name.empty())
return matches.GetSize();
std::lock_guard<std::recursive_mutex> guard(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.GetCString());
if (plugin_name.startswith(name_sref))
matches.AppendString(plugin_name.data());
}
return matches.GetSize();
}
LLDB now has "Platform" plug-ins. Platform plug-ins are plug-ins that provide an interface to a local or remote debugging platform. By default each host OS that supports LLDB should be registering a "default" platform that will be used unless a new platform is selected. Platforms are responsible for things such as: - getting process information by name or by processs ID - finding platform files. This is useful for remote debugging where there is an SDK with files that might already or need to be cached for debug access. - getting a list of platform supported architectures in the exact order they should be selected. This helps the native x86 platform on MacOSX select the correct x86_64/i386 slice from universal binaries. - Connect to remote platforms for remote debugging - Resolving an executable including finding an executable inside platform specific bundles (macosx uses .app bundles that contain files) and also selecting the appropriate slice of universal files for a given platform. So by default there is always a local platform, but remote platforms can be connected to. I will soon be adding a new "platform" command that will support the following commands: (lldb) platform connect --name machine1 macosx connect://host:port Connected to "machine1" platform. (lldb) platform disconnect macosx This allows LLDB to be well setup to do remote debugging and also once connected process listing and finding for things like: (lldb) process attach --name x<TAB> The currently selected platform plug-in can now auto complete any available processes that start with "x". The responsibilities for the platform plug-in will soon grow and expand. llvm-svn: 127286
2011-03-09 06:40:15 +08:00
#pragma mark Process
struct ProcessInstance {
ProcessInstance()
: name(), description(), create_callback(nullptr),
debugger_init_callback(nullptr) {}
ConstString name;
std::string description;
ProcessCreateInstance create_callback;
DebuggerInitializeCallback debugger_init_callback;
};
typedef std::vector<ProcessInstance> ProcessInstances;
static std::recursive_mutex &GetProcessMutex() {
static std::recursive_mutex g_instances_mutex;
return g_instances_mutex;
}
static ProcessInstances &GetProcessInstances() {
static ProcessInstances g_instances;
return g_instances;
}
bool PluginManager::RegisterPlugin(
const ConstString &name, const char *description,
ProcessCreateInstance create_callback,
DebuggerInitializeCallback debugger_init_callback) {
if (create_callback) {
ProcessInstance instance;
assert((bool)name);
instance.name = name;
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
instance.debugger_init_callback = debugger_init_callback;
std::lock_guard<std::recursive_mutex> guard(GetProcessMutex());
GetProcessInstances().push_back(instance);
}
return false;
}
const char *PluginManager::GetProcessPluginNameAtIndex(uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(GetProcessMutex());
ProcessInstances &instances = GetProcessInstances();
if (idx < instances.size())
return instances[idx].name.GetCString();
return nullptr;
}
const char *PluginManager::GetProcessPluginDescriptionAtIndex(uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(GetProcessMutex());
ProcessInstances &instances = GetProcessInstances();
if (idx < instances.size())
return instances[idx].description.c_str();
return nullptr;
Added new target instance settings for execution settings: Targets can now specify some additional parameters for when we debug executables that can help with plug-in selection: target.execution-level = auto | user | kernel target.execution-mode = auto | dynamic | static target.execution-os-type = auto | none | halted | live On some systems, the binaries that are created are the same wether you use them to debug a kernel, or a user space program. Many times inspecting an object file can reveal what an executable should be. For these cases we can now be a little more complete by specifying wether to detect all of these things automatically (inspect the main executable file and select a plug-in accordingly), or manually to force the selection of certain plug-ins. To do this we now allow the specficifation of wether one is debugging a user space program (target.execution-level = user) or a kernel program (target.execution-level = kernel). We can also specify if we want to debug a program where shared libraries are dynamically loaded using a DynamicLoader plug-in (target.execution-mode = dynamic), or wether we will treat all symbol files as already linked at the correct address (target.execution-mode = static). We can also specify if the inferior we are debugging is being debugged on a bare board (target.execution-os-type = none), or debugging an OS where we have a JTAG or other direct connection to the inferior stops the entire OS (target.execution-os-type = halted), or if we are debugging a program on something that has live debug services (target.execution-os-type = live). For the "target.execution-os-type = halted" mode, we will need to create ProcessHelper plug-ins that allow us to extract the process/thread and other OS information by reading/writing memory. This should allow LLDB to be used for a wide variety of debugging tasks and handle them all correctly. llvm-svn: 125815
2011-02-18 09:44:25 +08:00
}
bool PluginManager::UnregisterPlugin(ProcessCreateInstance create_callback) {
if (create_callback) {
std::lock_guard<std::recursive_mutex> guard(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) {
std::lock_guard<std::recursive_mutex> guard(GetProcessMutex());
ProcessInstances &instances = GetProcessInstances();
if (idx < instances.size())
return instances[idx].create_callback;
return nullptr;
}
ProcessCreateInstance
PluginManager::GetProcessCreateCallbackForPluginName(const ConstString &name) {
if (name) {
std::lock_guard<std::recursive_mutex> guard(GetProcessMutex());
ProcessInstances &instances = GetProcessInstances();
ProcessInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (name == pos->name)
return pos->create_callback;
}
}
return nullptr;
}
#pragma mark ScriptInterpreter
struct ScriptInterpreterInstance {
ScriptInterpreterInstance()
: name(), language(lldb::eScriptLanguageNone), description(),
create_callback(nullptr) {}
ConstString name;
lldb::ScriptLanguage language;
std::string description;
ScriptInterpreterCreateInstance create_callback;
};
typedef std::vector<ScriptInterpreterInstance> ScriptInterpreterInstances;
static std::recursive_mutex &GetScriptInterpreterMutex() {
static std::recursive_mutex g_instances_mutex;
return g_instances_mutex;
}
static ScriptInterpreterInstances &GetScriptInterpreterInstances() {
static ScriptInterpreterInstances g_instances;
return g_instances;
}
bool PluginManager::RegisterPlugin(
const ConstString &name, const char *description,
lldb::ScriptLanguage script_language,
ScriptInterpreterCreateInstance create_callback) {
if (!create_callback)
return false;
ScriptInterpreterInstance instance;
assert((bool)name);
instance.name = name;
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
instance.language = script_language;
std::lock_guard<std::recursive_mutex> guard(GetScriptInterpreterMutex());
GetScriptInterpreterInstances().push_back(instance);
return false;
}
bool PluginManager::UnregisterPlugin(
ScriptInterpreterCreateInstance create_callback) {
if (!create_callback)
return false;
std::lock_guard<std::recursive_mutex> guard(GetScriptInterpreterMutex());
ScriptInterpreterInstances &instances = GetScriptInterpreterInstances();
ScriptInterpreterInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (pos->create_callback != create_callback)
continue;
instances.erase(pos);
return true;
}
return false;
}
ScriptInterpreterCreateInstance
PluginManager::GetScriptInterpreterCreateCallbackAtIndex(uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(GetScriptInterpreterMutex());
ScriptInterpreterInstances &instances = GetScriptInterpreterInstances();
if (idx < instances.size())
return instances[idx].create_callback;
return nullptr;
}
lldb::ScriptInterpreterSP PluginManager::GetScriptInterpreterForLanguage(
lldb::ScriptLanguage script_lang, CommandInterpreter &interpreter) {
std::lock_guard<std::recursive_mutex> guard(GetScriptInterpreterMutex());
ScriptInterpreterInstances &instances = GetScriptInterpreterInstances();
ScriptInterpreterInstances::iterator pos, end = instances.end();
ScriptInterpreterCreateInstance none_instance = nullptr;
for (pos = instances.begin(); pos != end; ++pos) {
if (pos->language == lldb::eScriptLanguageNone)
none_instance = pos->create_callback;
if (script_lang == pos->language)
return pos->create_callback(interpreter);
}
// If we didn't find one, return the ScriptInterpreter for the null language.
assert(none_instance != nullptr);
return none_instance(interpreter);
}
#pragma mark -
#pragma mark StructuredDataPlugin
// -----------------------------------------------------------------------------
// StructuredDataPlugin
// -----------------------------------------------------------------------------
struct StructuredDataPluginInstance {
StructuredDataPluginInstance()
: name(), description(), create_callback(nullptr),
debugger_init_callback(nullptr), filter_callback(nullptr) {}
ConstString name;
std::string description;
StructuredDataPluginCreateInstance create_callback;
DebuggerInitializeCallback debugger_init_callback;
StructuredDataFilterLaunchInfo filter_callback;
};
typedef std::vector<StructuredDataPluginInstance> StructuredDataPluginInstances;
static std::recursive_mutex &GetStructuredDataPluginMutex() {
static std::recursive_mutex g_instances_mutex;
return g_instances_mutex;
}
static StructuredDataPluginInstances &GetStructuredDataPluginInstances() {
static StructuredDataPluginInstances g_instances;
return g_instances;
}
bool PluginManager::RegisterPlugin(
const ConstString &name, const char *description,
StructuredDataPluginCreateInstance create_callback,
DebuggerInitializeCallback debugger_init_callback,
StructuredDataFilterLaunchInfo filter_callback) {
if (create_callback) {
StructuredDataPluginInstance instance;
assert((bool)name);
instance.name = name;
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
instance.debugger_init_callback = debugger_init_callback;
instance.filter_callback = filter_callback;
std::lock_guard<std::recursive_mutex> guard(GetStructuredDataPluginMutex());
GetStructuredDataPluginInstances().push_back(instance);
}
return false;
}
bool PluginManager::UnregisterPlugin(
StructuredDataPluginCreateInstance create_callback) {
if (create_callback) {
std::lock_guard<std::recursive_mutex> guard(GetStructuredDataPluginMutex());
StructuredDataPluginInstances &instances =
GetStructuredDataPluginInstances();
StructuredDataPluginInstances::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;
}
StructuredDataPluginCreateInstance
PluginManager::GetStructuredDataPluginCreateCallbackAtIndex(uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(GetStructuredDataPluginMutex());
StructuredDataPluginInstances &instances = GetStructuredDataPluginInstances();
if (idx < instances.size())
return instances[idx].create_callback;
return nullptr;
}
StructuredDataPluginCreateInstance
PluginManager::GetStructuredDataPluginCreateCallbackForPluginName(
const ConstString &name) {
if (name) {
std::lock_guard<std::recursive_mutex> guard(GetStructuredDataPluginMutex());
StructuredDataPluginInstances &instances =
GetStructuredDataPluginInstances();
StructuredDataPluginInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (name == pos->name)
return pos->create_callback;
}
}
return nullptr;
}
StructuredDataFilterLaunchInfo
PluginManager::GetStructuredDataFilterCallbackAtIndex(
uint32_t idx, bool &iteration_complete) {
std::lock_guard<std::recursive_mutex> guard(GetStructuredDataPluginMutex());
StructuredDataPluginInstances &instances = GetStructuredDataPluginInstances();
if (idx < instances.size()) {
iteration_complete = false;
return instances[idx].filter_callback;
} else {
iteration_complete = true;
}
return nullptr;
}
#pragma mark SymbolFile
struct SymbolFileInstance {
SymbolFileInstance()
: name(), description(), create_callback(nullptr),
debugger_init_callback(nullptr) {}
ConstString name;
std::string description;
SymbolFileCreateInstance create_callback;
DebuggerInitializeCallback debugger_init_callback;
};
typedef std::vector<SymbolFileInstance> SymbolFileInstances;
static std::recursive_mutex &GetSymbolFileMutex() {
static std::recursive_mutex g_instances_mutex;
return g_instances_mutex;
}
static SymbolFileInstances &GetSymbolFileInstances() {
static SymbolFileInstances g_instances;
return g_instances;
}
bool PluginManager::RegisterPlugin(
const ConstString &name, const char *description,
SymbolFileCreateInstance create_callback,
DebuggerInitializeCallback debugger_init_callback) {
if (create_callback) {
SymbolFileInstance instance;
assert((bool)name);
instance.name = name;
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
instance.debugger_init_callback = debugger_init_callback;
std::lock_guard<std::recursive_mutex> guard(GetSymbolFileMutex());
GetSymbolFileInstances().push_back(instance);
}
return false;
}
bool PluginManager::UnregisterPlugin(SymbolFileCreateInstance create_callback) {
if (create_callback) {
std::lock_guard<std::recursive_mutex> guard(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) {
std::lock_guard<std::recursive_mutex> guard(GetSymbolFileMutex());
SymbolFileInstances &instances = GetSymbolFileInstances();
if (idx < instances.size())
return instances[idx].create_callback;
return nullptr;
}
SymbolFileCreateInstance
PluginManager::GetSymbolFileCreateCallbackForPluginName(
const ConstString &name) {
if (name) {
std::lock_guard<std::recursive_mutex> guard(GetSymbolFileMutex());
SymbolFileInstances &instances = GetSymbolFileInstances();
SymbolFileInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (name == pos->name)
return pos->create_callback;
}
}
return nullptr;
}
#pragma mark SymbolVendor
struct SymbolVendorInstance {
SymbolVendorInstance() : name(), description(), create_callback(nullptr) {}
ConstString name;
std::string description;
SymbolVendorCreateInstance create_callback;
};
typedef std::vector<SymbolVendorInstance> SymbolVendorInstances;
static std::recursive_mutex &GetSymbolVendorMutex() {
static std::recursive_mutex g_instances_mutex;
return g_instances_mutex;
}
static SymbolVendorInstances &GetSymbolVendorInstances() {
static SymbolVendorInstances g_instances;
return g_instances;
}
bool PluginManager::RegisterPlugin(const ConstString &name,
const char *description,
SymbolVendorCreateInstance create_callback) {
if (create_callback) {
SymbolVendorInstance instance;
assert((bool)name);
instance.name = name;
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
std::lock_guard<std::recursive_mutex> guard(GetSymbolVendorMutex());
GetSymbolVendorInstances().push_back(instance);
}
return false;
}
bool PluginManager::UnregisterPlugin(
SymbolVendorCreateInstance create_callback) {
if (create_callback) {
std::lock_guard<std::recursive_mutex> guard(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) {
std::lock_guard<std::recursive_mutex> guard(GetSymbolVendorMutex());
SymbolVendorInstances &instances = GetSymbolVendorInstances();
if (idx < instances.size())
return instances[idx].create_callback;
return nullptr;
}
SymbolVendorCreateInstance
PluginManager::GetSymbolVendorCreateCallbackForPluginName(
const ConstString &name) {
if (name) {
std::lock_guard<std::recursive_mutex> guard(GetSymbolVendorMutex());
SymbolVendorInstances &instances = GetSymbolVendorInstances();
SymbolVendorInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (name == pos->name)
return pos->create_callback;
}
}
return nullptr;
}
#pragma mark UnwindAssembly
The first part of an lldb native stack unwinder. The Unwind and RegisterContext subclasses still need to be finished; none of this code is used by lldb at this point (unless you call into it by hand). The ObjectFile class now has an UnwindTable object. The UnwindTable object has a series of FuncUnwinders objects (Function Unwinders) -- one for each function in that ObjectFile we've backtraced through during this debug session. The FuncUnwinders object has a few different UnwindPlans. UnwindPlans are a generic way of describing how to find the canonical address of a given function's stack frame (the CFA idea from DWARF/eh_frame) and how to restore the caller frame's register values, if they have been saved by this function. UnwindPlans are created from different sources. One source is the eh_frame exception handling information generated by the compiler for unwinding an exception throw. Another source is an assembly language inspection class (UnwindAssemblyProfiler, uses the Plugin architecture) which looks at the instructions in the funciton prologue and describes the stack movements/register saves that are done. Two additional types of UnwindPlans that are worth noting are the "fast" stack UnwindPlan which is useful for making a first pass over a thread's stack, determining how many stack frames there are and retrieving the pc and CFA values for each frame (enough to create StackFrameIDs). Only a minimal set of registers is recovered during a fast stack walk. The final UnwindPlan is an architectural default unwind plan. These are provided by the ArchDefaultUnwindPlan class (which uses the plugin architecture). When no symbol/function address range can be found for a given pc value -- when we have no eh_frame information and when we don't have a start address so we can't examine the assembly language instrucitons -- we have to make a best guess about how to unwind. That's when we use the architectural default UnwindPlan. On x86_64, this would be to assume that rbp is used as a stack pointer and we can use that to find the caller's frame pointer and pc value. It's a last-ditch best guess about how to unwind out of a frame. There are heuristics about when to use one UnwindPlan versues the other -- this will all happen in the still-begin-written UnwindLLDB subclass of Unwind which runs the UnwindPlans. llvm-svn: 113581
2010-09-10 15:49:16 +08:00
struct UnwindAssemblyInstance {
UnwindAssemblyInstance() : name(), description(), create_callback(nullptr) {}
The first part of an lldb native stack unwinder. The Unwind and RegisterContext subclasses still need to be finished; none of this code is used by lldb at this point (unless you call into it by hand). The ObjectFile class now has an UnwindTable object. The UnwindTable object has a series of FuncUnwinders objects (Function Unwinders) -- one for each function in that ObjectFile we've backtraced through during this debug session. The FuncUnwinders object has a few different UnwindPlans. UnwindPlans are a generic way of describing how to find the canonical address of a given function's stack frame (the CFA idea from DWARF/eh_frame) and how to restore the caller frame's register values, if they have been saved by this function. UnwindPlans are created from different sources. One source is the eh_frame exception handling information generated by the compiler for unwinding an exception throw. Another source is an assembly language inspection class (UnwindAssemblyProfiler, uses the Plugin architecture) which looks at the instructions in the funciton prologue and describes the stack movements/register saves that are done. Two additional types of UnwindPlans that are worth noting are the "fast" stack UnwindPlan which is useful for making a first pass over a thread's stack, determining how many stack frames there are and retrieving the pc and CFA values for each frame (enough to create StackFrameIDs). Only a minimal set of registers is recovered during a fast stack walk. The final UnwindPlan is an architectural default unwind plan. These are provided by the ArchDefaultUnwindPlan class (which uses the plugin architecture). When no symbol/function address range can be found for a given pc value -- when we have no eh_frame information and when we don't have a start address so we can't examine the assembly language instrucitons -- we have to make a best guess about how to unwind. That's when we use the architectural default UnwindPlan. On x86_64, this would be to assume that rbp is used as a stack pointer and we can use that to find the caller's frame pointer and pc value. It's a last-ditch best guess about how to unwind out of a frame. There are heuristics about when to use one UnwindPlan versues the other -- this will all happen in the still-begin-written UnwindLLDB subclass of Unwind which runs the UnwindPlans. llvm-svn: 113581
2010-09-10 15:49:16 +08:00
ConstString name;
std::string description;
UnwindAssemblyCreateInstance create_callback;
The first part of an lldb native stack unwinder. The Unwind and RegisterContext subclasses still need to be finished; none of this code is used by lldb at this point (unless you call into it by hand). The ObjectFile class now has an UnwindTable object. The UnwindTable object has a series of FuncUnwinders objects (Function Unwinders) -- one for each function in that ObjectFile we've backtraced through during this debug session. The FuncUnwinders object has a few different UnwindPlans. UnwindPlans are a generic way of describing how to find the canonical address of a given function's stack frame (the CFA idea from DWARF/eh_frame) and how to restore the caller frame's register values, if they have been saved by this function. UnwindPlans are created from different sources. One source is the eh_frame exception handling information generated by the compiler for unwinding an exception throw. Another source is an assembly language inspection class (UnwindAssemblyProfiler, uses the Plugin architecture) which looks at the instructions in the funciton prologue and describes the stack movements/register saves that are done. Two additional types of UnwindPlans that are worth noting are the "fast" stack UnwindPlan which is useful for making a first pass over a thread's stack, determining how many stack frames there are and retrieving the pc and CFA values for each frame (enough to create StackFrameIDs). Only a minimal set of registers is recovered during a fast stack walk. The final UnwindPlan is an architectural default unwind plan. These are provided by the ArchDefaultUnwindPlan class (which uses the plugin architecture). When no symbol/function address range can be found for a given pc value -- when we have no eh_frame information and when we don't have a start address so we can't examine the assembly language instrucitons -- we have to make a best guess about how to unwind. That's when we use the architectural default UnwindPlan. On x86_64, this would be to assume that rbp is used as a stack pointer and we can use that to find the caller's frame pointer and pc value. It's a last-ditch best guess about how to unwind out of a frame. There are heuristics about when to use one UnwindPlan versues the other -- this will all happen in the still-begin-written UnwindLLDB subclass of Unwind which runs the UnwindPlans. llvm-svn: 113581
2010-09-10 15:49:16 +08:00
};
typedef std::vector<UnwindAssemblyInstance> UnwindAssemblyInstances;
The first part of an lldb native stack unwinder. The Unwind and RegisterContext subclasses still need to be finished; none of this code is used by lldb at this point (unless you call into it by hand). The ObjectFile class now has an UnwindTable object. The UnwindTable object has a series of FuncUnwinders objects (Function Unwinders) -- one for each function in that ObjectFile we've backtraced through during this debug session. The FuncUnwinders object has a few different UnwindPlans. UnwindPlans are a generic way of describing how to find the canonical address of a given function's stack frame (the CFA idea from DWARF/eh_frame) and how to restore the caller frame's register values, if they have been saved by this function. UnwindPlans are created from different sources. One source is the eh_frame exception handling information generated by the compiler for unwinding an exception throw. Another source is an assembly language inspection class (UnwindAssemblyProfiler, uses the Plugin architecture) which looks at the instructions in the funciton prologue and describes the stack movements/register saves that are done. Two additional types of UnwindPlans that are worth noting are the "fast" stack UnwindPlan which is useful for making a first pass over a thread's stack, determining how many stack frames there are and retrieving the pc and CFA values for each frame (enough to create StackFrameIDs). Only a minimal set of registers is recovered during a fast stack walk. The final UnwindPlan is an architectural default unwind plan. These are provided by the ArchDefaultUnwindPlan class (which uses the plugin architecture). When no symbol/function address range can be found for a given pc value -- when we have no eh_frame information and when we don't have a start address so we can't examine the assembly language instrucitons -- we have to make a best guess about how to unwind. That's when we use the architectural default UnwindPlan. On x86_64, this would be to assume that rbp is used as a stack pointer and we can use that to find the caller's frame pointer and pc value. It's a last-ditch best guess about how to unwind out of a frame. There are heuristics about when to use one UnwindPlan versues the other -- this will all happen in the still-begin-written UnwindLLDB subclass of Unwind which runs the UnwindPlans. llvm-svn: 113581
2010-09-10 15:49:16 +08:00
static std::recursive_mutex &GetUnwindAssemblyMutex() {
static std::recursive_mutex g_instances_mutex;
return g_instances_mutex;
The first part of an lldb native stack unwinder. The Unwind and RegisterContext subclasses still need to be finished; none of this code is used by lldb at this point (unless you call into it by hand). The ObjectFile class now has an UnwindTable object. The UnwindTable object has a series of FuncUnwinders objects (Function Unwinders) -- one for each function in that ObjectFile we've backtraced through during this debug session. The FuncUnwinders object has a few different UnwindPlans. UnwindPlans are a generic way of describing how to find the canonical address of a given function's stack frame (the CFA idea from DWARF/eh_frame) and how to restore the caller frame's register values, if they have been saved by this function. UnwindPlans are created from different sources. One source is the eh_frame exception handling information generated by the compiler for unwinding an exception throw. Another source is an assembly language inspection class (UnwindAssemblyProfiler, uses the Plugin architecture) which looks at the instructions in the funciton prologue and describes the stack movements/register saves that are done. Two additional types of UnwindPlans that are worth noting are the "fast" stack UnwindPlan which is useful for making a first pass over a thread's stack, determining how many stack frames there are and retrieving the pc and CFA values for each frame (enough to create StackFrameIDs). Only a minimal set of registers is recovered during a fast stack walk. The final UnwindPlan is an architectural default unwind plan. These are provided by the ArchDefaultUnwindPlan class (which uses the plugin architecture). When no symbol/function address range can be found for a given pc value -- when we have no eh_frame information and when we don't have a start address so we can't examine the assembly language instrucitons -- we have to make a best guess about how to unwind. That's when we use the architectural default UnwindPlan. On x86_64, this would be to assume that rbp is used as a stack pointer and we can use that to find the caller's frame pointer and pc value. It's a last-ditch best guess about how to unwind out of a frame. There are heuristics about when to use one UnwindPlan versues the other -- this will all happen in the still-begin-written UnwindLLDB subclass of Unwind which runs the UnwindPlans. llvm-svn: 113581
2010-09-10 15:49:16 +08:00
}
static UnwindAssemblyInstances &GetUnwindAssemblyInstances() {
static UnwindAssemblyInstances g_instances;
return g_instances;
}
bool PluginManager::RegisterPlugin(
const ConstString &name, const char *description,
UnwindAssemblyCreateInstance create_callback) {
if (create_callback) {
UnwindAssemblyInstance instance;
assert((bool)name);
instance.name = name;
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
std::lock_guard<std::recursive_mutex> guard(GetUnwindAssemblyMutex());
GetUnwindAssemblyInstances().push_back(instance);
}
return false;
}
bool PluginManager::UnregisterPlugin(
UnwindAssemblyCreateInstance create_callback) {
if (create_callback) {
std::lock_guard<std::recursive_mutex> guard(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;
}
The first part of an lldb native stack unwinder. The Unwind and RegisterContext subclasses still need to be finished; none of this code is used by lldb at this point (unless you call into it by hand). The ObjectFile class now has an UnwindTable object. The UnwindTable object has a series of FuncUnwinders objects (Function Unwinders) -- one for each function in that ObjectFile we've backtraced through during this debug session. The FuncUnwinders object has a few different UnwindPlans. UnwindPlans are a generic way of describing how to find the canonical address of a given function's stack frame (the CFA idea from DWARF/eh_frame) and how to restore the caller frame's register values, if they have been saved by this function. UnwindPlans are created from different sources. One source is the eh_frame exception handling information generated by the compiler for unwinding an exception throw. Another source is an assembly language inspection class (UnwindAssemblyProfiler, uses the Plugin architecture) which looks at the instructions in the funciton prologue and describes the stack movements/register saves that are done. Two additional types of UnwindPlans that are worth noting are the "fast" stack UnwindPlan which is useful for making a first pass over a thread's stack, determining how many stack frames there are and retrieving the pc and CFA values for each frame (enough to create StackFrameIDs). Only a minimal set of registers is recovered during a fast stack walk. The final UnwindPlan is an architectural default unwind plan. These are provided by the ArchDefaultUnwindPlan class (which uses the plugin architecture). When no symbol/function address range can be found for a given pc value -- when we have no eh_frame information and when we don't have a start address so we can't examine the assembly language instrucitons -- we have to make a best guess about how to unwind. That's when we use the architectural default UnwindPlan. On x86_64, this would be to assume that rbp is used as a stack pointer and we can use that to find the caller's frame pointer and pc value. It's a last-ditch best guess about how to unwind out of a frame. There are heuristics about when to use one UnwindPlan versues the other -- this will all happen in the still-begin-written UnwindLLDB subclass of Unwind which runs the UnwindPlans. llvm-svn: 113581
2010-09-10 15:49:16 +08:00
}
}
return false;
The first part of an lldb native stack unwinder. The Unwind and RegisterContext subclasses still need to be finished; none of this code is used by lldb at this point (unless you call into it by hand). The ObjectFile class now has an UnwindTable object. The UnwindTable object has a series of FuncUnwinders objects (Function Unwinders) -- one for each function in that ObjectFile we've backtraced through during this debug session. The FuncUnwinders object has a few different UnwindPlans. UnwindPlans are a generic way of describing how to find the canonical address of a given function's stack frame (the CFA idea from DWARF/eh_frame) and how to restore the caller frame's register values, if they have been saved by this function. UnwindPlans are created from different sources. One source is the eh_frame exception handling information generated by the compiler for unwinding an exception throw. Another source is an assembly language inspection class (UnwindAssemblyProfiler, uses the Plugin architecture) which looks at the instructions in the funciton prologue and describes the stack movements/register saves that are done. Two additional types of UnwindPlans that are worth noting are the "fast" stack UnwindPlan which is useful for making a first pass over a thread's stack, determining how many stack frames there are and retrieving the pc and CFA values for each frame (enough to create StackFrameIDs). Only a minimal set of registers is recovered during a fast stack walk. The final UnwindPlan is an architectural default unwind plan. These are provided by the ArchDefaultUnwindPlan class (which uses the plugin architecture). When no symbol/function address range can be found for a given pc value -- when we have no eh_frame information and when we don't have a start address so we can't examine the assembly language instrucitons -- we have to make a best guess about how to unwind. That's when we use the architectural default UnwindPlan. On x86_64, this would be to assume that rbp is used as a stack pointer and we can use that to find the caller's frame pointer and pc value. It's a last-ditch best guess about how to unwind out of a frame. There are heuristics about when to use one UnwindPlan versues the other -- this will all happen in the still-begin-written UnwindLLDB subclass of Unwind which runs the UnwindPlans. llvm-svn: 113581
2010-09-10 15:49:16 +08:00
}
UnwindAssemblyCreateInstance
PluginManager::GetUnwindAssemblyCreateCallbackAtIndex(uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(GetUnwindAssemblyMutex());
UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances();
if (idx < instances.size())
return instances[idx].create_callback;
return nullptr;
The first part of an lldb native stack unwinder. The Unwind and RegisterContext subclasses still need to be finished; none of this code is used by lldb at this point (unless you call into it by hand). The ObjectFile class now has an UnwindTable object. The UnwindTable object has a series of FuncUnwinders objects (Function Unwinders) -- one for each function in that ObjectFile we've backtraced through during this debug session. The FuncUnwinders object has a few different UnwindPlans. UnwindPlans are a generic way of describing how to find the canonical address of a given function's stack frame (the CFA idea from DWARF/eh_frame) and how to restore the caller frame's register values, if they have been saved by this function. UnwindPlans are created from different sources. One source is the eh_frame exception handling information generated by the compiler for unwinding an exception throw. Another source is an assembly language inspection class (UnwindAssemblyProfiler, uses the Plugin architecture) which looks at the instructions in the funciton prologue and describes the stack movements/register saves that are done. Two additional types of UnwindPlans that are worth noting are the "fast" stack UnwindPlan which is useful for making a first pass over a thread's stack, determining how many stack frames there are and retrieving the pc and CFA values for each frame (enough to create StackFrameIDs). Only a minimal set of registers is recovered during a fast stack walk. The final UnwindPlan is an architectural default unwind plan. These are provided by the ArchDefaultUnwindPlan class (which uses the plugin architecture). When no symbol/function address range can be found for a given pc value -- when we have no eh_frame information and when we don't have a start address so we can't examine the assembly language instrucitons -- we have to make a best guess about how to unwind. That's when we use the architectural default UnwindPlan. On x86_64, this would be to assume that rbp is used as a stack pointer and we can use that to find the caller's frame pointer and pc value. It's a last-ditch best guess about how to unwind out of a frame. There are heuristics about when to use one UnwindPlan versues the other -- this will all happen in the still-begin-written UnwindLLDB subclass of Unwind which runs the UnwindPlans. llvm-svn: 113581
2010-09-10 15:49:16 +08:00
}
UnwindAssemblyCreateInstance
PluginManager::GetUnwindAssemblyCreateCallbackForPluginName(
const ConstString &name) {
if (name) {
std::lock_guard<std::recursive_mutex> guard(GetUnwindAssemblyMutex());
UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances();
UnwindAssemblyInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (name == pos->name)
return pos->create_callback;
The first part of an lldb native stack unwinder. The Unwind and RegisterContext subclasses still need to be finished; none of this code is used by lldb at this point (unless you call into it by hand). The ObjectFile class now has an UnwindTable object. The UnwindTable object has a series of FuncUnwinders objects (Function Unwinders) -- one for each function in that ObjectFile we've backtraced through during this debug session. The FuncUnwinders object has a few different UnwindPlans. UnwindPlans are a generic way of describing how to find the canonical address of a given function's stack frame (the CFA idea from DWARF/eh_frame) and how to restore the caller frame's register values, if they have been saved by this function. UnwindPlans are created from different sources. One source is the eh_frame exception handling information generated by the compiler for unwinding an exception throw. Another source is an assembly language inspection class (UnwindAssemblyProfiler, uses the Plugin architecture) which looks at the instructions in the funciton prologue and describes the stack movements/register saves that are done. Two additional types of UnwindPlans that are worth noting are the "fast" stack UnwindPlan which is useful for making a first pass over a thread's stack, determining how many stack frames there are and retrieving the pc and CFA values for each frame (enough to create StackFrameIDs). Only a minimal set of registers is recovered during a fast stack walk. The final UnwindPlan is an architectural default unwind plan. These are provided by the ArchDefaultUnwindPlan class (which uses the plugin architecture). When no symbol/function address range can be found for a given pc value -- when we have no eh_frame information and when we don't have a start address so we can't examine the assembly language instrucitons -- we have to make a best guess about how to unwind. That's when we use the architectural default UnwindPlan. On x86_64, this would be to assume that rbp is used as a stack pointer and we can use that to find the caller's frame pointer and pc value. It's a last-ditch best guess about how to unwind out of a frame. There are heuristics about when to use one UnwindPlan versues the other -- this will all happen in the still-begin-written UnwindLLDB subclass of Unwind which runs the UnwindPlans. llvm-svn: 113581
2010-09-10 15:49:16 +08:00
}
}
return nullptr;
The first part of an lldb native stack unwinder. The Unwind and RegisterContext subclasses still need to be finished; none of this code is used by lldb at this point (unless you call into it by hand). The ObjectFile class now has an UnwindTable object. The UnwindTable object has a series of FuncUnwinders objects (Function Unwinders) -- one for each function in that ObjectFile we've backtraced through during this debug session. The FuncUnwinders object has a few different UnwindPlans. UnwindPlans are a generic way of describing how to find the canonical address of a given function's stack frame (the CFA idea from DWARF/eh_frame) and how to restore the caller frame's register values, if they have been saved by this function. UnwindPlans are created from different sources. One source is the eh_frame exception handling information generated by the compiler for unwinding an exception throw. Another source is an assembly language inspection class (UnwindAssemblyProfiler, uses the Plugin architecture) which looks at the instructions in the funciton prologue and describes the stack movements/register saves that are done. Two additional types of UnwindPlans that are worth noting are the "fast" stack UnwindPlan which is useful for making a first pass over a thread's stack, determining how many stack frames there are and retrieving the pc and CFA values for each frame (enough to create StackFrameIDs). Only a minimal set of registers is recovered during a fast stack walk. The final UnwindPlan is an architectural default unwind plan. These are provided by the ArchDefaultUnwindPlan class (which uses the plugin architecture). When no symbol/function address range can be found for a given pc value -- when we have no eh_frame information and when we don't have a start address so we can't examine the assembly language instrucitons -- we have to make a best guess about how to unwind. That's when we use the architectural default UnwindPlan. On x86_64, this would be to assume that rbp is used as a stack pointer and we can use that to find the caller's frame pointer and pc value. It's a last-ditch best guess about how to unwind out of a frame. There are heuristics about when to use one UnwindPlan versues the other -- this will all happen in the still-begin-written UnwindLLDB subclass of Unwind which runs the UnwindPlans. llvm-svn: 113581
2010-09-10 15:49:16 +08:00
}
#pragma mark MemoryHistory
struct MemoryHistoryInstance {
MemoryHistoryInstance() : name(), description(), create_callback(nullptr) {}
ConstString name;
std::string description;
MemoryHistoryCreateInstance create_callback;
};
typedef std::vector<MemoryHistoryInstance> MemoryHistoryInstances;
static std::recursive_mutex &GetMemoryHistoryMutex() {
static std::recursive_mutex g_instances_mutex;
return g_instances_mutex;
}
static MemoryHistoryInstances &GetMemoryHistoryInstances() {
static MemoryHistoryInstances g_instances;
return g_instances;
}
bool PluginManager::RegisterPlugin(
const ConstString &name, const char *description,
MemoryHistoryCreateInstance create_callback) {
if (create_callback) {
MemoryHistoryInstance instance;
assert((bool)name);
instance.name = name;
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
std::lock_guard<std::recursive_mutex> guard(GetMemoryHistoryMutex());
GetMemoryHistoryInstances().push_back(instance);
}
return false;
}
bool PluginManager::UnregisterPlugin(
MemoryHistoryCreateInstance create_callback) {
if (create_callback) {
std::lock_guard<std::recursive_mutex> guard(GetMemoryHistoryMutex());
MemoryHistoryInstances &instances = GetMemoryHistoryInstances();
MemoryHistoryInstances::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;
}
MemoryHistoryCreateInstance
PluginManager::GetMemoryHistoryCreateCallbackAtIndex(uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(GetMemoryHistoryMutex());
MemoryHistoryInstances &instances = GetMemoryHistoryInstances();
if (idx < instances.size())
return instances[idx].create_callback;
return nullptr;
}
MemoryHistoryCreateInstance
PluginManager::GetMemoryHistoryCreateCallbackForPluginName(
const ConstString &name) {
if (name) {
std::lock_guard<std::recursive_mutex> guard(GetMemoryHistoryMutex());
MemoryHistoryInstances &instances = GetMemoryHistoryInstances();
MemoryHistoryInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (name == pos->name)
return pos->create_callback;
}
}
return nullptr;
}
LLDB AddressSanitizer instrumentation runtime plugin, breakpint on error and report data extraction Reviewed at http://reviews.llvm.org/D5592 This patch gives LLDB some ability to interact with AddressSanitizer runtime library, on top of what we already have (historical memory stack traces provided by ASan). Namely, that's the ability to stop on an error caught by ASan, and access the report information that are associated with it. The report information is also exposed into SB API. More precisely this patch... adds a new plugin type, InstrumentationRuntime, which should serve as a generic superclass for other instrumentation runtime libraries, these plugins get notified when modules are loaded, so they get a chance to "activate" when a specific dynamic library is loaded an instance of this plugin type, AddressSanitizerRuntime, which activates itself when it sees the ASan dynamic library or founds ASan statically linked in the executable adds a collection of these plugins into the Process class AddressSanitizerRuntime sets an internal breakpoint on __asan::AsanDie(), and when this breakpoint gets hit, it retrieves the report information from ASan this breakpoint is then exposed as a new StopReason, eStopReasonInstrumentation, with a new StopInfo subclass, InstrumentationRuntimeStopInfo the StopInfo superclass is extended with a m_extended_info field (it's a StructuredData::ObjectSP), that can hold arbitrary JSON-like data, which is the way the new plugin provides the report data the "thread info" command now accepts a "-s" flag that prints out the JSON data of a stop reason (same way the "-j" flag works now) SBThread has a new API, GetStopReasonExtendedInfoAsJSON, which dumps the JSON string into a SBStream adds a test case for all of this I plan to also get rid of the original ASan plugin (memory history stack traces) and use an instance of AddressSanitizerRuntime for that purpose. Kuba llvm-svn: 219546
2014-10-11 07:43:03 +08:00
#pragma mark InstrumentationRuntime
struct InstrumentationRuntimeInstance {
InstrumentationRuntimeInstance()
: name(), description(), create_callback(nullptr) {}
ConstString name;
std::string description;
InstrumentationRuntimeCreateInstance create_callback;
InstrumentationRuntimeGetType get_type_callback;
LLDB AddressSanitizer instrumentation runtime plugin, breakpint on error and report data extraction Reviewed at http://reviews.llvm.org/D5592 This patch gives LLDB some ability to interact with AddressSanitizer runtime library, on top of what we already have (historical memory stack traces provided by ASan). Namely, that's the ability to stop on an error caught by ASan, and access the report information that are associated with it. The report information is also exposed into SB API. More precisely this patch... adds a new plugin type, InstrumentationRuntime, which should serve as a generic superclass for other instrumentation runtime libraries, these plugins get notified when modules are loaded, so they get a chance to "activate" when a specific dynamic library is loaded an instance of this plugin type, AddressSanitizerRuntime, which activates itself when it sees the ASan dynamic library or founds ASan statically linked in the executable adds a collection of these plugins into the Process class AddressSanitizerRuntime sets an internal breakpoint on __asan::AsanDie(), and when this breakpoint gets hit, it retrieves the report information from ASan this breakpoint is then exposed as a new StopReason, eStopReasonInstrumentation, with a new StopInfo subclass, InstrumentationRuntimeStopInfo the StopInfo superclass is extended with a m_extended_info field (it's a StructuredData::ObjectSP), that can hold arbitrary JSON-like data, which is the way the new plugin provides the report data the "thread info" command now accepts a "-s" flag that prints out the JSON data of a stop reason (same way the "-j" flag works now) SBThread has a new API, GetStopReasonExtendedInfoAsJSON, which dumps the JSON string into a SBStream adds a test case for all of this I plan to also get rid of the original ASan plugin (memory history stack traces) and use an instance of AddressSanitizerRuntime for that purpose. Kuba llvm-svn: 219546
2014-10-11 07:43:03 +08:00
};
typedef std::vector<InstrumentationRuntimeInstance>
InstrumentationRuntimeInstances;
static std::recursive_mutex &GetInstrumentationRuntimeMutex() {
static std::recursive_mutex g_instances_mutex;
return g_instances_mutex;
LLDB AddressSanitizer instrumentation runtime plugin, breakpint on error and report data extraction Reviewed at http://reviews.llvm.org/D5592 This patch gives LLDB some ability to interact with AddressSanitizer runtime library, on top of what we already have (historical memory stack traces provided by ASan). Namely, that's the ability to stop on an error caught by ASan, and access the report information that are associated with it. The report information is also exposed into SB API. More precisely this patch... adds a new plugin type, InstrumentationRuntime, which should serve as a generic superclass for other instrumentation runtime libraries, these plugins get notified when modules are loaded, so they get a chance to "activate" when a specific dynamic library is loaded an instance of this plugin type, AddressSanitizerRuntime, which activates itself when it sees the ASan dynamic library or founds ASan statically linked in the executable adds a collection of these plugins into the Process class AddressSanitizerRuntime sets an internal breakpoint on __asan::AsanDie(), and when this breakpoint gets hit, it retrieves the report information from ASan this breakpoint is then exposed as a new StopReason, eStopReasonInstrumentation, with a new StopInfo subclass, InstrumentationRuntimeStopInfo the StopInfo superclass is extended with a m_extended_info field (it's a StructuredData::ObjectSP), that can hold arbitrary JSON-like data, which is the way the new plugin provides the report data the "thread info" command now accepts a "-s" flag that prints out the JSON data of a stop reason (same way the "-j" flag works now) SBThread has a new API, GetStopReasonExtendedInfoAsJSON, which dumps the JSON string into a SBStream adds a test case for all of this I plan to also get rid of the original ASan plugin (memory history stack traces) and use an instance of AddressSanitizerRuntime for that purpose. Kuba llvm-svn: 219546
2014-10-11 07:43:03 +08:00
}
static InstrumentationRuntimeInstances &GetInstrumentationRuntimeInstances() {
static InstrumentationRuntimeInstances g_instances;
return g_instances;
}
bool PluginManager::RegisterPlugin(
const ConstString &name, const char *description,
InstrumentationRuntimeCreateInstance create_callback,
InstrumentationRuntimeGetType get_type_callback) {
if (create_callback) {
InstrumentationRuntimeInstance instance;
assert((bool)name);
instance.name = name;
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
instance.get_type_callback = get_type_callback;
std::lock_guard<std::recursive_mutex> guard(
GetInstrumentationRuntimeMutex());
GetInstrumentationRuntimeInstances().push_back(instance);
}
return false;
}
bool PluginManager::UnregisterPlugin(
InstrumentationRuntimeCreateInstance create_callback) {
if (create_callback) {
std::lock_guard<std::recursive_mutex> guard(
GetInstrumentationRuntimeMutex());
InstrumentationRuntimeInstances &instances =
GetInstrumentationRuntimeInstances();
InstrumentationRuntimeInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (pos->create_callback == create_callback) {
instances.erase(pos);
return true;
}
LLDB AddressSanitizer instrumentation runtime plugin, breakpint on error and report data extraction Reviewed at http://reviews.llvm.org/D5592 This patch gives LLDB some ability to interact with AddressSanitizer runtime library, on top of what we already have (historical memory stack traces provided by ASan). Namely, that's the ability to stop on an error caught by ASan, and access the report information that are associated with it. The report information is also exposed into SB API. More precisely this patch... adds a new plugin type, InstrumentationRuntime, which should serve as a generic superclass for other instrumentation runtime libraries, these plugins get notified when modules are loaded, so they get a chance to "activate" when a specific dynamic library is loaded an instance of this plugin type, AddressSanitizerRuntime, which activates itself when it sees the ASan dynamic library or founds ASan statically linked in the executable adds a collection of these plugins into the Process class AddressSanitizerRuntime sets an internal breakpoint on __asan::AsanDie(), and when this breakpoint gets hit, it retrieves the report information from ASan this breakpoint is then exposed as a new StopReason, eStopReasonInstrumentation, with a new StopInfo subclass, InstrumentationRuntimeStopInfo the StopInfo superclass is extended with a m_extended_info field (it's a StructuredData::ObjectSP), that can hold arbitrary JSON-like data, which is the way the new plugin provides the report data the "thread info" command now accepts a "-s" flag that prints out the JSON data of a stop reason (same way the "-j" flag works now) SBThread has a new API, GetStopReasonExtendedInfoAsJSON, which dumps the JSON string into a SBStream adds a test case for all of this I plan to also get rid of the original ASan plugin (memory history stack traces) and use an instance of AddressSanitizerRuntime for that purpose. Kuba llvm-svn: 219546
2014-10-11 07:43:03 +08:00
}
}
return false;
LLDB AddressSanitizer instrumentation runtime plugin, breakpint on error and report data extraction Reviewed at http://reviews.llvm.org/D5592 This patch gives LLDB some ability to interact with AddressSanitizer runtime library, on top of what we already have (historical memory stack traces provided by ASan). Namely, that's the ability to stop on an error caught by ASan, and access the report information that are associated with it. The report information is also exposed into SB API. More precisely this patch... adds a new plugin type, InstrumentationRuntime, which should serve as a generic superclass for other instrumentation runtime libraries, these plugins get notified when modules are loaded, so they get a chance to "activate" when a specific dynamic library is loaded an instance of this plugin type, AddressSanitizerRuntime, which activates itself when it sees the ASan dynamic library or founds ASan statically linked in the executable adds a collection of these plugins into the Process class AddressSanitizerRuntime sets an internal breakpoint on __asan::AsanDie(), and when this breakpoint gets hit, it retrieves the report information from ASan this breakpoint is then exposed as a new StopReason, eStopReasonInstrumentation, with a new StopInfo subclass, InstrumentationRuntimeStopInfo the StopInfo superclass is extended with a m_extended_info field (it's a StructuredData::ObjectSP), that can hold arbitrary JSON-like data, which is the way the new plugin provides the report data the "thread info" command now accepts a "-s" flag that prints out the JSON data of a stop reason (same way the "-j" flag works now) SBThread has a new API, GetStopReasonExtendedInfoAsJSON, which dumps the JSON string into a SBStream adds a test case for all of this I plan to also get rid of the original ASan plugin (memory history stack traces) and use an instance of AddressSanitizerRuntime for that purpose. Kuba llvm-svn: 219546
2014-10-11 07:43:03 +08:00
}
InstrumentationRuntimeGetType
PluginManager::GetInstrumentationRuntimeGetTypeCallbackAtIndex(uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(GetInstrumentationRuntimeMutex());
InstrumentationRuntimeInstances &instances =
GetInstrumentationRuntimeInstances();
if (idx < instances.size())
return instances[idx].get_type_callback;
return nullptr;
LLDB AddressSanitizer instrumentation runtime plugin, breakpint on error and report data extraction Reviewed at http://reviews.llvm.org/D5592 This patch gives LLDB some ability to interact with AddressSanitizer runtime library, on top of what we already have (historical memory stack traces provided by ASan). Namely, that's the ability to stop on an error caught by ASan, and access the report information that are associated with it. The report information is also exposed into SB API. More precisely this patch... adds a new plugin type, InstrumentationRuntime, which should serve as a generic superclass for other instrumentation runtime libraries, these plugins get notified when modules are loaded, so they get a chance to "activate" when a specific dynamic library is loaded an instance of this plugin type, AddressSanitizerRuntime, which activates itself when it sees the ASan dynamic library or founds ASan statically linked in the executable adds a collection of these plugins into the Process class AddressSanitizerRuntime sets an internal breakpoint on __asan::AsanDie(), and when this breakpoint gets hit, it retrieves the report information from ASan this breakpoint is then exposed as a new StopReason, eStopReasonInstrumentation, with a new StopInfo subclass, InstrumentationRuntimeStopInfo the StopInfo superclass is extended with a m_extended_info field (it's a StructuredData::ObjectSP), that can hold arbitrary JSON-like data, which is the way the new plugin provides the report data the "thread info" command now accepts a "-s" flag that prints out the JSON data of a stop reason (same way the "-j" flag works now) SBThread has a new API, GetStopReasonExtendedInfoAsJSON, which dumps the JSON string into a SBStream adds a test case for all of this I plan to also get rid of the original ASan plugin (memory history stack traces) and use an instance of AddressSanitizerRuntime for that purpose. Kuba llvm-svn: 219546
2014-10-11 07:43:03 +08:00
}
InstrumentationRuntimeCreateInstance
PluginManager::GetInstrumentationRuntimeCreateCallbackAtIndex(uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(GetInstrumentationRuntimeMutex());
InstrumentationRuntimeInstances &instances =
GetInstrumentationRuntimeInstances();
if (idx < instances.size())
return instances[idx].create_callback;
return nullptr;
LLDB AddressSanitizer instrumentation runtime plugin, breakpint on error and report data extraction Reviewed at http://reviews.llvm.org/D5592 This patch gives LLDB some ability to interact with AddressSanitizer runtime library, on top of what we already have (historical memory stack traces provided by ASan). Namely, that's the ability to stop on an error caught by ASan, and access the report information that are associated with it. The report information is also exposed into SB API. More precisely this patch... adds a new plugin type, InstrumentationRuntime, which should serve as a generic superclass for other instrumentation runtime libraries, these plugins get notified when modules are loaded, so they get a chance to "activate" when a specific dynamic library is loaded an instance of this plugin type, AddressSanitizerRuntime, which activates itself when it sees the ASan dynamic library or founds ASan statically linked in the executable adds a collection of these plugins into the Process class AddressSanitizerRuntime sets an internal breakpoint on __asan::AsanDie(), and when this breakpoint gets hit, it retrieves the report information from ASan this breakpoint is then exposed as a new StopReason, eStopReasonInstrumentation, with a new StopInfo subclass, InstrumentationRuntimeStopInfo the StopInfo superclass is extended with a m_extended_info field (it's a StructuredData::ObjectSP), that can hold arbitrary JSON-like data, which is the way the new plugin provides the report data the "thread info" command now accepts a "-s" flag that prints out the JSON data of a stop reason (same way the "-j" flag works now) SBThread has a new API, GetStopReasonExtendedInfoAsJSON, which dumps the JSON string into a SBStream adds a test case for all of this I plan to also get rid of the original ASan plugin (memory history stack traces) and use an instance of AddressSanitizerRuntime for that purpose. Kuba llvm-svn: 219546
2014-10-11 07:43:03 +08:00
}
InstrumentationRuntimeCreateInstance
PluginManager::GetInstrumentationRuntimeCreateCallbackForPluginName(
const ConstString &name) {
if (name) {
std::lock_guard<std::recursive_mutex> guard(
GetInstrumentationRuntimeMutex());
InstrumentationRuntimeInstances &instances =
GetInstrumentationRuntimeInstances();
InstrumentationRuntimeInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (name == pos->name)
return pos->create_callback;
LLDB AddressSanitizer instrumentation runtime plugin, breakpint on error and report data extraction Reviewed at http://reviews.llvm.org/D5592 This patch gives LLDB some ability to interact with AddressSanitizer runtime library, on top of what we already have (historical memory stack traces provided by ASan). Namely, that's the ability to stop on an error caught by ASan, and access the report information that are associated with it. The report information is also exposed into SB API. More precisely this patch... adds a new plugin type, InstrumentationRuntime, which should serve as a generic superclass for other instrumentation runtime libraries, these plugins get notified when modules are loaded, so they get a chance to "activate" when a specific dynamic library is loaded an instance of this plugin type, AddressSanitizerRuntime, which activates itself when it sees the ASan dynamic library or founds ASan statically linked in the executable adds a collection of these plugins into the Process class AddressSanitizerRuntime sets an internal breakpoint on __asan::AsanDie(), and when this breakpoint gets hit, it retrieves the report information from ASan this breakpoint is then exposed as a new StopReason, eStopReasonInstrumentation, with a new StopInfo subclass, InstrumentationRuntimeStopInfo the StopInfo superclass is extended with a m_extended_info field (it's a StructuredData::ObjectSP), that can hold arbitrary JSON-like data, which is the way the new plugin provides the report data the "thread info" command now accepts a "-s" flag that prints out the JSON data of a stop reason (same way the "-j" flag works now) SBThread has a new API, GetStopReasonExtendedInfoAsJSON, which dumps the JSON string into a SBStream adds a test case for all of this I plan to also get rid of the original ASan plugin (memory history stack traces) and use an instance of AddressSanitizerRuntime for that purpose. Kuba llvm-svn: 219546
2014-10-11 07:43:03 +08:00
}
}
return nullptr;
LLDB AddressSanitizer instrumentation runtime plugin, breakpint on error and report data extraction Reviewed at http://reviews.llvm.org/D5592 This patch gives LLDB some ability to interact with AddressSanitizer runtime library, on top of what we already have (historical memory stack traces provided by ASan). Namely, that's the ability to stop on an error caught by ASan, and access the report information that are associated with it. The report information is also exposed into SB API. More precisely this patch... adds a new plugin type, InstrumentationRuntime, which should serve as a generic superclass for other instrumentation runtime libraries, these plugins get notified when modules are loaded, so they get a chance to "activate" when a specific dynamic library is loaded an instance of this plugin type, AddressSanitizerRuntime, which activates itself when it sees the ASan dynamic library or founds ASan statically linked in the executable adds a collection of these plugins into the Process class AddressSanitizerRuntime sets an internal breakpoint on __asan::AsanDie(), and when this breakpoint gets hit, it retrieves the report information from ASan this breakpoint is then exposed as a new StopReason, eStopReasonInstrumentation, with a new StopInfo subclass, InstrumentationRuntimeStopInfo the StopInfo superclass is extended with a m_extended_info field (it's a StructuredData::ObjectSP), that can hold arbitrary JSON-like data, which is the way the new plugin provides the report data the "thread info" command now accepts a "-s" flag that prints out the JSON data of a stop reason (same way the "-j" flag works now) SBThread has a new API, GetStopReasonExtendedInfoAsJSON, which dumps the JSON string into a SBStream adds a test case for all of this I plan to also get rid of the original ASan plugin (memory history stack traces) and use an instance of AddressSanitizerRuntime for that purpose. Kuba llvm-svn: 219546
2014-10-11 07:43:03 +08:00
}
TypeSystem is now a plugin interface and removed any "ClangASTContext &Class::GetClangASTContext()" functions. This cleans up type systems to be more pluggable. Prior to this we had issues: - Module, SymbolFile, and many others has "ClangASTContext &GetClangASTContext()" functions. All have been switched over to use "TypeSystem *GetTypeSystemForLanguage()" - Cleaned up any places that were using the GetClangASTContext() functions to use TypeSystem - Cleaned up Module so that it no longer has dedicated type system member variables: lldb::ClangASTContextUP m_ast; ///< The Clang AST context for this module. lldb::GoASTContextUP m_go_ast; ///< The Go AST context for this module. Now we have a type system map: typedef std::map<lldb::LanguageType, lldb::TypeSystemSP> TypeSystemMap; TypeSystemMap m_type_system_map; ///< A map of any type systems associated with this module - Many places in code were using ClangASTContext static functions to place with CompilerType objects and add modifiers (const, volatile, restrict) and to make typedefs, L and R value references and more. These have been made into CompilerType functions that are abstract: class CompilerType { ... //---------------------------------------------------------------------- // Return a new CompilerType that is a L value reference to this type if // this type is valid and the type system supports L value references, // else return an invalid type. //---------------------------------------------------------------------- CompilerType GetLValueReferenceType () const; //---------------------------------------------------------------------- // Return a new CompilerType that is a R value reference to this type if // this type is valid and the type system supports R value references, // else return an invalid type. //---------------------------------------------------------------------- CompilerType GetRValueReferenceType () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a const modifier to this type if // this type is valid and the type system supports const modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddConstModifier () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a volatile modifier to this type if // this type is valid and the type system supports volatile modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddVolatileModifier () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a restrict modifier to this type if // this type is valid and the type system supports restrict modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddRestrictModifier () const; //---------------------------------------------------------------------- // Create a typedef to this type using "name" as the name of the typedef // this type is valid and the type system supports typedefs, else return // an invalid type. //---------------------------------------------------------------------- CompilerType CreateTypedef (const char *name, const CompilerDeclContext &decl_ctx) const; }; Other changes include: - Removed "CompilerType TypeSystem::GetIntTypeFromBitSize(...)" and CompilerType TypeSystem::GetFloatTypeFromBitSize(...) and replaced it with "CompilerType TypeSystem::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, size_t bit_size);" - Fixed code in Type.h to not request the full type for a type for no good reason, just request the forward type and let the type expand as needed llvm-svn: 247953
2015-09-18 06:23:34 +08:00
#pragma mark TypeSystem
struct TypeSystemInstance {
TypeSystemInstance() : name(), description(), create_callback(nullptr) {}
TypeSystem is now a plugin interface and removed any "ClangASTContext &Class::GetClangASTContext()" functions. This cleans up type systems to be more pluggable. Prior to this we had issues: - Module, SymbolFile, and many others has "ClangASTContext &GetClangASTContext()" functions. All have been switched over to use "TypeSystem *GetTypeSystemForLanguage()" - Cleaned up any places that were using the GetClangASTContext() functions to use TypeSystem - Cleaned up Module so that it no longer has dedicated type system member variables: lldb::ClangASTContextUP m_ast; ///< The Clang AST context for this module. lldb::GoASTContextUP m_go_ast; ///< The Go AST context for this module. Now we have a type system map: typedef std::map<lldb::LanguageType, lldb::TypeSystemSP> TypeSystemMap; TypeSystemMap m_type_system_map; ///< A map of any type systems associated with this module - Many places in code were using ClangASTContext static functions to place with CompilerType objects and add modifiers (const, volatile, restrict) and to make typedefs, L and R value references and more. These have been made into CompilerType functions that are abstract: class CompilerType { ... //---------------------------------------------------------------------- // Return a new CompilerType that is a L value reference to this type if // this type is valid and the type system supports L value references, // else return an invalid type. //---------------------------------------------------------------------- CompilerType GetLValueReferenceType () const; //---------------------------------------------------------------------- // Return a new CompilerType that is a R value reference to this type if // this type is valid and the type system supports R value references, // else return an invalid type. //---------------------------------------------------------------------- CompilerType GetRValueReferenceType () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a const modifier to this type if // this type is valid and the type system supports const modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddConstModifier () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a volatile modifier to this type if // this type is valid and the type system supports volatile modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddVolatileModifier () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a restrict modifier to this type if // this type is valid and the type system supports restrict modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddRestrictModifier () const; //---------------------------------------------------------------------- // Create a typedef to this type using "name" as the name of the typedef // this type is valid and the type system supports typedefs, else return // an invalid type. //---------------------------------------------------------------------- CompilerType CreateTypedef (const char *name, const CompilerDeclContext &decl_ctx) const; }; Other changes include: - Removed "CompilerType TypeSystem::GetIntTypeFromBitSize(...)" and CompilerType TypeSystem::GetFloatTypeFromBitSize(...) and replaced it with "CompilerType TypeSystem::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, size_t bit_size);" - Fixed code in Type.h to not request the full type for a type for no good reason, just request the forward type and let the type expand as needed llvm-svn: 247953
2015-09-18 06:23:34 +08:00
ConstString name;
std::string description;
TypeSystemCreateInstance create_callback;
TypeSystemEnumerateSupportedLanguages enumerate_callback;
TypeSystem is now a plugin interface and removed any "ClangASTContext &Class::GetClangASTContext()" functions. This cleans up type systems to be more pluggable. Prior to this we had issues: - Module, SymbolFile, and many others has "ClangASTContext &GetClangASTContext()" functions. All have been switched over to use "TypeSystem *GetTypeSystemForLanguage()" - Cleaned up any places that were using the GetClangASTContext() functions to use TypeSystem - Cleaned up Module so that it no longer has dedicated type system member variables: lldb::ClangASTContextUP m_ast; ///< The Clang AST context for this module. lldb::GoASTContextUP m_go_ast; ///< The Go AST context for this module. Now we have a type system map: typedef std::map<lldb::LanguageType, lldb::TypeSystemSP> TypeSystemMap; TypeSystemMap m_type_system_map; ///< A map of any type systems associated with this module - Many places in code were using ClangASTContext static functions to place with CompilerType objects and add modifiers (const, volatile, restrict) and to make typedefs, L and R value references and more. These have been made into CompilerType functions that are abstract: class CompilerType { ... //---------------------------------------------------------------------- // Return a new CompilerType that is a L value reference to this type if // this type is valid and the type system supports L value references, // else return an invalid type. //---------------------------------------------------------------------- CompilerType GetLValueReferenceType () const; //---------------------------------------------------------------------- // Return a new CompilerType that is a R value reference to this type if // this type is valid and the type system supports R value references, // else return an invalid type. //---------------------------------------------------------------------- CompilerType GetRValueReferenceType () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a const modifier to this type if // this type is valid and the type system supports const modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddConstModifier () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a volatile modifier to this type if // this type is valid and the type system supports volatile modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddVolatileModifier () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a restrict modifier to this type if // this type is valid and the type system supports restrict modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddRestrictModifier () const; //---------------------------------------------------------------------- // Create a typedef to this type using "name" as the name of the typedef // this type is valid and the type system supports typedefs, else return // an invalid type. //---------------------------------------------------------------------- CompilerType CreateTypedef (const char *name, const CompilerDeclContext &decl_ctx) const; }; Other changes include: - Removed "CompilerType TypeSystem::GetIntTypeFromBitSize(...)" and CompilerType TypeSystem::GetFloatTypeFromBitSize(...) and replaced it with "CompilerType TypeSystem::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, size_t bit_size);" - Fixed code in Type.h to not request the full type for a type for no good reason, just request the forward type and let the type expand as needed llvm-svn: 247953
2015-09-18 06:23:34 +08:00
};
typedef std::vector<TypeSystemInstance> TypeSystemInstances;
static std::recursive_mutex &GetTypeSystemMutex() {
static std::recursive_mutex g_instances_mutex;
return g_instances_mutex;
TypeSystem is now a plugin interface and removed any "ClangASTContext &Class::GetClangASTContext()" functions. This cleans up type systems to be more pluggable. Prior to this we had issues: - Module, SymbolFile, and many others has "ClangASTContext &GetClangASTContext()" functions. All have been switched over to use "TypeSystem *GetTypeSystemForLanguage()" - Cleaned up any places that were using the GetClangASTContext() functions to use TypeSystem - Cleaned up Module so that it no longer has dedicated type system member variables: lldb::ClangASTContextUP m_ast; ///< The Clang AST context for this module. lldb::GoASTContextUP m_go_ast; ///< The Go AST context for this module. Now we have a type system map: typedef std::map<lldb::LanguageType, lldb::TypeSystemSP> TypeSystemMap; TypeSystemMap m_type_system_map; ///< A map of any type systems associated with this module - Many places in code were using ClangASTContext static functions to place with CompilerType objects and add modifiers (const, volatile, restrict) and to make typedefs, L and R value references and more. These have been made into CompilerType functions that are abstract: class CompilerType { ... //---------------------------------------------------------------------- // Return a new CompilerType that is a L value reference to this type if // this type is valid and the type system supports L value references, // else return an invalid type. //---------------------------------------------------------------------- CompilerType GetLValueReferenceType () const; //---------------------------------------------------------------------- // Return a new CompilerType that is a R value reference to this type if // this type is valid and the type system supports R value references, // else return an invalid type. //---------------------------------------------------------------------- CompilerType GetRValueReferenceType () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a const modifier to this type if // this type is valid and the type system supports const modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddConstModifier () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a volatile modifier to this type if // this type is valid and the type system supports volatile modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddVolatileModifier () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a restrict modifier to this type if // this type is valid and the type system supports restrict modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddRestrictModifier () const; //---------------------------------------------------------------------- // Create a typedef to this type using "name" as the name of the typedef // this type is valid and the type system supports typedefs, else return // an invalid type. //---------------------------------------------------------------------- CompilerType CreateTypedef (const char *name, const CompilerDeclContext &decl_ctx) const; }; Other changes include: - Removed "CompilerType TypeSystem::GetIntTypeFromBitSize(...)" and CompilerType TypeSystem::GetFloatTypeFromBitSize(...) and replaced it with "CompilerType TypeSystem::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, size_t bit_size);" - Fixed code in Type.h to not request the full type for a type for no good reason, just request the forward type and let the type expand as needed llvm-svn: 247953
2015-09-18 06:23:34 +08:00
}
static TypeSystemInstances &GetTypeSystemInstances() {
static TypeSystemInstances g_instances;
return g_instances;
}
bool PluginManager::RegisterPlugin(const ConstString &name,
const char *description,
TypeSystemCreateInstance create_callback,
TypeSystemEnumerateSupportedLanguages
enumerate_supported_languages_callback) {
if (create_callback) {
TypeSystemInstance instance;
assert((bool)name);
instance.name = name;
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
instance.enumerate_callback = enumerate_supported_languages_callback;
std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex());
GetTypeSystemInstances().push_back(instance);
}
return false;
}
bool PluginManager::UnregisterPlugin(TypeSystemCreateInstance create_callback) {
if (create_callback) {
std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex());
TypeSystemInstances &instances = GetTypeSystemInstances();
TypeSystemInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (pos->create_callback == create_callback) {
instances.erase(pos);
return true;
}
TypeSystem is now a plugin interface and removed any "ClangASTContext &Class::GetClangASTContext()" functions. This cleans up type systems to be more pluggable. Prior to this we had issues: - Module, SymbolFile, and many others has "ClangASTContext &GetClangASTContext()" functions. All have been switched over to use "TypeSystem *GetTypeSystemForLanguage()" - Cleaned up any places that were using the GetClangASTContext() functions to use TypeSystem - Cleaned up Module so that it no longer has dedicated type system member variables: lldb::ClangASTContextUP m_ast; ///< The Clang AST context for this module. lldb::GoASTContextUP m_go_ast; ///< The Go AST context for this module. Now we have a type system map: typedef std::map<lldb::LanguageType, lldb::TypeSystemSP> TypeSystemMap; TypeSystemMap m_type_system_map; ///< A map of any type systems associated with this module - Many places in code were using ClangASTContext static functions to place with CompilerType objects and add modifiers (const, volatile, restrict) and to make typedefs, L and R value references and more. These have been made into CompilerType functions that are abstract: class CompilerType { ... //---------------------------------------------------------------------- // Return a new CompilerType that is a L value reference to this type if // this type is valid and the type system supports L value references, // else return an invalid type. //---------------------------------------------------------------------- CompilerType GetLValueReferenceType () const; //---------------------------------------------------------------------- // Return a new CompilerType that is a R value reference to this type if // this type is valid and the type system supports R value references, // else return an invalid type. //---------------------------------------------------------------------- CompilerType GetRValueReferenceType () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a const modifier to this type if // this type is valid and the type system supports const modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddConstModifier () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a volatile modifier to this type if // this type is valid and the type system supports volatile modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddVolatileModifier () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a restrict modifier to this type if // this type is valid and the type system supports restrict modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddRestrictModifier () const; //---------------------------------------------------------------------- // Create a typedef to this type using "name" as the name of the typedef // this type is valid and the type system supports typedefs, else return // an invalid type. //---------------------------------------------------------------------- CompilerType CreateTypedef (const char *name, const CompilerDeclContext &decl_ctx) const; }; Other changes include: - Removed "CompilerType TypeSystem::GetIntTypeFromBitSize(...)" and CompilerType TypeSystem::GetFloatTypeFromBitSize(...) and replaced it with "CompilerType TypeSystem::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, size_t bit_size);" - Fixed code in Type.h to not request the full type for a type for no good reason, just request the forward type and let the type expand as needed llvm-svn: 247953
2015-09-18 06:23:34 +08:00
}
}
return false;
TypeSystem is now a plugin interface and removed any "ClangASTContext &Class::GetClangASTContext()" functions. This cleans up type systems to be more pluggable. Prior to this we had issues: - Module, SymbolFile, and many others has "ClangASTContext &GetClangASTContext()" functions. All have been switched over to use "TypeSystem *GetTypeSystemForLanguage()" - Cleaned up any places that were using the GetClangASTContext() functions to use TypeSystem - Cleaned up Module so that it no longer has dedicated type system member variables: lldb::ClangASTContextUP m_ast; ///< The Clang AST context for this module. lldb::GoASTContextUP m_go_ast; ///< The Go AST context for this module. Now we have a type system map: typedef std::map<lldb::LanguageType, lldb::TypeSystemSP> TypeSystemMap; TypeSystemMap m_type_system_map; ///< A map of any type systems associated with this module - Many places in code were using ClangASTContext static functions to place with CompilerType objects and add modifiers (const, volatile, restrict) and to make typedefs, L and R value references and more. These have been made into CompilerType functions that are abstract: class CompilerType { ... //---------------------------------------------------------------------- // Return a new CompilerType that is a L value reference to this type if // this type is valid and the type system supports L value references, // else return an invalid type. //---------------------------------------------------------------------- CompilerType GetLValueReferenceType () const; //---------------------------------------------------------------------- // Return a new CompilerType that is a R value reference to this type if // this type is valid and the type system supports R value references, // else return an invalid type. //---------------------------------------------------------------------- CompilerType GetRValueReferenceType () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a const modifier to this type if // this type is valid and the type system supports const modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddConstModifier () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a volatile modifier to this type if // this type is valid and the type system supports volatile modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddVolatileModifier () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a restrict modifier to this type if // this type is valid and the type system supports restrict modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddRestrictModifier () const; //---------------------------------------------------------------------- // Create a typedef to this type using "name" as the name of the typedef // this type is valid and the type system supports typedefs, else return // an invalid type. //---------------------------------------------------------------------- CompilerType CreateTypedef (const char *name, const CompilerDeclContext &decl_ctx) const; }; Other changes include: - Removed "CompilerType TypeSystem::GetIntTypeFromBitSize(...)" and CompilerType TypeSystem::GetFloatTypeFromBitSize(...) and replaced it with "CompilerType TypeSystem::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, size_t bit_size);" - Fixed code in Type.h to not request the full type for a type for no good reason, just request the forward type and let the type expand as needed llvm-svn: 247953
2015-09-18 06:23:34 +08:00
}
TypeSystemCreateInstance
PluginManager::GetTypeSystemCreateCallbackAtIndex(uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex());
TypeSystemInstances &instances = GetTypeSystemInstances();
if (idx < instances.size())
return instances[idx].create_callback;
return nullptr;
TypeSystem is now a plugin interface and removed any "ClangASTContext &Class::GetClangASTContext()" functions. This cleans up type systems to be more pluggable. Prior to this we had issues: - Module, SymbolFile, and many others has "ClangASTContext &GetClangASTContext()" functions. All have been switched over to use "TypeSystem *GetTypeSystemForLanguage()" - Cleaned up any places that were using the GetClangASTContext() functions to use TypeSystem - Cleaned up Module so that it no longer has dedicated type system member variables: lldb::ClangASTContextUP m_ast; ///< The Clang AST context for this module. lldb::GoASTContextUP m_go_ast; ///< The Go AST context for this module. Now we have a type system map: typedef std::map<lldb::LanguageType, lldb::TypeSystemSP> TypeSystemMap; TypeSystemMap m_type_system_map; ///< A map of any type systems associated with this module - Many places in code were using ClangASTContext static functions to place with CompilerType objects and add modifiers (const, volatile, restrict) and to make typedefs, L and R value references and more. These have been made into CompilerType functions that are abstract: class CompilerType { ... //---------------------------------------------------------------------- // Return a new CompilerType that is a L value reference to this type if // this type is valid and the type system supports L value references, // else return an invalid type. //---------------------------------------------------------------------- CompilerType GetLValueReferenceType () const; //---------------------------------------------------------------------- // Return a new CompilerType that is a R value reference to this type if // this type is valid and the type system supports R value references, // else return an invalid type. //---------------------------------------------------------------------- CompilerType GetRValueReferenceType () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a const modifier to this type if // this type is valid and the type system supports const modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddConstModifier () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a volatile modifier to this type if // this type is valid and the type system supports volatile modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddVolatileModifier () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a restrict modifier to this type if // this type is valid and the type system supports restrict modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddRestrictModifier () const; //---------------------------------------------------------------------- // Create a typedef to this type using "name" as the name of the typedef // this type is valid and the type system supports typedefs, else return // an invalid type. //---------------------------------------------------------------------- CompilerType CreateTypedef (const char *name, const CompilerDeclContext &decl_ctx) const; }; Other changes include: - Removed "CompilerType TypeSystem::GetIntTypeFromBitSize(...)" and CompilerType TypeSystem::GetFloatTypeFromBitSize(...) and replaced it with "CompilerType TypeSystem::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, size_t bit_size);" - Fixed code in Type.h to not request the full type for a type for no good reason, just request the forward type and let the type expand as needed llvm-svn: 247953
2015-09-18 06:23:34 +08:00
}
TypeSystemCreateInstance
PluginManager::GetTypeSystemCreateCallbackForPluginName(
const ConstString &name) {
if (name) {
std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex());
TypeSystemInstances &instances = GetTypeSystemInstances();
TypeSystemInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (name == pos->name)
return pos->create_callback;
TypeSystem is now a plugin interface and removed any "ClangASTContext &Class::GetClangASTContext()" functions. This cleans up type systems to be more pluggable. Prior to this we had issues: - Module, SymbolFile, and many others has "ClangASTContext &GetClangASTContext()" functions. All have been switched over to use "TypeSystem *GetTypeSystemForLanguage()" - Cleaned up any places that were using the GetClangASTContext() functions to use TypeSystem - Cleaned up Module so that it no longer has dedicated type system member variables: lldb::ClangASTContextUP m_ast; ///< The Clang AST context for this module. lldb::GoASTContextUP m_go_ast; ///< The Go AST context for this module. Now we have a type system map: typedef std::map<lldb::LanguageType, lldb::TypeSystemSP> TypeSystemMap; TypeSystemMap m_type_system_map; ///< A map of any type systems associated with this module - Many places in code were using ClangASTContext static functions to place with CompilerType objects and add modifiers (const, volatile, restrict) and to make typedefs, L and R value references and more. These have been made into CompilerType functions that are abstract: class CompilerType { ... //---------------------------------------------------------------------- // Return a new CompilerType that is a L value reference to this type if // this type is valid and the type system supports L value references, // else return an invalid type. //---------------------------------------------------------------------- CompilerType GetLValueReferenceType () const; //---------------------------------------------------------------------- // Return a new CompilerType that is a R value reference to this type if // this type is valid and the type system supports R value references, // else return an invalid type. //---------------------------------------------------------------------- CompilerType GetRValueReferenceType () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a const modifier to this type if // this type is valid and the type system supports const modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddConstModifier () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a volatile modifier to this type if // this type is valid and the type system supports volatile modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddVolatileModifier () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a restrict modifier to this type if // this type is valid and the type system supports restrict modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddRestrictModifier () const; //---------------------------------------------------------------------- // Create a typedef to this type using "name" as the name of the typedef // this type is valid and the type system supports typedefs, else return // an invalid type. //---------------------------------------------------------------------- CompilerType CreateTypedef (const char *name, const CompilerDeclContext &decl_ctx) const; }; Other changes include: - Removed "CompilerType TypeSystem::GetIntTypeFromBitSize(...)" and CompilerType TypeSystem::GetFloatTypeFromBitSize(...) and replaced it with "CompilerType TypeSystem::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, size_t bit_size);" - Fixed code in Type.h to not request the full type for a type for no good reason, just request the forward type and let the type expand as needed llvm-svn: 247953
2015-09-18 06:23:34 +08:00
}
}
return nullptr;
TypeSystem is now a plugin interface and removed any "ClangASTContext &Class::GetClangASTContext()" functions. This cleans up type systems to be more pluggable. Prior to this we had issues: - Module, SymbolFile, and many others has "ClangASTContext &GetClangASTContext()" functions. All have been switched over to use "TypeSystem *GetTypeSystemForLanguage()" - Cleaned up any places that were using the GetClangASTContext() functions to use TypeSystem - Cleaned up Module so that it no longer has dedicated type system member variables: lldb::ClangASTContextUP m_ast; ///< The Clang AST context for this module. lldb::GoASTContextUP m_go_ast; ///< The Go AST context for this module. Now we have a type system map: typedef std::map<lldb::LanguageType, lldb::TypeSystemSP> TypeSystemMap; TypeSystemMap m_type_system_map; ///< A map of any type systems associated with this module - Many places in code were using ClangASTContext static functions to place with CompilerType objects and add modifiers (const, volatile, restrict) and to make typedefs, L and R value references and more. These have been made into CompilerType functions that are abstract: class CompilerType { ... //---------------------------------------------------------------------- // Return a new CompilerType that is a L value reference to this type if // this type is valid and the type system supports L value references, // else return an invalid type. //---------------------------------------------------------------------- CompilerType GetLValueReferenceType () const; //---------------------------------------------------------------------- // Return a new CompilerType that is a R value reference to this type if // this type is valid and the type system supports R value references, // else return an invalid type. //---------------------------------------------------------------------- CompilerType GetRValueReferenceType () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a const modifier to this type if // this type is valid and the type system supports const modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddConstModifier () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a volatile modifier to this type if // this type is valid and the type system supports volatile modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddVolatileModifier () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a restrict modifier to this type if // this type is valid and the type system supports restrict modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddRestrictModifier () const; //---------------------------------------------------------------------- // Create a typedef to this type using "name" as the name of the typedef // this type is valid and the type system supports typedefs, else return // an invalid type. //---------------------------------------------------------------------- CompilerType CreateTypedef (const char *name, const CompilerDeclContext &decl_ctx) const; }; Other changes include: - Removed "CompilerType TypeSystem::GetIntTypeFromBitSize(...)" and CompilerType TypeSystem::GetFloatTypeFromBitSize(...) and replaced it with "CompilerType TypeSystem::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, size_t bit_size);" - Fixed code in Type.h to not request the full type for a type for no good reason, just request the forward type and let the type expand as needed llvm-svn: 247953
2015-09-18 06:23:34 +08:00
}
TypeSystemEnumerateSupportedLanguages
PluginManager::GetTypeSystemEnumerateSupportedLanguagesCallbackAtIndex(
uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex());
TypeSystemInstances &instances = GetTypeSystemInstances();
if (idx < instances.size())
return instances[idx].enumerate_callback;
return nullptr;
}
TypeSystemEnumerateSupportedLanguages
PluginManager::GetTypeSystemEnumerateSupportedLanguagesCallbackForPluginName(
const ConstString &name) {
if (name) {
std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex());
TypeSystemInstances &instances = GetTypeSystemInstances();
TypeSystemInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (name == pos->name)
return pos->enumerate_callback;
}
}
return nullptr;
}
TypeSystem is now a plugin interface and removed any "ClangASTContext &Class::GetClangASTContext()" functions. This cleans up type systems to be more pluggable. Prior to this we had issues: - Module, SymbolFile, and many others has "ClangASTContext &GetClangASTContext()" functions. All have been switched over to use "TypeSystem *GetTypeSystemForLanguage()" - Cleaned up any places that were using the GetClangASTContext() functions to use TypeSystem - Cleaned up Module so that it no longer has dedicated type system member variables: lldb::ClangASTContextUP m_ast; ///< The Clang AST context for this module. lldb::GoASTContextUP m_go_ast; ///< The Go AST context for this module. Now we have a type system map: typedef std::map<lldb::LanguageType, lldb::TypeSystemSP> TypeSystemMap; TypeSystemMap m_type_system_map; ///< A map of any type systems associated with this module - Many places in code were using ClangASTContext static functions to place with CompilerType objects and add modifiers (const, volatile, restrict) and to make typedefs, L and R value references and more. These have been made into CompilerType functions that are abstract: class CompilerType { ... //---------------------------------------------------------------------- // Return a new CompilerType that is a L value reference to this type if // this type is valid and the type system supports L value references, // else return an invalid type. //---------------------------------------------------------------------- CompilerType GetLValueReferenceType () const; //---------------------------------------------------------------------- // Return a new CompilerType that is a R value reference to this type if // this type is valid and the type system supports R value references, // else return an invalid type. //---------------------------------------------------------------------- CompilerType GetRValueReferenceType () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a const modifier to this type if // this type is valid and the type system supports const modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddConstModifier () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a volatile modifier to this type if // this type is valid and the type system supports volatile modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddVolatileModifier () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a restrict modifier to this type if // this type is valid and the type system supports restrict modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddRestrictModifier () const; //---------------------------------------------------------------------- // Create a typedef to this type using "name" as the name of the typedef // this type is valid and the type system supports typedefs, else return // an invalid type. //---------------------------------------------------------------------- CompilerType CreateTypedef (const char *name, const CompilerDeclContext &decl_ctx) const; }; Other changes include: - Removed "CompilerType TypeSystem::GetIntTypeFromBitSize(...)" and CompilerType TypeSystem::GetFloatTypeFromBitSize(...) and replaced it with "CompilerType TypeSystem::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, size_t bit_size);" - Fixed code in Type.h to not request the full type for a type for no good reason, just request the forward type and let the type expand as needed llvm-svn: 247953
2015-09-18 06:23:34 +08:00
#pragma mark REPL
struct REPLInstance {
REPLInstance() : name(), description(), create_callback(nullptr) {}
ConstString name;
std::string description;
REPLCreateInstance create_callback;
REPLEnumerateSupportedLanguages enumerate_languages_callback;
};
typedef std::vector<REPLInstance> REPLInstances;
static std::recursive_mutex &GetREPLMutex() {
static std::recursive_mutex g_instances_mutex;
return g_instances_mutex;
}
static REPLInstances &GetREPLInstances() {
static REPLInstances g_instances;
return g_instances;
}
bool PluginManager::RegisterPlugin(
const ConstString &name, const char *description,
REPLCreateInstance create_callback,
REPLEnumerateSupportedLanguages enumerate_languages_callback) {
if (create_callback) {
REPLInstance instance;
assert((bool)name);
instance.name = name;
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
instance.enumerate_languages_callback = enumerate_languages_callback;
std::lock_guard<std::recursive_mutex> guard(GetREPLMutex());
GetREPLInstances().push_back(instance);
}
return false;
}
bool PluginManager::UnregisterPlugin(REPLCreateInstance create_callback) {
if (create_callback) {
std::lock_guard<std::recursive_mutex> guard(GetREPLMutex());
REPLInstances &instances = GetREPLInstances();
REPLInstances::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;
}
REPLCreateInstance PluginManager::GetREPLCreateCallbackAtIndex(uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(GetREPLMutex());
REPLInstances &instances = GetREPLInstances();
if (idx < instances.size())
return instances[idx].create_callback;
return nullptr;
}
REPLCreateInstance
PluginManager::GetREPLCreateCallbackForPluginName(const ConstString &name) {
if (name) {
std::lock_guard<std::recursive_mutex> guard(GetREPLMutex());
REPLInstances &instances = GetREPLInstances();
REPLInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (name == pos->name)
return pos->create_callback;
}
}
return nullptr;
}
REPLEnumerateSupportedLanguages
PluginManager::GetREPLEnumerateSupportedLanguagesCallbackAtIndex(uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(GetREPLMutex());
REPLInstances &instances = GetREPLInstances();
if (idx < instances.size())
return instances[idx].enumerate_languages_callback;
return nullptr;
}
REPLEnumerateSupportedLanguages
PluginManager::GetREPLSystemEnumerateSupportedLanguagesCallbackForPluginName(
const ConstString &name) {
if (name) {
std::lock_guard<std::recursive_mutex> guard(GetREPLMutex());
REPLInstances &instances = GetREPLInstances();
REPLInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (name == pos->name)
return pos->enumerate_languages_callback;
}
}
return nullptr;
}
LLDB AddressSanitizer instrumentation runtime plugin, breakpint on error and report data extraction Reviewed at http://reviews.llvm.org/D5592 This patch gives LLDB some ability to interact with AddressSanitizer runtime library, on top of what we already have (historical memory stack traces provided by ASan). Namely, that's the ability to stop on an error caught by ASan, and access the report information that are associated with it. The report information is also exposed into SB API. More precisely this patch... adds a new plugin type, InstrumentationRuntime, which should serve as a generic superclass for other instrumentation runtime libraries, these plugins get notified when modules are loaded, so they get a chance to "activate" when a specific dynamic library is loaded an instance of this plugin type, AddressSanitizerRuntime, which activates itself when it sees the ASan dynamic library or founds ASan statically linked in the executable adds a collection of these plugins into the Process class AddressSanitizerRuntime sets an internal breakpoint on __asan::AsanDie(), and when this breakpoint gets hit, it retrieves the report information from ASan this breakpoint is then exposed as a new StopReason, eStopReasonInstrumentation, with a new StopInfo subclass, InstrumentationRuntimeStopInfo the StopInfo superclass is extended with a m_extended_info field (it's a StructuredData::ObjectSP), that can hold arbitrary JSON-like data, which is the way the new plugin provides the report data the "thread info" command now accepts a "-s" flag that prints out the JSON data of a stop reason (same way the "-j" flag works now) SBThread has a new API, GetStopReasonExtendedInfoAsJSON, which dumps the JSON string into a SBStream adds a test case for all of this I plan to also get rid of the original ASan plugin (memory history stack traces) and use an instance of AddressSanitizerRuntime for that purpose. Kuba llvm-svn: 219546
2014-10-11 07:43:03 +08:00
#pragma mark PluginManager
void PluginManager::DebuggerInitialize(Debugger &debugger) {
// Initialize the DynamicLoader plugins
{
std::lock_guard<std::recursive_mutex> guard(GetDynamicLoaderMutex());
DynamicLoaderInstances &instances = GetDynamicLoaderInstances();
DynamicLoaderInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (pos->debugger_init_callback)
pos->debugger_init_callback(debugger);
}
}
// Initialize the JITLoader plugins
{
std::lock_guard<std::recursive_mutex> guard(GetJITLoaderMutex());
JITLoaderInstances &instances = GetJITLoaderInstances();
JITLoaderInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (pos->debugger_init_callback)
pos->debugger_init_callback(debugger);
}
}
// Initialize the Platform plugins
{
std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex());
PlatformInstances &instances = GetPlatformInstances();
PlatformInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (pos->debugger_init_callback)
pos->debugger_init_callback(debugger);
}
}
// Initialize the Process plugins
{
std::lock_guard<std::recursive_mutex> guard(GetProcessMutex());
ProcessInstances &instances = GetProcessInstances();
ProcessInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++pos) {
if (pos->debugger_init_callback)
pos->debugger_init_callback(debugger);
}
}
// Initialize the SymbolFile plugins
{
std::lock_guard<std::recursive_mutex> guard(GetSymbolFileMutex());
for (auto &sym_file : GetSymbolFileInstances()) {
if (sym_file.debugger_init_callback)
sym_file.debugger_init_callback(debugger);
}
}
// Initialize the OperatingSystem plugins
{
std::lock_guard<std::recursive_mutex> guard(GetOperatingSystemMutex());
for (auto &os : GetOperatingSystemInstances()) {
if (os.debugger_init_callback)
os.debugger_init_callback(debugger);
}
}
// Initialize the StructuredDataPlugin plugins
{
std::lock_guard<std::recursive_mutex> guard(GetStructuredDataPluginMutex());
for (auto &plugin : GetStructuredDataPluginInstances()) {
if (plugin.debugger_init_callback)
plugin.debugger_init_callback(debugger);
}
}
}
// This is the preferred new way to register plugin specific settings. e.g.
// This will put a plugin's settings under e.g.
// "plugin.<plugin_type_name>.<plugin_type_desc>.SETTINGNAME".
static lldb::OptionValuePropertiesSP GetDebuggerPropertyForPlugins(
Debugger &debugger, const ConstString &plugin_type_name,
const ConstString &plugin_type_desc, bool can_create) {
lldb::OptionValuePropertiesSP parent_properties_sp(
debugger.GetValueProperties());
if (parent_properties_sp) {
static ConstString g_property_name("plugin");
OptionValuePropertiesSP plugin_properties_sp =
parent_properties_sp->GetSubProperty(nullptr, g_property_name);
if (!plugin_properties_sp && can_create) {
plugin_properties_sp.reset(new OptionValueProperties(g_property_name));
parent_properties_sp->AppendProperty(
g_property_name, ConstString("Settings specify to plugins."), true,
plugin_properties_sp);
}
if (plugin_properties_sp) {
lldb::OptionValuePropertiesSP plugin_type_properties_sp =
plugin_properties_sp->GetSubProperty(nullptr, plugin_type_name);
if (!plugin_type_properties_sp && can_create) {
plugin_type_properties_sp.reset(
new OptionValueProperties(plugin_type_name));
plugin_properties_sp->AppendProperty(plugin_type_name, plugin_type_desc,
true, plugin_type_properties_sp);
}
return plugin_type_properties_sp;
}
}
return lldb::OptionValuePropertiesSP();
}
// This is deprecated way to register plugin specific settings. e.g.
// "<plugin_type_name>.plugin.<plugin_type_desc>.SETTINGNAME"
// and Platform generic settings would be under "platform.SETTINGNAME".
static lldb::OptionValuePropertiesSP GetDebuggerPropertyForPluginsOldStyle(
Debugger &debugger, const ConstString &plugin_type_name,
const ConstString &plugin_type_desc, bool can_create) {
static ConstString g_property_name("plugin");
lldb::OptionValuePropertiesSP parent_properties_sp(
debugger.GetValueProperties());
if (parent_properties_sp) {
OptionValuePropertiesSP plugin_properties_sp =
parent_properties_sp->GetSubProperty(nullptr, plugin_type_name);
if (!plugin_properties_sp && can_create) {
plugin_properties_sp.reset(new OptionValueProperties(plugin_type_name));
parent_properties_sp->AppendProperty(plugin_type_name, plugin_type_desc,
true, plugin_properties_sp);
}
if (plugin_properties_sp) {
lldb::OptionValuePropertiesSP plugin_type_properties_sp =
plugin_properties_sp->GetSubProperty(nullptr, g_property_name);
if (!plugin_type_properties_sp && can_create) {
plugin_type_properties_sp.reset(
new OptionValueProperties(g_property_name));
plugin_properties_sp->AppendProperty(
g_property_name, ConstString("Settings specific to plugins"), true,
plugin_type_properties_sp);
}
return plugin_type_properties_sp;
}
}
return lldb::OptionValuePropertiesSP();
}
namespace {
typedef lldb::OptionValuePropertiesSP
GetDebuggerPropertyForPluginsPtr(Debugger &, const ConstString &,
const ConstString &, bool can_create);
lldb::OptionValuePropertiesSP
GetSettingForPlugin(Debugger &debugger, const ConstString &setting_name,
const ConstString &plugin_type_name,
GetDebuggerPropertyForPluginsPtr get_debugger_property =
GetDebuggerPropertyForPlugins) {
lldb::OptionValuePropertiesSP properties_sp;
lldb::OptionValuePropertiesSP plugin_type_properties_sp(get_debugger_property(
debugger, plugin_type_name,
ConstString(), // not creating to so we don't need the description
false));
if (plugin_type_properties_sp)
properties_sp =
plugin_type_properties_sp->GetSubProperty(nullptr, setting_name);
return properties_sp;
}
bool CreateSettingForPlugin(
Debugger &debugger, const ConstString &plugin_type_name,
const ConstString &plugin_type_desc,
const lldb::OptionValuePropertiesSP &properties_sp,
const ConstString &description, bool is_global_property,
GetDebuggerPropertyForPluginsPtr get_debugger_property =
GetDebuggerPropertyForPlugins) {
if (properties_sp) {
lldb::OptionValuePropertiesSP plugin_type_properties_sp(
get_debugger_property(debugger, plugin_type_name, plugin_type_desc,
true));
if (plugin_type_properties_sp) {
plugin_type_properties_sp->AppendProperty(properties_sp->GetName(),
description, is_global_property,
properties_sp);
return true;
}
}
return false;
}
const char *kDynamicLoaderPluginName("dynamic-loader");
const char *kPlatformPluginName("platform");
const char *kProcessPluginName("process");
const char *kSymbolFilePluginName("symbol-file");
const char *kJITLoaderPluginName("jit-loader");
const char *kStructuredDataPluginName("structured-data");
} // anonymous namespace
lldb::OptionValuePropertiesSP PluginManager::GetSettingForDynamicLoaderPlugin(
Debugger &debugger, const ConstString &setting_name) {
return GetSettingForPlugin(debugger, setting_name,
ConstString(kDynamicLoaderPluginName));
}
bool PluginManager::CreateSettingForDynamicLoaderPlugin(
Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
const ConstString &description, bool is_global_property) {
return CreateSettingForPlugin(
debugger, ConstString(kDynamicLoaderPluginName),
ConstString("Settings for dynamic loader plug-ins"), properties_sp,
description, is_global_property);
}
lldb::OptionValuePropertiesSP
PluginManager::GetSettingForPlatformPlugin(Debugger &debugger,
const ConstString &setting_name) {
return GetSettingForPlugin(debugger, setting_name,
ConstString(kPlatformPluginName),
GetDebuggerPropertyForPluginsOldStyle);
}
bool PluginManager::CreateSettingForPlatformPlugin(
Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
const ConstString &description, bool is_global_property) {
return CreateSettingForPlugin(debugger, ConstString(kPlatformPluginName),
ConstString("Settings for platform plug-ins"),
properties_sp, description, is_global_property,
GetDebuggerPropertyForPluginsOldStyle);
}
lldb::OptionValuePropertiesSP
PluginManager::GetSettingForProcessPlugin(Debugger &debugger,
const ConstString &setting_name) {
return GetSettingForPlugin(debugger, setting_name,
ConstString(kProcessPluginName));
}
bool PluginManager::CreateSettingForProcessPlugin(
Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
const ConstString &description, bool is_global_property) {
return CreateSettingForPlugin(debugger, ConstString(kProcessPluginName),
ConstString("Settings for process plug-ins"),
properties_sp, description, is_global_property);
}
lldb::OptionValuePropertiesSP
PluginManager::GetSettingForSymbolFilePlugin(Debugger &debugger,
const ConstString &setting_name) {
return GetSettingForPlugin(debugger, setting_name,
ConstString(kSymbolFilePluginName));
}
bool PluginManager::CreateSettingForSymbolFilePlugin(
Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
const ConstString &description, bool is_global_property) {
return CreateSettingForPlugin(
debugger, ConstString(kSymbolFilePluginName),
ConstString("Settings for symbol file plug-ins"), properties_sp,
description, is_global_property);
}
lldb::OptionValuePropertiesSP
PluginManager::GetSettingForJITLoaderPlugin(Debugger &debugger,
const ConstString &setting_name) {
return GetSettingForPlugin(debugger, setting_name,
ConstString(kJITLoaderPluginName));
}
bool PluginManager::CreateSettingForJITLoaderPlugin(
Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
const ConstString &description, bool is_global_property) {
return CreateSettingForPlugin(debugger, ConstString(kJITLoaderPluginName),
ConstString("Settings for JIT loader plug-ins"),
properties_sp, description, is_global_property);
}
static const char *kOperatingSystemPluginName("os");
lldb::OptionValuePropertiesSP PluginManager::GetSettingForOperatingSystemPlugin(
Debugger &debugger, const ConstString &setting_name) {
lldb::OptionValuePropertiesSP properties_sp;
lldb::OptionValuePropertiesSP plugin_type_properties_sp(
GetDebuggerPropertyForPlugins(
debugger, ConstString(kOperatingSystemPluginName),
ConstString(), // not creating to so we don't need the description
false));
if (plugin_type_properties_sp)
properties_sp =
plugin_type_properties_sp->GetSubProperty(nullptr, setting_name);
return properties_sp;
}
bool PluginManager::CreateSettingForOperatingSystemPlugin(
Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
const ConstString &description, bool is_global_property) {
if (properties_sp) {
lldb::OptionValuePropertiesSP plugin_type_properties_sp(
GetDebuggerPropertyForPlugins(
debugger, ConstString(kOperatingSystemPluginName),
ConstString("Settings for operating system plug-ins"), true));
if (plugin_type_properties_sp) {
plugin_type_properties_sp->AppendProperty(properties_sp->GetName(),
description, is_global_property,
properties_sp);
return true;
}
}
return false;
}
lldb::OptionValuePropertiesSP PluginManager::GetSettingForStructuredDataPlugin(
Debugger &debugger, const ConstString &setting_name) {
return GetSettingForPlugin(debugger, setting_name,
ConstString(kStructuredDataPluginName));
}
bool PluginManager::CreateSettingForStructuredDataPlugin(
Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
const ConstString &description, bool is_global_property) {
return CreateSettingForPlugin(
debugger, ConstString(kStructuredDataPluginName),
ConstString("Settings for structured data plug-ins"), properties_sp,
description, is_global_property);
}