<div dir="ltr">Nice addition, Kuba!  I look forward to working with that :-)</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Sep 3, 2014 at 6:03 PM, Kuba Brecka <span dir="ltr"><<a href="mailto:kuba.brecka@gmail.com" target="_blank">kuba.brecka@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: kuba.brecka<br>
Date: Wed Sep  3 20:03:18 2014<br>
New Revision: 217116<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=217116&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=217116&view=rev</a><br>
Log:<br>
ASan malloc/free history threads<br>
<br>
Reviewed at <a href="http://reviews.llvm.org/D4596" target="_blank">http://reviews.llvm.org/D4596</a><br>
<br>
<br>
Added:<br>
    lldb/trunk/include/lldb/Target/MemoryHistory.h<br>
    lldb/trunk/source/Plugins/MemoryHistory/<br>
    lldb/trunk/source/Plugins/MemoryHistory/CMakeLists.txt<br>
    lldb/trunk/source/Plugins/MemoryHistory/asan/<br>
    lldb/trunk/source/Plugins/MemoryHistory/asan/CMakeLists.txt<br>
    lldb/trunk/source/Plugins/MemoryHistory/asan/Makefile<br>
    lldb/trunk/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp<br>
    lldb/trunk/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h<br>
    lldb/trunk/source/Target/MemoryHistory.cpp<br>
    lldb/trunk/test/functionalities/asan/<br>
    lldb/trunk/test/functionalities/asan/Makefile<br>
    lldb/trunk/test/functionalities/asan/TestAsan.py<br>
    lldb/trunk/test/functionalities/asan/main.c<br>
Modified:<br>
    lldb/trunk/include/lldb/Core/PluginManager.h<br>
    lldb/trunk/include/lldb/lldb-forward.h<br>
    lldb/trunk/include/lldb/lldb-private-interfaces.h<br>
    lldb/trunk/lldb.xcodeproj/project.pbxproj<br>
    lldb/trunk/source/CMakeLists.txt<br>
    lldb/trunk/source/Commands/CommandObjectMemory.cpp<br>
    lldb/trunk/source/Core/PluginManager.cpp<br>
    lldb/trunk/source/Plugins/CMakeLists.txt<br>
    lldb/trunk/source/Plugins/Makefile<br>
    lldb/trunk/source/Plugins/Process/Utility/HistoryThread.h<br>
    lldb/trunk/source/Target/CMakeLists.txt<br>
    lldb/trunk/source/lldb.cpp<br>
    lldb/trunk/test/lldbtest.py<br>
<br>
Modified: lldb/trunk/include/lldb/Core/PluginManager.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/PluginManager.h?rev=217116&r1=217115&r2=217116&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/PluginManager.h?rev=217116&r1=217115&r2=217116&view=diff</a><br>

==============================================================================<br>
--- lldb/trunk/include/lldb/Core/PluginManager.h (original)<br>
+++ lldb/trunk/include/lldb/Core/PluginManager.h Wed Sep  3 20:03:18 2014<br>
@@ -342,6 +342,23 @@ public:<br>
<br>
     static UnwindAssemblyCreateInstance<br>
     GetUnwindAssemblyCreateCallbackForPluginName (const ConstString &name);<br>
+<br>
+    //------------------------------------------------------------------<br>
+    // MemoryHistory<br>
+    //------------------------------------------------------------------<br>
+    static bool<br>
+    RegisterPlugin (const ConstString &name,<br>
+                    const char *description,<br>
+                    MemoryHistoryCreateInstance create_callback);<br>
+<br>
+    static bool<br>
+    UnregisterPlugin (MemoryHistoryCreateInstance create_callback);<br>
+<br>
+    static MemoryHistoryCreateInstance<br>
+    GetMemoryHistoryCreateCallbackAtIndex (uint32_t idx);<br>
+<br>
+    static MemoryHistoryCreateInstance<br>
+    GetMemoryHistoryCreateCallbackForPluginName (const ConstString &name);<br>
<br>
     //------------------------------------------------------------------<br>
     // Some plug-ins might register a DebuggerInitializeCallback<br>
<br>
Added: lldb/trunk/include/lldb/Target/MemoryHistory.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/MemoryHistory.h?rev=217116&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/MemoryHistory.h?rev=217116&view=auto</a><br>

==============================================================================<br>
--- lldb/trunk/include/lldb/Target/MemoryHistory.h (added)<br>
+++ lldb/trunk/include/lldb/Target/MemoryHistory.h Wed Sep  3 20:03:18 2014<br>
@@ -0,0 +1,42 @@<br>
+//===-- MemoryHistory.h ---------------------------------------------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef liblldb_MemoryHistory_h_<br>
+#define liblldb_MemoryHistory_h_<br>
+<br>
+// C Includes<br>
+// C++ Includes<br>
+#include <vector><br>
+<br>
+// Other libraries and framework includes<br>
+// Project includes<br>
+#include "lldb/lldb-private.h"<br>
+#include "lldb/lldb-types.h"<br>
+#include "lldb/Core/PluginInterface.h"<br>
+<br>
+namespace lldb_private {<br>
+<br>
+typedef std::vector<lldb::ThreadSP> HistoryThreads;<br>
+<br>
+class MemoryHistory :<br>
+    public std::enable_shared_from_this<MemoryHistory>,<br>
+    public PluginInterface<br>
+{<br>
+public:<br>
+<br>
+    static lldb::MemoryHistorySP<br>
+    FindPlugin (const lldb::ProcessSP process);<br>
+<br>
+    virtual HistoryThreads<br>
+    GetHistoryThreads(lldb::addr_t address) = 0;<br>
+};<br>
+<br>
+} // namespace lldb_private<br>
+<br>
+#endif  // liblldb_MemoryHistory_h_<br>
<br>
Modified: lldb/trunk/include/lldb/lldb-forward.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward.h?rev=217116&r1=217115&r2=217116&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward.h?rev=217116&r1=217115&r2=217116&view=diff</a><br>

==============================================================================<br>
--- lldb/trunk/include/lldb/lldb-forward.h (original)<br>
+++ lldb/trunk/include/lldb/lldb-forward.h Wed Sep  3 20:03:18 2014<br>
@@ -116,6 +116,7 @@ class   Log;<br>
 class   LogChannel;<br>
 class   Mangled;<br>
 class   Materializer;<br>
+class   MemoryHistory;<br>
 class   Module;<br>
 class   ModuleList;<br>
 class   ModuleSpec;<br>
