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 suppressable = false;
80   ReportStack *stack = nullptr;
81 };
82 
83 struct ReportThread {
84   Tid id;
85   tid_t os_id;
86   bool running;
87   ThreadType thread_type;
88   char *name;
89   Tid parent_tid;
90   ReportStack *stack;
91 };
92 
93 struct ReportMutex {
94   int id;
95   uptr addr;
96   ReportStack *stack;
97 };
98 
99 class ReportDesc {
100  public:
101   ReportType typ;
102   uptr tag;
103   Vector<ReportStack*> stacks;
104   Vector<ReportMop*> mops;
105   Vector<ReportLocation*> locs;
106   Vector<ReportMutex*> mutexes;
107   Vector<ReportThread*> threads;
108   Vector<Tid> unique_tids;
109   ReportStack *sleep;
110   int count;
111   int signum = 0;
112 
113   ReportDesc();
114   ~ReportDesc();
115 
116  private:
117   ReportDesc(const ReportDesc&);
118   void operator = (const ReportDesc&);
119 };
120 
121 // Format and output the report to the console/log. No additional logic.
122 void PrintReport(const ReportDesc *rep);
123 void PrintStack(const ReportStack *stack);
124 
125 }  // namespace __tsan
126 
127 #endif  // TSAN_REPORT_H
128