aboutsummaryrefslogtreecommitdiff
path: root/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp')
-rw-r--r--source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp109
1 files changed, 68 insertions, 41 deletions
diff --git a/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp b/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
index c57519871624..a9d13ac79c37 100644
--- a/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
+++ b/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
@@ -12,8 +12,10 @@
#include "lldb/Target/MemoryHistory.h"
#include "lldb/lldb-private.h"
+#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginInterface.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Expression/UserExpression.h"
#include "lldb/Target/ThreadList.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Target.h"
@@ -22,6 +24,8 @@
#include "Plugins/Process/Utility/HistoryThread.h"
#include "lldb/Core/ValueObject.h"
+#include <sstream>
+
using namespace lldb;
using namespace lldb_private;
@@ -34,7 +38,7 @@ MemoryHistoryASan::CreateInstance (const ProcessSP &process_sp)
Target & target = process_sp->GetTarget();
const ModuleList &target_modules = target.GetImages();
- Mutex::Locker modules_locker(target_modules.GetMutex());
+ std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
const size_t num_modules = target_modules.GetSize();
for (size_t i = 0; i < num_modules; ++i)
{
@@ -80,8 +84,14 @@ MemoryHistoryASan::MemoryHistoryASan(const ProcessSP &process_sp)
}
const char *
-memory_history_asan_command_format = R"(
- struct t {
+memory_history_asan_command_prefix = R"(
+ extern "C"
+ {
+ size_t __asan_get_alloc_stack(void *addr, void **trace, size_t size, int *thread_id);
+ size_t __asan_get_free_stack(void *addr, void **trace, size_t size, int *thread_id);
+ }
+
+ struct data {
void *alloc_trace[256];
size_t alloc_count;
int alloc_tid;
@@ -89,10 +99,15 @@ memory_history_asan_command_format = R"(
void *free_trace[256];
size_t free_count;
int free_tid;
- } t;
+ };
+)";
+
+const char *
+memory_history_asan_command_format = R"(
+ data 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.alloc_count = __asan_get_alloc_stack((void *)0x%)" PRIx64 R"(, t.alloc_trace, 256, &t.alloc_tid);
+ t.free_count = __asan_get_free_stack((void *)0x%)" PRIx64 R"(, t.free_trace, 256, &t.free_tid);
t;
)";
@@ -110,7 +125,7 @@ static void CreateHistoryThreadFromValueObject(ProcessSP process_sp, ValueObject
return;
int count = count_sp->GetValueAsUnsigned(0);
- tid_t tid = tid_sp->GetValueAsUnsigned(0);
+ tid_t tid = tid_sp->GetValueAsUnsigned(0) + 1;
if (count <= 0)
return;
@@ -131,8 +146,9 @@ static void CreateHistoryThreadFromValueObject(ProcessSP process_sp, ValueObject
HistoryThread *history_thread = new HistoryThread(*process_sp, 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(thread_name);
+ std::ostringstream thread_name_with_number;
+ thread_name_with_number << thread_name << " Thread " << tid;
+ history_thread->SetThreadName(thread_name_with_number.str().c_str());
// Save this in the Process' ExtendedThreadList so a strong pointer retains the object
process_sp->GetExtendedThreadList().AddThread (new_thread_sp);
result.push_back(new_thread_sp);
@@ -146,38 +162,49 @@ MemoryHistoryASan::GetHistoryThreads(lldb::addr_t address)
HistoryThreads result;
ProcessSP process_sp = m_process_wp.lock();
- if (process_sp)
- {
- ThreadSP thread_sp = process_sp->GetThreadList().GetSelectedThread();
-
- if (thread_sp)
- {
- StackFrameSP frame_sp = thread_sp->GetSelectedFrame();
-
- if (frame_sp)
- {
- 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 (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), return_value_sp, options) == eExpressionCompleted)
- {
- if (return_value_sp)
- {
- CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "free", "Memory deallocated at", result);
- CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "alloc", "Memory allocated at", result);
- }
- }
- }
- }
+ if (! process_sp)
+ return result;
+
+ ThreadSP thread_sp = process_sp->GetThreadList().GetExpressionExecutionThread();
+ if (!thread_sp)
+ return result;
+
+ StackFrameSP frame_sp = thread_sp->GetSelectedFrame();
+ if (!frame_sp)
+ return result;
+
+ ExecutionContext exe_ctx (frame_sp);
+ ValueObjectSP return_value_sp;
+ StreamString expr;
+ Error eval_error;
+ 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);
+ options.SetPrefix(memory_history_asan_command_prefix);
+ options.SetAutoApplyFixIts(false);
+ options.SetLanguage(eLanguageTypeObjC_plus_plus);
+
+ ExpressionResults expr_result = UserExpression::Evaluate (exe_ctx,
+ options,
+ expr.GetData(),
+ "",
+ return_value_sp,
+ eval_error);
+ if (expr_result != eExpressionCompleted) {
+ process_sp->GetTarget().GetDebugger().GetAsyncOutputStream()->Printf("Warning: Cannot evaluate AddressSanitizer expression:\n%s\n", eval_error.AsCString());
+ return result;
}
+
+ if (!return_value_sp)
+ return result;
+
+ CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "free", "Memory deallocated by", result);
+ CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "alloc", "Memory allocated by", result);
+
return result;
}