@@ -316,6 +317,7 @@ namespace lldb {<br>
     typedef std::shared_ptr<lldb_private::LineTable> LineTableSP;<br>
     typedef std::shared_ptr<lldb_private::Listener> ListenerSP;<br>
     typedef std::shared_ptr<lldb_private::LogChannel> LogChannelSP;<br>
+    typedef std::shared_ptr<lldb_private::MemoryHistory> MemoryHistorySP;<br>
     typedef std::shared_ptr<lldb_private::Module> ModuleSP;<br>
     typedef std::weak_ptr<lldb_private::Module> ModuleWP;<br>
     typedef std::shared_ptr<lldb_private::ObjectFile> ObjectFileSP;<br>
<br>
Modified: lldb/trunk/include/lldb/lldb-private-interfaces.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-private-interfaces.h?rev=217116&r1=217115&r2=217116&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-private-interfaces.h?rev=217116&r1=217115&r2=217116&view=diff</a><br>

==============================================================================<br>
--- lldb/trunk/include/lldb/lldb-private-interfaces.h (original)<br>
+++ lldb/trunk/include/lldb/lldb-private-interfaces.h Wed Sep  3 20:03:18 2014<br>
@@ -39,6 +39,7 @@ namespace lldb_private<br>
     typedef bool (*ThreadPlanShouldStopHereCallback) (ThreadPlan *current_plan, Flags &flags, lldb::FrameComparison operation, void *baton);<br>
     typedef lldb::ThreadPlanSP (*ThreadPlanStepFromHereCallback) (ThreadPlan *current_plan, Flags &flags, lldb::FrameComparison operation, void *baton);<br>
     typedef UnwindAssembly* (*UnwindAssemblyCreateInstance) (const ArchSpec &arch);<br>
+    typedef lldb::MemoryHistorySP (*MemoryHistoryCreateInstance) (const lldb::ProcessSP &process_sp);<br>
     typedef int (*ComparisonFunction)(const void *, const void *);<br>
     typedef void (*DebuggerInitializeCallback)(Debugger &debugger);<br>
<br>
<br>
Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=217116&r1=217115&r2=217116&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=217116&r1=217115&r2=217116&view=diff</a><br>

==============================================================================<br>
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)<br>
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Wed Sep  3 20:03:18 2014<br>
@@ -618,6 +618,8 @@<br>
                4CF3D80C15AF4DC800845BF3 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDB919B414F6F10D008FF64B /* Security.framework */; };<br>
                4CF52AF51428291E0051E832 /* SBFileSpecList.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF52AF41428291E0051E832 /* SBFileSpecList.h */; settings = {ATTRIBUTES = (Public, ); }; };<br>
                4CF52AF8142829390051E832 /* SBFileSpecList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF52AF7142829390051E832 /* SBFileSpecList.cpp */; };<br>
+               8C2D6A53197A1EAF006989C9 /* MemoryHistory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C2D6A52197A1EAF006989C9 /* MemoryHistory.cpp */; };<br>
+               8C2D6A5E197A250F006989C9 /* MemoryHistoryASan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C2D6A5A197A1FDC006989C9 /* MemoryHistoryASan.cpp */; };<br>
                94094C6B163B6F840083A547 /* ValueObjectCast.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94094C69163B6CD90083A547 /* ValueObjectCast.cpp */; };<br>
                94145431175E63B500284436 /* lldb-versioning.h in Headers */ = {isa = PBXBuildFile; fileRef = 94145430175D7FDE00284436 /* lldb-versioning.h */; settings = {ATTRIBUTES = (Public, ); }; };<br>
                941BCC7F14E48C4000BB969C /* SBTypeFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 9461568614E355F2003A195C /* SBTypeFilter.h */; settings = {ATTRIBUTES = (Public, ); }; };<br>
