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