Skip to content

Commit

Permalink
[lldb] Add support for "external" reports in ThreadSanitizer LLDB plugin
Browse files Browse the repository at this point in the history
TSan now has the ability to report races on "external" object, i.e. any library class/object that has read-shared write-exclusive threading semantics. The detection and reporting work almost out of the box, but TSan can now provide the type of the object (as a string). This patch implements this into LLDB.

Differential Revision: https://reviews.llvm.org/D30024

llvm-svn: 295342
  • Loading branch information
kubamracek committed Feb 16, 2017
1 parent 8290274 commit 4569fee
Showing 1 changed file with 31 additions and 2 deletions.
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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));

Expand Down Expand Up @@ -511,6 +522,8 @@ 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";
}

// for unknown report codes just show the code
Expand Down Expand Up @@ -634,6 +647,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()
Expand Down Expand Up @@ -726,8 +746,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")
Expand Down

0 comments on commit 4569fee

Please sign in to comment.