@@ -1894,6 +1896,10 @@<br>
                69A01E1E1236C5D400C660B5 /* Mutex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Mutex.cpp; sourceTree = "<group>"; };<br>
                69A01E1F1236C5D400C660B5 /* Symbols.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Symbols.cpp; sourceTree = "<group>"; };<br>
                69A01E201236C5D400C660B5 /* TimeValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimeValue.cpp; sourceTree = "<group>"; };<br>
+               8C2D6A52197A1EAF006989C9 /* MemoryHistory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MemoryHistory.cpp; path = source/Target/MemoryHistory.cpp; sourceTree = "<group>"; };<br>

+               8C2D6A54197A1EBE006989C9 /* MemoryHistory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MemoryHistory.h; path = include/lldb/Target/MemoryHistory.h; sourceTree = "<group>"; };<br>

+               8C2D6A5A197A1FDC006989C9 /* MemoryHistoryASan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemoryHistoryASan.cpp; sourceTree = "<group>"; };<br>

+               8C2D6A5B197A1FDC006989C9 /* MemoryHistoryASan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryHistoryASan.h; sourceTree = "<group>"; };<br>

                94005E0313F438DF001EF42D /* python-wrapper.swig */ = {isa = PBXFileReference; lastKnownFileType = text; path = "python-wrapper.swig"; sourceTree = "<group>"; };<br>
                94005E0513F45A1B001EF42D /* embedded_interpreter.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; name = embedded_interpreter.py; path = source/Interpreter/embedded_interpreter.py; sourceTree = "<group>"; };<br>

                94031A9F13CF5B3D00DCFF3C /* PriorityPointerPair.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PriorityPointerPair.h; path = include/lldb/Utility/PriorityPointerPair.h; sourceTree = "<group>"; };<br>

@@ -2338,6 +2344,7 @@<br>
                260C897110F57C5600BB2B04 /* Plugins */ = {<br>
                        isa = PBXGroup;<br>
                        children = (<br>
+                               8C2D6A58197A1FB9006989C9 /* MemoryHistory */,<br>
                                26DB3E051379E7AD0080DC73 /* ABI */,<br>
                                260C897210F57C5600BB2B04 /* Disassembler */,<br>
                                260C897810F57C5600BB2B04 /* DynamicLoader */,<br>
@@ -3661,6 +3668,8 @@<br>
                                4CB4430A12491DDA00C13DC2 /* LanguageRuntime.cpp */,<br>
                                2690B36F1381D5B600ECFBAE /* Memory.h */,<br>
                                2690B3701381D5C300ECFBAE /* Memory.cpp */,<br>
+                               8C2D6A54197A1EBE006989C9 /* MemoryHistory.h */,<br>
+                               8C2D6A52197A1EAF006989C9 /* MemoryHistory.cpp */,<br>
                                2360092C193FB21500189DB1 /* MemoryRegionInfo.h */,<br>
                                4CB443F612499B6E00C13DC2 /* ObjCLanguageRuntime.h */,<br>
                                4CB443F212499B5000C13DC2 /* ObjCLanguageRuntime.cpp */,<br>
@@ -4114,6 +4123,23 @@<br>
                        path = source/Host/common;<br>
                        sourceTree = "<group>";<br>
                };<br>
+               8C2D6A58197A1FB9006989C9 /* MemoryHistory */ = {<br>
+                       isa = PBXGroup;<br>
+                       children = (<br>
+                               8C2D6A59197A1FCD006989C9 /* asan */,<br>
+                       );<br>
+                       path = MemoryHistory;<br>
+                       sourceTree = "<group>";<br>
+               };<br>
+               8C2D6A59197A1FCD006989C9 /* asan */ = {<br>
+                       isa = PBXGroup;<br>
+                       children = (<br>
+                               8C2D6A5A197A1FDC006989C9 /* MemoryHistoryASan.cpp */,<br>
+                               8C2D6A5B197A1FDC006989C9 /* MemoryHistoryASan.h */,<br>
+                       );<br>
+                       path = asan;<br>
+                       sourceTree = "<group>";<br>
+               };<br>
                9457596415349416005A9070 /* POSIX */ = {<br>
                        isa = PBXGroup;<br>
                        children = (<br>
@@ -4903,6 +4929,7 @@<br>
                                2689005A13353E0400698AC0 /* ValueObjectList.cpp in Sources */,<br>
                                2689005B13353E0400698AC0 /* ValueObjectRegister.cpp in Sources */,<br>
                                2689005C13353E0400698AC0 /* ValueObjectVariable.cpp in Sources */,<br>
+                               8C2D6A53197A1EAF006989C9 /* MemoryHistory.cpp in Sources */,<br>
                                2689005D13353E0400698AC0 /* VMRange.cpp in Sources */,<br>
                                2689005E13353E0E00698AC0 /* ClangASTSource.cpp in Sources */,<br>
                                2689005F13353E0E00698AC0 /* ClangFunction.cpp in Sources */,<br>
@@ -5126,6 +5153,7 @@<br>
                                264A1300137252C700875C42 /* ARM64_DWARF_Registers.cpp in Sources */,<br>
                                26DB3E161379E7AD0080DC73 /* ABIMacOSX_arm.cpp in Sources */,<br>
                                26DB3E191379E7AD0080DC73 /* ABIMacOSX_arm64.cpp in Sources */,<br>
+                               8C2D6A5E197A250F006989C9 /* MemoryHistoryASan.cpp in Sources */,<br>
                                26DB3E1C1379E7AD0080DC73 /* ABIMacOSX_i386.cpp in Sources */,<br>
                                26DB3E1F1379E7AD0080DC73 /* ABISysV_x86_64.cpp in Sources */,<br>
                                232CB61D191E00CD00EF39FC /* SoftwareBreakpoint.cpp in Sources */,<br>
<br>
Modified: lldb/trunk/source/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/CMakeLists.txt?rev=217116&r1=217115&r2=217116&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/CMakeLists.txt?rev=217116&r1=217115&r2=217116&view=diff</a><br>

==============================================================================<br>
--- lldb/trunk/source/CMakeLists.txt (original)<br>
+++ lldb/trunk/source/CMakeLists.txt Wed Sep  3 20:03:18 2014<br>
@@ -84,6 +84,7 @@ set( LLDB_USED_LIBS<br>
   lldbPluginInstructionARM64<br>
   lldbPluginObjectFilePECOFF<br>
   lldbPluginOSPython<br>
+  lldbPluginMemoryHistoryASan<br>
   )<br>
<br>
 # Need to export the API in the liblldb.dll for Windows<br>
<br>
Modified: lldb/trunk/source/Commands/CommandObjectMemory.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectMemory.cpp?rev=217116&r1=217115&r2=217116&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectMemory.cpp?rev=217116&r1=217115&r2=217116&view=diff</a><br>

==============================================================================<br>
--- lldb/trunk/source/Commands/CommandObjectMemory.cpp (original)<br>
+++ lldb/trunk/source/Commands/CommandObjectMemory.cpp Wed Sep  3 20:03:18 2014<br>
@@ -33,8 +33,10 @@<br>
 #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"<br>
 #include "lldb/Interpreter/OptionValueString.h"<br>
 #include "lldb/Symbol/TypeList.h"<br>
+#include "lldb/Target/MemoryHistory.h"<br>
 #include "lldb/Target/Process.h"<br>
 #include "lldb/Target/StackFrame.h"<br>
+#include "lldb/Target/Thread.h"<br>
<br>
 using namespace lldb;<br>
 using namespace lldb_private;<br>
@@ -1667,6 +1669,96 @@ protected:<br>
     OptionGroupWriteMemory m_memory_options;<br>
 };<br>
<br>
+//----------------------------------------------------------------------<br>
+// Get malloc/free history of a memory address.<br>
+//----------------------------------------------------------------------<br>
+class CommandObjectMemoryHistory : public CommandObjectParsed<br>
+{<br>
+public:<br>
+<br>
+    CommandObjectMemoryHistory (CommandInterpreter &interpreter) :<br>
+    CommandObjectParsed (interpreter,<br>
+                         "memory history",<br>
+                         "Prints out the recorded stack traces for allocation/deallocation of a memory address.",<br>
+                         NULL,<br>
+                         eFlagRequiresTarget | eFlagRequiresProcess | eFlagProcessMustBePaused | eFlagProcessMustBeLaunched)<br>
+    {<br>
+        CommandArgumentEntry arg1;<br>
+        CommandArgumentData addr_arg;<br>
+<br>
+        // Define the first (and only) variant of this arg.<br>
+        addr_arg.arg_type = eArgTypeAddress;<br>
+        addr_arg.arg_repetition = eArgRepeatPlain;<br>
+<br>
+        // There is only one variant this argument could be; put it into the argument entry.<br>
+        arg1.push_back (addr_arg);<br>
+<br>
+        // Push the data for the first argument into the m_arguments vector.<br>
+        m_arguments.push_back (arg1);<br>
+    }<br>
+<br>
+    virtual<br>
+    ~CommandObjectMemoryHistory ()<br>
+    {<br>
+    }<br>
+<br>
+    virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)<br>
+    {<br>
+        return m_cmd_name.c_str();<br>
+    }<br>
+<br>
+protected:<br>
+    virtual bool<br>
+    DoExecute (Args& command, CommandReturnObject &result)<br>
+    {<br>
+        const size_t argc = command.GetArgumentCount();<br>
+<br>
+        if (argc == 0 || argc > 1)<br>
+        {<br>
+            result.AppendErrorWithFormat ("%s takes an address expression", m_cmd_name.c_str());<br>
+            result.SetStatus(eReturnStatusFailed);<br>
+            return false;<br>
+        }<br>
+<br>
+        Error error;<br>
+        lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,<br>
+                                                   command.GetArgumentAtIndex(0),<br>
+                                                   LLDB_INVALID_ADDRESS,<br>
+                                                   &error);<br>
+<br>
+        if (addr == LLDB_INVALID_ADDRESS)<br>
+        {<br>
+            result.AppendError("invalid address expression");<br>
+            result.AppendError(error.AsCString());<br>
+            result.SetStatus(eReturnStatusFailed);<br>
+            return false;<br>
+        }<br>
+<br>
+        Stream *output_stream = &result.GetOutputStream();<br>
+<br>
+        const ProcessSP &process_sp = m_exe_ctx.GetProcessSP();<br>
+        const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(process_sp);<br>
+<br>
+        if (! memory_history.get())<br>
+        {<br>
+            result.AppendError("no available memory history provider");<br>
+            result.SetStatus(eReturnStatusFailed);<br>
+            return false;<br>
+        }<br>
+<br>
+        HistoryThreads thread_list = memory_history->GetHistoryThreads(addr);<br>
+<br>
+        for (auto thread : thread_list) {<br>
+            thread->GetStatus(*output_stream, 0, UINT32_MAX, 0);<br>
+        }<br>
+<br>
+        result.SetStatus(eReturnStatusSuccessFinishResult);<br>
+<br>
+        return true;<br>
+    }<br>
+<br>
+};<br>
+<br>
<br>
 //-------------------------------------------------------------------------<br>
 // CommandObjectMemory<br>
