2010-06-09 00:52:24 +08:00
|
|
|
//===-- 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"
|
|
|
|
|
2016-03-12 05:55:47 +08:00
|
|
|
// C Includes
|
|
|
|
// C++ Includes
|
|
|
|
#include <climits>
|
2016-05-18 09:59:10 +08:00
|
|
|
#include <mutex>
|
2010-06-09 00:52:24 +08:00
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
|
2016-03-12 05:55:47 +08:00
|
|
|
// Other libraries and framework includes
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include "llvm/Support/DynamicLibrary.h"
|
|
|
|
|
|
|
|
// Project includes
|
2012-10-20 02:02:49 +08:00
|
|
|
#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"
|
2014-08-22 01:29:12 +08:00
|
|
|
#include "lldb/Host/HostInfo.h"
|
2012-10-20 02:02:49 +08:00
|
|
|
#include "lldb/Interpreter/OptionValueProperties.h"
|
2017-02-03 05:39:50 +08:00
|
|
|
#include "lldb/Utility/Error.h"
|
2017-03-23 02:40:07 +08:00
|
|
|
#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;
|
2010-06-09 00:52:24 +08:00
|
|
|
using namespace lldb_private;
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
enum PluginAction {
|
|
|
|
ePluginRegisterInstance,
|
|
|
|
ePluginUnregisterInstance,
|
|
|
|
ePluginGetInstanceAtIndex
|
2010-06-09 00:52:24 +08:00
|
|
|
};
|
|
|
|
|
2016-03-12 05:55:47 +08:00
|
|
|
typedef bool (*PluginInitCallback)();
|
|
|
|
typedef void (*PluginTermCallback)();
|
2013-04-20 05:31:16 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
struct PluginInfo {
|
|
|
|
PluginInfo() : plugin_init_callback(nullptr), plugin_term_callback(nullptr) {}
|
2014-08-28 04:15:09 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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
|
2017-03-09 01:56:08 +08:00
|
|
|
LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
|
2016-09-07 04:57:50 +08:00
|
|
|
const FileSpec &file_spec) {
|
|
|
|
// PluginManager *plugin_manager = (PluginManager *)baton;
|
|
|
|
Error error;
|
|
|
|
|
2017-03-09 01:56:08 +08:00
|
|
|
namespace fs = llvm::sys::fs;
|
2016-09-07 04:57:50 +08:00
|
|
|
// 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.
|
2017-03-09 01:56:08 +08:00
|
|
|
if (ft == fs::file_type::regular_file || ft == fs::file_type::symlink_file ||
|
|
|
|
ft == fs::file_type::type_unknown) {
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-09 01:56:08 +08:00
|
|
|
if (ft == fs::file_type::directory_file ||
|
|
|
|
ft == fs::file_type::symlink_file || ft == fs::file_type::type_unknown) {
|
2016-09-07 04:57:50 +08:00
|
|
|
// 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() {
|
2011-03-24 12:28:38 +08:00
|
|
|
#if 1
|
2016-09-07 04:57:50 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2011-03-24 12:28:38 +08:00
|
|
|
#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
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +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
|
|
|
}
|
2016-09-07 04:57:50 +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
|
|
|
}
|
|
|
|
|
2010-06-09 00:52:24 +08:00
|
|
|
#pragma mark ABI
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
struct ABIInstance {
|
|
|
|
ABIInstance() : name(), description(), create_callback(nullptr) {}
|
2010-06-09 00:52:24 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
ConstString name;
|
|
|
|
std::string description;
|
|
|
|
ABICreateInstance create_callback;
|
2010-06-09 00:52:24 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::vector<ABIInstance> ABIInstances;
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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);
|
2011-03-19 09:12:21 +08:00
|
|
|
return true;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return false;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ABICreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
PluginManager::GetABICreateCallbackForPluginName(const ConstString &name) {
|
|
|
|
if (name) {
|
2016-05-18 09:59:10 +08:00
|
|
|
std::lock_guard<std::recursive_mutex> guard(GetABIInstancesMutex());
|
2016-09-07 04:57:50 +08:00
|
|
|
ABIInstances &instances = GetABIInstances();
|
2010-06-09 00:52:24 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
ABIInstances::iterator pos, end = instances.end();
|
|
|
|
for (pos = instances.begin(); pos != end; ++pos) {
|
|
|
|
if (name == pos->name)
|
|
|
|
return pos->create_callback;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return nullptr;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark Disassembler
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
struct DisassemblerInstance {
|
|
|
|
DisassemblerInstance() : name(), description(), create_callback(nullptr) {}
|
2010-06-09 00:52:24 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
ConstString name;
|
|
|
|
std::string description;
|
|
|
|
DisassemblerCreateInstance create_callback;
|
2010-06-09 00:52:24 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::vector<DisassemblerInstance> DisassemblerInstances;
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
static std::recursive_mutex &GetDisassemblerMutex() {
|
|
|
|
static std::recursive_mutex g_instances_mutex;
|
|
|
|
return g_instances_mutex;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
|
|
|
}
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return false;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
DisassemblerCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
DisassemblerCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return nullptr;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark DynamicLoader
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
struct DynamicLoaderInstance {
|
|
|
|
DynamicLoaderInstance()
|
|
|
|
: name(), description(), create_callback(nullptr),
|
|
|
|
debugger_init_callback(nullptr) {}
|
2010-06-09 00:52:24 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
ConstString name;
|
|
|
|
std::string description;
|
|
|
|
DynamicLoaderCreateInstance create_callback;
|
|
|
|
DebuggerInitializeCallback debugger_init_callback;
|
2010-06-09 00:52:24 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::vector<DynamicLoaderInstance> DynamicLoaderInstances;
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
static std::recursive_mutex &GetDynamicLoaderMutex() {
|
|
|
|
static std::recursive_mutex g_instances_mutex;
|
|
|
|
return g_instances_mutex;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
|
|
|
}
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return false;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
DynamicLoaderCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
DynamicLoaderCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return nullptr;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
2014-03-05 18:12:43 +08:00
|
|
|
#pragma mark JITLoader
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
struct JITLoaderInstance {
|
|
|
|
JITLoaderInstance()
|
|
|
|
: name(), description(), create_callback(nullptr),
|
|
|
|
debugger_init_callback(nullptr) {}
|
2014-03-05 18:12:43 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
ConstString name;
|
|
|
|
std::string description;
|
|
|
|
JITLoaderCreateInstance create_callback;
|
|
|
|
DebuggerInitializeCallback debugger_init_callback;
|
2014-03-05 18:12:43 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::vector<JITLoaderInstance> JITLoaderInstances;
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
static std::recursive_mutex &GetJITLoaderMutex() {
|
|
|
|
static std::recursive_mutex g_instances_mutex;
|
|
|
|
return g_instances_mutex;
|
2014-03-05 18:12:43 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
static JITLoaderInstances &GetJITLoaderInstances() {
|
|
|
|
static JITLoaderInstances g_instances;
|
|
|
|
return g_instances;
|
2014-03-05 18:12:43 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2016-05-18 09:59:10 +08:00
|
|
|
std::lock_guard<std::recursive_mutex> guard(GetJITLoaderMutex());
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2014-03-05 18:12:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
JITLoaderCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2014-03-05 18:12:43 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return nullptr;
|
2014-03-05 18:12:43 +08:00
|
|
|
}
|
|
|
|
|
2011-02-01 09:37:45 +08:00
|
|
|
#pragma mark EmulateInstruction
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
struct EmulateInstructionInstance {
|
|
|
|
EmulateInstructionInstance()
|
|
|
|
: name(), description(), create_callback(nullptr) {}
|
|
|
|
|
|
|
|
ConstString name;
|
|
|
|
std::string description;
|
|
|
|
EmulateInstructionCreateInstance create_callback;
|
2011-02-01 09:37:45 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::vector<EmulateInstructionInstance> EmulateInstructionInstances;
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
static std::recursive_mutex &GetEmulateInstructionMutex() {
|
|
|
|
static std::recursive_mutex g_instances_mutex;
|
|
|
|
return g_instances_mutex;
|
2011-02-01 09:37:45 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
|
|
|
}
|
2011-02-01 09:37:45 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return false;
|
2011-02-01 09:37:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
EmulateInstructionCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2011-02-01 09:37:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
EmulateInstructionCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2011-08-22 10:49:39 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return nullptr;
|
2011-08-22 10:49:39 +08:00
|
|
|
}
|
|
|
|
|
2016-03-12 05:55:47 +08:00
|
|
|
#pragma mark OperatingSystem
|
2011-08-22 10:49:39 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
struct OperatingSystemInstance {
|
|
|
|
OperatingSystemInstance()
|
|
|
|
: name(), description(), create_callback(nullptr),
|
|
|
|
debugger_init_callback(nullptr) {}
|
|
|
|
|
|
|
|
ConstString name;
|
|
|
|
std::string description;
|
|
|
|
OperatingSystemCreateInstance create_callback;
|
|
|
|
DebuggerInitializeCallback debugger_init_callback;
|
2011-08-22 10:49:39 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::vector<OperatingSystemInstance> OperatingSystemInstances;
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
static std::recursive_mutex &GetOperatingSystemMutex() {
|
|
|
|
static std::recursive_mutex g_instances_mutex;
|
|
|
|
return g_instances_mutex;
|
2011-08-22 10:49:39 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
|
|
|
}
|
2011-08-22 10:49:39 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return false;
|
2011-08-22 10:49:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
OperatingSystemCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2011-08-22 10:49:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
OperatingSystemCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2011-02-01 09:37:45 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return nullptr;
|
2011-02-01 09:37:45 +08:00
|
|
|
}
|
|
|
|
|
2015-08-28 05:33:50 +08:00
|
|
|
#pragma mark Language
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
struct LanguageInstance {
|
|
|
|
LanguageInstance() : name(), description(), create_callback(nullptr) {}
|
|
|
|
|
|
|
|
ConstString name;
|
|
|
|
std::string description;
|
|
|
|
LanguageCreateInstance create_callback;
|
2015-08-28 05:33:50 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::vector<LanguageInstance> LanguageInstances;
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
static std::recursive_mutex &GetLanguageMutex() {
|
|
|
|
static std::recursive_mutex g_instances_mutex;
|
|
|
|
return g_instances_mutex;
|
2015-08-28 05:33:50 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
|
|
|
}
|
2015-08-28 05:33:50 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return false;
|
2015-08-28 05:33:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
LanguageCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2015-08-28 05:33:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
LanguageCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2015-08-28 05:33:50 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return nullptr;
|
2015-08-28 05:33:50 +08:00
|
|
|
}
|
|
|
|
|
2010-09-23 10:01:19 +08:00
|
|
|
#pragma mark LanguageRuntime
|
2010-06-09 00:52:24 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
struct LanguageRuntimeInstance {
|
|
|
|
LanguageRuntimeInstance() : name(), description(), create_callback(nullptr) {}
|
2010-09-23 10:01:19 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
ConstString name;
|
|
|
|
std::string description;
|
|
|
|
LanguageRuntimeCreateInstance create_callback;
|
|
|
|
LanguageRuntimeGetCommandObject command_callback;
|
2010-09-23 10:01:19 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::vector<LanguageRuntimeInstance> LanguageRuntimeInstances;
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
static std::recursive_mutex &GetLanguageRuntimeMutex() {
|
|
|
|
static std::recursive_mutex g_instances_mutex;
|
|
|
|
return g_instances_mutex;
|
2010-09-23 10:01:19 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
|
|
|
}
|
2010-09-23 10:01:19 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return false;
|
2010-09-23 10:01:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
LanguageRuntimeCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2010-09-23 10:01:19 +08:00
|
|
|
}
|
|
|
|
|
2015-05-05 02:39:38 +08:00
|
|
|
LanguageRuntimeGetCommandObject
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2015-05-05 02:39:38 +08:00
|
|
|
}
|
|
|
|
|
2010-09-23 10:01:19 +08:00
|
|
|
LanguageRuntimeCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2010-09-23 10:01:19 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return nullptr;
|
2010-09-23 10:01:19 +08:00
|
|
|
}
|
|
|
|
|
2013-11-05 11:57:19 +08:00
|
|
|
#pragma mark SystemRuntime
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
struct SystemRuntimeInstance {
|
|
|
|
SystemRuntimeInstance() : name(), description(), create_callback(nullptr) {}
|
2013-11-05 11:57:19 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
ConstString name;
|
|
|
|
std::string description;
|
|
|
|
SystemRuntimeCreateInstance create_callback;
|
2013-11-05 11:57:19 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::vector<SystemRuntimeInstance> SystemRuntimeInstances;
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
static std::recursive_mutex &GetSystemRuntimeMutex() {
|
|
|
|
static std::recursive_mutex g_instances_mutex;
|
|
|
|
return g_instances_mutex;
|
2013-11-05 11:57:19 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
|
|
|
}
|
2013-11-05 11:57:19 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return false;
|
2013-11-05 11:57:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SystemRuntimeCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2013-11-05 11:57:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SystemRuntimeCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2013-11-05 11:57:19 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return nullptr;
|
2013-11-05 11:57:19 +08:00
|
|
|
}
|
|
|
|
|
2010-06-09 00:52:24 +08:00
|
|
|
#pragma mark ObjectFile
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2010-06-09 00:52:24 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::vector<ObjectFileInstance> ObjectFileInstances;
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
static std::recursive_mutex &GetObjectFileMutex() {
|
|
|
|
static std::recursive_mutex g_instances_mutex;
|
|
|
|
return g_instances_mutex;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
|
|
|
}
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return false;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ObjectFileCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
2011-04-14 06:47:15 +08:00
|
|
|
|
2012-02-05 10:38:54 +08:00
|
|
|
ObjectFileCreateMemoryInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2012-02-05 10:38:54 +08:00
|
|
|
}
|
|
|
|
|
2013-04-25 06:29:28 +08:00
|
|
|
ObjectFileGetModuleSpecifications
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2013-04-25 06:29:28 +08:00
|
|
|
}
|
|
|
|
|
2010-06-09 00:52:24 +08:00
|
|
|
ObjectFileCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
PluginManager::GetObjectFileCreateCallbackForPluginName(
|
|
|
|
const ConstString &name) {
|
|
|
|
if (name) {
|
|
|
|
std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex());
|
|
|
|
ObjectFileInstances &instances = GetObjectFileInstances();
|
2010-06-09 00:52:24 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
ObjectFileInstances::iterator pos, end = instances.end();
|
|
|
|
for (pos = instances.begin(); pos != end; ++pos) {
|
|
|
|
if (name == pos->name)
|
|
|
|
return pos->create_callback;
|
2012-02-05 10:38:54 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return nullptr;
|
2012-02-05 10:38:54 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
ObjectFileCreateMemoryInstance
|
|
|
|
PluginManager::GetObjectFileCreateMemoryCallbackForPluginName(
|
|
|
|
const ConstString &name) {
|
|
|
|
if (name) {
|
2016-05-18 09:59:10 +08:00
|
|
|
std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex());
|
2016-09-07 04:57:50 +08:00
|
|
|
ObjectFileInstances &instances = GetObjectFileInstances();
|
|
|
|
|
2014-06-13 08:54:12 +08:00
|
|
|
ObjectFileInstances::iterator pos, end = instances.end();
|
2016-09-07 04:57:50 +08:00
|
|
|
for (pos = instances.begin(); pos != end; ++pos) {
|
|
|
|
if (name == pos->name)
|
|
|
|
return pos->create_memory_callback;
|
2014-06-13 08:54:12 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
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;
|
2014-06-13 08:54:12 +08:00
|
|
|
}
|
2010-06-09 00:52:24 +08:00
|
|
|
|
|
|
|
#pragma mark ObjectContainer
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
struct ObjectContainerInstance {
|
|
|
|
ObjectContainerInstance()
|
|
|
|
: name(), description(), create_callback(nullptr),
|
|
|
|
get_module_specifications(nullptr) {}
|
2010-06-09 00:52:24 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
ConstString name;
|
|
|
|
std::string description;
|
|
|
|
ObjectContainerCreateInstance create_callback;
|
|
|
|
ObjectFileGetModuleSpecifications get_module_specifications;
|
2010-06-09 00:52:24 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::vector<ObjectContainerInstance> ObjectContainerInstances;
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
static std::recursive_mutex &GetObjectContainerMutex() {
|
|
|
|
static std::recursive_mutex g_instances_mutex;
|
|
|
|
return g_instances_mutex;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
|
|
|
}
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return false;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ObjectContainerCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
2011-04-14 06:47:15 +08:00
|
|
|
|
2010-06-09 00:52:24 +08:00
|
|
|
ObjectContainerCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return nullptr;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
2013-04-25 06:29:28 +08:00
|
|
|
ObjectFileGetModuleSpecifications
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2013-04-25 06:29:28 +08:00
|
|
|
}
|
|
|
|
|
2011-03-09 06:40:15 +08:00
|
|
|
#pragma mark Platform
|
2010-06-09 00:52:24 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
struct PlatformInstance {
|
|
|
|
PlatformInstance()
|
|
|
|
: name(), description(), create_callback(nullptr),
|
|
|
|
debugger_init_callback(nullptr) {}
|
|
|
|
|
|
|
|
ConstString name;
|
|
|
|
std::string description;
|
|
|
|
PlatformCreateInstance create_callback;
|
|
|
|
DebuggerInitializeCallback debugger_init_callback;
|
2011-03-09 06:40:15 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::vector<PlatformInstance> PlatformInstances;
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
static std::recursive_mutex &GetPlatformInstancesMutex() {
|
|
|
|
static std::recursive_mutex g_platform_instances_mutex;
|
|
|
|
return g_platform_instances_mutex;
|
2011-03-09 06:40:15 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +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) {
|
2016-05-18 09:59:10 +08:00
|
|
|
std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex());
|
2016-09-07 04:57:50 +08:00
|
|
|
|
|
|
|
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;
|
2011-03-09 06:40:15 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
bool PluginManager::UnregisterPlugin(PlatformCreateInstance create_callback) {
|
|
|
|
if (create_callback) {
|
2016-05-18 09:59:10 +08:00
|
|
|
std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex());
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
|
|
|
}
|
2011-03-09 06:40:15 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return false;
|
2011-03-09 06:40:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
PlatformCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2011-03-09 06:40:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
PlatformCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2011-03-09 06:40:15 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return nullptr;
|
2011-03-09 06:40:15 +08:00
|
|
|
}
|
2010-06-09 00:52:24 +08:00
|
|
|
|
2016-11-17 09:37:42 +08:00
|
|
|
size_t PluginManager::AutoCompletePlatformName(llvm::StringRef name,
|
2016-09-07 04:57:50 +08:00
|
|
|
StringList &matches) {
|
2016-11-17 09:37:42 +08:00
|
|
|
if (name.empty())
|
|
|
|
return matches.GetSize();
|
2011-04-14 06:47:15 +08:00
|
|
|
|
2016-11-17 09:37:42 +08:00
|
|
|
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());
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return matches.GetSize();
|
2011-04-14 06:47:15 +08:00
|
|
|
}
|
2016-03-12 05:55:47 +08:00
|
|
|
|
2011-03-09 06:40:15 +08:00
|
|
|
#pragma mark Process
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
struct ProcessInstance {
|
|
|
|
ProcessInstance()
|
|
|
|
: name(), description(), create_callback(nullptr),
|
|
|
|
debugger_init_callback(nullptr) {}
|
|
|
|
|
|
|
|
ConstString name;
|
|
|
|
std::string description;
|
|
|
|
ProcessCreateInstance create_callback;
|
|
|
|
DebuggerInitializeCallback debugger_init_callback;
|
2010-06-09 00:52:24 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::vector<ProcessInstance> ProcessInstances;
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2011-02-18 09:44:25 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
bool PluginManager::UnregisterPlugin(ProcessCreateInstance create_callback) {
|
|
|
|
if (create_callback) {
|
2016-05-18 09:59:10 +08:00
|
|
|
std::lock_guard<std::recursive_mutex> guard(GetProcessMutex());
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
|
|
|
}
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return false;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ProcessCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ProcessCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return nullptr;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
2015-07-31 04:28:07 +08:00
|
|
|
#pragma mark ScriptInterpreter
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
struct ScriptInterpreterInstance {
|
|
|
|
ScriptInterpreterInstance()
|
|
|
|
: name(), language(lldb::eScriptLanguageNone), description(),
|
|
|
|
create_callback(nullptr) {}
|
2015-07-31 04:28:07 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
ConstString name;
|
|
|
|
lldb::ScriptLanguage language;
|
|
|
|
std::string description;
|
|
|
|
ScriptInterpreterCreateInstance create_callback;
|
2015-07-31 04:28:07 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::vector<ScriptInterpreterInstance> ScriptInterpreterInstances;
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
static std::recursive_mutex &GetScriptInterpreterMutex() {
|
|
|
|
static std::recursive_mutex g_instances_mutex;
|
|
|
|
return g_instances_mutex;
|
2015-07-31 04:28:07 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
static ScriptInterpreterInstances &GetScriptInterpreterInstances() {
|
|
|
|
static ScriptInterpreterInstances g_instances;
|
|
|
|
return g_instances;
|
2015-07-31 04:28:07 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
bool PluginManager::RegisterPlugin(
|
|
|
|
const ConstString &name, const char *description,
|
|
|
|
lldb::ScriptLanguage script_language,
|
|
|
|
ScriptInterpreterCreateInstance create_callback) {
|
|
|
|
if (!create_callback)
|
2015-07-31 04:28:07 +08:00
|
|
|
return false;
|
2016-09-07 04:57:50 +08:00
|
|
|
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();
|
2015-07-31 04:28:07 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
ScriptInterpreterInstances::iterator pos, end = instances.end();
|
|
|
|
for (pos = instances.begin(); pos != end; ++pos) {
|
|
|
|
if (pos->create_callback != create_callback)
|
|
|
|
continue;
|
2015-07-31 04:28:07 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
instances.erase(pos);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2015-07-31 04:28:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ScriptInterpreterCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2015-07-31 04:28:07 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
lldb::ScriptInterpreterSP PluginManager::GetScriptInterpreterForLanguage(
|
|
|
|
lldb::ScriptLanguage script_lang, CommandInterpreter &interpreter) {
|
|
|
|
std::lock_guard<std::recursive_mutex> guard(GetScriptInterpreterMutex());
|
|
|
|
ScriptInterpreterInstances &instances = GetScriptInterpreterInstances();
|
2015-07-31 04:28:07 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2015-07-31 04:28:07 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
if (script_lang == pos->language)
|
|
|
|
return pos->create_callback(interpreter);
|
|
|
|
}
|
2015-07-31 04:28:07 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
// If we didn't find one, return the ScriptInterpreter for the null language.
|
|
|
|
assert(none_instance != nullptr);
|
|
|
|
return none_instance(interpreter);
|
2015-07-31 04:28:07 +08:00
|
|
|
}
|
|
|
|
|
2016-08-19 12:21:48 +08:00
|
|
|
#pragma mark -
|
|
|
|
#pragma mark StructuredDataPlugin
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// StructuredDataPlugin
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2016-08-19 12:21:48 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::vector<StructuredDataPluginInstance> StructuredDataPluginInstances;
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
static std::recursive_mutex &GetStructuredDataPluginMutex() {
|
|
|
|
static std::recursive_mutex g_instances_mutex;
|
|
|
|
return g_instances_mutex;
|
2016-08-19 12:21:48 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
static StructuredDataPluginInstances &GetStructuredDataPluginInstances() {
|
|
|
|
static StructuredDataPluginInstances g_instances;
|
|
|
|
return g_instances;
|
2016-08-19 12:21:48 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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) {
|
2016-08-19 12:21:48 +08:00
|
|
|
std::lock_guard<std::recursive_mutex> guard(GetStructuredDataPluginMutex());
|
|
|
|
StructuredDataPluginInstances &instances =
|
|
|
|
GetStructuredDataPluginInstances();
|
2016-09-07 04:57:50 +08:00
|
|
|
|
|
|
|
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;
|
2016-08-19 12:21:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
StructuredDataPluginCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2016-08-19 12:21:48 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
StructuredDataPluginCreateInstance
|
|
|
|
PluginManager::GetStructuredDataPluginCreateCallbackForPluginName(
|
|
|
|
const ConstString &name) {
|
|
|
|
if (name) {
|
2016-08-19 12:21:48 +08:00
|
|
|
std::lock_guard<std::recursive_mutex> guard(GetStructuredDataPluginMutex());
|
|
|
|
StructuredDataPluginInstances &instances =
|
|
|
|
GetStructuredDataPluginInstances();
|
2016-09-07 04:57:50 +08:00
|
|
|
|
|
|
|
StructuredDataPluginInstances::iterator pos, end = instances.end();
|
|
|
|
for (pos = instances.begin(); pos != end; ++pos) {
|
|
|
|
if (name == pos->name)
|
|
|
|
return pos->create_callback;
|
2016-08-19 12:21:48 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
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;
|
2016-08-19 12:21:48 +08:00
|
|
|
}
|
|
|
|
|
2010-06-09 00:52:24 +08:00
|
|
|
#pragma mark SymbolFile
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
struct SymbolFileInstance {
|
|
|
|
SymbolFileInstance()
|
|
|
|
: name(), description(), create_callback(nullptr),
|
|
|
|
debugger_init_callback(nullptr) {}
|
2010-06-09 00:52:24 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
ConstString name;
|
|
|
|
std::string description;
|
|
|
|
SymbolFileCreateInstance create_callback;
|
|
|
|
DebuggerInitializeCallback debugger_init_callback;
|
2010-06-09 00:52:24 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::vector<SymbolFileInstance> SymbolFileInstances;
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
static std::recursive_mutex &GetSymbolFileMutex() {
|
|
|
|
static std::recursive_mutex g_instances_mutex;
|
|
|
|
return g_instances_mutex;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
|
|
|
}
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return false;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SymbolFileCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
2011-04-14 06:47:15 +08:00
|
|
|
|
2010-06-09 00:52:24 +08:00
|
|
|
SymbolFileCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return nullptr;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark SymbolVendor
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
struct SymbolVendorInstance {
|
|
|
|
SymbolVendorInstance() : name(), description(), create_callback(nullptr) {}
|
2010-06-09 00:52:24 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
ConstString name;
|
|
|
|
std::string description;
|
|
|
|
SymbolVendorCreateInstance create_callback;
|
2010-06-09 00:52:24 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::vector<SymbolVendorInstance> SymbolVendorInstances;
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
static std::recursive_mutex &GetSymbolVendorMutex() {
|
|
|
|
static std::recursive_mutex g_instances_mutex;
|
|
|
|
return g_instances_mutex;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
|
|
|
}
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return false;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SymbolVendorCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SymbolVendorCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return nullptr;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
2011-04-26 05:14:26 +08:00
|
|
|
#pragma mark UnwindAssembly
|
2010-09-10 15:49:16 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
struct UnwindAssemblyInstance {
|
|
|
|
UnwindAssemblyInstance() : name(), description(), create_callback(nullptr) {}
|
2010-09-10 15:49:16 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
ConstString name;
|
|
|
|
std::string description;
|
|
|
|
UnwindAssemblyCreateInstance create_callback;
|
2010-09-10 15:49:16 +08:00
|
|
|
};
|
|
|
|
|
2011-04-26 05:14:26 +08:00
|
|
|
typedef std::vector<UnwindAssemblyInstance> UnwindAssemblyInstances;
|
2010-09-10 15:49:16 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
static std::recursive_mutex &GetUnwindAssemblyMutex() {
|
|
|
|
static std::recursive_mutex g_instances_mutex;
|
|
|
|
return g_instances_mutex;
|
2010-09-10 15:49:16 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +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;
|
|
|
|
}
|
2010-09-10 15:49:16 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return false;
|
2010-09-10 15:49:16 +08:00
|
|
|
}
|
|
|
|
|
2011-04-26 05:14:26 +08:00
|
|
|
UnwindAssemblyCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2010-09-10 15:49:16 +08:00
|
|
|
}
|
|
|
|
|
2011-04-26 05:14:26 +08:00
|
|
|
UnwindAssemblyCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2010-09-10 15:49:16 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return nullptr;
|
2010-09-10 15:49:16 +08:00
|
|
|
}
|
|
|
|
|
2014-09-04 09:03:18 +08:00
|
|
|
#pragma mark MemoryHistory
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
struct MemoryHistoryInstance {
|
|
|
|
MemoryHistoryInstance() : name(), description(), create_callback(nullptr) {}
|
|
|
|
|
|
|
|
ConstString name;
|
|
|
|
std::string description;
|
|
|
|
MemoryHistoryCreateInstance create_callback;
|
2014-09-04 09:03:18 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::vector<MemoryHistoryInstance> MemoryHistoryInstances;
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
static std::recursive_mutex &GetMemoryHistoryMutex() {
|
|
|
|
static std::recursive_mutex g_instances_mutex;
|
|
|
|
return g_instances_mutex;
|
2014-09-04 09:03:18 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
|
|
|
}
|
2014-09-04 09:03:18 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return false;
|
2014-09-04 09:03:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
MemoryHistoryCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2014-09-04 09:03:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
MemoryHistoryCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2014-09-04 09:03:18 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return nullptr;
|
2014-09-04 09:03:18 +08:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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
|
|
|
};
|
|
|
|
|
2016-09-07 04:57:50 +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
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +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
|
|
|
}
|
2016-09-07 04:57:50 +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
|
2016-09-07 04:57:50 +08:00
|
|
|
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
|
2016-09-07 04:57:50 +08:00
|
|
|
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
|
2016-09-07 04:57:50 +08:00
|
|
|
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
|
|
|
}
|
2016-09-07 04:57:50 +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
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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
|
|
|
|
2016-09-07 04:57:50 +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;
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +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
|
|
|
}
|
2016-09-07 04:57:50 +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
|
2016-09-07 04:57:50 +08:00
|
|
|
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
|
2016-09-07 04:57:50 +08:00
|
|
|
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
|
|
|
}
|
2016-09-07 04:57:50 +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
|
|
|
}
|
|
|
|
|
2015-10-09 07:07:53 +08:00
|
|
|
TypeSystemEnumerateSupportedLanguages
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2015-10-09 07:07:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TypeSystemEnumerateSupportedLanguages
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2015-10-09 07:07:53 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return nullptr;
|
2015-10-09 07:07:53 +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
|
|
|
|
2015-10-20 07:11:07 +08:00
|
|
|
#pragma mark REPL
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
struct REPLInstance {
|
|
|
|
REPLInstance() : name(), description(), create_callback(nullptr) {}
|
|
|
|
|
|
|
|
ConstString name;
|
|
|
|
std::string description;
|
|
|
|
REPLCreateInstance create_callback;
|
|
|
|
REPLEnumerateSupportedLanguages enumerate_languages_callback;
|
2015-10-20 07:11:07 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::vector<REPLInstance> REPLInstances;
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
static std::recursive_mutex &GetREPLMutex() {
|
|
|
|
static std::recursive_mutex g_instances_mutex;
|
|
|
|
return g_instances_mutex;
|
2015-10-20 07:11:07 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
static REPLInstances &GetREPLInstances() {
|
|
|
|
static REPLInstances g_instances;
|
|
|
|
return g_instances;
|
2015-10-20 07:11:07 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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) {
|
2016-05-18 09:59:10 +08:00
|
|
|
std::lock_guard<std::recursive_mutex> guard(GetREPLMutex());
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2015-10-20 07:11:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
REPLCreateInstance
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2015-10-20 07:11:07 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return nullptr;
|
2015-10-20 07:11:07 +08:00
|
|
|
}
|
|
|
|
|
2015-10-22 03:14:33 +08:00
|
|
|
REPLEnumerateSupportedLanguages
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2015-10-22 03:14:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
REPLEnumerateSupportedLanguages
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2015-10-22 03:14:33 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return nullptr;
|
2015-10-22 03:14:33 +08:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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);
|
2014-03-05 18:12:43 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-03-05 18:12:43 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
// 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);
|
2013-04-05 13:06:39 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2013-04-05 13:06:39 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
// 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);
|
2012-10-20 02:02:49 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2015-07-30 06:18:16 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
// 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);
|
2013-07-16 06:54:20 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2013-07-16 06:54:20 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
// 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);
|
2015-07-30 06:18:16 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2015-09-17 05:20:44 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
// 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);
|
2015-09-17 05:20:44 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2016-08-19 12:21:48 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
// 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);
|
2016-08-19 12:21:48 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2012-10-20 02:02:49 +08:00
|
|
|
}
|
|
|
|
|
2013-07-16 06:54:20 +08:00
|
|
|
// This is the preferred new way to register plugin specific settings. e.g.
|
2016-09-07 04:57:50 +08:00
|
|
|
// 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;
|
2012-10-20 02:02:49 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return lldb::OptionValuePropertiesSP();
|
2012-10-20 02:02:49 +08:00
|
|
|
}
|
|
|
|
|
2013-07-16 06:54:20 +08:00
|
|
|
// This is deprecated way to register plugin specific settings. e.g.
|
|
|
|
// "<plugin_type_name>.plugin.<plugin_type_desc>.SETTINGNAME"
|
2013-04-06 06:40:42 +08:00
|
|
|
// and Platform generic settings would be under "platform.SETTINGNAME".
|
2016-09-07 04:57:50 +08:00
|
|
|
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();
|
2013-04-06 06:40:42 +08:00
|
|
|
}
|
|
|
|
|
2015-09-17 01:38:36 +08:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
typedef lldb::OptionValuePropertiesSP
|
2016-09-07 04:57:50 +08:00
|
|
|
GetDebuggerPropertyForPluginsPtr(Debugger &, const ConstString &,
|
|
|
|
const ConstString &, bool can_create);
|
2013-04-06 06:40:42 +08:00
|
|
|
|
2012-10-20 02:02:49 +08:00
|
|
|
lldb::OptionValuePropertiesSP
|
2016-09-07 04:57:50 +08:00
|
|
|
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;
|
2012-10-20 02:02:49 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
return false;
|
2012-10-20 02:02:49 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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");
|
2015-09-17 01:38:36 +08:00
|
|
|
|
2016-03-12 05:55:47 +08:00
|
|
|
} // anonymous namespace
|
2013-04-05 13:06:39 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
lldb::OptionValuePropertiesSP PluginManager::GetSettingForDynamicLoaderPlugin(
|
|
|
|
Debugger &debugger, const ConstString &setting_name) {
|
|
|
|
return GetSettingForPlugin(debugger, setting_name,
|
|
|
|
ConstString(kDynamicLoaderPluginName));
|
2015-09-17 01:38:36 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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);
|
2013-07-16 06:54:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
lldb::OptionValuePropertiesSP
|
2016-09-07 04:57:50 +08:00
|
|
|
PluginManager::GetSettingForPlatformPlugin(Debugger &debugger,
|
|
|
|
const ConstString &setting_name) {
|
|
|
|
return GetSettingForPlugin(debugger, setting_name,
|
|
|
|
ConstString(kPlatformPluginName),
|
|
|
|
GetDebuggerPropertyForPluginsOldStyle);
|
2013-07-16 06:54:20 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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);
|
2013-04-05 13:06:39 +08:00
|
|
|
}
|
|
|
|
|
2015-07-30 06:18:16 +08:00
|
|
|
lldb::OptionValuePropertiesSP
|
2016-09-07 04:57:50 +08:00
|
|
|
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);
|
2015-09-17 01:38:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
lldb::OptionValuePropertiesSP
|
2016-09-07 04:57:50 +08:00
|
|
|
PluginManager::GetSettingForSymbolFilePlugin(Debugger &debugger,
|
|
|
|
const ConstString &setting_name) {
|
|
|
|
return GetSettingForPlugin(debugger, setting_name,
|
|
|
|
ConstString(kSymbolFilePluginName));
|
2015-07-30 06:18:16 +08:00
|
|
|
}
|
2015-09-17 05:20:44 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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);
|
|
|
|
}
|
2015-09-17 05:20:44 +08:00
|
|
|
|
|
|
|
lldb::OptionValuePropertiesSP
|
2016-09-07 04:57:50 +08:00
|
|
|
PluginManager::GetSettingForJITLoaderPlugin(Debugger &debugger,
|
|
|
|
const ConstString &setting_name) {
|
|
|
|
return GetSettingForPlugin(debugger, setting_name,
|
|
|
|
ConstString(kJITLoaderPluginName));
|
2015-09-17 05:20:44 +08:00
|
|
|
}
|
2016-08-19 12:21:48 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
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);
|
2016-08-19 12:21:48 +08:00
|
|
|
}
|