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_symbolizer.h"
16 #include "sanitizer_common/sanitizer_thread_registry.h"
17 #include "sanitizer_common/sanitizer_vector.h"
18 #include "tsan_defs.h"
19 
20 namespace __tsan {
21 
22 enum ReportType {
23   ReportTypeRace,
24   ReportTypeVptrRace,
25   ReportTypeUseAfterFree,
26   ReportTypeVptrUseAfterFree,
27   ReportTypeExternalRace,
28   ReportTypeThreadLeak,
29   ReportTypeMutexDestroyLocked,
30   ReportTypeMutexDoubleLock,
31   ReportTypeMutexInvalidAccess,
32   ReportTypeMutexBadUnlock,
33   ReportTypeMutexBadReadLock,
34   ReportTypeMutexBadReadUnlock,
35   ReportTypeSignalUnsafe,
36   ReportTypeErrnoInSignal,
37   ReportTypeDeadlock
38 };
39 
40 struct ReportStack {
41   SymbolizedStack *frames = nullptr;
42   bool suppressable = false;
43 };
44 
45 struct ReportMopMutex {
46   int id;
47   bool write;
48 };
49 
50 struct ReportMop {
51   int tid;
52   uptr addr;
53   int size;
54   bool write;
55   bool atomic;
56   uptr external_tag;
57   Vector<ReportMopMutex> mset;
58   ReportStack *stack;
59 
60   ReportMop();
61 };
62 
63 enum ReportLocationType {
64   ReportLocationGlobal,
65   ReportLocationHeap,
66   ReportLocationStack,
67   ReportLocationTLS,
68   ReportLocationFD
69 };
70 
71 struct ReportLocation {
72   ReportLocationType type = ReportLocationGlobal;
73   DataInfo global = {};
74   uptr heap_chunk_start = 0;
75   uptr heap_chunk_size = 0;
76   uptr external_tag = 0;
77   Tid tid = kInvalidTid;
78   int fd = 0;
79   bool fd_closed = false;
80   bool suppressable = false;
81   ReportStack *stack = nullptr;
82 };
83 
84 struct ReportThread {
85   Tid id;
86   tid_t os_id;
87   bool running;
88   ThreadType thread_type;
89   char *name;
90   Tid parent_tid;
91   ReportStack *stack;
92 };
93 
94 struct ReportMutex {
95   int id;
96   uptr addr;
97   ReportStack *stack;
98 };
99 
100 class ReportDesc {
101  public:
102   ReportType typ;
103   uptr tag;
104   Vector<ReportStack*> stacks;
105   Vector<ReportMop*> mops;
106   Vector<ReportLocation*> locs;
107   Vector<ReportMutex*> mutexes;
108   Vector<ReportThread*> threads;
109   Vector<Tid> unique_tids;
110   ReportStack *sleep;
111   int count;
112   int signum = 0;
113 
114   ReportDesc();
115   ~ReportDesc();
116 
117  private:
118   ReportDesc(const ReportDesc&);
119   void operator = (const ReportDesc&);
120 };
121 
122 // Format and output the report to the console/log. No additional logic.
123 void PrintReport(const ReportDesc *rep);
124 void PrintStack(const ReportStack *stack);
125 
126 }  // namespace __tsan
127 
128 #endif  // TSAN_REPORT_H
129