@@ -1681,6 +1773,7 @@ CommandObjectMemory::CommandObjectMemory<br>
     LoadSubCommand ("find", CommandObjectSP (new CommandObjectMemoryFind (interpreter)));<br>
     LoadSubCommand ("read",  CommandObjectSP (new CommandObjectMemoryRead (interpreter)));<br>
     LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));<br>
+    LoadSubCommand ("history", CommandObjectSP (new CommandObjectMemoryHistory (interpreter)));<br>
 }<br>
<br>
 CommandObjectMemory::~CommandObjectMemory ()<br>
<br>
Modified: lldb/trunk/source/Core/PluginManager.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/PluginManager.cpp?rev=217116&r1=217115&r2=217116&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/PluginManager.cpp?rev=217116&r1=217115&r2=217116&view=diff</a><br>

==============================================================================<br>
--- lldb/trunk/source/Core/PluginManager.cpp (original)<br>
+++ lldb/trunk/source/Core/PluginManager.cpp Wed Sep  3 20:03:18 2014<br>
@@ -2068,6 +2068,110 @@ PluginManager::GetUnwindAssemblyCreateCa<br>
     return NULL;<br>
 }<br>
<br>
+#pragma mark MemoryHistory<br>
+<br>
+struct MemoryHistoryInstance<br>
+{<br>
+    MemoryHistoryInstance() :<br>
+    name(),<br>
+    description(),<br>
+    create_callback(NULL)<br>
+    {<br>
+    }<br>
+<br>
+    ConstString name;<br>
+    std::string description;<br>
+    MemoryHistoryCreateInstance create_callback;<br>
+};<br>
+<br>
+typedef std::vector<MemoryHistoryInstance> MemoryHistoryInstances;<br>
+<br>
+static Mutex &<br>
+GetMemoryHistoryMutex ()<br>
+{<br>
+    static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);<br>
+    return g_instances_mutex;<br>
+}<br>
+<br>
+static MemoryHistoryInstances &<br>
+GetMemoryHistoryInstances ()<br>
+{<br>
+    static MemoryHistoryInstances g_instances;<br>
+    return g_instances;<br>
+}<br>
+<br>
+bool<br>
+PluginManager::RegisterPlugin<br>
+(<br>
+ const ConstString &name,<br>
+ const char *description,<br>
+ MemoryHistoryCreateInstance create_callback<br>
+ )<br>
+{<br>
+    if (create_callback)<br>
+    {<br>
+        MemoryHistoryInstance instance;<br>
+        assert ((bool)name);<br>
+        <a href="http://instance.name" target="_blank">instance.name</a> = name;<br>
+        if (description && description[0])<br>
+            instance.description = description;<br>
+        instance.create_callback = create_callback;<br>
+        Mutex::Locker locker (GetMemoryHistoryMutex ());<br>
+        GetMemoryHistoryInstances ().push_back (instance);<br>
+    }<br>
+    return false;<br>
+}<br>
+<br>
+bool<br>
+PluginManager::UnregisterPlugin (MemoryHistoryCreateInstance create_callback)<br>
+{<br>
+    if (create_callback)<br>
+    {<br>
+        Mutex::Locker locker (GetMemoryHistoryMutex ());<br>
+        MemoryHistoryInstances &instances = GetMemoryHistoryInstances ();<br>
+<br>
+        MemoryHistoryInstances::iterator pos, end = instances.end();<br>
+        for (pos = instances.begin(); pos != end; ++ pos)<br>
+        {<br>
+            if (pos->create_callback == create_callback)<br>
+            {<br>
+                instances.erase(pos);<br>
+                return true;<br>
+            }<br>
+        }<br>
+    }<br>
+    return false;<br>
+}<br>
+<br>
+MemoryHistoryCreateInstance<br>
+PluginManager::GetMemoryHistoryCreateCallbackAtIndex (uint32_t idx)<br>
+{<br>
+    Mutex::Locker locker (GetMemoryHistoryMutex ());<br>
+    MemoryHistoryInstances &instances = GetMemoryHistoryInstances ();<br>
+    if (idx < instances.size())<br>
+        return instances[idx].create_callback;<br>
+    return NULL;<br>
+}<br>
+<br>
+<br>
+MemoryHistoryCreateInstance<br>
+PluginManager::GetMemoryHistoryCreateCallbackForPluginName (const ConstString &name)<br>
+{<br>
+    if (name)<br>
+    {<br>
+        Mutex::Locker locker (GetMemoryHistoryMutex ());<br>
+        MemoryHistoryInstances &instances = GetMemoryHistoryInstances ();<br>
+<br>
+        MemoryHistoryInstances::iterator pos, end = instances.end();<br>
+        for (pos = instances.begin(); pos != end; ++ pos)<br>
+        {<br>
+            if (name == pos->name)<br>
+                return pos->create_callback;<br>
+        }<br>
+    }<br>
+    return NULL;<br>
+}<br>
+<br>
 void<br>
 PluginManager::DebuggerInitialize (Debugger &debugger)<br>
 {<br>
<br>
Modified: lldb/trunk/source/Plugins/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/CMakeLists.txt?rev=217116&r1=217115&r2=217116&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/CMakeLists.txt?rev=217116&r1=217115&r2=217116&view=diff</a><br>

==============================================================================<br>
--- lldb/trunk/source/Plugins/CMakeLists.txt (original)<br>
+++ lldb/trunk/source/Plugins/CMakeLists.txt Wed Sep  3 20:03:18 2014<br>
@@ -4,6 +4,7 @@ add_subdirectory(DynamicLoader)<br>
 add_subdirectory(Instruction)<br>
 add_subdirectory(JITLoader)<br>
 add_subdirectory(LanguageRuntime)<br>
+add_subdirectory(MemoryHistory)<br>
 add_subdirectory(ObjectContainer)<br>
 add_subdirectory(ObjectFile)<br>
 add_subdirectory(OperatingSystem)<br>
<br>
Modified: lldb/trunk/source/Plugins/Makefile<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Makefile?rev=217116&r1=217115&r2=217116&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Makefile?rev=217116&r1=217115&r2=217116&view=diff</a><br>

==============================================================================<br>
--- lldb/trunk/source/Plugins/Makefile (original)<br>
+++ lldb/trunk/source/Plugins/Makefile Wed Sep  3 20:03:18 2014<br>
@@ -24,7 +24,8 @@ DIRS := ABI/MacOSX-arm ABI/MacOSX-arm64<br>
        DynamicLoader/POSIX-DYLD \<br>
        DynamicLoader/Hexagon-DYLD \<br>
        OperatingSystem/Python \<br>
-       SymbolVendor/ELF<br>
+       SymbolVendor/ELF \<br>
+       MemoryHistory/asan<br>
<br>
 ifeq ($(HOST_OS),Darwin)<br>
 DIRS += Process/MacOSX-Kernel<br>
<br>
Added: lldb/trunk/source/Plugins/MemoryHistory/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/MemoryHistory/CMakeLists.txt?rev=217116&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/MemoryHistory/CMakeLists.txt?rev=217116&view=auto</a><br>

==============================================================================<br>
--- lldb/trunk/source/Plugins/MemoryHistory/CMakeLists.txt (added)<br>
+++ lldb/trunk/source/Plugins/MemoryHistory/CMakeLists.txt Wed Sep  3 20:03:18 2014<br>
@@ -0,0 +1 @@<br>
+add_subdirectory(asan)<br>
<br>
Added: lldb/trunk/source/Plugins/MemoryHistory/asan/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/MemoryHistory/asan/CMakeLists.txt?rev=217116&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/MemoryHistory/asan/CMakeLists.txt?rev=217116&view=auto</a><br>

==============================================================================<br>
--- lldb/trunk/source/Plugins/MemoryHistory/asan/CMakeLists.txt (added)<br>
+++ lldb/trunk/source/Plugins/MemoryHistory/asan/CMakeLists.txt Wed Sep  3 20:03:18 2014<br>
@@ -0,0 +1,5 @@<br>
+set(LLVM_NO_RTTI 1)<br>
+<br>
+add_lldb_library(lldbPluginMemoryHistoryASan<br>
+  MemoryHistoryASan.cpp<br>
+  )<br>
<br>
Added: lldb/trunk/source/Plugins/MemoryHistory/asan/Makefile<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/MemoryHistory/asan/Makefile?rev=217116&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/MemoryHistory/asan/Makefile?rev=217116&view=auto</a><br>

==============================================================================<br>
--- lldb/trunk/source/Plugins/MemoryHistory/asan/Makefile (added)<br>
+++ lldb/trunk/source/Plugins/MemoryHistory/asan/Makefile Wed Sep  3 20:03:18 2014<br>
@@ -0,0 +1,14 @@<br>
+##===- source/Plugins/MemoryHistory/asan/Makefile -------------*- Makefile -*-===##<br>
+#<br>
+#                     The LLVM Compiler Infrastructure<br>
+#<br>
+# This file is distributed under the University of Illinois Open Source<br>
+# License. See LICENSE.TXT for details.<br>
+#<br>
+##===----------------------------------------------------------------------===##<br>
+<br>
+LLDB_LEVEL := ../../../..<br>
+LIBRARYNAME := lldbPluginMemoryHistoryASan<br>
+BUILD_ARCHIVE = 1<br>
+<br>
+include $(LLDB_LEVEL)/Makefile<br>
<br>
Added: lldb/trunk/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp?rev=217116&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp?rev=217116&view=auto</a><br>

==============================================================================<br>
--- lldb/trunk/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp (added)<br>
+++ lldb/trunk/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp Wed Sep  3 20:03:18 2014<br>
@@ -0,0 +1,185 @@<br>
+//===-- MemoryHistoryASan.cpp -----------------------------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "MemoryHistoryASan.h"<br>
+<br>
+#include "lldb/Target/MemoryHistory.h"<br>
+<br>
+#include "lldb/lldb-private.h"<br>
+#include "lldb/Core/PluginInterface.h"<br>
+#include "lldb/Core/PluginManager.h"<br>
+#include "lldb/Target/ThreadList.h"<br>
+#include "lldb/Target/ExecutionContext.h"<br>
+#include "lldb/Target/Target.h"<br>
+#include "lldb/Target/Thread.h"<br>
+#include "lldb/Core/Module.h"<br>
+#include "Plugins/Process/Utility/HistoryThread.h"<br>
+#include "lldb/Core/ValueObject.h"<br>
+<br>
+using namespace lldb;<br>
+using namespace lldb_private;<br>
+<br>
+MemoryHistorySP<br>
+MemoryHistoryASan::CreateInstance (const ProcessSP &process_sp)<br>
+{<br>
+    if (!process_sp.get())<br>
+        return NULL;<br>
+<br>
+    Target & target = process_sp->GetTarget();<br>
+<br>
+    bool found_asan_runtime = false;<br>
+<br>
+    const ModuleList &target_modules = target.GetImages();<br>
+    Mutex::Locker modules_locker(target_modules.GetMutex());<br>
+    const size_t num_modules = target_modules.GetSize();<br>
+    for (size_t i = 0; i < num_modules; ++i)<br>
+    {<br>
+        Module *module_pointer = target_modules.GetModulePointerAtIndexUnlocked(i);<br>
+<br>
+        SymbolContextList sc_list;<br>
+        const bool include_symbols = true;<br>
+        const bool append = true;<br>
+        const bool include_inlines = true;<br>
+<br>
+        size_t num_matches = module_pointer->FindFunctions(ConstString("__asan_get_alloc_stack"), NULL, eFunctionNameTypeAuto, include_symbols, include_inlines, append, sc_list);<br>
+<br>
+        if (num_matches)<br>
+        {<br>
+            found_asan_runtime = true;<br>
+            break;<br>
+        }<br>
+    }<br>
+<br>
+    if (! found_asan_runtime)<br>
+        return MemoryHistorySP();<br>
+<br>
+    return MemoryHistorySP(new MemoryHistoryASan(process_sp));<br>
+}<br>
+<br>
+void<br>
+MemoryHistoryASan::Initialize()<br>
+{<br>
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),<br>
+                                   "ASan memory history provider.",<br>
+                                   CreateInstance);<br>
+}<br>
+<br>
+void<br>
+MemoryHistoryASan::Terminate()<br>
+{<br>
+    PluginManager::UnregisterPlugin (CreateInstance);<br>
+}<br>
+<br>
+<br>
+ConstString<br>
+MemoryHistoryASan::GetPluginNameStatic()<br>
+{<br>
+    static ConstString g_name("asan");<br>
+    return g_name;<br>
+}<br>
+<br>
+MemoryHistoryASan::MemoryHistoryASan(const ProcessSP &process_sp)<br>
+{<br>
+    this->m_process_sp = process_sp;<br>
+}<br>
+<br>
+const char *<br>
+memory_history_asan_command_format = R"(<br>
+    struct t {<br>
+        void *alloc_trace[256];<br>
+        size_t alloc_count;<br>
+        int alloc_tid;<br>
+<br>
+        void *free_trace[256];<br>
+        size_t free_count;<br>
+        int free_tid;<br>
+    } t;<br>
+<br>
+    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);<br>
+    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);<br>
+<br>
+    t;<br>
+)";<br>
+<br>
+#define GET_STACK_FUNCTION_TIMEOUT_USEC 2*1000*1000<br>
+<br>
+HistoryThreads<br>
+MemoryHistoryASan::GetHistoryThreads(lldb::addr_t address)<br>
+{<br>
+    ProcessSP process_sp = m_process_sp;<br>
+    ThreadSP thread_sp = m_process_sp->GetThreadList().GetSelectedThread();<br>
+    StackFrameSP frame_sp = thread_sp->GetSelectedFrame();<br>
+<br>
+    if (!frame_sp)<br>
+    {<br>
+        return HistoryThreads();<br>
+    }<br>
+<br>
+    ExecutionContext exe_ctx (frame_sp);<br>
+    ValueObjectSP return_value_sp;<br>
+    StreamString expr;<br>
+    expr.Printf(memory_history_asan_command_format, address, address);<br>
+<br>
+    EvaluateExpressionOptions options;<br>
+    options.SetUnwindOnError(true);<br>
+    options.SetTryAllThreads(true);<br>
+    options.SetStopOthers(true);<br>
+    options.SetIgnoreBreakpoints(true);<br>
+    options.SetTimeoutUsec(GET_STACK_FUNCTION_TIMEOUT_USEC);<br>
+<br>
+    if (m_process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), return_value_sp, options) != eExpressionCompleted)<br>
+    {<br>
+        return HistoryThreads();<br>
+    }<br>
+    if (!return_value_sp)<br>
+    {<br>
+        return HistoryThreads();<br>
+    }<br>
+<br>
+    HistoryThreads result;<br>
+<br>
+    int alloc_count = return_value_sp->GetValueForExpressionPath(".alloc_count")->GetValueAsUnsigned(0);<br>
+    int free_count = return_value_sp->GetValueForExpressionPath(".free_count")->GetValueAsUnsigned(0);<br>
+    tid_t alloc_tid = return_value_sp->GetValueForExpressionPath(".alloc_tid")->GetValueAsUnsigned(0);<br>
+    tid_t free_tid = return_value_sp->GetValueForExpressionPath(".free_tid")->GetValueAsUnsigned(0);<br>
+<br>
+    if (alloc_count > 0)<br>
+    {<br>
+        std::vector<lldb::addr_t> pcs;<br>
+        ValueObjectSP trace_sp = return_value_sp->GetValueForExpressionPath(".alloc_trace");<br>
+        for (int i = 0; i < alloc_count; i++) {<br>
+            addr_t pc = trace_sp->GetChildAtIndex(i, true)->GetValueAsUnsigned(0);<br>
+            pcs.push_back(pc);<br>
+        }<br>
+<br>
+        HistoryThread *history_thread = new HistoryThread(*process_sp, alloc_tid, pcs, 0, false);<br>
+        ThreadSP new_thread_sp(history_thread);<br>
+        // let's use thread name for the type of history thread, since history threads don't have names anyway<br>
+        history_thread->SetThreadName("Memory allocated at");<br>
+        result.push_back(new_thread_sp);<br>
+    }<br>
+<br>
+    if (free_count > 0)<br>
+    {<br>
+        std::vector<lldb::addr_t> pcs;<br>
+        ValueObjectSP trace_sp = return_value_sp->GetValueForExpressionPath(".free_trace");<br>
+        for (int i = 0; i < free_count; i++) {<br>
+            addr_t pc = trace_sp->GetChildAtIndex(i, true)->GetValueAsUnsigned(0);<br>
+            pcs.push_back(pc);<br>
+        }<br>
+<br>
+        HistoryThread *history_thread = new HistoryThread(*process_sp, free_tid, pcs, 0, false);<br>
+        ThreadSP new_thread_sp(history_thread);<br>
+        // let's use thread name for the type of history thread, since history threads don't have names anyway<br>
+        history_thread->SetThreadName("Memory deallocated at");<br>
+        result.push_back(new_thread_sp);<br>
+    }<br>
+<br>
+    return result;<br>
+}<br>
<br>
Added: lldb/trunk/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h?rev=217116&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h?rev=217116&view=auto</a><br>

