diff options
Diffstat (limited to 'source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.cpp')
-rw-r--r-- | source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.cpp | 90 |
1 files changed, 70 insertions, 20 deletions
diff --git a/source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.cpp b/source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.cpp index d8a46e5d4550..cbc77ebe9987 100644 --- a/source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.cpp +++ b/source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.cpp @@ -15,8 +15,6 @@ #include "lldb/Core/Module.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Core/RegularExpression.h" -#include "lldb/Core/Stream.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/ValueObject.h" #include "lldb/Expression/UserExpression.h" @@ -30,6 +28,8 @@ #include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/RegularExpression.h" +#include "lldb/Utility/Stream.h" using namespace lldb; using namespace lldb_private; @@ -85,6 +85,10 @@ extern "C" int *running, const char **name, int *parent_tid, void **trace, unsigned long trace_size); int __tsan_get_report_unique_tid(void *report, unsigned long idx, int *tid); + + // TODO: dlsym won't work on Windows. + void *dlsym(void* handle, const char* symbol); + int (*ptr__tsan_get_report_loc_object_type)(void *report, unsigned long idx, const char **object_type); } const int REPORT_TRACE_SIZE = 128; @@ -125,6 +129,7 @@ struct data { int fd; int suppressable; void *trace[REPORT_TRACE_SIZE]; + const char *object_type; } locs[REPORT_ARRAY_SIZE]; int mutex_count; @@ -158,6 +163,8 @@ struct data { const char *thread_sanitizer_retrieve_report_data_command = R"( data t = {0}; +ptr__tsan_get_report_loc_object_type = (typeof(ptr__tsan_get_report_loc_object_type))(void *)dlsym((void*)-2 /*RTLD_DEFAULT*/, "__tsan_get_report_loc_object_type"); + t.report = __tsan_get_current_report(); __tsan_get_report_data(t.report, &t.description, &t.report_count, &t.stack_count, &t.mop_count, &t.loc_count, &t.mutex_count, &t.thread_count, &t.unique_tid_count, t.sleep_trace, REPORT_TRACE_SIZE); @@ -177,6 +184,8 @@ if (t.loc_count > REPORT_ARRAY_SIZE) t.loc_count = REPORT_ARRAY_SIZE; for (int i = 0; i < t.loc_count; i++) { t.locs[i].idx = i; __tsan_get_report_loc(t.report, i, &t.locs[i].type, &t.locs[i].addr, &t.locs[i].start, &t.locs[i].size, &t.locs[i].tid, &t.locs[i].fd, &t.locs[i].suppressable, t.locs[i].trace, REPORT_TRACE_SIZE); + if (ptr__tsan_get_report_loc_object_type) + ptr__tsan_get_report_loc_object_type(t.report, i, &t.locs[i].object_type); } if (t.mutex_count > REPORT_ARRAY_SIZE) t.mutex_count = REPORT_ARRAY_SIZE; @@ -409,6 +418,8 @@ ThreadSanitizerRuntime::RetrieveReportData(ExecutionContextRef exe_ctx_ref) { o->GetValueForExpressionPath(".suppressable") ->GetValueAsUnsigned(0)); dict->AddItem("trace", StructuredData::ObjectSP(CreateStackTrace(o))); + dict->AddStringItem("object_type", + RetrieveString(o, process_sp, ".object_type")); }); dict->AddItem("locs", StructuredData::ObjectSP(locs)); @@ -511,6 +522,10 @@ ThreadSanitizerRuntime::FormatDescription(StructuredData::ObjectSP report) { return "Overwrite of errno in a signal handler"; } else if (description == "lock-order-inversion") { return "Lock order inversion (potential deadlock)"; + } else if (description == "external-race") { + return "Race on a library object"; + } else if (description == "swift-access-race") { + return "Swift access race"; } // for unknown report codes just show the code @@ -568,27 +583,31 @@ static void GetSymbolDeclarationFromAddress(ProcessSP process_sp, addr_t addr, } addr_t ThreadSanitizerRuntime::GetFirstNonInternalFramePc( - StructuredData::ObjectSP trace) { + StructuredData::ObjectSP trace, bool skip_one_frame) { ProcessSP process_sp = GetProcessSP(); ModuleSP runtime_module_sp = GetRuntimeModuleSP(); - addr_t result = 0; - trace->GetAsArray()->ForEach([process_sp, runtime_module_sp, - &result](StructuredData::Object *o) -> bool { - addr_t addr = o->GetIntegerValue(); + StructuredData::Array *trace_array = trace->GetAsArray(); + for (int i = 0; i < trace_array->GetSize(); i++) { + if (skip_one_frame && i == 0) + continue; + + addr_t addr; + if (!trace_array->GetItemAtIndexAsInteger(i, addr)) + continue; + lldb_private::Address so_addr; if (!process_sp->GetTarget().GetSectionLoadList().ResolveLoadAddress( addr, so_addr)) - return true; + continue; if (so_addr.GetModule() == runtime_module_sp) - return true; + continue; - result = addr; - return false; - }); + return addr; + } - return result; + return 0; } std::string @@ -599,6 +618,10 @@ ThreadSanitizerRuntime::GenerateSummary(StructuredData::ObjectSP report) { ->GetValueForKey("description") ->GetAsString() ->GetValue(); + bool skip_one_frame = + report->GetObjectForDotSeparatedPath("issue_type")->GetStringValue() == + "external-race"; + addr_t pc = 0; if (report->GetAsDictionary() ->GetValueForKey("mops") @@ -609,7 +632,8 @@ ThreadSanitizerRuntime::GenerateSummary(StructuredData::ObjectSP report) { ->GetAsArray() ->GetItemAtIndex(0) ->GetAsDictionary() - ->GetValueForKey("trace")); + ->GetValueForKey("trace"), + skip_one_frame); if (report->GetAsDictionary() ->GetValueForKey("stacks") @@ -620,7 +644,8 @@ ThreadSanitizerRuntime::GenerateSummary(StructuredData::ObjectSP report) { ->GetAsArray() ->GetItemAtIndex(0) ->GetAsDictionary() - ->GetValueForKey("trace")); + ->GetValueForKey("trace"), + skip_one_frame); if (pc != 0) { summary = summary + " in " + GetSymbolNameFromAddress(process_sp, pc); @@ -634,6 +659,13 @@ ThreadSanitizerRuntime::GenerateSummary(StructuredData::ObjectSP report) { ->GetValueForKey("locs") ->GetAsArray() ->GetItemAtIndex(0); + std::string object_type = loc->GetAsDictionary() + ->GetValueForKey("object_type") + ->GetAsString() + ->GetValue(); + if (!object_type.empty()) { + summary = "Race on " + object_type + " object"; + } addr_t addr = loc->GetAsDictionary() ->GetValueForKey("address") ->GetAsInteger() @@ -726,8 +758,17 @@ std::string ThreadSanitizerRuntime::GetLocationDescription( ->GetValueForKey("size") ->GetAsInteger() ->GetValue(); - result = - Sprintf("Location is a %ld-byte heap object at 0x%llx", size, addr); + std::string object_type = loc->GetAsDictionary() + ->GetValueForKey("object_type") + ->GetAsString() + ->GetValue(); + if (!object_type.empty()) { + result = Sprintf("Location is a %ld-byte %s object at 0x%llx", size, + object_type.c_str(), addr); + } else { + result = + Sprintf("Location is a %ld-byte heap object at 0x%llx", size, addr); + } } else if (type == "stack") { int tid = loc->GetAsDictionary() ->GetValueForKey("thread_id") @@ -920,9 +961,18 @@ static std::string GenerateThreadName(const std::string &path, addr_string = ""; } - result = Sprintf("%s%s of size %d%s by thread %d", - is_atomic ? "atomic " : "", is_write ? "write" : "read", - size, addr_string.c_str(), thread_id); + if (main_info->GetObjectForDotSeparatedPath("issue_type") + ->GetStringValue() == "external-race") { + result = Sprintf("%s access by thread %d", + is_write ? "mutating" : "read-only", thread_id); + } else if (main_info->GetObjectForDotSeparatedPath("issue_type") + ->GetStringValue() == "swift-access-race") { + result = Sprintf("modifying access by thread %d", thread_id); + } else { + result = Sprintf("%s%s of size %d%s by thread %d", + is_atomic ? "atomic " : "", is_write ? "write" : "read", + size, addr_string.c_str(), thread_id); + } } if (path == "threads") { |