ASan malloc/free history threads

Reviewed at http://reviews.llvm.org/D4596

llvm-svn: 217116
diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp
index bfbb296..8144f48 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 @@
     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 @@
     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 ()