==============================================================================<br>
--- lldb/trunk/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h (added)<br>
+++ lldb/trunk/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h Wed Sep  3 20:03:18 2014<br>
@@ -0,0 +1,62 @@<br>
+//===-- MemoryHistoryASan.h ----------------------------------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef liblldb_MemoryHistoryASan_h_<br>
+#define liblldb_MemoryHistoryASan_h_<br>
+<br>
+// C Includes<br>
+// C++ Includes<br>
+// Other libraries and framework includes<br>
+// Project includes<br>
+#include "lldb/lldb-private.h"<br>
+#include "lldb/Target/ABI.h"<br>
+#include "lldb/Target/MemoryHistory.h"<br>
+#include "lldb/Target/Process.h"<br>
+<br>
+namespace lldb_private {<br>
+<br>
+class MemoryHistoryASan : public lldb_private::MemoryHistory<br>
+{<br>
+public:<br>
+<br>
+    static lldb::MemoryHistorySP<br>
+    CreateInstance (const lldb::ProcessSP &process_sp);<br>
+<br>
+    static void<br>
+    Initialize();<br>
+<br>
+    static void<br>
+    Terminate();<br>
+<br>
+    static lldb_private::ConstString<br>
+    GetPluginNameStatic();<br>
+<br>
+    virtual<br>
+    ~MemoryHistoryASan () {}<br>
+<br>
+    virtual lldb_private::ConstString<br>
+    GetPluginName() { return GetPluginNameStatic(); }<br>
+<br>
+    virtual uint32_t<br>
+    GetPluginVersion() { return 1; }<br>
+<br>
+    virtual lldb_private::HistoryThreads<br>
+    GetHistoryThreads(lldb::addr_t address);<br>
+<br>
+private:<br>
+<br>
+    MemoryHistoryASan(const lldb::ProcessSP &process_sp);<br>
+<br>
+    lldb::ProcessSP m_process_sp;<br>
+<br>
+};<br>
+<br>
+} // namespace lldb_private<br>
+<br>
+#endif  // liblldb_MemoryHistoryASan_h_<br>
<br>
Modified: lldb/trunk/source/Plugins/Process/Utility/HistoryThread.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/HistoryThread.h?rev=217116&r1=217115&r2=217116&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/HistoryThread.h?rev=217116&r1=217115&r2=217116&view=diff</a><br>

