Index: include/lldb/API/SBProcess.h =================================================================== --- include/lldb/API/SBProcess.h +++ include/lldb/API/SBProcess.h @@ -316,6 +316,9 @@ //------------------------------------------------------------------ const char * GetExtendedBacktraceTypeAtIndex (uint32_t idx); + + lldb::SBThreadCollection + GetHistoryThreads (addr_t addr); protected: friend class SBAddress; Index: include/lldb/Target/Process.h =================================================================== --- include/lldb/Target/Process.h +++ include/lldb/Target/Process.h @@ -2922,6 +2922,9 @@ Error return_error ("Sending an event is not supported for this process."); return return_error; } + + lldb::ThreadCollectionSP + GetHistoryThreads(lldb::addr_t addr); protected: Index: scripts/Python/interface/SBProcess.i =================================================================== --- scripts/Python/interface/SBProcess.i +++ scripts/Python/interface/SBProcess.i @@ -389,6 +389,9 @@ const char * GetExtendedBacktraceTypeAtIndex (uint32_t idx); + lldb::SBThreadCollection + GetHistoryThreads (addr_t addr); + %pythoncode %{ def __get_is_alive__(self): '''Returns "True" if the process is currently alive, "False" otherwise''' Index: source/API/SBProcess.cpp =================================================================== --- source/API/SBProcess.cpp +++ source/API/SBProcess.cpp @@ -38,6 +38,7 @@ #include "lldb/API/SBEvent.h" #include "lldb/API/SBFileSpec.h" #include "lldb/API/SBThread.h" +#include "lldb/API/SBThreadCollection.h" #include "lldb/API/SBStream.h" #include "lldb/API/SBStringList.h" #include "lldb/API/SBUnixSignals.h" @@ -1381,3 +1382,15 @@ } return NULL; } + +SBThreadCollection +SBProcess::GetHistoryThreads (addr_t addr) +{ + ProcessSP process_sp(GetSP()); + SBThreadCollection threads; + if (process_sp) + { + threads = SBThreadCollection(process_sp->GetHistoryThreads(addr)); + } + return threads; +} Index: source/Target/Process.cpp =================================================================== --- source/Target/Process.cpp +++ source/Target/Process.cpp @@ -32,6 +32,7 @@ #include "lldb/Target/ABI.h" #include "lldb/Target/DynamicLoader.h" #include "lldb/Target/JITLoader.h" +#include "lldb/Target/MemoryHistory.h" #include "lldb/Target/OperatingSystem.h" #include "lldb/Target/LanguageRuntime.h" #include "lldb/Target/CPPLanguageRuntime.h" @@ -6022,3 +6023,19 @@ GetJITLoaders().ModulesDidLoad (module_list); } + +ThreadCollectionSP +Process::GetHistoryThreads(lldb::addr_t addr) +{ + ThreadCollectionSP threads; + + const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(shared_from_this()); + + if (! memory_history.get()) { + return threads; + } + + threads.reset(new ThreadCollection(memory_history->GetHistoryThreads(addr))); + + return threads; +} Index: test/functionalities/asan/TestAsan.py =================================================================== --- test/functionalities/asan/TestAsan.py +++ test/functionalities/asan/TestAsan.py @@ -70,6 +70,24 @@ 'Memory allocated at', 'a.out`f1', 'main.c:%d' % self.line_malloc, 'Memory deallocated at', 'a.out`f2', 'main.c:%d' % self.line_free]) + # do the same using SB API + process = self.dbg.GetSelectedTarget().process + val = process.GetSelectedThread().GetSelectedFrame().EvaluateExpression("pointer") + addr = val.GetValueAsUnsigned() + threads = process.GetHistoryThreads(addr); + self.assertEqual(threads.GetSize(), 2) + + history_thread = threads.GetThreadAtIndex(0) + self.assertTrue(history_thread.num_frames >= 2) + self.assertEqual(history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(), "main.c") + self.assertEqual(history_thread.frames[1].GetLineEntry().GetLine(), self.line_malloc) + + history_thread = threads.GetThreadAtIndex(1) + self.assertTrue(history_thread.num_frames >= 2) + self.assertEqual(history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(), "main.c") + self.assertEqual(history_thread.frames[1].GetLineEntry().GetLine(), self.line_free) + + # now let's break when an ASan report occurs and try the API then self.runCmd("breakpoint set -n __asan_report_error") self.runCmd("continue")