diff --git a/lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.h b/lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.h --- a/lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.h +++ b/lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.h @@ -61,7 +61,8 @@ StructuredData::ObjectSP RetrieveReportData(ExecutionContextRef exe_ctx_ref); - std::string FormatDescription(StructuredData::ObjectSP report); + std::string FormatDescription(StructuredData::ObjectSP report, + bool &is_swift_access_race); std::string GenerateSummary(StructuredData::ObjectSP report); diff --git a/lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp b/lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp --- a/lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp +++ b/lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp @@ -88,6 +88,7 @@ // 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); + int (*ptr__tsan_get_report_tag)(void *report, unsigned long *tag); } const int REPORT_TRACE_SIZE = 128; @@ -97,6 +98,7 @@ void *report; const char *description; int report_count; + unsigned long tag; void *sleep_trace[REPORT_TRACE_SIZE]; @@ -163,10 +165,14 @@ 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"); +ptr__tsan_get_report_tag = (typeof(ptr__tsan_get_report_tag))(void *)dlsym((void*)-2 /*RTLD_DEFAULT*/, "__tsan_get_report_tag"); 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); +if (ptr__tsan_get_report_tag) + ptr__tsan_get_report_tag(t.report, &t.tag); + if (t.stack_count > REPORT_ARRAY_SIZE) t.stack_count = REPORT_ARRAY_SIZE; for (int i = 0; i < t.stack_count; i++) { t.stacks[i].idx = i; @@ -347,6 +353,9 @@ ->GetValueAsUnsigned(0)); dict->AddItem("sleep_trace", StructuredData::ObjectSP(CreateStackTrace( main_value, ".sleep_trace"))); + dict->AddIntegerItem( + "tag", + main_value->GetValueForExpressionPath(".tag")->GetValueAsUnsigned(0)); StructuredData::Array *stacks = ConvertToStructuredArray( main_value, ".stacks", ".stack_count", @@ -485,8 +494,8 @@ return StructuredData::ObjectSP(dict); } -std::string -ThreadSanitizerRuntime::FormatDescription(StructuredData::ObjectSP report) { +std::string ThreadSanitizerRuntime::FormatDescription( + StructuredData::ObjectSP report, bool &is_swift_access_race) { std::string description = report->GetAsDictionary() ->GetValueForKey("issue_type") ->GetAsString() @@ -521,8 +530,18 @@ } else if (description == "lock-order-inversion") { return "Lock order inversion (potential deadlock)"; } else if (description == "external-race") { + auto tag = report->GetAsDictionary() + ->GetValueForKey("tag") + ->GetAsInteger() + ->GetValue(); + static const unsigned long kSwiftAccessRaceTag = 0x1; + if (tag == kSwiftAccessRaceTag) { + is_swift_access_race = true; + return "Swift access race"; + } return "Race on a library object"; } else if (description == "swift-access-race") { + is_swift_access_race = true; return "Swift access race"; } @@ -616,9 +635,14 @@ ->GetValueForKey("description") ->GetAsString() ->GetValue(); + bool is_swift_access_race = report->GetAsDictionary() + ->GetValueForKey("is_swift_access_race") + ->GetAsBoolean() + ->GetValue(); + bool skip_one_frame = - report->GetObjectForDotSeparatedPath("issue_type")->GetStringValue() == - "external-race"; + (report->GetObjectForDotSeparatedPath("issue_type")->GetStringValue() == + "external-race") && (!is_swift_access_race); addr_t pc = 0; if (report->GetAsDictionary() @@ -810,8 +834,12 @@ instance->RetrieveReportData(context->exe_ctx_ref); std::string stop_reason_description; if (report) { - std::string issue_description = instance->FormatDescription(report); + bool is_swift_access_race = false; + std::string issue_description = + instance->FormatDescription(report, is_swift_access_race); report->GetAsDictionary()->AddStringItem("description", issue_description); + report->GetAsDictionary()->AddBooleanItem("is_swift_access_race", + is_swift_access_race); stop_reason_description = issue_description + " detected"; report->GetAsDictionary()->AddStringItem("stop_description", stop_reason_description);