==============================================================================<br>
--- lldb/trunk/source/Plugins/Process/Utility/HistoryThread.h (original)<br>
+++ lldb/trunk/source/Plugins/Process/Utility/HistoryThread.h Wed Sep  3 20:03:18 2014<br>
@@ -101,6 +101,18 @@ public:<br>
     {<br>
         m_thread_name = name;<br>
     }<br>
+<br>
+    virtual const char *<br>
+    GetName ()<br>
+    {<br>
+        return m_thread_name.c_str();<br>
+    }<br>
+<br>
+    virtual void<br>
+    SetName(const char *name)<br>
+    {<br>
+        m_thread_name = name;<br>
+    }<br>
<br>
 protected:<br>
     virtual lldb::StackFrameListSP<br>
<br>
Modified: lldb/trunk/source/Target/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/CMakeLists.txt?rev=217116&r1=217115&r2=217116&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/CMakeLists.txt?rev=217116&r1=217115&r2=217116&view=diff</a><br>

==============================================================================<br>
--- lldb/trunk/source/Target/CMakeLists.txt (original)<br>
+++ lldb/trunk/source/Target/CMakeLists.txt Wed Sep  3 20:03:18 2014<br>
@@ -11,6 +11,7 @@ add_lldb_library(lldbTarget<br>
   JITLoaderList.cpp<br>
   LanguageRuntime.cpp<br>
   Memory.cpp<br>
+  MemoryHistory.cpp<br>
   NativeRegisterContext.cpp<br>
   NativeRegisterContextRegisterInfo.cpp<br>
   ObjCLanguageRuntime.cpp<br>
<br>
Added: lldb/trunk/source/Target/MemoryHistory.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/MemoryHistory.cpp?rev=217116&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/MemoryHistory.cpp?rev=217116&view=auto</a><br>

==============================================================================<br>
--- lldb/trunk/source/Target/MemoryHistory.cpp (added)<br>
+++ lldb/trunk/source/Target/MemoryHistory.cpp Wed Sep  3 20:03:18 2014<br>
@@ -0,0 +1,28 @@<br>
+//===-- MemoryHistory.cpp -------------------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "lldb/Target/MemoryHistory.h"<br>
+<br>
+#include "lldb/Core/PluginManager.h"<br>
+<br>
+using namespace lldb;<br>
+using namespace lldb_private;<br>
+<br>
+lldb::MemoryHistorySP<br>
+MemoryHistory::FindPlugin (const ProcessSP process)<br>
+{<br>
+    MemoryHistoryCreateInstance create_callback = NULL;<br>
+<br>
+    for (uint32_t idx = 0; (create_callback = PluginManager::GetMemoryHistoryCreateCallbackAtIndex(idx)) != NULL; ++idx)<br>
+    {<br>
+        return create_callback(process);<br>
+    }<br>
+<br>
+    return MemoryHistorySP();<br>
+}<br>
<br>
Modified: lldb/trunk/source/lldb.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/lldb.cpp?rev=217116&r1=217115&r2=217116&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/lldb.cpp?rev=217116&r1=217115&r2=217116&view=diff</a><br>

==============================================================================<br>
--- lldb/trunk/source/lldb.cpp (original)<br>
+++ lldb/trunk/source/lldb.cpp Wed Sep  3 20:03:18 2014<br>
@@ -92,6 +92,7 @@<br>
 #include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h"<br>
 #include "Plugins/Process/gdb-remote/ProcessGDBRemote.h"<br>
 #include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h"<br>
+#include "Plugins/MemoryHistory/asan/MemoryHistoryASan.h"<br>
<br>
 using namespace lldb;<br>
 using namespace lldb_private;<br>
@@ -154,6 +155,7 @@ lldb_private::Initialize ()<br>
 #endif<br>
         JITLoaderGDB::Initialize();<br>
         ProcessElfCore::Initialize();<br>
+        MemoryHistoryASan::Initialize();<br>
<br>
 #if defined (__APPLE__)<br>
         //----------------------------------------------------------------------<br>
@@ -244,6 +246,7 @@ lldb_private::Terminate ()<br>
 #endif<br>
     JITLoaderGDB::Terminate();<br>
     ProcessElfCore::Terminate();<br>
+    MemoryHistoryASan::Terminate();<br>
<br>
 #if defined (__APPLE__)<br>
     DynamicLoaderMacOSXDYLD::Terminate();<br>
<br>
Added: lldb/trunk/test/functionalities/asan/Makefile<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/asan/Makefile?rev=217116&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/asan/Makefile?rev=217116&view=auto</a><br>

==============================================================================<br>
--- lldb/trunk/test/functionalities/asan/Makefile (added)<br>
+++ lldb/trunk/test/functionalities/asan/Makefile Wed Sep  3 20:03:18 2014<br>
@@ -0,0 +1,6 @@<br>
+LEVEL = ../../make<br>
+<br>
+C_SOURCES := main.c<br>
+CFLAGS := $(CFLAGS) -fsanitize=address -g<br>
+<br>
+include $(LEVEL)/Makefile.rules<br>
<br>
Added: lldb/trunk/test/functionalities/asan/TestAsan.py<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/asan/TestAsan.py?rev=217116&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/asan/TestAsan.py?rev=217116&view=auto</a><br>

==============================================================================<br>
--- lldb/trunk/test/functionalities/asan/TestAsan.py (added)<br>
+++ lldb/trunk/test/functionalities/asan/TestAsan.py Wed Sep  3 20:03:18 2014<br>
@@ -0,0 +1,90 @@<br>
+"""<br>
+Test that ASan memory history provider returns correct stack traces<br>
+"""<br>
+<br>
+import os, time<br>
+import unittest2<br>
+import lldb<br>
+from lldbtest import *<br>
+import lldbutil<br>
+<br>
+class AsanTestCase(TestBase):<br>
+<br>
+    mydir = TestBase.compute_mydir(__file__)<br>
+<br>
+    # The default compiler ("clang") may not support Address Sanitizer or it<br>
+    # may not have the debugging API which was recently added, so we're calling<br>
+    # self.useBuiltClang() to use clang from the llvm-build directory instead<br>
+<br>
+    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")<br>
+    @dsym_test<br>
+    def test_with_dsym (self):<br>
+        compiler = self.findBuiltClang ()<br>
+        self.buildDsym (None, compiler)<br>
+        self.asan_tests ()<br>
+<br>
+    @dwarf_test<br>
+    def test_with_dwarf (self):<br>
+        compiler = self.findBuiltClang ()<br>
+        self.buildDwarf (None, compiler)<br>
+        self.asan_tests ()<br>
+<br>
+    def setUp(self):<br>
+        # Call super's setUp().<br>
+        TestBase.setUp(self)<br>
+        self.line_malloc = line_number('main.c', '// malloc line')<br>
+        self.line_malloc2 = line_number('main.c', '// malloc2 line')<br>
+        self.line_free = line_number('main.c', '// free line')<br>
+        self.line_breakpoint = line_number('main.c', '// break line')<br>
+<br>
+    def asan_tests (self):<br>
+        exe = os.path.join (os.getcwd(), "a.out")<br>
+        self.expect("file " + exe, patterns = [ "Current executable set to .*a.out" ])<br>
+<br>
+        self.runCmd("breakpoint set -f main.c -l %d" % self.line_breakpoint)<br>
+<br>
+        # "memory history" command should not work without a process<br>
+        self.expect("memory history 0",<br>
+            error = True,<br>
+            substrs = ["invalid process"])<br>
+<br>
+        self.runCmd("run")<br>
+<br>
+        # ASan will relaunch the process to insert its library.<br>
+        self.expect("thread list", "Process should be stopped due to exec.",<br>
+            substrs = ['stopped', 'stop reason = exec'])<br>
+<br>
+        self.runCmd("continue")<br>
+<br>
+        # the stop reason of the thread should be breakpoint.<br>
+        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,<br>
+            substrs = ['stopped', 'stop reason = breakpoint'])<br>
+<br>
+        # test that the ASan dylib is present<br>
+        self.expect("image lookup -n __asan_describe_address", "__asan_describe_address should be present",<br>
+            substrs = ['1 match found'])<br>
+<br>
+        # test the 'memory history' command<br>
+        self.expect("memory history 'pointer'",<br>
+            substrs = [<br>
+                'Memory allocated at', 'a.out`f1', 'main.c:%d' % self.line_malloc,<br>
+                'Memory deallocated at', 'a.out`f2', 'main.c:%d' % self.line_free])<br>
+<br>
+        self.runCmd("breakpoint set -n __asan_report_error")<br>
+<br>
+        self.runCmd("continue")<br>
+<br>
+        # the stop reason of the thread should be breakpoint.<br>
+        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,<br>
+            substrs = ['stopped', 'stop reason = breakpoint'])<br>
+<br>
+        # make sure the 'memory history' command still works even when we're generating a report now<br>
+        self.expect("memory history 'another_pointer'",<br>
+            substrs = [<br>
+                'Memory allocated at', 'a.out`f1', 'main.c:%d' % self.line_malloc2])<br>
+<br>
+if __name__ == '__main__':<br>
+    import atexit<br>
+    lldb.SBDebugger.Initialize()<br>
+    atexit.register(lambda: lldb.SBDebugger.Terminate())<br>
+    unittest2.main()<br>
<br>
Added: lldb/trunk/test/functionalities/asan/main.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/asan/main.c?rev=217116&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/asan/main.c?rev=217116&view=auto</a><br>

