Index: lib/tsan/rtl/tsan_debugging.cc =================================================================== --- lib/tsan/rtl/tsan_debugging.cc +++ lib/tsan/rtl/tsan_debugging.cc @@ -128,6 +128,16 @@ } SANITIZER_INTERFACE_ATTRIBUTE +int __tsan_get_report_loc_object_type(void *report, uptr idx, + const char **object_type) { + const ReportDesc *rep = (ReportDesc *)report; + CHECK_LT(idx, rep->locs.Size()); + ReportLocation *loc = rep->locs[idx]; + *object_type = GetObjectTypeFromTag(loc->external_tag); + return 1; +} + +SANITIZER_INTERFACE_ATTRIBUTE int __tsan_get_report_mutex(void *report, uptr idx, uptr *mutex_id, void **addr, int *destroyed, void **trace, uptr trace_size) { const ReportDesc *rep = (ReportDesc *)report; Index: lib/tsan/rtl/tsan_interface.h =================================================================== --- lib/tsan/rtl/tsan_interface.h +++ lib/tsan/rtl/tsan_interface.h @@ -132,6 +132,10 @@ int *fd, int *suppressable, void **trace, uptr trace_size); +SANITIZER_INTERFACE_ATTRIBUTE +int __tsan_get_report_loc_object_type(void *report, uptr idx, + const char **object_type); + // Returns information about mutexes included in the report. SANITIZER_INTERFACE_ATTRIBUTE int __tsan_get_report_mutex(void *report, uptr idx, uptr *mutex_id, void **addr, Index: test/tsan/debug_external.cc =================================================================== --- test/tsan/debug_external.cc +++ test/tsan/debug_external.cc @@ -0,0 +1,61 @@ +// RUN: %clangxx_tsan -O1 %s -o %t +// RUN: %deflake %run %t 2>&1 | FileCheck %s + +#include +#include +#include +#include + +extern "C" { +void __tsan_on_report(void *report); +int __tsan_get_report_loc(void *report, unsigned long idx, const char **type, + void **addr, void **start, + unsigned long *size, int *tid, int *fd, + int *suppressable, void **trace, + unsigned long trace_size); +int __tsan_get_report_loc_object_type(void *report, unsigned long idx, + const char **object_type); +void *__tsan_external_register_tag(const char *object_type); +void __tsan_external_assign_tag(void *addr, void *tag); +} + +void *Thread(void *arg) { + *((long *)arg) = 42; + return NULL; +} + +int main() { + void *tag = __tsan_external_register_tag("MyObject"); + long *obj = (long *)malloc(sizeof(long)); + fprintf(stderr, "obj = %p\n", obj); + // CHECK: obj = [[ADDR:0x[0-9a-f]+]] + __tsan_external_assign_tag(obj, tag); + + pthread_t t; + pthread_create(&t, 0, Thread, obj); + *obj = 41; + pthread_join(t, 0); + fprintf(stderr, "Done.\n"); + return 0; +} + +void __tsan_on_report(void *report) { + const char *type; + void *addr; + void *start; + unsigned long size; + int tid, fd, suppressable; + void *trace[16] = {0}; + __tsan_get_report_loc(report, 0, &type, &addr, &start, &size, &tid, &fd, + &suppressable, trace, 16); + fprintf(stderr, "type = %s, start = %p, size = %ld\n", type, start, size); + // CHECK: type = heap, start = [[ADDR]], size = 8 + + const char *object_type; + __tsan_get_report_loc_object_type(report, 0, &object_type); + fprintf(stderr, "object_type = %s\n", object_type); + // CHECK: object_type = MyObject +} + +// CHECK: Done. +// CHECK: ThreadSanitizer: reported 1 warnings