1//===-- tsan_report.h -------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file is a part of ThreadSanitizer (TSan), a race detector.
10//
11//===----------------------------------------------------------------------===//
12#ifndef TSAN_REPORT_H
13#define TSAN_REPORT_H
14
15#include "sanitizer_common/sanitizer_internal_defs.h"
16#include "sanitizer_common/sanitizer_stacktrace.h"
17#include "sanitizer_common/sanitizer_symbolizer.h"
18#include "sanitizer_common/sanitizer_thread_registry.h"
19#include "sanitizer_common/sanitizer_vector.h"
20#include "tsan_defs.h"
21
22namespace __tsan {
23
24enum ReportType {
25 ReportTypeRace,
26 ReportTypeVptrRace,
27 ReportTypeUseAfterFree,
28 ReportTypeVptrUseAfterFree,
29 ReportTypeExternalRace,
30 ReportTypeThreadLeak,
31 ReportTypeMutexDestroyLocked,
32 ReportTypeMutexDoubleLock,
33 ReportTypeMutexInvalidAccess,
34 ReportTypeMutexBadUnlock,
35 ReportTypeMutexBadReadLock,
36 ReportTypeMutexBadReadUnlock,
37 ReportTypeSignalUnsafe,
38 ReportTypeErrnoInSignal,
39 ReportTypeDeadlock,
40 ReportTypeMutexHeldWrongContext
41};
42
43struct ReportStack {
44 SymbolizedStack *frames = nullptr;
45 bool suppressable = false;
46};
47
48struct ReportMopMutex {
49 int id = 0;
50 bool write = false;
51};
52
53struct ReportMop {
54 int tid = kInvalidTid;
55 uptr addr = 0;
56 int size = 0;
57 bool write = false;
58 bool atomic = false;
59 uptr external_tag = 0;
60 Vector<ReportMopMutex> mset;
61 StackTrace stack_trace;
62 ReportStack* stack = nullptr;
63
64 ReportMop();
65 ~ReportMop();
66};
67
68enum ReportLocationType {
69 ReportLocationGlobal,
70 ReportLocationHeap,
71 ReportLocationStack,
72 ReportLocationTLS,
73 ReportLocationFD
74};
75
76struct ReportLocation {
77 ReportLocationType type = ReportLocationGlobal;
78 DataInfo global = {};
79 uptr heap_chunk_start = 0;
80 uptr heap_chunk_size = 0;
81 uptr external_tag = 0;
82 Tid tid = kInvalidTid;
83 int fd = 0;
84 bool fd_closed = false;
85 bool suppressable = false;
86 StackID stack_id = 0;
87 ReportStack *stack = nullptr;
88};
89
90struct ReportThread {
91 Tid id = kInvalidTid;
92 ThreadID os_id = 0;
93 bool running = false;
94 ThreadType thread_type = ThreadType::Regular;
95 char* name = nullptr;
96 Tid parent_tid = kInvalidTid;
97 StackID stack_id = 0;
98 ReportStack* stack = nullptr;
99 bool suppressable = false;
100};
101
102struct ReportMutex {
103 int id = 0;
104 uptr addr = 0;
105 StackID stack_id = 0;
106 ReportStack* stack = nullptr;
107};
108
109struct AddedStack {
110 StackTrace stack_trace;
111 bool suppressable = false;
112};
113
114class ReportDesc {
115 public:
116 ReportType typ = ReportTypeRace;
117 uptr tag = kExternalTagNone;
118 Vector<ReportStack*> stacks;
119 Vector<AddedStack> added_stacks;
120 Vector<ReportMop*> mops;
121 Vector<ReportLocation*> locs;
122 Vector<uptr> loc_addrs;
123 Vector<ReportMutex*> mutexes;
124 Vector<ReportThread*> threads;
125 Vector<Tid> unique_tids;
126 ReportStack* sleep = nullptr;
127 StackID sleep_stack_id = 0;
128 int count = 0;
129 int signum = 0;
130
131 ReportDesc();
132 ~ReportDesc();
133
134 private:
135 ReportDesc(const ReportDesc&);
136 void operator = (const ReportDesc&);
137};
138
139// Format and output the report to the console/log. No additional logic.
140void PrintReport(const ReportDesc *rep);
141void PrintStack(const ReportStack *stack);
142
143} // namespace __tsan
144
145#endif // TSAN_REPORT_H
146