==============================================================================<br>
--- lldb/trunk/test/functionalities/asan/main.c (added)<br>
+++ lldb/trunk/test/functionalities/asan/main.c Wed Sep  3 20:03:18 2014<br>
@@ -0,0 +1,34 @@<br>
+//===-- main.c --------------------------------------------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+#include <stdio.h><br>
+#include <stdlib.h><br>
+<br>
+char *pointer;<br>
+char *another_pointer;<br>
+<br>
+void f1() {<br>
+    pointer = malloc(10); // malloc line<br>
+    another_pointer = malloc(20); // malloc2 line<br>
+}<br>
+<br>
+void f2() {<br>
+    free(pointer); // free line<br>
+}<br>
+<br>
+int main (int argc, char const *argv[])<br>
+{<br>
+    f1();<br>
+    f2();<br>
+<br>
+    printf("Hello world!\n"); // break line<br>
+<br>
+    pointer[0] = 'A'; // BOOM<br>
+<br>
+    return 0;<br>
+}<br>
<br>
Modified: lldb/trunk/test/lldbtest.py<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lldbtest.py?rev=217116&r1=217115&r2=217116&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lldbtest.py?rev=217116&r1=217115&r2=217116&view=diff</a><br>

==============================================================================<br>
--- lldb/trunk/test/lldbtest.py (original)<br>
+++ lldb/trunk/test/lldbtest.py Wed Sep  3 20:03:18 2014<br>
@@ -1325,6 +1325,22 @@ class Base(unittest2.TestCase):<br>
         if not module.buildDwarf(self, architecture, compiler, dictionary, clean):<br>
             raise Exception("Don't know how to build binary with dwarf")<br>
