summaryrefslogtreecommitdiffstats
path: root/lldb/source
diff options
context:
space:
mode:
authorKuba Brecka <kuba.brecka@gmail.com>2014-09-04 01:03:18 +0000
committerKuba Brecka <kuba.brecka@gmail.com>2014-09-04 01:03:18 +0000
commitbeed821ffb058c164a885f96f2308c71cc7b632c (patch)
tree934e92deb6a97470ddbe389447d1daa20f4bc719 /lldb/source
parent13046deef35374954dcbd164ba2f56f3166648e6 (diff)
downloadbcm5719-llvm-beed821ffb058c164a885f96f2308c71cc7b632c.tar.gz
bcm5719-llvm-beed821ffb058c164a885f96f2308c71cc7b632c.zip
ASan malloc/free history threads
Reviewed at http://reviews.llvm.org/D4596 llvm-svn: 217116
Diffstat (limited to 'lldb/source')
-rw-r--r--lldb/source/CMakeLists.txt1
-rw-r--r--lldb/source/Commands/CommandObjectMemory.cpp93
-rw-r--r--lldb/source/Core/PluginManager.cpp104
-rw-r--r--lldb/source/Plugins/CMakeLists.txt1
-rw-r--r--lldb/source/Plugins/Makefile3
-rw-r--r--lldb/source/Plugins/MemoryHistory/CMakeLists.txt1
-rw-r--r--lldb/source/Plugins/MemoryHistory/asan/CMakeLists.txt5
-rw-r--r--lldb/source/Plugins/MemoryHistory/asan/Makefile14
-rw-r--r--lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp185
-rw-r--r--lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h62
-rw-r--r--lldb/source/Plugins/Process/Utility/HistoryThread.h12
-rw-r--r--lldb/source/Target/CMakeLists.txt1
-rw-r--r--lldb/source/Target/MemoryHistory.cpp28
-rw-r--r--lldb/source/lldb.cpp3
14 files changed, 512 insertions, 1 deletions
diff --git a/lldb/source/CMakeLists.txt b/lldb/source/CMakeLists.txt
index a1ee299f21a..1531a4af396 100644
--- a/lldb/source/CMakeLists.txt
+++ b/lldb/source/CMakeLists.txt
@@ -84,6 +84,7 @@ set( LLDB_USED_LIBS
lldbPluginInstructionARM64
lldbPluginObjectFilePECOFF
lldbPluginOSPython
+ lldbPluginMemoryHistoryASan
)
# Need to export the API in the liblldb.dll for Windows
diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp
index bfbb296158a..8144f48a5b4 100644
--- a/lldb/source/Commands/CommandObjectMemory.cpp
+++ b/lldb/source/Commands/CommandObjectMemory.cpp
@@ -33,8 +33,10 @@
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
#include "lldb/Interpreter/OptionValueString.h"
#include "lldb/Symbol/TypeList.h"
+#include "lldb/Target/MemoryHistory.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Thread.h"
using namespace lldb;
using namespace lldb_private;
@@ -1667,6 +1669,96 @@ protected:
OptionGroupWriteMemory m_memory_options;
};
+//----------------------------------------------------------------------
+// Get malloc/free history of a memory address.
+//----------------------------------------------------------------------
+class CommandObjectMemoryHistory : public CommandObjectParsed
+{
+public:
+
+ CommandObjectMemoryHistory (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "memory history",
+ "Prints out the recorded stack traces for allocation/deallocation of a memory address.",
+ NULL,
+ eFlagRequiresTarget | eFlagRequiresProcess | eFlagProcessMustBePaused | eFlagProcessMustBeLaunched)
+ {
+ CommandArgumentEntry arg1;
+ CommandArgumentData addr_arg;
+
+ // Define the first (and only) variant of this arg.
+ addr_arg.arg_type = eArgTypeAddress;
+ addr_arg.arg_repetition = eArgRepeatPlain;
+
+ // There is only one variant this argument could be; put it into the argument entry.
+ arg1.push_back (addr_arg);
+
+ // Push the data for the first argument into the m_arguments vector.
+ m_arguments.push_back (arg1);
+ }
+
+ virtual
+ ~CommandObjectMemoryHistory ()
+ {
+ }
+
+ virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
+ {
+ return m_cmd_name.c_str();
+ }
+
+protected:
+ virtual bool
+ DoExecute (Args& command, CommandReturnObject &result)
+ {
+ const size_t argc = command.GetArgumentCount();
+
+ if (argc == 0 || argc > 1)
+ {
+ result.AppendErrorWithFormat ("%s takes an address expression", m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ Error error;
+ lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
+ command.GetArgumentAtIndex(0),
+ LLDB_INVALID_ADDRESS,
+ &error);
+
+ if (addr == LLDB_INVALID_ADDRESS)
+ {
+ result.AppendError("invalid address expression");
+ result.AppendError(error.AsCString());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ Stream *output_stream = &result.GetOutputStream();
+
+ const ProcessSP &process_sp = m_exe_ctx.GetProcessSP();
+ const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(process_sp);
+
+ if (! memory_history.get())
+ {
+ result.AppendError("no available memory history provider");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ HistoryThreads thread_list = memory_history->GetHistoryThreads(addr);
+
+ for (auto thread : thread_list) {
+ thread->GetStatus(*output_stream, 0, UINT32_MAX, 0);
+ }
+
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+
+ return true;
+ }
+
+};
+
//-------------------------------------------------------------------------
// CommandObjectMemory
@@ -1681,6 +1773,7 @@ CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
LoadSubCommand ("find", CommandObjectSP (new CommandObjectMemoryFind (interpreter)));
LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
+ LoadSubCommand ("history", CommandObjectSP (new CommandObjectMemoryHistory (interpreter)));
}
CommandObjectMemory::~CommandObjectMemory ()
diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp
index cda55802fab..0cca76ee95e 100644
--- a/lldb/source/Core/PluginManager.cpp
+++ b/lldb/source/Core/PluginManager.cpp
@@ -2068,6 +2068,110 @@ PluginManager::GetUnwindAssemblyCreateCallbackForPluginName (const ConstString &
return NULL;
}
+#pragma mark MemoryHistory
+
+struct MemoryHistoryInstance
+{
+ MemoryHistoryInstance() :
+ name(),
+ description(),
+ create_callback(NULL)
+ {
+ }
+
+ ConstString name;
+ std::string description;
+ MemoryHistoryCreateInstance create_callback;
+};
+
+typedef std::vector<MemoryHistoryInstance> MemoryHistoryInstances;
+
+static Mutex &
+GetMemoryHistoryMutex ()
+{
+ static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
+ return g_instances_mutex;
+}
+
+static MemoryHistoryInstances &
+GetMemoryHistoryInstances ()
+{
+ static MemoryHistoryInstances g_instances;
+ return g_instances;
+}
+
+bool
+PluginManager::RegisterPlugin
+(
+ const ConstString &name,
+ const char *description,
+ MemoryHistoryCreateInstance create_callback
+ )
+{
+ if (create_callback)
+ {
+ MemoryHistoryInstance instance;
+ assert ((bool)name);
+ instance.name = name;
+ if (description && description[0])
+ instance.description = description;
+ instance.create_callback = create_callback;
+ Mutex::Locker locker (GetMemoryHistoryMutex ());
+ GetMemoryHistoryInstances ().push_back (instance);
+ }
+ return false;
+}
+
+bool
+PluginManager::UnregisterPlugin (MemoryHistoryCreateInstance create_callback)
+{
+ if (create_callback)
+ {
+ Mutex::Locker locker (GetMemoryHistoryMutex ());
+ MemoryHistoryInstances &instances = GetMemoryHistoryInstances ();
+
+ MemoryHistoryInstances::iterator pos, end = instances.end();
+ for (pos = instances.begin(); pos != end; ++ pos)
+ {
+ if (pos->create_callback == create_callback)
+ {
+ instances.erase(pos);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+MemoryHistoryCreateInstance
+PluginManager::GetMemoryHistoryCreateCallbackAtIndex (uint32_t idx)
+{
+ Mutex::Locker locker (GetMemoryHistoryMutex ());
+ MemoryHistoryInstances &instances = GetMemoryHistoryInstances ();
+ if (idx < instances.size())
+ return instances[idx].create_callback;
+ return NULL;
+}
+
+
+MemoryHistoryCreateInstance
+PluginManager::GetMemoryHistoryCreateCallbackForPluginName (const ConstString &name)
+{
+ if (name)
+ {
+ Mutex::Locker locker (GetMemoryHistoryMutex ());
+ MemoryHistoryInstances &instances = GetMemoryHistoryInstances ();
+
+ MemoryHistoryInstances::iterator pos, end = instances.end();
+ for (pos = instances.begin(); pos != end; ++ pos)
+ {
+ if (name == pos->name)
+ return pos->create_callback;
+ }
+ }
+ return NULL;
+}
+
void
PluginManager::DebuggerInitialize (Debugger &debugger)
{
diff --git a/lldb/source/Plugins/CMakeLists.txt b/lldb/source/Plugins/CMakeLists.txt
index 6b409ef4f97..b55936fc5af 100644
--- a/lldb/source/Plugins/CMakeLists.txt
+++ b/lldb/source/Plugins/CMakeLists.txt
@@ -4,6 +4,7 @@ add_subdirectory(DynamicLoader)
add_subdirectory(Instruction)
add_subdirectory(JITLoader)
add_subdirectory(LanguageRuntime)
+add_subdirectory(MemoryHistory)
add_subdirectory(ObjectContainer)
add_subdirectory(ObjectFile)
add_subdirectory(OperatingSystem)
diff --git a/lldb/source/Plugins/Makefile b/lldb/source/Plugins/Makefile
index 2427aea29a1..514ed3b6aa4 100644
--- a/lldb/source/Plugins/Makefile
+++ b/lldb/source/Plugins/Makefile
@@ -24,7 +24,8 @@ DIRS := ABI/MacOSX-arm ABI/MacOSX-arm64 ABI/MacOSX-i386 ABI/SysV-x86_64 ABI/SysV
DynamicLoader/POSIX-DYLD \
DynamicLoader/Hexagon-DYLD \
OperatingSystem/Python \
- SymbolVendor/ELF
+ SymbolVendor/ELF \
+ MemoryHistory/asan
ifeq ($(HOST_OS),Darwin)
DIRS += Process/MacOSX-Kernel
diff --git a/lldb/source/Plugins/MemoryHistory/CMakeLists.txt b/lldb/source/Plugins/MemoryHistory/CMakeLists.txt
new file mode 100644
index 00000000000..113f0636257
--- /dev/null
+++ b/lldb/source/Plugins/MemoryHistory/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(asan)
diff --git a/lldb/source/Plugins/MemoryHistory/asan/CMakeLists.txt b/lldb/source/Plugins/MemoryHistory/asan/CMakeLists.txt
new file mode 100644
index 00000000000..442a538d414
--- /dev/null
+++ b/lldb/source/Plugins/MemoryHistory/asan/CMakeLists.txt
@@ -0,0 +1,5 @@
+set(LLVM_NO_RTTI 1)
+
+add_lldb_library(lldbPluginMemoryHistoryASan
+ MemoryHistoryASan.cpp
+ )
diff --git a/lldb/source/Plugins/MemoryHistory/asan/Makefile b/lldb/source/Plugins/MemoryHistory/asan/Makefile
new file mode 100644
index 00000000000..86de6aba363
--- /dev/null
+++ b/lldb/source/Plugins/MemoryHistory/asan/Makefile
@@ -0,0 +1,14 @@
+##===- source/Plugins/MemoryHistory/asan/Makefile -------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LLDB_LEVEL := ../../../..
+LIBRARYNAME := lldbPluginMemoryHistoryASan
+BUILD_ARCHIVE = 1
+
+include $(LLDB_LEVEL)/Makefile
diff --git a/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp b/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
new file mode 100644
index 00000000000..0c0e6ab26e6
--- /dev/null
+++ b/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
@@ -0,0 +1,185 @@
+//===-- MemoryHistoryASan.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MemoryHistoryASan.h"
+
+#include "lldb/Target/MemoryHistory.h"
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/PluginInterface.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Target/ThreadList.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Core/Module.h"
+#include "Plugins/Process/Utility/HistoryThread.h"
+#include "lldb/Core/ValueObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+MemoryHistorySP
+MemoryHistoryASan::CreateInstance (const ProcessSP &process_sp)
+{
+ if (!process_sp.get())
+ return NULL;
+
+ Target & target = process_sp->GetTarget();
+
+ bool found_asan_runtime = false;
+
+ const ModuleList &target_modules = target.GetImages();
+ Mutex::Locker modules_locker(target_modules.GetMutex());
+ const size_t num_modules = target_modules.GetSize();
+ for (size_t i = 0; i < num_modules; ++i)
+ {
+ Module *module_pointer = target_modules.GetModulePointerAtIndexUnlocked(i);
+
+ SymbolContextList sc_list;
+ const bool include_symbols = true;
+ const bool append = true;
+ const bool include_inlines = true;
+
+ size_t num_matches = module_pointer->FindFunctions(ConstString("__asan_get_alloc_stack"), NULL, eFunctionNameTypeAuto, include_symbols, include_inlines, append, sc_list);
+
+ if (num_matches)
+ {
+ found_asan_runtime = true;
+ break;
+ }
+ }
+
+ if (! found_asan_runtime)
+ return MemoryHistorySP();
+
+ return MemoryHistorySP(new MemoryHistoryASan(process_sp));
+}
+
+void
+MemoryHistoryASan::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "ASan memory history provider.",
+ CreateInstance);
+}
+
+void
+MemoryHistoryASan::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+
+ConstString
+MemoryHistoryASan::GetPluginNameStatic()
+{
+ static ConstString g_name("asan");
+ return g_name;
+}
+
+MemoryHistoryASan::MemoryHistoryASan(const ProcessSP &process_sp)
+{
+ this->m_process_sp = process_sp;
+}
+
+const char *
+memory_history_asan_command_format = R"(
+ struct t {
+ void *alloc_trace[256];
+ size_t alloc_count;
+ int alloc_tid;
+
+ void *free_trace[256];
+ size_t free_count;
+ int free_tid;
+ } t;
+
+ t.alloc_count = ((size_t (*) (void *, void **, size_t, int *))__asan_get_alloc_stack)((void *)0x%)" PRIx64 R"(, t.alloc_trace, 256, &t.alloc_tid);
+ t.free_count = ((size_t (*) (void *, void **, size_t, int *))__asan_get_free_stack)((void *)0x%)" PRIx64 R"(, t.free_trace, 256, &t.free_tid);
+
+ t;
+)";
+
+#define GET_STACK_FUNCTION_TIMEOUT_USEC 2*1000*1000
+
+HistoryThreads
+MemoryHistoryASan::GetHistoryThreads(lldb::addr_t address)
+{
+ ProcessSP process_sp = m_process_sp;
+ ThreadSP thread_sp = m_process_sp->GetThreadList().GetSelectedThread();
+ StackFrameSP frame_sp = thread_sp->GetSelectedFrame();
+
+ if (!frame_sp)
+ {
+ return HistoryThreads();
+ }
+
+ ExecutionContext exe_ctx (frame_sp);
+ ValueObjectSP return_value_sp;
+ StreamString expr;
+ expr.Printf(memory_history_asan_command_format, address, address);
+
+ EvaluateExpressionOptions options;
+ options.SetUnwindOnError(true);
+ options.SetTryAllThreads(true);
+ options.SetStopOthers(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetTimeoutUsec(GET_STACK_FUNCTION_TIMEOUT_USEC);
+
+ if (m_process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), return_value_sp, options) != eExpressionCompleted)
+ {
+ return HistoryThreads();
+ }
+ if (!return_value_sp)
+ {
+ return HistoryThreads();
+ }
+
+ HistoryThreads result;
+
+ int alloc_count = return_value_sp->GetValueForExpressionPath(".alloc_count")->GetValueAsUnsigned(0);
+ int free_count = return_value_sp->GetValueForExpressionPath(".free_count")->GetValueAsUnsigned(0);
+ tid_t alloc_tid = return_value_sp->GetValueForExpressionPath(".alloc_tid")->GetValueAsUnsigned(0);
+ tid_t free_tid = return_value_sp->GetValueForExpressionPath(".free_tid")->GetValueAsUnsigned(0);
+
+ if (alloc_count > 0)
+ {
+ std::vector<lldb::addr_t> pcs;
+ ValueObjectSP trace_sp = return_value_sp->GetValueForExpressionPath(".alloc_trace");
+ for (int i = 0; i < alloc_count; i++) {
+ addr_t pc = trace_sp->GetChildAtIndex(i, true)->GetValueAsUnsigned(0);
+ pcs.push_back(pc);
+ }
+
+ HistoryThread *history_thread = new HistoryThread(*process_sp, alloc_tid, pcs, 0, false);
+ ThreadSP new_thread_sp(history_thread);
+ // let's use thread name for the type of history thread, since history threads don't have names anyway
+ history_thread->SetThreadName("Memory allocated at");
+ result.push_back(new_thread_sp);
+ }
+
+ if (free_count > 0)
+ {
+ std::vector<lldb::addr_t> pcs;
+ ValueObjectSP trace_sp = return_value_sp->GetValueForExpressionPath(".free_trace");
+ for (int i = 0; i < free_count; i++) {
+ addr_t pc = trace_sp->GetChildAtIndex(i, true)->GetValueAsUnsigned(0);
+ pcs.push_back(pc);
+ }
+
+ HistoryThread *history_thread = new HistoryThread(*process_sp, free_tid, pcs, 0, false);
+ ThreadSP new_thread_sp(history_thread);
+ // let's use thread name for the type of history thread, since history threads don't have names anyway
+ history_thread->SetThreadName("Memory deallocated at");
+ result.push_back(new_thread_sp);
+ }
+
+ return result;
+}
diff --git a/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h b/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h
new file mode 100644
index 00000000000..5307e0b3408
--- /dev/null
+++ b/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h
@@ -0,0 +1,62 @@
+//===-- MemoryHistoryASan.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_MemoryHistoryASan_h_
+#define liblldb_MemoryHistoryASan_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/ABI.h"
+#include "lldb/Target/MemoryHistory.h"
+#include "lldb/Target/Process.h"
+
+namespace lldb_private {
+
+class MemoryHistoryASan : public lldb_private::MemoryHistory
+{
+public:
+
+ static lldb::MemoryHistorySP
+ CreateInstance (const lldb::ProcessSP &process_sp);
+
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ virtual
+ ~MemoryHistoryASan () {}
+
+ virtual lldb_private::ConstString
+ GetPluginName() { return GetPluginNameStatic(); }
+
+ virtual uint32_t
+ GetPluginVersion() { return 1; }
+
+ virtual lldb_private::HistoryThreads
+ GetHistoryThreads(lldb::addr_t address);
+
+private:
+
+ MemoryHistoryASan(const lldb::ProcessSP &process_sp);
+
+ lldb::ProcessSP m_process_sp;
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_MemoryHistoryASan_h_
diff --git a/lldb/source/Plugins/Process/Utility/HistoryThread.h b/lldb/source/Plugins/Process/Utility/HistoryThread.h
index f9a431d8340..51173c626d7 100644
--- a/lldb/source/Plugins/Process/Utility/HistoryThread.h
+++ b/lldb/source/Plugins/Process/Utility/HistoryThread.h
@@ -101,6 +101,18 @@ public:
{
m_thread_name = name;
}
+
+ virtual const char *
+ GetName ()
+ {
+ return m_thread_name.c_str();
+ }
+
+ virtual void
+ SetName(const char *name)
+ {
+ m_thread_name = name;
+ }
protected:
virtual lldb::StackFrameListSP
diff --git a/lldb/source/Target/CMakeLists.txt b/lldb/source/Target/CMakeLists.txt
index c7b22e05bd5..3dc3617d8ea 100644
--- a/lldb/source/Target/CMakeLists.txt
+++ b/lldb/source/Target/CMakeLists.txt
@@ -11,6 +11,7 @@ add_lldb_library(lldbTarget
JITLoaderList.cpp
LanguageRuntime.cpp
Memory.cpp
+ MemoryHistory.cpp
NativeRegisterContext.cpp
NativeRegisterContextRegisterInfo.cpp
ObjCLanguageRuntime.cpp
diff --git a/lldb/source/Target/MemoryHistory.cpp b/lldb/source/Target/MemoryHistory.cpp
new file mode 100644
index 00000000000..53d675ab09e
--- /dev/null
+++ b/lldb/source/Target/MemoryHistory.cpp
@@ -0,0 +1,28 @@
+//===-- MemoryHistory.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/Target/MemoryHistory.h"
+
+#include "lldb/Core/PluginManager.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+lldb::MemoryHistorySP
+MemoryHistory::FindPlugin (const ProcessSP process)
+{
+ MemoryHistoryCreateInstance create_callback = NULL;
+
+ for (uint32_t idx = 0; (create_callback = PluginManager::GetMemoryHistoryCreateCallbackAtIndex(idx)) != NULL; ++idx)
+ {
+ return create_callback(process);
+ }
+
+ return MemoryHistorySP();
+}
diff --git a/lldb/source/lldb.cpp b/lldb/source/lldb.cpp
index cd620b7945b..cb2af8a081d 100644
--- a/lldb/source/lldb.cpp
+++ b/lldb/source/lldb.cpp
@@ -92,6 +92,7 @@
#include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h"
#include "Plugins/Process/gdb-remote/ProcessGDBRemote.h"
#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h"
+#include "Plugins/MemoryHistory/asan/MemoryHistoryASan.h"
using namespace lldb;
using namespace lldb_private;
@@ -154,6 +155,7 @@ lldb_private::Initialize ()
#endif
JITLoaderGDB::Initialize();
ProcessElfCore::Initialize();
+ MemoryHistoryASan::Initialize();
#if defined (__APPLE__)
//----------------------------------------------------------------------
@@ -244,6 +246,7 @@ lldb_private::Terminate ()
#endif
JITLoaderGDB::Terminate();
ProcessElfCore::Terminate();
+ MemoryHistoryASan::Terminate();
#if defined (__APPLE__)
DynamicLoaderMacOSXDYLD::Terminate();
OpenPOWER on IntegriCloud