Skip to content

Commit ebb0f1d

Browse files
committed
[tsan] Add debugging interfaces into interface header.
Reviewed By: vitalybuka, dvyukov Differential Revision: https://reviews.llvm.org/D147337
1 parent b0f89f0 commit ebb0f1d

File tree

2 files changed

+188
-0
lines changed

2 files changed

+188
-0
lines changed

compiler-rt/include/sanitizer/tsan_interface.h

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,121 @@ const char* __tsan_default_options(void);
178178
// User-provided default TSAN suppressions.
179179
const char* __tsan_default_suppressions(void);
180180

181+
/// Returns a report's description.
182+
///
183+
/// Returns a report's description (issue type), number of duplicate issues
184+
/// found, counts of array data (stack traces, memory operations, locations,
185+
/// mutexes, threads, unique thread IDs) and a stack trace of a <c>sleep()</c>
186+
/// call (if one was involved in the issue).
187+
///
188+
/// \param report Opaque pointer to the current report.
189+
/// \param[out] description Report type description.
190+
/// \param[out] count Count of duplicate issues.
191+
/// \param[out] stack_count Count of stack traces.
192+
/// \param[out] mop_count Count of memory operations.
193+
/// \param[out] loc_count Count of locations.
194+
/// \param[out] mutex_count Count of mutexes.
195+
/// \param[out] thread_count Count of threads.
196+
/// \param[out] unique_tid_count Count of unique thread IDs.
197+
/// \param sleep_trace A buffer to store the stack trace of a <c>sleep()</c>
198+
/// call.
199+
/// \param trace_size Size in bytes of the trace buffer.
200+
/// \returns Returns 1 if successful, 0 if not.
201+
int __tsan_get_report_data(void *report, const char **description, int *count,
202+
int *stack_count, int *mop_count, int *loc_count,
203+
int *mutex_count, int *thread_count,
204+
int *unique_tid_count, void **sleep_trace,
205+
uintptr_t trace_size);
206+
207+
/// Returns information about stack traces included in the report.
208+
///
209+
/// \param report Opaque pointer to the current report.
210+
/// \param idx Index to the report's stacks.
211+
/// \param trace A buffer to store the stack trace.
212+
/// \param trace_size Size in bytes of the trace buffer.
213+
/// \returns Returns 1 if successful, 0 if not.
214+
int __tsan_get_report_stack(void *report, uintptr_t idx, void **trace,
215+
uintptr_t trace_size);
216+
217+
/// Returns information about memory operations included in the report.
218+
///
219+
/// \param report Opaque pointer to the current report.
220+
/// \param idx Index to the report's memory operations.
221+
/// \param[out] tid Thread ID of the memory operation.
222+
/// \param[out] addr Address of the memory operation.
223+
/// \param[out] size Size of the memory operation.
224+
/// \param[out] write Write flag of the memory operation.
225+
/// \param[out] atomic Atomicity flag of the memory operation.
226+
/// \param trace A buffer to store the stack trace.
227+
/// \param trace_size Size in bytes of the trace buffer.
228+
/// \returns Returns 1 if successful, 0 if not.
229+
int __tsan_get_report_mop(void *report, uintptr_t idx, int *tid, void **addr,
230+
int *size, int *write, int *atomic, void **trace,
231+
uintptr_t trace_size);
232+
233+
/// Returns information about locations included in the report.
234+
///
235+
/// \param report Opaque pointer to the current report.
236+
/// \param idx Index to the report's locations.
237+
/// \param[out] type Type of the location.
238+
/// \param[out] addr Address of the location.
239+
/// \param[out] start Start of the location.
240+
/// \param[out] size Size of the location.
241+
/// \param[out] tid Thread ID of the location.
242+
/// \param[out] fd File descriptor of the location.
243+
/// \param[out] suppressable Suppressable flag.
244+
/// \param trace A buffer to store the stack trace.
245+
/// \param trace_size Size in bytes of the trace buffer.
246+
/// \returns Returns 1 if successful, 0 if not.
247+
int __tsan_get_report_loc(void *report, uintptr_t idx, const char **type,
248+
void **addr, uintptr_t *start, uintptr_t *size, int *tid,
249+
int *fd, int *suppressable, void **trace,
250+
uintptr_t trace_size);
251+
252+
/// Returns information about mutexes included in the report.
253+
///
254+
/// \param report Opaque pointer to the current report.
255+
/// \param idx Index to the report's mutexes.
256+
/// \param[out] mutex_id Id of the mutex.
257+
/// \param[out] addr Address of the mutex.
258+
/// \param[out] destroyed Destroyed mutex flag.
259+
/// \param trace A buffer to store the stack trace.
260+
/// \param trace_size Size in bytes of the trace buffer.
261+
/// \returns Returns 1 if successful, 0 if not.
262+
int __tsan_get_report_mutex(void *report, uintptr_t idx, uintptr_t *mutex_id, void **addr,
263+
int *destroyed, void **trace, uintptr_t trace_size);
264+
265+
/// Returns information about threads included in the report.
266+
///
267+
/// \param report Opaque pointer to the current report.
268+
/// \param idx Index to the report's threads.
269+
/// \param[out] tid Thread ID of the thread.
270+
/// \param[out] os_id Operating system's ID of the thread.
271+
/// \param[out] running Running flag of the thread.
272+
/// \param[out] name Name of the thread.
273+
/// \param[out] parent_tid ID of the parent thread.
274+
/// \param trace A buffer to store the stack trace.
275+
/// \param trace_size Size in bytes of the trace buffer.
276+
/// \returns Returns 1 if successful, 0 if not.
277+
int __tsan_get_report_thread(void *report, uintptr_t idx, int *tid, uintptr_t *os_id,
278+
int *running, const char **name, int *parent_tid,
279+
void **trace, uintptr_t trace_size);
280+
281+
/// Returns information about unique thread IDs included in the report.
282+
///
283+
/// \param report Opaque pointer to the current report.
284+
/// \param idx Index to the report's unique thread IDs.
285+
/// \param[out] tid Unique thread ID of the report.
286+
/// \returns Returns 1 if successful, 0 if not.
287+
int __tsan_get_report_unique_tid(void *report, uintptr_t idx, int *tid);
288+
289+
/// Returns the current report.
290+
///
291+
/// If TSan is currently reporting a detected issue on the current thread,
292+
/// returns an opaque pointer to the current report. Otherwise returns NULL.
293+
/// \returns An opaque pointer to the current report. Otherwise returns NULL.
294+
void *__tsan_get_current_report();
295+
181296
#ifdef __cplusplus
182297
} // extern "C"
183298
#endif
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s
2+
3+
#include "test.h"
4+
5+
extern "C" {
6+
void __tsan_on_report(void *report);
7+
void *__tsan_get_current_report();
8+
int __tsan_get_report_data(void *report, const char **description, int *count,
9+
int *stack_count, int *mop_count, int *loc_count,
10+
int *mutex_count, int *thread_count,
11+
int *unique_tid_count, void **sleep_trace,
12+
unsigned long trace_size);
13+
int __tsan_get_report_stack(void *report, uintptr_t idx, void **trace,
14+
uintptr_t trace_size);
15+
int __tsan_get_report_mutex(void *report, uintptr_t idx, uintptr_t *mutex_id, void **addr,
16+
int *destroyed, void **trace, uintptr_t trace_size);
17+
}
18+
19+
int main() {
20+
int m = 0;
21+
fprintf(stderr, "&m = %p\n", &m);
22+
// CHECK: &m = [[MUTEX:0x[0-9a-f]+]]
23+
AnnotateRWLockReleased(__FILE__, __LINE__, &m, 1);
24+
fprintf(stderr, "Done.\n");
25+
return 0;
26+
}
27+
28+
// Required for dyld macOS 12.0+
29+
#if (__APPLE__)
30+
__attribute__((weak))
31+
#endif
32+
__attribute__((disable_sanitizer_instrumentation))
33+
extern "C" void
34+
__tsan_on_report(void *report) {
35+
fprintf(stderr, "__tsan_on_report(%p)\n", report);
36+
fprintf(stderr, "__tsan_get_current_report() = %p\n",
37+
__tsan_get_current_report());
38+
// CHECK: __tsan_on_report([[REPORT:0x[0-9a-f]+]])
39+
// CHECK: __tsan_get_current_report() = [[REPORT]]
40+
41+
const char *description;
42+
int count;
43+
int stack_count, mop_count, loc_count, mutex_count, thread_count,
44+
unique_tid_count;
45+
void *sleep_trace[16] = {0};
46+
__tsan_get_report_data(report, &description, &count, &stack_count, &mop_count,
47+
&loc_count, &mutex_count, &thread_count,
48+
&unique_tid_count, sleep_trace, 16);
49+
50+
fprintf(stderr, "stack_count = %d\n", stack_count);
51+
// CHECK: stack_count = 1
52+
53+
fprintf(stderr, "mutex_count = %d\n", mutex_count);
54+
// CHECK: mutex_count = 1
55+
56+
void *trace[16] = {0};
57+
__tsan_get_report_stack(report, 0, trace, 16);
58+
59+
fprintf(stderr, "trace[0] = %p, trace[1] = %p, trace[2] = %p\n", trace[0], trace[1], trace[2]);
60+
// CHECK: trace[0] = 0x{{[0-9a-f]+}}, trace[1] = 0x{{[0-9a-f]+}}, trace[2] = {{0x0|\(nil\)|\(null\)}}
61+
62+
uintptr_t mutex_id;
63+
void *addr;
64+
int destroyed;
65+
__tsan_get_report_mutex(report, 0, &mutex_id, &addr, &destroyed, trace, 16);
66+
fprintf(stderr, "addr = %p, destroyed = %d\n", addr, destroyed);
67+
// CHECK: addr = [[MUTEX]], destroyed = 0
68+
fprintf(stderr, "trace[0] = %p, trace[1] = %p, trace[2] = %p\n", trace[0], trace[1], trace[2]);
69+
// CHECK: trace[0] = 0x{{[0-9a-f]+}}, trace[1] = 0x{{[0-9a-f]+}}, trace[2] = {{0x0|\(nil\)|\(null\)}}
70+
}
71+
72+
// CHECK: Done.
73+
// CHECK: ThreadSanitizer: reported 1 warnings

0 commit comments

Comments
 (0)