<br>
+    def findBuiltClang(self):<br>
+        """Tries to find and use Clang from the build directory as the compiler (instead of the system compiler)."""<br>
+        paths_to_try = [<br>
+          "llvm-build/Release+Asserts/x86_64/Release+Asserts/bin/clang",<br>
+          "llvm-build/Debug+Asserts/x86_64/Debug+Asserts/bin/clang",<br>
+          "llvm-build/Release/x86_64/Release/bin/clang",<br>
+          "llvm-build/Debug/x86_64/Debug/bin/clang",<br>
+        ]<br>
+        lldb_root_path = os.path.join(os.path.dirname(__file__), "..")<br>
+        for p in paths_to_try:<br>
+            path = os.path.join(lldb_root_path, p)<br>
+            if os.path.exists(path):<br>
+                return path<br>
+<br>
+        return os.environ["CC"]<br>
+<br>
     def getBuildFlags(self, use_cpp11=True, use_libcxx=False, use_libstdcxx=False, use_pthreads=True):<br>
         """ Returns a dictionary (which can be provided to build* functions above) which<br>
             contains OS-specific build flags.<br>
<br>
<br>
_______________________________________________<br>
lldb-commits mailing list<br>
<a href="mailto:lldb-commits@cs.uiuc.edu">lldb-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits</a><br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div dir="ltr"><table cellspacing="0" cellpadding="0" style="color:rgb(136,136,136);font-family:'Times New Roman'"><tbody><tr style="color:rgb(85,85,85);font-family:sans-serif;font-size:small">
<td nowrap style="border-top-style:solid;border-top-color:rgb(213,15,37);border-top-width:2px">Todd Fiala |</td><td nowrap style="border-top-style:solid;border-top-color:rgb(51,105,232);border-top-width:2px"> Software Engineer |</td>
<td nowrap style="border-top-style:solid;border-top-color:rgb(0,153,57);border-top-width:2px"> <a href="mailto:tfiala@google.com" style="color:rgb(17,85,204)" target="_blank"><span style="background-color:rgb(255,255,204);color:rgb(34,34,34);background-repeat:initial initial">tfiala@google.com</span></a> |</td>
<td nowrap style="border-top-style:solid;border-top-color:rgb(238,178,17);border-top-width:2px"><font color="#1155cc"> <a>650-943-3180</a></font></td></tr></tbody></table><br></div>
</div>