authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-10 00:59:52-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-10 01:00:37-07:00
log854b88fda0dc6e92399c27f819bb2a0f5c090eb9
tree519ea4302d30255d6ca79337cc326261f4058a14
parent036e9fd479219ed1116fed8c0da89fa5a2829cf9

tsan: update rtl files to LLVM 17.0.6


214 files changed, 15752 insertions(+), 9952 deletions(-)

lib/tsan/interception/interception.h+145-71
......@@ -14,9 +14,10 @@
1414#ifndef INTERCEPTION_H
1515#define INTERCEPTION_H
1616
17#include "sanitizer_common/sanitizer_asm.h"
1718#include "sanitizer_common/sanitizer_internal_defs.h"
1819
19#if !SANITIZER_LINUX && !SANITIZER_FREEBSD && !SANITIZER_MAC && \
20#if !SANITIZER_LINUX && !SANITIZER_FREEBSD && !SANITIZER_APPLE && \
2021 !SANITIZER_NETBSD && !SANITIZER_WINDOWS && !SANITIZER_FUCHSIA && \
2122 !SANITIZER_SOLARIS
2223# error "Interception doesn't work on this operating system."
......@@ -67,28 +68,54 @@ typedef __sanitizer::OFF64_T OFF64_T;
6768// for more details). To intercept such functions you need to use the
6869// INTERCEPTOR_WITH_SUFFIX(...) macro.
6970
70// How it works:
71// To replace system functions on Linux we just need to declare functions
72// with same names in our library and then obtain the real function pointers
71// How it works on Linux
72// ---------------------
73//
74// To replace system functions on Linux we just need to declare functions with
75// the same names in our library and then obtain the real function pointers
7376// using dlsym().
74// There is one complication. A user may also intercept some of the functions
75// we intercept. To resolve this we declare our interceptors with __interceptor_
76// prefix, and then make actual interceptors weak aliases to __interceptor_
77// functions.
7877//
79// This is not so on Mac OS, where the two-level namespace makes
80// our replacement functions invisible to other libraries. This may be overcomed
81// using the DYLD_FORCE_FLAT_NAMESPACE, but some errors loading the shared
82// libraries in Chromium were noticed when doing so.
78// There is one complication: a user may also intercept some of the functions we
79// intercept. To allow for up to 3 interceptors (including ours) of a given
80// function "func", the interceptor implementation is in ___interceptor_func,
81// which is aliased by a weak function __interceptor_func, which in turn is
82// aliased (via a trampoline) by weak wrapper function "func".
83//
84// Most user interceptors should define a foreign interceptor as follows:
85//
86// - provide a non-weak function "func" that performs interception;
87// - if __interceptor_func exists, call it to perform the real functionality;
88// - if it does not exist, figure out the real function and call it instead.
89//
90// In rare cases, a foreign interceptor (of another dynamic analysis runtime)
91// may be defined as follows (on supported architectures):
92//
93// - provide a non-weak function __interceptor_func that performs interception;
94// - if ___interceptor_func exists, call it to perform the real functionality;
95// - if it does not exist, figure out the real function and call it instead;
96// - provide a weak function "func" that is an alias to __interceptor_func.
97//
98// With this protocol, sanitizer interceptors, foreign user interceptors, and
99// foreign interceptors of other dynamic analysis runtimes, or any combination
100// thereof, may co-exist simultaneously.
101//
102// How it works on Mac OS
103// ----------------------
104//
105// This is not so on Mac OS, where the two-level namespace makes our replacement
106// functions invisible to other libraries. This may be overcomed using the
107// DYLD_FORCE_FLAT_NAMESPACE, but some errors loading the shared libraries in
108// Chromium were noticed when doing so.
109//
83110// Instead we create a dylib containing a __DATA,__interpose section that
84111// associates library functions with their wrappers. When this dylib is
85// preloaded before an executable using DYLD_INSERT_LIBRARIES, it routes all
86// the calls to interposed functions done through stubs to the wrapper
87// functions.
112// preloaded before an executable using DYLD_INSERT_LIBRARIES, it routes all the
113// calls to interposed functions done through stubs to the wrapper functions.
114//
88115// As it's decided at compile time which functions are to be intercepted on Mac,
89116// INTERCEPT_FUNCTION() is effectively a no-op on this system.
90117
91#if SANITIZER_MAC
118#if SANITIZER_APPLE
92119#include <sys/cdefs.h> // For __DARWIN_ALIAS_C().
93120
94121// Just a pair of pointers.
......@@ -100,53 +127,102 @@ struct interpose_substitution {
100127// For a function foo() create a global pair of pointers { wrap_foo, foo } in
101128// the __DATA,__interpose section.
102129// As a result all the calls to foo() will be routed to wrap_foo() at runtime.
103#define INTERPOSER(func_name) __attribute__((used)) \
130#define INTERPOSER(func_name) __attribute__((used)) \
104131const interpose_substitution substitution_##func_name[] \
105132 __attribute__((section("__DATA, __interpose"))) = { \
106 { reinterpret_cast<const uptr>(WRAP(func_name)), \
107 reinterpret_cast<const uptr>(func_name) } \
133 { reinterpret_cast<const uptr>(WRAP(func_name)), \
134 reinterpret_cast<const uptr>(func_name) } \
108135}
109136
110137// For a function foo() and a wrapper function bar() create a global pair
111138// of pointers { bar, foo } in the __DATA,__interpose section.
112139// As a result all the calls to foo() will be routed to bar() at runtime.
113140#define INTERPOSER_2(func_name, wrapper_name) __attribute__((used)) \
114const interpose_substitution substitution_##func_name[] \
115 __attribute__((section("__DATA, __interpose"))) = { \
116 { reinterpret_cast<const uptr>(wrapper_name), \
117 reinterpret_cast<const uptr>(func_name) } \
141const interpose_substitution substitution_##func_name[] \
142 __attribute__((section("__DATA, __interpose"))) = { \
143 { reinterpret_cast<const uptr>(wrapper_name), \
144 reinterpret_cast<const uptr>(func_name) } \
118145}
119146
120147# define WRAP(x) wrap_##x
121# define WRAPPER_NAME(x) "wrap_"#x
148# define TRAMPOLINE(x) WRAP(x)
122149# define INTERCEPTOR_ATTRIBUTE
123150# define DECLARE_WRAPPER(ret_type, func, ...)
124151
125152#elif SANITIZER_WINDOWS
126153# define WRAP(x) __asan_wrap_##x
127# define WRAPPER_NAME(x) "__asan_wrap_"#x
154# define TRAMPOLINE(x) WRAP(x)
128155# define INTERCEPTOR_ATTRIBUTE __declspec(dllexport)
129# define DECLARE_WRAPPER(ret_type, func, ...) \
156# define DECLARE_WRAPPER(ret_type, func, ...) \
130157 extern "C" ret_type func(__VA_ARGS__);
131# define DECLARE_WRAPPER_WINAPI(ret_type, func, ...) \
158# define DECLARE_WRAPPER_WINAPI(ret_type, func, ...) \
132159 extern "C" __declspec(dllimport) ret_type __stdcall func(__VA_ARGS__);
133#elif SANITIZER_FREEBSD || SANITIZER_NETBSD
134# define WRAP(x) __interceptor_ ## x
135# define WRAPPER_NAME(x) "__interceptor_" #x
160#elif !SANITIZER_FUCHSIA // LINUX, FREEBSD, NETBSD, SOLARIS
136161# define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default")))
162# if ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT
163// Weak aliases of weak aliases do not work, therefore we need to set up a
164// trampoline function. The function "func" is a weak alias to the trampoline
165// (so that we may check if "func" was overridden), which calls the weak
166// function __interceptor_func, which in turn aliases the actual interceptor
167// implementation ___interceptor_func:
168//
169// [wrapper "func": weak] --(alias)--> [TRAMPOLINE(func)]
170// |
171// +--------(tail call)-------+
172// |
173// v
174// [__interceptor_func: weak] --(alias)--> [WRAP(func)]
175//
176// We use inline assembly to define most of this, because not all compilers
177// support functions with the "naked" attribute with every architecture.
178# define WRAP(x) ___interceptor_ ## x
179# define TRAMPOLINE(x) __interceptor_trampoline_ ## x
180# if SANITIZER_FREEBSD || SANITIZER_NETBSD
137181// FreeBSD's dynamic linker (incompliantly) gives non-weak symbols higher
138182// priority than weak ones so weak aliases won't work for indirect calls
139183// in position-independent (-fPIC / -fPIE) mode.
140# define DECLARE_WRAPPER(ret_type, func, ...) \
141 extern "C" ret_type func(__VA_ARGS__) \
142 __attribute__((alias("__interceptor_" #func), visibility("default")));
143#elif !SANITIZER_FUCHSIA
144# define WRAP(x) __interceptor_ ## x
145# define WRAPPER_NAME(x) "__interceptor_" #x
146# define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default")))
147# define DECLARE_WRAPPER(ret_type, func, ...) \
148 extern "C" ret_type func(__VA_ARGS__) \
149 __attribute__((weak, alias("__interceptor_" #func), visibility("default")));
184# define __ASM_WEAK_WRAPPER(func) ".globl " #func "\n"
185# else
186# define __ASM_WEAK_WRAPPER(func) ".weak " #func "\n"
187# endif // SANITIZER_FREEBSD || SANITIZER_NETBSD
188// Keep trampoline implementation in sync with sanitizer_common/sanitizer_asm.h
189# define DECLARE_WRAPPER(ret_type, func, ...) \
190 extern "C" ret_type func(__VA_ARGS__); \
191 extern "C" ret_type TRAMPOLINE(func)(__VA_ARGS__); \
192 extern "C" ret_type __interceptor_##func(__VA_ARGS__) \
193 INTERCEPTOR_ATTRIBUTE __attribute__((weak)) ALIAS(WRAP(func)); \
194 asm( \
195 ".text\n" \
196 __ASM_WEAK_WRAPPER(func) \
197 ".set " #func ", " SANITIZER_STRINGIFY(TRAMPOLINE(func)) "\n" \
198 ".globl " SANITIZER_STRINGIFY(TRAMPOLINE(func)) "\n" \
199 ".type " SANITIZER_STRINGIFY(TRAMPOLINE(func)) ", %function\n" \
200 SANITIZER_STRINGIFY(TRAMPOLINE(func)) ":\n" \
201 SANITIZER_STRINGIFY(CFI_STARTPROC) "\n" \
202 SANITIZER_STRINGIFY(ASM_TAIL_CALL) " __interceptor_" \
203 SANITIZER_STRINGIFY(ASM_PREEMPTIBLE_SYM(func)) "\n" \
204 SANITIZER_STRINGIFY(CFI_ENDPROC) "\n" \
205 ".size " SANITIZER_STRINGIFY(TRAMPOLINE(func)) ", " \
206 ".-" SANITIZER_STRINGIFY(TRAMPOLINE(func)) "\n" \
207 );
208# else // ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT
209// Some architectures cannot implement efficient interceptor trampolines with
210// just a plain jump due to complexities of resolving a preemptible symbol. In
211// those cases, revert to just this scheme:
212//
213// [wrapper "func": weak] --(alias)--> [WRAP(func)]
214//
215# define WRAP(x) __interceptor_ ## x
216# define TRAMPOLINE(x) WRAP(x)
217# if SANITIZER_FREEBSD || SANITIZER_NETBSD
218# define __ATTRIBUTE_WEAK_WRAPPER
219# else
220# define __ATTRIBUTE_WEAK_WRAPPER __attribute__((weak))
221# endif // SANITIZER_FREEBSD || SANITIZER_NETBSD
222# define DECLARE_WRAPPER(ret_type, func, ...) \
223 extern "C" ret_type func(__VA_ARGS__) \
224 INTERCEPTOR_ATTRIBUTE __ATTRIBUTE_WEAK_WRAPPER ALIAS(WRAP(func));
225# endif // ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT
150226#endif
151227
152228#if SANITIZER_FUCHSIA
......@@ -157,33 +233,35 @@ const interpose_substitution substitution_##func_name[] \
157233# define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default")))
158234# define REAL(x) __unsanitized_##x
159235# define DECLARE_REAL(ret_type, func, ...)
160#elif !SANITIZER_MAC
236#elif !SANITIZER_APPLE
161237# define PTR_TO_REAL(x) real_##x
162238# define REAL(x) __interception::PTR_TO_REAL(x)
163239# define FUNC_TYPE(x) x##_type
164240
165# define DECLARE_REAL(ret_type, func, ...) \
241# define DECLARE_REAL(ret_type, func, ...) \
166242 typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \
167 namespace __interception { \
168 extern FUNC_TYPE(func) PTR_TO_REAL(func); \
243 namespace __interception { \
244 extern FUNC_TYPE(func) PTR_TO_REAL(func); \
169245 }
170246# define ASSIGN_REAL(dst, src) REAL(dst) = REAL(src)
171#else // SANITIZER_MAC
247#else // SANITIZER_APPLE
172248# define REAL(x) x
173249# define DECLARE_REAL(ret_type, func, ...) \
174250 extern "C" ret_type func(__VA_ARGS__);
175251# define ASSIGN_REAL(x, y)
176#endif // SANITIZER_MAC
252#endif // SANITIZER_APPLE
177253
178254#if !SANITIZER_FUCHSIA
179# define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...) \
255# define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...) \
180256 DECLARE_REAL(ret_type, func, __VA_ARGS__) \
257 extern "C" ret_type TRAMPOLINE(func)(__VA_ARGS__); \
181258 extern "C" ret_type WRAP(func)(__VA_ARGS__);
182259// Declare an interceptor and its wrapper defined in a different translation
183260// unit (ex. asm).
184# define DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(ret_type, func, ...) \
185 extern "C" ret_type WRAP(func)(__VA_ARGS__); \
186 extern "C" ret_type func(__VA_ARGS__);
261# define DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(ret_type, func, ...) \
262 extern "C" ret_type TRAMPOLINE(func)(__VA_ARGS__); \
263 extern "C" ret_type WRAP(func)(__VA_ARGS__); \
264 extern "C" ret_type func(__VA_ARGS__);
187265#else
188266# define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...)
189267# define DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(ret_type, func, ...)
......@@ -193,7 +271,7 @@ const interpose_substitution substitution_##func_name[] \
193271// macros does its job. In exceptional cases you may need to call REAL(foo)
194272// without defining INTERCEPTOR(..., foo, ...). For example, if you override
195273// foo with an interceptor for other function.
196#if !SANITIZER_MAC && !SANITIZER_FUCHSIA
274#if !SANITIZER_APPLE && !SANITIZER_FUCHSIA
197275# define DEFINE_REAL(ret_type, func, ...) \
198276 typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \
199277 namespace __interception { \
......@@ -213,25 +291,23 @@ const interpose_substitution substitution_##func_name[] \
213291 __interceptor_##func(__VA_ARGS__); \
214292 extern "C" INTERCEPTOR_ATTRIBUTE ret_type func(__VA_ARGS__)
215293
216#elif !SANITIZER_MAC
294#elif !SANITIZER_APPLE
217295
218#define INTERCEPTOR(ret_type, func, ...) \
219 DEFINE_REAL(ret_type, func, __VA_ARGS__) \
220 DECLARE_WRAPPER(ret_type, func, __VA_ARGS__) \
221 extern "C" \
222 INTERCEPTOR_ATTRIBUTE \
223 ret_type WRAP(func)(__VA_ARGS__)
296#define INTERCEPTOR(ret_type, func, ...) \
297 DEFINE_REAL(ret_type, func, __VA_ARGS__) \
298 DECLARE_WRAPPER(ret_type, func, __VA_ARGS__) \
299 extern "C" INTERCEPTOR_ATTRIBUTE ret_type WRAP(func)(__VA_ARGS__)
224300
225301// We don't need INTERCEPTOR_WITH_SUFFIX on non-Darwin for now.
226302#define INTERCEPTOR_WITH_SUFFIX(ret_type, func, ...) \
227303 INTERCEPTOR(ret_type, func, __VA_ARGS__)
228304
229#else // SANITIZER_MAC
305#else // SANITIZER_APPLE
230306
231#define INTERCEPTOR_ZZZ(suffix, ret_type, func, ...) \
232 extern "C" ret_type func(__VA_ARGS__) suffix; \
233 extern "C" ret_type WRAP(func)(__VA_ARGS__); \
234 INTERPOSER(func); \
307#define INTERCEPTOR_ZZZ(suffix, ret_type, func, ...) \
308 extern "C" ret_type func(__VA_ARGS__) suffix; \
309 extern "C" ret_type WRAP(func)(__VA_ARGS__); \
310 INTERPOSER(func); \
235311 extern "C" INTERCEPTOR_ATTRIBUTE ret_type WRAP(func)(__VA_ARGS__)
236312
237313#define INTERCEPTOR(ret_type, func, ...) \
......@@ -246,14 +322,12 @@ const interpose_substitution substitution_##func_name[] \
246322#endif
247323
248324#if SANITIZER_WINDOWS
249# define INTERCEPTOR_WINAPI(ret_type, func, ...) \
325# define INTERCEPTOR_WINAPI(ret_type, func, ...) \
250326 typedef ret_type (__stdcall *FUNC_TYPE(func))(__VA_ARGS__); \
251 namespace __interception { \
252 FUNC_TYPE(func) PTR_TO_REAL(func); \
253 } \
254 extern "C" \
255 INTERCEPTOR_ATTRIBUTE \
256 ret_type __stdcall WRAP(func)(__VA_ARGS__)
327 namespace __interception { \
328 FUNC_TYPE(func) PTR_TO_REAL(func); \
329 } \
330 extern "C" INTERCEPTOR_ATTRIBUTE ret_type __stdcall WRAP(func)(__VA_ARGS__)
257331#endif
258332
259333// ISO C++ forbids casting between pointer-to-function and pointer-to-object,
......@@ -278,7 +352,7 @@ typedef unsigned long uptr;
278352# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
279353# define INTERCEPT_FUNCTION_VER(func, symver) \
280354 INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver)
281#elif SANITIZER_MAC
355#elif SANITIZER_APPLE
282356# include "interception_mac.h"
283357# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_MAC(func)
284358# define INTERCEPT_FUNCTION_VER(func, symver) \
lib/tsan/interception/interception_linux.cpp+8-8
......@@ -33,7 +33,7 @@ static int StrCmp(const char *s1, const char *s2) {
3333}
3434#endif
3535
36static void *GetFuncAddr(const char *name, uptr wrapper_addr) {
36static void *GetFuncAddr(const char *name, uptr trampoline) {
3737#if SANITIZER_NETBSD
3838 // FIXME: Find a better way to handle renames
3939 if (StrCmp(name, "sigaction"))
......@@ -50,17 +50,17 @@ static void *GetFuncAddr(const char *name, uptr wrapper_addr) {
5050
5151 // In case `name' is not loaded, dlsym ends up finding the actual wrapper.
5252 // We don't want to intercept the wrapper and have it point to itself.
53 if ((uptr)addr == wrapper_addr)
53 if ((uptr)addr == trampoline)
5454 addr = nullptr;
5555 }
5656 return addr;
5757}
5858
5959bool InterceptFunction(const char *name, uptr *ptr_to_real, uptr func,
60 uptr wrapper) {
61 void *addr = GetFuncAddr(name, wrapper);
60 uptr trampoline) {
61 void *addr = GetFuncAddr(name, trampoline);
6262 *ptr_to_real = (uptr)addr;
63 return addr && (func == wrapper);
63 return addr && (func == trampoline);
6464}
6565
6666// dlvsym is a GNU extension supported by some other platforms.
......@@ -70,12 +70,12 @@ static void *GetFuncAddr(const char *name, const char *ver) {
7070}
7171
7272bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real,
73 uptr func, uptr wrapper) {
73 uptr func, uptr trampoline) {
7474 void *addr = GetFuncAddr(name, ver);
7575 *ptr_to_real = (uptr)addr;
76 return addr && (func == wrapper);
76 return addr && (func == trampoline);
7777}
78#endif // SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD
78# endif // SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD
7979
8080} // namespace __interception
8181
lib/tsan/interception/interception_linux.h+9-9
......@@ -15,7 +15,7 @@
1515 SANITIZER_SOLARIS
1616
1717#if !defined(INCLUDED_FROM_INTERCEPTION_LIB)
18# error "interception_linux.h should be included from interception library only"
18# error interception_linux.h should be included from interception library only
1919#endif
2020
2121#ifndef INTERCEPTION_LINUX_H
......@@ -23,26 +23,26 @@
2323
2424namespace __interception {
2525bool InterceptFunction(const char *name, uptr *ptr_to_real, uptr func,
26 uptr wrapper);
26 uptr trampoline);
2727bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real,
28 uptr func, uptr wrapper);
28 uptr func, uptr trampoline);
2929} // namespace __interception
3030
3131#define INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func) \
3232 ::__interception::InterceptFunction( \
3333 #func, \
34 (::__interception::uptr *) & REAL(func), \
35 (::__interception::uptr) & (func), \
36 (::__interception::uptr) & WRAP(func))
34 (::__interception::uptr *)&REAL(func), \
35 (::__interception::uptr)&(func), \
36 (::__interception::uptr)&TRAMPOLINE(func))
3737
3838// dlvsym is a GNU extension supported by some other platforms.
3939#if SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD
4040#define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \
4141 ::__interception::InterceptFunction( \
4242 #func, symver, \
43 (::__interception::uptr *) & REAL(func), \
44 (::__interception::uptr) & (func), \
45 (::__interception::uptr) & WRAP(func))
43 (::__interception::uptr *)&REAL(func), \
44 (::__interception::uptr)&(func), \
45 (::__interception::uptr)&TRAMPOLINE(func))
4646#else
4747#define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \
4848 INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
lib/tsan/interception/interception_mac.cpp+2-2
......@@ -13,6 +13,6 @@
1313
1414#include "interception.h"
1515
16#if SANITIZER_MAC
16#if SANITIZER_APPLE
1717
18#endif // SANITIZER_MAC
18#endif // SANITIZER_APPLE
lib/tsan/interception/interception_mac.h+2-2
......@@ -11,7 +11,7 @@
1111// Mac-specific interception methods.
1212//===----------------------------------------------------------------------===//
1313
14#if SANITIZER_MAC
14#if SANITIZER_APPLE
1515
1616#if !defined(INCLUDED_FROM_INTERCEPTION_LIB)
1717# error "interception_mac.h should be included from interception.h only"
......@@ -24,4 +24,4 @@
2424#define INTERCEPT_FUNCTION_VER_MAC(func, symver)
2525
2626#endif // INTERCEPTION_MAC_H
27#endif // SANITIZER_MAC
27#endif // SANITIZER_APPLE
lib/tsan/interception/interception_type_test.cpp+3-3
......@@ -13,7 +13,7 @@
1313
1414#include "interception.h"
1515
16#if SANITIZER_LINUX || SANITIZER_MAC
16#if SANITIZER_LINUX || SANITIZER_APPLE
1717
1818#include <sys/types.h>
1919#include <stddef.h>
......@@ -24,9 +24,9 @@ COMPILER_CHECK(sizeof(::SSIZE_T) == sizeof(ssize_t));
2424COMPILER_CHECK(sizeof(::PTRDIFF_T) == sizeof(ptrdiff_t));
2525COMPILER_CHECK(sizeof(::INTMAX_T) == sizeof(intmax_t));
2626
27#if !SANITIZER_MAC
27# if SANITIZER_GLIBC || SANITIZER_ANDROID
2828COMPILER_CHECK(sizeof(::OFF64_T) == sizeof(off64_t));
29#endif
29# endif
3030
3131// The following are the cases when pread (and friends) is used instead of
3232// pread64. In those cases we need OFF_T to match off_t. We don't care about the
lib/tsan/interception/interception_win.cpp+107-11
......@@ -56,7 +56,7 @@
5656// tramp: jmp QWORD [addr]
5757// addr: .bytes <hook>
5858//
59// Note: <real> is equilavent to <label>.
59// Note: <real> is equivalent to <label>.
6060//
6161// 3) HotPatch
6262//
......@@ -141,8 +141,29 @@ static const int kBranchLength =
141141 FIRST_32_SECOND_64(kJumpInstructionLength, kIndirectJumpInstructionLength);
142142static const int kDirectBranchLength = kBranchLength + kAddressLength;
143143
144# if defined(_MSC_VER)
145# define INTERCEPTION_FORMAT(f, a)
146# else
147# define INTERCEPTION_FORMAT(f, a) __attribute__((format(printf, f, a)))
148# endif
149
150static void (*ErrorReportCallback)(const char *format, ...)
151 INTERCEPTION_FORMAT(1, 2);
152
153void SetErrorReportCallback(void (*callback)(const char *format, ...)) {
154 ErrorReportCallback = callback;
155}
156
157# define ReportError(...) \
158 do { \
159 if (ErrorReportCallback) \
160 ErrorReportCallback(__VA_ARGS__); \
161 } while (0)
162
144163static void InterceptionFailed() {
145 // Do we have a good way to abort with an error message here?
164 ReportError("interception_win: failed due to an unrecoverable error.\n");
165 // This acts like an abort when no debugger is attached. According to an old
166 // comment, calling abort() leads to an infinite recursion in CheckFailed.
146167 __debugbreak();
147168}
148169
......@@ -249,8 +270,13 @@ static void WritePadding(uptr from, uptr size) {
249270}
250271
251272static void WriteJumpInstruction(uptr from, uptr target) {
252 if (!DistanceIsWithin2Gig(from + kJumpInstructionLength, target))
273 if (!DistanceIsWithin2Gig(from + kJumpInstructionLength, target)) {
274 ReportError(
275 "interception_win: cannot write jmp further than 2GB away, from %p to "
276 "%p.\n",
277 (void *)from, (void *)target);
253278 InterceptionFailed();
279 }
254280 ptrdiff_t offset = target - from - kJumpInstructionLength;
255281 *(u8*)from = 0xE9;
256282 *(u32*)(from + 1) = offset;
......@@ -274,6 +300,10 @@ static void WriteIndirectJumpInstruction(uptr from, uptr indirect_target) {
274300 int offset = indirect_target - from - kIndirectJumpInstructionLength;
275301 if (!DistanceIsWithin2Gig(from + kIndirectJumpInstructionLength,
276302 indirect_target)) {
303 ReportError(
304 "interception_win: cannot write indirect jmp with target further than "
305 "2GB away, from %p to %p.\n",
306 (void *)from, (void *)indirect_target);
277307 InterceptionFailed();
278308 }
279309 *(u16*)from = 0x25FF;
......@@ -398,8 +428,44 @@ static uptr AllocateMemoryForTrampoline(uptr image_address, size_t size) {
398428 return allocated_space;
399429}
400430
431// The following prologues cannot be patched because of the short jump
432// jumping to the patching region.
433
434#if SANITIZER_WINDOWS64
435// ntdll!wcslen in Win11
436// 488bc1 mov rax,rcx
437// 0fb710 movzx edx,word ptr [rax]
438// 4883c002 add rax,2
439// 6685d2 test dx,dx
440// 75f4 jne -12
441static const u8 kPrologueWithShortJump1[] = {
442 0x48, 0x8b, 0xc1, 0x0f, 0xb7, 0x10, 0x48, 0x83,
443 0xc0, 0x02, 0x66, 0x85, 0xd2, 0x75, 0xf4,
444};
445
446// ntdll!strrchr in Win11
447// 4c8bc1 mov r8,rcx
448// 8a01 mov al,byte ptr [rcx]
449// 48ffc1 inc rcx
450// 84c0 test al,al
451// 75f7 jne -9
452static const u8 kPrologueWithShortJump2[] = {
453 0x4c, 0x8b, 0xc1, 0x8a, 0x01, 0x48, 0xff, 0xc1,
454 0x84, 0xc0, 0x75, 0xf7,
455};
456#endif
457
401458// Returns 0 on error.
402459static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
460#if SANITIZER_WINDOWS64
461 if (memcmp((u8*)address, kPrologueWithShortJump1,
462 sizeof(kPrologueWithShortJump1)) == 0 ||
463 memcmp((u8*)address, kPrologueWithShortJump2,
464 sizeof(kPrologueWithShortJump2)) == 0) {
465 return 0;
466 }
467#endif
468
403469 switch (*(u64*)address) {
404470 case 0x90909090909006EB: // stub: jmp over 6 x nop.
405471 return 8;
......@@ -456,6 +522,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
456522 case 0xFF8B: // 8B FF : mov edi, edi
457523 case 0xEC8B: // 8B EC : mov ebp, esp
458524 case 0xc889: // 89 C8 : mov eax, ecx
525 case 0xE589: // 89 E5 : mov ebp, esp
459526 case 0xC18B: // 8B C1 : mov eax, ecx
460527 case 0xC033: // 33 C0 : xor eax, eax
461528 case 0xC933: // 33 C9 : xor ecx, ecx
......@@ -477,6 +544,14 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
477544 case 0xA1: // A1 XX XX XX XX XX XX XX XX :
478545 // movabs eax, dword ptr ds:[XXXXXXXX]
479546 return 9;
547
548 case 0x83:
549 const u8 next_byte = *(u8*)(address + 1);
550 const u8 mod = next_byte >> 6;
551 const u8 rm = next_byte & 7;
552 if (mod == 1 && rm == 4)
553 return 5; // 83 ModR/M SIB Disp8 Imm8
554 // add|or|adc|sbb|and|sub|xor|cmp [r+disp8], imm8
480555 }
481556
482557 switch (*(u16*)address) {
......@@ -493,6 +568,8 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
493568 case 0x5641: // push r14
494569 case 0x5741: // push r15
495570 case 0x9066: // Two-byte NOP
571 case 0xc084: // test al, al
572 case 0x018a: // mov al, byte ptr [rcx]
496573 return 2;
497574
498575 case 0x058B: // 8B 05 XX XX XX XX : mov eax, dword ptr [XX XX XX XX]
......@@ -509,6 +586,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
509586 case 0xd12b48: // 48 2b d1 : sub rdx, rcx
510587 case 0x07c1f6: // f6 c1 07 : test cl, 0x7
511588 case 0xc98548: // 48 85 C9 : test rcx, rcx
589 case 0xd28548: // 48 85 d2 : test rdx, rdx
512590 case 0xc0854d: // 4d 85 c0 : test r8, r8
513591 case 0xc2b60f: // 0f b6 c2 : movzx eax, dl
514592 case 0xc03345: // 45 33 c0 : xor r8d, r8d
......@@ -522,6 +600,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
522600 case 0xca2b48: // 48 2b ca : sub rcx, rdx
523601 case 0x10b70f: // 0f b7 10 : movzx edx, WORD PTR [rax]
524602 case 0xc00b4d: // 3d 0b c0 : or r8, r8
603 case 0xc08b41: // 41 8b c0 : mov eax, r8d
525604 case 0xd18b48: // 48 8b d1 : mov rdx, rcx
526605 case 0xdc8b4c: // 4c 8b dc : mov r11, rsp
527606 case 0xd18b4c: // 4c 8b d1 : mov r10, rcx
......@@ -556,6 +635,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
556635 case 0x246c8948: // 48 89 6C 24 XX : mov QWORD ptr [rsp + XX], rbp
557636 case 0x245c8948: // 48 89 5c 24 XX : mov QWORD PTR [rsp + XX], rbx
558637 case 0x24748948: // 48 89 74 24 XX : mov QWORD PTR [rsp + XX], rsi
638 case 0x247c8948: // 48 89 7c 24 XX : mov QWORD PTR [rsp + XX], rdi
559639 case 0x244C8948: // 48 89 4C 24 XX : mov QWORD PTR [rsp + XX], rcx
560640 case 0x24548948: // 48 89 54 24 XX : mov QWORD PTR [rsp + XX], rdx
561641 case 0x244c894c: // 4c 89 4c 24 XX : mov QWORD PTR [rsp + XX], r9
......@@ -592,6 +672,8 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
592672 case 0x24448B: // 8B 44 24 XX : mov eax, dword ptr [esp + XX]
593673 case 0x244C8B: // 8B 4C 24 XX : mov ecx, dword ptr [esp + XX]
594674 case 0x24548B: // 8B 54 24 XX : mov edx, dword ptr [esp + XX]
675 case 0x245C8B: // 8B 5C 24 XX : mov ebx, dword ptr [esp + XX]
676 case 0x246C8B: // 8B 6C 24 XX : mov ebp, dword ptr [esp + XX]
595677 case 0x24748B: // 8B 74 24 XX : mov esi, dword ptr [esp + XX]
596678 case 0x247C8B: // 8B 7C 24 XX : mov edi, dword ptr [esp + XX]
597679 return 4;
......@@ -603,12 +685,20 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
603685 }
604686#endif
605687
606 // Unknown instruction!
607 // FIXME: Unknown instruction failures might happen when we add a new
608 // interceptor or a new compiler version. In either case, they should result
609 // in visible and readable error messages. However, merely calling abort()
610 // leads to an infinite recursion in CheckFailed.
611 InterceptionFailed();
688 // Unknown instruction! This might happen when we add a new interceptor, use
689 // a new compiler version, or if Windows changed how some functions are
690 // compiled. In either case, we print the address and 8 bytes of instructions
691 // to notify the user about the error and to help identify the unknown
692 // instruction. Don't treat this as a fatal error, though we can break the
693 // debugger if one has been attached.
694 u8 *bytes = (u8 *)address;
695 ReportError(
696 "interception_win: unhandled instruction at %p: %02x %02x %02x %02x %02x "
697 "%02x %02x %02x\n",
698 (void *)address, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4],
699 bytes[5], bytes[6], bytes[7]);
700 if (::IsDebuggerPresent())
701 __debugbreak();
612702 return 0;
613703}
614704
......@@ -629,6 +719,8 @@ static bool CopyInstructions(uptr to, uptr from, size_t size) {
629719 while (cursor != size) {
630720 size_t rel_offset = 0;
631721 size_t instruction_size = GetInstructionSize(from + cursor, &rel_offset);
722 if (!instruction_size)
723 return false;
632724 _memcpy((void*)(to + cursor), (void*)(from + cursor),
633725 (size_t)instruction_size);
634726 if (rel_offset) {
......@@ -689,7 +781,7 @@ bool OverrideFunctionWithRedirectJump(
689781 return false;
690782
691783 if (orig_old_func) {
692 uptr relative_offset = *(u32*)(old_func + 1);
784 sptr relative_offset = *(s32 *)(old_func + 1);
693785 uptr absolute_target = old_func + relative_offset + kJumpInstructionLength;
694786 *orig_old_func = absolute_target;
695787 }
......@@ -846,6 +938,10 @@ static void **InterestingDLLsAvailable() {
846938 "msvcr120.dll", // VS2013
847939 "vcruntime140.dll", // VS2015
848940 "ucrtbase.dll", // Universal CRT
941#if (defined(__MINGW32__) && defined(__i386__))
942 "libc++.dll", // libc++
943 "libunwind.dll", // libunwind
944#endif
849945 // NTDLL should go last as it exports some functions that we should
850946 // override in the CRT [presumably only used internally].
851947 "ntdll.dll", NULL};
......@@ -1019,4 +1115,4 @@ bool OverrideImportedFunction(const char *module_to_patch,
10191115
10201116} // namespace __interception
10211117
1022#endif // SANITIZER_MAC
1118#endif // SANITIZER_APPLE
lib/tsan/interception/interception_win.h+5
......@@ -41,6 +41,11 @@ bool OverrideImportedFunction(const char *module_to_patch,
4141 const char *function_name, uptr new_function,
4242 uptr *orig_old_func);
4343
44// Sets a callback to be used for reporting errors by interception_win. The
45// callback will be called with printf-like arguments. Intended to be used with
46// __sanitizer::Report. Pass nullptr to disable error reporting (default).
47void SetErrorReportCallback(void (*callback)(const char *format, ...));
48
4449#if !SANITIZER_WINDOWS64
4550// Exposed for unittests
4651bool OverrideFunctionWithDetour(
lib/tsan/sanitizer_common/sancov_flags.inc+1-1
......@@ -14,7 +14,7 @@
1414#endif
1515
1616SANCOV_FLAG(bool, symbolize, true,
17 "If set, converage information will be symbolized by sancov tool "
17 "If set, coverage information will be symbolized by sancov tool "
1818 "after dumping.")
1919
2020SANCOV_FLAG(bool, help, false, "Print flags help.")
lib/tsan/sanitizer_common/sanitizer_addrhashmap.h+43-3
......@@ -39,6 +39,11 @@ namespace __sanitizer {
3939// the current thread has exclusive access to the data
4040// if !h.exists() then the element never existed
4141// }
42// {
43// Map::Handle h(&m, addr, false, true);
44// this will create a new element or return a handle to an existing element
45// if !h.created() this thread does *not* have exclusive access to the data
46// }
4247template<typename T, uptr kSize>
4348class AddrHashMap {
4449 private:
......@@ -56,7 +61,7 @@ class AddrHashMap {
5661 static const uptr kBucketSize = 3;
5762
5863 struct Bucket {
59 RWMutex mtx;
64 Mutex mtx;
6065 atomic_uintptr_t add;
6166 Cell cells[kBucketSize];
6267 };
......@@ -89,6 +94,12 @@ class AddrHashMap {
8994 bool create_;
9095 };
9196
97 typedef void (*ForEachCallback)(const uptr key, const T &val, void *arg);
98 // ForEach acquires a lock on each bucket while iterating over
99 // elements. Note that this only ensures that the structure of the hashmap is
100 // unchanged, there may be a data race to the element itself.
101 void ForEach(ForEachCallback cb, void *arg);
102
92103 private:
93104 friend class Handle;
94105 Bucket *table_;
......@@ -98,6 +109,33 @@ class AddrHashMap {
98109 uptr calcHash(uptr addr);
99110};
100111
112template <typename T, uptr kSize>
113void AddrHashMap<T, kSize>::ForEach(ForEachCallback cb, void *arg) {
114 for (uptr n = 0; n < kSize; n++) {
115 Bucket *bucket = &table_[n];
116
117 ReadLock lock(&bucket->mtx);
118
119 for (uptr i = 0; i < kBucketSize; i++) {
120 Cell *c = &bucket->cells[i];
121 uptr addr1 = atomic_load(&c->addr, memory_order_acquire);
122 if (addr1 != 0)
123 cb(addr1, c->val, arg);
124 }
125
126 // Iterate over any additional cells.
127 if (AddBucket *add =
128 (AddBucket *)atomic_load(&bucket->add, memory_order_acquire)) {
129 for (uptr i = 0; i < add->size; i++) {
130 Cell *c = &add->cells[i];
131 uptr addr1 = atomic_load(&c->addr, memory_order_acquire);
132 if (addr1 != 0)
133 cb(addr1, c->val, arg);
134 }
135 }
136 }
137}
138
101139template<typename T, uptr kSize>
102140AddrHashMap<T, kSize>::Handle::Handle(AddrHashMap<T, kSize> *map, uptr addr) {
103141 map_ = map;
......@@ -163,7 +201,8 @@ AddrHashMap<T, kSize>::AddrHashMap() {
163201}
164202
165203template <typename T, uptr kSize>
166void AddrHashMap<T, kSize>::acquire(Handle *h) NO_THREAD_SAFETY_ANALYSIS {
204void AddrHashMap<T, kSize>::acquire(Handle *h)
205 SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
167206 uptr addr = h->addr_;
168207 uptr hash = calcHash(addr);
169208 Bucket *b = &table_[hash];
......@@ -292,7 +331,8 @@ void AddrHashMap<T, kSize>::acquire(Handle *h) NO_THREAD_SAFETY_ANALYSIS {
292331 }
293332
294333 template <typename T, uptr kSize>
295 void AddrHashMap<T, kSize>::release(Handle *h) NO_THREAD_SAFETY_ANALYSIS {
334 void AddrHashMap<T, kSize>::release(Handle *h)
335 SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
296336 if (!h->cell_)
297337 return;
298338 Bucket *b = h->bucket_;
lib/tsan/sanitizer_common/sanitizer_allocator.cpp+23-66
......@@ -17,6 +17,7 @@
1717#include "sanitizer_allocator_internal.h"
1818#include "sanitizer_atomic.h"
1919#include "sanitizer_common.h"
20#include "sanitizer_platform.h"
2021
2122namespace __sanitizer {
2223
......@@ -24,66 +25,6 @@ namespace __sanitizer {
2425const char *PrimaryAllocatorName = "SizeClassAllocator";
2526const char *SecondaryAllocatorName = "LargeMmapAllocator";
2627
27// ThreadSanitizer for Go uses libc malloc/free.
28#if defined(SANITIZER_USE_MALLOC)
29# if SANITIZER_LINUX && !SANITIZER_ANDROID
30extern "C" void *__libc_malloc(uptr size);
31# if !SANITIZER_GO
32extern "C" void *__libc_memalign(uptr alignment, uptr size);
33# endif
34extern "C" void *__libc_realloc(void *ptr, uptr size);
35extern "C" void __libc_free(void *ptr);
36# else
37# include <stdlib.h>
38# define __libc_malloc malloc
39# if !SANITIZER_GO
40static void *__libc_memalign(uptr alignment, uptr size) {
41 void *p;
42 uptr error = posix_memalign(&p, alignment, size);
43 if (error) return nullptr;
44 return p;
45}
46# endif
47# define __libc_realloc realloc
48# define __libc_free free
49# endif
50
51static void *RawInternalAlloc(uptr size, InternalAllocatorCache *cache,
52 uptr alignment) {
53 (void)cache;
54#if !SANITIZER_GO
55 if (alignment == 0)
56 return __libc_malloc(size);
57 else
58 return __libc_memalign(alignment, size);
59#else
60 // Windows does not provide __libc_memalign/posix_memalign. It provides
61 // __aligned_malloc, but the allocated blocks can't be passed to free,
62 // they need to be passed to __aligned_free. InternalAlloc interface does
63 // not account for such requirement. Alignemnt does not seem to be used
64 // anywhere in runtime, so just call __libc_malloc for now.
65 DCHECK_EQ(alignment, 0);
66 return __libc_malloc(size);
67#endif
68}
69
70static void *RawInternalRealloc(void *ptr, uptr size,
71 InternalAllocatorCache *cache) {
72 (void)cache;
73 return __libc_realloc(ptr, size);
74}
75
76static void RawInternalFree(void *ptr, InternalAllocatorCache *cache) {
77 (void)cache;
78 __libc_free(ptr);
79}
80
81InternalAllocator *internal_allocator() {
82 return 0;
83}
84
85#else // SANITIZER_GO || defined(SANITIZER_USE_MALLOC)
86
8728static ALIGNED(64) char internal_alloc_placeholder[sizeof(InternalAllocator)];
8829static atomic_uint8_t internal_allocator_initialized;
8930static StaticSpinMutex internal_alloc_init_mu;
......@@ -135,8 +76,6 @@ static void RawInternalFree(void *ptr, InternalAllocatorCache *cache) {
13576 internal_allocator()->Deallocate(cache, ptr);
13677}
13778
138#endif // SANITIZER_GO || defined(SANITIZER_USE_MALLOC)
139
14079static void NORETURN ReportInternalAllocatorOutOfMemory(uptr requested_size) {
14180 SetAllocatorOutOfMemory();
14281 Report("FATAL: %s: internal allocator is out of memory trying to allocate "
......@@ -187,6 +126,16 @@ void InternalFree(void *addr, InternalAllocatorCache *cache) {
187126 RawInternalFree(addr, cache);
188127}
189128
129void InternalAllocatorLock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
130 internal_allocator_cache_mu.Lock();
131 internal_allocator()->ForceLock();
132}
133
134void InternalAllocatorUnlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
135 internal_allocator()->ForceUnlock();
136 internal_allocator_cache_mu.Unlock();
137}
138
190139// LowLevelAllocator
191140constexpr uptr kLowLevelAllocatorDefaultAlignment = 8;
192141static uptr low_level_alloc_min_alignment = kLowLevelAllocatorDefaultAlignment;
......@@ -197,12 +146,10 @@ void *LowLevelAllocator::Allocate(uptr size) {
197146 size = RoundUpTo(size, low_level_alloc_min_alignment);
198147 if (allocated_end_ - allocated_current_ < (sptr)size) {
199148 uptr size_to_allocate = RoundUpTo(size, GetPageSizeCached());
200 allocated_current_ =
201 (char*)MmapOrDie(size_to_allocate, __func__);
149 allocated_current_ = (char *)MmapOrDie(size_to_allocate, __func__);
202150 allocated_end_ = allocated_current_ + size_to_allocate;
203151 if (low_level_alloc_callback) {
204 low_level_alloc_callback((uptr)allocated_current_,
205 size_to_allocate);
152 low_level_alloc_callback((uptr)allocated_current_, size_to_allocate);
206153 }
207154 }
208155 CHECK(allocated_end_ - allocated_current_ >= (sptr)size);
......@@ -247,4 +194,14 @@ void PrintHintAllocatorCannotReturnNull() {
247194 "allocator_may_return_null=1\n");
248195}
249196
197static atomic_uint8_t rss_limit_exceeded;
198
199bool IsRssLimitExceeded() {
200 return atomic_load(&rss_limit_exceeded, memory_order_relaxed);
201}
202
203void SetRssLimitExceeded(bool limit_exceeded) {
204 atomic_store(&rss_limit_exceeded, limit_exceeded, memory_order_relaxed);
205}
206
250207} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_allocator.h+11-7
......@@ -14,6 +14,7 @@
1414#define SANITIZER_ALLOCATOR_H
1515
1616#include "sanitizer_common.h"
17#include "sanitizer_flat_map.h"
1718#include "sanitizer_internal_defs.h"
1819#include "sanitizer_lfstack.h"
1920#include "sanitizer_libc.h"
......@@ -43,12 +44,6 @@ void SetAllocatorOutOfMemory();
4344
4445void PrintHintAllocatorCannotReturnNull();
4546
46// Allocators call these callbacks on mmap/munmap.
47struct NoOpMapUnmapCallback {
48 void OnMap(uptr p, uptr size) const { }
49 void OnUnmap(uptr p, uptr size) const { }
50};
51
5247// Callback type for iterating over chunks.
5348typedef void (*ForEachChunkCallback)(uptr chunk, void *arg);
5449
......@@ -67,15 +62,24 @@ inline void RandomShuffle(T *a, u32 n, u32 *rand_state) {
6762 *rand_state = state;
6863}
6964
65struct NoOpMapUnmapCallback {
66 void OnMap(uptr p, uptr size) const {}
67 void OnMapSecondary(uptr p, uptr size, uptr user_begin,
68 uptr user_size) const {}
69 void OnUnmap(uptr p, uptr size) const {}
70};
71
7072#include "sanitizer_allocator_size_class_map.h"
7173#include "sanitizer_allocator_stats.h"
7274#include "sanitizer_allocator_primary64.h"
73#include "sanitizer_allocator_bytemap.h"
7475#include "sanitizer_allocator_primary32.h"
7576#include "sanitizer_allocator_local_cache.h"
7677#include "sanitizer_allocator_secondary.h"
7778#include "sanitizer_allocator_combined.h"
7879
80bool IsRssLimitExceeded();
81void SetRssLimitExceeded(bool limit_exceeded);
82
7983} // namespace __sanitizer
8084
8185#endif // SANITIZER_ALLOCATOR_H
lib/tsan/sanitizer_common/sanitizer_allocator_bytemap.h deleted-107
......@@ -1,107 +0,0 @@
1//===-- sanitizer_allocator_bytemap.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// Part of the Sanitizer Allocator.
10//
11//===----------------------------------------------------------------------===//
12#ifndef SANITIZER_ALLOCATOR_H
13#error This file must be included inside sanitizer_allocator.h
14#endif
15
16// Maps integers in rage [0, kSize) to u8 values.
17template <u64 kSize, typename AddressSpaceViewTy = LocalAddressSpaceView>
18class FlatByteMap {
19 public:
20 using AddressSpaceView = AddressSpaceViewTy;
21 void Init() {
22 internal_memset(map_, 0, sizeof(map_));
23 }
24
25 void set(uptr idx, u8 val) {
26 CHECK_LT(idx, kSize);
27 CHECK_EQ(0U, map_[idx]);
28 map_[idx] = val;
29 }
30 u8 operator[] (uptr idx) {
31 CHECK_LT(idx, kSize);
32 // FIXME: CHECK may be too expensive here.
33 return map_[idx];
34 }
35 private:
36 u8 map_[kSize];
37};
38
39// TwoLevelByteMap maps integers in range [0, kSize1*kSize2) to u8 values.
40// It is implemented as a two-dimensional array: array of kSize1 pointers
41// to kSize2-byte arrays. The secondary arrays are mmaped on demand.
42// Each value is initially zero and can be set to something else only once.
43// Setting and getting values from multiple threads is safe w/o extra locking.
44template <u64 kSize1, u64 kSize2,
45 typename AddressSpaceViewTy = LocalAddressSpaceView,
46 class MapUnmapCallback = NoOpMapUnmapCallback>
47class TwoLevelByteMap {
48 public:
49 using AddressSpaceView = AddressSpaceViewTy;
50 void Init() {
51 internal_memset(map1_, 0, sizeof(map1_));
52 mu_.Init();
53 }
54
55 void TestOnlyUnmap() {
56 for (uptr i = 0; i < kSize1; i++) {
57 u8 *p = Get(i);
58 if (!p) continue;
59 MapUnmapCallback().OnUnmap(reinterpret_cast<uptr>(p), kSize2);
60 UnmapOrDie(p, kSize2);
61 }
62 }
63
64 uptr size() const { return kSize1 * kSize2; }
65 uptr size1() const { return kSize1; }
66 uptr size2() const { return kSize2; }
67
68 void set(uptr idx, u8 val) {
69 CHECK_LT(idx, kSize1 * kSize2);
70 u8 *map2 = GetOrCreate(idx / kSize2);
71 CHECK_EQ(0U, map2[idx % kSize2]);
72 map2[idx % kSize2] = val;
73 }
74
75 u8 operator[] (uptr idx) const {
76 CHECK_LT(idx, kSize1 * kSize2);
77 u8 *map2 = Get(idx / kSize2);
78 if (!map2) return 0;
79 auto value_ptr = AddressSpaceView::Load(&map2[idx % kSize2]);
80 return *value_ptr;
81 }
82
83 private:
84 u8 *Get(uptr idx) const {
85 CHECK_LT(idx, kSize1);
86 return reinterpret_cast<u8 *>(
87 atomic_load(&map1_[idx], memory_order_acquire));
88 }
89
90 u8 *GetOrCreate(uptr idx) {
91 u8 *res = Get(idx);
92 if (!res) {
93 SpinMutexLock l(&mu_);
94 if (!(res = Get(idx))) {
95 res = (u8*)MmapOrDie(kSize2, "TwoLevelByteMap");
96 MapUnmapCallback().OnMap(reinterpret_cast<uptr>(res), kSize2);
97 atomic_store(&map1_[idx], reinterpret_cast<uptr>(res),
98 memory_order_release);
99 }
100 }
101 return res;
102 }
103
104 atomic_uintptr_t map1_[kSize1];
105 StaticSpinMutex mu_;
106};
107
lib/tsan/sanitizer_common/sanitizer_allocator_combined.h+8-10
......@@ -29,9 +29,9 @@ class CombinedAllocator {
2929 LargeMmapAllocatorPtrArray,
3030 typename PrimaryAllocator::AddressSpaceView>;
3131
32 void InitLinkerInitialized(s32 release_to_os_interval_ms) {
33 stats_.InitLinkerInitialized();
34 primary_.Init(release_to_os_interval_ms);
32 void InitLinkerInitialized(s32 release_to_os_interval_ms,
33 uptr heap_start = 0) {
34 primary_.Init(release_to_os_interval_ms, heap_start);
3535 secondary_.InitLinkerInitialized();
3636 }
3737
......@@ -112,15 +112,13 @@ class CombinedAllocator {
112112 return new_p;
113113 }
114114
115 bool PointerIsMine(void *p) {
115 bool PointerIsMine(const void *p) const {
116116 if (primary_.PointerIsMine(p))
117117 return true;
118118 return secondary_.PointerIsMine(p);
119119 }
120120
121 bool FromPrimary(void *p) {
122 return primary_.PointerIsMine(p);
123 }
121 bool FromPrimary(const void *p) const { return primary_.PointerIsMine(p); }
124122
125123 void *GetMetaData(const void *p) {
126124 if (primary_.PointerIsMine(p))
......@@ -136,7 +134,7 @@ class CombinedAllocator {
136134
137135 // This function does the same as GetBlockBegin, but is much faster.
138136 // Must be called with the allocator locked.
139 void *GetBlockBeginFastLocked(void *p) {
137 void *GetBlockBeginFastLocked(const void *p) {
140138 if (primary_.PointerIsMine(p))
141139 return primary_.GetBlockBegin(p);
142140 return secondary_.GetBlockBeginFastLocked(p);
......@@ -177,12 +175,12 @@ class CombinedAllocator {
177175
178176 // ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone
179177 // introspection API.
180 void ForceLock() NO_THREAD_SAFETY_ANALYSIS {
178 void ForceLock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
181179 primary_.ForceLock();
182180 secondary_.ForceLock();
183181 }
184182
185 void ForceUnlock() NO_THREAD_SAFETY_ANALYSIS {
183 void ForceUnlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
186184 secondary_.ForceUnlock();
187185 primary_.ForceUnlock();
188186 }
lib/tsan/sanitizer_common/sanitizer_allocator_dlsym.h created+79
......@@ -0,0 +1,79 @@
1//===-- sanitizer_allocator_dlsym.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// Hack: Sanitizer initializer calls dlsym which may need to allocate and call
10// back into uninitialized sanitizer.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef SANITIZER_ALLOCATOR_DLSYM_H
15#define SANITIZER_ALLOCATOR_DLSYM_H
16
17#include "sanitizer_allocator_internal.h"
18
19namespace __sanitizer {
20
21template <typename Details>
22struct DlSymAllocator {
23 static bool Use() {
24 // Fuchsia doesn't use dlsym-based interceptors.
25 return !SANITIZER_FUCHSIA && UNLIKELY(Details::UseImpl());
26 }
27
28 static bool PointerIsMine(const void *ptr) {
29 // Fuchsia doesn't use dlsym-based interceptors.
30 return !SANITIZER_FUCHSIA &&
31 UNLIKELY(internal_allocator()->FromPrimary(ptr));
32 }
33
34 static void *Allocate(uptr size_in_bytes) {
35 void *ptr = InternalAlloc(size_in_bytes, nullptr, kWordSize);
36 CHECK(internal_allocator()->FromPrimary(ptr));
37 Details::OnAllocate(ptr,
38 internal_allocator()->GetActuallyAllocatedSize(ptr));
39 return ptr;
40 }
41
42 static void *Callocate(SIZE_T nmemb, SIZE_T size) {
43 void *ptr = InternalCalloc(nmemb, size);
44 CHECK(internal_allocator()->FromPrimary(ptr));
45 Details::OnAllocate(ptr,
46 internal_allocator()->GetActuallyAllocatedSize(ptr));
47 return ptr;
48 }
49
50 static void Free(void *ptr) {
51 uptr size = internal_allocator()->GetActuallyAllocatedSize(ptr);
52 Details::OnFree(ptr, size);
53 InternalFree(ptr);
54 }
55
56 static void *Realloc(void *ptr, uptr new_size) {
57 if (!ptr)
58 return Allocate(new_size);
59 CHECK(internal_allocator()->FromPrimary(ptr));
60 if (!new_size) {
61 Free(ptr);
62 return nullptr;
63 }
64 uptr size = internal_allocator()->GetActuallyAllocatedSize(ptr);
65 uptr memcpy_size = Min(new_size, size);
66 void *new_ptr = Allocate(new_size);
67 if (new_ptr)
68 internal_memcpy(new_ptr, ptr, memcpy_size);
69 Free(ptr);
70 return new_ptr;
71 }
72
73 static void OnAllocate(const void *ptr, uptr size) {}
74 static void OnFree(const void *ptr, uptr size) {}
75};
76
77} // namespace __sanitizer
78
79#endif // SANITIZER_ALLOCATOR_DLSYM_H
lib/tsan/sanitizer_common/sanitizer_allocator_interface.h+4
......@@ -21,8 +21,12 @@ extern "C" {
2121SANITIZER_INTERFACE_ATTRIBUTE
2222uptr __sanitizer_get_estimated_allocated_size(uptr size);
2323SANITIZER_INTERFACE_ATTRIBUTE int __sanitizer_get_ownership(const void *p);
24SANITIZER_INTERFACE_ATTRIBUTE const void *__sanitizer_get_allocated_begin(
25 const void *p);
2426SANITIZER_INTERFACE_ATTRIBUTE uptr
2527__sanitizer_get_allocated_size(const void *p);
28SANITIZER_INTERFACE_ATTRIBUTE uptr
29__sanitizer_get_allocated_size_fast(const void *p);
2630SANITIZER_INTERFACE_ATTRIBUTE uptr __sanitizer_get_current_allocated_bytes();
2731SANITIZER_INTERFACE_ATTRIBUTE uptr __sanitizer_get_heap_size();
2832SANITIZER_INTERFACE_ATTRIBUTE uptr __sanitizer_get_free_bytes();
lib/tsan/sanitizer_common/sanitizer_allocator_internal.h+2-1
......@@ -48,8 +48,9 @@ void *InternalReallocArray(void *p, uptr count, uptr size,
4848void *InternalCalloc(uptr count, uptr size,
4949 InternalAllocatorCache *cache = nullptr);
5050void InternalFree(void *p, InternalAllocatorCache *cache = nullptr);
51void InternalAllocatorLock();
52void InternalAllocatorUnlock();
5153InternalAllocator *internal_allocator();
52
5354} // namespace __sanitizer
5455
5556#endif // SANITIZER_ALLOCATOR_INTERNAL_H
lib/tsan/sanitizer_common/sanitizer_allocator_primary32.h+11-12
......@@ -189,7 +189,7 @@ class SizeClassAllocator32 {
189189 sci->free_list.push_front(b);
190190 }
191191
192 bool PointerIsMine(const void *p) {
192 bool PointerIsMine(const void *p) const {
193193 uptr mem = reinterpret_cast<uptr>(p);
194194 if (SANITIZER_SIGN_EXTENDED_ADDRESSES)
195195 mem &= (kSpaceSize - 1);
......@@ -198,8 +198,9 @@ class SizeClassAllocator32 {
198198 return GetSizeClass(p) != 0;
199199 }
200200
201 uptr GetSizeClass(const void *p) {
202 return possible_regions[ComputeRegionId(reinterpret_cast<uptr>(p))];
201 uptr GetSizeClass(const void *p) const {
202 uptr id = ComputeRegionId(reinterpret_cast<uptr>(p));
203 return possible_regions.contains(id) ? possible_regions[id] : 0;
203204 }
204205
205206 void *GetBlockBegin(const void *p) {
......@@ -237,13 +238,13 @@ class SizeClassAllocator32 {
237238
238239 // ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone
239240 // introspection API.
240 void ForceLock() NO_THREAD_SAFETY_ANALYSIS {
241 void ForceLock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
241242 for (uptr i = 0; i < kNumClasses; i++) {
242243 GetSizeClassInfo(i)->mutex.Lock();
243244 }
244245 }
245246
246 void ForceUnlock() NO_THREAD_SAFETY_ANALYSIS {
247 void ForceUnlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
247248 for (int i = kNumClasses - 1; i >= 0; i--) {
248249 GetSizeClassInfo(i)->mutex.Unlock();
249250 }
......@@ -251,9 +252,9 @@ class SizeClassAllocator32 {
251252
252253 // Iterate over all existing chunks.
253254 // The allocator must be locked when calling this function.
254 void ForEachChunk(ForEachChunkCallback callback, void *arg) {
255 void ForEachChunk(ForEachChunkCallback callback, void *arg) const {
255256 for (uptr region = 0; region < kNumPossibleRegions; region++)
256 if (possible_regions[region]) {
257 if (possible_regions.contains(region) && possible_regions[region]) {
257258 uptr chunk_size = ClassIdToSize(possible_regions[region]);
258259 uptr max_chunks_in_region = kRegionSize / (chunk_size + kMetadataSize);
259260 uptr region_beg = region * kRegionSize;
......@@ -292,9 +293,7 @@ class SizeClassAllocator32 {
292293 return res;
293294 }
294295
295 uptr ComputeRegionBeg(uptr mem) {
296 return mem & ~(kRegionSize - 1);
297 }
296 uptr ComputeRegionBeg(uptr mem) const { return mem & ~(kRegionSize - 1); }
298297
299298 uptr AllocateRegion(AllocatorStats *stat, uptr class_id) {
300299 DCHECK_LT(class_id, kNumClasses);
......@@ -305,7 +304,7 @@ class SizeClassAllocator32 {
305304 MapUnmapCallback().OnMap(res, kRegionSize);
306305 stat->Add(AllocatorStatMapped, kRegionSize);
307306 CHECK(IsAligned(res, kRegionSize));
308 possible_regions.set(ComputeRegionId(res), static_cast<u8>(class_id));
307 possible_regions[ComputeRegionId(res)] = class_id;
309308 return res;
310309 }
311310
......@@ -354,7 +353,7 @@ class SizeClassAllocator32 {
354353 DCHECK_GT(max_count, 0);
355354 TransferBatch *b = nullptr;
356355 constexpr uptr kShuffleArraySize = 48;
357 uptr shuffle_array[kShuffleArraySize];
356 UNINITIALIZED uptr shuffle_array[kShuffleArraySize];
358357 uptr count = 0;
359358 for (uptr i = region; i < region + n_chunks * size; i += size) {
360359 shuffle_array[count++] = i;
lib/tsan/sanitizer_common/sanitizer_allocator_primary64.h+15-14
......@@ -161,7 +161,7 @@ class SizeClassAllocator64 {
161161 void ForceReleaseToOS() {
162162 MemoryMapperT memory_mapper(*this);
163163 for (uptr class_id = 1; class_id < kNumClasses; class_id++) {
164 BlockingMutexLock l(&GetRegionInfo(class_id)->mutex);
164 Lock l(&GetRegionInfo(class_id)->mutex);
165165 MaybeReleaseToOS(&memory_mapper, class_id, true /*force*/);
166166 }
167167 }
......@@ -178,7 +178,7 @@ class SizeClassAllocator64 {
178178 uptr region_beg = GetRegionBeginBySizeClass(class_id);
179179 CompactPtrT *free_array = GetFreeArray(region_beg);
180180
181 BlockingMutexLock l(&region->mutex);
181 Lock l(&region->mutex);
182182 uptr old_num_chunks = region->num_freed_chunks;
183183 uptr new_num_freed_chunks = old_num_chunks + n_chunks;
184184 // Failure to allocate free array space while releasing memory is non
......@@ -204,7 +204,7 @@ class SizeClassAllocator64 {
204204 uptr region_beg = GetRegionBeginBySizeClass(class_id);
205205 CompactPtrT *free_array = GetFreeArray(region_beg);
206206
207 BlockingMutexLock l(&region->mutex);
207 Lock l(&region->mutex);
208208#if SANITIZER_WINDOWS
209209 /* On Windows unmapping of memory during __sanitizer_purge_allocator is
210210 explicit and immediate, so unmapped regions must be explicitly mapped back
......@@ -282,6 +282,8 @@ class SizeClassAllocator64 {
282282 CHECK(kMetadataSize);
283283 uptr class_id = GetSizeClass(p);
284284 uptr size = ClassIdToSize(class_id);
285 if (!size)
286 return nullptr;
285287 uptr chunk_idx = GetChunkIdx(reinterpret_cast<uptr>(p), size);
286288 uptr region_beg = GetRegionBeginBySizeClass(class_id);
287289 return reinterpret_cast<void *>(GetMetadataEnd(region_beg) -
......@@ -300,9 +302,8 @@ class SizeClassAllocator64 {
300302 UnmapWithCallbackOrDie((uptr)address_range.base(), address_range.size());
301303 }
302304
303 static void FillMemoryProfile(uptr start, uptr rss, bool file, uptr *stats,
304 uptr stats_size) {
305 for (uptr class_id = 0; class_id < stats_size; class_id++)
305 static void FillMemoryProfile(uptr start, uptr rss, bool file, uptr *stats) {
306 for (uptr class_id = 0; class_id < kNumClasses; class_id++)
306307 if (stats[class_id] == start)
307308 stats[class_id] = rss;
308309 }
......@@ -315,7 +316,7 @@ class SizeClassAllocator64 {
315316 Printf(
316317 "%s %02zd (%6zd): mapped: %6zdK allocs: %7zd frees: %7zd inuse: %6zd "
317318 "num_freed_chunks %7zd avail: %6zd rss: %6zdK releases: %6zd "
318 "last released: %6zdK region: 0x%zx\n",
319 "last released: %6lldK region: 0x%zx\n",
319320 region->exhausted ? "F" : " ", class_id, ClassIdToSize(class_id),
320321 region->mapped_user >> 10, region->stats.n_allocated,
321322 region->stats.n_freed, in_use, region->num_freed_chunks, avail_chunks,
......@@ -328,7 +329,7 @@ class SizeClassAllocator64 {
328329 uptr rss_stats[kNumClasses];
329330 for (uptr class_id = 0; class_id < kNumClasses; class_id++)
330331 rss_stats[class_id] = SpaceBeg() + kRegionSize * class_id;
331 GetMemoryProfile(FillMemoryProfile, rss_stats, kNumClasses);
332 GetMemoryProfile(FillMemoryProfile, rss_stats);
332333
333334 uptr total_mapped = 0;
334335 uptr total_rss = 0;
......@@ -353,13 +354,13 @@ class SizeClassAllocator64 {
353354
354355 // ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone
355356 // introspection API.
356 void ForceLock() NO_THREAD_SAFETY_ANALYSIS {
357 void ForceLock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
357358 for (uptr i = 0; i < kNumClasses; i++) {
358359 GetRegionInfo(i)->mutex.Lock();
359360 }
360361 }
361362
362 void ForceUnlock() NO_THREAD_SAFETY_ANALYSIS {
363 void ForceUnlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
363364 for (int i = (int)kNumClasses - 1; i >= 0; i--) {
364365 GetRegionInfo(i)->mutex.Unlock();
365366 }
......@@ -623,7 +624,7 @@ class SizeClassAllocator64 {
623624
624625 static const uptr kRegionSize = kSpaceSize / kNumClassesRounded;
625626 // FreeArray is the array of free-d chunks (stored as 4-byte offsets).
626 // In the worst case it may reguire kRegionSize/SizeClassMap::kMinSize
627 // In the worst case it may require kRegionSize/SizeClassMap::kMinSize
627628 // elements, but in reality this will not happen. For simplicity we
628629 // dedicate 1/8 of the region's virtual space to FreeArray.
629630 static const uptr kFreeArraySize = kRegionSize / 8;
......@@ -634,8 +635,8 @@ class SizeClassAllocator64 {
634635 return kUsingConstantSpaceBeg ? kSpaceBeg : NonConstSpaceBeg;
635636 }
636637 uptr SpaceEnd() const { return SpaceBeg() + kSpaceSize; }
637 // kRegionSize must be >= 2^32.
638 COMPILER_CHECK((kRegionSize) >= (1ULL << (SANITIZER_WORDSIZE / 2)));
638 // kRegionSize should be able to satisfy the largest size class.
639 static_assert(kRegionSize >= SizeClassMap::kMaxSize);
639640 // kRegionSize must be <= 2^36, see CompactPtrT.
640641 COMPILER_CHECK((kRegionSize) <= (1ULL << (SANITIZER_WORDSIZE / 2 + 4)));
641642 // Call mmap for user memory with at least this size.
......@@ -665,7 +666,7 @@ class SizeClassAllocator64 {
665666 };
666667
667668 struct ALIGNED(SANITIZER_CACHE_LINE_SIZE) RegionInfo {
668 BlockingMutex mutex;
669 Mutex mutex;
669670 uptr num_freed_chunks; // Number of elements in the freearray.
670671 uptr mapped_free_array; // Bytes mapped for freearray.
671672 uptr allocated_user; // Bytes allocated for user memory.
lib/tsan/sanitizer_common/sanitizer_allocator_report.cpp+1-2
......@@ -128,8 +128,7 @@ void NORETURN ReportAllocationSizeTooBig(uptr user_size, uptr max_size,
128128void NORETURN ReportOutOfMemory(uptr requested_size, const StackTrace *stack) {
129129 {
130130 ScopedAllocatorErrorReport report("out-of-memory", stack);
131 Report("ERROR: %s: allocator is out of memory trying to allocate 0x%zx "
132 "bytes\n", SanitizerToolName, requested_size);
131 ERROR_OOM("allocator is trying to allocate 0x%zx bytes\n", requested_size);
133132 }
134133 Die();
135134}
lib/tsan/sanitizer_common/sanitizer_allocator_secondary.h+9-9
......@@ -82,7 +82,7 @@ class LargeMmapAllocator {
8282 InitLinkerInitialized();
8383 }
8484
85 void *Allocate(AllocatorStats *stat, uptr size, uptr alignment) {
85 void *Allocate(AllocatorStats *stat, const uptr size, uptr alignment) {
8686 CHECK(IsPowerOfTwo(alignment));
8787 uptr map_size = RoundUpMapSize(size);
8888 if (alignment > page_size_)
......@@ -99,11 +99,11 @@ class LargeMmapAllocator {
9999 if (!map_beg)
100100 return nullptr;
101101 CHECK(IsAligned(map_beg, page_size_));
102 MapUnmapCallback().OnMap(map_beg, map_size);
103102 uptr map_end = map_beg + map_size;
104103 uptr res = map_beg + page_size_;
105104 if (res & (alignment - 1)) // Align.
106105 res += alignment - (res & (alignment - 1));
106 MapUnmapCallback().OnMapSecondary(map_beg, map_size, res, size);
107107 CHECK(IsAligned(res, alignment));
108108 CHECK(IsAligned(res, page_size_));
109109 CHECK_GE(res + size, map_beg);
......@@ -161,7 +161,7 @@ class LargeMmapAllocator {
161161 return res;
162162 }
163163
164 bool PointerIsMine(const void *p) {
164 bool PointerIsMine(const void *p) const {
165165 return GetBlockBegin(p) != nullptr;
166166 }
167167
......@@ -179,7 +179,7 @@ class LargeMmapAllocator {
179179 return GetHeader(p) + 1;
180180 }
181181
182 void *GetBlockBegin(const void *ptr) {
182 void *GetBlockBegin(const void *ptr) const {
183183 uptr p = reinterpret_cast<uptr>(ptr);
184184 SpinMutexLock l(&mutex_);
185185 uptr nearest_chunk = 0;
......@@ -215,7 +215,7 @@ class LargeMmapAllocator {
215215
216216 // This function does the same as GetBlockBegin, but is much faster.
217217 // Must be called with the allocator locked.
218 void *GetBlockBeginFastLocked(void *ptr) {
218 void *GetBlockBeginFastLocked(const void *ptr) {
219219 mutex_.CheckLocked();
220220 uptr p = reinterpret_cast<uptr>(ptr);
221221 uptr n = n_chunks_;
......@@ -267,9 +267,9 @@ class LargeMmapAllocator {
267267
268268 // ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone
269269 // introspection API.
270 void ForceLock() ACQUIRE(mutex_) { mutex_.Lock(); }
270 void ForceLock() SANITIZER_ACQUIRE(mutex_) { mutex_.Lock(); }
271271
272 void ForceUnlock() RELEASE(mutex_) { mutex_.Unlock(); }
272 void ForceUnlock() SANITIZER_RELEASE(mutex_) { mutex_.Unlock(); }
273273
274274 // Iterate over all existing chunks.
275275 // The allocator must be locked when calling this function.
......@@ -301,7 +301,7 @@ class LargeMmapAllocator {
301301 return GetHeader(reinterpret_cast<uptr>(p));
302302 }
303303
304 void *GetUser(const Header *h) {
304 void *GetUser(const Header *h) const {
305305 CHECK(IsAligned((uptr)h, page_size_));
306306 return reinterpret_cast<void*>(reinterpret_cast<uptr>(h) + page_size_);
307307 }
......@@ -318,5 +318,5 @@ class LargeMmapAllocator {
318318 struct Stats {
319319 uptr n_allocs, n_frees, currently_allocated, max_allocated, by_size_log[64];
320320 } stats;
321 StaticSpinMutex mutex_;
321 mutable StaticSpinMutex mutex_;
322322};
lib/tsan/sanitizer_common/sanitizer_allocator_size_class_map.h+4-4
......@@ -193,13 +193,13 @@ class SizeClassMap {
193193 uptr cached = MaxCachedHint(s) * s;
194194 if (i == kBatchClassID)
195195 d = p = l = 0;
196 Printf("c%02zd => s: %zd diff: +%zd %02zd%% l %zd "
197 "cached: %zd %zd; id %zd\n",
198 i, Size(i), d, p, l, MaxCachedHint(s), cached, ClassID(s));
196 Printf(
197 "c%02zu => s: %zu diff: +%zu %02zu%% l %zu cached: %zu %zu; id %zu\n",
198 i, Size(i), d, p, l, MaxCachedHint(s), cached, ClassID(s));
199199 total_cached += cached;
200200 prev_s = s;
201201 }
202 Printf("Total cached: %zd\n", total_cached);
202 Printf("Total cached: %zu\n", total_cached);
203203 }
204204
205205 static void Validate() {
lib/tsan/sanitizer_common/sanitizer_allocator_stats.h+12-15
......@@ -25,19 +25,13 @@ typedef uptr AllocatorStatCounters[AllocatorStatCount];
2525// Per-thread stats, live in per-thread cache.
2626class AllocatorStats {
2727 public:
28 void Init() {
29 internal_memset(this, 0, sizeof(*this));
30 }
31 void InitLinkerInitialized() {}
32
28 void Init() { internal_memset(this, 0, sizeof(*this)); }
3329 void Add(AllocatorStat i, uptr v) {
34 v += atomic_load(&stats_[i], memory_order_relaxed);
35 atomic_store(&stats_[i], v, memory_order_relaxed);
30 atomic_fetch_add(&stats_[i], v, memory_order_relaxed);
3631 }
3732
3833 void Sub(AllocatorStat i, uptr v) {
39 v = atomic_load(&stats_[i], memory_order_relaxed) - v;
40 atomic_store(&stats_[i], v, memory_order_relaxed);
34 atomic_fetch_sub(&stats_[i], v, memory_order_relaxed);
4135 }
4236
4337 void Set(AllocatorStat i, uptr v) {
......@@ -58,17 +52,13 @@ class AllocatorStats {
5852// Global stats, used for aggregation and querying.
5953class AllocatorGlobalStats : public AllocatorStats {
6054 public:
61 void InitLinkerInitialized() {
62 next_ = this;
63 prev_ = this;
64 }
6555 void Init() {
6656 internal_memset(this, 0, sizeof(*this));
67 InitLinkerInitialized();
6857 }
6958
7059 void Register(AllocatorStats *s) {
7160 SpinMutexLock l(&mu_);
61 LazyInit();
7262 s->next_ = next_;
7363 s->prev_ = this;
7464 next_->prev_ = s;
......@@ -87,7 +77,7 @@ class AllocatorGlobalStats : public AllocatorStats {
8777 internal_memset(s, 0, AllocatorStatCount * sizeof(uptr));
8878 SpinMutexLock l(&mu_);
8979 const AllocatorStats *stats = this;
90 for (;;) {
80 for (; stats;) {
9181 for (int i = 0; i < AllocatorStatCount; i++)
9282 s[i] += stats->Get(AllocatorStat(i));
9383 stats = stats->next_;
......@@ -100,6 +90,13 @@ class AllocatorGlobalStats : public AllocatorStats {
10090 }
10191
10292 private:
93 void LazyInit() {
94 if (!next_) {
95 next_ = this;
96 prev_ = this;
97 }
98 }
99
103100 mutable StaticSpinMutex mu_;
104101};
105102
lib/tsan/sanitizer_common/sanitizer_array_ref.h created+123
......@@ -0,0 +1,123 @@
1//===-- sanitizer_array_ref.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#ifndef SANITIZER_ARRAY_REF_H
10#define SANITIZER_ARRAY_REF_H
11
12#include "sanitizer_internal_defs.h"
13
14namespace __sanitizer {
15
16/// ArrayRef - Represent a constant reference to an array (0 or more elements
17/// consecutively in memory), i.e. a start pointer and a length. It allows
18/// various APIs to take consecutive elements easily and conveniently.
19///
20/// This class does not own the underlying data, it is expected to be used in
21/// situations where the data resides in some other buffer, whose lifetime
22/// extends past that of the ArrayRef. For this reason, it is not in general
23/// safe to store an ArrayRef.
24///
25/// This is intended to be trivially copyable, so it should be passed by
26/// value.
27template <typename T>
28class ArrayRef {
29 public:
30 constexpr ArrayRef() {}
31 constexpr ArrayRef(const T *begin, const T *end) : begin_(begin), end_(end) {
32 DCHECK(empty() || begin);
33 }
34 constexpr ArrayRef(const T *data, uptr length)
35 : ArrayRef(data, data + length) {}
36 template <uptr N>
37 constexpr ArrayRef(const T (&src)[N]) : ArrayRef(src, src + N) {}
38 template <typename C>
39 constexpr ArrayRef(const C &src)
40 : ArrayRef(src.data(), src.data() + src.size()) {}
41 ArrayRef(const T &one_elt) : ArrayRef(&one_elt, &one_elt + 1) {}
42
43 const T *data() const { return empty() ? nullptr : begin_; }
44
45 const T *begin() const { return begin_; }
46 const T *end() const { return end_; }
47
48 bool empty() const { return begin_ == end_; }
49
50 uptr size() const { return end_ - begin_; }
51
52 /// equals - Check for element-wise equality.
53 bool equals(ArrayRef rhs) const {
54 if (size() != rhs.size())
55 return false;
56 auto r = rhs.begin();
57 for (auto &l : *this) {
58 if (!(l == *r))
59 return false;
60 ++r;
61 }
62 return true;
63 }
64
65 /// slice(n, m) - Chop off the first N elements of the array, and keep M
66 /// elements in the array.
67 ArrayRef<T> slice(uptr N, uptr M) const {
68 DCHECK_LE(N + M, size());
69 return ArrayRef<T>(data() + N, M);
70 }
71
72 /// slice(n) - Chop off the first N elements of the array.
73 ArrayRef<T> slice(uptr N) const { return slice(N, size() - N); }
74
75 /// Drop the first \p N elements of the array.
76 ArrayRef<T> drop_front(uptr N = 1) const {
77 DCHECK_GE(size(), N);
78 return slice(N, size() - N);
79 }
80
81 /// Drop the last \p N elements of the array.
82 ArrayRef<T> drop_back(uptr N = 1) const {
83 DCHECK_GE(size(), N);
84 return slice(0, size() - N);
85 }
86
87 /// Return a copy of *this with only the first \p N elements.
88 ArrayRef<T> take_front(uptr N = 1) const {
89 if (N >= size())
90 return *this;
91 return drop_back(size() - N);
92 }
93
94 /// Return a copy of *this with only the last \p N elements.
95 ArrayRef<T> take_back(uptr N = 1) const {
96 if (N >= size())
97 return *this;
98 return drop_front(size() - N);
99 }
100
101 const T &operator[](uptr index) const {
102 DCHECK_LT(index, size());
103 return begin_[index];
104 }
105
106 private:
107 const T *begin_ = nullptr;
108 const T *end_ = nullptr;
109};
110
111template <typename T>
112inline bool operator==(ArrayRef<T> lhs, ArrayRef<T> rhs) {
113 return lhs.equals(rhs);
114}
115
116template <typename T>
117inline bool operator!=(ArrayRef<T> lhs, ArrayRef<T> rhs) {
118 return !(lhs == rhs);
119}
120
121} // namespace __sanitizer
122
123#endif // SANITIZER_ARRAY_REF_H
lib/tsan/sanitizer_common/sanitizer_asm.h+54-3
......@@ -6,7 +6,7 @@
66//
77//===----------------------------------------------------------------------===//
88//
9// Various support for assemebler.
9// Various support for assembler.
1010//
1111//===----------------------------------------------------------------------===//
1212
......@@ -42,13 +42,57 @@
4242# define CFI_RESTORE(reg)
4343#endif
4444
45#if defined(__x86_64__) || defined(__i386__) || defined(__sparc__)
46# define ASM_TAIL_CALL jmp
47#elif defined(__arm__) || defined(__aarch64__) || defined(__mips__) || \
48 defined(__powerpc__) || defined(__loongarch_lp64)
49# define ASM_TAIL_CALL b
50#elif defined(__s390__)
51# define ASM_TAIL_CALL jg
52#elif defined(__riscv)
53# define ASM_TAIL_CALL tail
54#endif
55
56#if defined(__ELF__) && defined(__x86_64__) || defined(__i386__) || \
57 defined(__riscv)
58# define ASM_PREEMPTIBLE_SYM(sym) sym@plt
59#else
60# define ASM_PREEMPTIBLE_SYM(sym) sym
61#endif
62
4563#if !defined(__APPLE__)
4664# define ASM_HIDDEN(symbol) .hidden symbol
4765# define ASM_TYPE_FUNCTION(symbol) .type symbol, %function
4866# define ASM_SIZE(symbol) .size symbol, .-symbol
4967# define ASM_SYMBOL(symbol) symbol
5068# define ASM_SYMBOL_INTERCEPTOR(symbol) symbol
51# define ASM_WRAPPER_NAME(symbol) __interceptor_##symbol
69# if defined(__i386__) || defined(__powerpc__) || defined(__s390__) || \
70 defined(__sparc__)
71// For details, see interception.h
72# define ASM_WRAPPER_NAME(symbol) __interceptor_##symbol
73# define ASM_TRAMPOLINE_ALIAS(symbol, name) \
74 .weak symbol; \
75 .set symbol, ASM_WRAPPER_NAME(name)
76# define ASM_INTERCEPTOR_TRAMPOLINE(name)
77# define ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT 0
78# else // Architecture supports interceptor trampoline
79// Keep trampoline implementation in sync with interception/interception.h
80# define ASM_WRAPPER_NAME(symbol) ___interceptor_##symbol
81# define ASM_TRAMPOLINE_ALIAS(symbol, name) \
82 .weak symbol; \
83 .set symbol, __interceptor_trampoline_##name
84# define ASM_INTERCEPTOR_TRAMPOLINE(name) \
85 .weak __interceptor_##name; \
86 .set __interceptor_##name, ASM_WRAPPER_NAME(name); \
87 .globl __interceptor_trampoline_##name; \
88 ASM_TYPE_FUNCTION(__interceptor_trampoline_##name); \
89 __interceptor_trampoline_##name: \
90 CFI_STARTPROC; \
91 ASM_TAIL_CALL ASM_PREEMPTIBLE_SYM(__interceptor_##name); \
92 CFI_ENDPROC; \
93 ASM_SIZE(__interceptor_trampoline_##name)
94# define ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT 1
95# endif // Architecture supports interceptor trampoline
5296#else
5397# define ASM_HIDDEN(symbol)
5498# define ASM_TYPE_FUNCTION(symbol)
......@@ -61,8 +105,15 @@
61105#if defined(__ELF__) && (defined(__GNU__) || defined(__FreeBSD__) || \
62106 defined(__Fuchsia__) || defined(__linux__))
63107// clang-format off
64#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits // NOLINT
108#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits
65109// clang-format on
66110#else
67111#define NO_EXEC_STACK_DIRECTIVE
68112#endif
113
114#if (defined(__x86_64__) || defined(__i386__)) && defined(__has_include) && __has_include(<cet.h>)
115#include <cet.h>
116#endif
117#ifndef _CET_ENDBR
118#define _CET_ENDBR
119#endif
lib/tsan/sanitizer_common/sanitizer_atomic_clang.h+8-9
......@@ -74,13 +74,12 @@ template <typename T>
7474inline bool atomic_compare_exchange_strong(volatile T *a, typename T::Type *cmp,
7575 typename T::Type xchg,
7676 memory_order mo) {
77 typedef typename T::Type Type;
78 Type cmpv = *cmp;
79 Type prev;
80 prev = __sync_val_compare_and_swap(&a->val_dont_use, cmpv, xchg);
81 if (prev == cmpv) return true;
82 *cmp = prev;
83 return false;
77 // Transitioned from __sync_val_compare_and_swap to support targets like
78 // SPARC V8 that cannot inline atomic cmpxchg. __atomic_compare_exchange
79 // can then be resolved from libatomic. __ATOMIC_SEQ_CST is used to best
80 // match the __sync builtin memory order.
81 return __atomic_compare_exchange(&a->val_dont_use, cmp, &xchg, false,
82 __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
8483}
8584
8685template<typename T>
......@@ -96,8 +95,8 @@ inline bool atomic_compare_exchange_weak(volatile T *a,
9695// This include provides explicit template instantiations for atomic_uint64_t
9796// on MIPS32, which does not directly support 8 byte atomics. It has to
9897// proceed the template definitions above.
99#if defined(_MIPS_SIM) && defined(_ABIO32)
100 #include "sanitizer_atomic_clang_mips.h"
98#if defined(_MIPS_SIM) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
99# include "sanitizer_atomic_clang_mips.h"
101100#endif
102101
103102#undef ATOMIC_ORDER
lib/tsan/sanitizer_common/sanitizer_atomic_clang_mips.h+1-1
......@@ -18,7 +18,7 @@ namespace __sanitizer {
1818
1919// MIPS32 does not support atomics > 4 bytes. To address this lack of
2020// functionality, the sanitizer library provides helper methods which use an
21// internal spin lock mechanism to emulate atomic oprations when the size is
21// internal spin lock mechanism to emulate atomic operations when the size is
2222// 8 bytes.
2323static void __spin_lock(volatile int *lock) {
2424 while (__sync_lock_test_and_set(lock, 1))
lib/tsan/sanitizer_common/sanitizer_chained_origin_depot.cpp created+148
......@@ -0,0 +1,148 @@
1//===-- sanitizer_chained_origin_depot.cpp --------------------------------===//
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// A storage for chained origins.
10//===----------------------------------------------------------------------===//
11
12#include "sanitizer_chained_origin_depot.h"
13
14#include "sanitizer_stackdepotbase.h"
15
16namespace __sanitizer {
17
18namespace {
19struct ChainedOriginDepotDesc {
20 u32 here_id;
21 u32 prev_id;
22};
23
24struct ChainedOriginDepotNode {
25 using hash_type = u32;
26 u32 link;
27 u32 here_id;
28 u32 prev_id;
29
30 typedef ChainedOriginDepotDesc args_type;
31
32 bool eq(hash_type hash, const args_type &args) const;
33
34 static uptr allocated() { return 0; }
35
36 static hash_type hash(const args_type &args);
37
38 static bool is_valid(const args_type &args);
39
40 void store(u32 id, const args_type &args, hash_type other_hash);
41
42 args_type load(u32 id) const;
43
44 struct Handle {
45 const ChainedOriginDepotNode *node_ = nullptr;
46 u32 id_ = 0;
47 Handle(const ChainedOriginDepotNode *node, u32 id) : node_(node), id_(id) {}
48 bool valid() const { return node_; }
49 u32 id() const { return id_; }
50 int here_id() const { return node_->here_id; }
51 int prev_id() const { return node_->prev_id; }
52 };
53
54 static Handle get_handle(u32 id);
55
56 typedef Handle handle_type;
57};
58
59} // namespace
60
61static StackDepotBase<ChainedOriginDepotNode, 4, 20> depot;
62
63bool ChainedOriginDepotNode::eq(hash_type hash, const args_type &args) const {
64 return here_id == args.here_id && prev_id == args.prev_id;
65}
66
67/* This is murmur2 hash for the 64->32 bit case.
68 It does not behave all that well because the keys have a very biased
69 distribution (I've seen 7-element buckets with the table only 14% full).
70
71 here_id is built of
72 * (1 bits) Reserved, zero.
73 * (8 bits) Part id = bits 13..20 of the hash value of here_id's key.
74 * (23 bits) Sequential number (each part has each own sequence).
75
76 prev_id has either the same distribution as here_id (but with 3:8:21)
77 split, or one of two reserved values (-1) or (-2). Either case can
78 dominate depending on the workload.
79*/
80ChainedOriginDepotNode::hash_type ChainedOriginDepotNode::hash(
81 const args_type &args) {
82 const u32 m = 0x5bd1e995;
83 const u32 seed = 0x9747b28c;
84 const u32 r = 24;
85 u32 h = seed;
86 u32 k = args.here_id;
87 k *= m;
88 k ^= k >> r;
89 k *= m;
90 h *= m;
91 h ^= k;
92
93 k = args.prev_id;
94 k *= m;
95 k ^= k >> r;
96 k *= m;
97 h *= m;
98 h ^= k;
99
100 h ^= h >> 13;
101 h *= m;
102 h ^= h >> 15;
103 return h;
104}
105
106bool ChainedOriginDepotNode::is_valid(const args_type &args) { return true; }
107
108void ChainedOriginDepotNode::store(u32 id, const args_type &args,
109 hash_type other_hash) {
110 here_id = args.here_id;
111 prev_id = args.prev_id;
112}
113
114ChainedOriginDepotNode::args_type ChainedOriginDepotNode::load(u32 id) const {
115 args_type ret = {here_id, prev_id};
116 return ret;
117}
118
119ChainedOriginDepotNode::Handle ChainedOriginDepotNode::get_handle(u32 id) {
120 return Handle(&depot.nodes[id], id);
121}
122
123ChainedOriginDepot::ChainedOriginDepot() {}
124
125StackDepotStats ChainedOriginDepot::GetStats() const {
126 return depot.GetStats();
127}
128
129bool ChainedOriginDepot::Put(u32 here_id, u32 prev_id, u32 *new_id) {
130 ChainedOriginDepotDesc desc = {here_id, prev_id};
131 bool inserted;
132 *new_id = depot.Put(desc, &inserted);
133 return inserted;
134}
135
136u32 ChainedOriginDepot::Get(u32 id, u32 *other) {
137 ChainedOriginDepotDesc desc = depot.Get(id);
138 *other = desc.prev_id;
139 return desc.here_id;
140}
141
142void ChainedOriginDepot::LockAll() { depot.LockAll(); }
143
144void ChainedOriginDepot::UnlockAll() { depot.UnlockAll(); }
145
146void ChainedOriginDepot::TestOnlyUnmap() { depot.TestOnlyUnmap(); }
147
148} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_chained_origin_depot.h created+46
......@@ -0,0 +1,46 @@
1//===-- sanitizer_chained_origin_depot.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// A storage for chained origins.
10//===----------------------------------------------------------------------===//
11
12#ifndef SANITIZER_CHAINED_ORIGIN_DEPOT_H
13#define SANITIZER_CHAINED_ORIGIN_DEPOT_H
14
15#include "sanitizer_common.h"
16
17namespace __sanitizer {
18
19class ChainedOriginDepot {
20 public:
21 ChainedOriginDepot();
22
23 // Gets the statistic of the origin chain storage.
24 StackDepotStats GetStats() const;
25
26 // Stores a chain with StackDepot ID here_id and previous chain ID prev_id.
27 // If successful, returns true and the new chain id new_id.
28 // If the same element already exists, returns false and sets new_id to the
29 // existing ID.
30 bool Put(u32 here_id, u32 prev_id, u32 *new_id);
31
32 // Retrieves the stored StackDepot ID for the given origin ID.
33 u32 Get(u32 id, u32 *other);
34
35 void LockAll();
36 void UnlockAll();
37 void TestOnlyUnmap();
38
39 private:
40 ChainedOriginDepot(const ChainedOriginDepot &) = delete;
41 void operator=(const ChainedOriginDepot &) = delete;
42};
43
44} // namespace __sanitizer
45
46#endif // SANITIZER_CHAINED_ORIGIN_DEPOT_H
lib/tsan/sanitizer_common/sanitizer_common.cpp+68-10
......@@ -11,10 +11,12 @@
1111//===----------------------------------------------------------------------===//
1212
1313#include "sanitizer_common.h"
14
1415#include "sanitizer_allocator_interface.h"
1516#include "sanitizer_allocator_internal.h"
1617#include "sanitizer_atomic.h"
1718#include "sanitizer_flags.h"
19#include "sanitizer_interface_internal.h"
1820#include "sanitizer_libc.h"
1921#include "sanitizer_placement_new.h"
2022
......@@ -44,15 +46,41 @@ void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type,
4446 Die();
4547 }
4648 recursion_count++;
47 Report("ERROR: %s failed to "
48 "%s 0x%zx (%zd) bytes of %s (error code: %d)\n",
49 SanitizerToolName, mmap_type, size, size, mem_type, err);
49 if (ErrorIsOOM(err)) {
50 ERROR_OOM("failed to %s 0x%zx (%zd) bytes of %s (error code: %d)\n",
51 mmap_type, size, size, mem_type, err);
52 } else {
53 Report(
54 "ERROR: %s failed to "
55 "%s 0x%zx (%zd) bytes of %s (error code: %d)\n",
56 SanitizerToolName, mmap_type, size, size, mem_type, err);
57 }
5058#if !SANITIZER_GO
5159 DumpProcessMap();
5260#endif
5361 UNREACHABLE("unable to mmap");
5462}
5563
64void NORETURN ReportMunmapFailureAndDie(void *addr, uptr size, error_t err,
65 bool raw_report) {
66 static int recursion_count;
67 if (raw_report || recursion_count) {
68 // If raw report is requested or we went into recursion just die. The
69 // Report() and CHECK calls below may call munmap recursively and fail.
70 RawWrite("ERROR: Failed to munmap\n");
71 Die();
72 }
73 recursion_count++;
74 Report(
75 "ERROR: %s failed to deallocate 0x%zx (%zd) bytes at address %p (error "
76 "code: %d)\n",
77 SanitizerToolName, size, size, addr, err);
78#if !SANITIZER_GO
79 DumpProcessMap();
80#endif
81 UNREACHABLE("unable to unmmap");
82}
83
5684typedef bool UptrComparisonFunction(const uptr &a, const uptr &b);
5785typedef bool U32ComparisonFunction(const u32 &a, const u32 &b);
5886
......@@ -138,13 +166,21 @@ void LoadedModule::set(const char *module_name, uptr base_address,
138166 set(module_name, base_address);
139167 arch_ = arch;
140168 internal_memcpy(uuid_, uuid, sizeof(uuid_));
169 uuid_size_ = kModuleUUIDSize;
141170 instrumented_ = instrumented;
142171}
143172
173void LoadedModule::setUuid(const char *uuid, uptr size) {
174 if (size > kModuleUUIDSize)
175 size = kModuleUUIDSize;
176 internal_memcpy(uuid_, uuid, size);
177 uuid_size_ = size;
178}
179
144180void LoadedModule::clear() {
145181 InternalFree(full_name_);
146182 base_address_ = 0;
147 max_executable_address_ = 0;
183 max_address_ = 0;
148184 full_name_ = nullptr;
149185 arch_ = kModuleArchUnknown;
150186 internal_memset(uuid_, 0, kModuleUUIDSize);
......@@ -162,8 +198,7 @@ void LoadedModule::addAddressRange(uptr beg, uptr end, bool executable,
162198 AddressRange *r =
163199 new(mem) AddressRange(beg, end, executable, writable, name);
164200 ranges_.push_back(r);
165 if (executable && end > max_executable_address_)
166 max_executable_address_ = end;
201 max_address_ = Max(max_address_, end);
167202}
168203
169204bool LoadedModule::containsAddress(uptr address) const {
......@@ -301,18 +336,22 @@ struct MallocFreeHook {
301336
302337static MallocFreeHook MFHooks[kMaxMallocFreeHooks];
303338
304void RunMallocHooks(const void *ptr, uptr size) {
339void RunMallocHooks(void *ptr, uptr size) {
340 __sanitizer_malloc_hook(ptr, size);
305341 for (int i = 0; i < kMaxMallocFreeHooks; i++) {
306342 auto hook = MFHooks[i].malloc_hook;
307 if (!hook) return;
343 if (!hook)
344 break;
308345 hook(ptr, size);
309346 }
310347}
311348
312void RunFreeHooks(const void *ptr) {
349void RunFreeHooks(void *ptr) {
350 __sanitizer_free_hook(ptr);
313351 for (int i = 0; i < kMaxMallocFreeHooks; i++) {
314352 auto hook = MFHooks[i].free_hook;
315 if (!hook) return;
353 if (!hook)
354 break;
316355 hook(ptr);
317356 }
318357}
......@@ -338,6 +377,13 @@ void SleepForSeconds(unsigned seconds) {
338377}
339378void SleepForMillis(unsigned millis) { internal_usleep((u64)millis * 1000); }
340379
380void WaitForDebugger(unsigned seconds, const char *label) {
381 if (seconds) {
382 Report("Sleeping for %u second(s) %s\n", seconds, label);
383 SleepForSeconds(seconds);
384 }
385}
386
341387} // namespace __sanitizer
342388
343389using namespace __sanitizer;
......@@ -360,4 +406,16 @@ int __sanitizer_install_malloc_and_free_hooks(void (*malloc_hook)(const void *,
360406 void (*free_hook)(const void *)) {
361407 return InstallMallocFreeHooks(malloc_hook, free_hook);
362408}
409
410// Provide default (no-op) implementation of malloc hooks.
411SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_malloc_hook, void *ptr,
412 uptr size) {
413 (void)ptr;
414 (void)size;
415}
416
417SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_free_hook, void *ptr) {
418 (void)ptr;
419}
420
363421} // extern "C"
lib/tsan/sanitizer_common/sanitizer_common.h+82-68
......@@ -16,7 +16,6 @@
1616#define SANITIZER_COMMON_H
1717
1818#include "sanitizer_flags.h"
19#include "sanitizer_interface_internal.h"
2019#include "sanitizer_internal_defs.h"
2120#include "sanitizer_libc.h"
2221#include "sanitizer_list.h"
......@@ -118,9 +117,15 @@ void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
118117// unaccessible memory.
119118bool MprotectNoAccess(uptr addr, uptr size);
120119bool MprotectReadOnly(uptr addr, uptr size);
120bool MprotectReadWrite(uptr addr, uptr size);
121121
122122void MprotectMallocZones(void *addr, int prot);
123123
124#if SANITIZER_WINDOWS
125// Zero previously mmap'd memory. Currently used only on Windows.
126bool ZeroMmapFixedRegion(uptr fixed_addr, uptr size) WARN_UNUSED_RESULT;
127#endif
128
124129#if SANITIZER_LINUX
125130// Unmap memory. Currently only used on Linux.
126131void UnmapFromTo(uptr from, uptr to);
......@@ -171,8 +176,8 @@ void SetShadowRegionHugePageMode(uptr addr, uptr length);
171176bool DontDumpShadowMemory(uptr addr, uptr length);
172177// Check if the built VMA size matches the runtime one.
173178void CheckVMASize();
174void RunMallocHooks(const void *ptr, uptr size);
175void RunFreeHooks(const void *ptr);
179void RunMallocHooks(void *ptr, uptr size);
180void RunFreeHooks(void *ptr);
176181
177182class ReservedAddressRange {
178183 public:
......@@ -192,12 +197,13 @@ class ReservedAddressRange {
192197};
193198
194199typedef void (*fill_profile_f)(uptr start, uptr rss, bool file,
195 /*out*/uptr *stats, uptr stats_size);
200 /*out*/ uptr *stats);
196201
197202// Parse the contents of /proc/self/smaps and generate a memory profile.
198// |cb| is a tool-specific callback that fills the |stats| array containing
199// |stats_size| elements.
200void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size);
203// |cb| is a tool-specific callback that fills the |stats| array.
204void GetMemoryProfile(fill_profile_f cb, uptr *stats);
205void ParseUnixMemoryProfile(fill_profile_f cb, uptr *stats, char *smaps,
206 uptr smaps_len);
201207
202208// Simple low-level (mmap-based) allocator for internal use. Doesn't have
203209// constructor, so all instances of LowLevelAllocator should be
......@@ -206,6 +212,7 @@ class LowLevelAllocator {
206212 public:
207213 // Requires an external lock.
208214 void *Allocate(uptr size);
215
209216 private:
210217 char *allocated_end_;
211218 char *allocated_current_;
......@@ -222,8 +229,8 @@ void CatastrophicErrorWrite(const char *buffer, uptr length);
222229void RawWrite(const char *buffer);
223230bool ColorizeReports();
224231void RemoveANSIEscapeSequencesFromString(char *buffer);
225void Printf(const char *format, ...);
226void Report(const char *format, ...);
232void Printf(const char *format, ...) FORMAT(1, 2);
233void Report(const char *format, ...) FORMAT(1, 2);
227234void SetPrintfAndReportCallback(void (*callback)(const char *));
228235#define VReport(level, ...) \
229236 do { \
......@@ -237,12 +244,12 @@ void SetPrintfAndReportCallback(void (*callback)(const char *));
237244// Lock sanitizer error reporting and protects against nested errors.
238245class ScopedErrorReportLock {
239246 public:
240 ScopedErrorReportLock() ACQUIRE(mutex_) { Lock(); }
241 ~ScopedErrorReportLock() RELEASE(mutex_) { Unlock(); }
247 ScopedErrorReportLock() SANITIZER_ACQUIRE(mutex_) { Lock(); }
248 ~ScopedErrorReportLock() SANITIZER_RELEASE(mutex_) { Unlock(); }
242249
243 static void Lock() ACQUIRE(mutex_);
244 static void Unlock() RELEASE(mutex_);
245 static void CheckLocked() CHECK_LOCKED(mutex_);
250 static void Lock() SANITIZER_ACQUIRE(mutex_);
251 static void Unlock() SANITIZER_RELEASE(mutex_);
252 static void CheckLocked() SANITIZER_CHECK_LOCKED(mutex_);
246253
247254 private:
248255 static atomic_uintptr_t reporting_thread_;
......@@ -285,7 +292,7 @@ void SetStackSizeLimitInBytes(uptr limit);
285292bool AddressSpaceIsUnlimited();
286293void SetAddressSpaceUnlimited();
287294void AdjustStackSize(void *attr);
288void PlatformPrepareForSandboxing(__sanitizer_sandbox_arguments *args);
295void PlatformPrepareForSandboxing(void *args);
289296void SetSandboxingCallback(void (*f)());
290297
291298void InitializeCoverage(bool enabled, const char *coverage_dir);
......@@ -294,6 +301,7 @@ void InitTlsSize();
294301uptr GetTlsSize();
295302
296303// Other
304void WaitForDebugger(unsigned seconds, const char *label);
297305void SleepForSeconds(unsigned seconds);
298306void SleepForMillis(unsigned millis);
299307u64 NanoTime();
......@@ -309,6 +317,20 @@ CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2);
309317void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type,
310318 const char *mmap_type, error_t err,
311319 bool raw_report = false);
320void NORETURN ReportMunmapFailureAndDie(void *ptr, uptr size, error_t err,
321 bool raw_report = false);
322
323// Returns true if the platform-specific error reported is an OOM error.
324bool ErrorIsOOM(error_t err);
325
326// This reports an error in the form:
327//
328// `ERROR: {{SanitizerToolName}}: out of memory: {{err_msg}}`
329//
330// Downstream tools that read sanitizer output will know that errors starting
331// in this format are specifically OOM errors.
332#define ERROR_OOM(err_msg, ...) \
333 Report("ERROR: %s: out of memory: " err_msg, SanitizerToolName, __VA_ARGS__)
312334
313335// Specific tools may override behavior of "Die" function to do tool-specific
314336// job.
......@@ -325,12 +347,6 @@ void SetUserDieCallback(DieCallbackType callback);
325347
326348void SetCheckUnwindCallback(void (*callback)());
327349
328// Callback will be called if soft_rss_limit_mb is given and the limit is
329// exceeded (exceeded==true) or if rss went down below the limit
330// (exceeded==false).
331// The callback should be registered once at the tool init time.
332void SetSoftRssLimitExceededCallback(void (*Callback)(bool exceeded));
333
334350// Functions related to signal handling.
335351typedef void (*SignalHandlerType)(int, void *, void *);
336352HandleSignalMode GetHandleSignalMode(int signum);
......@@ -371,7 +387,7 @@ void ReportErrorSummary(const char *error_type, const AddressInfo &info,
371387void ReportErrorSummary(const char *error_type, const StackTrace *trace,
372388 const char *alt_tool_name = nullptr);
373389
374void ReportMmapWriteExec(int prot);
390void ReportMmapWriteExec(int prot, int mflags);
375391
376392// Math
377393#if SANITIZER_WINDOWS && !defined(__clang__) && !defined(__GNUC__)
......@@ -419,9 +435,7 @@ inline uptr LeastSignificantSetBitIndex(uptr x) {
419435 return up;
420436}
421437
422inline bool IsPowerOfTwo(uptr x) {
423 return (x & (x - 1)) == 0;
424}
438inline constexpr bool IsPowerOfTwo(uptr x) { return (x & (x - 1)) == 0; }
425439
426440inline uptr RoundUpToPowerOfTwo(uptr size) {
427441 CHECK(size);
......@@ -433,16 +447,16 @@ inline uptr RoundUpToPowerOfTwo(uptr size) {
433447 return 1ULL << (up + 1);
434448}
435449
436inline uptr RoundUpTo(uptr size, uptr boundary) {
450inline constexpr uptr RoundUpTo(uptr size, uptr boundary) {
437451 RAW_CHECK(IsPowerOfTwo(boundary));
438452 return (size + boundary - 1) & ~(boundary - 1);
439453}
440454
441inline uptr RoundDownTo(uptr x, uptr boundary) {
455inline constexpr uptr RoundDownTo(uptr x, uptr boundary) {
442456 return x & ~(boundary - 1);
443457}
444458
445inline bool IsAligned(uptr a, uptr alignment) {
459inline constexpr bool IsAligned(uptr a, uptr alignment) {
446460 return (a & (alignment - 1)) == 0;
447461}
448462
......@@ -461,6 +475,10 @@ template <class T>
461475constexpr T Max(T a, T b) {
462476 return a > b ? a : b;
463477}
478template <class T>
479constexpr T Abs(T a) {
480 return a < 0 ? -a : a;
481}
464482template<class T> void Swap(T& a, T& b) {
465483 T tmp = a;
466484 a = b;
......@@ -502,8 +520,8 @@ class InternalMmapVectorNoCtor {
502520 return data_[i];
503521 }
504522 void push_back(const T &element) {
505 CHECK_LE(size_, capacity());
506 if (size_ == capacity()) {
523 if (UNLIKELY(size_ >= capacity())) {
524 CHECK_EQ(size_, capacity());
507525 uptr new_capacity = RoundUpToPowerOfTwo(size_ + 1);
508526 Realloc(new_capacity);
509527 }
......@@ -563,7 +581,7 @@ class InternalMmapVectorNoCtor {
563581 }
564582
565583 private:
566 void Realloc(uptr new_capacity) {
584 NOINLINE void Realloc(uptr new_capacity) {
567585 CHECK_GT(new_capacity, 0);
568586 CHECK_LE(size_, new_capacity);
569587 uptr new_capacity_bytes =
......@@ -618,7 +636,7 @@ class InternalScopedString {
618636 buffer_.resize(1);
619637 buffer_[0] = '\0';
620638 }
621 void append(const char *format, ...);
639 void append(const char *format, ...) FORMAT(2, 3);
622640 const char *data() const { return buffer_.data(); }
623641 char *data() { return buffer_.data(); }
624642
......@@ -670,11 +688,9 @@ void Sort(T *v, uptr size, Compare comp = {}) {
670688
671689// Works like std::lower_bound: finds the first element that is not less
672690// than the val.
673template <class Container,
691template <class Container, class T,
674692 class Compare = CompareLess<typename Container::value_type>>
675uptr InternalLowerBound(const Container &v,
676 const typename Container::value_type &val,
677 Compare comp = {}) {
693uptr InternalLowerBound(const Container &v, const T &val, Compare comp = {}) {
678694 uptr first = 0;
679695 uptr last = v.size();
680696 while (last > first) {
......@@ -697,7 +713,9 @@ enum ModuleArch {
697713 kModuleArchARMV7S,
698714 kModuleArchARMV7K,
699715 kModuleArchARM64,
700 kModuleArchRISCV64
716 kModuleArchLoongArch64,
717 kModuleArchRISCV64,
718 kModuleArchHexagon
701719};
702720
703721// Sorts and removes duplicates from the container.
......@@ -721,12 +739,15 @@ void SortAndDedup(Container &v, Compare comp = {}) {
721739 v.resize(last + 1);
722740}
723741
742constexpr uptr kDefaultFileMaxSize = FIRST_32_SECOND_64(1 << 26, 1 << 28);
743
724744// Opens the file 'file_name" and reads up to 'max_len' bytes.
725745// The resulting buffer is mmaped and stored in '*buff'.
726746// Returns true if file was successfully opened and read.
727747bool ReadFileToVector(const char *file_name,
728748 InternalMmapVectorNoCtor<char> *buff,
729 uptr max_len = 1 << 26, error_t *errno_p = nullptr);
749 uptr max_len = kDefaultFileMaxSize,
750 error_t *errno_p = nullptr);
730751
731752// Opens the file 'file_name" and reads up to 'max_len' bytes.
732753// This function is less I/O efficient than ReadFileToVector as it may reread
......@@ -737,9 +758,12 @@ bool ReadFileToVector(const char *file_name,
737758// The total number of read bytes is stored in '*read_len'.
738759// Returns true if file was successfully opened and read.
739760bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
740 uptr *read_len, uptr max_len = 1 << 26,
761 uptr *read_len, uptr max_len = kDefaultFileMaxSize,
741762 error_t *errno_p = nullptr);
742763
764int GetModuleAndOffsetForPc(uptr pc, char *module_name, uptr module_name_len,
765 uptr *pc_offset);
766
743767// When adding a new architecture, don't forget to also update
744768// script/asan_symbolize.py and sanitizer_symbolizer_libcdep.cpp.
745769inline const char *ModuleArchToString(ModuleArch arch) {
......@@ -762,14 +786,22 @@ inline const char *ModuleArchToString(ModuleArch arch) {
762786 return "armv7k";
763787 case kModuleArchARM64:
764788 return "arm64";
789 case kModuleArchLoongArch64:
790 return "loongarch64";
765791 case kModuleArchRISCV64:
766792 return "riscv64";
793 case kModuleArchHexagon:
794 return "hexagon";
767795 }
768796 CHECK(0 && "Invalid module arch");
769797 return "";
770798}
771799
800#if SANITIZER_APPLE
772801const uptr kModuleUUIDSize = 16;
802#else
803const uptr kModuleUUIDSize = 32;
804#endif
773805const uptr kMaxSegName = 16;
774806
775807// Represents a binary loaded into virtual memory (e.g. this can be an
......@@ -779,8 +811,9 @@ class LoadedModule {
779811 LoadedModule()
780812 : full_name_(nullptr),
781813 base_address_(0),
782 max_executable_address_(0),
814 max_address_(0),
783815 arch_(kModuleArchUnknown),
816 uuid_size_(0),
784817 instrumented_(false) {
785818 internal_memset(uuid_, 0, kModuleUUIDSize);
786819 ranges_.clear();
......@@ -788,6 +821,7 @@ class LoadedModule {
788821 void set(const char *module_name, uptr base_address);
789822 void set(const char *module_name, uptr base_address, ModuleArch arch,
790823 u8 uuid[kModuleUUIDSize], bool instrumented);
824 void setUuid(const char *uuid, uptr size);
791825 void clear();
792826 void addAddressRange(uptr beg, uptr end, bool executable, bool writable,
793827 const char *name = nullptr);
......@@ -795,9 +829,10 @@ class LoadedModule {
795829
796830 const char *full_name() const { return full_name_; }
797831 uptr base_address() const { return base_address_; }
798 uptr max_executable_address() const { return max_executable_address_; }
832 uptr max_address() const { return max_address_; }
799833 ModuleArch arch() const { return arch_; }
800834 const u8 *uuid() const { return uuid_; }
835 uptr uuid_size() const { return uuid_size_; }
801836 bool instrumented() const { return instrumented_; }
802837
803838 struct AddressRange {
......@@ -824,8 +859,9 @@ class LoadedModule {
824859 private:
825860 char *full_name_; // Owned.
826861 uptr base_address_;
827 uptr max_executable_address_;
862 uptr max_address_;
828863 ModuleArch arch_;
864 uptr uuid_size_;
829865 u8 uuid_[kModuleUUIDSize];
830866 bool instrumented_;
831867 IntrusiveList<AddressRange> ranges_;
......@@ -883,13 +919,13 @@ void WriteToSyslog(const char *buffer);
883919#define SANITIZER_WIN_TRACE 0
884920#endif
885921
886#if SANITIZER_MAC || SANITIZER_WIN_TRACE
922#if SANITIZER_APPLE || SANITIZER_WIN_TRACE
887923void LogFullErrorReport(const char *buffer);
888924#else
889925inline void LogFullErrorReport(const char *buffer) {}
890926#endif
891927
892#if SANITIZER_LINUX || SANITIZER_MAC
928#if SANITIZER_LINUX || SANITIZER_APPLE
893929void WriteOneLineToSyslog(const char *s);
894930void LogMessageOnPrintf(const char *str);
895931#else
......@@ -951,7 +987,7 @@ struct SignalContext {
951987 uptr sp;
952988 uptr bp;
953989 bool is_memory_access;
954 enum WriteFlag { UNKNOWN, READ, WRITE } write_flag;
990 enum WriteFlag { Unknown, Read, Write } write_flag;
955991
956992 // In some cases the kernel cannot provide the true faulting address; `addr`
957993 // will be zero then. This field allows to distinguish between these cases
......@@ -996,7 +1032,6 @@ struct SignalContext {
9961032};
9971033
9981034void InitializePlatformEarly();
999void MaybeReexec();
10001035
10011036template <typename Fn>
10021037class RunOnDestruction {
......@@ -1049,31 +1084,10 @@ inline u32 GetNumberOfCPUsCached() {
10491084 return NumberOfCPUsCached;
10501085}
10511086
1052template <typename T>
1053class ArrayRef {
1054 public:
1055 ArrayRef() {}
1056 ArrayRef(T *begin, T *end) : begin_(begin), end_(end) {}
1057
1058 T *begin() { return begin_; }
1059 T *end() { return end_; }
1060
1061 private:
1062 T *begin_ = nullptr;
1063 T *end_ = nullptr;
1064};
1065
1066#define PRINTF_128(v) \
1067 (*((u8 *)&v + 0)), (*((u8 *)&v + 1)), (*((u8 *)&v + 2)), (*((u8 *)&v + 3)), \
1068 (*((u8 *)&v + 4)), (*((u8 *)&v + 5)), (*((u8 *)&v + 6)), \
1069 (*((u8 *)&v + 7)), (*((u8 *)&v + 8)), (*((u8 *)&v + 9)), \
1070 (*((u8 *)&v + 10)), (*((u8 *)&v + 11)), (*((u8 *)&v + 12)), \
1071 (*((u8 *)&v + 13)), (*((u8 *)&v + 14)), (*((u8 *)&v + 15))
1072
10731087} // namespace __sanitizer
10741088
10751089inline void *operator new(__sanitizer::operator_new_size_type size,
1076 __sanitizer::LowLevelAllocator &alloc) { // NOLINT
1090 __sanitizer::LowLevelAllocator &alloc) {
10771091 return alloc.Allocate(size);
10781092}
10791093
lib/tsan/sanitizer_common/sanitizer_common_interceptors.inc+878-736
......@@ -21,19 +21,13 @@
2121// COMMON_INTERCEPTOR_FD_RELEASE
2222// COMMON_INTERCEPTOR_FD_ACCESS
2323// COMMON_INTERCEPTOR_SET_THREAD_NAME
24// COMMON_INTERCEPTOR_ON_DLOPEN
24// COMMON_INTERCEPTOR_DLOPEN
2525// COMMON_INTERCEPTOR_ON_EXIT
26// COMMON_INTERCEPTOR_MUTEX_PRE_LOCK
27// COMMON_INTERCEPTOR_MUTEX_POST_LOCK
28// COMMON_INTERCEPTOR_MUTEX_UNLOCK
29// COMMON_INTERCEPTOR_MUTEX_REPAIR
3026// COMMON_INTERCEPTOR_SET_PTHREAD_NAME
3127// COMMON_INTERCEPTOR_HANDLE_RECVMSG
3228// COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED
33// COMMON_INTERCEPTOR_MEMSET_IMPL
34// COMMON_INTERCEPTOR_MEMMOVE_IMPL
35// COMMON_INTERCEPTOR_MEMCPY_IMPL
3629// COMMON_INTERCEPTOR_MMAP_IMPL
30// COMMON_INTERCEPTOR_MUNMAP_IMPL
3731// COMMON_INTERCEPTOR_COPY_STRING
3832// COMMON_INTERCEPTOR_STRNDUP_IMPL
3933// COMMON_INTERCEPTOR_STRERROR
......@@ -132,14 +126,75 @@ extern const short *_toupper_tab_;
132126extern const short *_tolower_tab_;
133127#endif
134128
135// Platform-specific options.
136#if SANITIZER_MAC
137#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0
138#elif SANITIZER_WINDOWS64
139#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0
140#else
141#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 1
142#endif // SANITIZER_MAC
129#if SANITIZER_MUSL && \
130 (defined(__i386__) || defined(__arm__) || SANITIZER_MIPS32 || SANITIZER_PPC32)
131// musl 1.2.0 on existing 32-bit architectures uses new symbol names for the
132// time-related functions that take 64-bit time_t values. See
133// https://musl.libc.org/time64.html
134#define adjtime __adjtime64
135#define adjtimex __adjtimex_time64
136#define aio_suspend __aio_suspend_time64
137#define clock_adjtime __clock_adjtime64
138#define clock_getres __clock_getres_time64
139#define clock_gettime __clock_gettime64
140#define clock_nanosleep __clock_nanosleep_time64
141#define clock_settime __clock_settime64
142#define cnd_timedwait __cnd_timedwait_time64
143#define ctime __ctime64
144#define ctime_r __ctime64_r
145#define difftime __difftime64
146#define dlsym __dlsym_time64
147#define fstatat __fstatat_time64
148#define fstat __fstat_time64
149#define ftime __ftime64
150#define futimens __futimens_time64
151#define futimesat __futimesat_time64
152#define futimes __futimes_time64
153#define getitimer __getitimer_time64
154#define getrusage __getrusage_time64
155#define gettimeofday __gettimeofday_time64
156#define gmtime __gmtime64
157#define gmtime_r __gmtime64_r
158#define localtime __localtime64
159#define localtime_r __localtime64_r
160#define lstat __lstat_time64
161#define lutimes __lutimes_time64
162#define mktime __mktime64
163#define mq_timedreceive __mq_timedreceive_time64
164#define mq_timedsend __mq_timedsend_time64
165#define mtx_timedlock __mtx_timedlock_time64
166#define nanosleep __nanosleep_time64
167#define ppoll __ppoll_time64
168#define pselect __pselect_time64
169#define pthread_cond_timedwait __pthread_cond_timedwait_time64
170#define pthread_mutex_timedlock __pthread_mutex_timedlock_time64
171#define pthread_rwlock_timedrdlock __pthread_rwlock_timedrdlock_time64
172#define pthread_rwlock_timedwrlock __pthread_rwlock_timedwrlock_time64
173#define pthread_timedjoin_np __pthread_timedjoin_np_time64
174#define recvmmsg __recvmmsg_time64
175#define sched_rr_get_interval __sched_rr_get_interval_time64
176#define select __select_time64
177#define semtimedop __semtimedop_time64
178#define sem_timedwait __sem_timedwait_time64
179#define setitimer __setitimer_time64
180#define settimeofday __settimeofday_time64
181#define sigtimedwait __sigtimedwait_time64
182#define stat __stat_time64
183#define stime __stime64
184#define thrd_sleep __thrd_sleep_time64
185#define timegm __timegm_time64
186#define timerfd_gettime __timerfd_gettime64
187#define timerfd_settime __timerfd_settime64
188#define timer_gettime __timer_gettime64
189#define timer_settime __timer_settime64
190#define timespec_get __timespec_get_time64
191#define time __time64
192#define utimensat __utimensat_time64
193#define utimes __utimes_time64
194#define utime __utime64
195#define wait3 __wait3_time64
196#define wait4 __wait4_time64
197#endif
143198
144199#ifndef COMMON_INTERCEPTOR_INITIALIZE_RANGE
145200#define COMMON_INTERCEPTOR_INITIALIZE_RANGE(p, size) {}
......@@ -153,26 +208,6 @@ extern const short *_tolower_tab_;
153208#define COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd) {}
154209#endif
155210
156#ifndef COMMON_INTERCEPTOR_MUTEX_PRE_LOCK
157#define COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m) {}
158#endif
159
160#ifndef COMMON_INTERCEPTOR_MUTEX_POST_LOCK
161#define COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m) {}
162#endif
163
164#ifndef COMMON_INTERCEPTOR_MUTEX_UNLOCK
165#define COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m) {}
166#endif
167
168#ifndef COMMON_INTERCEPTOR_MUTEX_REPAIR
169#define COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m) {}
170#endif
171
172#ifndef COMMON_INTERCEPTOR_MUTEX_INVALID
173#define COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m) {}
174#endif
175
176211#ifndef COMMON_INTERCEPTOR_HANDLE_RECVMSG
177212#define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) ((void)(msg))
178213#endif
......@@ -204,11 +239,11 @@ extern const short *_tolower_tab_;
204239
205240#define COMMON_INTERCEPTOR_READ_STRING(ctx, s, n) \
206241 COMMON_INTERCEPTOR_READ_RANGE((ctx), (s), \
207 common_flags()->strict_string_checks ? (REAL(strlen)(s)) + 1 : (n) )
242 common_flags()->strict_string_checks ? (internal_strlen(s)) + 1 : (n) )
208243
209#ifndef COMMON_INTERCEPTOR_ON_DLOPEN
210#define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \
211 CheckNoDeepBind(filename, flag);
244#ifndef COMMON_INTERCEPTOR_DLOPEN
245#define COMMON_INTERCEPTOR_DLOPEN(filename, flag) \
246 ({ CheckNoDeepBind(filename, flag); REAL(dlopen)(filename, flag); })
212247#endif
213248
214249#ifndef COMMON_INTERCEPTOR_GET_TLS_RANGE
......@@ -256,53 +291,17 @@ extern const short *_tolower_tab_;
256291 COMMON_INTERCEPT_FUNCTION(fn)
257292#endif
258293
259#ifndef COMMON_INTERCEPTOR_MEMSET_IMPL
260#define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size) \
261 { \
262 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) \
263 return internal_memset(dst, v, size); \
264 COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size); \
265 if (common_flags()->intercept_intrin) \
266 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \
267 return REAL(memset)(dst, v, size); \
268 }
269#endif
270
271#ifndef COMMON_INTERCEPTOR_MEMMOVE_IMPL
272#define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size) \
273 { \
274 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) \
275 return internal_memmove(dst, src, size); \
276 COMMON_INTERCEPTOR_ENTER(ctx, memmove, dst, src, size); \
277 if (common_flags()->intercept_intrin) { \
278 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \
279 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size); \
280 } \
281 return REAL(memmove)(dst, src, size); \
282 }
283#endif
284
285#ifndef COMMON_INTERCEPTOR_MEMCPY_IMPL
286#define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size) \
287 { \
288 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) { \
289 return internal_memmove(dst, src, size); \
290 } \
291 COMMON_INTERCEPTOR_ENTER(ctx, memcpy, dst, src, size); \
292 if (common_flags()->intercept_intrin) { \
293 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \
294 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size); \
295 } \
296 return REAL(memcpy)(dst, src, size); \
297 }
298#endif
299
300294#ifndef COMMON_INTERCEPTOR_MMAP_IMPL
301295#define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, sz, prot, flags, fd, \
302296 off) \
303297 { return REAL(mmap)(addr, sz, prot, flags, fd, off); }
304298#endif
305299
300#ifndef COMMON_INTERCEPTOR_MUNMAP_IMPL
301#define COMMON_INTERCEPTOR_MUNMAP_IMPL(ctx, addr, sz) \
302 { return REAL(munmap)(addr, sz); }
303#endif
304
306305#ifndef COMMON_INTERCEPTOR_COPY_STRING
307306#define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) {}
308307#endif
......@@ -315,9 +314,11 @@ extern const short *_tolower_tab_;
315314 if (common_flags()->intercept_strndup) { \
316315 COMMON_INTERCEPTOR_READ_STRING(ctx, s, Min(size, copy_length + 1)); \
317316 } \
318 COMMON_INTERCEPTOR_COPY_STRING(ctx, new_mem, s, copy_length); \
319 internal_memcpy(new_mem, s, copy_length); \
320 new_mem[copy_length] = '\0'; \
317 if (new_mem) { \
318 COMMON_INTERCEPTOR_COPY_STRING(ctx, new_mem, s, copy_length); \
319 internal_memcpy(new_mem, s, copy_length); \
320 new_mem[copy_length] = '\0'; \
321 } \
321322 return new_mem;
322323#endif
323324
......@@ -435,7 +436,7 @@ INTERCEPTOR(char*, textdomain, const char *domainname) {
435436 if (domainname) COMMON_INTERCEPTOR_READ_STRING(ctx, domainname, 0);
436437 char *domain = REAL(textdomain)(domainname);
437438 if (domain) {
438 COMMON_INTERCEPTOR_INITIALIZE_RANGE(domain, REAL(strlen)(domain) + 1);
439 COMMON_INTERCEPTOR_INITIALIZE_RANGE(domain, internal_strlen(domain) + 1);
439440 }
440441 return domain;
441442}
......@@ -575,8 +576,8 @@ INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, SIZE_T size) {
575576#if SANITIZER_INTERCEPT_STRSTR || SANITIZER_INTERCEPT_STRCASESTR
576577static inline void StrstrCheck(void *ctx, char *r, const char *s1,
577578 const char *s2) {
578 uptr len1 = REAL(strlen)(s1);
579 uptr len2 = REAL(strlen)(s2);
579 uptr len1 = internal_strlen(s1);
580 uptr len2 = internal_strlen(s2);
580581 COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r ? r - s1 + len2 : len1 + 1);
581582 COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, len2 + 1);
582583}
......@@ -640,10 +641,10 @@ INTERCEPTOR(char*, strtok, char *str, const char *delimiters) {
640641 // for subsequent calls). We do not need to check strtok's result.
641642 // As the delimiters can change, we check them every call.
642643 if (str != nullptr) {
643 COMMON_INTERCEPTOR_READ_RANGE(ctx, str, REAL(strlen)(str) + 1);
644 COMMON_INTERCEPTOR_READ_RANGE(ctx, str, internal_strlen(str) + 1);
644645 }
645646 COMMON_INTERCEPTOR_READ_RANGE(ctx, delimiters,
646 REAL(strlen)(delimiters) + 1);
647 internal_strlen(delimiters) + 1);
647648 return REAL(strtok)(str, delimiters);
648649 } else {
649650 // However, when strict_string_checks is disabled we cannot check the
......@@ -657,11 +658,11 @@ INTERCEPTOR(char*, strtok, char *str, const char *delimiters) {
657658 COMMON_INTERCEPTOR_READ_RANGE(ctx, delimiters, 1);
658659 char *result = REAL(strtok)(str, delimiters);
659660 if (result != nullptr) {
660 COMMON_INTERCEPTOR_READ_RANGE(ctx, result, REAL(strlen)(result) + 1);
661 COMMON_INTERCEPTOR_READ_RANGE(ctx, result, internal_strlen(result) + 1);
661662 } else if (str != nullptr) {
662663 // No delimiter were found, it's safe to assume that the entire str was
663664 // scanned.
664 COMMON_INTERCEPTOR_READ_RANGE(ctx, str, REAL(strlen)(str) + 1);
665 COMMON_INTERCEPTOR_READ_RANGE(ctx, str, internal_strlen(str) + 1);
665666 }
666667 return result;
667668 }
......@@ -706,7 +707,7 @@ INTERCEPTOR(char*, strchr, const char *s, int c) {
706707 if (common_flags()->intercept_strchr) {
707708 // Keep strlen as macro argument, as macro may ignore it.
708709 COMMON_INTERCEPTOR_READ_STRING(ctx, s,
709 (result ? result - s : REAL(strlen)(s)) + 1);
710 (result ? result - s : internal_strlen(s)) + 1);
710711 }
711712 return result;
712713}
......@@ -737,7 +738,7 @@ INTERCEPTOR(char*, strrchr, const char *s, int c) {
737738 return internal_strrchr(s, c);
738739 COMMON_INTERCEPTOR_ENTER(ctx, strrchr, s, c);
739740 if (common_flags()->intercept_strchr)
740 COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
741 COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s) + 1);
741742 return REAL(strrchr)(s, c);
742743}
743744#define INIT_STRRCHR COMMON_INTERCEPT_FUNCTION(strrchr)
......@@ -751,7 +752,7 @@ INTERCEPTOR(SIZE_T, strspn, const char *s1, const char *s2) {
751752 COMMON_INTERCEPTOR_ENTER(ctx, strspn, s1, s2);
752753 SIZE_T r = REAL(strspn)(s1, s2);
753754 if (common_flags()->intercept_strspn) {
754 COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, REAL(strlen)(s2) + 1);
755 COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, internal_strlen(s2) + 1);
755756 COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r + 1);
756757 }
757758 return r;
......@@ -762,7 +763,7 @@ INTERCEPTOR(SIZE_T, strcspn, const char *s1, const char *s2) {
762763 COMMON_INTERCEPTOR_ENTER(ctx, strcspn, s1, s2);
763764 SIZE_T r = REAL(strcspn)(s1, s2);
764765 if (common_flags()->intercept_strspn) {
765 COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, REAL(strlen)(s2) + 1);
766 COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, internal_strlen(s2) + 1);
766767 COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r + 1);
767768 }
768769 return r;
......@@ -781,9 +782,9 @@ INTERCEPTOR(char *, strpbrk, const char *s1, const char *s2) {
781782 COMMON_INTERCEPTOR_ENTER(ctx, strpbrk, s1, s2);
782783 char *r = REAL(strpbrk)(s1, s2);
783784 if (common_flags()->intercept_strpbrk) {
784 COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, REAL(strlen)(s2) + 1);
785 COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, internal_strlen(s2) + 1);
785786 COMMON_INTERCEPTOR_READ_STRING(ctx, s1,
786 r ? r - s1 + 1 : REAL(strlen)(s1) + 1);
787 r ? r - s1 + 1 : internal_strlen(s1) + 1);
787788 }
788789 return r;
789790}
......@@ -793,57 +794,6 @@ INTERCEPTOR(char *, strpbrk, const char *s1, const char *s2) {
793794#define INIT_STRPBRK
794795#endif
795796
796#if SANITIZER_INTERCEPT_MEMSET
797INTERCEPTOR(void *, memset, void *dst, int v, uptr size) {
798 void *ctx;
799 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size);
800}
801
802#define INIT_MEMSET COMMON_INTERCEPT_FUNCTION(memset)
803#else
804#define INIT_MEMSET
805#endif
806
807#if SANITIZER_INTERCEPT_MEMMOVE
808INTERCEPTOR(void *, memmove, void *dst, const void *src, uptr size) {
809 void *ctx;
810 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
811}
812
813#define INIT_MEMMOVE COMMON_INTERCEPT_FUNCTION(memmove)
814#else
815#define INIT_MEMMOVE
816#endif
817
818#if SANITIZER_INTERCEPT_MEMCPY
819INTERCEPTOR(void *, memcpy, void *dst, const void *src, uptr size) {
820 // On OS X, calling internal_memcpy here will cause memory corruptions,
821 // because memcpy and memmove are actually aliases of the same
822 // implementation. We need to use internal_memmove here.
823 // N.B.: If we switch this to internal_ we'll have to use internal_memmove
824 // due to memcpy being an alias of memmove on OS X.
825 void *ctx;
826#if PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE
827 COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size);
828#else
829 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
830#endif
831}
832
833#define INIT_MEMCPY \
834 do { \
835 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { \
836 COMMON_INTERCEPT_FUNCTION(memcpy); \
837 } else { \
838 ASSIGN_REAL(memcpy, memmove); \
839 } \
840 CHECK(REAL(memcpy)); \
841 } while (false)
842
843#else
844#define INIT_MEMCPY
845#endif
846
847797#if SANITIZER_INTERCEPT_MEMCMP
848798DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, uptr called_pc,
849799 const void *s1, const void *s2, uptr n,
......@@ -1251,7 +1201,7 @@ INTERCEPTOR(char *, fgets, char *s, SIZE_T size, void *file) {
12511201 // https://github.com/google/sanitizers/issues/321.
12521202 char *res = REAL(fgets)(s, size, file);
12531203 if (res)
1254 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1);
1204 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, internal_strlen(s) + 1);
12551205 return res;
12561206}
12571207#define INIT_FGETS COMMON_INTERCEPT_FUNCTION(fgets)
......@@ -1264,8 +1214,8 @@ INTERCEPTOR_WITH_SUFFIX(int, fputs, char *s, void *file) {
12641214 // libc file streams can call user-supplied functions, see fopencookie.
12651215 void *ctx;
12661216 COMMON_INTERCEPTOR_ENTER(ctx, fputs, s, file);
1267 if (!SANITIZER_MAC || s) { // `fputs(NULL, file)` is supported on Darwin.
1268 COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
1217 if (!SANITIZER_APPLE || s) { // `fputs(NULL, file)` is supported on Darwin.
1218 COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s) + 1);
12691219 }
12701220 return REAL(fputs)(s, file);
12711221}
......@@ -1279,8 +1229,8 @@ INTERCEPTOR(int, puts, char *s) {
12791229 // libc file streams can call user-supplied functions, see fopencookie.
12801230 void *ctx;
12811231 COMMON_INTERCEPTOR_ENTER(ctx, puts, s);
1282 if (!SANITIZER_MAC || s) { // `puts(NULL)` is supported on Darwin.
1283 COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
1232 if (!SANITIZER_APPLE || s) { // `puts(NULL)` is supported on Darwin.
1233 COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s) + 1);
12841234 }
12851235 return REAL(puts)(s);
12861236}
......@@ -1295,12 +1245,21 @@ INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,
12951245 void *ctx;
12961246 COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
12971247 static const int PR_SET_NAME = 15;
1298 int res = REAL(prctl(option, arg2, arg3, arg4, arg5));
1248 static const int PR_SET_VMA = 0x53564d41;
1249 static const int PR_SCHED_CORE = 62;
1250 static const int PR_SCHED_CORE_GET = 0;
1251 if (option == PR_SET_VMA && arg2 == 0UL) {
1252 char *name = (char *)arg5;
1253 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
1254 }
1255 int res = REAL(prctl)(option, arg2, arg3, arg4, arg5);
12991256 if (option == PR_SET_NAME) {
13001257 char buff[16];
13011258 internal_strncpy(buff, (char *)arg2, 15);
13021259 buff[15] = 0;
13031260 COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, buff);
1261 } else if (res != -1 && option == PR_SCHED_CORE && arg2 == PR_SCHED_CORE_GET) {
1262 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (u64*)(arg5), sizeof(u64));
13041263 }
13051264 return res;
13061265}
......@@ -1334,7 +1293,7 @@ static void unpoison_tm(void *ctx, __sanitizer_tm *tm) {
13341293 // Can not use COMMON_INTERCEPTOR_WRITE_RANGE here, because tm->tm_zone
13351294 // can point to shared memory and tsan would report a data race.
13361295 COMMON_INTERCEPTOR_INITIALIZE_RANGE(tm->tm_zone,
1337 REAL(strlen(tm->tm_zone)) + 1);
1296 internal_strlen(tm->tm_zone) + 1);
13381297 }
13391298#endif
13401299}
......@@ -1387,7 +1346,7 @@ INTERCEPTOR(char *, ctime, unsigned long *timep) {
13871346 char *res = REAL(ctime)(timep);
13881347 if (res) {
13891348 COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
1390 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1349 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
13911350 }
13921351 return res;
13931352}
......@@ -1400,7 +1359,7 @@ INTERCEPTOR(char *, ctime_r, unsigned long *timep, char *result) {
14001359 char *res = REAL(ctime_r)(timep, result);
14011360 if (res) {
14021361 COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
1403 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1362 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
14041363 }
14051364 return res;
14061365}
......@@ -1413,7 +1372,7 @@ INTERCEPTOR(char *, asctime, __sanitizer_tm *tm) {
14131372 char *res = REAL(asctime)(tm);
14141373 if (res) {
14151374 COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm));
1416 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1375 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
14171376 }
14181377 return res;
14191378}
......@@ -1426,7 +1385,7 @@ INTERCEPTOR(char *, asctime_r, __sanitizer_tm *tm, char *result) {
14261385 char *res = REAL(asctime_r)(tm, result);
14271386 if (res) {
14281387 COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm));
1429 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1388 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
14301389 }
14311390 return res;
14321391}
......@@ -1463,7 +1422,7 @@ INTERCEPTOR(char *, strptime, char *s, char *format, __sanitizer_tm *tm) {
14631422 void *ctx;
14641423 COMMON_INTERCEPTOR_ENTER(ctx, strptime, s, format, tm);
14651424 if (format)
1466 COMMON_INTERCEPTOR_READ_RANGE(ctx, format, REAL(strlen)(format) + 1);
1425 COMMON_INTERCEPTOR_READ_RANGE(ctx, format, internal_strlen(format) + 1);
14671426 // FIXME: under ASan the call below may write to freed memory and corrupt
14681427 // its metadata. See
14691428 // https://github.com/google/sanitizers/issues/321.
......@@ -1532,6 +1491,16 @@ VSCANF_INTERCEPTOR_IMPL(__isoc99_vsscanf, false, str, format, ap)
15321491
15331492INTERCEPTOR(int, __isoc99_vfscanf, void *stream, const char *format, va_list ap)
15341493VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap)
1494
1495INTERCEPTOR(int, __isoc23_vscanf, const char *format, va_list ap)
1496VSCANF_INTERCEPTOR_IMPL(__isoc23_vscanf, false, format, ap)
1497
1498INTERCEPTOR(int, __isoc23_vsscanf, const char *str, const char *format,
1499 va_list ap)
1500VSCANF_INTERCEPTOR_IMPL(__isoc23_vsscanf, false, str, format, ap)
1501
1502INTERCEPTOR(int, __isoc23_vfscanf, void *stream, const char *format, va_list ap)
1503VSCANF_INTERCEPTOR_IMPL(__isoc23_vfscanf, false, stream, format, ap)
15351504#endif // SANITIZER_INTERCEPT_ISOC99_SCANF
15361505
15371506INTERCEPTOR(int, scanf, const char *format, ...)
......@@ -1552,6 +1521,15 @@ FORMAT_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format)
15521521
15531522INTERCEPTOR(int, __isoc99_sscanf, const char *str, const char *format, ...)
15541523FORMAT_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
1524
1525INTERCEPTOR(int, __isoc23_scanf, const char *format, ...)
1526FORMAT_INTERCEPTOR_IMPL(__isoc23_scanf, __isoc23_vscanf, format)
1527
1528INTERCEPTOR(int, __isoc23_fscanf, void *stream, const char *format, ...)
1529FORMAT_INTERCEPTOR_IMPL(__isoc23_fscanf, __isoc23_vfscanf, stream, format)
1530
1531INTERCEPTOR(int, __isoc23_sscanf, const char *str, const char *format, ...)
1532FORMAT_INTERCEPTOR_IMPL(__isoc23_sscanf, __isoc23_vsscanf, str, format)
15551533#endif
15561534
15571535#endif
......@@ -1575,7 +1553,13 @@ FORMAT_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
15751553 COMMON_INTERCEPT_FUNCTION(__isoc99_fscanf); \
15761554 COMMON_INTERCEPT_FUNCTION(__isoc99_vscanf); \
15771555 COMMON_INTERCEPT_FUNCTION(__isoc99_vsscanf); \
1578 COMMON_INTERCEPT_FUNCTION(__isoc99_vfscanf);
1556 COMMON_INTERCEPT_FUNCTION(__isoc99_vfscanf); \
1557 COMMON_INTERCEPT_FUNCTION(__isoc23_scanf); \
1558 COMMON_INTERCEPT_FUNCTION(__isoc23_sscanf); \
1559 COMMON_INTERCEPT_FUNCTION(__isoc23_fscanf); \
1560 COMMON_INTERCEPT_FUNCTION(__isoc23_vscanf); \
1561 COMMON_INTERCEPT_FUNCTION(__isoc23_vsscanf); \
1562 COMMON_INTERCEPT_FUNCTION(__isoc23_vfscanf);
15791563#else
15801564#define INIT_ISOC99_SCANF
15811565#endif
......@@ -1843,9 +1827,9 @@ INTERCEPTOR(int, ioctl, int d, unsigned long request, ...) {
18431827 const ioctl_desc *desc = ioctl_lookup(request);
18441828 ioctl_desc decoded_desc;
18451829 if (!desc) {
1846 VPrintf(2, "Decoding unknown ioctl 0x%x\n", request);
1830 VPrintf(2, "Decoding unknown ioctl 0x%lx\n", request);
18471831 if (!ioctl_decode(request, &decoded_desc))
1848 Printf("WARNING: failed decoding unknown ioctl 0x%x\n", request);
1832 Printf("WARNING: failed decoding unknown ioctl 0x%lx\n", request);
18491833 else
18501834 desc = &decoded_desc;
18511835 }
......@@ -1869,26 +1853,26 @@ UNUSED static void unpoison_passwd(void *ctx, __sanitizer_passwd *pwd) {
18691853 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd, sizeof(*pwd));
18701854 if (pwd->pw_name)
18711855 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_name,
1872 REAL(strlen)(pwd->pw_name) + 1);
1856 internal_strlen(pwd->pw_name) + 1);
18731857 if (pwd->pw_passwd)
18741858 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_passwd,
1875 REAL(strlen)(pwd->pw_passwd) + 1);
1859 internal_strlen(pwd->pw_passwd) + 1);
18761860#if !SANITIZER_ANDROID
18771861 if (pwd->pw_gecos)
18781862 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_gecos,
1879 REAL(strlen)(pwd->pw_gecos) + 1);
1863 internal_strlen(pwd->pw_gecos) + 1);
18801864#endif
1881#if SANITIZER_MAC || SANITIZER_FREEBSD || SANITIZER_NETBSD
1865#if SANITIZER_APPLE || SANITIZER_FREEBSD || SANITIZER_NETBSD
18821866 if (pwd->pw_class)
18831867 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_class,
1884 REAL(strlen)(pwd->pw_class) + 1);
1868 internal_strlen(pwd->pw_class) + 1);
18851869#endif
18861870 if (pwd->pw_dir)
18871871 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_dir,
1888 REAL(strlen)(pwd->pw_dir) + 1);
1872 internal_strlen(pwd->pw_dir) + 1);
18891873 if (pwd->pw_shell)
18901874 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_shell,
1891 REAL(strlen)(pwd->pw_shell) + 1);
1875 internal_strlen(pwd->pw_shell) + 1);
18921876 }
18931877}
18941878
......@@ -1897,13 +1881,13 @@ UNUSED static void unpoison_group(void *ctx, __sanitizer_group *grp) {
18971881 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp, sizeof(*grp));
18981882 if (grp->gr_name)
18991883 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp->gr_name,
1900 REAL(strlen)(grp->gr_name) + 1);
1884 internal_strlen(grp->gr_name) + 1);
19011885 if (grp->gr_passwd)
19021886 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp->gr_passwd,
1903 REAL(strlen)(grp->gr_passwd) + 1);
1887 internal_strlen(grp->gr_passwd) + 1);
19041888 char **p = grp->gr_mem;
19051889 for (; *p; ++p) {
1906 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
1890 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, internal_strlen(*p) + 1);
19071891 }
19081892 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp->gr_mem,
19091893 (p - grp->gr_mem + 1) * sizeof(*p));
......@@ -1916,7 +1900,7 @@ INTERCEPTOR(__sanitizer_passwd *, getpwnam, const char *name) {
19161900 void *ctx;
19171901 COMMON_INTERCEPTOR_ENTER(ctx, getpwnam, name);
19181902 if (name)
1919 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
1903 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
19201904 __sanitizer_passwd *res = REAL(getpwnam)(name);
19211905 unpoison_passwd(ctx, res);
19221906 return res;
......@@ -1931,7 +1915,7 @@ INTERCEPTOR(__sanitizer_passwd *, getpwuid, u32 uid) {
19311915INTERCEPTOR(__sanitizer_group *, getgrnam, const char *name) {
19321916 void *ctx;
19331917 COMMON_INTERCEPTOR_ENTER(ctx, getgrnam, name);
1934 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
1918 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
19351919 __sanitizer_group *res = REAL(getgrnam)(name);
19361920 unpoison_group(ctx, res);
19371921 return res;
......@@ -1957,7 +1941,7 @@ INTERCEPTOR(int, getpwnam_r, const char *name, __sanitizer_passwd *pwd,
19571941 char *buf, SIZE_T buflen, __sanitizer_passwd **result) {
19581942 void *ctx;
19591943 COMMON_INTERCEPTOR_ENTER(ctx, getpwnam_r, name, pwd, buf, buflen, result);
1960 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
1944 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
19611945 // FIXME: under ASan the call below may write to freed memory and corrupt
19621946 // its metadata. See
19631947 // https://github.com/google/sanitizers/issues/321.
......@@ -1984,7 +1968,7 @@ INTERCEPTOR(int, getgrnam_r, const char *name, __sanitizer_group *grp,
19841968 char *buf, SIZE_T buflen, __sanitizer_group **result) {
19851969 void *ctx;
19861970 COMMON_INTERCEPTOR_ENTER(ctx, getgrnam_r, name, grp, buf, buflen, result);
1987 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
1971 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
19881972 // FIXME: under ASan the call below may write to freed memory and corrupt
19891973 // its metadata. See
19901974 // https://github.com/google/sanitizers/issues/321.
......@@ -2229,8 +2213,20 @@ INTERCEPTOR(int, clock_getcpuclockid, pid_t pid,
22292213 return res;
22302214}
22312215
2232#define INIT_CLOCK_GETCPUCLOCKID \
2233 COMMON_INTERCEPT_FUNCTION(clock_getcpuclockid);
2216INTERCEPTOR(int, pthread_getcpuclockid, uptr thread,
2217 __sanitizer_clockid_t *clockid) {
2218 void *ctx;
2219 COMMON_INTERCEPTOR_ENTER(ctx, pthread_getcpuclockid, thread, clockid);
2220 int res = REAL(pthread_getcpuclockid)(thread, clockid);
2221 if (!res && clockid) {
2222 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, clockid, sizeof *clockid);
2223 }
2224 return res;
2225}
2226
2227#define INIT_CLOCK_GETCPUCLOCKID \
2228 COMMON_INTERCEPT_FUNCTION(clock_getcpuclockid); \
2229 COMMON_INTERCEPT_FUNCTION(pthread_getcpuclockid);
22342230#else
22352231#define INIT_CLOCK_GETCPUCLOCKID
22362232#endif
......@@ -2289,7 +2285,7 @@ static void unpoison_glob_t(void *ctx, __sanitizer_glob_t *pglob) {
22892285 ctx, pglob->gl_pathv, (pglob->gl_pathc + 1) * sizeof(*pglob->gl_pathv));
22902286 for (SIZE_T i = 0; i < pglob->gl_pathc; ++i) {
22912287 char *p = pglob->gl_pathv[i];
2292 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, REAL(strlen)(p) + 1);
2288 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, internal_strlen(p) + 1);
22932289 }
22942290}
22952291
......@@ -2319,19 +2315,19 @@ static void *wrapped_gl_readdir(void *dir) {
23192315
23202316static void *wrapped_gl_opendir(const char *s) {
23212317 COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
2322 COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
2318 COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, internal_strlen(s) + 1);
23232319 return pglob_copy->gl_opendir(s);
23242320}
23252321
23262322static int wrapped_gl_lstat(const char *s, void *st) {
23272323 COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
2328 COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
2324 COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, internal_strlen(s) + 1);
23292325 return pglob_copy->gl_lstat(s, st);
23302326}
23312327
23322328static int wrapped_gl_stat(const char *s, void *st) {
23332329 COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
2334 COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
2330 COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, internal_strlen(s) + 1);
23352331 return pglob_copy->gl_stat(s, st);
23362332}
23372333
......@@ -2410,6 +2406,136 @@ INTERCEPTOR(int, glob64, const char *pattern, int flags,
24102406#define INIT_GLOB64
24112407#endif // SANITIZER_INTERCEPT_GLOB64
24122408
2409#if SANITIZER_INTERCEPT___B64_TO
2410INTERCEPTOR(int, __b64_ntop, unsigned char const *src, SIZE_T srclength,
2411 char *target, SIZE_T targsize) {
2412 void *ctx;
2413 COMMON_INTERCEPTOR_ENTER(ctx, __b64_ntop, src, srclength, target, targsize);
2414 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, srclength);
2415 int res = REAL(__b64_ntop)(src, srclength, target, targsize);
2416 if (res >= 0)
2417 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, target, res + 1);
2418 return res;
2419}
2420INTERCEPTOR(int, __b64_pton, char const *src, char *target, SIZE_T targsize) {
2421 void *ctx;
2422 COMMON_INTERCEPTOR_ENTER(ctx, __b64_pton, src, target, targsize);
2423 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
2424 int res = REAL(__b64_pton)(src, target, targsize);
2425 if (res >= 0)
2426 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, target, res);
2427 return res;
2428}
2429#define INIT___B64_TO \
2430 COMMON_INTERCEPT_FUNCTION(__b64_ntop); \
2431 COMMON_INTERCEPT_FUNCTION(__b64_pton);
2432#else // SANITIZER_INTERCEPT___B64_TO
2433#define INIT___B64_TO
2434#endif // SANITIZER_INTERCEPT___B64_TO
2435
2436#if SANITIZER_INTERCEPT_DN_COMP_EXPAND
2437# if __GLIBC_PREREQ(2, 34)
2438// Changed with https://sourceware.org/git/?p=glibc.git;h=640bbdf
2439# define DN_COMP_INTERCEPTOR_NAME dn_comp
2440# define DN_EXPAND_INTERCEPTOR_NAME dn_expand
2441# else
2442# define DN_COMP_INTERCEPTOR_NAME __dn_comp
2443# define DN_EXPAND_INTERCEPTOR_NAME __dn_expand
2444# endif
2445INTERCEPTOR(int, DN_COMP_INTERCEPTOR_NAME, unsigned char *exp_dn,
2446 unsigned char *comp_dn, int length, unsigned char **dnptrs,
2447 unsigned char **lastdnptr) {
2448 void *ctx;
2449 COMMON_INTERCEPTOR_ENTER(ctx, DN_COMP_INTERCEPTOR_NAME, exp_dn, comp_dn,
2450 length, dnptrs, lastdnptr);
2451 int res = REAL(DN_COMP_INTERCEPTOR_NAME)(exp_dn, comp_dn, length, dnptrs,
2452 lastdnptr);
2453 if (res >= 0) {
2454 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, comp_dn, res);
2455 if (dnptrs && lastdnptr) {
2456 unsigned char **p = dnptrs;
2457 for (; p != lastdnptr && *p; ++p)
2458 ;
2459 if (p != lastdnptr)
2460 ++p;
2461 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dnptrs, (p - dnptrs) * sizeof(*p));
2462 }
2463 }
2464 return res;
2465}
2466INTERCEPTOR(int, DN_EXPAND_INTERCEPTOR_NAME, unsigned char const *base,
2467 unsigned char const *end, unsigned char const *src, char *dest,
2468 int space) {
2469 void *ctx;
2470 COMMON_INTERCEPTOR_ENTER(ctx, DN_EXPAND_INTERCEPTOR_NAME, base, end, src,
2471 dest, space);
2472 // TODO: add read check if __dn_comp intercept added
2473 int res = REAL(DN_EXPAND_INTERCEPTOR_NAME)(base, end, src, dest, space);
2474 if (res >= 0)
2475 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, internal_strlen(dest) + 1);
2476 return res;
2477}
2478# define INIT_DN_COMP_EXPAND \
2479 COMMON_INTERCEPT_FUNCTION(DN_COMP_INTERCEPTOR_NAME); \
2480 COMMON_INTERCEPT_FUNCTION(DN_EXPAND_INTERCEPTOR_NAME);
2481#else // SANITIZER_INTERCEPT_DN_COMP_EXPAND
2482# define INIT_DN_COMP_EXPAND
2483#endif // SANITIZER_INTERCEPT_DN_COMP_EXPAND
2484
2485#if SANITIZER_INTERCEPT_POSIX_SPAWN
2486
2487template <class RealSpawnPtr>
2488static int PosixSpawnImpl(void *ctx, RealSpawnPtr *real_posix_spawn, pid_t *pid,
2489 const char *file_or_path, const void *file_actions,
2490 const void *attrp, char *const argv[],
2491 char *const envp[]) {
2492 COMMON_INTERCEPTOR_READ_RANGE(ctx, file_or_path,
2493 internal_strlen(file_or_path) + 1);
2494 if (argv) {
2495 for (char *const *s = argv; ; ++s) {
2496 COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(*s));
2497 if (!*s) break;
2498 COMMON_INTERCEPTOR_READ_RANGE(ctx, *s, internal_strlen(*s) + 1);
2499 }
2500 }
2501 if (envp) {
2502 for (char *const *s = envp; ; ++s) {
2503 COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(*s));
2504 if (!*s) break;
2505 COMMON_INTERCEPTOR_READ_RANGE(ctx, *s, internal_strlen(*s) + 1);
2506 }
2507 }
2508 int res =
2509 real_posix_spawn(pid, file_or_path, file_actions, attrp, argv, envp);
2510 if (res == 0)
2511 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pid, sizeof(*pid));
2512 return res;
2513}
2514INTERCEPTOR(int, posix_spawn, pid_t *pid, const char *path,
2515 const void *file_actions, const void *attrp, char *const argv[],
2516 char *const envp[]) {
2517 void *ctx;
2518 COMMON_INTERCEPTOR_ENTER(ctx, posix_spawn, pid, path, file_actions, attrp,
2519 argv, envp);
2520 return PosixSpawnImpl(ctx, REAL(posix_spawn), pid, path, file_actions, attrp,
2521 argv, envp);
2522}
2523INTERCEPTOR(int, posix_spawnp, pid_t *pid, const char *file,
2524 const void *file_actions, const void *attrp, char *const argv[],
2525 char *const envp[]) {
2526 void *ctx;
2527 COMMON_INTERCEPTOR_ENTER(ctx, posix_spawnp, pid, file, file_actions, attrp,
2528 argv, envp);
2529 return PosixSpawnImpl(ctx, REAL(posix_spawnp), pid, file, file_actions, attrp,
2530 argv, envp);
2531}
2532# define INIT_POSIX_SPAWN \
2533 COMMON_INTERCEPT_FUNCTION(posix_spawn); \
2534 COMMON_INTERCEPT_FUNCTION(posix_spawnp);
2535#else // SANITIZER_INTERCEPT_POSIX_SPAWN
2536# define INIT_POSIX_SPAWN
2537#endif // SANITIZER_INTERCEPT_POSIX_SPAWN
2538
24132539#if SANITIZER_INTERCEPT_WAIT
24142540// According to sys/wait.h, wait(), waitid(), waitpid() may have symbol version
24152541// suffixes on Darwin. See the declaration of INTERCEPTOR_WITH_SUFFIX for
......@@ -2519,7 +2645,7 @@ INTERCEPTOR(char *, inet_ntop, int af, const void *src, char *dst, u32 size) {
25192645 // its metadata. See
25202646 // https://github.com/google/sanitizers/issues/321.
25212647 char *res = REAL(inet_ntop)(af, src, dst, size);
2522 if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
2648 if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
25232649 return res;
25242650}
25252651INTERCEPTOR(int, inet_pton, int af, const char *src, void *dst) {
......@@ -2548,7 +2674,7 @@ INTERCEPTOR(int, inet_pton, int af, const char *src, void *dst) {
25482674INTERCEPTOR(int, inet_aton, const char *cp, void *dst) {
25492675 void *ctx;
25502676 COMMON_INTERCEPTOR_ENTER(ctx, inet_aton, cp, dst);
2551 if (cp) COMMON_INTERCEPTOR_READ_RANGE(ctx, cp, REAL(strlen)(cp) + 1);
2677 if (cp) COMMON_INTERCEPTOR_READ_RANGE(ctx, cp, internal_strlen(cp) + 1);
25522678 // FIXME: under ASan the call below may write to freed memory and corrupt
25532679 // its metadata. See
25542680 // https://github.com/google/sanitizers/issues/321.
......@@ -2590,9 +2716,9 @@ INTERCEPTOR(int, getaddrinfo, char *node, char *service,
25902716 struct __sanitizer_addrinfo **out) {
25912717 void *ctx;
25922718 COMMON_INTERCEPTOR_ENTER(ctx, getaddrinfo, node, service, hints, out);
2593 if (node) COMMON_INTERCEPTOR_READ_RANGE(ctx, node, REAL(strlen)(node) + 1);
2719 if (node) COMMON_INTERCEPTOR_READ_RANGE(ctx, node, internal_strlen(node) + 1);
25942720 if (service)
2595 COMMON_INTERCEPTOR_READ_RANGE(ctx, service, REAL(strlen)(service) + 1);
2721 COMMON_INTERCEPTOR_READ_RANGE(ctx, service, internal_strlen(service) + 1);
25962722 if (hints)
25972723 COMMON_INTERCEPTOR_READ_RANGE(ctx, hints, sizeof(__sanitizer_addrinfo));
25982724 // FIXME: under ASan the call below may write to freed memory and corrupt
......@@ -2608,7 +2734,7 @@ INTERCEPTOR(int, getaddrinfo, char *node, char *service,
26082734 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_addr, p->ai_addrlen);
26092735 if (p->ai_canonname)
26102736 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_canonname,
2611 REAL(strlen)(p->ai_canonname) + 1);
2737 internal_strlen(p->ai_canonname) + 1);
26122738 p = p->ai_next;
26132739 }
26142740 }
......@@ -2634,9 +2760,9 @@ INTERCEPTOR(int, getnameinfo, void *sockaddr, unsigned salen, char *host,
26342760 REAL(getnameinfo)(sockaddr, salen, host, hostlen, serv, servlen, flags);
26352761 if (res == 0) {
26362762 if (host && hostlen)
2637 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, host, REAL(strlen)(host) + 1);
2763 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, host, internal_strlen(host) + 1);
26382764 if (serv && servlen)
2639 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, serv, REAL(strlen)(serv) + 1);
2765 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, serv, internal_strlen(serv) + 1);
26402766 }
26412767 return res;
26422768}
......@@ -2646,17 +2772,20 @@ INTERCEPTOR(int, getnameinfo, void *sockaddr, unsigned salen, char *host,
26462772#endif
26472773
26482774#if SANITIZER_INTERCEPT_GETSOCKNAME
2649INTERCEPTOR(int, getsockname, int sock_fd, void *addr, int *addrlen) {
2775INTERCEPTOR(int, getsockname, int sock_fd, void *addr, unsigned *addrlen) {
26502776 void *ctx;
26512777 COMMON_INTERCEPTOR_ENTER(ctx, getsockname, sock_fd, addr, addrlen);
2652 COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
2653 int addrlen_in = *addrlen;
2778 unsigned addr_sz;
2779 if (addrlen) {
2780 COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
2781 addr_sz = *addrlen;
2782 }
26542783 // FIXME: under ASan the call below may write to freed memory and corrupt
26552784 // its metadata. See
26562785 // https://github.com/google/sanitizers/issues/321.
26572786 int res = REAL(getsockname)(sock_fd, addr, addrlen);
2658 if (res == 0) {
2659 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addrlen_in, *addrlen));
2787 if (!res && addr && addrlen) {
2788 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addr_sz, *addrlen));
26602789 }
26612790 return res;
26622791}
......@@ -2669,10 +2798,10 @@ INTERCEPTOR(int, getsockname, int sock_fd, void *addr, int *addrlen) {
26692798static void write_hostent(void *ctx, struct __sanitizer_hostent *h) {
26702799 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h, sizeof(__sanitizer_hostent));
26712800 if (h->h_name)
2672 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h->h_name, REAL(strlen)(h->h_name) + 1);
2801 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h->h_name, internal_strlen(h->h_name) + 1);
26732802 char **p = h->h_aliases;
26742803 while (*p) {
2675 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
2804 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, internal_strlen(*p) + 1);
26762805 ++p;
26772806 }
26782807 COMMON_INTERCEPTOR_WRITE_RANGE(
......@@ -3161,13 +3290,17 @@ INTERCEPTOR(int, getpeername, int sockfd, void *addr, unsigned *addrlen) {
31613290 void *ctx;
31623291 COMMON_INTERCEPTOR_ENTER(ctx, getpeername, sockfd, addr, addrlen);
31633292 unsigned addr_sz;
3164 if (addrlen) addr_sz = *addrlen;
3293 if (addrlen) {
3294 COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
3295 addr_sz = *addrlen;
3296 }
31653297 // FIXME: under ASan the call below may write to freed memory and corrupt
31663298 // its metadata. See
31673299 // https://github.com/google/sanitizers/issues/321.
31683300 int res = REAL(getpeername)(sockfd, addr, addrlen);
3169 if (!res && addr && addrlen)
3301 if (!res && addr && addrlen) {
31703302 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addr_sz, *addrlen));
3303 }
31713304 return res;
31723305}
31733306#define INIT_GETPEERNAME COMMON_INTERCEPT_FUNCTION(getpeername);
......@@ -3196,7 +3329,7 @@ INTERCEPTOR(int, sysinfo, void *info) {
31963329INTERCEPTOR(__sanitizer_dirent *, opendir, const char *path) {
31973330 void *ctx;
31983331 COMMON_INTERCEPTOR_ENTER(ctx, opendir, path);
3199 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
3332 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
32003333 __sanitizer_dirent *res = REAL(opendir)(path);
32013334 if (res)
32023335 COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path);
......@@ -3210,7 +3343,8 @@ INTERCEPTOR(__sanitizer_dirent *, readdir, void *dirp) {
32103343 // its metadata. See
32113344 // https://github.com/google/sanitizers/issues/321.
32123345 __sanitizer_dirent *res = REAL(readdir)(dirp);
3213 if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
3346 if (res)
3347 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, __sanitizer_dirsiz(res));
32143348 return res;
32153349}
32163350
......@@ -3225,7 +3359,7 @@ INTERCEPTOR(int, readdir_r, void *dirp, __sanitizer_dirent *entry,
32253359 if (!res) {
32263360 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
32273361 if (*result)
3228 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
3362 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, __sanitizer_dirsiz(*result));
32293363 }
32303364 return res;
32313365}
......@@ -3246,7 +3380,8 @@ INTERCEPTOR(__sanitizer_dirent64 *, readdir64, void *dirp) {
32463380 // its metadata. See
32473381 // https://github.com/google/sanitizers/issues/321.
32483382 __sanitizer_dirent64 *res = REAL(readdir64)(dirp);
3249 if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
3383 if (res)
3384 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, __sanitizer_dirsiz(res));
32503385 return res;
32513386}
32523387
......@@ -3261,7 +3396,7 @@ INTERCEPTOR(int, readdir64_r, void *dirp, __sanitizer_dirent64 *entry,
32613396 if (!res) {
32623397 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
32633398 if (*result)
3264 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
3399 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, __sanitizer_dirsiz(*result));
32653400 }
32663401 return res;
32673402}
......@@ -3351,10 +3486,10 @@ INTERCEPTOR(char *, setlocale, int category, char *locale) {
33513486 void *ctx;
33523487 COMMON_INTERCEPTOR_ENTER(ctx, setlocale, category, locale);
33533488 if (locale)
3354 COMMON_INTERCEPTOR_READ_RANGE(ctx, locale, REAL(strlen)(locale) + 1);
3489 COMMON_INTERCEPTOR_READ_RANGE(ctx, locale, internal_strlen(locale) + 1);
33553490 char *res = REAL(setlocale)(category, locale);
33563491 if (res) {
3357 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
3492 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
33583493 unpoison_ctype_arrays(ctx);
33593494 }
33603495 return res;
......@@ -3373,7 +3508,7 @@ INTERCEPTOR(char *, getcwd, char *buf, SIZE_T size) {
33733508 // its metadata. See
33743509 // https://github.com/google/sanitizers/issues/321.
33753510 char *res = REAL(getcwd)(buf, size);
3376 if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
3511 if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
33773512 return res;
33783513}
33793514#define INIT_GETCWD COMMON_INTERCEPT_FUNCTION(getcwd);
......@@ -3389,7 +3524,7 @@ INTERCEPTOR(char *, get_current_dir_name, int fake) {
33893524 // its metadata. See
33903525 // https://github.com/google/sanitizers/issues/321.
33913526 char *res = REAL(get_current_dir_name)(fake);
3392 if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
3527 if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
33933528 return res;
33943529}
33953530
......@@ -3429,30 +3564,26 @@ UNUSED static inline void StrtolFixAndCheck(void *ctx, const char *nptr,
34293564 (real_endptr - nptr) + 1 : 0);
34303565}
34313566
3432
34333567#if SANITIZER_INTERCEPT_STRTOIMAX
3434INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) {
3435 void *ctx;
3436 COMMON_INTERCEPTOR_ENTER(ctx, strtoimax, nptr, endptr, base);
3437 // FIXME: under ASan the call below may write to freed memory and corrupt
3438 // its metadata. See
3439 // https://github.com/google/sanitizers/issues/321.
3568template <typename Fn>
3569static ALWAYS_INLINE auto StrtoimaxImpl(void *ctx, Fn real, const char *nptr,
3570 char **endptr, int base)
3571 -> decltype(real(nullptr, nullptr, 0)) {
34403572 char *real_endptr;
3441 INTMAX_T res = REAL(strtoimax)(nptr, &real_endptr, base);
3573 auto res = real(nptr, &real_endptr, base);
34423574 StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
34433575 return res;
34443576}
34453577
3578INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) {
3579 void *ctx;
3580 COMMON_INTERCEPTOR_ENTER(ctx, strtoimax, nptr, endptr, base);
3581 return StrtoimaxImpl(ctx, REAL(strtoimax), nptr, endptr, base);
3582}
34463583INTERCEPTOR(UINTMAX_T, strtoumax, const char *nptr, char **endptr, int base) {
34473584 void *ctx;
34483585 COMMON_INTERCEPTOR_ENTER(ctx, strtoumax, nptr, endptr, base);
3449 // FIXME: under ASan the call below may write to freed memory and corrupt
3450 // its metadata. See
3451 // https://github.com/google/sanitizers/issues/321.
3452 char *real_endptr;
3453 UINTMAX_T res = REAL(strtoumax)(nptr, &real_endptr, base);
3454 StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
3455 return res;
3586 return StrtoimaxImpl(ctx, REAL(strtoumax), nptr, endptr, base);
34563587}
34573588
34583589#define INIT_STRTOIMAX \
......@@ -3462,6 +3593,25 @@ INTERCEPTOR(UINTMAX_T, strtoumax, const char *nptr, char **endptr, int base) {
34623593#define INIT_STRTOIMAX
34633594#endif
34643595
3596#if SANITIZER_INTERCEPT_STRTOIMAX && SANITIZER_GLIBC
3597INTERCEPTOR(INTMAX_T, __isoc23_strtoimax, const char *nptr, char **endptr, int base) {
3598 void *ctx;
3599 COMMON_INTERCEPTOR_ENTER(ctx, __isoc23_strtoimax, nptr, endptr, base);
3600 return StrtoimaxImpl(ctx, REAL(__isoc23_strtoimax), nptr, endptr, base);
3601}
3602INTERCEPTOR(UINTMAX_T, __isoc23_strtoumax, const char *nptr, char **endptr, int base) {
3603 void *ctx;
3604 COMMON_INTERCEPTOR_ENTER(ctx, __isoc23_strtoumax, nptr, endptr, base);
3605 return StrtoimaxImpl(ctx, REAL(__isoc23_strtoumax), nptr, endptr, base);
3606}
3607
3608# define INIT_STRTOIMAX_C23 \
3609 COMMON_INTERCEPT_FUNCTION(__isoc23_strtoimax); \
3610 COMMON_INTERCEPT_FUNCTION(__isoc23_strtoumax);
3611#else
3612# define INIT_STRTOIMAX_C23
3613#endif
3614
34653615#if SANITIZER_INTERCEPT_MBSTOWCS
34663616INTERCEPTOR(SIZE_T, mbstowcs, wchar_t *dest, const char *src, SIZE_T len) {
34673617 void *ctx;
......@@ -3663,7 +3813,7 @@ INTERCEPTOR(int, tcgetattr, int fd, void *termios_p) {
36633813INTERCEPTOR(char *, realpath, const char *path, char *resolved_path) {
36643814 void *ctx;
36653815 COMMON_INTERCEPTOR_ENTER(ctx, realpath, path, resolved_path);
3666 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
3816 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
36673817
36683818 // Workaround a bug in glibc where dlsym(RTLD_NEXT, ...) returns the oldest
36693819 // version of a versioned symbol. For realpath(), this gives us something
......@@ -3674,11 +3824,12 @@ INTERCEPTOR(char *, realpath, const char *path, char *resolved_path) {
36743824 allocated_path = resolved_path = (char *)WRAP(malloc)(path_max + 1);
36753825
36763826 char *res = REAL(realpath)(path, resolved_path);
3677 if (allocated_path && !res) WRAP(free)(allocated_path);
3678 if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
3827 if (allocated_path && !res)
3828 WRAP(free)(allocated_path);
3829 if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
36793830 return res;
36803831}
3681#define INIT_REALPATH COMMON_INTERCEPT_FUNCTION(realpath);
3832# define INIT_REALPATH COMMON_INTERCEPT_FUNCTION(realpath);
36823833#else
36833834#define INIT_REALPATH
36843835#endif
......@@ -3687,9 +3838,9 @@ INTERCEPTOR(char *, realpath, const char *path, char *resolved_path) {
36873838INTERCEPTOR(char *, canonicalize_file_name, const char *path) {
36883839 void *ctx;
36893840 COMMON_INTERCEPTOR_ENTER(ctx, canonicalize_file_name, path);
3690 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
3841 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
36913842 char *res = REAL(canonicalize_file_name)(path);
3692 if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
3843 if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
36933844 return res;
36943845}
36953846#define INIT_CANONICALIZE_FILE_NAME \
......@@ -3750,7 +3901,7 @@ INTERCEPTOR(char *, strerror, int errnum) {
37503901 COMMON_INTERCEPTOR_ENTER(ctx, strerror, errnum);
37513902 COMMON_INTERCEPTOR_STRERROR();
37523903 char *res = REAL(strerror)(errnum);
3753 if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
3904 if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
37543905 return res;
37553906}
37563907#define INIT_STRERROR COMMON_INTERCEPT_FUNCTION(strerror);
......@@ -3765,7 +3916,7 @@ INTERCEPTOR(char *, strerror, int errnum) {
37653916// * GNU version returns message pointer, which points to either buf or some
37663917// static storage.
37673918#if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE) || \
3768 SANITIZER_MAC || SANITIZER_ANDROID || SANITIZER_NETBSD || \
3919 SANITIZER_APPLE || SANITIZER_ANDROID || SANITIZER_NETBSD || \
37693920 SANITIZER_FREEBSD
37703921// POSIX version. Spec is not clear on whether buf is NULL-terminated.
37713922// At least on OSX, buf contents are valid even when the call fails.
......@@ -3792,13 +3943,13 @@ INTERCEPTOR(char *, strerror_r, int errnum, char *buf, SIZE_T buflen) {
37923943 // https://github.com/google/sanitizers/issues/321.
37933944 char *res = REAL(strerror_r)(errnum, buf, buflen);
37943945 if (res == buf)
3795 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
3946 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
37963947 else
3797 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
3948 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
37983949 return res;
37993950}
38003951#endif //(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE ||
3801 //SANITIZER_MAC
3952 //SANITIZER_APPLE
38023953#define INIT_STRERROR_R COMMON_INTERCEPT_FUNCTION(strerror_r);
38033954#else
38043955#define INIT_STRERROR_R
......@@ -3814,7 +3965,7 @@ INTERCEPTOR(int, __xpg_strerror_r, int errnum, char *buf, SIZE_T buflen) {
38143965 int res = REAL(__xpg_strerror_r)(errnum, buf, buflen);
38153966 // This version always returns a null-terminated string.
38163967 if (buf && buflen)
3817 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
3968 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, internal_strlen(buf) + 1);
38183969 return res;
38193970}
38203971#define INIT_XPG_STRERROR_R COMMON_INTERCEPT_FUNCTION(__xpg_strerror_r);
......@@ -3832,7 +3983,7 @@ static THREADLOCAL scandir_compar_f scandir_compar;
38323983
38333984static int wrapped_scandir_filter(const struct __sanitizer_dirent *dir) {
38343985 COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
3835 COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, dir->d_reclen);
3986 COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, __sanitizer_dirsiz(dir));
38363987 return scandir_filter(dir);
38373988}
38383989
......@@ -3840,9 +3991,9 @@ static int wrapped_scandir_compar(const struct __sanitizer_dirent **a,
38403991 const struct __sanitizer_dirent **b) {
38413992 COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
38423993 COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, sizeof(*a));
3843 COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, (*a)->d_reclen);
3994 COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, __sanitizer_dirsiz(*a));
38443995 COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, sizeof(*b));
3845 COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, (*b)->d_reclen);
3996 COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, __sanitizer_dirsiz(*b));
38463997 return scandir_compar(a, b);
38473998}
38483999
......@@ -3850,7 +4001,7 @@ INTERCEPTOR(int, scandir, char *dirp, __sanitizer_dirent ***namelist,
38504001 scandir_filter_f filter, scandir_compar_f compar) {
38514002 void *ctx;
38524003 COMMON_INTERCEPTOR_ENTER(ctx, scandir, dirp, namelist, filter, compar);
3853 if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1);
4004 if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, internal_strlen(dirp) + 1);
38544005 scandir_filter = filter;
38554006 scandir_compar = compar;
38564007 // FIXME: under ASan the call below may write to freed memory and corrupt
......@@ -3866,7 +4017,7 @@ INTERCEPTOR(int, scandir, char *dirp, __sanitizer_dirent ***namelist,
38664017 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *namelist, sizeof(**namelist) * res);
38674018 for (int i = 0; i < res; ++i)
38684019 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (*namelist)[i],
3869 (*namelist)[i]->d_reclen);
4020 __sanitizer_dirsiz((*namelist)[i]));
38704021 }
38714022 return res;
38724023}
......@@ -3885,7 +4036,7 @@ static THREADLOCAL scandir64_compar_f scandir64_compar;
38854036
38864037static int wrapped_scandir64_filter(const struct __sanitizer_dirent64 *dir) {
38874038 COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
3888 COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, dir->d_reclen);
4039 COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, __sanitizer_dirsiz(dir));
38894040 return scandir64_filter(dir);
38904041}
38914042
......@@ -3893,9 +4044,9 @@ static int wrapped_scandir64_compar(const struct __sanitizer_dirent64 **a,
38934044 const struct __sanitizer_dirent64 **b) {
38944045 COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
38954046 COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, sizeof(*a));
3896 COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, (*a)->d_reclen);
4047 COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, __sanitizer_dirsiz(*a));
38974048 COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, sizeof(*b));
3898 COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, (*b)->d_reclen);
4049 COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, __sanitizer_dirsiz(*b));
38994050 return scandir64_compar(a, b);
39004051}
39014052
......@@ -3903,7 +4054,7 @@ INTERCEPTOR(int, scandir64, char *dirp, __sanitizer_dirent64 ***namelist,
39034054 scandir64_filter_f filter, scandir64_compar_f compar) {
39044055 void *ctx;
39054056 COMMON_INTERCEPTOR_ENTER(ctx, scandir64, dirp, namelist, filter, compar);
3906 if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1);
4057 if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, internal_strlen(dirp) + 1);
39074058 scandir64_filter = filter;
39084059 scandir64_compar = compar;
39094060 // FIXME: under ASan the call below may write to freed memory and corrupt
......@@ -3920,7 +4071,7 @@ INTERCEPTOR(int, scandir64, char *dirp, __sanitizer_dirent64 ***namelist,
39204071 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *namelist, sizeof(**namelist) * res);
39214072 for (int i = 0; i < res; ++i)
39224073 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (*namelist)[i],
3923 (*namelist)[i]->d_reclen);
4074 __sanitizer_dirsiz((*namelist)[i]));
39244075 }
39254076 return res;
39264077}
......@@ -3999,19 +4150,20 @@ INTERCEPTOR(int, ppoll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
39994150INTERCEPTOR(int, wordexp, char *s, __sanitizer_wordexp_t *p, int flags) {
40004151 void *ctx;
40014152 COMMON_INTERCEPTOR_ENTER(ctx, wordexp, s, p, flags);
4002 if (s) COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
4153 if (s) COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s) + 1);
40034154 // FIXME: under ASan the call below may write to freed memory and corrupt
40044155 // its metadata. See
40054156 // https://github.com/google/sanitizers/issues/321.
40064157 int res = REAL(wordexp)(s, p, flags);
40074158 if (!res && p) {
40084159 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
4009 if (p->we_wordc)
4010 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->we_wordv,
4011 sizeof(*p->we_wordv) * p->we_wordc);
4012 for (uptr i = 0; i < p->we_wordc; ++i) {
4160 uptr we_wordc =
4161 ((flags & wordexp_wrde_dooffs) ? p->we_offs : 0) + p->we_wordc;
4162 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->we_wordv,
4163 sizeof(*p->we_wordv) * (we_wordc + 1));
4164 for (uptr i = 0; i < we_wordc; ++i) {
40134165 char *w = p->we_wordv[i];
4014 if (w) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, w, REAL(strlen)(w) + 1);
4166 if (w) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, w, internal_strlen(w) + 1);
40154167 }
40164168 }
40174169 return res;
......@@ -4196,12 +4348,16 @@ INTERCEPTOR(int, pthread_sigmask, int how, __sanitizer_sigset_t *set,
41964348INTERCEPTOR(int, backtrace, void **buffer, int size) {
41974349 void *ctx;
41984350 COMMON_INTERCEPTOR_ENTER(ctx, backtrace, buffer, size);
4199 // FIXME: under ASan the call below may write to freed memory and corrupt
4200 // its metadata. See
4201 // https://github.com/google/sanitizers/issues/321.
4202 int res = REAL(backtrace)(buffer, size);
4203 if (res && buffer)
4351 // 'buffer' might be freed memory, hence it is unsafe to directly call
4352 // REAL(backtrace)(buffer, size). Instead, we use our own known-good
4353 // scratch buffer.
4354 void **scratch = (void**)InternalAlloc(sizeof(void*) * size);
4355 int res = REAL(backtrace)(scratch, size);
4356 if (res && buffer) {
42044357 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buffer, res * sizeof(*buffer));
4358 internal_memcpy(buffer, scratch, res * sizeof(*buffer));
4359 }
4360 InternalFree(scratch);
42054361 return res;
42064362}
42074363
......@@ -4210,14 +4366,13 @@ INTERCEPTOR(char **, backtrace_symbols, void **buffer, int size) {
42104366 COMMON_INTERCEPTOR_ENTER(ctx, backtrace_symbols, buffer, size);
42114367 if (buffer && size)
42124368 COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, size * sizeof(*buffer));
4213 // FIXME: under ASan the call below may write to freed memory and corrupt
4214 // its metadata. See
4215 // https://github.com/google/sanitizers/issues/321.
4369 // The COMMON_INTERCEPTOR_READ_RANGE above ensures that 'buffer' is
4370 // valid for reading.
42164371 char **res = REAL(backtrace_symbols)(buffer, size);
42174372 if (res && size) {
42184373 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, size * sizeof(*res));
42194374 for (int i = 0; i < size; ++i)
4220 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res[i], REAL(strlen(res[i])) + 1);
4375 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res[i], internal_strlen(res[i]) + 1);
42214376 }
42224377 return res;
42234378}
......@@ -4243,90 +4398,13 @@ INTERCEPTOR(void, _exit, int status) {
42434398#define INIT__EXIT
42444399#endif
42454400
4246#if SANITIZER_INTERCEPT_PTHREAD_MUTEX
4247INTERCEPTOR(int, pthread_mutex_lock, void *m) {
4248 void *ctx;
4249 COMMON_INTERCEPTOR_ENTER(ctx, pthread_mutex_lock, m);
4250 COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m);
4251 int res = REAL(pthread_mutex_lock)(m);
4252 if (res == errno_EOWNERDEAD)
4253 COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m);
4254 if (res == 0 || res == errno_EOWNERDEAD)
4255 COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m);
4256 if (res == errno_EINVAL)
4257 COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
4258 return res;
4259}
4260
4261INTERCEPTOR(int, pthread_mutex_unlock, void *m) {
4262 void *ctx;
4263 COMMON_INTERCEPTOR_ENTER(ctx, pthread_mutex_unlock, m);
4264 COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m);
4265 int res = REAL(pthread_mutex_unlock)(m);
4266 if (res == errno_EINVAL)
4267 COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
4268 return res;
4269}
4270
4271#define INIT_PTHREAD_MUTEX_LOCK COMMON_INTERCEPT_FUNCTION(pthread_mutex_lock)
4272#define INIT_PTHREAD_MUTEX_UNLOCK \
4273 COMMON_INTERCEPT_FUNCTION(pthread_mutex_unlock)
4274#else
4275#define INIT_PTHREAD_MUTEX_LOCK
4276#define INIT_PTHREAD_MUTEX_UNLOCK
4277#endif
4278
4279#if SANITIZER_INTERCEPT___PTHREAD_MUTEX
4280INTERCEPTOR(int, __pthread_mutex_lock, void *m) {
4281 void *ctx;
4282 COMMON_INTERCEPTOR_ENTER(ctx, __pthread_mutex_lock, m);
4283 COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m);
4284 int res = REAL(__pthread_mutex_lock)(m);
4285 if (res == errno_EOWNERDEAD)
4286 COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m);
4287 if (res == 0 || res == errno_EOWNERDEAD)
4288 COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m);
4289 if (res == errno_EINVAL)
4290 COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
4291 return res;
4292}
4293
4294INTERCEPTOR(int, __pthread_mutex_unlock, void *m) {
4295 void *ctx;
4296 COMMON_INTERCEPTOR_ENTER(ctx, __pthread_mutex_unlock, m);
4297 COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m);
4298 int res = REAL(__pthread_mutex_unlock)(m);
4299 if (res == errno_EINVAL)
4300 COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
4301 return res;
4302}
4303
4304#define INIT___PTHREAD_MUTEX_LOCK \
4305 COMMON_INTERCEPT_FUNCTION(__pthread_mutex_lock)
4306#define INIT___PTHREAD_MUTEX_UNLOCK \
4307 COMMON_INTERCEPT_FUNCTION(__pthread_mutex_unlock)
4308#else
4309#define INIT___PTHREAD_MUTEX_LOCK
4310#define INIT___PTHREAD_MUTEX_UNLOCK
4311#endif
4312
43134401#if SANITIZER_INTERCEPT___LIBC_MUTEX
4314INTERCEPTOR(int, __libc_mutex_lock, void *m)
4315ALIAS(WRAPPER_NAME(pthread_mutex_lock));
4316
4317INTERCEPTOR(int, __libc_mutex_unlock, void *m)
4318ALIAS(WRAPPER_NAME(pthread_mutex_unlock));
4319
43204402INTERCEPTOR(int, __libc_thr_setcancelstate, int state, int *oldstate)
4321ALIAS(WRAPPER_NAME(pthread_setcancelstate));
4403ALIAS(WRAP(pthread_setcancelstate));
43224404
4323#define INIT___LIBC_MUTEX_LOCK COMMON_INTERCEPT_FUNCTION(__libc_mutex_lock)
4324#define INIT___LIBC_MUTEX_UNLOCK COMMON_INTERCEPT_FUNCTION(__libc_mutex_unlock)
43254405#define INIT___LIBC_THR_SETCANCELSTATE \
43264406 COMMON_INTERCEPT_FUNCTION(__libc_thr_setcancelstate)
43274407#else
4328#define INIT___LIBC_MUTEX_LOCK
4329#define INIT___LIBC_MUTEX_UNLOCK
43304408#define INIT___LIBC_THR_SETCANCELSTATE
43314409#endif
43324410
......@@ -4335,16 +4413,16 @@ static void write_mntent(void *ctx, __sanitizer_mntent *mnt) {
43354413 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt, sizeof(*mnt));
43364414 if (mnt->mnt_fsname)
43374415 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_fsname,
4338 REAL(strlen)(mnt->mnt_fsname) + 1);
4416 internal_strlen(mnt->mnt_fsname) + 1);
43394417 if (mnt->mnt_dir)
43404418 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_dir,
4341 REAL(strlen)(mnt->mnt_dir) + 1);
4419 internal_strlen(mnt->mnt_dir) + 1);
43424420 if (mnt->mnt_type)
43434421 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_type,
4344 REAL(strlen)(mnt->mnt_type) + 1);
4422 internal_strlen(mnt->mnt_type) + 1);
43454423 if (mnt->mnt_opts)
43464424 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_opts,
4347 REAL(strlen)(mnt->mnt_opts) + 1);
4425 internal_strlen(mnt->mnt_opts) + 1);
43484426}
43494427#endif
43504428
......@@ -4379,7 +4457,7 @@ INTERCEPTOR(__sanitizer_mntent *, getmntent_r, void *fp,
43794457INTERCEPTOR(int, statfs, char *path, void *buf) {
43804458 void *ctx;
43814459 COMMON_INTERCEPTOR_ENTER(ctx, statfs, path, buf);
4382 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
4460 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
43834461 // FIXME: under ASan the call below may write to freed memory and corrupt
43844462 // its metadata. See
43854463 // https://github.com/google/sanitizers/issues/321.
......@@ -4408,7 +4486,7 @@ INTERCEPTOR(int, fstatfs, int fd, void *buf) {
44084486INTERCEPTOR(int, statfs64, char *path, void *buf) {
44094487 void *ctx;
44104488 COMMON_INTERCEPTOR_ENTER(ctx, statfs64, path, buf);
4411 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
4489 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
44124490 // FIXME: under ASan the call below may write to freed memory and corrupt
44134491 // its metadata. See
44144492 // https://github.com/google/sanitizers/issues/321.
......@@ -4437,7 +4515,7 @@ INTERCEPTOR(int, fstatfs64, int fd, void *buf) {
44374515INTERCEPTOR(int, statvfs, char *path, void *buf) {
44384516 void *ctx;
44394517 COMMON_INTERCEPTOR_ENTER(ctx, statvfs, path, buf);
4440 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
4518 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
44414519 // FIXME: under ASan the call below may write to freed memory and corrupt
44424520 // its metadata. See
44434521 // https://github.com/google/sanitizers/issues/321.
......@@ -4471,7 +4549,7 @@ INTERCEPTOR(int, fstatvfs, int fd, void *buf) {
44714549INTERCEPTOR(int, statvfs64, char *path, void *buf) {
44724550 void *ctx;
44734551 COMMON_INTERCEPTOR_ENTER(ctx, statvfs64, path, buf);
4474 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
4552 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
44754553 // FIXME: under ASan the call below may write to freed memory and corrupt
44764554 // its metadata. See
44774555 // https://github.com/google/sanitizers/issues/321.
......@@ -4500,7 +4578,7 @@ INTERCEPTOR(int, fstatvfs64, int fd, void *buf) {
45004578INTERCEPTOR(int, initgroups, char *user, u32 group) {
45014579 void *ctx;
45024580 COMMON_INTERCEPTOR_ENTER(ctx, initgroups, user, group);
4503 if (user) COMMON_INTERCEPTOR_READ_RANGE(ctx, user, REAL(strlen)(user) + 1);
4581 if (user) COMMON_INTERCEPTOR_READ_RANGE(ctx, user, internal_strlen(user) + 1);
45044582 int res = REAL(initgroups)(user, group);
45054583 return res;
45064584}
......@@ -4515,13 +4593,13 @@ INTERCEPTOR(char *, ether_ntoa, __sanitizer_ether_addr *addr) {
45154593 COMMON_INTERCEPTOR_ENTER(ctx, ether_ntoa, addr);
45164594 if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
45174595 char *res = REAL(ether_ntoa)(addr);
4518 if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
4596 if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
45194597 return res;
45204598}
45214599INTERCEPTOR(__sanitizer_ether_addr *, ether_aton, char *buf) {
45224600 void *ctx;
45234601 COMMON_INTERCEPTOR_ENTER(ctx, ether_aton, buf);
4524 if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
4602 if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, internal_strlen(buf) + 1);
45254603 __sanitizer_ether_addr *res = REAL(ether_aton)(buf);
45264604 if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, sizeof(*res));
45274605 return res;
......@@ -4543,14 +4621,14 @@ INTERCEPTOR(int, ether_ntohost, char *hostname, __sanitizer_ether_addr *addr) {
45434621 // https://github.com/google/sanitizers/issues/321.
45444622 int res = REAL(ether_ntohost)(hostname, addr);
45454623 if (!res && hostname)
4546 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1);
4624 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, internal_strlen(hostname) + 1);
45474625 return res;
45484626}
45494627INTERCEPTOR(int, ether_hostton, char *hostname, __sanitizer_ether_addr *addr) {
45504628 void *ctx;
45514629 COMMON_INTERCEPTOR_ENTER(ctx, ether_hostton, hostname, addr);
45524630 if (hostname)
4553 COMMON_INTERCEPTOR_READ_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1);
4631 COMMON_INTERCEPTOR_READ_RANGE(ctx, hostname, internal_strlen(hostname) + 1);
45544632 // FIXME: under ASan the call below may write to freed memory and corrupt
45554633 // its metadata. See
45564634 // https://github.com/google/sanitizers/issues/321.
......@@ -4562,7 +4640,7 @@ INTERCEPTOR(int, ether_line, char *line, __sanitizer_ether_addr *addr,
45624640 char *hostname) {
45634641 void *ctx;
45644642 COMMON_INTERCEPTOR_ENTER(ctx, ether_line, line, addr, hostname);
4565 if (line) COMMON_INTERCEPTOR_READ_RANGE(ctx, line, REAL(strlen)(line) + 1);
4643 if (line) COMMON_INTERCEPTOR_READ_RANGE(ctx, line, internal_strlen(line) + 1);
45664644 // FIXME: under ASan the call below may write to freed memory and corrupt
45674645 // its metadata. See
45684646 // https://github.com/google/sanitizers/issues/321.
......@@ -4570,7 +4648,7 @@ INTERCEPTOR(int, ether_line, char *line, __sanitizer_ether_addr *addr,
45704648 if (!res) {
45714649 if (addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
45724650 if (hostname)
4573 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1);
4651 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, internal_strlen(hostname) + 1);
45744652 }
45754653 return res;
45764654}
......@@ -4591,14 +4669,14 @@ INTERCEPTOR(char *, ether_ntoa_r, __sanitizer_ether_addr *addr, char *buf) {
45914669 // its metadata. See
45924670 // https://github.com/google/sanitizers/issues/321.
45934671 char *res = REAL(ether_ntoa_r)(addr, buf);
4594 if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
4672 if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
45954673 return res;
45964674}
45974675INTERCEPTOR(__sanitizer_ether_addr *, ether_aton_r, char *buf,
45984676 __sanitizer_ether_addr *addr) {
45994677 void *ctx;
46004678 COMMON_INTERCEPTOR_ENTER(ctx, ether_aton_r, buf, addr);
4601 if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
4679 if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, internal_strlen(buf) + 1);
46024680 // FIXME: under ASan the call below may write to freed memory and corrupt
46034681 // its metadata. See
46044682 // https://github.com/google/sanitizers/issues/321.
......@@ -4766,6 +4844,27 @@ INTERCEPTOR(int, pthread_attr_getaffinity_np, void *attr, SIZE_T cpusetsize,
47664844#define INIT_PTHREAD_ATTR_GETAFFINITY_NP
47674845#endif
47684846
4847#if SANITIZER_INTERCEPT_PTHREAD_GETAFFINITY_NP
4848INTERCEPTOR(int, pthread_getaffinity_np, void *attr, SIZE_T cpusetsize,
4849 void *cpuset) {
4850 void *ctx;
4851 COMMON_INTERCEPTOR_ENTER(ctx, pthread_getaffinity_np, attr, cpusetsize,
4852 cpuset);
4853 // FIXME: under ASan the call below may write to freed memory and corrupt
4854 // its metadata. See
4855 // https://github.com/google/sanitizers/issues/321.
4856 int res = REAL(pthread_getaffinity_np)(attr, cpusetsize, cpuset);
4857 if (!res && cpusetsize && cpuset)
4858 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cpuset, cpusetsize);
4859 return res;
4860}
4861
4862#define INIT_PTHREAD_GETAFFINITY_NP \
4863 COMMON_INTERCEPT_FUNCTION(pthread_getaffinity_np);
4864#else
4865#define INIT_PTHREAD_GETAFFINITY_NP
4866#endif
4867
47694868#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPSHARED
47704869INTERCEPTOR_PTHREAD_MUTEXATTR_GET(pshared, sizeof(int))
47714870#define INIT_PTHREAD_MUTEXATTR_GETPSHARED \
......@@ -4864,9 +4963,9 @@ INTERCEPTOR(char *, tmpnam, char *s) {
48644963 // FIXME: under ASan the call below may write to freed memory and corrupt
48654964 // its metadata. See
48664965 // https://github.com/google/sanitizers/issues/321.
4867 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1);
4966 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, internal_strlen(s) + 1);
48684967 else
4869 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
4968 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
48704969 }
48714970 return res;
48724971}
......@@ -4883,7 +4982,7 @@ INTERCEPTOR(char *, tmpnam_r, char *s) {
48834982 // its metadata. See
48844983 // https://github.com/google/sanitizers/issues/321.
48854984 char *res = REAL(tmpnam_r)(s);
4886 if (res && s) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1);
4985 if (res && s) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, internal_strlen(s) + 1);
48874986 return res;
48884987}
48894988#define INIT_TMPNAM_R COMMON_INTERCEPT_FUNCTION(tmpnam_r);
......@@ -4897,7 +4996,7 @@ INTERCEPTOR(char *, ptsname, int fd) {
48974996 COMMON_INTERCEPTOR_ENTER(ctx, ptsname, fd);
48984997 char *res = REAL(ptsname)(fd);
48994998 if (res != nullptr)
4900 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
4999 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
49015000 return res;
49025001}
49035002#define INIT_PTSNAME COMMON_INTERCEPT_FUNCTION(ptsname);
......@@ -4911,7 +5010,7 @@ INTERCEPTOR(int, ptsname_r, int fd, char *name, SIZE_T namesize) {
49115010 COMMON_INTERCEPTOR_ENTER(ctx, ptsname_r, fd, name, namesize);
49125011 int res = REAL(ptsname_r)(fd, name, namesize);
49135012 if (res == 0)
4914 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1);
5013 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
49155014 return res;
49165015}
49175016#define INIT_PTSNAME_R COMMON_INTERCEPT_FUNCTION(ptsname_r);
......@@ -4925,7 +5024,7 @@ INTERCEPTOR(char *, ttyname, int fd) {
49255024 COMMON_INTERCEPTOR_ENTER(ctx, ttyname, fd);
49265025 char *res = REAL(ttyname)(fd);
49275026 if (res != nullptr)
4928 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
5027 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
49295028 return res;
49305029}
49315030#define INIT_TTYNAME COMMON_INTERCEPT_FUNCTION(ttyname);
......@@ -4939,7 +5038,7 @@ INTERCEPTOR(int, ttyname_r, int fd, char *name, SIZE_T namesize) {
49395038 COMMON_INTERCEPTOR_ENTER(ctx, ttyname_r, fd, name, namesize);
49405039 int res = REAL(ttyname_r)(fd, name, namesize);
49415040 if (res == 0)
4942 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1);
5041 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
49435042 return res;
49445043}
49455044#define INIT_TTYNAME_R COMMON_INTERCEPT_FUNCTION(ttyname_r);
......@@ -4951,10 +5050,10 @@ INTERCEPTOR(int, ttyname_r, int fd, char *name, SIZE_T namesize) {
49515050INTERCEPTOR(char *, tempnam, char *dir, char *pfx) {
49525051 void *ctx;
49535052 COMMON_INTERCEPTOR_ENTER(ctx, tempnam, dir, pfx);
4954 if (dir) COMMON_INTERCEPTOR_READ_RANGE(ctx, dir, REAL(strlen)(dir) + 1);
4955 if (pfx) COMMON_INTERCEPTOR_READ_RANGE(ctx, pfx, REAL(strlen)(pfx) + 1);
5053 if (dir) COMMON_INTERCEPTOR_READ_RANGE(ctx, dir, internal_strlen(dir) + 1);
5054 if (pfx) COMMON_INTERCEPTOR_READ_RANGE(ctx, pfx, internal_strlen(pfx) + 1);
49565055 char *res = REAL(tempnam)(dir, pfx);
4957 if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
5056 if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
49585057 return res;
49595058}
49605059#define INIT_TEMPNAM COMMON_INTERCEPT_FUNCTION(tempnam);
......@@ -5332,9 +5431,7 @@ INTERCEPTOR(void *, __tls_get_addr, void *arg) {
53325431// On PowerPC, we also need to intercept __tls_get_addr_opt, which has
53335432// mostly the same semantics as __tls_get_addr, but its presence enables
53345433// some optimizations in linker (which are safe to ignore here).
5335extern "C" __attribute__((alias("__interceptor___tls_get_addr"),
5336 visibility("default")))
5337void *__tls_get_addr_opt(void *arg);
5434INTERCEPTOR(void *, __tls_get_addr_opt, void *arg) ALIAS(WRAP(__tls_get_addr));
53385435#endif
53395436#else // SANITIZER_S390
53405437// On s390, we have to intercept two functions here:
......@@ -5368,21 +5465,20 @@ INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) {
53685465
53695466#if SANITIZER_S390 && \
53705467 (SANITIZER_INTERCEPT_TLS_GET_ADDR || SANITIZER_INTERCEPT_TLS_GET_OFFSET)
5371extern "C" uptr __tls_get_offset(void *arg);
5372extern "C" uptr __interceptor___tls_get_offset(void *arg);
53735468// We need a hidden symbol aliasing the above, so that we can jump
53745469// directly to it from the assembly below.
5375extern "C" __attribute__((alias("__interceptor___tls_get_addr_internal"),
5376 visibility("hidden")))
5377uptr __tls_get_addr_hidden(void *arg);
5470extern "C" __attribute__((visibility("hidden"))) uptr __tls_get_addr_hidden(
5471 void *arg) ALIAS(WRAP(__tls_get_addr_internal));
5472extern "C" uptr __tls_get_offset(void *arg);
5473extern "C" uptr TRAMPOLINE(__tls_get_offset)(void *arg);
5474extern "C" uptr WRAP(__tls_get_offset)(void *arg);
53785475// Now carefully intercept __tls_get_offset.
53795476asm(
53805477 ".text\n"
53815478// The __intercept_ version has to exist, so that gen_dynamic_list.py
53825479// exports our symbol.
53835480 ".weak __tls_get_offset\n"
5384 ".type __tls_get_offset, @function\n"
5385 "__tls_get_offset:\n"
5481 ".set __tls_get_offset, __interceptor___tls_get_offset\n"
53865482 ".global __interceptor___tls_get_offset\n"
53875483 ".type __interceptor___tls_get_offset, @function\n"
53885484 "__interceptor___tls_get_offset:\n"
......@@ -5414,7 +5510,7 @@ asm(
54145510INTERCEPTOR(SSIZE_T, listxattr, const char *path, char *list, SIZE_T size) {
54155511 void *ctx;
54165512 COMMON_INTERCEPTOR_ENTER(ctx, listxattr, path, list, size);
5417 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
5513 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
54185514 // FIXME: under ASan the call below may write to freed memory and corrupt
54195515 // its metadata. See
54205516 // https://github.com/google/sanitizers/issues/321.
......@@ -5427,7 +5523,7 @@ INTERCEPTOR(SSIZE_T, listxattr, const char *path, char *list, SIZE_T size) {
54275523INTERCEPTOR(SSIZE_T, llistxattr, const char *path, char *list, SIZE_T size) {
54285524 void *ctx;
54295525 COMMON_INTERCEPTOR_ENTER(ctx, llistxattr, path, list, size);
5430 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
5526 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
54315527 // FIXME: under ASan the call below may write to freed memory and corrupt
54325528 // its metadata. See
54335529 // https://github.com/google/sanitizers/issues/321.
......@@ -5458,8 +5554,8 @@ INTERCEPTOR(SSIZE_T, getxattr, const char *path, const char *name, char *value,
54585554 SIZE_T size) {
54595555 void *ctx;
54605556 COMMON_INTERCEPTOR_ENTER(ctx, getxattr, path, name, value, size);
5461 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
5462 if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
5557 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
5558 if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
54635559 // FIXME: under ASan the call below may write to freed memory and corrupt
54645560 // its metadata. See
54655561 // https://github.com/google/sanitizers/issues/321.
......@@ -5471,8 +5567,8 @@ INTERCEPTOR(SSIZE_T, lgetxattr, const char *path, const char *name, char *value,
54715567 SIZE_T size) {
54725568 void *ctx;
54735569 COMMON_INTERCEPTOR_ENTER(ctx, lgetxattr, path, name, value, size);
5474 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
5475 if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
5570 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
5571 if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
54765572 // FIXME: under ASan the call below may write to freed memory and corrupt
54775573 // its metadata. See
54785574 // https://github.com/google/sanitizers/issues/321.
......@@ -5484,7 +5580,7 @@ INTERCEPTOR(SSIZE_T, fgetxattr, int fd, const char *name, char *value,
54845580 SIZE_T size) {
54855581 void *ctx;
54865582 COMMON_INTERCEPTOR_ENTER(ctx, fgetxattr, fd, name, value, size);
5487 if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
5583 if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
54885584 // FIXME: under ASan the call below may write to freed memory and corrupt
54895585 // its metadata. See
54905586 // https://github.com/google/sanitizers/issues/321.
......@@ -5554,7 +5650,7 @@ INTERCEPTOR(int, getifaddrs, __sanitizer_ifaddrs **ifap) {
55545650 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(__sanitizer_ifaddrs));
55555651 if (p->ifa_name)
55565652 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_name,
5557 REAL(strlen)(p->ifa_name) + 1);
5653 internal_strlen(p->ifa_name) + 1);
55585654 if (p->ifa_addr)
55595655 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_addr, struct_sockaddr_sz);
55605656 if (p->ifa_netmask)
......@@ -5584,14 +5680,14 @@ INTERCEPTOR(char *, if_indextoname, unsigned int ifindex, char* ifname) {
55845680 // https://github.com/google/sanitizers/issues/321.
55855681 char *res = REAL(if_indextoname)(ifindex, ifname);
55865682 if (res && ifname)
5587 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifname, REAL(strlen)(ifname) + 1);
5683 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifname, internal_strlen(ifname) + 1);
55885684 return res;
55895685}
55905686INTERCEPTOR(unsigned int, if_nametoindex, const char* ifname) {
55915687 void *ctx;
55925688 COMMON_INTERCEPTOR_ENTER(ctx, if_nametoindex, ifname);
55935689 if (ifname)
5594 COMMON_INTERCEPTOR_READ_RANGE(ctx, ifname, REAL(strlen)(ifname) + 1);
5690 COMMON_INTERCEPTOR_READ_RANGE(ctx, ifname, internal_strlen(ifname) + 1);
55955691 return REAL(if_nametoindex)(ifname);
55965692}
55975693#define INIT_IF_INDEXTONAME \
......@@ -5611,8 +5707,10 @@ INTERCEPTOR(int, capget, void *hdrp, void *datap) {
56115707 // its metadata. See
56125708 // https://github.com/google/sanitizers/issues/321.
56135709 int res = REAL(capget)(hdrp, datap);
5614 if (res == 0 && datap)
5615 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datap, __user_cap_data_struct_sz);
5710 if (res == 0 && datap) {
5711 unsigned datasz = __user_cap_data_struct_sz(hdrp);
5712 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datap, datasz);
5713 }
56165714 // We can also return -1 and write to hdrp->version if the version passed in
56175715 // hdrp->version is unsupported. But that's not a trivial condition to check,
56185716 // and anyway COMMON_INTERCEPTOR_READ_RANGE protects us to some extent.
......@@ -5623,8 +5721,10 @@ INTERCEPTOR(int, capset, void *hdrp, const void *datap) {
56235721 COMMON_INTERCEPTOR_ENTER(ctx, capset, hdrp, datap);
56245722 if (hdrp)
56255723 COMMON_INTERCEPTOR_READ_RANGE(ctx, hdrp, __user_cap_header_struct_sz);
5626 if (datap)
5627 COMMON_INTERCEPTOR_READ_RANGE(ctx, datap, __user_cap_data_struct_sz);
5724 if (datap) {
5725 unsigned datasz = __user_cap_data_struct_sz(hdrp);
5726 COMMON_INTERCEPTOR_READ_RANGE(ctx, datap, datasz);
5727 }
56285728 return REAL(capset)(hdrp, datap);
56295729}
56305730#define INIT_CAPGET \
......@@ -5634,105 +5734,6 @@ INTERCEPTOR(int, capset, void *hdrp, const void *datap) {
56345734#define INIT_CAPGET
56355735#endif
56365736
5637#if SANITIZER_INTERCEPT_AEABI_MEM
5638INTERCEPTOR(void *, __aeabi_memmove, void *to, const void *from, uptr size) {
5639 void *ctx;
5640 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
5641}
5642
5643INTERCEPTOR(void *, __aeabi_memmove4, void *to, const void *from, uptr size) {
5644 void *ctx;
5645 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
5646}
5647
5648INTERCEPTOR(void *, __aeabi_memmove8, void *to, const void *from, uptr size) {
5649 void *ctx;
5650 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
5651}
5652
5653INTERCEPTOR(void *, __aeabi_memcpy, void *to, const void *from, uptr size) {
5654 void *ctx;
5655 COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
5656}
5657
5658INTERCEPTOR(void *, __aeabi_memcpy4, void *to, const void *from, uptr size) {
5659 void *ctx;
5660 COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
5661}
5662
5663INTERCEPTOR(void *, __aeabi_memcpy8, void *to, const void *from, uptr size) {
5664 void *ctx;
5665 COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
5666}
5667
5668// Note the argument order.
5669INTERCEPTOR(void *, __aeabi_memset, void *block, uptr size, int c) {
5670 void *ctx;
5671 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
5672}
5673
5674INTERCEPTOR(void *, __aeabi_memset4, void *block, uptr size, int c) {
5675 void *ctx;
5676 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
5677}
5678
5679INTERCEPTOR(void *, __aeabi_memset8, void *block, uptr size, int c) {
5680 void *ctx;
5681 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
5682}
5683
5684INTERCEPTOR(void *, __aeabi_memclr, void *block, uptr size) {
5685 void *ctx;
5686 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
5687}
5688
5689INTERCEPTOR(void *, __aeabi_memclr4, void *block, uptr size) {
5690 void *ctx;
5691 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
5692}
5693
5694INTERCEPTOR(void *, __aeabi_memclr8, void *block, uptr size) {
5695 void *ctx;
5696 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
5697}
5698
5699#define INIT_AEABI_MEM \
5700 COMMON_INTERCEPT_FUNCTION(__aeabi_memmove); \
5701 COMMON_INTERCEPT_FUNCTION(__aeabi_memmove4); \
5702 COMMON_INTERCEPT_FUNCTION(__aeabi_memmove8); \
5703 COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy); \
5704 COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy4); \
5705 COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy8); \
5706 COMMON_INTERCEPT_FUNCTION(__aeabi_memset); \
5707 COMMON_INTERCEPT_FUNCTION(__aeabi_memset4); \
5708 COMMON_INTERCEPT_FUNCTION(__aeabi_memset8); \
5709 COMMON_INTERCEPT_FUNCTION(__aeabi_memclr); \
5710 COMMON_INTERCEPT_FUNCTION(__aeabi_memclr4); \
5711 COMMON_INTERCEPT_FUNCTION(__aeabi_memclr8);
5712#else
5713#define INIT_AEABI_MEM
5714#endif // SANITIZER_INTERCEPT_AEABI_MEM
5715
5716#if SANITIZER_INTERCEPT___BZERO
5717INTERCEPTOR(void *, __bzero, void *block, uptr size) {
5718 void *ctx;
5719 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
5720}
5721#define INIT___BZERO COMMON_INTERCEPT_FUNCTION(__bzero);
5722#else
5723#define INIT___BZERO
5724#endif // SANITIZER_INTERCEPT___BZERO
5725
5726#if SANITIZER_INTERCEPT_BZERO
5727INTERCEPTOR(void *, bzero, void *block, uptr size) {
5728 void *ctx;
5729 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
5730}
5731#define INIT_BZERO COMMON_INTERCEPT_FUNCTION(bzero);
5732#else
5733#define INIT_BZERO
5734#endif // SANITIZER_INTERCEPT_BZERO
5735
57365737#if SANITIZER_INTERCEPT_FTIME
57375738INTERCEPTOR(int, ftime, __sanitizer_timeb *tp) {
57385739 void *ctx;
......@@ -5849,7 +5850,7 @@ INTERCEPTOR(int, xdr_string, __sanitizer_XDR *xdrs, char **p,
58495850 COMMON_INTERCEPTOR_ENTER(ctx, xdr_string, xdrs, p, maxsize);
58505851 if (p && xdrs->x_op == __sanitizer_XDR_ENCODE) {
58515852 COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p));
5852 COMMON_INTERCEPTOR_READ_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
5853 COMMON_INTERCEPTOR_READ_RANGE(ctx, *p, internal_strlen(*p) + 1);
58535854 }
58545855 // FIXME: under ASan the call below may write to freed memory and corrupt
58555856 // its metadata. See
......@@ -5858,7 +5859,7 @@ INTERCEPTOR(int, xdr_string, __sanitizer_XDR *xdrs, char **p,
58585859 if (p && xdrs->x_op == __sanitizer_XDR_DECODE) {
58595860 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
58605861 if (res && *p)
5861 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
5862 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, internal_strlen(*p) + 1);
58625863 }
58635864 return res;
58645865}
......@@ -6069,8 +6070,8 @@ INTERCEPTOR(int, __woverflow, __sanitizer_FILE *fp, int ch) {
60696070INTERCEPTOR(__sanitizer_FILE *, fopen, const char *path, const char *mode) {
60706071 void *ctx;
60716072 COMMON_INTERCEPTOR_ENTER(ctx, fopen, path, mode);
6072 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
6073 COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
6073 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
6074 COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
60746075 __sanitizer_FILE *res = REAL(fopen)(path, mode);
60756076 COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
60766077 if (res) unpoison_file(res);
......@@ -6079,7 +6080,7 @@ INTERCEPTOR(__sanitizer_FILE *, fopen, const char *path, const char *mode) {
60796080INTERCEPTOR(__sanitizer_FILE *, fdopen, int fd, const char *mode) {
60806081 void *ctx;
60816082 COMMON_INTERCEPTOR_ENTER(ctx, fdopen, fd, mode);
6082 COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
6083 COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
60836084 __sanitizer_FILE *res = REAL(fdopen)(fd, mode);
60846085 if (res) unpoison_file(res);
60856086 return res;
......@@ -6088,8 +6089,8 @@ INTERCEPTOR(__sanitizer_FILE *, freopen, const char *path, const char *mode,
60886089 __sanitizer_FILE *fp) {
60896090 void *ctx;
60906091 COMMON_INTERCEPTOR_ENTER(ctx, freopen, path, mode, fp);
6091 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
6092 COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
6092 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
6093 COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
60936094 COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
60946095 __sanitizer_FILE *res = REAL(freopen)(path, mode, fp);
60956096 COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
......@@ -6113,7 +6114,7 @@ INTERCEPTOR(int, flopen, const char *path, int flags, ...) {
61136114 va_end(ap);
61146115 COMMON_INTERCEPTOR_ENTER(ctx, flopen, path, flags, mode);
61156116 if (path) {
6116 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
6117 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
61176118 }
61186119 return REAL(flopen)(path, flags, mode);
61196120}
......@@ -6126,7 +6127,7 @@ INTERCEPTOR(int, flopenat, int dirfd, const char *path, int flags, ...) {
61266127 va_end(ap);
61276128 COMMON_INTERCEPTOR_ENTER(ctx, flopen, path, flags, mode);
61286129 if (path) {
6129 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
6130 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
61306131 }
61316132 return REAL(flopenat)(dirfd, path, flags, mode);
61326133}
......@@ -6142,8 +6143,8 @@ INTERCEPTOR(int, flopenat, int dirfd, const char *path, int flags, ...) {
61426143INTERCEPTOR(__sanitizer_FILE *, fopen64, const char *path, const char *mode) {
61436144 void *ctx;
61446145 COMMON_INTERCEPTOR_ENTER(ctx, fopen64, path, mode);
6145 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
6146 COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
6146 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
6147 COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
61476148 __sanitizer_FILE *res = REAL(fopen64)(path, mode);
61486149 COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
61496150 if (res) unpoison_file(res);
......@@ -6153,8 +6154,8 @@ INTERCEPTOR(__sanitizer_FILE *, freopen64, const char *path, const char *mode,
61536154 __sanitizer_FILE *fp) {
61546155 void *ctx;
61556156 COMMON_INTERCEPTOR_ENTER(ctx, freopen64, path, mode, fp);
6156 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
6157 COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
6157 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
6158 COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
61586159 COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
61596160 __sanitizer_FILE *res = REAL(freopen64)(path, mode, fp);
61606161 COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
......@@ -6305,8 +6306,7 @@ INTERCEPTOR(void*, dlopen, const char *filename, int flag) {
63056306 void *ctx;
63066307 COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlopen, filename, flag);
63076308 if (filename) COMMON_INTERCEPTOR_READ_STRING(ctx, filename, 0);
6308 COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag);
6309 void *res = REAL(dlopen)(filename, flag);
6309 void *res = COMMON_INTERCEPTOR_DLOPEN(filename, flag);
63106310 Symbolizer::GetOrInit()->InvalidateModuleList();
63116311 COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, res);
63126312 return res;
......@@ -6332,9 +6332,9 @@ INTERCEPTOR(char *, getpass, const char *prompt) {
63326332 void *ctx;
63336333 COMMON_INTERCEPTOR_ENTER(ctx, getpass, prompt);
63346334 if (prompt)
6335 COMMON_INTERCEPTOR_READ_RANGE(ctx, prompt, REAL(strlen)(prompt)+1);
6335 COMMON_INTERCEPTOR_READ_RANGE(ctx, prompt, internal_strlen(prompt)+1);
63366336 char *res = REAL(getpass)(prompt);
6337 if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res)+1);
6337 if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res)+1);
63386338 return res;
63396339}
63406340
......@@ -6475,7 +6475,7 @@ INTERCEPTOR(int, sem_init, __sanitizer_sem_t *s, int pshared, unsigned value) {
64756475 COMMON_INTERCEPTOR_ENTER(ctx, sem_init, s, pshared, value);
64766476 // Workaround a bug in glibc's "old" semaphore implementation by
64776477 // zero-initializing the sem_t contents. This has to be done here because
6478 // interceptors bind to the lowest symbols version by default, hitting the
6478 // interceptors bind to the lowest version before glibc 2.36, hitting the
64796479 // buggy code path while the non-sanitized build of the same code works fine.
64806480 REAL(memset)(s, 0, sizeof(*s));
64816481 int res = REAL(sem_init)(s, pshared, value);
......@@ -6538,17 +6538,42 @@ INTERCEPTOR(int, sem_getvalue, __sanitizer_sem_t *s, int *sval) {
65386538 }
65396539 return res;
65406540}
6541#define INIT_SEM \
6542 COMMON_INTERCEPT_FUNCTION(sem_init); \
6543 COMMON_INTERCEPT_FUNCTION(sem_destroy); \
6544 COMMON_INTERCEPT_FUNCTION(sem_wait); \
6545 COMMON_INTERCEPT_FUNCTION(sem_trywait); \
6546 COMMON_INTERCEPT_FUNCTION(sem_timedwait); \
6547 COMMON_INTERCEPT_FUNCTION(sem_post); \
6548 COMMON_INTERCEPT_FUNCTION(sem_getvalue);
6541
6542INTERCEPTOR(__sanitizer_sem_t *, sem_open, const char *name, int oflag, ...) {
6543 void *ctx;
6544 va_list ap;
6545 va_start(ap, oflag);
6546 u32 mode = va_arg(ap, u32);
6547 u32 value = va_arg(ap, u32);
6548 COMMON_INTERCEPTOR_ENTER(ctx, sem_open, name, oflag, mode, value);
6549 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
6550 __sanitizer_sem_t *s = REAL(sem_open)(name, oflag, mode, value);
6551 if (s)
6552 COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, sizeof(*s));
6553 va_end(ap);
6554 return s;
6555}
6556
6557INTERCEPTOR(int, sem_unlink, const char *name) {
6558 void *ctx;
6559 COMMON_INTERCEPTOR_ENTER(ctx, sem_unlink, name);
6560 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
6561 return REAL(sem_unlink)(name);
6562}
6563
6564# define INIT_SEM \
6565 COMMON_INTERCEPT_FUNCTION(sem_init); \
6566 COMMON_INTERCEPT_FUNCTION(sem_destroy); \
6567 COMMON_INTERCEPT_FUNCTION(sem_wait); \
6568 COMMON_INTERCEPT_FUNCTION(sem_trywait); \
6569 COMMON_INTERCEPT_FUNCTION(sem_timedwait); \
6570 COMMON_INTERCEPT_FUNCTION(sem_post); \
6571 COMMON_INTERCEPT_FUNCTION(sem_getvalue); \
6572 COMMON_INTERCEPT_FUNCTION(sem_open); \
6573 COMMON_INTERCEPT_FUNCTION(sem_unlink);
65496574#else
6550#define INIT_SEM
6551#endif // SANITIZER_INTERCEPT_SEM
6575# define INIT_SEM
6576#endif // SANITIZER_INTERCEPT_SEM
65526577
65536578#if SANITIZER_INTERCEPT_PTHREAD_SETCANCEL
65546579INTERCEPTOR(int, pthread_setcancelstate, int state, int *oldstate) {
......@@ -6631,7 +6656,7 @@ INTERCEPTOR(char *, ctermid, char *s) {
66316656 COMMON_INTERCEPTOR_ENTER(ctx, ctermid, s);
66326657 char *res = REAL(ctermid)(s);
66336658 if (res) {
6634 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
6659 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
66356660 }
66366661 return res;
66376662}
......@@ -6646,7 +6671,7 @@ INTERCEPTOR(char *, ctermid_r, char *s) {
66466671 COMMON_INTERCEPTOR_ENTER(ctx, ctermid_r, s);
66476672 char *res = REAL(ctermid_r)(s);
66486673 if (res) {
6649 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
6674 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
66506675 }
66516676 return res;
66526677}
......@@ -6772,6 +6797,23 @@ INTERCEPTOR(int, stat, const char *path, void *buf) {
67726797#define INIT_STAT
67736798#endif
67746799
6800#if SANITIZER_INTERCEPT_STAT64
6801INTERCEPTOR(int, stat64, const char *path, void *buf) {
6802 void *ctx;
6803 COMMON_INTERCEPTOR_ENTER(ctx, stat64, path, buf);
6804 if (common_flags()->intercept_stat)
6805 COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
6806 int res = REAL(stat64)(path, buf);
6807 if (!res)
6808 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
6809 return res;
6810}
6811#define INIT_STAT64 COMMON_INTERCEPT_FUNCTION(stat64)
6812#else
6813#define INIT_STAT64
6814#endif
6815
6816
67756817#if SANITIZER_INTERCEPT_LSTAT
67766818INTERCEPTOR(int, lstat, const char *path, void *buf) {
67776819 void *ctx;
......@@ -6788,6 +6830,22 @@ INTERCEPTOR(int, lstat, const char *path, void *buf) {
67886830#define INIT_LSTAT
67896831#endif
67906832
6833#if SANITIZER_INTERCEPT_STAT64
6834INTERCEPTOR(int, lstat64, const char *path, void *buf) {
6835 void *ctx;
6836 COMMON_INTERCEPTOR_ENTER(ctx, lstat64, path, buf);
6837 if (common_flags()->intercept_stat)
6838 COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
6839 int res = REAL(lstat64)(path, buf);
6840 if (!res)
6841 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
6842 return res;
6843}
6844#define INIT_LSTAT64 COMMON_INTERCEPT_FUNCTION(lstat64)
6845#else
6846#define INIT_LSTAT64
6847#endif
6848
67916849#if SANITIZER_INTERCEPT___XSTAT
67926850INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) {
67936851 void *ctx;
......@@ -6960,6 +7018,7 @@ INTERCEPTOR(int, mprobe, void *ptr) {
69607018}
69617019#endif
69627020
7021#if SANITIZER_INTERCEPT_WCSLEN
69637022INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
69647023 void *ctx;
69657024 COMMON_INTERCEPTOR_ENTER(ctx, wcslen, s);
......@@ -6978,13 +7037,16 @@ INTERCEPTOR(SIZE_T, wcsnlen, const wchar_t *s, SIZE_T n) {
69787037#define INIT_WCSLEN \
69797038 COMMON_INTERCEPT_FUNCTION(wcslen); \
69807039 COMMON_INTERCEPT_FUNCTION(wcsnlen);
7040#else
7041#define INIT_WCSLEN
7042#endif
69817043
69827044#if SANITIZER_INTERCEPT_WCSCAT
69837045INTERCEPTOR(wchar_t *, wcscat, wchar_t *dst, const wchar_t *src) {
69847046 void *ctx;
69857047 COMMON_INTERCEPTOR_ENTER(ctx, wcscat, dst, src);
6986 SIZE_T src_size = REAL(wcslen)(src);
6987 SIZE_T dst_size = REAL(wcslen)(dst);
7048 SIZE_T src_size = internal_wcslen(src);
7049 SIZE_T dst_size = internal_wcslen(dst);
69887050 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, (src_size + 1) * sizeof(wchar_t));
69897051 COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
69907052 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
......@@ -6995,8 +7057,8 @@ INTERCEPTOR(wchar_t *, wcscat, wchar_t *dst, const wchar_t *src) {
69957057INTERCEPTOR(wchar_t *, wcsncat, wchar_t *dst, const wchar_t *src, SIZE_T n) {
69967058 void *ctx;
69977059 COMMON_INTERCEPTOR_ENTER(ctx, wcsncat, dst, src, n);
6998 SIZE_T src_size = REAL(wcsnlen)(src, n);
6999 SIZE_T dst_size = REAL(wcslen)(dst);
7060 SIZE_T src_size = internal_wcsnlen(src, n);
7061 SIZE_T dst_size = internal_wcslen(dst);
70007062 COMMON_INTERCEPTOR_READ_RANGE(ctx, src,
70017063 Min(src_size + 1, n) * sizeof(wchar_t));
70027064 COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
......@@ -7015,7 +7077,7 @@ INTERCEPTOR(wchar_t *, wcsncat, wchar_t *dst, const wchar_t *src, SIZE_T n) {
70157077INTERCEPTOR(wchar_t *, wcsdup, wchar_t *s) {
70167078 void *ctx;
70177079 COMMON_INTERCEPTOR_ENTER(ctx, wcsdup, s);
7018 SIZE_T len = REAL(wcslen)(s);
7080 SIZE_T len = internal_wcslen(s);
70197081 COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * (len + 1));
70207082 wchar_t *result = REAL(wcsdup)(s);
70217083 if (result)
......@@ -7029,9 +7091,9 @@ INTERCEPTOR(wchar_t *, wcsdup, wchar_t *s) {
70297091#endif
70307092
70317093#if SANITIZER_INTERCEPT_STRXFRM
7032static SIZE_T RealStrLen(const char *str) { return REAL(strlen)(str); }
7094static SIZE_T RealStrLen(const char *str) { return internal_strlen(str); }
70337095
7034static SIZE_T RealStrLen(const wchar_t *str) { return REAL(wcslen)(str); }
7096static SIZE_T RealStrLen(const wchar_t *str) { return internal_wcslen(str); }
70357097
70367098#define STRXFRM_INTERCEPTOR_IMPL(strxfrm, dest, src, len, ...) \
70377099 { \
......@@ -7105,7 +7167,7 @@ INTERCEPTOR(int, acct, const char *file) {
71057167 void *ctx;
71067168 COMMON_INTERCEPTOR_ENTER(ctx, acct, file);
71077169 if (file)
7108 COMMON_INTERCEPTOR_READ_RANGE(ctx, file, REAL(strlen)(file) + 1);
7170 COMMON_INTERCEPTOR_READ_RANGE(ctx, file, internal_strlen(file) + 1);
71097171 return REAL(acct)(file);
71107172}
71117173#define INIT_ACCT COMMON_INTERCEPT_FUNCTION(acct)
......@@ -7120,7 +7182,7 @@ INTERCEPTOR(const char *, user_from_uid, u32 uid, int nouser) {
71207182 COMMON_INTERCEPTOR_ENTER(ctx, user_from_uid, uid, nouser);
71217183 user = REAL(user_from_uid)(uid, nouser);
71227184 if (user)
7123 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, user, REAL(strlen)(user) + 1);
7185 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, user, internal_strlen(user) + 1);
71247186 return user;
71257187}
71267188#define INIT_USER_FROM_UID COMMON_INTERCEPT_FUNCTION(user_from_uid)
......@@ -7134,7 +7196,7 @@ INTERCEPTOR(int, uid_from_user, const char *name, u32 *uid) {
71347196 int res;
71357197 COMMON_INTERCEPTOR_ENTER(ctx, uid_from_user, name, uid);
71367198 if (name)
7137 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
7199 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
71387200 res = REAL(uid_from_user)(name, uid);
71397201 if (uid)
71407202 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, uid, sizeof(*uid));
......@@ -7152,7 +7214,7 @@ INTERCEPTOR(const char *, group_from_gid, u32 gid, int nogroup) {
71527214 COMMON_INTERCEPTOR_ENTER(ctx, group_from_gid, gid, nogroup);
71537215 group = REAL(group_from_gid)(gid, nogroup);
71547216 if (group)
7155 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, group, REAL(strlen)(group) + 1);
7217 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, group, internal_strlen(group) + 1);
71567218 return group;
71577219}
71587220#define INIT_GROUP_FROM_GID COMMON_INTERCEPT_FUNCTION(group_from_gid)
......@@ -7166,7 +7228,7 @@ INTERCEPTOR(int, gid_from_group, const char *group, u32 *gid) {
71667228 int res;
71677229 COMMON_INTERCEPTOR_ENTER(ctx, gid_from_group, group, gid);
71687230 if (group)
7169 COMMON_INTERCEPTOR_READ_RANGE(ctx, group, REAL(strlen)(group) + 1);
7231 COMMON_INTERCEPTOR_READ_RANGE(ctx, group, internal_strlen(group) + 1);
71707232 res = REAL(gid_from_group)(group, gid);
71717233 if (gid)
71727234 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, gid, sizeof(*gid));
......@@ -7182,7 +7244,7 @@ INTERCEPTOR(int, access, const char *path, int mode) {
71827244 void *ctx;
71837245 COMMON_INTERCEPTOR_ENTER(ctx, access, path, mode);
71847246 if (path)
7185 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
7247 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
71867248 return REAL(access)(path, mode);
71877249}
71887250#define INIT_ACCESS COMMON_INTERCEPT_FUNCTION(access)
......@@ -7195,7 +7257,7 @@ INTERCEPTOR(int, faccessat, int fd, const char *path, int mode, int flags) {
71957257 void *ctx;
71967258 COMMON_INTERCEPTOR_ENTER(ctx, faccessat, fd, path, mode, flags);
71977259 if (path)
7198 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
7260 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
71997261 return REAL(faccessat)(fd, path, mode, flags);
72007262}
72017263#define INIT_FACCESSAT COMMON_INTERCEPT_FUNCTION(faccessat)
......@@ -7210,7 +7272,7 @@ INTERCEPTOR(int, getgrouplist, const char *name, u32 basegid, u32 *groups,
72107272 int res;
72117273 COMMON_INTERCEPTOR_ENTER(ctx, getgrouplist, name, basegid, groups, ngroups);
72127274 if (name)
7213 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
7275 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
72147276 if (ngroups)
72157277 COMMON_INTERCEPTOR_READ_RANGE(ctx, ngroups, sizeof(*ngroups));
72167278 res = REAL(getgrouplist)(name, basegid, groups, ngroups);
......@@ -7234,7 +7296,7 @@ INTERCEPTOR(int, getgroupmembership, const char *name, u32 basegid, u32 *groups,
72347296 COMMON_INTERCEPTOR_ENTER(ctx, getgroupmembership, name, basegid, groups,
72357297 maxgrp, ngroups);
72367298 if (name)
7237 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
7299 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
72387300 res = REAL(getgroupmembership)(name, basegid, groups, maxgrp, ngroups);
72397301 if (!res && groups && ngroups) {
72407302 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, groups, sizeof(*groups) * (*ngroups));
......@@ -7252,7 +7314,7 @@ INTERCEPTOR(int, getgroupmembership, const char *name, u32 basegid, u32 *groups,
72527314INTERCEPTOR(SSIZE_T, readlink, const char *path, char *buf, SIZE_T bufsiz) {
72537315 void* ctx;
72547316 COMMON_INTERCEPTOR_ENTER(ctx, readlink, path, buf, bufsiz);
7255 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
7317 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
72567318 SSIZE_T res = REAL(readlink)(path, buf, bufsiz);
72577319 if (res > 0)
72587320 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res);
......@@ -7269,7 +7331,7 @@ INTERCEPTOR(SSIZE_T, readlinkat, int dirfd, const char *path, char *buf,
72697331 SIZE_T bufsiz) {
72707332 void* ctx;
72717333 COMMON_INTERCEPTOR_ENTER(ctx, readlinkat, dirfd, path, buf, bufsiz);
7272 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
7334 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
72737335 SSIZE_T res = REAL(readlinkat)(dirfd, path, buf, bufsiz);
72747336 if (res > 0)
72757337 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res);
......@@ -7287,7 +7349,7 @@ INTERCEPTOR(int, name_to_handle_at, int dirfd, const char *pathname,
72877349 void* ctx;
72887350 COMMON_INTERCEPTOR_ENTER(ctx, name_to_handle_at, dirfd, pathname, handle,
72897351 mount_id, flags);
7290 COMMON_INTERCEPTOR_READ_RANGE(ctx, pathname, REAL(strlen)(pathname) + 1);
7352 COMMON_INTERCEPTOR_READ_RANGE(ctx, pathname, internal_strlen(pathname) + 1);
72917353
72927354 __sanitizer_file_handle *sanitizer_handle =
72937355 reinterpret_cast<__sanitizer_file_handle*>(handle);
......@@ -7351,7 +7413,7 @@ INTERCEPTOR(SIZE_T, strlcpy, char *dst, char *src, SIZE_T size) {
73517413 ctx, src, Min(internal_strnlen(src, size), size - 1) + 1);
73527414 }
73537415 res = REAL(strlcpy)(dst, src, size);
7354 COMMON_INTERCEPTOR_COPY_STRING(ctx, dst, src, REAL(strlen)(dst) + 1);
7416 COMMON_INTERCEPTOR_COPY_STRING(ctx, dst, src, internal_strlen(dst) + 1);
73557417 return res;
73567418}
73577419
......@@ -7379,17 +7441,25 @@ INTERCEPTOR(void *, mmap, void *addr, SIZE_T sz, int prot, int flags, int fd,
73797441 OFF_T off) {
73807442 void *ctx;
73817443 if (common_flags()->detect_write_exec)
7382 ReportMmapWriteExec(prot);
7444 ReportMmapWriteExec(prot, flags);
73837445 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
73847446 return (void *)internal_mmap(addr, sz, prot, flags, fd, off);
73857447 COMMON_INTERCEPTOR_ENTER(ctx, mmap, addr, sz, prot, flags, fd, off);
73867448 COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, sz, prot, flags, fd, off);
73877449}
73887450
7451INTERCEPTOR(int, munmap, void *addr, SIZE_T sz) {
7452 void *ctx;
7453 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
7454 return (int)internal_munmap(addr, sz);
7455 COMMON_INTERCEPTOR_ENTER(ctx, munmap, addr, sz);
7456 COMMON_INTERCEPTOR_MUNMAP_IMPL(ctx, addr, sz);
7457}
7458
73897459INTERCEPTOR(int, mprotect, void *addr, SIZE_T sz, int prot) {
73907460 void *ctx;
73917461 if (common_flags()->detect_write_exec)
7392 ReportMmapWriteExec(prot);
7462 ReportMmapWriteExec(prot, 0);
73937463 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
73947464 return (int)internal_mprotect(addr, sz, prot);
73957465 COMMON_INTERCEPTOR_ENTER(ctx, mprotect, addr, sz, prot);
......@@ -7398,6 +7468,7 @@ INTERCEPTOR(int, mprotect, void *addr, SIZE_T sz, int prot) {
73987468}
73997469#define INIT_MMAP \
74007470 COMMON_INTERCEPT_FUNCTION(mmap); \
7471 COMMON_INTERCEPT_FUNCTION(munmap); \
74017472 COMMON_INTERCEPT_FUNCTION(mprotect);
74027473#else
74037474#define INIT_MMAP
......@@ -7408,7 +7479,7 @@ INTERCEPTOR(void *, mmap64, void *addr, SIZE_T sz, int prot, int flags, int fd,
74087479 OFF64_T off) {
74097480 void *ctx;
74107481 if (common_flags()->detect_write_exec)
7411 ReportMmapWriteExec(prot);
7482 ReportMmapWriteExec(prot, flags);
74127483 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
74137484 return (void *)internal_mmap(addr, sz, prot, flags, fd, off);
74147485 COMMON_INTERCEPTOR_ENTER(ctx, mmap64, addr, sz, prot, flags, fd, off);
......@@ -7426,7 +7497,7 @@ INTERCEPTOR(char *, devname, u64 dev, u32 type) {
74267497 COMMON_INTERCEPTOR_ENTER(ctx, devname, dev, type);
74277498 name = REAL(devname)(dev, type);
74287499 if (name)
7429 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1);
7500 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
74307501 return name;
74317502}
74327503#define INIT_DEVNAME COMMON_INTERCEPT_FUNCTION(devname);
......@@ -7448,7 +7519,7 @@ INTERCEPTOR(DEVNAME_R_RETTYPE, devname_r, u64 dev, u32 type, char *path,
74487519 COMMON_INTERCEPTOR_ENTER(ctx, devname_r, dev, type, path, len);
74497520 DEVNAME_R_RETTYPE res = REAL(devname_r)(dev, type, path, len);
74507521 if (DEVNAME_R_SUCCESS(res))
7451 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, path, REAL(strlen)(path) + 1);
7522 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, path, internal_strlen(path) + 1);
74527523 return res;
74537524}
74547525#define INIT_DEVNAME_R COMMON_INTERCEPT_FUNCTION(devname_r);
......@@ -7478,7 +7549,7 @@ INTERCEPTOR(void, strmode, u32 mode, char *bp) {
74787549 COMMON_INTERCEPTOR_ENTER(ctx, strmode, mode, bp);
74797550 REAL(strmode)(mode, bp);
74807551 if (bp)
7481 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, bp, REAL(strlen)(bp) + 1);
7552 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, bp, internal_strlen(bp) + 1);
74827553}
74837554#define INIT_STRMODE COMMON_INTERCEPT_FUNCTION(strmode)
74847555#else
......@@ -7498,40 +7569,44 @@ INTERCEPTOR(struct __sanitizer_ttyent *, getttynam, char *name) {
74987569 void *ctx;
74997570 COMMON_INTERCEPTOR_ENTER(ctx, getttynam, name);
75007571 if (name)
7501 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
7572 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
75027573 struct __sanitizer_ttyent *ttyent = REAL(getttynam)(name);
75037574 if (ttyent)
75047575 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ttyent, struct_ttyent_sz);
75057576 return ttyent;
75067577}
7578#define INIT_TTYENT \
7579 COMMON_INTERCEPT_FUNCTION(getttyent); \
7580 COMMON_INTERCEPT_FUNCTION(getttynam);
7581#else
7582#define INIT_TTYENT
7583#endif
7584
7585#if SANITIZER_INTERCEPT_TTYENTPATH
75077586INTERCEPTOR(int, setttyentpath, char *path) {
75087587 void *ctx;
75097588 COMMON_INTERCEPTOR_ENTER(ctx, setttyentpath, path);
75107589 if (path)
7511 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
7590 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
75127591 return REAL(setttyentpath)(path);
75137592}
7514#define INIT_TTYENT \
7515 COMMON_INTERCEPT_FUNCTION(getttyent); \
7516 COMMON_INTERCEPT_FUNCTION(getttynam); \
7517 COMMON_INTERCEPT_FUNCTION(setttyentpath)
7593#define INIT_TTYENTPATH COMMON_INTERCEPT_FUNCTION(setttyentpath);
75187594#else
7519#define INIT_TTYENT
7595#define INIT_TTYENTPATH
75207596#endif
75217597
75227598#if SANITIZER_INTERCEPT_PROTOENT
75237599static void write_protoent(void *ctx, struct __sanitizer_protoent *p) {
75247600 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
75257601
7526 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_name, REAL(strlen)(p->p_name) + 1);
7602 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_name, internal_strlen(p->p_name) + 1);
75277603
75287604 SIZE_T pp_size = 1; // One handles the trailing \0
75297605
75307606 for (char **pp = p->p_aliases; *pp; ++pp, ++pp_size)
7531 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *pp, REAL(strlen)(*pp) + 1);
7607 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *pp, internal_strlen(*pp) + 1);
75327608
7533 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_aliases,
7534 pp_size * sizeof(char **));
7609 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_aliases, pp_size * sizeof(char *));
75357610}
75367611
75377612INTERCEPTOR(struct __sanitizer_protoent *, getprotoent) {
......@@ -7547,7 +7622,7 @@ INTERCEPTOR(struct __sanitizer_protoent *, getprotobyname, const char *name) {
75477622 void *ctx;
75487623 COMMON_INTERCEPTOR_ENTER(ctx, getprotobyname, name);
75497624 if (name)
7550 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
7625 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
75517626 struct __sanitizer_protoent *p = REAL(getprotobyname)(name);
75527627 if (p)
75537628 write_protoent(ctx, p);
......@@ -7591,7 +7666,7 @@ INTERCEPTOR(int, getprotobyname_r, const char *name,
75917666 COMMON_INTERCEPTOR_ENTER(ctx, getprotobyname_r, name, result_buf, buf,
75927667 buflen, result);
75937668 if (name)
7594 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
7669 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
75957670 int res = REAL(getprotobyname_r)(name, result_buf, buf, buflen, result);
75967671
75977672 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof *result);
......@@ -7630,15 +7705,14 @@ INTERCEPTOR(struct __sanitizer_netent *, getnetent) {
76307705 if (n) {
76317706 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
76327707
7633 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, REAL(strlen)(n->n_name) + 1);
7708 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, internal_strlen(n->n_name) + 1);
76347709
76357710 SIZE_T nn_size = 1; // One handles the trailing \0
76367711
76377712 for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size)
7638 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, REAL(strlen)(*nn) + 1);
7713 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, internal_strlen(*nn) + 1);
76397714
7640 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases,
7641 nn_size * sizeof(char **));
7715 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases, nn_size * sizeof(char *));
76427716 }
76437717 return n;
76447718}
......@@ -7647,20 +7721,19 @@ INTERCEPTOR(struct __sanitizer_netent *, getnetbyname, const char *name) {
76477721 void *ctx;
76487722 COMMON_INTERCEPTOR_ENTER(ctx, getnetbyname, name);
76497723 if (name)
7650 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
7724 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
76517725 struct __sanitizer_netent *n = REAL(getnetbyname)(name);
76527726 if (n) {
76537727 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
76547728
7655 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, REAL(strlen)(n->n_name) + 1);
7729 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, internal_strlen(n->n_name) + 1);
76567730
76577731 SIZE_T nn_size = 1; // One handles the trailing \0
76587732
76597733 for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size)
7660 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, REAL(strlen)(*nn) + 1);
7734 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, internal_strlen(*nn) + 1);
76617735
7662 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases,
7663 nn_size * sizeof(char **));
7736 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases, nn_size * sizeof(char *));
76647737 }
76657738 return n;
76667739}
......@@ -7672,15 +7745,14 @@ INTERCEPTOR(struct __sanitizer_netent *, getnetbyaddr, u32 net, int type) {
76727745 if (n) {
76737746 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
76747747
7675 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, REAL(strlen)(n->n_name) + 1);
7748 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, internal_strlen(n->n_name) + 1);
76767749
76777750 SIZE_T nn_size = 1; // One handles the trailing \0
76787751
76797752 for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size)
7680 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, REAL(strlen)(*nn) + 1);
7753 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, internal_strlen(*nn) + 1);
76817754
7682 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases,
7683 nn_size * sizeof(char **));
7755 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases, nn_size * sizeof(char *));
76847756 }
76857757 return n;
76867758}
......@@ -7753,12 +7825,12 @@ INTERCEPTOR(void, setbuf, __sanitizer_FILE *stream, char *buf) {
77537825 unpoison_file(stream);
77547826}
77557827
7756INTERCEPTOR(void, setbuffer, __sanitizer_FILE *stream, char *buf, int mode) {
7828INTERCEPTOR(void, setbuffer, __sanitizer_FILE *stream, char *buf, SIZE_T size) {
77577829 void *ctx;
7758 COMMON_INTERCEPTOR_ENTER(ctx, setbuffer, stream, buf, mode);
7759 REAL(setbuffer)(stream, buf, mode);
7830 COMMON_INTERCEPTOR_ENTER(ctx, setbuffer, stream, buf, size);
7831 REAL(setbuffer)(stream, buf, size);
77607832 if (buf) {
7761 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer_bufsiz);
7833 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, size);
77627834 }
77637835 if (stream)
77647836 unpoison_file(stream);
......@@ -7798,9 +7870,9 @@ INTERCEPTOR(int, regcomp, void *preg, const char *pattern, int cflags) {
77987870 void *ctx;
77997871 COMMON_INTERCEPTOR_ENTER(ctx, regcomp, preg, pattern, cflags);
78007872 if (pattern)
7801 COMMON_INTERCEPTOR_READ_RANGE(ctx, pattern, REAL(strlen)(pattern) + 1);
7873 COMMON_INTERCEPTOR_READ_RANGE(ctx, pattern, internal_strlen(pattern) + 1);
78027874 int res = REAL(regcomp)(preg, pattern, cflags);
7803 if (!res)
7875 if (preg)
78047876 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, preg, struct_regex_sz);
78057877 return res;
78067878}
......@@ -7811,7 +7883,7 @@ INTERCEPTOR(int, regexec, const void *preg, const char *string, SIZE_T nmatch,
78117883 if (preg)
78127884 COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz);
78137885 if (string)
7814 COMMON_INTERCEPTOR_READ_RANGE(ctx, string, REAL(strlen)(string) + 1);
7886 COMMON_INTERCEPTOR_READ_RANGE(ctx, string, internal_strlen(string) + 1);
78157887 int res = REAL(regexec)(preg, string, nmatch, pmatch, eflags);
78167888 if (!res && pmatch)
78177889 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pmatch, nmatch * struct_regmatch_sz);
......@@ -7825,7 +7897,7 @@ INTERCEPTOR(SIZE_T, regerror, int errcode, const void *preg, char *errbuf,
78257897 COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz);
78267898 SIZE_T res = REAL(regerror)(errcode, preg, errbuf, errbuf_size);
78277899 if (errbuf)
7828 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, errbuf, REAL(strlen)(errbuf) + 1);
7900 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, errbuf, internal_strlen(errbuf) + 1);
78297901 return res;
78307902}
78317903INTERCEPTOR(void, regfree, const void *preg) {
......@@ -7850,15 +7922,15 @@ INTERCEPTOR(SSIZE_T, regnsub, char *buf, SIZE_T bufsiz, const char *sub,
78507922 void *ctx;
78517923 COMMON_INTERCEPTOR_ENTER(ctx, regnsub, buf, bufsiz, sub, rm, str);
78527924 if (sub)
7853 COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, REAL(strlen)(sub) + 1);
7925 COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, internal_strlen(sub) + 1);
78547926 // The implementation demands and hardcodes 10 elements
78557927 if (rm)
78567928 COMMON_INTERCEPTOR_READ_RANGE(ctx, rm, 10 * struct_regmatch_sz);
78577929 if (str)
7858 COMMON_INTERCEPTOR_READ_RANGE(ctx, str, REAL(strlen)(str) + 1);
7930 COMMON_INTERCEPTOR_READ_RANGE(ctx, str, internal_strlen(str) + 1);
78597931 SSIZE_T res = REAL(regnsub)(buf, bufsiz, sub, rm, str);
78607932 if (res > 0 && buf)
7861 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
7933 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, internal_strlen(buf) + 1);
78627934 return res;
78637935}
78647936INTERCEPTOR(SSIZE_T, regasub, char **buf, const char *sub,
......@@ -7866,16 +7938,16 @@ INTERCEPTOR(SSIZE_T, regasub, char **buf, const char *sub,
78667938 void *ctx;
78677939 COMMON_INTERCEPTOR_ENTER(ctx, regasub, buf, sub, rm, sstr);
78687940 if (sub)
7869 COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, REAL(strlen)(sub) + 1);
7941 COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, internal_strlen(sub) + 1);
78707942 // Hardcode 10 elements as this is hardcoded size
78717943 if (rm)
78727944 COMMON_INTERCEPTOR_READ_RANGE(ctx, rm, 10 * struct_regmatch_sz);
78737945 if (sstr)
7874 COMMON_INTERCEPTOR_READ_RANGE(ctx, sstr, REAL(strlen)(sstr) + 1);
7946 COMMON_INTERCEPTOR_READ_RANGE(ctx, sstr, internal_strlen(sstr) + 1);
78757947 SSIZE_T res = REAL(regasub)(buf, sub, rm, sstr);
78767948 if (res > 0 && buf) {
78777949 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sizeof(char *));
7878 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *buf, REAL(strlen)(*buf) + 1);
7950 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *buf, internal_strlen(*buf) + 1);
78797951 }
78807952 return res;
78817953}
......@@ -7897,7 +7969,7 @@ INTERCEPTOR(void *, fts_open, char *const *path_argv, int options,
78977969 COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
78987970 if (!*pa)
78997971 break;
7900 COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, REAL(strlen)(*pa) + 1);
7972 COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, internal_strlen(*pa) + 1);
79017973 }
79027974 }
79037975 // TODO(kamil): handle compar callback
......@@ -7989,7 +8061,7 @@ INTERCEPTOR(int, sysctlbyname, char *sname, void *oldp, SIZE_T *oldlenp,
79898061 COMMON_INTERCEPTOR_ENTER(ctx, sysctlbyname, sname, oldp, oldlenp, newp,
79908062 newlen);
79918063 if (sname)
7992 COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
8064 COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, internal_strlen(sname) + 1);
79938065 if (oldlenp)
79948066 COMMON_INTERCEPTOR_READ_RANGE(ctx, oldlenp, sizeof(*oldlenp));
79958067 if (newp && newlen)
......@@ -8010,7 +8082,7 @@ INTERCEPTOR(int, sysctlnametomib, const char *sname, int *name,
80108082 void *ctx;
80118083 COMMON_INTERCEPTOR_ENTER(ctx, sysctlnametomib, sname, name, namelenp);
80128084 if (sname)
8013 COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
8085 COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, internal_strlen(sname) + 1);
80148086 if (namelenp)
80158087 COMMON_INTERCEPTOR_READ_RANGE(ctx, namelenp, sizeof(*namelenp));
80168088 int res = REAL(sysctlnametomib)(sname, name, namelenp);
......@@ -8050,7 +8122,7 @@ INTERCEPTOR(void *, asysctlbyname, const char *sname, SIZE_T *len) {
80508122 void *ctx;
80518123 COMMON_INTERCEPTOR_ENTER(ctx, asysctlbyname, sname, len);
80528124 if (sname)
8053 COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
8125 COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, internal_strlen(sname) + 1);
80548126 void *res = REAL(asysctlbyname)(sname, len);
80558127 if (res && len) {
80568128 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
......@@ -8073,7 +8145,7 @@ INTERCEPTOR(int, sysctlgetmibinfo, char *sname, int *name,
80738145 COMMON_INTERCEPTOR_ENTER(ctx, sysctlgetmibinfo, sname, name, namelenp, cname,
80748146 csz, rnode, v);
80758147 if (sname)
8076 COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
8148 COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, internal_strlen(sname) + 1);
80778149 if (namelenp)
80788150 COMMON_INTERCEPTOR_READ_RANGE(ctx, namelenp, sizeof(*namelenp));
80798151 if (csz)
......@@ -8107,7 +8179,7 @@ INTERCEPTOR(char *, nl_langinfo, long item) {
81078179 COMMON_INTERCEPTOR_ENTER(ctx, nl_langinfo, item);
81088180 char *ret = REAL(nl_langinfo)(item);
81098181 if (ret)
8110 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, REAL(strlen)(ret) + 1);
8182 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, internal_strlen(ret) + 1);
81118183 return ret;
81128184}
81138185#define INIT_NL_LANGINFO COMMON_INTERCEPT_FUNCTION(nl_langinfo)
......@@ -8127,7 +8199,7 @@ INTERCEPTOR(int, modctl, int operation, void *argp) {
81278199 COMMON_INTERCEPTOR_READ_RANGE(ctx, ml, sizeof(*ml));
81288200 if (ml->ml_filename)
81298201 COMMON_INTERCEPTOR_READ_RANGE(ctx, ml->ml_filename,
8130 REAL(strlen)(ml->ml_filename) + 1);
8202 internal_strlen(ml->ml_filename) + 1);
81318203 if (ml->ml_props)
81328204 COMMON_INTERCEPTOR_READ_RANGE(ctx, ml->ml_props, ml->ml_propslen);
81338205 }
......@@ -8135,7 +8207,7 @@ INTERCEPTOR(int, modctl, int operation, void *argp) {
81358207 } else if (operation == modctl_unload) {
81368208 if (argp) {
81378209 const char *name = (const char *)argp;
8138 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
8210 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
81398211 }
81408212 ret = REAL(modctl)(operation, argp);
81418213 } else if (operation == modctl_stat) {
......@@ -8177,7 +8249,7 @@ INTERCEPTOR(long long, strtonum, const char *nptr, long long minval,
81778249 if (errstr) {
81788250 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, errstr, sizeof(const char *));
81798251 if (*errstr)
8180 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *errstr, REAL(strlen)(*errstr) + 1);
8252 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *errstr, internal_strlen(*errstr) + 1);
81818253 }
81828254 return ret;
81838255}
......@@ -8197,7 +8269,7 @@ INTERCEPTOR(char *, fparseln, __sanitizer_FILE *stream, SIZE_T *len,
81978269 COMMON_INTERCEPTOR_READ_RANGE(ctx, delim, sizeof(delim[0]) * 3);
81988270 char *ret = REAL(fparseln)(stream, len, lineno, delim, flags);
81998271 if (ret) {
8200 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, REAL(strlen)(ret) + 1);
8272 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, internal_strlen(ret) + 1);
82018273 if (len)
82028274 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
82038275 if (lineno)
......@@ -8214,7 +8286,7 @@ INTERCEPTOR(char *, fparseln, __sanitizer_FILE *stream, SIZE_T *len,
82148286INTERCEPTOR(int, statvfs1, const char *path, void *buf, int flags) {
82158287 void *ctx;
82168288 COMMON_INTERCEPTOR_ENTER(ctx, statvfs1, path, buf, flags);
8217 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
8289 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
82188290 int res = REAL(statvfs1)(path, buf, flags);
82198291 if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
82208292 return res;
......@@ -8495,7 +8567,7 @@ INTERCEPTOR(char *, SHA1File, char *filename, char *buf) {
84958567 void *ctx;
84968568 COMMON_INTERCEPTOR_ENTER(ctx, SHA1File, filename, buf);
84978569 if (filename)
8498 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
8570 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
84998571 char *ret = REAL(SHA1File)(filename, buf);
85008572 if (ret)
85018573 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
......@@ -8506,7 +8578,7 @@ INTERCEPTOR(char *, SHA1FileChunk, char *filename, char *buf, OFF_T offset,
85068578 void *ctx;
85078579 COMMON_INTERCEPTOR_ENTER(ctx, SHA1FileChunk, filename, buf, offset, length);
85088580 if (filename)
8509 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
8581 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
85108582 char *ret = REAL(SHA1FileChunk)(filename, buf, offset, length);
85118583 if (ret)
85128584 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
......@@ -8582,7 +8654,7 @@ INTERCEPTOR(char *, MD4File, const char *filename, char *buf) {
85828654 void *ctx;
85838655 COMMON_INTERCEPTOR_ENTER(ctx, MD4File, filename, buf);
85848656 if (filename)
8585 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
8657 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
85868658 char *ret = REAL(MD4File)(filename, buf);
85878659 if (ret)
85888660 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD4_return_length);
......@@ -8665,7 +8737,7 @@ INTERCEPTOR(char *, RMD160File, char *filename, char *buf) {
86658737 void *ctx;
86668738 COMMON_INTERCEPTOR_ENTER(ctx, RMD160File, filename, buf);
86678739 if (filename)
8668 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
8740 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
86698741 char *ret = REAL(RMD160File)(filename, buf);
86708742 if (ret)
86718743 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
......@@ -8676,7 +8748,7 @@ INTERCEPTOR(char *, RMD160FileChunk, char *filename, char *buf, OFF_T offset,
86768748 void *ctx;
86778749 COMMON_INTERCEPTOR_ENTER(ctx, RMD160FileChunk, filename, buf, offset, length);
86788750 if (filename)
8679 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
8751 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
86808752 char *ret = REAL(RMD160FileChunk)(filename, buf, offset, length);
86818753 if (ret)
86828754 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
......@@ -8752,7 +8824,7 @@ INTERCEPTOR(char *, MD5File, const char *filename, char *buf) {
87528824 void *ctx;
87538825 COMMON_INTERCEPTOR_ENTER(ctx, MD5File, filename, buf);
87548826 if (filename)
8755 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
8827 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
87568828 char *ret = REAL(MD5File)(filename, buf);
87578829 if (ret)
87588830 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length);
......@@ -8882,7 +8954,7 @@ INTERCEPTOR(char *, MD2File, const char *filename, char *buf) {
88828954 void *ctx;
88838955 COMMON_INTERCEPTOR_ENTER(ctx, MD2File, filename, buf);
88848956 if (filename)
8885 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
8957 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
88868958 char *ret = REAL(MD2File)(filename, buf);
88878959 if (ret)
88888960 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD2_return_length);
......@@ -8960,7 +9032,7 @@ INTERCEPTOR(char *, MD2Data, const unsigned char *data, unsigned int len,
89609032 void *ctx; \
89619033 COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_File, filename, buf); \
89629034 if (filename) \
8963 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);\
9035 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);\
89649036 char *ret = REAL(SHA##LEN##_File)(filename, buf); \
89659037 if (ret) \
89669038 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
......@@ -8972,7 +9044,7 @@ INTERCEPTOR(char *, MD2Data, const unsigned char *data, unsigned int len,
89729044 COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_FileChunk, filename, buf, offset, \
89739045 length); \
89749046 if (filename) \
8975 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);\
9047 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);\
89769048 char *ret = REAL(SHA##LEN##_FileChunk)(filename, buf, offset, length); \
89779049 if (ret) \
89789050 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
......@@ -8989,10 +9061,10 @@ INTERCEPTOR(char *, MD2Data, const unsigned char *data, unsigned int len,
89899061 return ret; \
89909062 }
89919063
8992SHA2_INTERCEPTORS(224, u32);
8993SHA2_INTERCEPTORS(256, u32);
8994SHA2_INTERCEPTORS(384, u64);
8995SHA2_INTERCEPTORS(512, u64);
9064SHA2_INTERCEPTORS(224, u32)
9065SHA2_INTERCEPTORS(256, u32)
9066SHA2_INTERCEPTORS(384, u64)
9067SHA2_INTERCEPTORS(512, u64)
89969068
89979069#define INIT_SHA2_INTECEPTORS(LEN) \
89989070 COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Init); \
......@@ -9036,7 +9108,7 @@ INTERCEPTOR(int, strvis, char *dst, const char *src, int flag) {
90369108 void *ctx;
90379109 COMMON_INTERCEPTOR_ENTER(ctx, strvis, dst, src, flag);
90389110 if (src)
9039 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
9111 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
90409112 int len = REAL(strvis)(dst, src, flag);
90419113 if (dst)
90429114 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
......@@ -9046,7 +9118,7 @@ INTERCEPTOR(int, stravis, char **dst, const char *src, int flag) {
90469118 void *ctx;
90479119 COMMON_INTERCEPTOR_ENTER(ctx, stravis, dst, src, flag);
90489120 if (src)
9049 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
9121 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
90509122 int len = REAL(stravis)(dst, src, flag);
90519123 if (dst) {
90529124 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(char *));
......@@ -9059,7 +9131,7 @@ INTERCEPTOR(int, strnvis, char *dst, SIZE_T dlen, const char *src, int flag) {
90599131 void *ctx;
90609132 COMMON_INTERCEPTOR_ENTER(ctx, strnvis, dst, dlen, src, flag);
90619133 if (src)
9062 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
9134 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
90639135 int len = REAL(strnvis)(dst, dlen, src, flag);
90649136 // The interface will be valid even if there is no space for NULL char
90659137 if (dst && len > 0)
......@@ -9109,7 +9181,7 @@ INTERCEPTOR(char *, svis, char *dst, int c, int flag, int nextc,
91099181 void *ctx;
91109182 COMMON_INTERCEPTOR_ENTER(ctx, svis, dst, c, flag, nextc, extra);
91119183 if (extra)
9112 COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
9184 COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
91139185 char *end = REAL(svis)(dst, c, flag, nextc, extra);
91149186 if (dst && end)
91159187 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1);
......@@ -9120,7 +9192,7 @@ INTERCEPTOR(char *, snvis, char *dst, SIZE_T dlen, int c, int flag, int nextc,
91209192 void *ctx;
91219193 COMMON_INTERCEPTOR_ENTER(ctx, snvis, dst, dlen, c, flag, nextc, extra);
91229194 if (extra)
9123 COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
9195 COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
91249196 char *end = REAL(snvis)(dst, dlen, c, flag, nextc, extra);
91259197 if (dst && end)
91269198 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst,
......@@ -9132,9 +9204,9 @@ INTERCEPTOR(int, strsvis, char *dst, const char *src, int flag,
91329204 void *ctx;
91339205 COMMON_INTERCEPTOR_ENTER(ctx, strsvis, dst, src, flag, extra);
91349206 if (src)
9135 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
9207 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
91369208 if (extra)
9137 COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
9209 COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
91389210 int len = REAL(strsvis)(dst, src, flag, extra);
91399211 if (dst)
91409212 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
......@@ -9145,9 +9217,9 @@ INTERCEPTOR(int, strsnvis, char *dst, SIZE_T dlen, const char *src, int flag,
91459217 void *ctx;
91469218 COMMON_INTERCEPTOR_ENTER(ctx, strsnvis, dst, dlen, src, flag, extra);
91479219 if (src)
9148 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
9220 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
91499221 if (extra)
9150 COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
9222 COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
91519223 int len = REAL(strsnvis)(dst, dlen, src, flag, extra);
91529224 // The interface will be valid even if there is no space for NULL char
91539225 if (dst && len >= 0)
......@@ -9161,7 +9233,7 @@ INTERCEPTOR(int, strsvisx, char *dst, const char *src, SIZE_T len, int flag,
91619233 if (src)
91629234 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
91639235 if (extra)
9164 COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
9236 COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
91659237 int ret = REAL(strsvisx)(dst, src, len, flag, extra);
91669238 if (dst)
91679239 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
......@@ -9174,7 +9246,7 @@ INTERCEPTOR(int, strsnvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len,
91749246 if (src)
91759247 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
91769248 if (extra)
9177 COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
9249 COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
91789250 int ret = REAL(strsnvisx)(dst, dlen, src, len, flag, extra);
91799251 if (dst && ret >= 0)
91809252 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
......@@ -9188,7 +9260,7 @@ INTERCEPTOR(int, strsenvisx, char *dst, SIZE_T dlen, const char *src,
91889260 if (src)
91899261 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
91909262 if (extra)
9191 COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
9263 COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
91929264 // FIXME: only need to be checked when "flag | VIS_NOLOCALE" doesn't hold
91939265 // according to the implementation
91949266 if (cerr_ptr)
......@@ -9215,7 +9287,7 @@ INTERCEPTOR(int, strunvis, char *dst, const char *src) {
92159287 void *ctx;
92169288 COMMON_INTERCEPTOR_ENTER(ctx, strunvis, dst, src);
92179289 if (src)
9218 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
9290 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
92199291 int ret = REAL(strunvis)(dst, src);
92209292 if (ret != -1)
92219293 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
......@@ -9225,7 +9297,7 @@ INTERCEPTOR(int, strnunvis, char *dst, SIZE_T dlen, const char *src) {
92259297 void *ctx;
92269298 COMMON_INTERCEPTOR_ENTER(ctx, strnunvis, dst, dlen, src);
92279299 if (src)
9228 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
9300 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
92299301 int ret = REAL(strnunvis)(dst, dlen, src);
92309302 if (ret != -1)
92319303 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
......@@ -9235,7 +9307,7 @@ INTERCEPTOR(int, strunvisx, char *dst, const char *src, int flag) {
92359307 void *ctx;
92369308 COMMON_INTERCEPTOR_ENTER(ctx, strunvisx, dst, src, flag);
92379309 if (src)
9238 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
9310 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
92399311 int ret = REAL(strunvisx)(dst, src, flag);
92409312 if (ret != -1)
92419313 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
......@@ -9246,7 +9318,7 @@ INTERCEPTOR(int, strnunvisx, char *dst, SIZE_T dlen, const char *src,
92469318 void *ctx;
92479319 COMMON_INTERCEPTOR_ENTER(ctx, strnunvisx, dst, dlen, src, flag);
92489320 if (src)
9249 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
9321 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
92509322 int ret = REAL(strnunvisx)(dst, dlen, src, flag);
92519323 if (ret != -1)
92529324 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
......@@ -9282,7 +9354,7 @@ INTERCEPTOR(struct __sanitizer_cdbr *, cdbr_open, const char *path, int flags) {
92829354 void *ctx;
92839355 COMMON_INTERCEPTOR_ENTER(ctx, cdbr_open, path, flags);
92849356 if (path)
9285 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
9357 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
92869358 struct __sanitizer_cdbr *cdbr = REAL(cdbr_open)(path, flags);
92879359 if (cdbr)
92889360 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbr, sizeof(*cdbr));
......@@ -9474,7 +9546,7 @@ INTERCEPTOR(void *, getfsspec, const char *spec) {
94749546 void *ctx;
94759547 COMMON_INTERCEPTOR_ENTER(ctx, getfsspec, spec);
94769548 if (spec)
9477 COMMON_INTERCEPTOR_READ_RANGE(ctx, spec, REAL(strlen)(spec) + 1);
9549 COMMON_INTERCEPTOR_READ_RANGE(ctx, spec, internal_strlen(spec) + 1);
94789550 void *ret = REAL(getfsspec)(spec);
94799551 if (ret)
94809552 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz);
......@@ -9485,7 +9557,7 @@ INTERCEPTOR(void *, getfsfile, const char *file) {
94859557 void *ctx;
94869558 COMMON_INTERCEPTOR_ENTER(ctx, getfsfile, file);
94879559 if (file)
9488 COMMON_INTERCEPTOR_READ_RANGE(ctx, file, REAL(strlen)(file) + 1);
9560 COMMON_INTERCEPTOR_READ_RANGE(ctx, file, internal_strlen(file) + 1);
94899561 void *ret = REAL(getfsfile)(file);
94909562 if (ret)
94919563 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz);
......@@ -9529,9 +9601,9 @@ INTERCEPTOR(__sanitizer_FILE *, popen, const char *command, const char *type) {
95299601 void *ctx;
95309602 COMMON_INTERCEPTOR_ENTER(ctx, popen, command, type);
95319603 if (command)
9532 COMMON_INTERCEPTOR_READ_RANGE(ctx, command, REAL(strlen)(command) + 1);
9604 COMMON_INTERCEPTOR_READ_RANGE(ctx, command, internal_strlen(command) + 1);
95339605 if (type)
9534 COMMON_INTERCEPTOR_READ_RANGE(ctx, type, REAL(strlen)(type) + 1);
9606 COMMON_INTERCEPTOR_READ_RANGE(ctx, type, internal_strlen(type) + 1);
95359607 __sanitizer_FILE *res = REAL(popen)(command, type);
95369608 COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, nullptr);
95379609 if (res) unpoison_file(res);
......@@ -9548,13 +9620,13 @@ INTERCEPTOR(__sanitizer_FILE *, popenve, const char *path,
95489620 void *ctx;
95499621 COMMON_INTERCEPTOR_ENTER(ctx, popenve, path, argv, envp, type);
95509622 if (path)
9551 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
9623 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
95529624 if (argv) {
95539625 for (char *const *pa = argv; ; ++pa) {
95549626 COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
95559627 if (!*pa)
95569628 break;
9557 COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, REAL(strlen)(*pa) + 1);
9629 COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, internal_strlen(*pa) + 1);
95589630 }
95599631 }
95609632 if (envp) {
......@@ -9562,11 +9634,11 @@ INTERCEPTOR(__sanitizer_FILE *, popenve, const char *path,
95629634 COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
95639635 if (!*pa)
95649636 break;
9565 COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, REAL(strlen)(*pa) + 1);
9637 COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, internal_strlen(*pa) + 1);
95669638 }
95679639 }
95689640 if (type)
9569 COMMON_INTERCEPTOR_READ_RANGE(ctx, type, REAL(strlen)(type) + 1);
9641 COMMON_INTERCEPTOR_READ_RANGE(ctx, type, internal_strlen(type) + 1);
95709642 __sanitizer_FILE *res = REAL(popenve)(path, argv, envp, type);
95719643 COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, nullptr);
95729644 if (res) unpoison_file(res);
......@@ -9762,7 +9834,7 @@ INTERCEPTOR(char *, fdevname, int fd) {
97629834 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
97639835 char *name = REAL(fdevname)(fd);
97649836 if (name) {
9765 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1);
9837 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
97669838 if (fd > 0)
97679839 COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
97689840 }
......@@ -9775,7 +9847,7 @@ INTERCEPTOR(char *, fdevname_r, int fd, char *buf, SIZE_T len) {
97759847 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
97769848 char *name = REAL(fdevname_r)(fd, buf, len);
97779849 if (name && buf && len > 0) {
9778 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
9850 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, internal_strlen(buf) + 1);
97799851 if (fd > 0)
97809852 COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
97819853 }
......@@ -9795,7 +9867,7 @@ INTERCEPTOR(char *, getusershell) {
97959867 COMMON_INTERCEPTOR_ENTER(ctx, getusershell);
97969868 char *res = REAL(getusershell)();
97979869 if (res)
9798 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
9870 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
97999871 return res;
98009872}
98019873
......@@ -9820,7 +9892,7 @@ INTERCEPTOR(int, sl_add, void *sl, char *item) {
98209892 if (sl)
98219893 COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
98229894 if (item)
9823 COMMON_INTERCEPTOR_READ_RANGE(ctx, item, REAL(strlen)(item) + 1);
9895 COMMON_INTERCEPTOR_READ_RANGE(ctx, item, internal_strlen(item) + 1);
98249896 int res = REAL(sl_add)(sl, item);
98259897 if (!res)
98269898 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
......@@ -9833,10 +9905,10 @@ INTERCEPTOR(char *, sl_find, void *sl, const char *item) {
98339905 if (sl)
98349906 COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
98359907 if (item)
9836 COMMON_INTERCEPTOR_READ_RANGE(ctx, item, REAL(strlen)(item) + 1);
9908 COMMON_INTERCEPTOR_READ_RANGE(ctx, item, internal_strlen(item) + 1);
98379909 char *res = REAL(sl_find)(sl, item);
98389910 if (res)
9839 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
9911 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
98409912 return res;
98419913}
98429914
......@@ -9872,41 +9944,6 @@ INTERCEPTOR(SSIZE_T, getrandom, void *buf, SIZE_T buflen, unsigned int flags) {
98729944#define INIT_GETRANDOM
98739945#endif
98749946
9875#if SANITIZER_INTERCEPT_CRYPT
9876INTERCEPTOR(char *, crypt, char *key, char *salt) {
9877 void *ctx;
9878 COMMON_INTERCEPTOR_ENTER(ctx, crypt, key, salt);
9879 COMMON_INTERCEPTOR_READ_RANGE(ctx, key, internal_strlen(key) + 1);
9880 COMMON_INTERCEPTOR_READ_RANGE(ctx, salt, internal_strlen(salt) + 1);
9881 char *res = REAL(crypt)(key, salt);
9882 if (res != nullptr)
9883 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
9884 return res;
9885}
9886#define INIT_CRYPT COMMON_INTERCEPT_FUNCTION(crypt);
9887#else
9888#define INIT_CRYPT
9889#endif
9890
9891#if SANITIZER_INTERCEPT_CRYPT_R
9892INTERCEPTOR(char *, crypt_r, char *key, char *salt, void *data) {
9893 void *ctx;
9894 COMMON_INTERCEPTOR_ENTER(ctx, crypt_r, key, salt, data);
9895 COMMON_INTERCEPTOR_READ_RANGE(ctx, key, internal_strlen(key) + 1);
9896 COMMON_INTERCEPTOR_READ_RANGE(ctx, salt, internal_strlen(salt) + 1);
9897 char *res = REAL(crypt_r)(key, salt, data);
9898 if (res != nullptr) {
9899 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data,
9900 __sanitizer::struct_crypt_data_sz);
9901 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
9902 }
9903 return res;
9904}
9905#define INIT_CRYPT_R COMMON_INTERCEPT_FUNCTION(crypt_r);
9906#else
9907#define INIT_CRYPT_R
9908#endif
9909
99109947#if SANITIZER_INTERCEPT_GETENTROPY
99119948INTERCEPTOR(int, getentropy, void *buf, SIZE_T buflen) {
99129949 void *ctx;
......@@ -9922,7 +9959,52 @@ INTERCEPTOR(int, getentropy, void *buf, SIZE_T buflen) {
99229959#define INIT_GETENTROPY
99239960#endif
99249961
9925#if SANITIZER_INTERCEPT_QSORT
9962#if SANITIZER_INTERCEPT_QSORT_R
9963typedef int (*qsort_r_compar_f)(const void *, const void *, void *);
9964struct qsort_r_compar_params {
9965 SIZE_T size;
9966 qsort_r_compar_f compar;
9967 void *arg;
9968};
9969static int wrapped_qsort_r_compar(const void *a, const void *b, void *arg) {
9970 qsort_r_compar_params *params = (qsort_r_compar_params *)arg;
9971 COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
9972 COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, params->size);
9973 COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, params->size);
9974 return params->compar(a, b, params->arg);
9975}
9976
9977INTERCEPTOR(void, qsort_r, void *base, SIZE_T nmemb, SIZE_T size,
9978 qsort_r_compar_f compar, void *arg) {
9979 void *ctx;
9980 COMMON_INTERCEPTOR_ENTER(ctx, qsort_r, base, nmemb, size, compar, arg);
9981 // Run the comparator over all array elements to detect any memory issues.
9982 if (nmemb > 1) {
9983 for (SIZE_T i = 0; i < nmemb - 1; ++i) {
9984 void *p = (void *)((char *)base + i * size);
9985 void *q = (void *)((char *)base + (i + 1) * size);
9986 COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
9987 compar(p, q, arg);
9988 }
9989 }
9990 qsort_r_compar_params params = {size, compar, arg};
9991 REAL(qsort_r)(base, nmemb, size, wrapped_qsort_r_compar, &params);
9992 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size);
9993}
9994# define INIT_QSORT_R COMMON_INTERCEPT_FUNCTION(qsort_r)
9995#else
9996# define INIT_QSORT_R
9997#endif
9998
9999#if SANITIZER_INTERCEPT_QSORT && SANITIZER_INTERCEPT_QSORT_R
10000INTERCEPTOR(void, qsort, void *base, SIZE_T nmemb, SIZE_T size,
10001 qsort_r_compar_f compar) {
10002 void *ctx;
10003 COMMON_INTERCEPTOR_ENTER(ctx, qsort, base, nmemb, size, compar);
10004 WRAP(qsort_r)(base, nmemb, size, compar, nullptr);
10005}
10006# define INIT_QSORT COMMON_INTERCEPT_FUNCTION(qsort)
10007#elif SANITIZER_INTERCEPT_QSORT && !SANITIZER_INTERCEPT_QSORT_R
992610008// Glibc qsort uses a temporary buffer allocated either on stack or on heap.
992710009// Poisoned memory from there may get copied into the comparator arguments,
992810010// where it needs to be dealt with. But even that is not enough - the results of
......@@ -9937,7 +10019,7 @@ INTERCEPTOR(int, getentropy, void *buf, SIZE_T buflen) {
993710019typedef int (*qsort_compar_f)(const void *, const void *);
993810020static THREADLOCAL qsort_compar_f qsort_compar;
993910021static THREADLOCAL SIZE_T qsort_size;
9940int wrapped_qsort_compar(const void *a, const void *b) {
10022static int wrapped_qsort_compar(const void *a, const void *b) {
994110023 COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
994210024 COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, qsort_size);
994310025 COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, qsort_size);
......@@ -9979,60 +10061,34 @@ INTERCEPTOR(void, qsort, void *base, SIZE_T nmemb, SIZE_T size,
997910061 }
998010062 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size);
998110063}
9982#define INIT_QSORT COMMON_INTERCEPT_FUNCTION(qsort)
10064# define INIT_QSORT COMMON_INTERCEPT_FUNCTION(qsort)
998310065#else
9984#define INIT_QSORT
10066# define INIT_QSORT
998510067#endif
998610068
9987#if SANITIZER_INTERCEPT_QSORT_R
9988typedef int (*qsort_r_compar_f)(const void *, const void *, void *);
9989static THREADLOCAL qsort_r_compar_f qsort_r_compar;
9990static THREADLOCAL SIZE_T qsort_r_size;
9991int wrapped_qsort_r_compar(const void *a, const void *b, void *arg) {
9992 COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
9993 COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, qsort_r_size);
9994 COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, qsort_r_size);
9995 return qsort_r_compar(a, b, arg);
10069#if SANITIZER_INTERCEPT_BSEARCH
10070typedef int (*bsearch_compar_f)(const void *, const void *);
10071struct bsearch_compar_params {
10072 const void *key;
10073 bsearch_compar_f compar;
10074};
10075
10076static int wrapped_bsearch_compar(const void *key, const void *b) {
10077 const bsearch_compar_params *params = (const bsearch_compar_params *)key;
10078 COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
10079 return params->compar(params->key, b);
999610080}
999710081
9998INTERCEPTOR(void, qsort_r, void *base, SIZE_T nmemb, SIZE_T size,
9999 qsort_r_compar_f compar, void *arg) {
10082INTERCEPTOR(void *, bsearch, const void *key, const void *base, SIZE_T nmemb,
10083 SIZE_T size, bsearch_compar_f compar) {
1000010084 void *ctx;
10001 COMMON_INTERCEPTOR_ENTER(ctx, qsort_r, base, nmemb, size, compar, arg);
10002 // Run the comparator over all array elements to detect any memory issues.
10003 if (nmemb > 1) {
10004 for (SIZE_T i = 0; i < nmemb - 1; ++i) {
10005 void *p = (void *)((char *)base + i * size);
10006 void *q = (void *)((char *)base + (i + 1) * size);
10007 COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
10008 compar(p, q, arg);
10009 }
10010 }
10011 qsort_r_compar_f old_compar = qsort_r_compar;
10012 SIZE_T old_size = qsort_r_size;
10013 // Handle qsort_r() implementations that recurse using an
10014 // interposable function call:
10015 bool already_wrapped = compar == wrapped_qsort_r_compar;
10016 if (already_wrapped) {
10017 // This case should only happen if the qsort() implementation calls itself
10018 // using a preemptible function call (e.g. the FreeBSD libc version).
10019 // Check that the size and comparator arguments are as expected.
10020 CHECK_NE(compar, qsort_r_compar);
10021 CHECK_EQ(qsort_r_size, size);
10022 } else {
10023 qsort_r_compar = compar;
10024 qsort_r_size = size;
10025 }
10026 REAL(qsort_r)(base, nmemb, size, wrapped_qsort_r_compar, arg);
10027 if (!already_wrapped) {
10028 qsort_r_compar = old_compar;
10029 qsort_r_size = old_size;
10030 }
10031 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size);
10085 COMMON_INTERCEPTOR_ENTER(ctx, bsearch, key, base, nmemb, size, compar);
10086 bsearch_compar_params params = {key, compar};
10087 return REAL(bsearch)(&params, base, nmemb, size, wrapped_bsearch_compar);
1003210088}
10033#define INIT_QSORT_R COMMON_INTERCEPT_FUNCTION(qsort_r)
10089# define INIT_BSEARCH COMMON_INTERCEPT_FUNCTION(bsearch)
1003410090#else
10035#define INIT_QSORT_R
10091# define INIT_BSEARCH
1003610092#endif
1003710093
1003810094#if SANITIZER_INTERCEPT_SIGALTSTACK
......@@ -10050,6 +10106,42 @@ INTERCEPTOR(int, sigaltstack, void *ss, void *oss) {
1005010106#define INIT_SIGALTSTACK
1005110107#endif
1005210108
10109#if SANITIZER_INTERCEPT_PROCCTL
10110INTERCEPTOR(int, procctl, int idtype, u64 id, int cmd, uptr data) {
10111 void *ctx;
10112 COMMON_INTERCEPTOR_ENTER(ctx, procctl, idtype, id, cmd, data);
10113 static const int PROC_REAP_ACQUIRE = 2;
10114 static const int PROC_REAP_RELEASE = 3;
10115 static const int PROC_REAP_STATUS = 4;
10116 static const int PROC_REAP_GETPIDS = 5;
10117 static const int PROC_REAP_KILL = 6;
10118 if (cmd < PROC_REAP_ACQUIRE || cmd > PROC_REAP_KILL) {
10119 COMMON_INTERCEPTOR_READ_RANGE(ctx, (void *)data, sizeof(int));
10120 } else {
10121 // reap_acquire/reap_release bears no arguments.
10122 if (cmd > PROC_REAP_RELEASE) {
10123 unsigned int reapsz;
10124 switch (cmd) {
10125 case PROC_REAP_STATUS:
10126 reapsz = struct_procctl_reaper_status_sz;
10127 break;
10128 case PROC_REAP_GETPIDS:
10129 reapsz = struct_procctl_reaper_pids_sz;
10130 break;
10131 case PROC_REAP_KILL:
10132 reapsz = struct_procctl_reaper_kill_sz;
10133 break;
10134 }
10135 COMMON_INTERCEPTOR_READ_RANGE(ctx, (void *)data, reapsz);
10136 }
10137 }
10138 return REAL(procctl)(idtype, id, cmd, data);
10139}
10140#define INIT_PROCCTL COMMON_INTERCEPT_FUNCTION(procctl)
10141#else
10142#define INIT_PROCCTL
10143#endif
10144
1005310145#if SANITIZER_INTERCEPT_UNAME
1005410146INTERCEPTOR(int, uname, struct utsname *utsname) {
1005510147#if SANITIZER_LINUX
......@@ -10088,14 +10180,66 @@ INTERCEPTOR(int, __xuname, int size, void *utsname) {
1008810180#define INIT___XUNAME
1008910181#endif
1009010182
10183#if SANITIZER_INTERCEPT_HEXDUMP
10184INTERCEPTOR(void, hexdump, const void *ptr, int length, const char *header, int flags) {
10185 void *ctx;
10186 COMMON_INTERCEPTOR_ENTER(ctx, hexdump, ptr, length, header, flags);
10187 COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, length);
10188 COMMON_INTERCEPTOR_READ_RANGE(ctx, header, internal_strlen(header) + 1);
10189 REAL(hexdump)(ptr, length, header, flags);
10190}
10191
10192#define INIT_HEXDUMP COMMON_INTERCEPT_FUNCTION(hexdump);
10193#else
10194#define INIT_HEXDUMP
10195#endif
10196
10197#if SANITIZER_INTERCEPT_ARGP_PARSE
10198INTERCEPTOR(int, argp_parse, const struct argp *argp, int argc, char **argv,
10199 unsigned flags, int *arg_index, void *input) {
10200 void *ctx;
10201 COMMON_INTERCEPTOR_ENTER(ctx, argp_parse, argp, argc, argv, flags, arg_index,
10202 input);
10203 for (int i = 0; i < argc; i++)
10204 COMMON_INTERCEPTOR_READ_RANGE(ctx, argv[i], internal_strlen(argv[i]) + 1);
10205 int res = REAL(argp_parse)(argp, argc, argv, flags, arg_index, input);
10206 if (!res && arg_index)
10207 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, arg_index, sizeof(int));
10208 return res;
10209}
10210
10211#define INIT_ARGP_PARSE COMMON_INTERCEPT_FUNCTION(argp_parse);
10212#else
10213#define INIT_ARGP_PARSE
10214#endif
10215
10216#if SANITIZER_INTERCEPT_CPUSET_GETAFFINITY
10217INTERCEPTOR(int, cpuset_getaffinity, int level, int which, __int64_t id, SIZE_T cpusetsize, __sanitizer_cpuset_t *mask) {
10218 void *ctx;
10219 COMMON_INTERCEPTOR_ENTER(ctx, cpuset_getaffinity, level, which, id, cpusetsize, mask);
10220 int res = REAL(cpuset_getaffinity)(level, which, id, cpusetsize, mask);
10221 if (mask && !res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mask, cpusetsize);
10222 return res;
10223}
10224#define INIT_CPUSET_GETAFFINITY COMMON_INTERCEPT_FUNCTION(cpuset_getaffinity);
10225#else
10226#define INIT_CPUSET_GETAFFINITY
10227#endif
10228
1009110229#include "sanitizer_common_interceptors_netbsd_compat.inc"
1009210230
10231namespace __sanitizer {
10232void InitializeMemintrinsicInterceptors();
10233} // namespace __sanitizer
10234
1009310235static void InitializeCommonInterceptors() {
1009410236#if SI_POSIX
1009510237 static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
1009610238 interceptor_metadata_map = new ((void *)&metadata_mem) MetadataHashMap();
1009710239#endif
1009810240
10241 __sanitizer::InitializeMemintrinsicInterceptors();
10242
1009910243 INIT_MMAP;
1010010244 INIT_MMAP64;
1010110245 INIT_TEXTDOMAIN;
......@@ -10117,9 +10261,6 @@ static void InitializeCommonInterceptors() {
1011710261 INIT_STRPBRK;
1011810262 INIT_STRXFRM;
1011910263 INIT___STRXFRM_L;
10120 INIT_MEMSET;
10121 INIT_MEMMOVE;
10122 INIT_MEMCPY;
1012310264 INIT_MEMCHR;
1012410265 INIT_MEMCMP;
1012510266 INIT_BCMP;
......@@ -10166,6 +10307,9 @@ static void InitializeCommonInterceptors() {
1016610307 INIT_TIME;
1016710308 INIT_GLOB;
1016810309 INIT_GLOB64;
10310 INIT___B64_TO;
10311 INIT_DN_COMP_EXPAND;
10312 INIT_POSIX_SPAWN;
1016910313 INIT_WAIT;
1017010314 INIT_WAIT4;
1017110315 INIT_INET;
......@@ -10200,6 +10344,7 @@ static void InitializeCommonInterceptors() {
1020010344 INIT_GETCWD;
1020110345 INIT_GET_CURRENT_DIR_NAME;
1020210346 INIT_STRTOIMAX;
10347 INIT_STRTOIMAX_C23;
1020310348 INIT_MBSTOWCS;
1020410349 INIT_MBSNRTOWCS;
1020510350 INIT_WCSTOMBS;
......@@ -10231,12 +10376,6 @@ static void InitializeCommonInterceptors() {
1023110376 INIT_PTHREAD_SIGMASK;
1023210377 INIT_BACKTRACE;
1023310378 INIT__EXIT;
10234 INIT_PTHREAD_MUTEX_LOCK;
10235 INIT_PTHREAD_MUTEX_UNLOCK;
10236 INIT___PTHREAD_MUTEX_LOCK;
10237 INIT___PTHREAD_MUTEX_UNLOCK;
10238 INIT___LIBC_MUTEX_LOCK;
10239 INIT___LIBC_MUTEX_UNLOCK;
1024010379 INIT___LIBC_THR_SETCANCELSTATE;
1024110380 INIT_GETMNTENT;
1024210381 INIT_GETMNTENT_R;
......@@ -10254,6 +10393,7 @@ static void InitializeCommonInterceptors() {
1025410393 INIT_PTHREAD_ATTR_GET_SCHED;
1025510394 INIT_PTHREAD_ATTR_GETINHERITSCHED;
1025610395 INIT_PTHREAD_ATTR_GETAFFINITY_NP;
10396 INIT_PTHREAD_GETAFFINITY_NP;
1025710397 INIT_PTHREAD_MUTEXATTR_GETPSHARED;
1025810398 INIT_PTHREAD_MUTEXATTR_GETTYPE;
1025910399 INIT_PTHREAD_MUTEXATTR_GETPROTOCOL;
......@@ -10293,9 +10433,6 @@ static void InitializeCommonInterceptors() {
1029310433 INIT_GETIFADDRS;
1029410434 INIT_IF_INDEXTONAME;
1029510435 INIT_CAPGET;
10296 INIT_AEABI_MEM;
10297 INIT___BZERO;
10298 INIT_BZERO;
1029910436 INIT_FTIME;
1030010437 INIT_XDR;
1030110438 INIT_XDRREC_LINUX;
......@@ -10322,8 +10459,10 @@ static void InitializeCommonInterceptors() {
1032210459 INIT_RECV_RECVFROM;
1032310460 INIT_SEND_SENDTO;
1032410461 INIT_STAT;
10462 INIT_STAT64;
1032510463 INIT_EVENTFD_READ_WRITE;
1032610464 INIT_LSTAT;
10465 INIT_LSTAT64;
1032710466 INIT___XSTAT;
1032810467 INIT___XSTAT64;
1032910468 INIT___LXSTAT;
......@@ -10396,14 +10535,17 @@ static void InitializeCommonInterceptors() {
1039610535 INIT_GETUSERSHELL;
1039710536 INIT_SL_INIT;
1039810537 INIT_GETRANDOM;
10399 INIT_CRYPT;
10400 INIT_CRYPT_R;
1040110538 INIT_GETENTROPY;
1040210539 INIT_QSORT;
1040310540 INIT_QSORT_R;
10541 INIT_BSEARCH;
1040410542 INIT_SIGALTSTACK;
10543 INIT_PROCCTL
1040510544 INIT_UNAME;
1040610545 INIT___XUNAME;
10546 INIT_HEXDUMP;
10547 INIT_ARGP_PARSE;
10548 INIT_CPUSET_GETAFFINITY;
1040710549
1040810550 INIT___PRINTF_CHK;
1040910551}
lib/tsan/sanitizer_common/sanitizer_common_interceptors_format.inc+17-9
......@@ -324,8 +324,8 @@ static void scanf_common(void *ctx, int n_inputs, bool allowGnuMalloc,
324324 continue;
325325 int size = scanf_get_value_size(&dir);
326326 if (size == FSS_INVALID) {
327 Report("%s: WARNING: unexpected format specifier in scanf interceptor: ",
328 SanitizerToolName, "%.*s\n", dir.end - dir.begin, dir.begin);
327 Report("%s: WARNING: unexpected format specifier in scanf interceptor: %.*s\n",
328 SanitizerToolName, static_cast<int>(dir.end - dir.begin), dir.begin);
329329 break;
330330 }
331331 void *argp = va_arg(aq, void *);
......@@ -340,11 +340,19 @@ static void scanf_common(void *ctx, int n_inputs, bool allowGnuMalloc,
340340 size = 0;
341341 }
342342 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, argp, size);
343 // For %ms/%mc, write the allocated output buffer as well.
343 // For %mc/%mC/%ms/%m[/%mS, write the allocated output buffer as well.
344344 if (dir.allocate) {
345 char *buf = *(char **)argp;
346 if (buf)
347 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, internal_strlen(buf) + 1);
345 if (char *buf = *(char **)argp) {
346 if (dir.convSpecifier == 'c')
347 size = 1;
348 else if (dir.convSpecifier == 'C')
349 size = sizeof(wchar_t);
350 else if (dir.convSpecifier == 'S')
351 size = (internal_wcslen((wchar_t *)buf) + 1) * sizeof(wchar_t);
352 else // 's' or '['
353 size = internal_strlen(buf) + 1;
354 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, size);
355 }
348356 }
349357 }
350358}
......@@ -469,7 +477,7 @@ static int printf_get_value_size(PrintfDirective *dir) {
469477 break; \
470478 default: \
471479 Report("WARNING: unexpected floating-point arg size" \
472 " in printf interceptor: %d\n", size); \
480 " in printf interceptor: %zu\n", static_cast<uptr>(size)); \
473481 return; \
474482 } \
475483 } else { \
......@@ -484,7 +492,7 @@ static int printf_get_value_size(PrintfDirective *dir) {
484492 break; \
485493 default: \
486494 Report("WARNING: unexpected arg size" \
487 " in printf interceptor: %d\n", size); \
495 " in printf interceptor: %zu\n", static_cast<uptr>(size)); \
488496 return; \
489497 } \
490498 } \
......@@ -530,7 +538,7 @@ static void printf_common(void *ctx, const char *format, va_list aq) {
530538 Report(
531539 "%s: WARNING: unexpected format specifier in printf "
532540 "interceptor: %.*s (reported once per process)\n",
533 SanitizerToolName, dir.end - dir.begin, dir.begin);
541 SanitizerToolName, static_cast<int>(dir.end - dir.begin), dir.begin);
534542 break;
535543 }
536544 if (dir.convSpecifier == 'n') {
lib/tsan/sanitizer_common/sanitizer_common_interceptors_ioctl.inc+9-1
......@@ -115,11 +115,19 @@ static void ioctl_table_fill() {
115115 // _(SOUND_MIXER_WRITE_MUTE, WRITE, sizeof(int)); // same as ...WRITE_ENHANCE
116116 _(BLKFLSBUF, NONE, 0);
117117 _(BLKGETSIZE, WRITE, sizeof(uptr));
118 _(BLKRAGET, WRITE, sizeof(int));
118 _(BLKRAGET, WRITE, sizeof(uptr));
119119 _(BLKRASET, NONE, 0);
120120 _(BLKROGET, WRITE, sizeof(int));
121121 _(BLKROSET, READ, sizeof(int));
122122 _(BLKRRPART, NONE, 0);
123 _(BLKFRASET, NONE, 0);
124 _(BLKFRAGET, WRITE, sizeof(uptr));
125 _(BLKSECTSET, READ, sizeof(short));
126 _(BLKSECTGET, WRITE, sizeof(short));
127 _(BLKSSZGET, WRITE, sizeof(int));
128 _(BLKBSZGET, WRITE, sizeof(int));
129 _(BLKBSZSET, READ, sizeof(uptr));
130 _(BLKGETSIZE64, WRITE, sizeof(u64));
123131 _(CDROMEJECT, NONE, 0);
124132 _(CDROMEJECT_SW, NONE, 0);
125133 _(CDROMMULTISESSION, WRITE, struct_cdrom_multisession_sz);
lib/tsan/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc created+244
......@@ -0,0 +1,244 @@
1//===-- sanitizer_common_interceptors_memintrinsics.inc ---------*- 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// Memintrinsic function interceptors for tools like AddressSanitizer,
10// ThreadSanitizer, MemorySanitizer, etc.
11//
12// These interceptors are part of the common interceptors, but separated out so
13// that implementations may add them, if necessary, to a separate source file
14// that should define SANITIZER_COMMON_NO_REDEFINE_BUILTINS at the top.
15//
16// This file should be included into the tool's memintrinsic interceptor file,
17// which has to define its own macros:
18// COMMON_INTERCEPTOR_ENTER
19// COMMON_INTERCEPTOR_READ_RANGE
20// COMMON_INTERCEPTOR_WRITE_RANGE
21// COMMON_INTERCEPTOR_MEMSET_IMPL
22// COMMON_INTERCEPTOR_MEMMOVE_IMPL
23// COMMON_INTERCEPTOR_MEMCPY_IMPL
24// COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED
25//===----------------------------------------------------------------------===//
26
27#ifdef SANITIZER_REDEFINE_BUILTINS_H
28#error "Define SANITIZER_COMMON_NO_REDEFINE_BUILTINS in .cpp file"
29#endif
30
31#include "interception/interception.h"
32#include "sanitizer_platform_interceptors.h"
33
34// Platform-specific options.
35#if SANITIZER_APPLE
36#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0
37#elif SANITIZER_WINDOWS64
38#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0
39#else
40#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 1
41#endif // SANITIZER_APPLE
42
43#ifndef COMMON_INTERCEPTOR_MEMSET_IMPL
44#define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size) \
45 { \
46 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) \
47 return internal_memset(dst, v, size); \
48 COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size); \
49 if (common_flags()->intercept_intrin) \
50 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \
51 return REAL(memset)(dst, v, size); \
52 }
53#endif
54
55#ifndef COMMON_INTERCEPTOR_MEMMOVE_IMPL
56#define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size) \
57 { \
58 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) \
59 return internal_memmove(dst, src, size); \
60 COMMON_INTERCEPTOR_ENTER(ctx, memmove, dst, src, size); \
61 if (common_flags()->intercept_intrin) { \
62 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \
63 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size); \
64 } \
65 return REAL(memmove)(dst, src, size); \
66 }
67#endif
68
69#ifndef COMMON_INTERCEPTOR_MEMCPY_IMPL
70#define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size) \
71 { \
72 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) { \
73 return internal_memmove(dst, src, size); \
74 } \
75 COMMON_INTERCEPTOR_ENTER(ctx, memcpy, dst, src, size); \
76 if (common_flags()->intercept_intrin) { \
77 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \
78 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size); \
79 } \
80 return REAL(memcpy)(dst, src, size); \
81 }
82#endif
83
84#if SANITIZER_INTERCEPT_MEMSET
85INTERCEPTOR(void *, memset, void *dst, int v, uptr size) {
86 void *ctx;
87 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size);
88}
89
90#define INIT_MEMSET COMMON_INTERCEPT_FUNCTION(memset)
91#else
92#define INIT_MEMSET
93#endif
94
95#if SANITIZER_INTERCEPT_MEMMOVE
96INTERCEPTOR(void *, memmove, void *dst, const void *src, uptr size) {
97 void *ctx;
98 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
99}
100
101#define INIT_MEMMOVE COMMON_INTERCEPT_FUNCTION(memmove)
102#else
103#define INIT_MEMMOVE
104#endif
105
106#if SANITIZER_INTERCEPT_MEMCPY
107INTERCEPTOR(void *, memcpy, void *dst, const void *src, uptr size) {
108 // On OS X, calling internal_memcpy here will cause memory corruptions,
109 // because memcpy and memmove are actually aliases of the same
110 // implementation. We need to use internal_memmove here.
111 // N.B.: If we switch this to internal_ we'll have to use internal_memmove
112 // due to memcpy being an alias of memmove on OS X.
113 void *ctx;
114#if PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE
115 COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size);
116#else
117 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
118#endif
119}
120
121#define INIT_MEMCPY \
122 do { \
123 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { \
124 COMMON_INTERCEPT_FUNCTION(memcpy); \
125 } else { \
126 ASSIGN_REAL(memcpy, memmove); \
127 } \
128 CHECK(REAL(memcpy)); \
129 } while (false)
130
131#else
132#define INIT_MEMCPY
133#endif
134
135#if SANITIZER_INTERCEPT_AEABI_MEM
136INTERCEPTOR(void *, __aeabi_memmove, void *to, const void *from, uptr size) {
137 void *ctx;
138 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
139}
140
141INTERCEPTOR(void *, __aeabi_memmove4, void *to, const void *from, uptr size) {
142 void *ctx;
143 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
144}
145
146INTERCEPTOR(void *, __aeabi_memmove8, void *to, const void *from, uptr size) {
147 void *ctx;
148 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
149}
150
151INTERCEPTOR(void *, __aeabi_memcpy, void *to, const void *from, uptr size) {
152 void *ctx;
153 COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
154}
155
156INTERCEPTOR(void *, __aeabi_memcpy4, void *to, const void *from, uptr size) {
157 void *ctx;
158 COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
159}
160
161INTERCEPTOR(void *, __aeabi_memcpy8, void *to, const void *from, uptr size) {
162 void *ctx;
163 COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
164}
165
166// Note the argument order.
167INTERCEPTOR(void *, __aeabi_memset, void *block, uptr size, int c) {
168 void *ctx;
169 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
170}
171
172INTERCEPTOR(void *, __aeabi_memset4, void *block, uptr size, int c) {
173 void *ctx;
174 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
175}
176
177INTERCEPTOR(void *, __aeabi_memset8, void *block, uptr size, int c) {
178 void *ctx;
179 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
180}
181
182INTERCEPTOR(void *, __aeabi_memclr, void *block, uptr size) {
183 void *ctx;
184 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
185}
186
187INTERCEPTOR(void *, __aeabi_memclr4, void *block, uptr size) {
188 void *ctx;
189 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
190}
191
192INTERCEPTOR(void *, __aeabi_memclr8, void *block, uptr size) {
193 void *ctx;
194 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
195}
196
197#define INIT_AEABI_MEM \
198 COMMON_INTERCEPT_FUNCTION(__aeabi_memmove); \
199 COMMON_INTERCEPT_FUNCTION(__aeabi_memmove4); \
200 COMMON_INTERCEPT_FUNCTION(__aeabi_memmove8); \
201 COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy); \
202 COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy4); \
203 COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy8); \
204 COMMON_INTERCEPT_FUNCTION(__aeabi_memset); \
205 COMMON_INTERCEPT_FUNCTION(__aeabi_memset4); \
206 COMMON_INTERCEPT_FUNCTION(__aeabi_memset8); \
207 COMMON_INTERCEPT_FUNCTION(__aeabi_memclr); \
208 COMMON_INTERCEPT_FUNCTION(__aeabi_memclr4); \
209 COMMON_INTERCEPT_FUNCTION(__aeabi_memclr8);
210#else
211#define INIT_AEABI_MEM
212#endif // SANITIZER_INTERCEPT_AEABI_MEM
213
214#if SANITIZER_INTERCEPT___BZERO
215INTERCEPTOR(void *, __bzero, void *block, uptr size) {
216 void *ctx;
217 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
218}
219#define INIT___BZERO COMMON_INTERCEPT_FUNCTION(__bzero);
220#else
221#define INIT___BZERO
222#endif // SANITIZER_INTERCEPT___BZERO
223
224#if SANITIZER_INTERCEPT_BZERO
225INTERCEPTOR(void *, bzero, void *block, uptr size) {
226 void *ctx;
227 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
228}
229#define INIT_BZERO COMMON_INTERCEPT_FUNCTION(bzero);
230#else
231#define INIT_BZERO
232#endif // SANITIZER_INTERCEPT_BZERO
233
234namespace __sanitizer {
235// This does not need to be called if InitializeCommonInterceptors() is called.
236void InitializeMemintrinsicInterceptors() {
237 INIT_MEMSET;
238 INIT_MEMMOVE;
239 INIT_MEMCPY;
240 INIT_AEABI_MEM;
241 INIT___BZERO;
242 INIT_BZERO;
243}
244} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_common_interceptors_netbsd_compat.inc+2-2
......@@ -33,7 +33,7 @@
3333INTERCEPTOR(int, statvfs, char *path, void *buf) {
3434 void *ctx;
3535 COMMON_INTERCEPTOR_ENTER(ctx, statvfs, path, buf);
36 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
36 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
3737 // FIXME: under ASan the call below may write to freed memory and corrupt
3838 // its metadata. See
3939 // https://github.com/google/sanitizers/issues/321.
......@@ -99,7 +99,7 @@ INTERCEPTOR(int, getvfsstat, void *buf, SIZE_T bufsize, int flags) {
9999INTERCEPTOR(int, statvfs1, const char *path, void *buf, int flags) {
100100 void *ctx;
101101 COMMON_INTERCEPTOR_ENTER(ctx, statvfs1, path, buf, flags);
102 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
102 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
103103 int res = REAL(statvfs1)(path, buf, flags);
104104 if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs90_sz);
105105 return res;
lib/tsan/sanitizer_common/sanitizer_common_interface.inc+10
......@@ -9,12 +9,16 @@
99//===----------------------------------------------------------------------===//
1010INTERFACE_FUNCTION(__sanitizer_acquire_crash_state)
1111INTERFACE_FUNCTION(__sanitizer_annotate_contiguous_container)
12INTERFACE_FUNCTION(__sanitizer_annotate_double_ended_contiguous_container)
1213INTERFACE_FUNCTION(__sanitizer_contiguous_container_find_bad_address)
14INTERFACE_FUNCTION(
15 __sanitizer_double_ended_contiguous_container_find_bad_address)
1316INTERFACE_FUNCTION(__sanitizer_set_death_callback)
1417INTERFACE_FUNCTION(__sanitizer_set_report_path)
1518INTERFACE_FUNCTION(__sanitizer_set_report_fd)
1619INTERFACE_FUNCTION(__sanitizer_get_report_path)
1720INTERFACE_FUNCTION(__sanitizer_verify_contiguous_container)
21INTERFACE_FUNCTION(__sanitizer_verify_double_ended_contiguous_container)
1822INTERFACE_WEAK_FUNCTION(__sanitizer_on_print)
1923INTERFACE_WEAK_FUNCTION(__sanitizer_report_error_summary)
2024INTERFACE_WEAK_FUNCTION(__sanitizer_sandbox_on_notify)
......@@ -28,7 +32,9 @@ INTERFACE_FUNCTION(__sanitizer_get_module_and_offset_for_pc)
2832INTERFACE_FUNCTION(__sanitizer_symbolize_global)
2933INTERFACE_FUNCTION(__sanitizer_symbolize_pc)
3034// Allocator interface.
35INTERFACE_FUNCTION(__sanitizer_get_allocated_begin)
3136INTERFACE_FUNCTION(__sanitizer_get_allocated_size)
37INTERFACE_FUNCTION(__sanitizer_get_allocated_size_fast)
3238INTERFACE_FUNCTION(__sanitizer_get_current_allocated_bytes)
3339INTERFACE_FUNCTION(__sanitizer_get_estimated_allocated_size)
3440INTERFACE_FUNCTION(__sanitizer_get_free_bytes)
......@@ -40,3 +46,7 @@ INTERFACE_FUNCTION(__sanitizer_purge_allocator)
4046INTERFACE_FUNCTION(__sanitizer_print_memory_profile)
4147INTERFACE_WEAK_FUNCTION(__sanitizer_free_hook)
4248INTERFACE_WEAK_FUNCTION(__sanitizer_malloc_hook)
49// Memintrinsic functions.
50INTERFACE_FUNCTION(__sanitizer_internal_memcpy)
51INTERFACE_FUNCTION(__sanitizer_internal_memmove)
52INTERFACE_FUNCTION(__sanitizer_internal_memset)
lib/tsan/sanitizer_common/sanitizer_common_interface_posix.inc+2
......@@ -11,3 +11,5 @@ INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_code)
1111INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_data)
1212INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_demangle)
1313INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_flush)
14INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_set_demangle)
15INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_set_inline_frames)
lib/tsan/sanitizer_common/sanitizer_common_libcdep.cpp+63-36
......@@ -10,27 +10,22 @@
1010// run-time libraries.
1111//===----------------------------------------------------------------------===//
1212
13#include "sanitizer_allocator.h"
1314#include "sanitizer_allocator_interface.h"
1415#include "sanitizer_common.h"
1516#include "sanitizer_flags.h"
17#include "sanitizer_interface_internal.h"
1618#include "sanitizer_procmaps.h"
17
19#include "sanitizer_stackdepot.h"
1820
1921namespace __sanitizer {
2022
21static void (*SoftRssLimitExceededCallback)(bool exceeded);
22void SetSoftRssLimitExceededCallback(void (*Callback)(bool exceeded)) {
23 CHECK_EQ(SoftRssLimitExceededCallback, nullptr);
24 SoftRssLimitExceededCallback = Callback;
25}
26
2723#if (SANITIZER_LINUX || SANITIZER_NETBSD) && !SANITIZER_GO
2824// Weak default implementation for when sanitizer_stackdepot is not linked in.
29SANITIZER_WEAK_ATTRIBUTE StackDepotStats *StackDepotGetStats() {
30 return nullptr;
31}
25SANITIZER_WEAK_ATTRIBUTE StackDepotStats StackDepotGetStats() { return {}; }
3226
3327void *BackgroundThread(void *arg) {
28 VPrintf(1, "%s: Started BackgroundThread\n", SanitizerToolName);
3429 const uptr hard_rss_limit_mb = common_flags()->hard_rss_limit_mb;
3530 const uptr soft_rss_limit_mb = common_flags()->soft_rss_limit_mb;
3631 const bool heap_profile = common_flags()->heap_profile;
......@@ -48,16 +43,12 @@ void *BackgroundThread(void *arg) {
4843 prev_reported_rss = current_rss_mb;
4944 }
5045 // If stack depot has grown 10% since last time, print it too.
51 StackDepotStats *stack_depot_stats = StackDepotGetStats();
52 if (stack_depot_stats) {
53 if (prev_reported_stack_depot_size * 11 / 10 <
54 stack_depot_stats->allocated) {
55 Printf("%s: StackDepot: %zd ids; %zdM allocated\n",
56 SanitizerToolName,
57 stack_depot_stats->n_uniq_ids,
58 stack_depot_stats->allocated >> 20);
59 prev_reported_stack_depot_size = stack_depot_stats->allocated;
60 }
46 StackDepotStats stack_depot_stats = StackDepotGetStats();
47 if (prev_reported_stack_depot_size * 11 / 10 <
48 stack_depot_stats.allocated) {
49 Printf("%s: StackDepot: %zd ids; %zdM allocated\n", SanitizerToolName,
50 stack_depot_stats.n_uniq_ids, stack_depot_stats.allocated >> 20);
51 prev_reported_stack_depot_size = stack_depot_stats.allocated;
6152 }
6253 }
6354 // Check RSS against the limit.
......@@ -72,13 +63,13 @@ void *BackgroundThread(void *arg) {
7263 reached_soft_rss_limit = true;
7364 Report("%s: soft rss limit exhausted (%zdMb vs %zdMb)\n",
7465 SanitizerToolName, soft_rss_limit_mb, current_rss_mb);
75 if (SoftRssLimitExceededCallback)
76 SoftRssLimitExceededCallback(true);
66 SetRssLimitExceeded(true);
7767 } else if (soft_rss_limit_mb >= current_rss_mb &&
7868 reached_soft_rss_limit) {
7969 reached_soft_rss_limit = false;
80 if (SoftRssLimitExceededCallback)
81 SoftRssLimitExceededCallback(false);
70 Report("%s: soft rss limit unexhausted (%zdMb vs %zdMb)\n",
71 SanitizerToolName, soft_rss_limit_mb, current_rss_mb);
72 SetRssLimitExceeded(false);
8273 }
8374 }
8475 if (heap_profile &&
......@@ -89,6 +80,42 @@ void *BackgroundThread(void *arg) {
8980 }
9081 }
9182}
83
84void MaybeStartBackgroudThread() {
85 // Need to implement/test on other platforms.
86 // Start the background thread if one of the rss limits is given.
87 if (!common_flags()->hard_rss_limit_mb &&
88 !common_flags()->soft_rss_limit_mb &&
89 !common_flags()->heap_profile) return;
90 if (!&real_pthread_create) {
91 VPrintf(1, "%s: real_pthread_create undefined\n", SanitizerToolName);
92 return; // Can't spawn the thread anyway.
93 }
94
95 static bool started = false;
96 if (!started) {
97 started = true;
98 internal_start_thread(BackgroundThread, nullptr);
99 }
100}
101
102# if !SANITIZER_START_BACKGROUND_THREAD_IN_ASAN_INTERNAL
103# ifdef __clang__
104# pragma clang diagnostic push
105// We avoid global-constructors to be sure that globals are ready when
106// sanitizers need them. This can happend before global constructors executed.
107// Here we don't mind if thread is started on later stages.
108# pragma clang diagnostic ignored "-Wglobal-constructors"
109# endif
110static struct BackgroudThreadStarted {
111 BackgroudThreadStarted() { MaybeStartBackgroudThread(); }
112} background_thread_strarter UNUSED;
113# ifdef __clang__
114# pragma clang diagnostic pop
115# endif
116# endif
117#else
118void MaybeStartBackgroudThread() {}
92119#endif
93120
94121void WriteToSyslog(const char *msg) {
......@@ -111,18 +138,6 @@ void WriteToSyslog(const char *msg) {
111138 WriteOneLineToSyslog(p);
112139}
113140
114void MaybeStartBackgroudThread() {
115#if (SANITIZER_LINUX || SANITIZER_NETBSD) && \
116 !SANITIZER_GO // Need to implement/test on other platforms.
117 // Start the background thread if one of the rss limits is given.
118 if (!common_flags()->hard_rss_limit_mb &&
119 !common_flags()->soft_rss_limit_mb &&
120 !common_flags()->heap_profile) return;
121 if (!&real_pthread_create) return; // Can't spawn the thread anyway.
122 internal_start_thread(BackgroundThread, nullptr);
123#endif
124}
125
126141static void (*sandboxing_callback)();
127142void SetSandboxingCallback(void (*f)()) {
128143 sandboxing_callback = f;
......@@ -191,10 +206,22 @@ void ProtectGap(uptr addr, uptr size, uptr zero_base_shadow_start,
191206
192207#endif // !SANITIZER_FUCHSIA
193208
209#if !SANITIZER_WINDOWS && !SANITIZER_GO
210// Weak default implementation for when sanitizer_stackdepot is not linked in.
211SANITIZER_WEAK_ATTRIBUTE void StackDepotStopBackgroundThread() {}
212static void StopStackDepotBackgroundThread() {
213 StackDepotStopBackgroundThread();
214}
215#else
216// SANITIZER_WEAK_ATTRIBUTE is unsupported.
217static void StopStackDepotBackgroundThread() {}
218#endif
219
194220} // namespace __sanitizer
195221
196222SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_sandbox_on_notify,
197223 __sanitizer_sandbox_arguments *args) {
224 __sanitizer::StopStackDepotBackgroundThread();
198225 __sanitizer::PlatformPrepareForSandboxing(args);
199226 if (__sanitizer::sandboxing_callback)
200227 __sanitizer::sandboxing_callback();
lib/tsan/sanitizer_common/sanitizer_common_nolibc.cpp+2-1
......@@ -25,9 +25,10 @@ void LogMessageOnPrintf(const char *str) {}
2525#endif
2626void WriteToSyslog(const char *buffer) {}
2727void Abort() { internal__exit(1); }
28bool CreateDir(const char *pathname) { return false; }
2829#endif // !SANITIZER_WINDOWS
2930
30#if !SANITIZER_WINDOWS && !SANITIZER_MAC
31#if !SANITIZER_WINDOWS && !SANITIZER_APPLE
3132void ListOfModules::init() {}
3233void InitializePlatformCommonFlags(CommonFlags *cf) {}
3334#endif
lib/tsan/sanitizer_common/sanitizer_common_syscalls.inc+921-658
......@@ -43,45 +43,47 @@
4343#include "sanitizer_platform.h"
4444#if SANITIZER_LINUX
4545
46#include "sanitizer_libc.h"
46# include "sanitizer_libc.h"
4747
48#define PRE_SYSCALL(name) \
49 SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_syscall_pre_impl_##name
50#define PRE_READ(p, s) COMMON_SYSCALL_PRE_READ_RANGE(p, s)
51#define PRE_WRITE(p, s) COMMON_SYSCALL_PRE_WRITE_RANGE(p, s)
48# define PRE_SYSCALL(name) \
49 SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_syscall_pre_impl_##name
50# define PRE_READ(p, s) COMMON_SYSCALL_PRE_READ_RANGE(p, s)
51# define PRE_WRITE(p, s) COMMON_SYSCALL_PRE_WRITE_RANGE(p, s)
5252
53#define POST_SYSCALL(name) \
54 SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_syscall_post_impl_##name
55#define POST_READ(p, s) COMMON_SYSCALL_POST_READ_RANGE(p, s)
56#define POST_WRITE(p, s) COMMON_SYSCALL_POST_WRITE_RANGE(p, s)
53# define POST_SYSCALL(name) \
54 SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_syscall_post_impl_##name
55# define POST_READ(p, s) COMMON_SYSCALL_POST_READ_RANGE(p, s)
56# define POST_WRITE(p, s) COMMON_SYSCALL_POST_WRITE_RANGE(p, s)
5757
58#ifndef COMMON_SYSCALL_ACQUIRE
59# define COMMON_SYSCALL_ACQUIRE(addr) ((void)(addr))
60#endif
58# ifndef COMMON_SYSCALL_ACQUIRE
59# define COMMON_SYSCALL_ACQUIRE(addr) ((void)(addr))
60# endif
6161
62#ifndef COMMON_SYSCALL_RELEASE
63# define COMMON_SYSCALL_RELEASE(addr) ((void)(addr))
64#endif
62# ifndef COMMON_SYSCALL_RELEASE
63# define COMMON_SYSCALL_RELEASE(addr) ((void)(addr))
64# endif
6565
66#ifndef COMMON_SYSCALL_FD_CLOSE
67# define COMMON_SYSCALL_FD_CLOSE(fd) ((void)(fd))
68#endif
66# ifndef COMMON_SYSCALL_FD_CLOSE
67# define COMMON_SYSCALL_FD_CLOSE(fd) ((void)(fd))
68# endif
6969
70#ifndef COMMON_SYSCALL_FD_ACQUIRE
71# define COMMON_SYSCALL_FD_ACQUIRE(fd) ((void)(fd))
72#endif
70# ifndef COMMON_SYSCALL_FD_ACQUIRE
71# define COMMON_SYSCALL_FD_ACQUIRE(fd) ((void)(fd))
72# endif
7373
74#ifndef COMMON_SYSCALL_FD_RELEASE
75# define COMMON_SYSCALL_FD_RELEASE(fd) ((void)(fd))
76#endif
74# ifndef COMMON_SYSCALL_FD_RELEASE
75# define COMMON_SYSCALL_FD_RELEASE(fd) ((void)(fd))
76# endif
7777
78#ifndef COMMON_SYSCALL_PRE_FORK
79# define COMMON_SYSCALL_PRE_FORK() {}
80#endif
78# ifndef COMMON_SYSCALL_PRE_FORK
79# define COMMON_SYSCALL_PRE_FORK() \
80 {}
81# endif
8182
82#ifndef COMMON_SYSCALL_POST_FORK
83# define COMMON_SYSCALL_POST_FORK(res) {}
84#endif
83# ifndef COMMON_SYSCALL_POST_FORK
84# define COMMON_SYSCALL_POST_FORK(res) \
85 {}
86# endif
8587
8688// FIXME: do some kind of PRE_READ for all syscall arguments (int(s) and such).
8789
......@@ -130,8 +132,8 @@ struct sanitizer_kernel_sockaddr {
130132// Declare it "void" to catch sizeof(kernel_sigset_t).
131133typedef void kernel_sigset_t;
132134
133static void kernel_write_iovec(const __sanitizer_iovec *iovec,
134 SIZE_T iovlen, SIZE_T maxlen) {
135static void kernel_write_iovec(const __sanitizer_iovec *iovec, SIZE_T iovlen,
136 SIZE_T maxlen) {
135137 for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
136138 SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
137139 POST_WRITE(iovec[i].iov_base, sz);
......@@ -141,8 +143,8 @@ static void kernel_write_iovec(const __sanitizer_iovec *iovec,
141143
142144// This functions uses POST_READ, because it needs to run after syscall to know
143145// the real read range.
144static void kernel_read_iovec(const __sanitizer_iovec *iovec,
145 SIZE_T iovlen, SIZE_T maxlen) {
146static void kernel_read_iovec(const __sanitizer_iovec *iovec, SIZE_T iovlen,
147 SIZE_T maxlen) {
146148 POST_READ(iovec, sizeof(*iovec) * iovlen);
147149 for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
148150 SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
......@@ -155,8 +157,8 @@ PRE_SYSCALL(recvmsg)(long sockfd, sanitizer_kernel_msghdr *msg, long flags) {
155157 PRE_READ(msg, sizeof(*msg));
156158}
157159
158POST_SYSCALL(recvmsg)(long res, long sockfd, sanitizer_kernel_msghdr *msg,
159 long flags) {
160POST_SYSCALL(recvmsg)
161(long res, long sockfd, sanitizer_kernel_msghdr *msg, long flags) {
160162 if (res >= 0) {
161163 if (msg) {
162164 for (unsigned long i = 0; i < msg->msg_iovlen; ++i) {
......@@ -167,13 +169,14 @@ POST_SYSCALL(recvmsg)(long res, long sockfd, sanitizer_kernel_msghdr *msg,
167169 }
168170}
169171
170PRE_SYSCALL(recvmmsg)(long fd, sanitizer_kernel_mmsghdr *msg, long vlen,
171 long flags, void *timeout) {
172PRE_SYSCALL(recvmmsg)
173(long fd, sanitizer_kernel_mmsghdr *msg, long vlen, long flags, void *timeout) {
172174 PRE_READ(msg, vlen * sizeof(*msg));
173175}
174176
175POST_SYSCALL(recvmmsg)(long res, long fd, sanitizer_kernel_mmsghdr *msg,
176 long vlen, long flags, void *timeout) {
177POST_SYSCALL(recvmmsg)
178(long res, long fd, sanitizer_kernel_mmsghdr *msg, long vlen, long flags,
179 void *timeout) {
177180 if (res >= 0) {
178181 if (msg) {
179182 for (unsigned long i = 0; i < msg->msg_hdr.msg_iovlen; ++i) {
......@@ -183,7 +186,8 @@ POST_SYSCALL(recvmmsg)(long res, long fd, sanitizer_kernel_mmsghdr *msg,
183186 POST_WRITE(msg->msg_hdr.msg_control, msg->msg_hdr.msg_controllen);
184187 POST_WRITE(&msg->msg_len, sizeof(msg->msg_len));
185188 }
186 if (timeout) POST_WRITE(timeout, struct_timespec_sz);
189 if (timeout)
190 POST_WRITE(timeout, struct_timespec_sz);
187191 }
188192}
189193
......@@ -203,7 +207,8 @@ PRE_SYSCALL(time)(void *tloc) {}
203207
204208POST_SYSCALL(time)(long res, void *tloc) {
205209 if (res >= 0) {
206 if (tloc) POST_WRITE(tloc, sizeof(long));
210 if (tloc)
211 POST_WRITE(tloc, sizeof(long));
207212 }
208213}
209214
......@@ -211,7 +216,8 @@ PRE_SYSCALL(stime)(void *tptr) {}
211216
212217POST_SYSCALL(stime)(long res, void *tptr) {
213218 if (res >= 0) {
214 if (tptr) POST_WRITE(tptr, sizeof(long));
219 if (tptr)
220 POST_WRITE(tptr, sizeof(long));
215221 }
216222}
217223
......@@ -219,8 +225,10 @@ PRE_SYSCALL(gettimeofday)(void *tv, void *tz) {}
219225
220226POST_SYSCALL(gettimeofday)(long res, void *tv, void *tz) {
221227 if (res >= 0) {
222 if (tv) POST_WRITE(tv, timeval_sz);
223 if (tz) POST_WRITE(tz, struct_timezone_sz);
228 if (tv)
229 POST_WRITE(tv, timeval_sz);
230 if (tz)
231 POST_WRITE(tz, struct_timezone_sz);
224232 }
225233}
226234
......@@ -228,26 +236,30 @@ PRE_SYSCALL(settimeofday)(void *tv, void *tz) {}
228236
229237POST_SYSCALL(settimeofday)(long res, void *tv, void *tz) {
230238 if (res >= 0) {
231 if (tv) POST_WRITE(tv, timeval_sz);
232 if (tz) POST_WRITE(tz, struct_timezone_sz);
239 if (tv)
240 POST_WRITE(tv, timeval_sz);
241 if (tz)
242 POST_WRITE(tz, struct_timezone_sz);
233243 }
234244}
235245
236#if !SANITIZER_ANDROID
246# if !SANITIZER_ANDROID
237247PRE_SYSCALL(adjtimex)(void *txc_p) {}
238248
239249POST_SYSCALL(adjtimex)(long res, void *txc_p) {
240250 if (res >= 0) {
241 if (txc_p) POST_WRITE(txc_p, struct_timex_sz);
251 if (txc_p)
252 POST_WRITE(txc_p, struct_timex_sz);
242253 }
243254}
244#endif
255# endif
245256
246257PRE_SYSCALL(times)(void *tbuf) {}
247258
248259POST_SYSCALL(times)(long res, void *tbuf) {
249260 if (res >= 0) {
250 if (tbuf) POST_WRITE(tbuf, struct_tms_sz);
261 if (tbuf)
262 POST_WRITE(tbuf, struct_tms_sz);
251263 }
252264}
253265
......@@ -259,8 +271,10 @@ PRE_SYSCALL(nanosleep)(void *rqtp, void *rmtp) {}
259271
260272POST_SYSCALL(nanosleep)(long res, void *rqtp, void *rmtp) {
261273 if (res >= 0) {
262 if (rqtp) POST_WRITE(rqtp, struct_timespec_sz);
263 if (rmtp) POST_WRITE(rmtp, struct_timespec_sz);
274 if (rqtp)
275 POST_WRITE(rqtp, struct_timespec_sz);
276 if (rmtp)
277 POST_WRITE(rmtp, struct_timespec_sz);
264278 }
265279}
266280
......@@ -296,9 +310,12 @@ PRE_SYSCALL(getresuid)(void *ruid, void *euid, void *suid) {}
296310
297311POST_SYSCALL(getresuid)(long res, void *ruid, void *euid, void *suid) {
298312 if (res >= 0) {
299 if (ruid) POST_WRITE(ruid, sizeof(unsigned));
300 if (euid) POST_WRITE(euid, sizeof(unsigned));
301 if (suid) POST_WRITE(suid, sizeof(unsigned));
313 if (ruid)
314 POST_WRITE(ruid, sizeof(unsigned));
315 if (euid)
316 POST_WRITE(euid, sizeof(unsigned));
317 if (suid)
318 POST_WRITE(suid, sizeof(unsigned));
302319 }
303320}
304321
......@@ -306,9 +323,12 @@ PRE_SYSCALL(getresgid)(void *rgid, void *egid, void *sgid) {}
306323
307324POST_SYSCALL(getresgid)(long res, void *rgid, void *egid, void *sgid) {
308325 if (res >= 0) {
309 if (rgid) POST_WRITE(rgid, sizeof(unsigned));
310 if (egid) POST_WRITE(egid, sizeof(unsigned));
311 if (sgid) POST_WRITE(sgid, sizeof(unsigned));
326 if (rgid)
327 POST_WRITE(rgid, sizeof(unsigned));
328 if (egid)
329 POST_WRITE(egid, sizeof(unsigned));
330 if (sgid)
331 POST_WRITE(sgid, sizeof(unsigned));
312332 }
313333}
314334
......@@ -326,10 +346,11 @@ POST_SYSCALL(getsid)(long res, long pid) {}
326346
327347PRE_SYSCALL(getgroups)(long gidsetsize, void *grouplist) {}
328348
329POST_SYSCALL(getgroups)(long res, long gidsetsize,
330 __sanitizer___kernel_gid_t *grouplist) {
349POST_SYSCALL(getgroups)
350(long res, long gidsetsize, __sanitizer___kernel_gid_t *grouplist) {
331351 if (res >= 0) {
332 if (grouplist) POST_WRITE(grouplist, res * sizeof(*grouplist));
352 if (grouplist)
353 POST_WRITE(grouplist, res * sizeof(*grouplist));
333354 }
334355}
335356
......@@ -374,11 +395,12 @@ PRE_SYSCALL(setsid)() {}
374395POST_SYSCALL(setsid)(long res) {}
375396
376397PRE_SYSCALL(setgroups)(long gidsetsize, __sanitizer___kernel_gid_t *grouplist) {
377 if (grouplist) POST_WRITE(grouplist, gidsetsize * sizeof(*grouplist));
398 if (grouplist)
399 POST_WRITE(grouplist, gidsetsize * sizeof(*grouplist));
378400}
379401
380POST_SYSCALL(setgroups)(long res, long gidsetsize,
381 __sanitizer___kernel_gid_t *grouplist) {}
402POST_SYSCALL(setgroups)
403(long res, long gidsetsize, __sanitizer___kernel_gid_t *grouplist) {}
382404
383405PRE_SYSCALL(acct)(const void *name) {
384406 if (name)
......@@ -388,17 +410,21 @@ PRE_SYSCALL(acct)(const void *name) {
388410POST_SYSCALL(acct)(long res, const void *name) {}
389411
390412PRE_SYSCALL(capget)(void *header, void *dataptr) {
391 if (header) PRE_READ(header, __user_cap_header_struct_sz);
413 if (header)
414 PRE_READ(header, __user_cap_header_struct_sz);
392415}
393416
394417POST_SYSCALL(capget)(long res, void *header, void *dataptr) {
395418 if (res >= 0)
396 if (dataptr) POST_WRITE(dataptr, __user_cap_data_struct_sz);
419 if (dataptr)
420 POST_WRITE(dataptr, __user_cap_data_struct_sz(header));
397421}
398422
399423PRE_SYSCALL(capset)(void *header, const void *data) {
400 if (header) PRE_READ(header, __user_cap_header_struct_sz);
401 if (data) PRE_READ(data, __user_cap_data_struct_sz);
424 if (header)
425 PRE_READ(header, __user_cap_header_struct_sz);
426 if (data)
427 PRE_READ(data, __user_cap_data_struct_sz(header));
402428}
403429
404430POST_SYSCALL(capset)(long res, void *header, const void *data) {}
......@@ -411,7 +437,8 @@ PRE_SYSCALL(sigpending)(void *set) {}
411437
412438POST_SYSCALL(sigpending)(long res, void *set) {
413439 if (res >= 0) {
414 if (set) POST_WRITE(set, old_sigset_t_sz);
440 if (set)
441 POST_WRITE(set, old_sigset_t_sz);
415442 }
416443}
417444
......@@ -419,8 +446,10 @@ PRE_SYSCALL(sigprocmask)(long how, void *set, void *oset) {}
419446
420447POST_SYSCALL(sigprocmask)(long res, long how, void *set, void *oset) {
421448 if (res >= 0) {
422 if (set) POST_WRITE(set, old_sigset_t_sz);
423 if (oset) POST_WRITE(oset, old_sigset_t_sz);
449 if (set)
450 POST_WRITE(set, old_sigset_t_sz);
451 if (oset)
452 POST_WRITE(oset, old_sigset_t_sz);
424453 }
425454}
426455
......@@ -428,7 +457,8 @@ PRE_SYSCALL(getitimer)(long which, void *value) {}
428457
429458POST_SYSCALL(getitimer)(long res, long which, void *value) {
430459 if (res >= 0) {
431 if (value) POST_WRITE(value, struct_itimerval_sz);
460 if (value)
461 POST_WRITE(value, struct_itimerval_sz);
432462 }
433463}
434464
......@@ -436,19 +466,23 @@ PRE_SYSCALL(setitimer)(long which, void *value, void *ovalue) {}
436466
437467POST_SYSCALL(setitimer)(long res, long which, void *value, void *ovalue) {
438468 if (res >= 0) {
439 if (value) POST_WRITE(value, struct_itimerval_sz);
440 if (ovalue) POST_WRITE(ovalue, struct_itimerval_sz);
469 if (value)
470 POST_WRITE(value, struct_itimerval_sz);
471 if (ovalue)
472 POST_WRITE(ovalue, struct_itimerval_sz);
441473 }
442474}
443475
444PRE_SYSCALL(timer_create)(long which_clock, void *timer_event_spec,
445 void *created_timer_id) {}
476PRE_SYSCALL(timer_create)
477(long which_clock, void *timer_event_spec, void *created_timer_id) {}
446478
447POST_SYSCALL(timer_create)(long res, long which_clock, void *timer_event_spec,
448 void *created_timer_id) {
479POST_SYSCALL(timer_create)
480(long res, long which_clock, void *timer_event_spec, void *created_timer_id) {
449481 if (res >= 0) {
450 if (timer_event_spec) POST_WRITE(timer_event_spec, struct_sigevent_sz);
451 if (created_timer_id) POST_WRITE(created_timer_id, sizeof(long));
482 if (timer_event_spec)
483 POST_WRITE(timer_event_spec, struct_sigevent_sz);
484 if (created_timer_id)
485 POST_WRITE(created_timer_id, sizeof(long));
452486 }
453487}
454488
......@@ -456,7 +490,8 @@ PRE_SYSCALL(timer_gettime)(long timer_id, void *setting) {}
456490
457491POST_SYSCALL(timer_gettime)(long res, long timer_id, void *setting) {
458492 if (res >= 0) {
459 if (setting) POST_WRITE(setting, struct_itimerspec_sz);
493 if (setting)
494 POST_WRITE(setting, struct_itimerspec_sz);
460495 }
461496}
462497
......@@ -464,15 +499,18 @@ PRE_SYSCALL(timer_getoverrun)(long timer_id) {}
464499
465500POST_SYSCALL(timer_getoverrun)(long res, long timer_id) {}
466501
467PRE_SYSCALL(timer_settime)(long timer_id, long flags, const void *new_setting,
468 void *old_setting) {
469 if (new_setting) PRE_READ(new_setting, struct_itimerspec_sz);
502PRE_SYSCALL(timer_settime)
503(long timer_id, long flags, const void *new_setting, void *old_setting) {
504 if (new_setting)
505 PRE_READ(new_setting, struct_itimerspec_sz);
470506}
471507
472POST_SYSCALL(timer_settime)(long res, long timer_id, long flags,
473 const void *new_setting, void *old_setting) {
508POST_SYSCALL(timer_settime)
509(long res, long timer_id, long flags, const void *new_setting,
510 void *old_setting) {
474511 if (res >= 0) {
475 if (old_setting) POST_WRITE(old_setting, struct_itimerspec_sz);
512 if (old_setting)
513 POST_WRITE(old_setting, struct_itimerspec_sz);
476514 }
477515}
478516
......@@ -481,7 +519,8 @@ PRE_SYSCALL(timer_delete)(long timer_id) {}
481519POST_SYSCALL(timer_delete)(long res, long timer_id) {}
482520
483521PRE_SYSCALL(clock_settime)(long which_clock, const void *tp) {
484 if (tp) PRE_READ(tp, struct_timespec_sz);
522 if (tp)
523 PRE_READ(tp, struct_timespec_sz);
485524}
486525
487526POST_SYSCALL(clock_settime)(long res, long which_clock, const void *tp) {}
......@@ -490,37 +529,42 @@ PRE_SYSCALL(clock_gettime)(long which_clock, void *tp) {}
490529
491530POST_SYSCALL(clock_gettime)(long res, long which_clock, void *tp) {
492531 if (res >= 0) {
493 if (tp) POST_WRITE(tp, struct_timespec_sz);
532 if (tp)
533 POST_WRITE(tp, struct_timespec_sz);
494534 }
495535}
496536
497#if !SANITIZER_ANDROID
537# if !SANITIZER_ANDROID
498538PRE_SYSCALL(clock_adjtime)(long which_clock, void *tx) {}
499539
500540POST_SYSCALL(clock_adjtime)(long res, long which_clock, void *tx) {
501541 if (res >= 0) {
502 if (tx) POST_WRITE(tx, struct_timex_sz);
542 if (tx)
543 POST_WRITE(tx, struct_timex_sz);
503544 }
504545}
505#endif
546# endif
506547
507548PRE_SYSCALL(clock_getres)(long which_clock, void *tp) {}
508549
509550POST_SYSCALL(clock_getres)(long res, long which_clock, void *tp) {
510551 if (res >= 0) {
511 if (tp) POST_WRITE(tp, struct_timespec_sz);
552 if (tp)
553 POST_WRITE(tp, struct_timespec_sz);
512554 }
513555}
514556
515PRE_SYSCALL(clock_nanosleep)(long which_clock, long flags, const void *rqtp,
516 void *rmtp) {
517 if (rqtp) PRE_READ(rqtp, struct_timespec_sz);
557PRE_SYSCALL(clock_nanosleep)
558(long which_clock, long flags, const void *rqtp, void *rmtp) {
559 if (rqtp)
560 PRE_READ(rqtp, struct_timespec_sz);
518561}
519562
520POST_SYSCALL(clock_nanosleep)(long res, long which_clock, long flags,
521 const void *rqtp, void *rmtp) {
563POST_SYSCALL(clock_nanosleep)
564(long res, long which_clock, long flags, const void *rqtp, void *rmtp) {
522565 if (res >= 0) {
523 if (rmtp) POST_WRITE(rmtp, struct_timespec_sz);
566 if (rmtp)
567 POST_WRITE(rmtp, struct_timespec_sz);
524568 }
525569}
526570
......@@ -532,12 +576,14 @@ PRE_SYSCALL(sched_setscheduler)(long pid, long policy, void *param) {}
532576
533577POST_SYSCALL(sched_setscheduler)(long res, long pid, long policy, void *param) {
534578 if (res >= 0) {
535 if (param) POST_WRITE(param, struct_sched_param_sz);
579 if (param)
580 POST_WRITE(param, struct_sched_param_sz);
536581 }
537582}
538583
539584PRE_SYSCALL(sched_setparam)(long pid, void *param) {
540 if (param) PRE_READ(param, struct_sched_param_sz);
585 if (param)
586 PRE_READ(param, struct_sched_param_sz);
541587}
542588
543589POST_SYSCALL(sched_setparam)(long res, long pid, void *param) {}
......@@ -550,23 +596,26 @@ PRE_SYSCALL(sched_getparam)(long pid, void *param) {}
550596
551597POST_SYSCALL(sched_getparam)(long res, long pid, void *param) {
552598 if (res >= 0) {
553 if (param) POST_WRITE(param, struct_sched_param_sz);
599 if (param)
600 POST_WRITE(param, struct_sched_param_sz);
554601 }
555602}
556603
557604PRE_SYSCALL(sched_setaffinity)(long pid, long len, void *user_mask_ptr) {
558 if (user_mask_ptr) PRE_READ(user_mask_ptr, len);
605 if (user_mask_ptr)
606 PRE_READ(user_mask_ptr, len);
559607}
560608
561POST_SYSCALL(sched_setaffinity)(long res, long pid, long len,
562 void *user_mask_ptr) {}
609POST_SYSCALL(sched_setaffinity)
610(long res, long pid, long len, void *user_mask_ptr) {}
563611
564612PRE_SYSCALL(sched_getaffinity)(long pid, long len, void *user_mask_ptr) {}
565613
566POST_SYSCALL(sched_getaffinity)(long res, long pid, long len,
567 void *user_mask_ptr) {
614POST_SYSCALL(sched_getaffinity)
615(long res, long pid, long len, void *user_mask_ptr) {
568616 if (res >= 0) {
569 if (user_mask_ptr) POST_WRITE(user_mask_ptr, len);
617 if (user_mask_ptr)
618 POST_WRITE(user_mask_ptr, len);
570619 }
571620}
572621
......@@ -586,7 +635,8 @@ PRE_SYSCALL(sched_rr_get_interval)(long pid, void *interval) {}
586635
587636POST_SYSCALL(sched_rr_get_interval)(long res, long pid, void *interval) {
588637 if (res >= 0) {
589 if (interval) POST_WRITE(interval, struct_timespec_sz);
638 if (interval)
639 POST_WRITE(interval, struct_timespec_sz);
590640 }
591641}
592642
......@@ -610,13 +660,14 @@ PRE_SYSCALL(restart_syscall)() {}
610660
611661POST_SYSCALL(restart_syscall)(long res) {}
612662
613PRE_SYSCALL(kexec_load)(long entry, long nr_segments, void *segments,
614 long flags) {}
663PRE_SYSCALL(kexec_load)
664(long entry, long nr_segments, void *segments, long flags) {}
615665
616POST_SYSCALL(kexec_load)(long res, long entry, long nr_segments, void *segments,
617 long flags) {
666POST_SYSCALL(kexec_load)
667(long res, long entry, long nr_segments, void *segments, long flags) {
618668 if (res >= 0) {
619 if (segments) POST_WRITE(segments, struct_kexec_segment_sz);
669 if (segments)
670 POST_WRITE(segments, struct_kexec_segment_sz);
620671 }
621672}
622673
......@@ -630,22 +681,26 @@ POST_SYSCALL(exit_group)(long res, long error_code) {}
630681
631682PRE_SYSCALL(wait4)(long pid, void *stat_addr, long options, void *ru) {}
632683
633POST_SYSCALL(wait4)(long res, long pid, void *stat_addr, long options,
634 void *ru) {
684POST_SYSCALL(wait4)
685(long res, long pid, void *stat_addr, long options, void *ru) {
635686 if (res >= 0) {
636 if (stat_addr) POST_WRITE(stat_addr, sizeof(int));
637 if (ru) POST_WRITE(ru, struct_rusage_sz);
687 if (stat_addr)
688 POST_WRITE(stat_addr, sizeof(int));
689 if (ru)
690 POST_WRITE(ru, struct_rusage_sz);
638691 }
639692}
640693
641PRE_SYSCALL(waitid)(long which, long pid, void *infop, long options, void *ru) {
642}
694PRE_SYSCALL(waitid)
695(long which, long pid, void *infop, long options, void *ru) {}
643696
644POST_SYSCALL(waitid)(long res, long which, long pid, void *infop, long options,
645 void *ru) {
697POST_SYSCALL(waitid)
698(long res, long which, long pid, void *infop, long options, void *ru) {
646699 if (res >= 0) {
647 if (infop) POST_WRITE(infop, siginfo_t_sz);
648 if (ru) POST_WRITE(ru, struct_rusage_sz);
700 if (infop)
701 POST_WRITE(infop, siginfo_t_sz);
702 if (ru)
703 POST_WRITE(ru, struct_rusage_sz);
649704 }
650705}
651706
......@@ -653,7 +708,8 @@ PRE_SYSCALL(waitpid)(long pid, void *stat_addr, long options) {}
653708
654709POST_SYSCALL(waitpid)(long res, long pid, void *stat_addr, long options) {
655710 if (res >= 0) {
656 if (stat_addr) POST_WRITE(stat_addr, sizeof(int));
711 if (stat_addr)
712 POST_WRITE(stat_addr, sizeof(int));
657713 }
658714}
659715
......@@ -661,7 +717,8 @@ PRE_SYSCALL(set_tid_address)(void *tidptr) {}
661717
662718POST_SYSCALL(set_tid_address)(long res, void *tidptr) {
663719 if (res >= 0) {
664 if (tidptr) POST_WRITE(tidptr, sizeof(int));
720 if (tidptr)
721 POST_WRITE(tidptr, sizeof(int));
665722 }
666723}
667724
......@@ -682,11 +739,14 @@ POST_SYSCALL(delete_module)(long res, const void *name_user, long flags) {}
682739
683740PRE_SYSCALL(rt_sigprocmask)(long how, void *set, void *oset, long sigsetsize) {}
684741
685POST_SYSCALL(rt_sigprocmask)(long res, long how, kernel_sigset_t *set,
686 kernel_sigset_t *oset, long sigsetsize) {
742POST_SYSCALL(rt_sigprocmask)
743(long res, long how, kernel_sigset_t *set, kernel_sigset_t *oset,
744 long sigsetsize) {
687745 if (res >= 0) {
688 if (set) POST_WRITE(set, sigsetsize);
689 if (oset) POST_WRITE(oset, sigsetsize);
746 if (set)
747 POST_WRITE(set, sigsetsize);
748 if (oset)
749 POST_WRITE(oset, sigsetsize);
690750 }
691751}
692752
......@@ -694,29 +754,34 @@ PRE_SYSCALL(rt_sigpending)(void *set, long sigsetsize) {}
694754
695755POST_SYSCALL(rt_sigpending)(long res, kernel_sigset_t *set, long sigsetsize) {
696756 if (res >= 0) {
697 if (set) POST_WRITE(set, sigsetsize);
757 if (set)
758 POST_WRITE(set, sigsetsize);
698759 }
699760}
700761
701PRE_SYSCALL(rt_sigtimedwait)(const kernel_sigset_t *uthese, void *uinfo,
702 const void *uts, long sigsetsize) {
703 if (uthese) PRE_READ(uthese, sigsetsize);
704 if (uts) PRE_READ(uts, struct_timespec_sz);
762PRE_SYSCALL(rt_sigtimedwait)
763(const kernel_sigset_t *uthese, void *uinfo, const void *uts, long sigsetsize) {
764 if (uthese)
765 PRE_READ(uthese, sigsetsize);
766 if (uts)
767 PRE_READ(uts, struct_timespec_sz);
705768}
706769
707POST_SYSCALL(rt_sigtimedwait)(long res, const void *uthese, void *uinfo,
708 const void *uts, long sigsetsize) {
770POST_SYSCALL(rt_sigtimedwait)
771(long res, const void *uthese, void *uinfo, const void *uts, long sigsetsize) {
709772 if (res >= 0) {
710 if (uinfo) POST_WRITE(uinfo, siginfo_t_sz);
773 if (uinfo)
774 POST_WRITE(uinfo, siginfo_t_sz);
711775 }
712776}
713777
714778PRE_SYSCALL(rt_tgsigqueueinfo)(long tgid, long pid, long sig, void *uinfo) {}
715779
716POST_SYSCALL(rt_tgsigqueueinfo)(long res, long tgid, long pid, long sig,
717 void *uinfo) {
780POST_SYSCALL(rt_tgsigqueueinfo)
781(long res, long tgid, long pid, long sig, void *uinfo) {
718782 if (res >= 0) {
719 if (uinfo) POST_WRITE(uinfo, siginfo_t_sz);
783 if (uinfo)
784 POST_WRITE(uinfo, siginfo_t_sz);
720785 }
721786}
722787
......@@ -736,7 +801,8 @@ PRE_SYSCALL(rt_sigqueueinfo)(long pid, long sig, void *uinfo) {}
736801
737802POST_SYSCALL(rt_sigqueueinfo)(long res, long pid, long sig, void *uinfo) {
738803 if (res >= 0) {
739 if (uinfo) POST_WRITE(uinfo, siginfo_t_sz);
804 if (uinfo)
805 POST_WRITE(uinfo, siginfo_t_sz);
740806 }
741807}
742808
......@@ -772,11 +838,11 @@ PRE_SYSCALL(bdflush)(long func, long data) {}
772838
773839POST_SYSCALL(bdflush)(long res, long func, long data) {}
774840
775PRE_SYSCALL(mount)(void *dev_name, void *dir_name, void *type, long flags,
776 void *data) {}
841PRE_SYSCALL(mount)
842(void *dev_name, void *dir_name, void *type, long flags, void *data) {}
777843
778POST_SYSCALL(mount)(long res, void *dev_name, void *dir_name, void *type,
779 long flags, void *data) {
844POST_SYSCALL(mount)
845(long res, void *dev_name, void *dir_name, void *type, long flags, void *data) {
780846 if (res >= 0) {
781847 if (dev_name)
782848 POST_WRITE(dev_name,
......@@ -826,11 +892,12 @@ PRE_SYSCALL(stat)(const void *filename, void *statbuf) {
826892
827893POST_SYSCALL(stat)(long res, const void *filename, void *statbuf) {
828894 if (res >= 0) {
829 if (statbuf) POST_WRITE(statbuf, struct___old_kernel_stat_sz);
895 if (statbuf)
896 POST_WRITE(statbuf, struct___old_kernel_stat_sz);
830897 }
831898}
832899
833#if !SANITIZER_ANDROID
900# if !SANITIZER_ANDROID
834901PRE_SYSCALL(statfs)(const void *path, void *buf) {
835902 if (path)
836903 PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
......@@ -838,26 +905,31 @@ PRE_SYSCALL(statfs)(const void *path, void *buf) {
838905
839906POST_SYSCALL(statfs)(long res, const void *path, void *buf) {
840907 if (res >= 0) {
841 if (buf) POST_WRITE(buf, struct_statfs_sz);
908 if (buf)
909 POST_WRITE(buf, struct_statfs_sz);
842910 }
843911}
844912
845PRE_SYSCALL(statfs64)(const void *path, long sz, void *buf) {
846 if (path)
847 PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
848}
913PRE_SYSCALL(fstatfs)(long fd, void *buf) {}
849914
850POST_SYSCALL(statfs64)(long res, const void *path, long sz, void *buf) {
915POST_SYSCALL(fstatfs)(long res, long fd, void *buf) {
851916 if (res >= 0) {
852 if (buf) POST_WRITE(buf, struct_statfs64_sz);
917 if (buf)
918 POST_WRITE(buf, struct_statfs_sz);
853919 }
854920}
921# endif // !SANITIZER_ANDROID
855922
856PRE_SYSCALL(fstatfs)(long fd, void *buf) {}
923# if SANITIZER_GLIBC
924PRE_SYSCALL(statfs64)(const void *path, long sz, void *buf) {
925 if (path)
926 PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
927}
857928
858POST_SYSCALL(fstatfs)(long res, long fd, void *buf) {
929POST_SYSCALL(statfs64)(long res, const void *path, long sz, void *buf) {
859930 if (res >= 0) {
860 if (buf) POST_WRITE(buf, struct_statfs_sz);
931 if (buf)
932 POST_WRITE(buf, struct_statfs64_sz);
861933 }
862934}
863935
......@@ -865,10 +937,11 @@ PRE_SYSCALL(fstatfs64)(long fd, long sz, void *buf) {}
865937
866938POST_SYSCALL(fstatfs64)(long res, long fd, long sz, void *buf) {
867939 if (res >= 0) {
868 if (buf) POST_WRITE(buf, struct_statfs64_sz);
940 if (buf)
941 POST_WRITE(buf, struct_statfs64_sz);
869942 }
870943}
871#endif // !SANITIZER_ANDROID
944# endif // SANITIZER_GLIBC
872945
873946PRE_SYSCALL(lstat)(const void *filename, void *statbuf) {
874947 if (filename)
......@@ -878,7 +951,8 @@ PRE_SYSCALL(lstat)(const void *filename, void *statbuf) {
878951
879952POST_SYSCALL(lstat)(long res, const void *filename, void *statbuf) {
880953 if (res >= 0) {
881 if (statbuf) POST_WRITE(statbuf, struct___old_kernel_stat_sz);
954 if (statbuf)
955 POST_WRITE(statbuf, struct___old_kernel_stat_sz);
882956 }
883957}
884958
......@@ -886,7 +960,8 @@ PRE_SYSCALL(fstat)(long fd, void *statbuf) {}
886960
887961POST_SYSCALL(fstat)(long res, long fd, void *statbuf) {
888962 if (res >= 0) {
889 if (statbuf) POST_WRITE(statbuf, struct___old_kernel_stat_sz);
963 if (statbuf)
964 POST_WRITE(statbuf, struct___old_kernel_stat_sz);
890965 }
891966}
892967
......@@ -898,7 +973,8 @@ PRE_SYSCALL(newstat)(const void *filename, void *statbuf) {
898973
899974POST_SYSCALL(newstat)(long res, const void *filename, void *statbuf) {
900975 if (res >= 0) {
901 if (statbuf) POST_WRITE(statbuf, struct_kernel_stat_sz);
976 if (statbuf)
977 POST_WRITE(statbuf, struct_kernel_stat_sz);
902978 }
903979}
904980
......@@ -910,7 +986,8 @@ PRE_SYSCALL(newlstat)(const void *filename, void *statbuf) {
910986
911987POST_SYSCALL(newlstat)(long res, const void *filename, void *statbuf) {
912988 if (res >= 0) {
913 if (statbuf) POST_WRITE(statbuf, struct_kernel_stat_sz);
989 if (statbuf)
990 POST_WRITE(statbuf, struct_kernel_stat_sz);
914991 }
915992}
916993
......@@ -918,19 +995,21 @@ PRE_SYSCALL(newfstat)(long fd, void *statbuf) {}
918995
919996POST_SYSCALL(newfstat)(long res, long fd, void *statbuf) {
920997 if (res >= 0) {
921 if (statbuf) POST_WRITE(statbuf, struct_kernel_stat_sz);
998 if (statbuf)
999 POST_WRITE(statbuf, struct_kernel_stat_sz);
9221000 }
9231001}
9241002
925#if !SANITIZER_ANDROID
1003# if SANITIZER_GLIBC
9261004PRE_SYSCALL(ustat)(long dev, void *ubuf) {}
9271005
9281006POST_SYSCALL(ustat)(long res, long dev, void *ubuf) {
9291007 if (res >= 0) {
930 if (ubuf) POST_WRITE(ubuf, struct_ustat_sz);
1008 if (ubuf)
1009 POST_WRITE(ubuf, struct_ustat_sz);
9311010 }
9321011}
933#endif // !SANITIZER_ANDROID
1012# endif // SANITIZER_GLIBC
9341013
9351014PRE_SYSCALL(stat64)(const void *filename, void *statbuf) {
9361015 if (filename)
......@@ -940,7 +1019,8 @@ PRE_SYSCALL(stat64)(const void *filename, void *statbuf) {
9401019
9411020POST_SYSCALL(stat64)(long res, const void *filename, void *statbuf) {
9421021 if (res >= 0) {
943 if (statbuf) POST_WRITE(statbuf, struct_kernel_stat64_sz);
1022 if (statbuf)
1023 POST_WRITE(statbuf, struct_kernel_stat64_sz);
9441024 }
9451025}
9461026
......@@ -948,7 +1028,8 @@ PRE_SYSCALL(fstat64)(long fd, void *statbuf) {}
9481028
9491029POST_SYSCALL(fstat64)(long res, long fd, void *statbuf) {
9501030 if (res >= 0) {
951 if (statbuf) POST_WRITE(statbuf, struct_kernel_stat64_sz);
1031 if (statbuf)
1032 POST_WRITE(statbuf, struct_kernel_stat64_sz);
9521033 }
9531034}
9541035
......@@ -960,71 +1041,80 @@ PRE_SYSCALL(lstat64)(const void *filename, void *statbuf) {
9601041
9611042POST_SYSCALL(lstat64)(long res, const void *filename, void *statbuf) {
9621043 if (res >= 0) {
963 if (statbuf) POST_WRITE(statbuf, struct_kernel_stat64_sz);
1044 if (statbuf)
1045 POST_WRITE(statbuf, struct_kernel_stat64_sz);
9641046 }
9651047}
9661048
967PRE_SYSCALL(setxattr)(const void *path, const void *name, const void *value,
968 long size, long flags) {
1049PRE_SYSCALL(setxattr)
1050(const void *path, const void *name, const void *value, long size, long flags) {
9691051 if (path)
9701052 PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
9711053 if (name)
9721054 PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
973 if (value) PRE_READ(value, size);
1055 if (value)
1056 PRE_READ(value, size);
9741057}
9751058
976POST_SYSCALL(setxattr)(long res, const void *path, const void *name,
977 const void *value, long size, long flags) {}
1059POST_SYSCALL(setxattr)
1060(long res, const void *path, const void *name, const void *value, long size,
1061 long flags) {}
9781062
979PRE_SYSCALL(lsetxattr)(const void *path, const void *name, const void *value,
980 long size, long flags) {
1063PRE_SYSCALL(lsetxattr)
1064(const void *path, const void *name, const void *value, long size, long flags) {
9811065 if (path)
9821066 PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
9831067 if (name)
9841068 PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
985 if (value) PRE_READ(value, size);
1069 if (value)
1070 PRE_READ(value, size);
9861071}
9871072
988POST_SYSCALL(lsetxattr)(long res, const void *path, const void *name,
989 const void *value, long size, long flags) {}
1073POST_SYSCALL(lsetxattr)
1074(long res, const void *path, const void *name, const void *value, long size,
1075 long flags) {}
9901076
991PRE_SYSCALL(fsetxattr)(long fd, const void *name, const void *value, long size,
992 long flags) {
1077PRE_SYSCALL(fsetxattr)
1078(long fd, const void *name, const void *value, long size, long flags) {
9931079 if (name)
9941080 PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
995 if (value) PRE_READ(value, size);
1081 if (value)
1082 PRE_READ(value, size);
9961083}
9971084
998POST_SYSCALL(fsetxattr)(long res, long fd, const void *name, const void *value,
999 long size, long flags) {}
1085POST_SYSCALL(fsetxattr)
1086(long res, long fd, const void *name, const void *value, long size,
1087 long flags) {}
10001088
1001PRE_SYSCALL(getxattr)(const void *path, const void *name, void *value,
1002 long size) {
1089PRE_SYSCALL(getxattr)
1090(const void *path, const void *name, void *value, long size) {
10031091 if (path)
10041092 PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
10051093 if (name)
10061094 PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
10071095}
10081096
1009POST_SYSCALL(getxattr)(long res, const void *path, const void *name,
1010 void *value, long size) {
1097POST_SYSCALL(getxattr)
1098(long res, const void *path, const void *name, void *value, long size) {
10111099 if (size && res > 0) {
1012 if (value) POST_WRITE(value, res);
1100 if (value)
1101 POST_WRITE(value, res);
10131102 }
10141103}
10151104
1016PRE_SYSCALL(lgetxattr)(const void *path, const void *name, void *value,
1017 long size) {
1105PRE_SYSCALL(lgetxattr)
1106(const void *path, const void *name, void *value, long size) {
10181107 if (path)
10191108 PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
10201109 if (name)
10211110 PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
10221111}
10231112
1024POST_SYSCALL(lgetxattr)(long res, const void *path, const void *name,
1025 void *value, long size) {
1113POST_SYSCALL(lgetxattr)
1114(long res, const void *path, const void *name, void *value, long size) {
10261115 if (size && res > 0) {
1027 if (value) POST_WRITE(value, res);
1116 if (value)
1117 POST_WRITE(value, res);
10281118 }
10291119}
10301120
......@@ -1033,10 +1123,11 @@ PRE_SYSCALL(fgetxattr)(long fd, const void *name, void *value, long size) {
10331123 PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
10341124}
10351125
1036POST_SYSCALL(fgetxattr)(long res, long fd, const void *name, void *value,
1037 long size) {
1126POST_SYSCALL(fgetxattr)
1127(long res, long fd, const void *name, void *value, long size) {
10381128 if (size && res > 0) {
1039 if (value) POST_WRITE(value, res);
1129 if (value)
1130 POST_WRITE(value, res);
10401131 }
10411132}
10421133
......@@ -1047,7 +1138,8 @@ PRE_SYSCALL(listxattr)(const void *path, void *list, long size) {
10471138
10481139POST_SYSCALL(listxattr)(long res, const void *path, void *list, long size) {
10491140 if (size && res > 0) {
1050 if (list) POST_WRITE(list, res);
1141 if (list)
1142 POST_WRITE(list, res);
10511143 }
10521144}
10531145
......@@ -1058,7 +1150,8 @@ PRE_SYSCALL(llistxattr)(const void *path, void *list, long size) {
10581150
10591151POST_SYSCALL(llistxattr)(long res, const void *path, void *list, long size) {
10601152 if (size && res > 0) {
1061 if (list) POST_WRITE(list, res);
1153 if (list)
1154 POST_WRITE(list, res);
10621155 }
10631156}
10641157
......@@ -1066,7 +1159,8 @@ PRE_SYSCALL(flistxattr)(long fd, void *list, long size) {}
10661159
10671160POST_SYSCALL(flistxattr)(long res, long fd, void *list, long size) {
10681161 if (size && res > 0) {
1069 if (list) POST_WRITE(list, res);
1162 if (list)
1163 POST_WRITE(list, res);
10701164 }
10711165}
10721166
......@@ -1103,17 +1197,17 @@ PRE_SYSCALL(mprotect)(long start, long len, long prot) {}
11031197
11041198POST_SYSCALL(mprotect)(long res, long start, long len, long prot) {}
11051199
1106PRE_SYSCALL(mremap)(long addr, long old_len, long new_len, long flags,
1107 long new_addr) {}
1200PRE_SYSCALL(mremap)
1201(long addr, long old_len, long new_len, long flags, long new_addr) {}
11081202
1109POST_SYSCALL(mremap)(long res, long addr, long old_len, long new_len,
1110 long flags, long new_addr) {}
1203POST_SYSCALL(mremap)
1204(long res, long addr, long old_len, long new_len, long flags, long new_addr) {}
11111205
1112PRE_SYSCALL(remap_file_pages)(long start, long size, long prot, long pgoff,
1113 long flags) {}
1206PRE_SYSCALL(remap_file_pages)
1207(long start, long size, long prot, long pgoff, long flags) {}
11141208
1115POST_SYSCALL(remap_file_pages)(long res, long start, long size, long prot,
1116 long pgoff, long flags) {}
1209POST_SYSCALL(remap_file_pages)
1210(long res, long start, long size, long prot, long pgoff, long flags) {}
11171211
11181212PRE_SYSCALL(msync)(long start, long len, long flags) {}
11191213
......@@ -1189,7 +1283,8 @@ PRE_SYSCALL(link)(const void *oldname, const void *newname) {
11891283POST_SYSCALL(link)(long res, const void *oldname, const void *newname) {}
11901284
11911285PRE_SYSCALL(symlink)(const void *old, const void *new_) {
1192 if (old) PRE_READ(old, __sanitizer::internal_strlen((const char *)old) + 1);
1286 if (old)
1287 PRE_READ(old, __sanitizer::internal_strlen((const char *)old) + 1);
11931288 if (new_)
11941289 PRE_READ(new_, __sanitizer::internal_strlen((const char *)new_) + 1);
11951290}
......@@ -1237,14 +1332,16 @@ PRE_SYSCALL(pipe)(void *fildes) {}
12371332
12381333POST_SYSCALL(pipe)(long res, void *fildes) {
12391334 if (res >= 0)
1240 if (fildes) POST_WRITE(fildes, sizeof(int) * 2);
1335 if (fildes)
1336 POST_WRITE(fildes, sizeof(int) * 2);
12411337}
12421338
12431339PRE_SYSCALL(pipe2)(void *fildes, long flags) {}
12441340
12451341POST_SYSCALL(pipe2)(long res, void *fildes, long flags) {
12461342 if (res >= 0)
1247 if (fildes) POST_WRITE(fildes, sizeof(int) * 2);
1343 if (fildes)
1344 POST_WRITE(fildes, sizeof(int) * 2);
12481345}
12491346
12501347PRE_SYSCALL(dup)(long fildes) {}
......@@ -1272,16 +1369,18 @@ PRE_SYSCALL(flock)(long fd, long cmd) {}
12721369POST_SYSCALL(flock)(long res, long fd, long cmd) {}
12731370
12741371PRE_SYSCALL(io_setup)(long nr_reqs, void **ctx) {
1275 if (ctx) PRE_WRITE(ctx, sizeof(*ctx));
1372 if (ctx)
1373 PRE_WRITE(ctx, sizeof(*ctx));
12761374}
12771375
12781376POST_SYSCALL(io_setup)(long res, long nr_reqs, void **ctx) {
1279 if (res >= 0) {
1280 if (ctx) POST_WRITE(ctx, sizeof(*ctx));
1377 if (res >= 0 && ctx) {
1378 POST_WRITE(ctx, sizeof(*ctx));
12811379 // (*ctx) is actually a pointer to a kernel mapped page, and there are
12821380 // people out there who are crazy enough to peek into that page's 32-byte
12831381 // header.
1284 if (*ctx) POST_WRITE(*ctx, 32);
1382 if (*ctx)
1383 POST_WRITE(*ctx, 32);
12851384 }
12861385}
12871386
......@@ -1289,16 +1388,21 @@ PRE_SYSCALL(io_destroy)(long ctx) {}
12891388
12901389POST_SYSCALL(io_destroy)(long res, long ctx) {}
12911390
1292PRE_SYSCALL(io_getevents)(long ctx_id, long min_nr, long nr,
1293 __sanitizer_io_event *ioevpp, void *timeout) {
1294 if (timeout) PRE_READ(timeout, struct_timespec_sz);
1391PRE_SYSCALL(io_getevents)
1392(long ctx_id, long min_nr, long nr, __sanitizer_io_event *ioevpp,
1393 void *timeout) {
1394 if (timeout)
1395 PRE_READ(timeout, struct_timespec_sz);
12951396}
12961397
1297POST_SYSCALL(io_getevents)(long res, long ctx_id, long min_nr, long nr,
1298 __sanitizer_io_event *ioevpp, void *timeout) {
1398POST_SYSCALL(io_getevents)
1399(long res, long ctx_id, long min_nr, long nr, __sanitizer_io_event *ioevpp,
1400 void *timeout) {
12991401 if (res >= 0) {
1300 if (ioevpp) POST_WRITE(ioevpp, res * sizeof(*ioevpp));
1301 if (timeout) POST_WRITE(timeout, struct_timespec_sz);
1402 if (ioevpp)
1403 POST_WRITE(ioevpp, res * sizeof(*ioevpp));
1404 if (timeout)
1405 POST_WRITE(timeout, struct_timespec_sz);
13021406 }
13031407 for (long i = 0; i < res; i++) {
13041408 // We synchronize io_submit -> io_getevents/io_cancel using the
......@@ -1308,26 +1412,26 @@ POST_SYSCALL(io_getevents)(long res, long ctx_id, long min_nr, long nr,
13081412 // synchronize on 0. But there does not seem to be a better solution
13091413 // (except wrapping all operations in own context, which is unreliable).
13101414 // We can not reliably extract fildes in io_getevents.
1311 COMMON_SYSCALL_ACQUIRE((void*)ioevpp[i].data);
1415 COMMON_SYSCALL_ACQUIRE((void *)ioevpp[i].data);
13121416 }
13131417}
13141418
13151419PRE_SYSCALL(io_submit)(long ctx_id, long nr, __sanitizer_iocb **iocbpp) {
13161420 for (long i = 0; i < nr; ++i) {
13171421 uptr op = iocbpp[i]->aio_lio_opcode;
1318 void *data = (void*)iocbpp[i]->aio_data;
1319 void *buf = (void*)iocbpp[i]->aio_buf;
1422 void *data = (void *)iocbpp[i]->aio_data;
1423 void *buf = (void *)iocbpp[i]->aio_buf;
13201424 uptr len = (uptr)iocbpp[i]->aio_nbytes;
13211425 if (op == iocb_cmd_pwrite && buf && len) {
13221426 PRE_READ(buf, len);
13231427 } else if (op == iocb_cmd_pread && buf && len) {
13241428 POST_WRITE(buf, len);
13251429 } else if (op == iocb_cmd_pwritev) {
1326 __sanitizer_iovec *iovec = (__sanitizer_iovec*)buf;
1430 __sanitizer_iovec *iovec = (__sanitizer_iovec *)buf;
13271431 for (uptr v = 0; v < len; v++)
13281432 PRE_READ(iovec[v].iov_base, iovec[v].iov_len);
13291433 } else if (op == iocb_cmd_preadv) {
1330 __sanitizer_iovec *iovec = (__sanitizer_iovec*)buf;
1434 __sanitizer_iovec *iovec = (__sanitizer_iovec *)buf;
13311435 for (uptr v = 0; v < len; v++)
13321436 POST_WRITE(iovec[v].iov_base, iovec[v].iov_len);
13331437 }
......@@ -1336,19 +1440,18 @@ PRE_SYSCALL(io_submit)(long ctx_id, long nr, __sanitizer_iocb **iocbpp) {
13361440 }
13371441}
13381442
1339POST_SYSCALL(io_submit)(long res, long ctx_id, long nr,
1340 __sanitizer_iocb **iocbpp) {}
1443POST_SYSCALL(io_submit)
1444(long res, long ctx_id, long nr, __sanitizer_iocb **iocbpp) {}
13411445
1342PRE_SYSCALL(io_cancel)(long ctx_id, __sanitizer_iocb *iocb,
1343 __sanitizer_io_event *result) {
1344}
1446PRE_SYSCALL(io_cancel)
1447(long ctx_id, __sanitizer_iocb *iocb, __sanitizer_io_event *result) {}
13451448
1346POST_SYSCALL(io_cancel)(long res, long ctx_id, __sanitizer_iocb *iocb,
1347 __sanitizer_io_event *result) {
1449POST_SYSCALL(io_cancel)
1450(long res, long ctx_id, __sanitizer_iocb *iocb, __sanitizer_io_event *result) {
13481451 if (res == 0) {
13491452 if (result) {
13501453 // See comment in io_getevents.
1351 COMMON_SYSCALL_ACQUIRE((void*)result->data);
1454 COMMON_SYSCALL_ACQUIRE((void *)result->data);
13521455 POST_WRITE(result, sizeof(*result));
13531456 }
13541457 if (iocb)
......@@ -1358,19 +1461,23 @@ POST_SYSCALL(io_cancel)(long res, long ctx_id, __sanitizer_iocb *iocb,
13581461
13591462PRE_SYSCALL(sendfile)(long out_fd, long in_fd, void *offset, long count) {}
13601463
1361POST_SYSCALL(sendfile)(long res, long out_fd, long in_fd,
1362 __sanitizer___kernel_off_t *offset, long count) {
1464POST_SYSCALL(sendfile)
1465(long res, long out_fd, long in_fd, __sanitizer___kernel_off_t *offset,
1466 long count) {
13631467 if (res >= 0) {
1364 if (offset) POST_WRITE(offset, sizeof(*offset));
1468 if (offset)
1469 POST_WRITE(offset, sizeof(*offset));
13651470 }
13661471}
13671472
13681473PRE_SYSCALL(sendfile64)(long out_fd, long in_fd, void *offset, long count) {}
13691474
1370POST_SYSCALL(sendfile64)(long res, long out_fd, long in_fd,
1371 __sanitizer___kernel_loff_t *offset, long count) {
1475POST_SYSCALL(sendfile64)
1476(long res, long out_fd, long in_fd, __sanitizer___kernel_loff_t *offset,
1477 long count) {
13721478 if (res >= 0) {
1373 if (offset) POST_WRITE(offset, sizeof(*offset));
1479 if (offset)
1480 POST_WRITE(offset, sizeof(*offset));
13741481 }
13751482}
13761483
......@@ -1402,9 +1509,7 @@ PRE_SYSCALL(open)(const void *filename, long flags, long mode) {
14021509
14031510POST_SYSCALL(open)(long res, const void *filename, long flags, long mode) {}
14041511
1405PRE_SYSCALL(close)(long fd) {
1406 COMMON_SYSCALL_FD_CLOSE((int)fd);
1407}
1512PRE_SYSCALL(close)(long fd) { COMMON_SYSCALL_FD_CLOSE((int)fd); }
14081513
14091514POST_SYSCALL(close)(long res, long fd) {}
14101515
......@@ -1440,7 +1545,7 @@ PRE_SYSCALL(fchown)(long fd, long user, long group) {}
14401545
14411546POST_SYSCALL(fchown)(long res, long fd, long user, long group) {}
14421547
1443#if SANITIZER_USES_UID16_SYSCALLS
1548# if SANITIZER_USES_UID16_SYSCALLS
14441549PRE_SYSCALL(chown16)(const void *filename, long user, long group) {
14451550 if (filename)
14461551 PRE_READ(filename,
......@@ -1483,13 +1588,16 @@ POST_SYSCALL(setresuid16)(long res, long ruid, long euid, long suid) {}
14831588
14841589PRE_SYSCALL(getresuid16)(void *ruid, void *euid, void *suid) {}
14851590
1486POST_SYSCALL(getresuid16)(long res, __sanitizer___kernel_old_uid_t *ruid,
1487 __sanitizer___kernel_old_uid_t *euid,
1488 __sanitizer___kernel_old_uid_t *suid) {
1591POST_SYSCALL(getresuid16)
1592(long res, __sanitizer___kernel_old_uid_t *ruid,
1593 __sanitizer___kernel_old_uid_t *euid, __sanitizer___kernel_old_uid_t *suid) {
14891594 if (res >= 0) {
1490 if (ruid) POST_WRITE(ruid, sizeof(*ruid));
1491 if (euid) POST_WRITE(euid, sizeof(*euid));
1492 if (suid) POST_WRITE(suid, sizeof(*suid));
1595 if (ruid)
1596 POST_WRITE(ruid, sizeof(*ruid));
1597 if (euid)
1598 POST_WRITE(euid, sizeof(*euid));
1599 if (suid)
1600 POST_WRITE(suid, sizeof(*suid));
14931601 }
14941602}
14951603
......@@ -1499,13 +1607,16 @@ POST_SYSCALL(setresgid16)(long res, long rgid, long egid, long sgid) {}
14991607
15001608PRE_SYSCALL(getresgid16)(void *rgid, void *egid, void *sgid) {}
15011609
1502POST_SYSCALL(getresgid16)(long res, __sanitizer___kernel_old_gid_t *rgid,
1503 __sanitizer___kernel_old_gid_t *egid,
1504 __sanitizer___kernel_old_gid_t *sgid) {
1610POST_SYSCALL(getresgid16)
1611(long res, __sanitizer___kernel_old_gid_t *rgid,
1612 __sanitizer___kernel_old_gid_t *egid, __sanitizer___kernel_old_gid_t *sgid) {
15051613 if (res >= 0) {
1506 if (rgid) POST_WRITE(rgid, sizeof(*rgid));
1507 if (egid) POST_WRITE(egid, sizeof(*egid));
1508 if (sgid) POST_WRITE(sgid, sizeof(*sgid));
1614 if (rgid)
1615 POST_WRITE(rgid, sizeof(*rgid));
1616 if (egid)
1617 POST_WRITE(egid, sizeof(*egid));
1618 if (sgid)
1619 POST_WRITE(sgid, sizeof(*sgid));
15091620 }
15101621}
15111622
......@@ -1517,23 +1628,25 @@ PRE_SYSCALL(setfsgid16)(long gid) {}
15171628
15181629POST_SYSCALL(setfsgid16)(long res, long gid) {}
15191630
1520PRE_SYSCALL(getgroups16)(long gidsetsize,
1521 __sanitizer___kernel_old_gid_t *grouplist) {}
1631PRE_SYSCALL(getgroups16)
1632(long gidsetsize, __sanitizer___kernel_old_gid_t *grouplist) {}
15221633
1523POST_SYSCALL(getgroups16)(long res, long gidsetsize,
1524 __sanitizer___kernel_old_gid_t *grouplist) {
1634POST_SYSCALL(getgroups16)
1635(long res, long gidsetsize, __sanitizer___kernel_old_gid_t *grouplist) {
15251636 if (res >= 0) {
1526 if (grouplist) POST_WRITE(grouplist, res * sizeof(*grouplist));
1637 if (grouplist)
1638 POST_WRITE(grouplist, res * sizeof(*grouplist));
15271639 }
15281640}
15291641
1530PRE_SYSCALL(setgroups16)(long gidsetsize,
1531 __sanitizer___kernel_old_gid_t *grouplist) {
1532 if (grouplist) POST_WRITE(grouplist, gidsetsize * sizeof(*grouplist));
1642PRE_SYSCALL(setgroups16)
1643(long gidsetsize, __sanitizer___kernel_old_gid_t *grouplist) {
1644 if (grouplist)
1645 POST_WRITE(grouplist, gidsetsize * sizeof(*grouplist));
15331646}
15341647
1535POST_SYSCALL(setgroups16)(long res, long gidsetsize,
1536 __sanitizer___kernel_old_gid_t *grouplist) {}
1648POST_SYSCALL(setgroups16)
1649(long res, long gidsetsize, __sanitizer___kernel_old_gid_t *grouplist) {}
15371650
15381651PRE_SYSCALL(getuid16)() {}
15391652
......@@ -1550,7 +1663,7 @@ POST_SYSCALL(getgid16)(long res) {}
15501663PRE_SYSCALL(getegid16)() {}
15511664
15521665POST_SYSCALL(getegid16)(long res) {}
1553#endif // SANITIZER_USES_UID16_SYSCALLS
1666# endif // SANITIZER_USES_UID16_SYSCALLS
15541667
15551668PRE_SYSCALL(utime)(void *filename, void *times) {}
15561669
......@@ -1559,7 +1672,8 @@ POST_SYSCALL(utime)(long res, void *filename, void *times) {
15591672 if (filename)
15601673 POST_WRITE(filename,
15611674 __sanitizer::internal_strlen((const char *)filename) + 1);
1562 if (times) POST_WRITE(times, struct_utimbuf_sz);
1675 if (times)
1676 POST_WRITE(times, struct_utimbuf_sz);
15631677 }
15641678}
15651679
......@@ -1570,7 +1684,8 @@ POST_SYSCALL(utimes)(long res, void *filename, void *utimes) {
15701684 if (filename)
15711685 POST_WRITE(filename,
15721686 __sanitizer::internal_strlen((const char *)filename) + 1);
1573 if (utimes) POST_WRITE(utimes, timeval_sz);
1687 if (utimes)
1688 POST_WRITE(utimes, timeval_sz);
15741689 }
15751690}
15761691
......@@ -1578,91 +1693,104 @@ PRE_SYSCALL(lseek)(long fd, long offset, long origin) {}
15781693
15791694POST_SYSCALL(lseek)(long res, long fd, long offset, long origin) {}
15801695
1581PRE_SYSCALL(llseek)(long fd, long offset_high, long offset_low, void *result,
1582 long origin) {}
1696PRE_SYSCALL(llseek)
1697(long fd, long offset_high, long offset_low, void *result, long origin) {}
15831698
1584POST_SYSCALL(llseek)(long res, long fd, long offset_high, long offset_low,
1585 void *result, long origin) {
1699POST_SYSCALL(llseek)
1700(long res, long fd, long offset_high, long offset_low, void *result,
1701 long origin) {
15861702 if (res >= 0) {
1587 if (result) POST_WRITE(result, sizeof(long long));
1703 if (result)
1704 POST_WRITE(result, sizeof(long long));
15881705 }
15891706}
15901707
15911708PRE_SYSCALL(readv)(long fd, const __sanitizer_iovec *vec, long vlen) {}
15921709
1593POST_SYSCALL(readv)(long res, long fd, const __sanitizer_iovec *vec,
1594 long vlen) {
1710POST_SYSCALL(readv)
1711(long res, long fd, const __sanitizer_iovec *vec, long vlen) {
15951712 if (res >= 0) {
1596 if (vec) kernel_write_iovec(vec, vlen, res);
1713 if (vec)
1714 kernel_write_iovec(vec, vlen, res);
15971715 }
15981716}
15991717
16001718PRE_SYSCALL(write)(long fd, const void *buf, long count) {
1601 if (buf) PRE_READ(buf, count);
1719 if (buf)
1720 PRE_READ(buf, count);
16021721}
16031722
16041723POST_SYSCALL(write)(long res, long fd, const void *buf, long count) {}
16051724
16061725PRE_SYSCALL(writev)(long fd, const __sanitizer_iovec *vec, long vlen) {}
16071726
1608POST_SYSCALL(writev)(long res, long fd, const __sanitizer_iovec *vec,
1609 long vlen) {
1727POST_SYSCALL(writev)
1728(long res, long fd, const __sanitizer_iovec *vec, long vlen) {
16101729 if (res >= 0) {
1611 if (vec) kernel_read_iovec(vec, vlen, res);
1730 if (vec)
1731 kernel_read_iovec(vec, vlen, res);
16121732 }
16131733}
16141734
1615#ifdef _LP64
1735# ifdef _LP64
16161736PRE_SYSCALL(pread64)(long fd, void *buf, long count, long pos) {}
16171737
16181738POST_SYSCALL(pread64)(long res, long fd, void *buf, long count, long pos) {
16191739 if (res >= 0) {
1620 if (buf) POST_WRITE(buf, res);
1740 if (buf)
1741 POST_WRITE(buf, res);
16211742 }
16221743}
16231744
16241745PRE_SYSCALL(pwrite64)(long fd, const void *buf, long count, long pos) {
1625 if (buf) PRE_READ(buf, count);
1746 if (buf)
1747 PRE_READ(buf, count);
16261748}
16271749
1628POST_SYSCALL(pwrite64)(long res, long fd, const void *buf, long count,
1629 long pos) {}
1630#else
1750POST_SYSCALL(pwrite64)
1751(long res, long fd, const void *buf, long count, long pos) {}
1752# else
16311753PRE_SYSCALL(pread64)(long fd, void *buf, long count, long pos0, long pos1) {}
16321754
1633POST_SYSCALL(pread64)(long res, long fd, void *buf, long count, long pos0,
1634 long pos1) {
1755POST_SYSCALL(pread64)
1756(long res, long fd, void *buf, long count, long pos0, long pos1) {
16351757 if (res >= 0) {
1636 if (buf) POST_WRITE(buf, res);
1758 if (buf)
1759 POST_WRITE(buf, res);
16371760 }
16381761}
16391762
1640PRE_SYSCALL(pwrite64)(long fd, const void *buf, long count, long pos0,
1641 long pos1) {
1642 if (buf) PRE_READ(buf, count);
1763PRE_SYSCALL(pwrite64)
1764(long fd, const void *buf, long count, long pos0, long pos1) {
1765 if (buf)
1766 PRE_READ(buf, count);
16431767}
16441768
1645POST_SYSCALL(pwrite64)(long res, long fd, const void *buf, long count,
1646 long pos0, long pos1) {}
1647#endif
1769POST_SYSCALL(pwrite64)
1770(long res, long fd, const void *buf, long count, long pos0, long pos1) {}
1771# endif
16481772
1649PRE_SYSCALL(preadv)(long fd, const __sanitizer_iovec *vec, long vlen,
1650 long pos_l, long pos_h) {}
1773PRE_SYSCALL(preadv)
1774(long fd, const __sanitizer_iovec *vec, long vlen, long pos_l, long pos_h) {}
16511775
1652POST_SYSCALL(preadv)(long res, long fd, const __sanitizer_iovec *vec, long vlen,
1653 long pos_l, long pos_h) {
1776POST_SYSCALL(preadv)
1777(long res, long fd, const __sanitizer_iovec *vec, long vlen, long pos_l,
1778 long pos_h) {
16541779 if (res >= 0) {
1655 if (vec) kernel_write_iovec(vec, vlen, res);
1780 if (vec)
1781 kernel_write_iovec(vec, vlen, res);
16561782 }
16571783}
16581784
1659PRE_SYSCALL(pwritev)(long fd, const __sanitizer_iovec *vec, long vlen,
1660 long pos_l, long pos_h) {}
1785PRE_SYSCALL(pwritev)
1786(long fd, const __sanitizer_iovec *vec, long vlen, long pos_l, long pos_h) {}
16611787
1662POST_SYSCALL(pwritev)(long res, long fd, const __sanitizer_iovec *vec,
1663 long vlen, long pos_l, long pos_h) {
1788POST_SYSCALL(pwritev)
1789(long res, long fd, const __sanitizer_iovec *vec, long vlen, long pos_l,
1790 long pos_h) {
16641791 if (res >= 0) {
1665 if (vec) kernel_read_iovec(vec, vlen, res);
1792 if (vec)
1793 kernel_read_iovec(vec, vlen, res);
16661794 }
16671795}
16681796
......@@ -1717,14 +1845,15 @@ PRE_SYSCALL(quotactl)(long cmd, const void *special, long id, void *addr) {
17171845 PRE_READ(special, __sanitizer::internal_strlen((const char *)special) + 1);
17181846}
17191847
1720POST_SYSCALL(quotactl)(long res, long cmd, const void *special, long id,
1721 void *addr) {}
1848POST_SYSCALL(quotactl)
1849(long res, long cmd, const void *special, long id, void *addr) {}
17221850
17231851PRE_SYSCALL(getdents)(long fd, void *dirent, long count) {}
17241852
17251853POST_SYSCALL(getdents)(long res, long fd, void *dirent, long count) {
17261854 if (res >= 0) {
1727 if (dirent) POST_WRITE(dirent, res);
1855 if (dirent)
1856 POST_WRITE(dirent, res);
17281857 }
17291858}
17301859
......@@ -1732,15 +1861,16 @@ PRE_SYSCALL(getdents64)(long fd, void *dirent, long count) {}
17321861
17331862POST_SYSCALL(getdents64)(long res, long fd, void *dirent, long count) {
17341863 if (res >= 0) {
1735 if (dirent) POST_WRITE(dirent, res);
1864 if (dirent)
1865 POST_WRITE(dirent, res);
17361866 }
17371867}
17381868
1739PRE_SYSCALL(setsockopt)(long fd, long level, long optname, void *optval,
1740 long optlen) {}
1869PRE_SYSCALL(setsockopt)
1870(long fd, long level, long optname, void *optval, long optlen) {}
17411871
1742POST_SYSCALL(setsockopt)(long res, long fd, long level, long optname,
1743 void *optval, long optlen) {
1872POST_SYSCALL(setsockopt)
1873(long res, long fd, long level, long optname, void *optval, long optlen) {
17441874 if (res >= 0) {
17451875 if (optval)
17461876 POST_WRITE(optval,
......@@ -1748,77 +1878,88 @@ POST_SYSCALL(setsockopt)(long res, long fd, long level, long optname,
17481878 }
17491879}
17501880
1751PRE_SYSCALL(getsockopt)(long fd, long level, long optname, void *optval,
1752 void *optlen) {}
1881PRE_SYSCALL(getsockopt)
1882(long fd, long level, long optname, void *optval, void *optlen) {}
17531883
1754POST_SYSCALL(getsockopt)(long res, long fd, long level, long optname,
1755 void *optval, void *optlen) {
1884POST_SYSCALL(getsockopt)
1885(long res, long fd, long level, long optname, void *optval, void *optlen) {
17561886 if (res >= 0) {
17571887 if (optval)
17581888 POST_WRITE(optval,
17591889 __sanitizer::internal_strlen((const char *)optval) + 1);
1760 if (optlen) POST_WRITE(optlen, sizeof(int));
1890 if (optlen)
1891 POST_WRITE(optlen, sizeof(int));
17611892 }
17621893}
17631894
17641895PRE_SYSCALL(bind)(long arg0, sanitizer_kernel_sockaddr *arg1, long arg2) {}
17651896
1766POST_SYSCALL(bind)(long res, long arg0, sanitizer_kernel_sockaddr *arg1,
1767 long arg2) {
1897POST_SYSCALL(bind)
1898(long res, long arg0, sanitizer_kernel_sockaddr *arg1, long arg2) {
17681899 if (res >= 0) {
1769 if (arg1) POST_WRITE(arg1, sizeof(*arg1));
1900 if (arg1)
1901 POST_WRITE(arg1, sizeof(*arg1));
17701902 }
17711903}
17721904
17731905PRE_SYSCALL(connect)(long arg0, sanitizer_kernel_sockaddr *arg1, long arg2) {}
17741906
1775POST_SYSCALL(connect)(long res, long arg0, sanitizer_kernel_sockaddr *arg1,
1776 long arg2) {
1907POST_SYSCALL(connect)
1908(long res, long arg0, sanitizer_kernel_sockaddr *arg1, long arg2) {
17771909 if (res >= 0) {
1778 if (arg1) POST_WRITE(arg1, sizeof(*arg1));
1910 if (arg1)
1911 POST_WRITE(arg1, sizeof(*arg1));
17791912 }
17801913}
17811914
17821915PRE_SYSCALL(accept)(long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2) {}
17831916
1784POST_SYSCALL(accept)(long res, long arg0, sanitizer_kernel_sockaddr *arg1,
1785 void *arg2) {
1917POST_SYSCALL(accept)
1918(long res, long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2) {
17861919 if (res >= 0) {
1787 if (arg1) POST_WRITE(arg1, sizeof(*arg1));
1788 if (arg2) POST_WRITE(arg2, sizeof(unsigned));
1920 if (arg1)
1921 POST_WRITE(arg1, sizeof(*arg1));
1922 if (arg2)
1923 POST_WRITE(arg2, sizeof(unsigned));
17891924 }
17901925}
17911926
1792PRE_SYSCALL(accept4)(long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2,
1793 long arg3) {}
1927PRE_SYSCALL(accept4)
1928(long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2, long arg3) {}
17941929
1795POST_SYSCALL(accept4)(long res, long arg0, sanitizer_kernel_sockaddr *arg1,
1796 void *arg2, long arg3) {
1930POST_SYSCALL(accept4)
1931(long res, long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2, long arg3) {
17971932 if (res >= 0) {
1798 if (arg1) POST_WRITE(arg1, sizeof(*arg1));
1799 if (arg2) POST_WRITE(arg2, sizeof(unsigned));
1933 if (arg1)
1934 POST_WRITE(arg1, sizeof(*arg1));
1935 if (arg2)
1936 POST_WRITE(arg2, sizeof(unsigned));
18001937 }
18011938}
18021939
1803PRE_SYSCALL(getsockname)(long arg0, sanitizer_kernel_sockaddr *arg1,
1804 void *arg2) {}
1940PRE_SYSCALL(getsockname)
1941(long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2) {}
18051942
1806POST_SYSCALL(getsockname)(long res, long arg0, sanitizer_kernel_sockaddr *arg1,
1807 void *arg2) {
1943POST_SYSCALL(getsockname)
1944(long res, long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2) {
18081945 if (res >= 0) {
1809 if (arg1) POST_WRITE(arg1, sizeof(*arg1));
1810 if (arg2) POST_WRITE(arg2, sizeof(unsigned));
1946 if (arg1)
1947 POST_WRITE(arg1, sizeof(*arg1));
1948 if (arg2)
1949 POST_WRITE(arg2, sizeof(unsigned));
18111950 }
18121951}
18131952
1814PRE_SYSCALL(getpeername)(long arg0, sanitizer_kernel_sockaddr *arg1,
1815 void *arg2) {}
1953PRE_SYSCALL(getpeername)
1954(long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2) {}
18161955
1817POST_SYSCALL(getpeername)(long res, long arg0, sanitizer_kernel_sockaddr *arg1,
1818 void *arg2) {
1956POST_SYSCALL(getpeername)
1957(long res, long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2) {
18191958 if (res >= 0) {
1820 if (arg1) POST_WRITE(arg1, sizeof(*arg1));
1821 if (arg2) POST_WRITE(arg2, sizeof(unsigned));
1959 if (arg1)
1960 POST_WRITE(arg1, sizeof(*arg1));
1961 if (arg2)
1962 POST_WRITE(arg2, sizeof(unsigned));
18221963 }
18231964}
18241965
......@@ -1826,18 +1967,23 @@ PRE_SYSCALL(send)(long arg0, void *arg1, long arg2, long arg3) {}
18261967
18271968POST_SYSCALL(send)(long res, long arg0, void *arg1, long arg2, long arg3) {
18281969 if (res) {
1829 if (arg1) POST_READ(arg1, res);
1970 if (arg1)
1971 POST_READ(arg1, res);
18301972 }
18311973}
18321974
1833PRE_SYSCALL(sendto)(long arg0, void *arg1, long arg2, long arg3,
1834 sanitizer_kernel_sockaddr *arg4, long arg5) {}
1975PRE_SYSCALL(sendto)
1976(long arg0, void *arg1, long arg2, long arg3, sanitizer_kernel_sockaddr *arg4,
1977 long arg5) {}
18351978
1836POST_SYSCALL(sendto)(long res, long arg0, void *arg1, long arg2, long arg3,
1837 sanitizer_kernel_sockaddr *arg4, long arg5) {
1979POST_SYSCALL(sendto)
1980(long res, long arg0, void *arg1, long arg2, long arg3,
1981 sanitizer_kernel_sockaddr *arg4, long arg5) {
18381982 if (res >= 0) {
1839 if (arg1) POST_READ(arg1, res);
1840 if (arg4) POST_WRITE(arg4, sizeof(*arg4));
1983 if (arg1)
1984 POST_READ(arg1, res);
1985 if (arg4)
1986 POST_WRITE(arg4, sizeof(*arg4));
18411987 }
18421988}
18431989
......@@ -1857,19 +2003,25 @@ PRE_SYSCALL(recv)(long arg0, void *buf, long len, long flags) {}
18572003
18582004POST_SYSCALL(recv)(long res, void *buf, long len, long flags) {
18592005 if (res >= 0) {
1860 if (buf) POST_WRITE(buf, res);
2006 if (buf)
2007 POST_WRITE(buf, res);
18612008 }
18622009}
18632010
1864PRE_SYSCALL(recvfrom)(long arg0, void *buf, long len, long flags,
1865 sanitizer_kernel_sockaddr *arg4, void *arg5) {}
2011PRE_SYSCALL(recvfrom)
2012(long arg0, void *buf, long len, long flags, sanitizer_kernel_sockaddr *arg4,
2013 void *arg5) {}
18662014
1867POST_SYSCALL(recvfrom)(long res, long arg0, void *buf, long len, long flags,
1868 sanitizer_kernel_sockaddr *arg4, void *arg5) {
2015POST_SYSCALL(recvfrom)
2016(long res, long arg0, void *buf, long len, long flags,
2017 sanitizer_kernel_sockaddr *arg4, void *arg5) {
18692018 if (res >= 0) {
1870 if (buf) POST_WRITE(buf, res);
1871 if (arg4) POST_WRITE(arg4, sizeof(*arg4));
1872 if (arg5) POST_WRITE(arg5, sizeof(int));
2019 if (buf)
2020 POST_WRITE(buf, res);
2021 if (arg4)
2022 POST_WRITE(arg4, sizeof(*arg4));
2023 if (arg5)
2024 POST_WRITE(arg5, sizeof(int));
18732025 }
18742026}
18752027
......@@ -1881,14 +2033,16 @@ PRE_SYSCALL(socketpair)(long arg0, long arg1, long arg2, int *sv) {}
18812033
18822034POST_SYSCALL(socketpair)(long res, long arg0, long arg1, long arg2, int *sv) {
18832035 if (res >= 0)
1884 if (sv) POST_WRITE(sv, sizeof(int) * 2);
2036 if (sv)
2037 POST_WRITE(sv, sizeof(int) * 2);
18852038}
18862039
18872040PRE_SYSCALL(socketcall)(long call, void *args) {}
18882041
18892042POST_SYSCALL(socketcall)(long res, long call, void *args) {
18902043 if (res >= 0) {
1891 if (args) POST_WRITE(args, sizeof(long));
2044 if (args)
2045 POST_WRITE(args, sizeof(long));
18922046 }
18932047}
18942048
......@@ -1898,25 +2052,31 @@ POST_SYSCALL(listen)(long res, long arg0, long arg1) {}
18982052
18992053PRE_SYSCALL(poll)(void *ufds, long nfds, long timeout) {}
19002054
1901POST_SYSCALL(poll)(long res, __sanitizer_pollfd *ufds, long nfds,
1902 long timeout) {
2055POST_SYSCALL(poll)
2056(long res, __sanitizer_pollfd *ufds, long nfds, long timeout) {
19032057 if (res >= 0) {
1904 if (ufds) POST_WRITE(ufds, nfds * sizeof(*ufds));
2058 if (ufds)
2059 POST_WRITE(ufds, nfds * sizeof(*ufds));
19052060 }
19062061}
19072062
1908PRE_SYSCALL(select)(long n, __sanitizer___kernel_fd_set *inp,
1909 __sanitizer___kernel_fd_set *outp,
1910 __sanitizer___kernel_fd_set *exp, void *tvp) {}
2063PRE_SYSCALL(select)
2064(long n, __sanitizer___kernel_fd_set *inp, __sanitizer___kernel_fd_set *outp,
2065 __sanitizer___kernel_fd_set *exp, void *tvp) {}
19112066
1912POST_SYSCALL(select)(long res, long n, __sanitizer___kernel_fd_set *inp,
1913 __sanitizer___kernel_fd_set *outp,
1914 __sanitizer___kernel_fd_set *exp, void *tvp) {
2067POST_SYSCALL(select)
2068(long res, long n, __sanitizer___kernel_fd_set *inp,
2069 __sanitizer___kernel_fd_set *outp, __sanitizer___kernel_fd_set *exp,
2070 void *tvp) {
19152071 if (res >= 0) {
1916 if (inp) POST_WRITE(inp, sizeof(*inp));
1917 if (outp) POST_WRITE(outp, sizeof(*outp));
1918 if (exp) POST_WRITE(exp, sizeof(*exp));
1919 if (tvp) POST_WRITE(tvp, timeval_sz);
2072 if (inp)
2073 POST_WRITE(inp, sizeof(*inp));
2074 if (outp)
2075 POST_WRITE(outp, sizeof(*outp));
2076 if (exp)
2077 POST_WRITE(exp, sizeof(*exp));
2078 if (tvp)
2079 POST_WRITE(tvp, timeval_sz);
19202080 }
19212081}
19222082
......@@ -1936,29 +2096,58 @@ PRE_SYSCALL(epoll_ctl)(long epfd, long op, long fd, void *event) {}
19362096
19372097POST_SYSCALL(epoll_ctl)(long res, long epfd, long op, long fd, void *event) {
19382098 if (res >= 0) {
1939 if (event) POST_WRITE(event, struct_epoll_event_sz);
2099 if (event)
2100 POST_WRITE(event, struct_epoll_event_sz);
2101 }
2102}
2103
2104PRE_SYSCALL(epoll_wait)
2105(long epfd, void *events, long maxevents, long timeout) {}
2106
2107POST_SYSCALL(epoll_wait)
2108(long res, long epfd, void *events, long maxevents, long timeout) {
2109 if (res >= 0) {
2110 COMMON_SYSCALL_FD_ACQUIRE(epfd);
2111 if (events)
2112 POST_WRITE(events, res * struct_epoll_event_sz);
19402113 }
19412114}
19422115
1943PRE_SYSCALL(epoll_wait)(long epfd, void *events, long maxevents, long timeout) {
2116PRE_SYSCALL(epoll_pwait)
2117(long epfd, void *events, long maxevents, long timeout,
2118 const kernel_sigset_t *sigmask, long sigsetsize) {
2119 if (sigmask)
2120 PRE_READ(sigmask, sigsetsize);
19442121}
19452122
1946POST_SYSCALL(epoll_wait)(long res, long epfd, void *events, long maxevents,
1947 long timeout) {
2123POST_SYSCALL(epoll_pwait)
2124(long res, long epfd, void *events, long maxevents, long timeout,
2125 const void *sigmask, long sigsetsize) {
19482126 if (res >= 0) {
1949 if (events) POST_WRITE(events, struct_epoll_event_sz);
2127 COMMON_SYSCALL_FD_ACQUIRE(epfd);
2128 if (events)
2129 POST_WRITE(events, res * struct_epoll_event_sz);
19502130 }
19512131}
19522132
1953PRE_SYSCALL(epoll_pwait)(long epfd, void *events, long maxevents, long timeout,
1954 const kernel_sigset_t *sigmask, long sigsetsize) {
1955 if (sigmask) PRE_READ(sigmask, sigsetsize);
2133PRE_SYSCALL(epoll_pwait2)
2134(long epfd, void *events, long maxevents,
2135 const sanitizer_kernel_timespec *timeout, const kernel_sigset_t *sigmask,
2136 long sigsetsize) {
2137 if (timeout)
2138 PRE_READ(timeout, sizeof(*timeout));
2139 if (sigmask)
2140 PRE_READ(sigmask, sigsetsize);
19562141}
19572142
1958POST_SYSCALL(epoll_pwait)(long res, long epfd, void *events, long maxevents,
1959 long timeout, const void *sigmask, long sigsetsize) {
2143POST_SYSCALL(epoll_pwait2)
2144(long res, long epfd, void *events, long maxevents,
2145 const sanitizer_kernel_timespec *timeout, const void *sigmask,
2146 long sigsetsize) {
19602147 if (res >= 0) {
1961 if (events) POST_WRITE(events, struct_epoll_event_sz);
2148 COMMON_SYSCALL_FD_ACQUIRE(epfd);
2149 if (events)
2150 POST_WRITE(events, res * struct_epoll_event_sz);
19622151 }
19632152}
19642153
......@@ -1993,7 +2182,8 @@ PRE_SYSCALL(newuname)(void *name) {}
19932182
19942183POST_SYSCALL(newuname)(long res, void *name) {
19952184 if (res >= 0) {
1996 if (name) POST_WRITE(name, struct_new_utsname_sz);
2185 if (name)
2186 POST_WRITE(name, struct_new_utsname_sz);
19972187 }
19982188}
19992189
......@@ -2001,7 +2191,8 @@ PRE_SYSCALL(uname)(void *arg0) {}
20012191
20022192POST_SYSCALL(uname)(long res, void *arg0) {
20032193 if (res >= 0) {
2004 if (arg0) POST_WRITE(arg0, struct_old_utsname_sz);
2194 if (arg0)
2195 POST_WRITE(arg0, struct_old_utsname_sz);
20052196 }
20062197}
20072198
......@@ -2009,7 +2200,8 @@ PRE_SYSCALL(olduname)(void *arg0) {}
20092200
20102201POST_SYSCALL(olduname)(long res, void *arg0) {
20112202 if (res >= 0) {
2012 if (arg0) POST_WRITE(arg0, struct_oldold_utsname_sz);
2203 if (arg0)
2204 POST_WRITE(arg0, struct_oldold_utsname_sz);
20132205 }
20142206}
20152207
......@@ -2017,7 +2209,8 @@ PRE_SYSCALL(getrlimit)(long resource, void *rlim) {}
20172209
20182210POST_SYSCALL(getrlimit)(long res, long resource, void *rlim) {
20192211 if (res >= 0) {
2020 if (rlim) POST_WRITE(rlim, struct_rlimit_sz);
2212 if (rlim)
2213 POST_WRITE(rlim, struct_rlimit_sz);
20212214 }
20222215}
20232216
......@@ -2025,7 +2218,8 @@ PRE_SYSCALL(old_getrlimit)(long resource, void *rlim) {}
20252218
20262219POST_SYSCALL(old_getrlimit)(long res, long resource, void *rlim) {
20272220 if (res >= 0) {
2028 if (rlim) POST_WRITE(rlim, struct_rlimit_sz);
2221 if (rlim)
2222 POST_WRITE(rlim, struct_rlimit_sz);
20292223 }
20302224}
20312225
......@@ -2033,29 +2227,33 @@ PRE_SYSCALL(setrlimit)(long resource, void *rlim) {}
20332227
20342228POST_SYSCALL(setrlimit)(long res, long resource, void *rlim) {
20352229 if (res >= 0) {
2036 if (rlim) POST_WRITE(rlim, struct_rlimit_sz);
2230 if (rlim)
2231 POST_WRITE(rlim, struct_rlimit_sz);
20372232 }
20382233}
20392234
2040#if !SANITIZER_ANDROID
2041PRE_SYSCALL(prlimit64)(long pid, long resource, const void *new_rlim,
2042 void *old_rlim) {
2043 if (new_rlim) PRE_READ(new_rlim, struct_rlimit64_sz);
2235# if SANITIZER_GLIBC
2236PRE_SYSCALL(prlimit64)
2237(long pid, long resource, const void *new_rlim, void *old_rlim) {
2238 if (new_rlim)
2239 PRE_READ(new_rlim, struct_rlimit64_sz);
20442240}
20452241
2046POST_SYSCALL(prlimit64)(long res, long pid, long resource, const void *new_rlim,
2047 void *old_rlim) {
2242POST_SYSCALL(prlimit64)
2243(long res, long pid, long resource, const void *new_rlim, void *old_rlim) {
20482244 if (res >= 0) {
2049 if (old_rlim) POST_WRITE(old_rlim, struct_rlimit64_sz);
2245 if (old_rlim)
2246 POST_WRITE(old_rlim, struct_rlimit64_sz);
20502247 }
20512248}
2052#endif
2249# endif
20532250
20542251PRE_SYSCALL(getrusage)(long who, void *ru) {}
20552252
20562253POST_SYSCALL(getrusage)(long res, long who, void *ru) {
20572254 if (res >= 0) {
2058 if (ru) POST_WRITE(ru, struct_rusage_sz);
2255 if (ru)
2256 POST_WRITE(ru, struct_rusage_sz);
20592257 }
20602258}
20612259
......@@ -2068,31 +2266,34 @@ PRE_SYSCALL(msgget)(long key, long msgflg) {}
20682266POST_SYSCALL(msgget)(long res, long key, long msgflg) {}
20692267
20702268PRE_SYSCALL(msgsnd)(long msqid, void *msgp, long msgsz, long msgflg) {
2071 if (msgp) PRE_READ(msgp, msgsz);
2269 if (msgp)
2270 PRE_READ(msgp, msgsz);
20722271}
20732272
2074POST_SYSCALL(msgsnd)(long res, long msqid, void *msgp, long msgsz,
2075 long msgflg) {}
2273POST_SYSCALL(msgsnd)
2274(long res, long msqid, void *msgp, long msgsz, long msgflg) {}
20762275
2077PRE_SYSCALL(msgrcv)(long msqid, void *msgp, long msgsz, long msgtyp,
2078 long msgflg) {}
2276PRE_SYSCALL(msgrcv)
2277(long msqid, void *msgp, long msgsz, long msgtyp, long msgflg) {}
20792278
2080POST_SYSCALL(msgrcv)(long res, long msqid, void *msgp, long msgsz, long msgtyp,
2081 long msgflg) {
2279POST_SYSCALL(msgrcv)
2280(long res, long msqid, void *msgp, long msgsz, long msgtyp, long msgflg) {
20822281 if (res >= 0) {
2083 if (msgp) POST_WRITE(msgp, res);
2282 if (msgp)
2283 POST_WRITE(msgp, res);
20842284 }
20852285}
20862286
2087#if !SANITIZER_ANDROID
2287# if !SANITIZER_ANDROID
20882288PRE_SYSCALL(msgctl)(long msqid, long cmd, void *buf) {}
20892289
20902290POST_SYSCALL(msgctl)(long res, long msqid, long cmd, void *buf) {
20912291 if (res >= 0) {
2092 if (buf) POST_WRITE(buf, struct_msqid_ds_sz);
2292 if (buf)
2293 POST_WRITE(buf, struct_msqid_ds_sz);
20932294 }
20942295}
2095#endif
2296# endif
20962297
20972298PRE_SYSCALL(semget)(long key, long nsems, long semflg) {}
20982299
......@@ -2106,13 +2307,14 @@ PRE_SYSCALL(semctl)(long semid, long semnum, long cmd, void *arg) {}
21062307
21072308POST_SYSCALL(semctl)(long res, long semid, long semnum, long cmd, void *arg) {}
21082309
2109PRE_SYSCALL(semtimedop)(long semid, void *sops, long nsops,
2110 const void *timeout) {
2111 if (timeout) PRE_READ(timeout, struct_timespec_sz);
2310PRE_SYSCALL(semtimedop)
2311(long semid, void *sops, long nsops, const void *timeout) {
2312 if (timeout)
2313 PRE_READ(timeout, struct_timespec_sz);
21122314}
21132315
2114POST_SYSCALL(semtimedop)(long res, long semid, void *sops, long nsops,
2115 const void *timeout) {}
2316POST_SYSCALL(semtimedop)
2317(long res, long semid, void *sops, long nsops, const void *timeout) {}
21162318
21172319PRE_SYSCALL(shmat)(long shmid, void *shmaddr, long shmflg) {}
21182320
......@@ -2138,18 +2340,20 @@ POST_SYSCALL(shmdt)(long res, void *shmaddr) {
21382340 }
21392341}
21402342
2141PRE_SYSCALL(ipc)(long call, long first, long second, long third, void *ptr,
2142 long fifth) {}
2343PRE_SYSCALL(ipc)
2344(long call, long first, long second, long third, void *ptr, long fifth) {}
21432345
2144POST_SYSCALL(ipc)(long res, long call, long first, long second, long third,
2145 void *ptr, long fifth) {}
2346POST_SYSCALL(ipc)
2347(long res, long call, long first, long second, long third, void *ptr,
2348 long fifth) {}
21462349
2147#if !SANITIZER_ANDROID
2350# if !SANITIZER_ANDROID
21482351PRE_SYSCALL(shmctl)(long shmid, long cmd, void *buf) {}
21492352
21502353POST_SYSCALL(shmctl)(long res, long shmid, long cmd, void *buf) {
21512354 if (res >= 0) {
2152 if (buf) POST_WRITE(buf, sizeof(__sanitizer_shmid_ds));
2355 if (buf)
2356 POST_WRITE(buf, sizeof(__sanitizer_shmid_ds));
21532357 }
21542358}
21552359
......@@ -2158,10 +2362,11 @@ PRE_SYSCALL(mq_open)(const void *name, long oflag, long mode, void *attr) {
21582362 PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
21592363}
21602364
2161POST_SYSCALL(mq_open)(long res, const void *name, long oflag, long mode,
2162 void *attr) {
2365POST_SYSCALL(mq_open)
2366(long res, const void *name, long oflag, long mode, void *attr) {
21632367 if (res >= 0) {
2164 if (attr) POST_WRITE(attr, struct_mq_attr_sz);
2368 if (attr)
2369 POST_WRITE(attr, struct_mq_attr_sz);
21652370 }
21662371}
21672372
......@@ -2172,62 +2377,73 @@ PRE_SYSCALL(mq_unlink)(const void *name) {
21722377
21732378POST_SYSCALL(mq_unlink)(long res, const void *name) {}
21742379
2175PRE_SYSCALL(mq_timedsend)(long mqdes, const void *msg_ptr, long msg_len,
2176 long msg_prio, const void *abs_timeout) {
2177 if (msg_ptr) PRE_READ(msg_ptr, msg_len);
2178 if (abs_timeout) PRE_READ(abs_timeout, struct_timespec_sz);
2380PRE_SYSCALL(mq_timedsend)
2381(long mqdes, const void *msg_ptr, long msg_len, long msg_prio,
2382 const void *abs_timeout) {
2383 if (msg_ptr)
2384 PRE_READ(msg_ptr, msg_len);
2385 if (abs_timeout)
2386 PRE_READ(abs_timeout, struct_timespec_sz);
21792387}
21802388
2181POST_SYSCALL(mq_timedsend)(long res, long mqdes, const void *msg_ptr,
2182 long msg_len, long msg_prio,
2183 const void *abs_timeout) {}
2389POST_SYSCALL(mq_timedsend)
2390(long res, long mqdes, const void *msg_ptr, long msg_len, long msg_prio,
2391 const void *abs_timeout) {}
21842392
2185PRE_SYSCALL(mq_timedreceive)(long mqdes, void *msg_ptr, long msg_len,
2186 void *msg_prio, const void *abs_timeout) {
2187 if (abs_timeout) PRE_READ(abs_timeout, struct_timespec_sz);
2393PRE_SYSCALL(mq_timedreceive)
2394(long mqdes, void *msg_ptr, long msg_len, void *msg_prio,
2395 const void *abs_timeout) {
2396 if (abs_timeout)
2397 PRE_READ(abs_timeout, struct_timespec_sz);
21882398}
21892399
2190POST_SYSCALL(mq_timedreceive)(long res, long mqdes, void *msg_ptr, long msg_len,
2191 int *msg_prio, const void *abs_timeout) {
2400POST_SYSCALL(mq_timedreceive)
2401(long res, long mqdes, void *msg_ptr, long msg_len, int *msg_prio,
2402 const void *abs_timeout) {
21922403 if (res >= 0) {
2193 if (msg_ptr) POST_WRITE(msg_ptr, res);
2194 if (msg_prio) POST_WRITE(msg_prio, sizeof(*msg_prio));
2404 if (msg_ptr)
2405 POST_WRITE(msg_ptr, res);
2406 if (msg_prio)
2407 POST_WRITE(msg_prio, sizeof(*msg_prio));
21952408 }
21962409}
21972410
21982411PRE_SYSCALL(mq_notify)(long mqdes, const void *notification) {
2199 if (notification) PRE_READ(notification, struct_sigevent_sz);
2412 if (notification)
2413 PRE_READ(notification, struct_sigevent_sz);
22002414}
22012415
22022416POST_SYSCALL(mq_notify)(long res, long mqdes, const void *notification) {}
22032417
22042418PRE_SYSCALL(mq_getsetattr)(long mqdes, const void *mqstat, void *omqstat) {
2205 if (mqstat) PRE_READ(mqstat, struct_mq_attr_sz);
2419 if (mqstat)
2420 PRE_READ(mqstat, struct_mq_attr_sz);
22062421}
22072422
2208POST_SYSCALL(mq_getsetattr)(long res, long mqdes, const void *mqstat,
2209 void *omqstat) {
2423POST_SYSCALL(mq_getsetattr)
2424(long res, long mqdes, const void *mqstat, void *omqstat) {
22102425 if (res >= 0) {
2211 if (omqstat) POST_WRITE(omqstat, struct_mq_attr_sz);
2426 if (omqstat)
2427 POST_WRITE(omqstat, struct_mq_attr_sz);
22122428 }
22132429}
2214#endif // SANITIZER_ANDROID
2430# endif // SANITIZER_ANDROID
22152431
22162432PRE_SYSCALL(pciconfig_iobase)(long which, long bus, long devfn) {}
22172433
22182434POST_SYSCALL(pciconfig_iobase)(long res, long which, long bus, long devfn) {}
22192435
2220PRE_SYSCALL(pciconfig_read)(long bus, long dfn, long off, long len, void *buf) {
2221}
2436PRE_SYSCALL(pciconfig_read)
2437(long bus, long dfn, long off, long len, void *buf) {}
22222438
2223POST_SYSCALL(pciconfig_read)(long res, long bus, long dfn, long off, long len,
2224 void *buf) {}
2439POST_SYSCALL(pciconfig_read)
2440(long res, long bus, long dfn, long off, long len, void *buf) {}
22252441
2226PRE_SYSCALL(pciconfig_write)(long bus, long dfn, long off, long len,
2227 void *buf) {}
2442PRE_SYSCALL(pciconfig_write)
2443(long bus, long dfn, long off, long len, void *buf) {}
22282444
2229POST_SYSCALL(pciconfig_write)(long res, long bus, long dfn, long off, long len,
2230 void *buf) {}
2445POST_SYSCALL(pciconfig_write)
2446(long res, long bus, long dfn, long off, long len, void *buf) {}
22312447
22322448PRE_SYSCALL(swapon)(const void *specialfile, long swap_flags) {
22332449 if (specialfile)
......@@ -2247,8 +2463,10 @@ POST_SYSCALL(swapoff)(long res, const void *specialfile) {}
22472463
22482464PRE_SYSCALL(sysctl)(__sanitizer___sysctl_args *args) {
22492465 if (args) {
2250 if (args->name) PRE_READ(args->name, args->nlen * sizeof(*args->name));
2251 if (args->newval) PRE_READ(args->name, args->newlen);
2466 if (args->name)
2467 PRE_READ(args->name, args->nlen * sizeof(*args->name));
2468 if (args->newval)
2469 PRE_READ(args->name, args->newlen);
22522470 }
22532471}
22542472
......@@ -2265,7 +2483,8 @@ PRE_SYSCALL(sysinfo)(void *info) {}
22652483
22662484POST_SYSCALL(sysinfo)(long res, void *info) {
22672485 if (res >= 0) {
2268 if (info) POST_WRITE(info, struct_sysinfo_sz);
2486 if (info)
2487 POST_WRITE(info, struct_sysinfo_sz);
22692488 }
22702489}
22712490
......@@ -2294,10 +2513,10 @@ PRE_SYSCALL(ni_syscall)() {}
22942513POST_SYSCALL(ni_syscall)(long res) {}
22952514
22962515PRE_SYSCALL(ptrace)(long request, long pid, long addr, long data) {
2297#if !SANITIZER_ANDROID && \
2298 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
2299 defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \
2300 SANITIZER_RISCV64)
2516# if !SANITIZER_ANDROID && \
2517 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
2518 defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \
2519 defined(__loongarch__) || SANITIZER_RISCV64)
23012520 if (data) {
23022521 if (request == ptrace_setregs) {
23032522 PRE_READ((void *)data, struct_user_regs_struct_sz);
......@@ -2312,14 +2531,14 @@ PRE_SYSCALL(ptrace)(long request, long pid, long addr, long data) {
23122531 PRE_READ(iov->iov_base, iov->iov_len);
23132532 }
23142533 }
2315#endif
2534# endif
23162535}
23172536
23182537POST_SYSCALL(ptrace)(long res, long request, long pid, long addr, long data) {
2319#if !SANITIZER_ANDROID && \
2320 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
2321 defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \
2322 SANITIZER_RISCV64)
2538# if !SANITIZER_ANDROID && \
2539 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
2540 defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \
2541 defined(__loongarch__) || SANITIZER_RISCV64)
23232542 if (res >= 0 && data) {
23242543 // Note that this is different from the interceptor in
23252544 // sanitizer_common_interceptors.inc.
......@@ -2340,11 +2559,12 @@ POST_SYSCALL(ptrace)(long res, long request, long pid, long addr, long data) {
23402559 POST_WRITE((void *)data, sizeof(void *));
23412560 }
23422561 }
2343#endif
2562# endif
23442563}
23452564
2346PRE_SYSCALL(add_key)(const void *_type, const void *_description,
2347 const void *_payload, long plen, long destringid) {
2565PRE_SYSCALL(add_key)
2566(const void *_type, const void *_description, const void *_payload, long plen,
2567 long destringid) {
23482568 if (_type)
23492569 PRE_READ(_type, __sanitizer::internal_strlen((const char *)_type) + 1);
23502570 if (_description)
......@@ -2352,11 +2572,13 @@ PRE_SYSCALL(add_key)(const void *_type, const void *_description,
23522572 __sanitizer::internal_strlen((const char *)_description) + 1);
23532573}
23542574
2355POST_SYSCALL(add_key)(long res, const void *_type, const void *_description,
2356 const void *_payload, long plen, long destringid) {}
2575POST_SYSCALL(add_key)
2576(long res, const void *_type, const void *_description, const void *_payload,
2577 long plen, long destringid) {}
23572578
2358PRE_SYSCALL(request_key)(const void *_type, const void *_description,
2359 const void *_callout_info, long destringid) {
2579PRE_SYSCALL(request_key)
2580(const void *_type, const void *_description, const void *_callout_info,
2581 long destringid) {
23602582 if (_type)
23612583 PRE_READ(_type, __sanitizer::internal_strlen((const char *)_type) + 1);
23622584 if (_description)
......@@ -2367,13 +2589,14 @@ PRE_SYSCALL(request_key)(const void *_type, const void *_description,
23672589 __sanitizer::internal_strlen((const char *)_callout_info) + 1);
23682590}
23692591
2370POST_SYSCALL(request_key)(long res, const void *_type, const void *_description,
2371 const void *_callout_info, long destringid) {}
2592POST_SYSCALL(request_key)
2593(long res, const void *_type, const void *_description,
2594 const void *_callout_info, long destringid) {}
23722595
23732596PRE_SYSCALL(keyctl)(long cmd, long arg2, long arg3, long arg4, long arg5) {}
23742597
2375POST_SYSCALL(keyctl)(long res, long cmd, long arg2, long arg3, long arg4,
2376 long arg5) {}
2598POST_SYSCALL(keyctl)
2599(long res, long cmd, long arg2, long arg3, long arg4, long arg5) {}
23772600
23782601PRE_SYSCALL(ioprio_set)(long which, long who, long ioprio) {}
23792602
......@@ -2387,50 +2610,62 @@ PRE_SYSCALL(set_mempolicy)(long mode, void *nmask, long maxnode) {}
23872610
23882611POST_SYSCALL(set_mempolicy)(long res, long mode, void *nmask, long maxnode) {
23892612 if (res >= 0) {
2390 if (nmask) POST_WRITE(nmask, sizeof(long));
2613 if (nmask)
2614 POST_WRITE(nmask, sizeof(long));
23912615 }
23922616}
23932617
2394PRE_SYSCALL(migrate_pages)(long pid, long maxnode, const void *from,
2395 const void *to) {
2396 if (from) PRE_READ(from, sizeof(long));
2397 if (to) PRE_READ(to, sizeof(long));
2618PRE_SYSCALL(migrate_pages)
2619(long pid, long maxnode, const void *from, const void *to) {
2620 if (from)
2621 PRE_READ(from, sizeof(long));
2622 if (to)
2623 PRE_READ(to, sizeof(long));
23982624}
23992625
2400POST_SYSCALL(migrate_pages)(long res, long pid, long maxnode, const void *from,
2401 const void *to) {}
2626POST_SYSCALL(migrate_pages)
2627(long res, long pid, long maxnode, const void *from, const void *to) {}
24022628
2403PRE_SYSCALL(move_pages)(long pid, long nr_pages, const void **pages,
2404 const int *nodes, int *status, long flags) {
2405 if (pages) PRE_READ(pages, nr_pages * sizeof(*pages));
2406 if (nodes) PRE_READ(nodes, nr_pages * sizeof(*nodes));
2629PRE_SYSCALL(move_pages)
2630(long pid, long nr_pages, const void **pages, const int *nodes, int *status,
2631 long flags) {
2632 if (pages)
2633 PRE_READ(pages, nr_pages * sizeof(*pages));
2634 if (nodes)
2635 PRE_READ(nodes, nr_pages * sizeof(*nodes));
24072636}
24082637
2409POST_SYSCALL(move_pages)(long res, long pid, long nr_pages, const void **pages,
2410 const int *nodes, int *status, long flags) {
2638POST_SYSCALL(move_pages)
2639(long res, long pid, long nr_pages, const void **pages, const int *nodes,
2640 int *status, long flags) {
24112641 if (res >= 0) {
2412 if (status) POST_WRITE(status, nr_pages * sizeof(*status));
2642 if (status)
2643 POST_WRITE(status, nr_pages * sizeof(*status));
24132644 }
24142645}
24152646
2416PRE_SYSCALL(mbind)(long start, long len, long mode, void *nmask, long maxnode,
2417 long flags) {}
2647PRE_SYSCALL(mbind)
2648(long start, long len, long mode, void *nmask, long maxnode, long flags) {}
24182649
2419POST_SYSCALL(mbind)(long res, long start, long len, long mode, void *nmask,
2420 long maxnode, long flags) {
2650POST_SYSCALL(mbind)
2651(long res, long start, long len, long mode, void *nmask, long maxnode,
2652 long flags) {
24212653 if (res >= 0) {
2422 if (nmask) POST_WRITE(nmask, sizeof(long));
2654 if (nmask)
2655 POST_WRITE(nmask, sizeof(long));
24232656 }
24242657}
24252658
2426PRE_SYSCALL(get_mempolicy)(void *policy, void *nmask, long maxnode, long addr,
2427 long flags) {}
2659PRE_SYSCALL(get_mempolicy)
2660(void *policy, void *nmask, long maxnode, long addr, long flags) {}
24282661
2429POST_SYSCALL(get_mempolicy)(long res, void *policy, void *nmask, long maxnode,
2430 long addr, long flags) {
2662POST_SYSCALL(get_mempolicy)
2663(long res, void *policy, void *nmask, long maxnode, long addr, long flags) {
24312664 if (res >= 0) {
2432 if (policy) POST_WRITE(policy, sizeof(int));
2433 if (nmask) POST_WRITE(nmask, sizeof(long));
2665 if (policy)
2666 POST_WRITE(policy, sizeof(int));
2667 if (nmask)
2668 POST_WRITE(nmask, sizeof(long));
24342669 }
24352670}
24362671
......@@ -2447,8 +2682,8 @@ PRE_SYSCALL(inotify_add_watch)(long fd, const void *path, long mask) {
24472682 PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
24482683}
24492684
2450POST_SYSCALL(inotify_add_watch)(long res, long fd, const void *path,
2451 long mask) {}
2685POST_SYSCALL(inotify_add_watch)
2686(long res, long fd, const void *path, long mask) {}
24522687
24532688PRE_SYSCALL(inotify_rm_watch)(long fd, long wd) {}
24542689
......@@ -2458,8 +2693,10 @@ PRE_SYSCALL(spu_run)(long fd, void *unpc, void *ustatus) {}
24582693
24592694POST_SYSCALL(spu_run)(long res, long fd, unsigned *unpc, unsigned *ustatus) {
24602695 if (res >= 0) {
2461 if (unpc) POST_WRITE(unpc, sizeof(*unpc));
2462 if (ustatus) POST_WRITE(ustatus, sizeof(*ustatus));
2696 if (unpc)
2697 POST_WRITE(unpc, sizeof(*unpc));
2698 if (ustatus)
2699 POST_WRITE(ustatus, sizeof(*ustatus));
24632700 }
24642701}
24652702
......@@ -2468,8 +2705,8 @@ PRE_SYSCALL(spu_create)(const void *name, long flags, long mode, long fd) {
24682705 PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
24692706}
24702707
2471POST_SYSCALL(spu_create)(long res, const void *name, long flags, long mode,
2472 long fd) {}
2708POST_SYSCALL(spu_create)
2709(long res, const void *name, long flags, long mode, long fd) {}
24732710
24742711PRE_SYSCALL(mknodat)(long dfd, const void *filename, long mode, long dev) {
24752712 if (filename)
......@@ -2477,8 +2714,8 @@ PRE_SYSCALL(mknodat)(long dfd, const void *filename, long mode, long dev) {
24772714 __sanitizer::internal_strlen((const char *)filename) + 1);
24782715}
24792716
2480POST_SYSCALL(mknodat)(long res, long dfd, const void *filename, long mode,
2481 long dev) {}
2717POST_SYSCALL(mknodat)
2718(long res, long dfd, const void *filename, long mode, long dev) {}
24822719
24832720PRE_SYSCALL(mkdirat)(long dfd, const void *pathname, long mode) {
24842721 if (pathname)
......@@ -2503,30 +2740,33 @@ PRE_SYSCALL(symlinkat)(const void *oldname, long newdfd, const void *newname) {
25032740 PRE_READ(newname, __sanitizer::internal_strlen((const char *)newname) + 1);
25042741}
25052742
2506POST_SYSCALL(symlinkat)(long res, const void *oldname, long newdfd,
2507 const void *newname) {}
2743POST_SYSCALL(symlinkat)
2744(long res, const void *oldname, long newdfd, const void *newname) {}
25082745
2509PRE_SYSCALL(linkat)(long olddfd, const void *oldname, long newdfd,
2510 const void *newname, long flags) {
2746PRE_SYSCALL(linkat)
2747(long olddfd, const void *oldname, long newdfd, const void *newname,
2748 long flags) {
25112749 if (oldname)
25122750 PRE_READ(oldname, __sanitizer::internal_strlen((const char *)oldname) + 1);
25132751 if (newname)
25142752 PRE_READ(newname, __sanitizer::internal_strlen((const char *)newname) + 1);
25152753}
25162754
2517POST_SYSCALL(linkat)(long res, long olddfd, const void *oldname, long newdfd,
2518 const void *newname, long flags) {}
2755POST_SYSCALL(linkat)
2756(long res, long olddfd, const void *oldname, long newdfd, const void *newname,
2757 long flags) {}
25192758
2520PRE_SYSCALL(renameat)(long olddfd, const void *oldname, long newdfd,
2521 const void *newname) {
2759PRE_SYSCALL(renameat)
2760(long olddfd, const void *oldname, long newdfd, const void *newname) {
25222761 if (oldname)
25232762 PRE_READ(oldname, __sanitizer::internal_strlen((const char *)oldname) + 1);
25242763 if (newname)
25252764 PRE_READ(newname, __sanitizer::internal_strlen((const char *)newname) + 1);
25262765}
25272766
2528POST_SYSCALL(renameat)(long res, long olddfd, const void *oldname, long newdfd,
2529 const void *newname) {}
2767POST_SYSCALL(renameat)
2768(long res, long olddfd, const void *oldname, long newdfd, const void *newname) {
2769}
25302770
25312771PRE_SYSCALL(futimesat)(long dfd, const void *filename, void *utimes) {
25322772 if (filename)
......@@ -2534,10 +2774,11 @@ PRE_SYSCALL(futimesat)(long dfd, const void *filename, void *utimes) {
25342774 __sanitizer::internal_strlen((const char *)filename) + 1);
25352775}
25362776
2537POST_SYSCALL(futimesat)(long res, long dfd, const void *filename,
2538 void *utimes) {
2777POST_SYSCALL(futimesat)
2778(long res, long dfd, const void *filename, void *utimes) {
25392779 if (res >= 0) {
2540 if (utimes) POST_WRITE(utimes, timeval_sz);
2780 if (utimes)
2781 POST_WRITE(utimes, timeval_sz);
25412782 }
25422783}
25432784
......@@ -2557,15 +2798,15 @@ PRE_SYSCALL(fchmodat)(long dfd, const void *filename, long mode) {
25572798
25582799POST_SYSCALL(fchmodat)(long res, long dfd, const void *filename, long mode) {}
25592800
2560PRE_SYSCALL(fchownat)(long dfd, const void *filename, long user, long group,
2561 long flag) {
2801PRE_SYSCALL(fchownat)
2802(long dfd, const void *filename, long user, long group, long flag) {
25622803 if (filename)
25632804 PRE_READ(filename,
25642805 __sanitizer::internal_strlen((const char *)filename) + 1);
25652806}
25662807
2567POST_SYSCALL(fchownat)(long res, long dfd, const void *filename, long user,
2568 long group, long flag) {}
2808POST_SYSCALL(fchownat)
2809(long res, long dfd, const void *filename, long user, long group, long flag) {}
25692810
25702811PRE_SYSCALL(openat)(long dfd, const void *filename, long flags, long mode) {
25712812 if (filename)
......@@ -2573,34 +2814,36 @@ PRE_SYSCALL(openat)(long dfd, const void *filename, long flags, long mode) {
25732814 __sanitizer::internal_strlen((const char *)filename) + 1);
25742815}
25752816
2576POST_SYSCALL(openat)(long res, long dfd, const void *filename, long flags,
2577 long mode) {}
2817POST_SYSCALL(openat)
2818(long res, long dfd, const void *filename, long flags, long mode) {}
25782819
2579PRE_SYSCALL(newfstatat)(long dfd, const void *filename, void *statbuf,
2580 long flag) {
2820PRE_SYSCALL(newfstatat)
2821(long dfd, const void *filename, void *statbuf, long flag) {
25812822 if (filename)
25822823 PRE_READ(filename,
25832824 __sanitizer::internal_strlen((const char *)filename) + 1);
25842825}
25852826
2586POST_SYSCALL(newfstatat)(long res, long dfd, const void *filename,
2587 void *statbuf, long flag) {
2827POST_SYSCALL(newfstatat)
2828(long res, long dfd, const void *filename, void *statbuf, long flag) {
25882829 if (res >= 0) {
2589 if (statbuf) POST_WRITE(statbuf, struct_kernel_stat_sz);
2830 if (statbuf)
2831 POST_WRITE(statbuf, struct_kernel_stat_sz);
25902832 }
25912833}
25922834
2593PRE_SYSCALL(fstatat64)(long dfd, const void *filename, void *statbuf,
2594 long flag) {
2835PRE_SYSCALL(fstatat64)
2836(long dfd, const void *filename, void *statbuf, long flag) {
25952837 if (filename)
25962838 PRE_READ(filename,
25972839 __sanitizer::internal_strlen((const char *)filename) + 1);
25982840}
25992841
2600POST_SYSCALL(fstatat64)(long res, long dfd, const void *filename, void *statbuf,
2601 long flag) {
2842POST_SYSCALL(fstatat64)
2843(long res, long dfd, const void *filename, void *statbuf, long flag) {
26022844 if (res >= 0) {
2603 if (statbuf) POST_WRITE(statbuf, struct_kernel_stat64_sz);
2845 if (statbuf)
2846 POST_WRITE(statbuf, struct_kernel_stat64_sz);
26042847 }
26052848}
26062849
......@@ -2609,25 +2852,26 @@ PRE_SYSCALL(readlinkat)(long dfd, const void *path, void *buf, long bufsiz) {
26092852 PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
26102853}
26112854
2612POST_SYSCALL(readlinkat)(long res, long dfd, const void *path, void *buf,
2613 long bufsiz) {
2855POST_SYSCALL(readlinkat)
2856(long res, long dfd, const void *path, void *buf, long bufsiz) {
26142857 if (res >= 0) {
26152858 if (buf)
26162859 POST_WRITE(buf, __sanitizer::internal_strlen((const char *)buf) + 1);
26172860 }
26182861}
26192862
2620PRE_SYSCALL(utimensat)(long dfd, const void *filename, void *utimes,
2621 long flags) {
2863PRE_SYSCALL(utimensat)
2864(long dfd, const void *filename, void *utimes, long flags) {
26222865 if (filename)
26232866 PRE_READ(filename,
26242867 __sanitizer::internal_strlen((const char *)filename) + 1);
26252868}
26262869
2627POST_SYSCALL(utimensat)(long res, long dfd, const void *filename, void *utimes,
2628 long flags) {
2870POST_SYSCALL(utimensat)
2871(long res, long dfd, const void *filename, void *utimes, long flags) {
26292872 if (res >= 0) {
2630 if (utimes) POST_WRITE(utimes, struct_timespec_sz);
2873 if (utimes)
2874 POST_WRITE(utimes, struct_timespec_sz);
26312875 }
26322876}
26332877
......@@ -2635,24 +2879,28 @@ PRE_SYSCALL(unshare)(long unshare_flags) {}
26352879
26362880POST_SYSCALL(unshare)(long res, long unshare_flags) {}
26372881
2638PRE_SYSCALL(splice)(long fd_in, void *off_in, long fd_out, void *off_out,
2639 long len, long flags) {}
2882PRE_SYSCALL(splice)
2883(long fd_in, void *off_in, long fd_out, void *off_out, long len, long flags) {}
26402884
2641POST_SYSCALL(splice)(long res, long fd_in, void *off_in, long fd_out,
2642 void *off_out, long len, long flags) {
2885POST_SYSCALL(splice)
2886(long res, long fd_in, void *off_in, long fd_out, void *off_out, long len,
2887 long flags) {
26432888 if (res >= 0) {
2644 if (off_in) POST_WRITE(off_in, sizeof(long long));
2645 if (off_out) POST_WRITE(off_out, sizeof(long long));
2889 if (off_in)
2890 POST_WRITE(off_in, sizeof(long long));
2891 if (off_out)
2892 POST_WRITE(off_out, sizeof(long long));
26462893 }
26472894}
26482895
2649PRE_SYSCALL(vmsplice)(long fd, const __sanitizer_iovec *iov, long nr_segs,
2650 long flags) {}
2896PRE_SYSCALL(vmsplice)
2897(long fd, const __sanitizer_iovec *iov, long nr_segs, long flags) {}
26512898
2652POST_SYSCALL(vmsplice)(long res, long fd, const __sanitizer_iovec *iov,
2653 long nr_segs, long flags) {
2899POST_SYSCALL(vmsplice)
2900(long res, long fd, const __sanitizer_iovec *iov, long nr_segs, long flags) {
26542901 if (res >= 0) {
2655 if (iov) kernel_read_iovec(iov, nr_segs, res);
2902 if (iov)
2903 kernel_read_iovec(iov, nr_segs, res);
26562904 }
26572905}
26582906
......@@ -2662,8 +2910,8 @@ POST_SYSCALL(tee)(long res, long fdin, long fdout, long len, long flags) {}
26622910
26632911PRE_SYSCALL(get_robust_list)(long pid, void *head_ptr, void *len_ptr) {}
26642912
2665POST_SYSCALL(get_robust_list)(long res, long pid, void *head_ptr,
2666 void *len_ptr) {}
2913POST_SYSCALL(get_robust_list)
2914(long res, long pid, void *head_ptr, void *len_ptr) {}
26672915
26682916PRE_SYSCALL(set_robust_list)(void *head, long len) {}
26692917
......@@ -2673,27 +2921,31 @@ PRE_SYSCALL(getcpu)(void *cpu, void *node, void *cache) {}
26732921
26742922POST_SYSCALL(getcpu)(long res, void *cpu, void *node, void *cache) {
26752923 if (res >= 0) {
2676 if (cpu) POST_WRITE(cpu, sizeof(unsigned));
2677 if (node) POST_WRITE(node, sizeof(unsigned));
2924 if (cpu)
2925 POST_WRITE(cpu, sizeof(unsigned));
2926 if (node)
2927 POST_WRITE(node, sizeof(unsigned));
26782928 // The third argument to this system call is nowadays unused.
26792929 }
26802930}
26812931
26822932PRE_SYSCALL(signalfd)(long ufd, void *user_mask, long sizemask) {}
26832933
2684POST_SYSCALL(signalfd)(long res, long ufd, kernel_sigset_t *user_mask,
2685 long sizemask) {
2934POST_SYSCALL(signalfd)
2935(long res, long ufd, kernel_sigset_t *user_mask, long sizemask) {
26862936 if (res >= 0) {
2687 if (user_mask) POST_WRITE(user_mask, sizemask);
2937 if (user_mask)
2938 POST_WRITE(user_mask, sizemask);
26882939 }
26892940}
26902941
26912942PRE_SYSCALL(signalfd4)(long ufd, void *user_mask, long sizemask, long flags) {}
26922943
2693POST_SYSCALL(signalfd4)(long res, long ufd, kernel_sigset_t *user_mask,
2694 long sizemask, long flags) {
2944POST_SYSCALL(signalfd4)
2945(long res, long ufd, kernel_sigset_t *user_mask, long sizemask, long flags) {
26952946 if (res >= 0) {
2696 if (user_mask) POST_WRITE(user_mask, sizemask);
2947 if (user_mask)
2948 POST_WRITE(user_mask, sizemask);
26972949 }
26982950}
26992951
......@@ -2701,15 +2953,17 @@ PRE_SYSCALL(timerfd_create)(long clockid, long flags) {}
27012953
27022954POST_SYSCALL(timerfd_create)(long res, long clockid, long flags) {}
27032955
2704PRE_SYSCALL(timerfd_settime)(long ufd, long flags, const void *utmr,
2705 void *otmr) {
2706 if (utmr) PRE_READ(utmr, struct_itimerspec_sz);
2956PRE_SYSCALL(timerfd_settime)
2957(long ufd, long flags, const void *utmr, void *otmr) {
2958 if (utmr)
2959 PRE_READ(utmr, struct_itimerspec_sz);
27072960}
27082961
2709POST_SYSCALL(timerfd_settime)(long res, long ufd, long flags, const void *utmr,
2710 void *otmr) {
2962POST_SYSCALL(timerfd_settime)
2963(long res, long ufd, long flags, const void *utmr, void *otmr) {
27112964 if (res >= 0) {
2712 if (otmr) POST_WRITE(otmr, struct_itimerspec_sz);
2965 if (otmr)
2966 POST_WRITE(otmr, struct_itimerspec_sz);
27132967 }
27142968}
27152969
......@@ -2717,7 +2971,8 @@ PRE_SYSCALL(timerfd_gettime)(long ufd, void *otmr) {}
27172971
27182972POST_SYSCALL(timerfd_gettime)(long res, long ufd, void *otmr) {
27192973 if (res >= 0) {
2720 if (otmr) POST_WRITE(otmr, struct_itimerspec_sz);
2974 if (otmr)
2975 POST_WRITE(otmr, struct_itimerspec_sz);
27212976 }
27222977}
27232978
......@@ -2735,33 +2990,42 @@ POST_SYSCALL(old_readdir)(long res, long arg0, void *arg1, long arg2) {
27352990 // Missing definition of 'struct old_linux_dirent'.
27362991}
27372992
2738PRE_SYSCALL(pselect6)(long arg0, __sanitizer___kernel_fd_set *arg1,
2739 __sanitizer___kernel_fd_set *arg2,
2740 __sanitizer___kernel_fd_set *arg3, void *arg4,
2741 void *arg5) {}
2993PRE_SYSCALL(pselect6)
2994(long arg0, __sanitizer___kernel_fd_set *arg1,
2995 __sanitizer___kernel_fd_set *arg2, __sanitizer___kernel_fd_set *arg3,
2996 void *arg4, void *arg5) {}
27422997
2743POST_SYSCALL(pselect6)(long res, long arg0, __sanitizer___kernel_fd_set *arg1,
2744 __sanitizer___kernel_fd_set *arg2,
2745 __sanitizer___kernel_fd_set *arg3, void *arg4,
2746 void *arg5) {
2998POST_SYSCALL(pselect6)
2999(long res, long arg0, __sanitizer___kernel_fd_set *arg1,
3000 __sanitizer___kernel_fd_set *arg2, __sanitizer___kernel_fd_set *arg3,
3001 void *arg4, void *arg5) {
27473002 if (res >= 0) {
2748 if (arg1) POST_WRITE(arg1, sizeof(*arg1));
2749 if (arg2) POST_WRITE(arg2, sizeof(*arg2));
2750 if (arg3) POST_WRITE(arg3, sizeof(*arg3));
2751 if (arg4) POST_WRITE(arg4, struct_timespec_sz);
3003 if (arg1)
3004 POST_WRITE(arg1, sizeof(*arg1));
3005 if (arg2)
3006 POST_WRITE(arg2, sizeof(*arg2));
3007 if (arg3)
3008 POST_WRITE(arg3, sizeof(*arg3));
3009 if (arg4)
3010 POST_WRITE(arg4, struct_timespec_sz);
27523011 }
27533012}
27543013
2755PRE_SYSCALL(ppoll)(__sanitizer_pollfd *arg0, long arg1, void *arg2,
2756 const kernel_sigset_t *arg3, long arg4) {
2757 if (arg3) PRE_READ(arg3, arg4);
3014PRE_SYSCALL(ppoll)
3015(__sanitizer_pollfd *arg0, long arg1, void *arg2, const kernel_sigset_t *arg3,
3016 long arg4) {
3017 if (arg3)
3018 PRE_READ(arg3, arg4);
27583019}
27593020
2760POST_SYSCALL(ppoll)(long res, __sanitizer_pollfd *arg0, long arg1, void *arg2,
2761 const void *arg3, long arg4) {
3021POST_SYSCALL(ppoll)
3022(long res, __sanitizer_pollfd *arg0, long arg1, void *arg2, const void *arg3,
3023 long arg4) {
27623024 if (res >= 0) {
2763 if (arg0) POST_WRITE(arg0, sizeof(*arg0));
2764 if (arg2) POST_WRITE(arg2, struct_timespec_sz);
3025 if (arg0)
3026 POST_WRITE(arg0, sizeof(*arg0));
3027 if (arg2)
3028 POST_WRITE(arg2, struct_timespec_sz);
27653029 }
27663030}
27673031
......@@ -2769,81 +3033,79 @@ PRE_SYSCALL(syncfs)(long fd) {}
27693033
27703034POST_SYSCALL(syncfs)(long res, long fd) {}
27713035
2772PRE_SYSCALL(perf_event_open)(__sanitizer_perf_event_attr *attr_uptr, long pid,
2773 long cpu, long group_fd, long flags) {
2774 if (attr_uptr) PRE_READ(attr_uptr, attr_uptr->size);
3036PRE_SYSCALL(perf_event_open)
3037(__sanitizer_perf_event_attr *attr_uptr, long pid, long cpu, long group_fd,
3038 long flags) {
3039 if (attr_uptr)
3040 PRE_READ(attr_uptr, attr_uptr->size);
27753041}
27763042
2777POST_SYSCALL(perf_event_open)(long res, __sanitizer_perf_event_attr *attr_uptr,
2778 long pid, long cpu, long group_fd, long flags) {}
3043POST_SYSCALL(perf_event_open)
3044(long res, __sanitizer_perf_event_attr *attr_uptr, long pid, long cpu,
3045 long group_fd, long flags) {}
27793046
2780PRE_SYSCALL(mmap_pgoff)(long addr, long len, long prot, long flags, long fd,
2781 long pgoff) {}
3047PRE_SYSCALL(mmap_pgoff)
3048(long addr, long len, long prot, long flags, long fd, long pgoff) {}
27823049
2783POST_SYSCALL(mmap_pgoff)(long res, long addr, long len, long prot, long flags,
2784 long fd, long pgoff) {}
3050POST_SYSCALL(mmap_pgoff)
3051(long res, long addr, long len, long prot, long flags, long fd, long pgoff) {}
27853052
27863053PRE_SYSCALL(old_mmap)(void *arg) {}
27873054
27883055POST_SYSCALL(old_mmap)(long res, void *arg) {}
27893056
2790PRE_SYSCALL(name_to_handle_at)(long dfd, const void *name, void *handle,
2791 void *mnt_id, long flag) {}
3057PRE_SYSCALL(name_to_handle_at)
3058(long dfd, const void *name, void *handle, void *mnt_id, long flag) {}
27923059
2793POST_SYSCALL(name_to_handle_at)(long res, long dfd, const void *name,
2794 void *handle, void *mnt_id, long flag) {}
3060POST_SYSCALL(name_to_handle_at)
3061(long res, long dfd, const void *name, void *handle, void *mnt_id, long flag) {}
27953062
27963063PRE_SYSCALL(open_by_handle_at)(long mountdirfd, void *handle, long flags) {}
27973064
2798POST_SYSCALL(open_by_handle_at)(long res, long mountdirfd, void *handle,
2799 long flags) {}
3065POST_SYSCALL(open_by_handle_at)
3066(long res, long mountdirfd, void *handle, long flags) {}
28003067
28013068PRE_SYSCALL(setns)(long fd, long nstype) {}
28023069
28033070POST_SYSCALL(setns)(long res, long fd, long nstype) {}
28043071
2805PRE_SYSCALL(process_vm_readv)(long pid, const __sanitizer_iovec *lvec,
2806 long liovcnt, const void *rvec, long riovcnt,
2807 long flags) {}
3072PRE_SYSCALL(process_vm_readv)
3073(long pid, const __sanitizer_iovec *lvec, long liovcnt, const void *rvec,
3074 long riovcnt, long flags) {}
28083075
2809POST_SYSCALL(process_vm_readv)(long res, long pid,
2810 const __sanitizer_iovec *lvec, long liovcnt,
2811 const void *rvec, long riovcnt, long flags) {
3076POST_SYSCALL(process_vm_readv)
3077(long res, long pid, const __sanitizer_iovec *lvec, long liovcnt,
3078 const void *rvec, long riovcnt, long flags) {
28123079 if (res >= 0) {
2813 if (lvec) kernel_write_iovec(lvec, liovcnt, res);
3080 if (lvec)
3081 kernel_write_iovec(lvec, liovcnt, res);
28143082 }
28153083}
28163084
2817PRE_SYSCALL(process_vm_writev)(long pid, const __sanitizer_iovec *lvec,
2818 long liovcnt, const void *rvec, long riovcnt,
2819 long flags) {}
3085PRE_SYSCALL(process_vm_writev)
3086(long pid, const __sanitizer_iovec *lvec, long liovcnt, const void *rvec,
3087 long riovcnt, long flags) {}
28203088
2821POST_SYSCALL(process_vm_writev)(long res, long pid,
2822 const __sanitizer_iovec *lvec, long liovcnt,
2823 const void *rvec, long riovcnt, long flags) {
3089POST_SYSCALL(process_vm_writev)
3090(long res, long pid, const __sanitizer_iovec *lvec, long liovcnt,
3091 const void *rvec, long riovcnt, long flags) {
28243092 if (res >= 0) {
2825 if (lvec) kernel_read_iovec(lvec, liovcnt, res);
3093 if (lvec)
3094 kernel_read_iovec(lvec, liovcnt, res);
28263095 }
28273096}
28283097
2829PRE_SYSCALL(fork)() {
2830 COMMON_SYSCALL_PRE_FORK();
2831}
3098PRE_SYSCALL(fork)() { COMMON_SYSCALL_PRE_FORK(); }
28323099
2833POST_SYSCALL(fork)(long res) {
2834 COMMON_SYSCALL_POST_FORK(res);
2835}
3100POST_SYSCALL(fork)(long res) { COMMON_SYSCALL_POST_FORK(res); }
28363101
2837PRE_SYSCALL(vfork)() {
2838 COMMON_SYSCALL_PRE_FORK();
2839}
3102PRE_SYSCALL(vfork)() { COMMON_SYSCALL_PRE_FORK(); }
28403103
2841POST_SYSCALL(vfork)(long res) {
2842 COMMON_SYSCALL_POST_FORK(res);
2843}
3104POST_SYSCALL(vfork)(long res) { COMMON_SYSCALL_POST_FORK(res); }
28443105
2845PRE_SYSCALL(sigaction)(long signum, const __sanitizer_kernel_sigaction_t *act,
2846 __sanitizer_kernel_sigaction_t *oldact) {
3106PRE_SYSCALL(sigaction)
3107(long signum, const __sanitizer_kernel_sigaction_t *act,
3108 __sanitizer_kernel_sigaction_t *oldact) {
28473109 if (act) {
28483110 PRE_READ(&act->sigaction, sizeof(act->sigaction));
28493111 PRE_READ(&act->sa_flags, sizeof(act->sa_flags));
......@@ -2851,15 +3113,16 @@ PRE_SYSCALL(sigaction)(long signum, const __sanitizer_kernel_sigaction_t *act,
28513113 }
28523114}
28533115
2854POST_SYSCALL(sigaction)(long res, long signum,
2855 const __sanitizer_kernel_sigaction_t *act,
2856 __sanitizer_kernel_sigaction_t *oldact) {
2857 if (res >= 0 && oldact) POST_WRITE(oldact, sizeof(*oldact));
3116POST_SYSCALL(sigaction)
3117(long res, long signum, const __sanitizer_kernel_sigaction_t *act,
3118 __sanitizer_kernel_sigaction_t *oldact) {
3119 if (res >= 0 && oldact)
3120 POST_WRITE(oldact, sizeof(*oldact));
28583121}
28593122
2860PRE_SYSCALL(rt_sigaction)(long signum,
2861 const __sanitizer_kernel_sigaction_t *act,
2862 __sanitizer_kernel_sigaction_t *oldact, SIZE_T sz) {
3123PRE_SYSCALL(rt_sigaction)
3124(long signum, const __sanitizer_kernel_sigaction_t *act,
3125 __sanitizer_kernel_sigaction_t *oldact, SIZE_T sz) {
28633126 if (act) {
28643127 PRE_READ(&act->sigaction, sizeof(act->sigaction));
28653128 PRE_READ(&act->sa_flags, sizeof(act->sa_flags));
......@@ -2867,9 +3130,9 @@ PRE_SYSCALL(rt_sigaction)(long signum,
28673130 }
28683131}
28693132
2870POST_SYSCALL(rt_sigaction)(long res, long signum,
2871 const __sanitizer_kernel_sigaction_t *act,
2872 __sanitizer_kernel_sigaction_t *oldact, SIZE_T sz) {
3133POST_SYSCALL(rt_sigaction)
3134(long res, long signum, const __sanitizer_kernel_sigaction_t *act,
3135 __sanitizer_kernel_sigaction_t *oldact, SIZE_T sz) {
28733136 if (res >= 0 && oldact) {
28743137 SIZE_T oldact_sz = ((char *)&oldact->sa_mask) - ((char *)oldact) + sz;
28753138 POST_WRITE(oldact, oldact_sz);
......@@ -2906,11 +3169,11 @@ POST_SYSCALL(sigaltstack)(long res, void *ss, void *oss) {
29063169}
29073170} // extern "C"
29083171
2909#undef PRE_SYSCALL
2910#undef PRE_READ
2911#undef PRE_WRITE
2912#undef POST_SYSCALL
2913#undef POST_READ
2914#undef POST_WRITE
3172# undef PRE_SYSCALL
3173# undef PRE_READ
3174# undef PRE_WRITE
3175# undef POST_SYSCALL
3176# undef POST_READ
3177# undef POST_WRITE
29153178
29163179#endif // SANITIZER_LINUX
lib/tsan/sanitizer_common/sanitizer_coverage_interface.inc+10
......@@ -27,6 +27,16 @@ INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_gep)
2727INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_pc_guard)
2828INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_pc_guard_init)
2929INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_pc_indir)
30INTERFACE_WEAK_FUNCTION(__sanitizer_cov_load1)
31INTERFACE_WEAK_FUNCTION(__sanitizer_cov_load2)
32INTERFACE_WEAK_FUNCTION(__sanitizer_cov_load4)
33INTERFACE_WEAK_FUNCTION(__sanitizer_cov_load8)
34INTERFACE_WEAK_FUNCTION(__sanitizer_cov_load16)
35INTERFACE_WEAK_FUNCTION(__sanitizer_cov_store1)
36INTERFACE_WEAK_FUNCTION(__sanitizer_cov_store2)
37INTERFACE_WEAK_FUNCTION(__sanitizer_cov_store4)
38INTERFACE_WEAK_FUNCTION(__sanitizer_cov_store8)
39INTERFACE_WEAK_FUNCTION(__sanitizer_cov_store16)
3040INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_switch)
3141INTERFACE_WEAK_FUNCTION(__sanitizer_cov_8bit_counters_init)
3242INTERFACE_WEAK_FUNCTION(__sanitizer_cov_bool_flag_init)
lib/tsan/sanitizer_common/sanitizer_coverage_win_dll_thunk.cpp created+20
......@@ -0,0 +1,20 @@
1//===-- sanitizer_coverage_win_dll_thunk.cpp ------------------------------===//
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 defines a family of thunks that should be statically linked into
10// the DLLs that have instrumentation in order to delegate the calls to the
11// shared runtime that lives in the main binary.
12// See https://github.com/google/sanitizers/issues/209 for the details.
13//===----------------------------------------------------------------------===//
14#ifdef SANITIZER_DLL_THUNK
15#include "sanitizer_win_dll_thunk.h"
16// Sanitizer Coverage interface functions.
17#define INTERFACE_FUNCTION(Name) INTERCEPT_SANITIZER_FUNCTION(Name)
18#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name)
19#include "sanitizer_coverage_interface.inc"
20#endif // SANITIZER_DLL_THUNK
lib/tsan/sanitizer_common/sanitizer_coverage_win_dynamic_runtime_thunk.cpp created+26
......@@ -0,0 +1,26 @@
1//===-- sanitizer_coverage_win_dynamic_runtime_thunk.cpp ------------------===//
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 defines things that need to be present in the application modules
10// to interact with Sanitizer Coverage, when it is included in a dll.
11//
12//===----------------------------------------------------------------------===//
13#ifdef SANITIZER_DYNAMIC_RUNTIME_THUNK
14#define SANITIZER_IMPORT_INTERFACE 1
15#include "sanitizer_win_defs.h"
16// Define weak alias for all weak functions imported from sanitizer coverage.
17#define INTERFACE_FUNCTION(Name)
18#define INTERFACE_WEAK_FUNCTION(Name) WIN_WEAK_IMPORT_DEF(Name)
19#include "sanitizer_coverage_interface.inc"
20#endif // SANITIZER_DYNAMIC_RUNTIME_THUNK
21
22namespace __sanitizer {
23// Add one, otherwise unused, external symbol to this object file so that the
24// Visual C++ linker includes it and reads the .drective section.
25void ForceWholeArchiveIncludeForSanCov() {}
26}
lib/tsan/sanitizer_common/sanitizer_coverage_win_weak_interception.cpp created+23
......@@ -0,0 +1,23 @@
1//===-- sanitizer_coverage_win_weak_interception.cpp ----------------------===//
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// This module should be included in Sanitizer Coverage when it implemented as a
9// shared library on Windows (dll), in order to delegate the calls of weak
10// functions to the implementation in the main executable when a strong
11// definition is provided.
12//===----------------------------------------------------------------------===//
13#ifdef SANITIZER_DYNAMIC
14#include "sanitizer_win_weak_interception.h"
15#include "sanitizer_interface_internal.h"
16#include "sancov_flags.h"
17// Check if strong definitions for weak functions are present in the main
18// executable. If that is the case, override dll functions to point to strong
19// implementations.
20#define INTERFACE_FUNCTION(Name)
21#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name)
22#include "sanitizer_coverage_interface.inc"
23#endif // SANITIZER_DYNAMIC
lib/tsan/sanitizer_common/sanitizer_deadlock_detector.h+1-1
......@@ -293,7 +293,7 @@ class DeadlockDetector {
293293 }
294294
295295 // Returns true iff dtls is empty (no locks are currently held) and we can
296 // add the node to the currently held locks w/o chanding the global state.
296 // add the node to the currently held locks w/o changing the global state.
297297 // This operation is thread-safe as it only touches the dtls.
298298 bool onFirstLock(DeadlockDetectorTLS<BV> *dtls, uptr node, u32 stk = 0) {
299299 if (!dtls->empty()) return false;
lib/tsan/sanitizer_common/sanitizer_dense_map.h created+705
......@@ -0,0 +1,705 @@
1//===- sanitizer_dense_map.h - Dense probed hash table ----------*- 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 is fork of llvm/ADT/DenseMap.h class with the following changes:
10// * Use mmap to allocate.
11// * No iterators.
12// * Does not shrink.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef SANITIZER_DENSE_MAP_H
17#define SANITIZER_DENSE_MAP_H
18
19#include "sanitizer_common.h"
20#include "sanitizer_dense_map_info.h"
21#include "sanitizer_internal_defs.h"
22#include "sanitizer_type_traits.h"
23
24namespace __sanitizer {
25
26template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
27 typename BucketT>
28class DenseMapBase {
29 public:
30 using size_type = unsigned;
31 using key_type = KeyT;
32 using mapped_type = ValueT;
33 using value_type = BucketT;
34
35 WARN_UNUSED_RESULT bool empty() const { return getNumEntries() == 0; }
36 unsigned size() const { return getNumEntries(); }
37
38 /// Grow the densemap so that it can contain at least \p NumEntries items
39 /// before resizing again.
40 void reserve(size_type NumEntries) {
41 auto NumBuckets = getMinBucketToReserveForEntries(NumEntries);
42 if (NumBuckets > getNumBuckets())
43 grow(NumBuckets);
44 }
45
46 void clear() {
47 if (getNumEntries() == 0 && getNumTombstones() == 0)
48 return;
49
50 const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
51 if (__sanitizer::is_trivially_destructible<ValueT>::value) {
52 // Use a simpler loop when values don't need destruction.
53 for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P)
54 P->getFirst() = EmptyKey;
55 } else {
56 unsigned NumEntries = getNumEntries();
57 for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {
58 if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey)) {
59 if (!KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) {
60 P->getSecond().~ValueT();
61 --NumEntries;
62 }
63 P->getFirst() = EmptyKey;
64 }
65 }
66 CHECK_EQ(NumEntries, 0);
67 }
68 setNumEntries(0);
69 setNumTombstones(0);
70 }
71
72 /// Return 1 if the specified key is in the map, 0 otherwise.
73 size_type count(const KeyT &Key) const {
74 const BucketT *TheBucket;
75 return LookupBucketFor(Key, TheBucket) ? 1 : 0;
76 }
77
78 value_type *find(const KeyT &Key) {
79 BucketT *TheBucket;
80 if (LookupBucketFor(Key, TheBucket))
81 return TheBucket;
82 return nullptr;
83 }
84 const value_type *find(const KeyT &Key) const {
85 const BucketT *TheBucket;
86 if (LookupBucketFor(Key, TheBucket))
87 return TheBucket;
88 return nullptr;
89 }
90
91 /// Alternate version of find() which allows a different, and possibly
92 /// less expensive, key type.
93 /// The DenseMapInfo is responsible for supplying methods
94 /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
95 /// type used.
96 template <class LookupKeyT>
97 value_type *find_as(const LookupKeyT &Key) {
98 BucketT *TheBucket;
99 if (LookupBucketFor(Key, TheBucket))
100 return TheBucket;
101 return nullptr;
102 }
103 template <class LookupKeyT>
104 const value_type *find_as(const LookupKeyT &Key) const {
105 const BucketT *TheBucket;
106 if (LookupBucketFor(Key, TheBucket))
107 return TheBucket;
108 return nullptr;
109 }
110
111 /// lookup - Return the entry for the specified key, or a default
112 /// constructed value if no such entry exists.
113 ValueT lookup(const KeyT &Key) const {
114 const BucketT *TheBucket;
115 if (LookupBucketFor(Key, TheBucket))
116 return TheBucket->getSecond();
117 return ValueT();
118 }
119
120 // Inserts key,value pair into the map if the key isn't already in the map.
121 // If the key is already in the map, it returns false and doesn't update the
122 // value.
123 detail::DenseMapPair<value_type *, bool> insert(const value_type &KV) {
124 return try_emplace(KV.first, KV.second);
125 }
126
127 // Inserts key,value pair into the map if the key isn't already in the map.
128 // If the key is already in the map, it returns false and doesn't update the
129 // value.
130 detail::DenseMapPair<value_type *, bool> insert(value_type &&KV) {
131 return try_emplace(__sanitizer::move(KV.first),
132 __sanitizer::move(KV.second));
133 }
134
135 // Inserts key,value pair into the map if the key isn't already in the map.
136 // The value is constructed in-place if the key is not in the map, otherwise
137 // it is not moved.
138 template <typename... Ts>
139 detail::DenseMapPair<value_type *, bool> try_emplace(KeyT &&Key,
140 Ts &&...Args) {
141 BucketT *TheBucket;
142 if (LookupBucketFor(Key, TheBucket))
143 return {TheBucket, false}; // Already in map.
144
145 // Otherwise, insert the new element.
146 TheBucket = InsertIntoBucket(TheBucket, __sanitizer::move(Key),
147 __sanitizer::forward<Ts>(Args)...);
148 return {TheBucket, true};
149 }
150
151 // Inserts key,value pair into the map if the key isn't already in the map.
152 // The value is constructed in-place if the key is not in the map, otherwise
153 // it is not moved.
154 template <typename... Ts>
155 detail::DenseMapPair<value_type *, bool> try_emplace(const KeyT &Key,
156 Ts &&...Args) {
157 BucketT *TheBucket;
158 if (LookupBucketFor(Key, TheBucket))
159 return {TheBucket, false}; // Already in map.
160
161 // Otherwise, insert the new element.
162 TheBucket =
163 InsertIntoBucket(TheBucket, Key, __sanitizer::forward<Ts>(Args)...);
164 return {TheBucket, true};
165 }
166
167 /// Alternate version of insert() which allows a different, and possibly
168 /// less expensive, key type.
169 /// The DenseMapInfo is responsible for supplying methods
170 /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
171 /// type used.
172 template <typename LookupKeyT>
173 detail::DenseMapPair<value_type *, bool> insert_as(value_type &&KV,
174 const LookupKeyT &Val) {
175 BucketT *TheBucket;
176 if (LookupBucketFor(Val, TheBucket))
177 return {TheBucket, false}; // Already in map.
178
179 // Otherwise, insert the new element.
180 TheBucket =
181 InsertIntoBucketWithLookup(TheBucket, __sanitizer::move(KV.first),
182 __sanitizer::move(KV.second), Val);
183 return {TheBucket, true};
184 }
185
186 bool erase(const KeyT &Val) {
187 BucketT *TheBucket;
188 if (!LookupBucketFor(Val, TheBucket))
189 return false; // not in map.
190
191 TheBucket->getSecond().~ValueT();
192 TheBucket->getFirst() = getTombstoneKey();
193 decrementNumEntries();
194 incrementNumTombstones();
195 return true;
196 }
197
198 void erase(value_type *I) {
199 CHECK_NE(I, nullptr);
200 BucketT *TheBucket = &*I;
201 TheBucket->getSecond().~ValueT();
202 TheBucket->getFirst() = getTombstoneKey();
203 decrementNumEntries();
204 incrementNumTombstones();
205 }
206
207 value_type &FindAndConstruct(const KeyT &Key) {
208 BucketT *TheBucket;
209 if (LookupBucketFor(Key, TheBucket))
210 return *TheBucket;
211
212 return *InsertIntoBucket(TheBucket, Key);
213 }
214
215 ValueT &operator[](const KeyT &Key) { return FindAndConstruct(Key).second; }
216
217 value_type &FindAndConstruct(KeyT &&Key) {
218 BucketT *TheBucket;
219 if (LookupBucketFor(Key, TheBucket))
220 return *TheBucket;
221
222 return *InsertIntoBucket(TheBucket, __sanitizer::move(Key));
223 }
224
225 ValueT &operator[](KeyT &&Key) {
226 return FindAndConstruct(__sanitizer::move(Key)).second;
227 }
228
229 /// Iterate over active entries of the container.
230 ///
231 /// Function can return fast to stop the process.
232 template <class Fn>
233 void forEach(Fn fn) {
234 const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
235 for (auto *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {
236 const KeyT K = P->getFirst();
237 if (!KeyInfoT::isEqual(K, EmptyKey) &&
238 !KeyInfoT::isEqual(K, TombstoneKey)) {
239 if (!fn(*P))
240 return;
241 }
242 }
243 }
244
245 template <class Fn>
246 void forEach(Fn fn) const {
247 const_cast<DenseMapBase *>(this)->forEach(
248 [&](const value_type &KV) { return fn(KV); });
249 }
250
251 protected:
252 DenseMapBase() = default;
253
254 void destroyAll() {
255 if (getNumBuckets() == 0) // Nothing to do.
256 return;
257
258 const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
259 for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {
260 if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) &&
261 !KeyInfoT::isEqual(P->getFirst(), TombstoneKey))
262 P->getSecond().~ValueT();
263 P->getFirst().~KeyT();
264 }
265 }
266
267 void initEmpty() {
268 setNumEntries(0);
269 setNumTombstones(0);
270
271 CHECK_EQ((getNumBuckets() & (getNumBuckets() - 1)), 0);
272 const KeyT EmptyKey = getEmptyKey();
273 for (BucketT *B = getBuckets(), *E = getBucketsEnd(); B != E; ++B)
274 ::new (&B->getFirst()) KeyT(EmptyKey);
275 }
276
277 /// Returns the number of buckets to allocate to ensure that the DenseMap can
278 /// accommodate \p NumEntries without need to grow().
279 unsigned getMinBucketToReserveForEntries(unsigned NumEntries) {
280 // Ensure that "NumEntries * 4 < NumBuckets * 3"
281 if (NumEntries == 0)
282 return 0;
283 // +1 is required because of the strict equality.
284 // For example if NumEntries is 48, we need to return 401.
285 return RoundUpToPowerOfTwo((NumEntries * 4 / 3 + 1) + /* NextPowerOf2 */ 1);
286 }
287
288 void moveFromOldBuckets(BucketT *OldBucketsBegin, BucketT *OldBucketsEnd) {
289 initEmpty();
290
291 // Insert all the old elements.
292 const KeyT EmptyKey = getEmptyKey();
293 const KeyT TombstoneKey = getTombstoneKey();
294 for (BucketT *B = OldBucketsBegin, *E = OldBucketsEnd; B != E; ++B) {
295 if (!KeyInfoT::isEqual(B->getFirst(), EmptyKey) &&
296 !KeyInfoT::isEqual(B->getFirst(), TombstoneKey)) {
297 // Insert the key/value into the new table.
298 BucketT *DestBucket;
299 bool FoundVal = LookupBucketFor(B->getFirst(), DestBucket);
300 (void)FoundVal; // silence warning.
301 CHECK(!FoundVal);
302 DestBucket->getFirst() = __sanitizer::move(B->getFirst());
303 ::new (&DestBucket->getSecond())
304 ValueT(__sanitizer::move(B->getSecond()));
305 incrementNumEntries();
306
307 // Free the value.
308 B->getSecond().~ValueT();
309 }
310 B->getFirst().~KeyT();
311 }
312 }
313
314 template <typename OtherBaseT>
315 void copyFrom(
316 const DenseMapBase<OtherBaseT, KeyT, ValueT, KeyInfoT, BucketT> &other) {
317 CHECK_NE(&other, this);
318 CHECK_EQ(getNumBuckets(), other.getNumBuckets());
319
320 setNumEntries(other.getNumEntries());
321 setNumTombstones(other.getNumTombstones());
322
323 if (__sanitizer::is_trivially_copyable<KeyT>::value &&
324 __sanitizer::is_trivially_copyable<ValueT>::value)
325 internal_memcpy(reinterpret_cast<void *>(getBuckets()),
326 other.getBuckets(), getNumBuckets() * sizeof(BucketT));
327 else
328 for (uptr i = 0; i < getNumBuckets(); ++i) {
329 ::new (&getBuckets()[i].getFirst())
330 KeyT(other.getBuckets()[i].getFirst());
331 if (!KeyInfoT::isEqual(getBuckets()[i].getFirst(), getEmptyKey()) &&
332 !KeyInfoT::isEqual(getBuckets()[i].getFirst(), getTombstoneKey()))
333 ::new (&getBuckets()[i].getSecond())
334 ValueT(other.getBuckets()[i].getSecond());
335 }
336 }
337
338 static unsigned getHashValue(const KeyT &Val) {
339 return KeyInfoT::getHashValue(Val);
340 }
341
342 template <typename LookupKeyT>
343 static unsigned getHashValue(const LookupKeyT &Val) {
344 return KeyInfoT::getHashValue(Val);
345 }
346
347 static const KeyT getEmptyKey() { return KeyInfoT::getEmptyKey(); }
348
349 static const KeyT getTombstoneKey() { return KeyInfoT::getTombstoneKey(); }
350
351 private:
352 unsigned getNumEntries() const {
353 return static_cast<const DerivedT *>(this)->getNumEntries();
354 }
355
356 void setNumEntries(unsigned Num) {
357 static_cast<DerivedT *>(this)->setNumEntries(Num);
358 }
359
360 void incrementNumEntries() { setNumEntries(getNumEntries() + 1); }
361
362 void decrementNumEntries() { setNumEntries(getNumEntries() - 1); }
363
364 unsigned getNumTombstones() const {
365 return static_cast<const DerivedT *>(this)->getNumTombstones();
366 }
367
368 void setNumTombstones(unsigned Num) {
369 static_cast<DerivedT *>(this)->setNumTombstones(Num);
370 }
371
372 void incrementNumTombstones() { setNumTombstones(getNumTombstones() + 1); }
373
374 void decrementNumTombstones() { setNumTombstones(getNumTombstones() - 1); }
375
376 const BucketT *getBuckets() const {
377 return static_cast<const DerivedT *>(this)->getBuckets();
378 }
379
380 BucketT *getBuckets() { return static_cast<DerivedT *>(this)->getBuckets(); }
381
382 unsigned getNumBuckets() const {
383 return static_cast<const DerivedT *>(this)->getNumBuckets();
384 }
385
386 BucketT *getBucketsEnd() { return getBuckets() + getNumBuckets(); }
387
388 const BucketT *getBucketsEnd() const {
389 return getBuckets() + getNumBuckets();
390 }
391
392 void grow(unsigned AtLeast) { static_cast<DerivedT *>(this)->grow(AtLeast); }
393
394 template <typename KeyArg, typename... ValueArgs>
395 BucketT *InsertIntoBucket(BucketT *TheBucket, KeyArg &&Key,
396 ValueArgs &&...Values) {
397 TheBucket = InsertIntoBucketImpl(Key, Key, TheBucket);
398
399 TheBucket->getFirst() = __sanitizer::forward<KeyArg>(Key);
400 ::new (&TheBucket->getSecond())
401 ValueT(__sanitizer::forward<ValueArgs>(Values)...);
402 return TheBucket;
403 }
404
405 template <typename LookupKeyT>
406 BucketT *InsertIntoBucketWithLookup(BucketT *TheBucket, KeyT &&Key,
407 ValueT &&Value, LookupKeyT &Lookup) {
408 TheBucket = InsertIntoBucketImpl(Key, Lookup, TheBucket);
409
410 TheBucket->getFirst() = __sanitizer::move(Key);
411 ::new (&TheBucket->getSecond()) ValueT(__sanitizer::move(Value));
412 return TheBucket;
413 }
414
415 template <typename LookupKeyT>
416 BucketT *InsertIntoBucketImpl(const KeyT &Key, const LookupKeyT &Lookup,
417 BucketT *TheBucket) {
418 // If the load of the hash table is more than 3/4, or if fewer than 1/8 of
419 // the buckets are empty (meaning that many are filled with tombstones),
420 // grow the table.
421 //
422 // The later case is tricky. For example, if we had one empty bucket with
423 // tons of tombstones, failing lookups (e.g. for insertion) would have to
424 // probe almost the entire table until it found the empty bucket. If the
425 // table completely filled with tombstones, no lookup would ever succeed,
426 // causing infinite loops in lookup.
427 unsigned NewNumEntries = getNumEntries() + 1;
428 unsigned NumBuckets = getNumBuckets();
429 if (UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) {
430 this->grow(NumBuckets * 2);
431 LookupBucketFor(Lookup, TheBucket);
432 NumBuckets = getNumBuckets();
433 } else if (UNLIKELY(NumBuckets - (NewNumEntries + getNumTombstones()) <=
434 NumBuckets / 8)) {
435 this->grow(NumBuckets);
436 LookupBucketFor(Lookup, TheBucket);
437 }
438 CHECK(TheBucket);
439
440 // Only update the state after we've grown our bucket space appropriately
441 // so that when growing buckets we have self-consistent entry count.
442 incrementNumEntries();
443
444 // If we are writing over a tombstone, remember this.
445 const KeyT EmptyKey = getEmptyKey();
446 if (!KeyInfoT::isEqual(TheBucket->getFirst(), EmptyKey))
447 decrementNumTombstones();
448
449 return TheBucket;
450 }
451
452 /// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in
453 /// FoundBucket. If the bucket contains the key and a value, this returns
454 /// true, otherwise it returns a bucket with an empty marker or tombstone and
455 /// returns false.
456 template <typename LookupKeyT>
457 bool LookupBucketFor(const LookupKeyT &Val,
458 const BucketT *&FoundBucket) const {
459 const BucketT *BucketsPtr = getBuckets();
460 const unsigned NumBuckets = getNumBuckets();
461
462 if (NumBuckets == 0) {
463 FoundBucket = nullptr;
464 return false;
465 }
466
467 // FoundTombstone - Keep track of whether we find a tombstone while probing.
468 const BucketT *FoundTombstone = nullptr;
469 const KeyT EmptyKey = getEmptyKey();
470 const KeyT TombstoneKey = getTombstoneKey();
471 CHECK(!KeyInfoT::isEqual(Val, EmptyKey));
472 CHECK(!KeyInfoT::isEqual(Val, TombstoneKey));
473
474 unsigned BucketNo = getHashValue(Val) & (NumBuckets - 1);
475 unsigned ProbeAmt = 1;
476 while (true) {
477 const BucketT *ThisBucket = BucketsPtr + BucketNo;
478 // Found Val's bucket? If so, return it.
479 if (LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) {
480 FoundBucket = ThisBucket;
481 return true;
482 }
483
484 // If we found an empty bucket, the key doesn't exist in the set.
485 // Insert it and return the default value.
486 if (LIKELY(KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey))) {
487 // If we've already seen a tombstone while probing, fill it in instead
488 // of the empty bucket we eventually probed to.
489 FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket;
490 return false;
491 }
492
493 // If this is a tombstone, remember it. If Val ends up not in the map, we
494 // prefer to return it than something that would require more probing.
495 if (KeyInfoT::isEqual(ThisBucket->getFirst(), TombstoneKey) &&
496 !FoundTombstone)
497 FoundTombstone = ThisBucket; // Remember the first tombstone found.
498
499 // Otherwise, it's a hash collision or a tombstone, continue quadratic
500 // probing.
501 BucketNo += ProbeAmt++;
502 BucketNo &= (NumBuckets - 1);
503 }
504 }
505
506 template <typename LookupKeyT>
507 bool LookupBucketFor(const LookupKeyT &Val, BucketT *&FoundBucket) {
508 const BucketT *ConstFoundBucket;
509 bool Result = const_cast<const DenseMapBase *>(this)->LookupBucketFor(
510 Val, ConstFoundBucket);
511 FoundBucket = const_cast<BucketT *>(ConstFoundBucket);
512 return Result;
513 }
514
515 public:
516 /// Return the approximate size (in bytes) of the actual map.
517 /// This is just the raw memory used by DenseMap.
518 /// If entries are pointers to objects, the size of the referenced objects
519 /// are not included.
520 uptr getMemorySize() const {
521 return RoundUpTo(getNumBuckets() * sizeof(BucketT), GetPageSizeCached());
522 }
523};
524
525/// Equality comparison for DenseMap.
526///
527/// Iterates over elements of LHS confirming that each (key, value) pair in LHS
528/// is also in RHS, and that no additional pairs are in RHS.
529/// Equivalent to N calls to RHS.find and N value comparisons. Amortized
530/// complexity is linear, worst case is O(N^2) (if every hash collides).
531template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
532 typename BucketT>
533bool operator==(
534 const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &LHS,
535 const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &RHS) {
536 if (LHS.size() != RHS.size())
537 return false;
538
539 bool R = true;
540 LHS.forEach(
541 [&](const typename DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT,
542 BucketT>::value_type &KV) -> bool {
543 const auto *I = RHS.find(KV.first);
544 if (!I || I->second != KV.second) {
545 R = false;
546 return false;
547 }
548 return true;
549 });
550
551 return R;
552}
553
554/// Inequality comparison for DenseMap.
555///
556/// Equivalent to !(LHS == RHS). See operator== for performance notes.
557template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
558 typename BucketT>
559bool operator!=(
560 const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &LHS,
561 const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &RHS) {
562 return !(LHS == RHS);
563}
564
565template <typename KeyT, typename ValueT,
566 typename KeyInfoT = DenseMapInfo<KeyT>,
567 typename BucketT = detail::DenseMapPair<KeyT, ValueT>>
568class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
569 KeyT, ValueT, KeyInfoT, BucketT> {
570 friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
571
572 // Lift some types from the dependent base class into this class for
573 // simplicity of referring to them.
574 using BaseT = DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
575
576 BucketT *Buckets = nullptr;
577 unsigned NumEntries = 0;
578 unsigned NumTombstones = 0;
579 unsigned NumBuckets = 0;
580
581 public:
582 /// Create a DenseMap with an optional \p InitialReserve that guarantee that
583 /// this number of elements can be inserted in the map without grow()
584 explicit DenseMap(unsigned InitialReserve) { init(InitialReserve); }
585 constexpr DenseMap() = default;
586
587 DenseMap(const DenseMap &other) : BaseT() {
588 init(0);
589 copyFrom(other);
590 }
591
592 DenseMap(DenseMap &&other) : BaseT() {
593 init(0);
594 swap(other);
595 }
596
597 ~DenseMap() {
598 this->destroyAll();
599 deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets);
600 }
601
602 void swap(DenseMap &RHS) {
603 Swap(Buckets, RHS.Buckets);
604 Swap(NumEntries, RHS.NumEntries);
605 Swap(NumTombstones, RHS.NumTombstones);
606 Swap(NumBuckets, RHS.NumBuckets);
607 }
608
609 DenseMap &operator=(const DenseMap &other) {
610 if (&other != this)
611 copyFrom(other);
612 return *this;
613 }
614
615 DenseMap &operator=(DenseMap &&other) {
616 this->destroyAll();
617 deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets, alignof(BucketT));
618 init(0);
619 swap(other);
620 return *this;
621 }
622
623 void copyFrom(const DenseMap &other) {
624 this->destroyAll();
625 deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets);
626 if (allocateBuckets(other.NumBuckets)) {
627 this->BaseT::copyFrom(other);
628 } else {
629 NumEntries = 0;
630 NumTombstones = 0;
631 }
632 }
633
634 void init(unsigned InitNumEntries) {
635 auto InitBuckets = BaseT::getMinBucketToReserveForEntries(InitNumEntries);
636 if (allocateBuckets(InitBuckets)) {
637 this->BaseT::initEmpty();
638 } else {
639 NumEntries = 0;
640 NumTombstones = 0;
641 }
642 }
643
644 void grow(unsigned AtLeast) {
645 unsigned OldNumBuckets = NumBuckets;
646 BucketT *OldBuckets = Buckets;
647
648 allocateBuckets(RoundUpToPowerOfTwo(Max<unsigned>(64, AtLeast)));
649 CHECK(Buckets);
650 if (!OldBuckets) {
651 this->BaseT::initEmpty();
652 return;
653 }
654
655 this->moveFromOldBuckets(OldBuckets, OldBuckets + OldNumBuckets);
656
657 // Free the old table.
658 deallocate_buffer(OldBuckets, sizeof(BucketT) * OldNumBuckets);
659 }
660
661 private:
662 unsigned getNumEntries() const { return NumEntries; }
663
664 void setNumEntries(unsigned Num) { NumEntries = Num; }
665
666 unsigned getNumTombstones() const { return NumTombstones; }
667
668 void setNumTombstones(unsigned Num) { NumTombstones = Num; }
669
670 BucketT *getBuckets() const { return Buckets; }
671
672 unsigned getNumBuckets() const { return NumBuckets; }
673
674 bool allocateBuckets(unsigned Num) {
675 NumBuckets = Num;
676 if (NumBuckets == 0) {
677 Buckets = nullptr;
678 return false;
679 }
680
681 uptr Size = sizeof(BucketT) * NumBuckets;
682 if (Size * 2 <= GetPageSizeCached()) {
683 // We always allocate at least a page, so use entire space.
684 unsigned Log2 = MostSignificantSetBitIndex(GetPageSizeCached() / Size);
685 Size <<= Log2;
686 NumBuckets <<= Log2;
687 CHECK_EQ(Size, sizeof(BucketT) * NumBuckets);
688 CHECK_GT(Size * 2, GetPageSizeCached());
689 }
690 Buckets = static_cast<BucketT *>(allocate_buffer(Size));
691 return true;
692 }
693
694 static void *allocate_buffer(uptr Size) {
695 return MmapOrDie(RoundUpTo(Size, GetPageSizeCached()), "DenseMap");
696 }
697
698 static void deallocate_buffer(void *Ptr, uptr Size) {
699 UnmapOrDie(Ptr, RoundUpTo(Size, GetPageSizeCached()));
700 }
701};
702
703} // namespace __sanitizer
704
705#endif // SANITIZER_DENSE_MAP_H
lib/tsan/sanitizer_common/sanitizer_dense_map_info.h created+282
......@@ -0,0 +1,282 @@
1//===- sanitizer_dense_map_info.h - Type traits for DenseMap ----*- 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#ifndef SANITIZER_DENSE_MAP_INFO_H
10#define SANITIZER_DENSE_MAP_INFO_H
11
12#include "sanitizer_common.h"
13#include "sanitizer_internal_defs.h"
14#include "sanitizer_type_traits.h"
15
16namespace __sanitizer {
17
18namespace detail {
19
20/// Simplistic combination of 32-bit hash values into 32-bit hash values.
21static constexpr unsigned combineHashValue(unsigned a, unsigned b) {
22 u64 key = (u64)a << 32 | (u64)b;
23 key += ~(key << 32);
24 key ^= (key >> 22);
25 key += ~(key << 13);
26 key ^= (key >> 8);
27 key += (key << 3);
28 key ^= (key >> 15);
29 key += ~(key << 27);
30 key ^= (key >> 31);
31 return (unsigned)key;
32}
33
34// We extend a pair to allow users to override the bucket type with their own
35// implementation without requiring two members.
36template <typename KeyT, typename ValueT>
37struct DenseMapPair {
38 KeyT first = {};
39 ValueT second = {};
40 constexpr DenseMapPair() = default;
41 constexpr DenseMapPair(const KeyT &f, const ValueT &s)
42 : first(f), second(s) {}
43
44 template <typename KeyT2, typename ValueT2>
45 constexpr DenseMapPair(KeyT2 &&f, ValueT2 &&s)
46 : first(__sanitizer::forward<KeyT2>(f)),
47 second(__sanitizer::forward<ValueT2>(s)) {}
48
49 constexpr DenseMapPair(const DenseMapPair &other) = default;
50 constexpr DenseMapPair &operator=(const DenseMapPair &other) = default;
51 constexpr DenseMapPair(DenseMapPair &&other) = default;
52 constexpr DenseMapPair &operator=(DenseMapPair &&other) = default;
53
54 KeyT &getFirst() { return first; }
55 const KeyT &getFirst() const { return first; }
56 ValueT &getSecond() { return second; }
57 const ValueT &getSecond() const { return second; }
58};
59
60} // end namespace detail
61
62template <typename T>
63struct DenseMapInfo {
64 // static T getEmptyKey();
65 // static T getTombstoneKey();
66 // static unsigned getHashValue(const T &Val);
67 // static bool isEqual(const T &LHS, const T &RHS);
68};
69
70// Provide DenseMapInfo for all pointers. Come up with sentinel pointer values
71// that are aligned to alignof(T) bytes, but try to avoid requiring T to be
72// complete. This allows clients to instantiate DenseMap<T*, ...> with forward
73// declared key types. Assume that no pointer key type requires more than 4096
74// bytes of alignment.
75template <typename T>
76struct DenseMapInfo<T *> {
77 // The following should hold, but it would require T to be complete:
78 // static_assert(alignof(T) <= (1 << Log2MaxAlign),
79 // "DenseMap does not support pointer keys requiring more than "
80 // "Log2MaxAlign bits of alignment");
81 static constexpr uptr Log2MaxAlign = 12;
82
83 static constexpr T *getEmptyKey() {
84 uptr Val = static_cast<uptr>(-1);
85 Val <<= Log2MaxAlign;
86 return reinterpret_cast<T *>(Val);
87 }
88
89 static constexpr T *getTombstoneKey() {
90 uptr Val = static_cast<uptr>(-2);
91 Val <<= Log2MaxAlign;
92 return reinterpret_cast<T *>(Val);
93 }
94
95 static constexpr unsigned getHashValue(const T *PtrVal) {
96 return (unsigned((uptr)PtrVal) >> 4) ^ (unsigned((uptr)PtrVal) >> 9);
97 }
98
99 static constexpr bool isEqual(const T *LHS, const T *RHS) {
100 return LHS == RHS;
101 }
102};
103
104// Provide DenseMapInfo for chars.
105template <>
106struct DenseMapInfo<char> {
107 static constexpr char getEmptyKey() { return ~0; }
108 static constexpr char getTombstoneKey() { return ~0 - 1; }
109 static constexpr unsigned getHashValue(const char &Val) { return Val * 37U; }
110
111 static constexpr bool isEqual(const char &LHS, const char &RHS) {
112 return LHS == RHS;
113 }
114};
115
116// Provide DenseMapInfo for unsigned chars.
117template <>
118struct DenseMapInfo<unsigned char> {
119 static constexpr unsigned char getEmptyKey() { return ~0; }
120 static constexpr unsigned char getTombstoneKey() { return ~0 - 1; }
121 static constexpr unsigned getHashValue(const unsigned char &Val) {
122 return Val * 37U;
123 }
124
125 static constexpr bool isEqual(const unsigned char &LHS,
126 const unsigned char &RHS) {
127 return LHS == RHS;
128 }
129};
130
131// Provide DenseMapInfo for unsigned shorts.
132template <>
133struct DenseMapInfo<unsigned short> {
134 static constexpr unsigned short getEmptyKey() { return 0xFFFF; }
135 static constexpr unsigned short getTombstoneKey() { return 0xFFFF - 1; }
136 static constexpr unsigned getHashValue(const unsigned short &Val) {
137 return Val * 37U;
138 }
139
140 static constexpr bool isEqual(const unsigned short &LHS,
141 const unsigned short &RHS) {
142 return LHS == RHS;
143 }
144};
145
146// Provide DenseMapInfo for unsigned ints.
147template <>
148struct DenseMapInfo<unsigned> {
149 static constexpr unsigned getEmptyKey() { return ~0U; }
150 static constexpr unsigned getTombstoneKey() { return ~0U - 1; }
151 static constexpr unsigned getHashValue(const unsigned &Val) {
152 return Val * 37U;
153 }
154
155 static constexpr bool isEqual(const unsigned &LHS, const unsigned &RHS) {
156 return LHS == RHS;
157 }
158};
159
160// Provide DenseMapInfo for unsigned longs.
161template <>
162struct DenseMapInfo<unsigned long> {
163 static constexpr unsigned long getEmptyKey() { return ~0UL; }
164 static constexpr unsigned long getTombstoneKey() { return ~0UL - 1L; }
165
166 static constexpr unsigned getHashValue(const unsigned long &Val) {
167 return (unsigned)(Val * 37UL);
168 }
169
170 static constexpr bool isEqual(const unsigned long &LHS,
171 const unsigned long &RHS) {
172 return LHS == RHS;
173 }
174};
175
176// Provide DenseMapInfo for unsigned long longs.
177template <>
178struct DenseMapInfo<unsigned long long> {
179 static constexpr unsigned long long getEmptyKey() { return ~0ULL; }
180 static constexpr unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; }
181
182 static constexpr unsigned getHashValue(const unsigned long long &Val) {
183 return (unsigned)(Val * 37ULL);
184 }
185
186 static constexpr bool isEqual(const unsigned long long &LHS,
187 const unsigned long long &RHS) {
188 return LHS == RHS;
189 }
190};
191
192// Provide DenseMapInfo for shorts.
193template <>
194struct DenseMapInfo<short> {
195 static constexpr short getEmptyKey() { return 0x7FFF; }
196 static constexpr short getTombstoneKey() { return -0x7FFF - 1; }
197 static constexpr unsigned getHashValue(const short &Val) { return Val * 37U; }
198 static constexpr bool isEqual(const short &LHS, const short &RHS) {
199 return LHS == RHS;
200 }
201};
202
203// Provide DenseMapInfo for ints.
204template <>
205struct DenseMapInfo<int> {
206 static constexpr int getEmptyKey() { return 0x7fffffff; }
207 static constexpr int getTombstoneKey() { return -0x7fffffff - 1; }
208 static constexpr unsigned getHashValue(const int &Val) {
209 return (unsigned)(Val * 37U);
210 }
211
212 static constexpr bool isEqual(const int &LHS, const int &RHS) {
213 return LHS == RHS;
214 }
215};
216
217// Provide DenseMapInfo for longs.
218template <>
219struct DenseMapInfo<long> {
220 static constexpr long getEmptyKey() {
221 return (1UL << (sizeof(long) * 8 - 1)) - 1UL;
222 }
223
224 static constexpr long getTombstoneKey() { return getEmptyKey() - 1L; }
225
226 static constexpr unsigned getHashValue(const long &Val) {
227 return (unsigned)(Val * 37UL);
228 }
229
230 static constexpr bool isEqual(const long &LHS, const long &RHS) {
231 return LHS == RHS;
232 }
233};
234
235// Provide DenseMapInfo for long longs.
236template <>
237struct DenseMapInfo<long long> {
238 static constexpr long long getEmptyKey() { return 0x7fffffffffffffffLL; }
239 static constexpr long long getTombstoneKey() {
240 return -0x7fffffffffffffffLL - 1;
241 }
242
243 static constexpr unsigned getHashValue(const long long &Val) {
244 return (unsigned)(Val * 37ULL);
245 }
246
247 static constexpr bool isEqual(const long long &LHS, const long long &RHS) {
248 return LHS == RHS;
249 }
250};
251
252// Provide DenseMapInfo for all pairs whose members have info.
253template <typename T, typename U>
254struct DenseMapInfo<detail::DenseMapPair<T, U>> {
255 using Pair = detail::DenseMapPair<T, U>;
256 using FirstInfo = DenseMapInfo<T>;
257 using SecondInfo = DenseMapInfo<U>;
258
259 static constexpr Pair getEmptyKey() {
260 return detail::DenseMapPair<T, U>(FirstInfo::getEmptyKey(),
261 SecondInfo::getEmptyKey());
262 }
263
264 static constexpr Pair getTombstoneKey() {
265 return detail::DenseMapPair<T, U>(FirstInfo::getTombstoneKey(),
266 SecondInfo::getTombstoneKey());
267 }
268
269 static constexpr unsigned getHashValue(const Pair &PairVal) {
270 return detail::combineHashValue(FirstInfo::getHashValue(PairVal.first),
271 SecondInfo::getHashValue(PairVal.second));
272 }
273
274 static constexpr bool isEqual(const Pair &LHS, const Pair &RHS) {
275 return FirstInfo::isEqual(LHS.first, RHS.first) &&
276 SecondInfo::isEqual(LHS.second, RHS.second);
277 }
278};
279
280} // namespace __sanitizer
281
282#endif // SANITIZER_DENSE_MAP_INFO_H
lib/tsan/sanitizer_common/sanitizer_errno.h+1-1
......@@ -21,7 +21,7 @@
2121#include "sanitizer_errno_codes.h"
2222#include "sanitizer_platform.h"
2323
24#if SANITIZER_FREEBSD || SANITIZER_MAC
24#if SANITIZER_FREEBSD || SANITIZER_APPLE
2525# define __errno_location __error
2626#elif SANITIZER_ANDROID || SANITIZER_NETBSD
2727# define __errno_location __errno
lib/tsan/sanitizer_common/sanitizer_errno_codes.h+1
......@@ -25,6 +25,7 @@ namespace __sanitizer {
2525#define errno_EBUSY 16
2626#define errno_EINVAL 22
2727#define errno_ENAMETOOLONG 36
28#define errno_ENOSYS 38
2829
2930// Those might not present or their value differ on different platforms.
3031extern const int errno_EOWNERDEAD;
lib/tsan/sanitizer_common/sanitizer_file.cpp+20
......@@ -19,6 +19,7 @@
1919
2020#include "sanitizer_common.h"
2121#include "sanitizer_file.h"
22# include "sanitizer_interface_internal.h"
2223
2324namespace __sanitizer {
2425
......@@ -75,6 +76,24 @@ void ReportFile::ReopenIfNecessary() {
7576 fd_pid = pid;
7677}
7778
79static void RecursiveCreateParentDirs(char *path) {
80 if (path[0] == '\0')
81 return;
82 for (int i = 1; path[i] != '\0'; ++i) {
83 char save = path[i];
84 if (!IsPathSeparator(path[i]))
85 continue;
86 path[i] = '\0';
87 if (!DirExists(path) && !CreateDir(path)) {
88 const char *ErrorMsgPrefix = "ERROR: Can't create directory: ";
89 WriteToFile(kStderrFd, ErrorMsgPrefix, internal_strlen(ErrorMsgPrefix));
90 WriteToFile(kStderrFd, path, internal_strlen(path));
91 Die();
92 }
93 path[i] = save;
94 }
95}
96
7897void ReportFile::SetReportPath(const char *path) {
7998 if (path) {
8099 uptr len = internal_strlen(path);
......@@ -95,6 +114,7 @@ void ReportFile::SetReportPath(const char *path) {
95114 fd = kStdoutFd;
96115 } else {
97116 internal_snprintf(path_prefix, kMaxPathLength, "%s", path);
117 RecursiveCreateParentDirs(path_prefix);
98118 }
99119}
100120
lib/tsan/sanitizer_common/sanitizer_file.h+4-1
......@@ -15,7 +15,7 @@
1515#ifndef SANITIZER_FILE_H
1616#define SANITIZER_FILE_H
1717
18#include "sanitizer_interface_internal.h"
18#include "sanitizer_common.h"
1919#include "sanitizer_internal_defs.h"
2020#include "sanitizer_libc.h"
2121#include "sanitizer_mutex.h"
......@@ -78,9 +78,12 @@ bool SupportsColoredOutput(fd_t fd);
7878// OS
7979const char *GetPwd();
8080bool FileExists(const char *filename);
81bool DirExists(const char *path);
8182char *FindPathToBinary(const char *name);
8283bool IsPathSeparator(const char c);
8384bool IsAbsolutePath(const char *path);
85// Returns true on success, false on failure.
86bool CreateDir(const char *pathname);
8487// Starts a subprocess and returs its pid.
8588// If *_fd parameters are not kInvalidFd their corresponding input/output
8689// streams will be redirect to the file. The files will always be closed
lib/tsan/sanitizer_common/sanitizer_flag_parser.cpp+2-2
......@@ -13,9 +13,9 @@
1313#include "sanitizer_flag_parser.h"
1414
1515#include "sanitizer_common.h"
16#include "sanitizer_libc.h"
17#include "sanitizer_flags.h"
1816#include "sanitizer_flag_parser.h"
17#include "sanitizer_flags.h"
18#include "sanitizer_libc.h"
1919
2020namespace __sanitizer {
2121
lib/tsan/sanitizer_common/sanitizer_flag_parser.h+2-2
......@@ -13,9 +13,9 @@
1313#ifndef SANITIZER_FLAG_REGISTRY_H
1414#define SANITIZER_FLAG_REGISTRY_H
1515
16#include "sanitizer_common.h"
1617#include "sanitizer_internal_defs.h"
1718#include "sanitizer_libc.h"
18#include "sanitizer_common.h"
1919
2020namespace __sanitizer {
2121
......@@ -138,7 +138,7 @@ inline bool FlagHandler<uptr>::Parse(const char *value) {
138138
139139template <>
140140inline bool FlagHandler<uptr>::Format(char *buffer, uptr size) {
141 uptr num_symbols_should_write = internal_snprintf(buffer, size, "%p", *t_);
141 uptr num_symbols_should_write = internal_snprintf(buffer, size, "0x%zx", *t_);
142142 return num_symbols_should_write < size;
143143}
144144
lib/tsan/sanitizer_common/sanitizer_flags.inc+15-5
......@@ -62,16 +62,19 @@ COMMON_FLAG(
6262COMMON_FLAG(const char *, log_suffix, nullptr,
6363 "String to append to log file name, e.g. \".txt\".")
6464COMMON_FLAG(
65 bool, log_to_syslog, (bool)SANITIZER_ANDROID || (bool)SANITIZER_MAC,
65 bool, log_to_syslog, (bool)SANITIZER_ANDROID || (bool)SANITIZER_APPLE,
6666 "Write all sanitizer output to syslog in addition to other means of "
6767 "logging.")
6868COMMON_FLAG(
6969 int, verbosity, 0,
7070 "Verbosity level (0 - silent, 1 - a bit of output, 2+ - more output).")
71COMMON_FLAG(bool, strip_env, 1,
71COMMON_FLAG(bool, strip_env, true,
7272 "Whether to remove the sanitizer from DYLD_INSERT_LIBRARIES to "
73 "avoid passing it to children. Default is true.")
74COMMON_FLAG(bool, detect_leaks, !SANITIZER_MAC, "Enable memory leak detection.")
73 "avoid passing it to children on Apple platforms. Default is true.")
74COMMON_FLAG(bool, verify_interceptors, true,
75 "Verify that interceptors are working on Apple platforms. Default "
76 "is true.")
77COMMON_FLAG(bool, detect_leaks, !SANITIZER_APPLE, "Enable memory leak detection.")
7578COMMON_FLAG(
7679 bool, leak_check_at_exit, true,
7780 "Invoke leak checking in an atexit handler. Has no effect if "
......@@ -160,6 +163,10 @@ COMMON_FLAG(
160163COMMON_FLAG(const char *, coverage_dir, ".",
161164 "Target directory for coverage dumps. Defaults to the current "
162165 "directory.")
166COMMON_FLAG(const char *, cov_8bit_counters_out, "",
167 "If non-empty, write 8bit counters to this file. ")
168COMMON_FLAG(const char *, cov_pcs_out, "",
169 "If non-empty, write the coverage pc table to this file. ")
163170COMMON_FLAG(bool, full_address_space, false,
164171 "Sanitize complete address space; "
165172 "by default kernel area on 32-bit platforms will not be sanitized")
......@@ -175,6 +182,7 @@ COMMON_FLAG(bool, use_madv_dontdump, true,
175182 "in core file.")
176183COMMON_FLAG(bool, symbolize_inline_frames, true,
177184 "Print inlined frames in stacktraces. Defaults to true.")
185COMMON_FLAG(bool, demangle, true, "Print demangled symbols.")
178186COMMON_FLAG(bool, symbolize_vs_style, false,
179187 "Print file locations in Visual Studio style (e.g: "
180188 " file(10,42): ...")
......@@ -187,6 +195,8 @@ COMMON_FLAG(const char *, stack_trace_format, "DEFAULT",
187195 "Format string used to render stack frames. "
188196 "See sanitizer_stacktrace_printer.h for the format description. "
189197 "Use DEFAULT to get default format.")
198COMMON_FLAG(int, compress_stack_depot, 0,
199 "Compress stack depot to save memory.")
190200COMMON_FLAG(bool, no_huge_pages_for_shadow, true,
191201 "If true, the shadow is not allowed to use huge pages. ")
192202COMMON_FLAG(bool, strict_string_checks, false,
......@@ -238,7 +248,7 @@ COMMON_FLAG(bool, decorate_proc_maps, (bool)SANITIZER_ANDROID,
238248COMMON_FLAG(int, exitcode, 1, "Override the program exit status if the tool "
239249 "found an error")
240250COMMON_FLAG(
241 bool, abort_on_error, (bool)SANITIZER_ANDROID || (bool)SANITIZER_MAC,
251 bool, abort_on_error, (bool)SANITIZER_ANDROID || (bool)SANITIZER_APPLE,
242252 "If set, the tool calls abort() instead of _exit() after printing the "
243253 "error report.")
244254COMMON_FLAG(bool, suppress_equal_pcs, true,
lib/tsan/sanitizer_common/sanitizer_flat_map.h created+162
......@@ -0,0 +1,162 @@
1//===-- sanitizer_flat_map.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// Part of the Sanitizer Allocator.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef SANITIZER_FLAT_MAP_H
14#define SANITIZER_FLAT_MAP_H
15
16#include "sanitizer_atomic.h"
17#include "sanitizer_common.h"
18#include "sanitizer_internal_defs.h"
19#include "sanitizer_local_address_space_view.h"
20#include "sanitizer_mutex.h"
21
22namespace __sanitizer {
23
24// Maps integers in rage [0, kSize) to values.
25template <typename T, u64 kSize,
26 typename AddressSpaceViewTy = LocalAddressSpaceView>
27class FlatMap {
28 public:
29 using AddressSpaceView = AddressSpaceViewTy;
30 void Init() { internal_memset(map_, 0, sizeof(map_)); }
31
32 constexpr uptr size() const { return kSize; }
33
34 bool contains(uptr idx) const {
35 CHECK_LT(idx, kSize);
36 return true;
37 }
38
39 T &operator[](uptr idx) {
40 DCHECK_LT(idx, kSize);
41 return map_[idx];
42 }
43
44 const T &operator[](uptr idx) const {
45 DCHECK_LT(idx, kSize);
46 return map_[idx];
47 }
48
49 private:
50 T map_[kSize];
51};
52
53// TwoLevelMap maps integers in range [0, kSize1*kSize2) to values.
54// It is implemented as a two-dimensional array: array of kSize1 pointers
55// to kSize2-byte arrays. The secondary arrays are mmaped on demand.
56// Each value is initially zero and can be set to something else only once.
57// Setting and getting values from multiple threads is safe w/o extra locking.
58template <typename T, u64 kSize1, u64 kSize2,
59 typename AddressSpaceViewTy = LocalAddressSpaceView>
60class TwoLevelMap {
61 static_assert(IsPowerOfTwo(kSize2), "Use a power of two for performance.");
62
63 public:
64 using AddressSpaceView = AddressSpaceViewTy;
65 void Init() {
66 mu_.Init();
67 internal_memset(map1_, 0, sizeof(map1_));
68 }
69
70 void TestOnlyUnmap() {
71 for (uptr i = 0; i < kSize1; i++) {
72 T *p = Get(i);
73 if (!p)
74 continue;
75 UnmapOrDie(p, kSize2);
76 }
77 Init();
78 }
79
80 uptr MemoryUsage() const {
81 uptr res = 0;
82 for (uptr i = 0; i < kSize1; i++) {
83 T *p = Get(i);
84 if (!p)
85 continue;
86 res += MmapSize();
87 }
88 return res;
89 }
90
91 constexpr uptr size() const { return kSize1 * kSize2; }
92 constexpr uptr size1() const { return kSize1; }
93 constexpr uptr size2() const { return kSize2; }
94
95 bool contains(uptr idx) const {
96 CHECK_LT(idx, kSize1 * kSize2);
97 return Get(idx / kSize2);
98 }
99
100 const T &operator[](uptr idx) const {
101 DCHECK_LT(idx, kSize1 * kSize2);
102 T *map2 = GetOrCreate(idx / kSize2);
103 return *AddressSpaceView::Load(&map2[idx % kSize2]);
104 }
105
106 T &operator[](uptr idx) {
107 DCHECK_LT(idx, kSize1 * kSize2);
108 T *map2 = GetOrCreate(idx / kSize2);
109 return *AddressSpaceView::LoadWritable(&map2[idx % kSize2]);
110 }
111
112 private:
113 constexpr uptr MmapSize() const {
114 return RoundUpTo(kSize2 * sizeof(T), GetPageSizeCached());
115 }
116
117 T *Get(uptr idx) const {
118 DCHECK_LT(idx, kSize1);
119 return reinterpret_cast<T *>(
120 atomic_load(&map1_[idx], memory_order_acquire));
121 }
122
123 T *GetOrCreate(uptr idx) const {
124 DCHECK_LT(idx, kSize1);
125 // This code needs to use memory_order_acquire/consume, but we use
126 // memory_order_relaxed for performance reasons (matters for arm64). We
127 // expect memory_order_relaxed to be effectively equivalent to
128 // memory_order_consume in this case for all relevant architectures: all
129 // dependent data is reachable only by dereferencing the resulting pointer.
130 // If relaxed load fails to see stored ptr, the code will fall back to
131 // Create() and reload the value again with locked mutex as a memory
132 // barrier.
133 T *res = reinterpret_cast<T *>(atomic_load_relaxed(&map1_[idx]));
134 if (LIKELY(res))
135 return res;
136 return Create(idx);
137 }
138
139 NOINLINE T *Create(uptr idx) const {
140 SpinMutexLock l(&mu_);
141 T *res = Get(idx);
142 if (!res) {
143 res = reinterpret_cast<T *>(MmapOrDie(MmapSize(), "TwoLevelMap"));
144 atomic_store(&map1_[idx], reinterpret_cast<uptr>(res),
145 memory_order_release);
146 }
147 return res;
148 }
149
150 mutable StaticSpinMutex mu_;
151 mutable atomic_uintptr_t map1_[kSize1];
152};
153
154template <u64 kSize, typename AddressSpaceViewTy = LocalAddressSpaceView>
155using FlatByteMap = FlatMap<u8, kSize, AddressSpaceViewTy>;
156
157template <u64 kSize1, u64 kSize2,
158 typename AddressSpaceViewTy = LocalAddressSpaceView>
159using TwoLevelByteMap = TwoLevelMap<u8, kSize1, kSize2, AddressSpaceViewTy>;
160} // namespace __sanitizer
161
162#endif
lib/tsan/sanitizer_common/sanitizer_fuchsia.cpp+37-79
......@@ -14,24 +14,25 @@
1414#include "sanitizer_fuchsia.h"
1515#if SANITIZER_FUCHSIA
1616
17#include <pthread.h>
18#include <stdlib.h>
19#include <unistd.h>
20#include <zircon/errors.h>
21#include <zircon/process.h>
22#include <zircon/syscalls.h>
23#include <zircon/utc.h>
24
25#include "sanitizer_common.h"
26#include "sanitizer_libc.h"
27#include "sanitizer_mutex.h"
17# include <pthread.h>
18# include <stdlib.h>
19# include <unistd.h>
20# include <zircon/errors.h>
21# include <zircon/process.h>
22# include <zircon/syscalls.h>
23# include <zircon/utc.h>
24
25# include "sanitizer_common.h"
26# include "sanitizer_interface_internal.h"
27# include "sanitizer_libc.h"
28# include "sanitizer_mutex.h"
2829
2930namespace __sanitizer {
3031
3132void NORETURN internal__exit(int exitcode) { _zx_process_exit(exitcode); }
3233
3334uptr internal_sched_yield() {
34 zx_status_t status = _zx_nanosleep(0);
35 zx_status_t status = _zx_thread_legacy_yield(0u);
3536 CHECK_EQ(status, ZX_OK);
3637 return 0; // Why doesn't this return void?
3738}
......@@ -86,10 +87,9 @@ void GetThreadStackTopAndBottom(bool, uptr *stack_top, uptr *stack_bottom) {
8687}
8788
8889void InitializePlatformEarly() {}
89void MaybeReexec() {}
9090void CheckASLR() {}
9191void CheckMPROTECT() {}
92void PlatformPrepareForSandboxing(__sanitizer_sandbox_arguments *args) {}
92void PlatformPrepareForSandboxing(void *args) {}
9393void DisableCoreDumperIfNecessary() {}
9494void InstallDeadlySignalHandlers(SignalHandlerType handler) {}
9595void SetAlternateSignalStack() {}
......@@ -112,47 +112,6 @@ void FutexWake(atomic_uint32_t *p, u32 count) {
112112 CHECK_EQ(status, ZX_OK);
113113}
114114
115enum MutexState : int { MtxUnlocked = 0, MtxLocked = 1, MtxSleeping = 2 };
116
117BlockingMutex::BlockingMutex() {
118 // NOTE! It's important that this use internal_memset, because plain
119 // memset might be intercepted (e.g., actually be __asan_memset).
120 // Defining this so the compiler initializes each field, e.g.:
121 // BlockingMutex::BlockingMutex() : BlockingMutex(LINKER_INITIALIZED) {}
122 // might result in the compiler generating a call to memset, which would
123 // have the same problem.
124 internal_memset(this, 0, sizeof(*this));
125}
126
127void BlockingMutex::Lock() {
128 CHECK_EQ(owner_, 0);
129 atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
130 if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked)
131 return;
132 while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) {
133 zx_status_t status =
134 _zx_futex_wait(reinterpret_cast<zx_futex_t *>(m), MtxSleeping,
135 ZX_HANDLE_INVALID, ZX_TIME_INFINITE);
136 if (status != ZX_ERR_BAD_STATE) // Normal race.
137 CHECK_EQ(status, ZX_OK);
138 }
139}
140
141void BlockingMutex::Unlock() {
142 atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
143 u32 v = atomic_exchange(m, MtxUnlocked, memory_order_release);
144 CHECK_NE(v, MtxUnlocked);
145 if (v == MtxSleeping) {
146 zx_status_t status = _zx_futex_wake(reinterpret_cast<zx_futex_t *>(m), 1);
147 CHECK_EQ(status, ZX_OK);
148 }
149}
150
151void BlockingMutex::CheckLocked() const {
152 auto m = reinterpret_cast<atomic_uint32_t const *>(&opaque_storage_);
153 CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed));
154}
155
156115uptr GetPageSize() { return _zx_system_get_page_size(); }
157116
158117uptr GetMmapGranularity() { return _zx_system_get_page_size(); }
......@@ -168,6 +127,8 @@ uptr GetMaxUserVirtualAddress() {
168127
169128uptr GetMaxVirtualAddress() { return GetMaxUserVirtualAddress(); }
170129
130bool ErrorIsOOM(error_t err) { return err == ZX_ERR_NO_MEMORY; }
131
171132static void *DoAnonymousMmapOrDie(uptr size, const char *mem_type,
172133 bool raw_report, bool die_for_nomem) {
173134 size = RoundUpTo(size, GetPageSize());
......@@ -315,6 +276,21 @@ void *MmapFixedNoAccess(uptr fixed_addr, uptr size, const char *name) {
315276 UNIMPLEMENTED();
316277}
317278
279bool MprotectNoAccess(uptr addr, uptr size) {
280 return _zx_vmar_protect(_zx_vmar_root_self(), 0, addr, size) == ZX_OK;
281}
282
283bool MprotectReadOnly(uptr addr, uptr size) {
284 return _zx_vmar_protect(_zx_vmar_root_self(), ZX_VM_PERM_READ, addr, size) ==
285 ZX_OK;
286}
287
288bool MprotectReadWrite(uptr addr, uptr size) {
289 return _zx_vmar_protect(_zx_vmar_root_self(),
290 ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, addr,
291 size) == ZX_OK;
292}
293
318294void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
319295 const char *mem_type) {
320296 CHECK_GE(size, GetPageSize());
......@@ -413,33 +389,12 @@ bool IsAccessibleMemoryRange(uptr beg, uptr size) {
413389}
414390
415391// FIXME implement on this platform.
416void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) {}
392void GetMemoryProfile(fill_profile_f cb, uptr *stats) {}
417393
418394bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
419395 uptr *read_len, uptr max_len, error_t *errno_p) {
420 zx_handle_t vmo;
421 zx_status_t status = __sanitizer_get_configuration(file_name, &vmo);
422 if (status == ZX_OK) {
423 uint64_t vmo_size;
424 status = _zx_vmo_get_size(vmo, &vmo_size);
425 if (status == ZX_OK) {
426 if (vmo_size < max_len)
427 max_len = vmo_size;
428 size_t map_size = RoundUpTo(max_len, GetPageSize());
429 uintptr_t addr;
430 status = _zx_vmar_map(_zx_vmar_root_self(), ZX_VM_PERM_READ, 0, vmo, 0,
431 map_size, &addr);
432 if (status == ZX_OK) {
433 *buff = reinterpret_cast<char *>(addr);
434 *buff_size = map_size;
435 *read_len = max_len;
436 }
437 }
438 _zx_handle_close(vmo);
439 }
440 if (status != ZX_OK && errno_p)
441 *errno_p = status;
442 return status == ZX_OK;
396 *errno_p = ZX_ERR_NOT_SUPPORTED;
397 return false;
443398}
444399
445400void RawWrite(const char *buffer) {
......@@ -516,6 +471,9 @@ u32 GetNumberOfCPUs() { return zx_system_get_num_cpus(); }
516471
517472uptr GetRSS() { UNIMPLEMENTED(); }
518473
474void *internal_start_thread(void *(*func)(void *arg), void *arg) { return 0; }
475void internal_join_thread(void *th) {}
476
519477void InitializePlatformCommonFlags(CommonFlags *cf) {}
520478
521479} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_hash.h+24
......@@ -38,6 +38,30 @@ class MurMur2HashBuilder {
3838 return x;
3939 }
4040};
41
42class MurMur2Hash64Builder {
43 static const u64 m = 0xc6a4a7935bd1e995ull;
44 static const u64 seed = 0x9747b28c9747b28cull;
45 static const u64 r = 47;
46 u64 h;
47
48 public:
49 explicit MurMur2Hash64Builder(u64 init = 0) { h = seed ^ (init * m); }
50 void add(u64 k) {
51 k *= m;
52 k ^= k >> r;
53 k *= m;
54 h ^= k;
55 h *= m;
56 }
57 u64 get() {
58 u64 x = h;
59 x ^= x >> r;
60 x *= m;
61 x ^= x >> r;
62 return x;
63 }
64};
4165} //namespace __sanitizer
4266
4367#endif // SANITIZER_HASH_H
lib/tsan/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc+1-3
......@@ -1267,8 +1267,6 @@ static void ioctl_table_fill() {
12671267 _(TIOCGFLAGS, WRITE, sizeof(int));
12681268 _(TIOCSFLAGS, READ, sizeof(int));
12691269 _(TIOCDCDTIMESTAMP, WRITE, struct_timeval_sz);
1270 _(TIOCRCVFRAME, READ, sizeof(uptr));
1271 _(TIOCXMTFRAME, READ, sizeof(uptr));
12721270 _(TIOCPTMGET, WRITE, struct_ptmget_sz);
12731271 _(TIOCGRANTPT, NONE, 0);
12741272 _(TIOCPTSNAME, WRITE, struct_ptmget_sz);
......@@ -1406,7 +1404,7 @@ static void ioctl_table_fill() {
14061404 _(URIO_SEND_COMMAND, READWRITE, struct_urio_command_sz);
14071405 _(URIO_RECV_COMMAND, READWRITE, struct_urio_command_sz);
14081406#undef _
1409} // NOLINT
1407}
14101408
14111409static bool ioctl_initialized = false;
14121410
lib/tsan/sanitizer_common/sanitizer_interface_internal.h+121-90
......@@ -20,103 +20,134 @@
2020#include "sanitizer_internal_defs.h"
2121
2222extern "C" {
23 // Tell the tools to write their reports to "path.<pid>" instead of stderr.
24 // The special values are "stdout" and "stderr".
25 SANITIZER_INTERFACE_ATTRIBUTE
26 void __sanitizer_set_report_path(const char *path);
27 // Tell the tools to write their reports to the provided file descriptor
28 // (casted to void *).
29 SANITIZER_INTERFACE_ATTRIBUTE
30 void __sanitizer_set_report_fd(void *fd);
31 // Get the current full report file path, if a path was specified by
32 // an earlier call to __sanitizer_set_report_path. Returns null otherwise.
33 SANITIZER_INTERFACE_ATTRIBUTE
34 const char *__sanitizer_get_report_path();
23// Tell the tools to write their reports to "path.<pid>" instead of stderr.
24// The special values are "stdout" and "stderr".
25SANITIZER_INTERFACE_ATTRIBUTE
26void __sanitizer_set_report_path(const char *path);
27// Tell the tools to write their reports to the provided file descriptor
28// (casted to void *).
29SANITIZER_INTERFACE_ATTRIBUTE
30void __sanitizer_set_report_fd(void *fd);
31// Get the current full report file path, if a path was specified by
32// an earlier call to __sanitizer_set_report_path. Returns null otherwise.
33SANITIZER_INTERFACE_ATTRIBUTE
34const char *__sanitizer_get_report_path();
3535
36 typedef struct {
37 int coverage_sandboxed;
38 __sanitizer::sptr coverage_fd;
39 unsigned int coverage_max_block_size;
40 } __sanitizer_sandbox_arguments;
36typedef struct {
37 int coverage_sandboxed;
38 __sanitizer::sptr coverage_fd;
39 unsigned int coverage_max_block_size;
40} __sanitizer_sandbox_arguments;
4141
42 // Notify the tools that the sandbox is going to be turned on.
43 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
44 __sanitizer_sandbox_on_notify(__sanitizer_sandbox_arguments *args);
42// Notify the tools that the sandbox is going to be turned on.
43SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
44__sanitizer_sandbox_on_notify(__sanitizer_sandbox_arguments *args);
4545
46 // This function is called by the tool when it has just finished reporting
47 // an error. 'error_summary' is a one-line string that summarizes
48 // the error message. This function can be overridden by the client.
49 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
50 void __sanitizer_report_error_summary(const char *error_summary);
46// This function is called by the tool when it has just finished reporting
47// an error. 'error_summary' is a one-line string that summarizes
48// the error message. This function can be overridden by the client.
49SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
50__sanitizer_report_error_summary(const char *error_summary);
5151
52 SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump();
53 SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage(
54 const __sanitizer::uptr *pcs, const __sanitizer::uptr len);
55 SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_trace_pc_guard_coverage();
52SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump();
53SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage(
54 const __sanitizer::uptr *pcs, const __sanitizer::uptr len);
55SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_trace_pc_guard_coverage();
5656
57 SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov(__sanitizer::u32 *guard);
57SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov(__sanitizer::u32 *guard);
5858
59 // Returns 1 on the first call, then returns 0 thereafter. Called by the tool
60 // to ensure only one report is printed when multiple errors occur
61 // simultaneously.
62 SANITIZER_INTERFACE_ATTRIBUTE int __sanitizer_acquire_crash_state();
59// Returns 1 on the first call, then returns 0 thereafter. Called by the tool
60// to ensure only one report is printed when multiple errors occur
61// simultaneously.
62SANITIZER_INTERFACE_ATTRIBUTE int __sanitizer_acquire_crash_state();
6363
64 SANITIZER_INTERFACE_ATTRIBUTE
65 void __sanitizer_annotate_contiguous_container(const void *beg,
66 const void *end,
67 const void *old_mid,
68 const void *new_mid);
69 SANITIZER_INTERFACE_ATTRIBUTE
70 int __sanitizer_verify_contiguous_container(const void *beg, const void *mid,
71 const void *end);
72 SANITIZER_INTERFACE_ATTRIBUTE
73 const void *__sanitizer_contiguous_container_find_bad_address(
74 const void *beg, const void *mid, const void *end);
64SANITIZER_INTERFACE_ATTRIBUTE
65void __sanitizer_annotate_contiguous_container(const void *beg, const void *end,
66 const void *old_mid,
67 const void *new_mid);
68SANITIZER_INTERFACE_ATTRIBUTE
69void __sanitizer_annotate_double_ended_contiguous_container(
70 const void *storage_beg, const void *storage_end,
71 const void *old_container_beg, const void *old_container_end,
72 const void *new_container_beg, const void *new_container_end);
73SANITIZER_INTERFACE_ATTRIBUTE
74int __sanitizer_verify_contiguous_container(const void *beg, const void *mid,
75 const void *end);
76SANITIZER_INTERFACE_ATTRIBUTE
77int __sanitizer_verify_double_ended_contiguous_container(
78 const void *storage_beg, const void *container_beg,
79 const void *container_end, const void *storage_end);
80SANITIZER_INTERFACE_ATTRIBUTE
81const void *__sanitizer_contiguous_container_find_bad_address(const void *beg,
82 const void *mid,
83 const void *end);
84SANITIZER_INTERFACE_ATTRIBUTE
85const void *__sanitizer_double_ended_contiguous_container_find_bad_address(
86 const void *storage_beg, const void *container_beg,
87 const void *container_end, const void *storage_end);
7588
76 SANITIZER_INTERFACE_ATTRIBUTE
77 int __sanitizer_get_module_and_offset_for_pc(
78 __sanitizer::uptr pc, char *module_path,
79 __sanitizer::uptr module_path_len, __sanitizer::uptr *pc_offset);
80
81 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
82 void __sanitizer_cov_trace_cmp();
83 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
84 void __sanitizer_cov_trace_cmp1();
85 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
86 void __sanitizer_cov_trace_cmp2();
87 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
88 void __sanitizer_cov_trace_cmp4();
89 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
90 void __sanitizer_cov_trace_cmp8();
91 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
92 void __sanitizer_cov_trace_const_cmp1();
93 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
94 void __sanitizer_cov_trace_const_cmp2();
95 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
96 void __sanitizer_cov_trace_const_cmp4();
97 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
98 void __sanitizer_cov_trace_const_cmp8();
99 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
100 void __sanitizer_cov_trace_switch();
101 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
102 void __sanitizer_cov_trace_div4();
103 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
104 void __sanitizer_cov_trace_div8();
105 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
106 void __sanitizer_cov_trace_gep();
107 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
108 void __sanitizer_cov_trace_pc_indir();
109 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
110 void __sanitizer_cov_trace_pc_guard(__sanitizer::u32*);
111 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
112 void __sanitizer_cov_trace_pc_guard_init(__sanitizer::u32*,
113 __sanitizer::u32*);
114 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
115 void __sanitizer_cov_8bit_counters_init();
116 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
117 __sanitizer_cov_bool_flag_init();
118 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
119 __sanitizer_cov_pcs_init();
120} // extern "C"
89SANITIZER_INTERFACE_ATTRIBUTE
90int __sanitizer_get_module_and_offset_for_pc(void *pc, char *module_path,
91 __sanitizer::uptr module_path_len,
92 void **pc_offset);
93SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
94__sanitizer_cov_trace_cmp();
95SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
96__sanitizer_cov_trace_cmp1();
97SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
98__sanitizer_cov_trace_cmp2();
99SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
100__sanitizer_cov_trace_cmp4();
101SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
102__sanitizer_cov_trace_cmp8();
103SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
104__sanitizer_cov_trace_const_cmp1();
105SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
106__sanitizer_cov_trace_const_cmp2();
107SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
108__sanitizer_cov_trace_const_cmp4();
109SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
110__sanitizer_cov_trace_const_cmp8();
111SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
112__sanitizer_cov_trace_switch();
113SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
114__sanitizer_cov_trace_div4();
115SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
116__sanitizer_cov_trace_div8();
117SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
118__sanitizer_cov_trace_gep();
119SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
120__sanitizer_cov_trace_pc_indir();
121SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
122__sanitizer_cov_load1();
123SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
124__sanitizer_cov_load2();
125SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
126__sanitizer_cov_load4();
127SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
128__sanitizer_cov_load8();
129SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
130__sanitizer_cov_load16();
131SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
132__sanitizer_cov_store1();
133SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
134__sanitizer_cov_store2();
135SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
136__sanitizer_cov_store4();
137SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
138__sanitizer_cov_store8();
139SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
140__sanitizer_cov_store16();
141SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
142__sanitizer_cov_trace_pc_guard(__sanitizer::u32 *);
143SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
144__sanitizer_cov_trace_pc_guard_init(__sanitizer::u32 *, __sanitizer::u32 *);
145SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
146__sanitizer_cov_8bit_counters_init(char *, char *);
147SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
148__sanitizer_cov_bool_flag_init();
149SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
150__sanitizer_cov_pcs_init(const __sanitizer::uptr *, const __sanitizer::uptr *);
151} // extern "C"
121152
122153#endif // SANITIZER_INTERFACE_INTERNAL_H
lib/tsan/sanitizer_common/sanitizer_internal_defs.h+56-35
......@@ -13,6 +13,7 @@
1313#define SANITIZER_DEFS_H
1414
1515#include "sanitizer_platform.h"
16#include "sanitizer_redefine_builtins.h"
1617
1718#ifndef SANITIZER_DEBUG
1819# define SANITIZER_DEBUG 0
......@@ -37,15 +38,6 @@
3738# define SANITIZER_WEAK_ATTRIBUTE __attribute__((weak))
3839#endif
3940
40// TLS is handled differently on different platforms
41#if SANITIZER_LINUX || SANITIZER_NETBSD || \
42 SANITIZER_FREEBSD
43# define SANITIZER_TLS_INITIAL_EXEC_ATTRIBUTE \
44 __attribute__((tls_model("initial-exec"))) thread_local
45#else
46# define SANITIZER_TLS_INITIAL_EXEC_ATTRIBUTE
47#endif
48
4941//--------------------------- WEAK FUNCTIONS ---------------------------------//
5042// When working with weak functions, to simplify the code and make it more
5143// portable, when possible define a default implementation using this macro:
......@@ -73,7 +65,7 @@
7365// Before Xcode 4.5, the Darwin linker doesn't reliably support undefined
7466// weak symbols. Mac OS X 10.9/Darwin 13 is the first release only supported
7567// by Xcode >= 4.5.
76#elif SANITIZER_MAC && \
68#elif SANITIZER_APPLE && \
7769 __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1090 && !SANITIZER_GO
7870# define SANITIZER_SUPPORTS_WEAK_HOOKS 1
7971#else
......@@ -125,6 +117,10 @@
125117# define __has_attribute(x) 0
126118#endif
127119
120#if !defined(__has_cpp_attribute)
121# define __has_cpp_attribute(x) 0
122#endif
123
128124// For portability reasons we do not include stddef.h, stdint.h or any other
129125// system header, but we do need some basic types that are not defined
130126// in a portable way by the language itself.
......@@ -135,8 +131,13 @@ namespace __sanitizer {
135131typedef unsigned long long uptr;
136132typedef signed long long sptr;
137133#else
134# if (SANITIZER_WORDSIZE == 64) || SANITIZER_APPLE || SANITIZER_WINDOWS
138135typedef unsigned long uptr;
139136typedef signed long sptr;
137# else
138typedef unsigned int uptr;
139typedef signed int sptr;
140# endif
140141#endif // defined(_WIN64)
141142#if defined(__x86_64__)
142143// Since x32 uses ILP32 data model in 64-bit hardware mode, we must use
......@@ -168,17 +169,17 @@ typedef long pid_t;
168169typedef int pid_t;
169170#endif
170171
171#if SANITIZER_FREEBSD || SANITIZER_NETBSD || \
172 SANITIZER_MAC || \
172#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_APPLE || \
173173 (SANITIZER_SOLARIS && (defined(_LP64) || _FILE_OFFSET_BITS == 64)) || \
174 (SANITIZER_LINUX && defined(__x86_64__))
174 (SANITIZER_LINUX && !SANITIZER_GLIBC && !SANITIZER_ANDROID) || \
175 (SANITIZER_LINUX && (defined(__x86_64__) || defined(__hexagon__)))
175176typedef u64 OFF_T;
176177#else
177178typedef uptr OFF_T;
178179#endif
179180typedef u64 OFF64_T;
180181
181#if (SANITIZER_WORDSIZE == 64) || SANITIZER_MAC
182#if (SANITIZER_WORDSIZE == 64) || SANITIZER_APPLE
182183typedef uptr operator_new_size_type;
183184#else
184185# if defined(__s390__) && !defined(__s390x__)
......@@ -217,7 +218,7 @@ typedef u64 tid_t;
217218# define WARN_UNUSED_RESULT
218219#else // _MSC_VER
219220# define ALWAYS_INLINE inline __attribute__((always_inline))
220# define ALIAS(x) __attribute__((alias(x)))
221# define ALIAS(x) __attribute__((alias(SANITIZER_STRINGIFY(x))))
221222// Please only use the ALIGNED macro before the type.
222223// Using ALIGNED after the variable declaration is not portable!
223224# define ALIGNED(x) __attribute__((aligned(x)))
......@@ -250,6 +251,20 @@ typedef u64 tid_t;
250251# define NOEXCEPT throw()
251252#endif
252253
254#if __has_cpp_attribute(clang::fallthrough)
255# define FALLTHROUGH [[clang::fallthrough]]
256#elif __has_cpp_attribute(fallthrough)
257# define FALLTHROUGH [[fallthrough]]
258#else
259# define FALLTHROUGH
260#endif
261
262#if __has_attribute(uninitialized)
263# define UNINITIALIZED __attribute__((uninitialized))
264#else
265# define UNINITIALIZED
266#endif
267
253268// Unaligned versions of basic types.
254269typedef ALIGNED(1) u16 uu16;
255270typedef ALIGNED(1) u32 uu32;
......@@ -277,14 +292,17 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond,
277292 u64 v1, u64 v2);
278293
279294// Check macro
280#define RAW_CHECK_MSG(expr, msg) do { \
281 if (UNLIKELY(!(expr))) { \
282 RawWrite(msg); \
283 Die(); \
284 } \
285} while (0)
295#define RAW_CHECK_MSG(expr, msg, ...) \
296 do { \
297 if (UNLIKELY(!(expr))) { \
298 const char* msgs[] = {msg, __VA_ARGS__}; \
299 for (const char* m : msgs) RawWrite(m); \
300 Die(); \
301 } \
302 } while (0)
286303
287#define RAW_CHECK(expr) RAW_CHECK_MSG(expr, #expr)
304#define RAW_CHECK(expr) RAW_CHECK_MSG(expr, #expr "\n", )
305#define RAW_CHECK_VA(expr, ...) RAW_CHECK_MSG(expr, #expr "\n", __VA_ARGS__)
288306
289307#define CHECK_IMPL(c1, op, c2) \
290308 do { \
......@@ -366,13 +384,10 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond,
366384enum LinkerInitialized { LINKER_INITIALIZED = 0 };
367385
368386#if !defined(_MSC_VER) || defined(__clang__)
369#if SANITIZER_S390_31
370#define GET_CALLER_PC() \
371 (__sanitizer::uptr) __builtin_extract_return_addr(__builtin_return_address(0))
372#else
373#define GET_CALLER_PC() (__sanitizer::uptr) __builtin_return_address(0)
374#endif
375#define GET_CURRENT_FRAME() (__sanitizer::uptr) __builtin_frame_address(0)
387# define GET_CALLER_PC() \
388 ((__sanitizer::uptr)__builtin_extract_return_addr( \
389 __builtin_return_address(0)))
390# define GET_CURRENT_FRAME() ((__sanitizer::uptr)__builtin_frame_address(0))
376391inline void Trap() {
377392 __builtin_trap();
378393}
......@@ -381,13 +396,13 @@ extern "C" void* _ReturnAddress(void);
381396extern "C" void* _AddressOfReturnAddress(void);
382397# pragma intrinsic(_ReturnAddress)
383398# pragma intrinsic(_AddressOfReturnAddress)
384#define GET_CALLER_PC() (__sanitizer::uptr) _ReturnAddress()
399# define GET_CALLER_PC() ((__sanitizer::uptr)_ReturnAddress())
385400// CaptureStackBackTrace doesn't need to know BP on Windows.
386#define GET_CURRENT_FRAME() \
387 (((__sanitizer::uptr)_AddressOfReturnAddress()) + sizeof(__sanitizer::uptr))
401# define GET_CURRENT_FRAME() \
402 (((__sanitizer::uptr)_AddressOfReturnAddress()) + sizeof(__sanitizer::uptr))
388403
389404extern "C" void __ud2(void);
390# pragma intrinsic(__ud2)
405# pragma intrinsic(__ud2)
391406inline void Trap() {
392407 __ud2();
393408}
......@@ -409,8 +424,14 @@ inline void Trap() {
409424 (void)enable_fp; \
410425 } while (0)
411426
412constexpr u32 kInvalidTid = -1;
413constexpr u32 kMainTid = 0;
427// Internal thread identifier allocated by ThreadRegistry.
428typedef u32 Tid;
429constexpr Tid kInvalidTid = -1;
430constexpr Tid kMainTid = 0;
431
432// Stack depot stack identifier.
433typedef u32 StackID;
434const StackID kInvalidStackID = 0;
414435
415436} // namespace __sanitizer
416437
lib/tsan/sanitizer_common/sanitizer_leb128.h created+87
......@@ -0,0 +1,87 @@
1//===-- sanitizer_leb128.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#ifndef SANITIZER_LEB128_H
10#define SANITIZER_LEB128_H
11
12#include "sanitizer_common.h"
13#include "sanitizer_internal_defs.h"
14
15namespace __sanitizer {
16
17template <typename T, typename It>
18It EncodeSLEB128(T value, It begin, It end) {
19 bool more;
20 do {
21 u8 byte = value & 0x7f;
22 // NOTE: this assumes that this signed shift is an arithmetic right shift.
23 value >>= 7;
24 more = !((((value == 0) && ((byte & 0x40) == 0)) ||
25 ((value == -1) && ((byte & 0x40) != 0))));
26 if (more)
27 byte |= 0x80;
28 if (UNLIKELY(begin == end))
29 break;
30 *(begin++) = byte;
31 } while (more);
32 return begin;
33}
34
35template <typename T, typename It>
36It DecodeSLEB128(It begin, It end, T* v) {
37 T value = 0;
38 unsigned shift = 0;
39 u8 byte;
40 do {
41 if (UNLIKELY(begin == end))
42 return begin;
43 byte = *(begin++);
44 T slice = byte & 0x7f;
45 value |= slice << shift;
46 shift += 7;
47 } while (byte >= 128);
48 if (shift < 64 && (byte & 0x40))
49 value |= (-1ULL) << shift;
50 *v = value;
51 return begin;
52}
53
54template <typename T, typename It>
55It EncodeULEB128(T value, It begin, It end) {
56 do {
57 u8 byte = value & 0x7f;
58 value >>= 7;
59 if (value)
60 byte |= 0x80;
61 if (UNLIKELY(begin == end))
62 break;
63 *(begin++) = byte;
64 } while (value);
65 return begin;
66}
67
68template <typename T, typename It>
69It DecodeULEB128(It begin, It end, T* v) {
70 T value = 0;
71 unsigned shift = 0;
72 u8 byte;
73 do {
74 if (UNLIKELY(begin == end))
75 return begin;
76 byte = *(begin++);
77 T slice = byte & 0x7f;
78 value += slice << shift;
79 shift += 7;
80 } while (byte >= 128);
81 *v = value;
82 return begin;
83}
84
85} // namespace __sanitizer
86
87#endif // SANITIZER_LEB128_H
lib/tsan/sanitizer_common/sanitizer_libc.cpp+24-3
......@@ -10,6 +10,9 @@
1010// run-time libraries. See sanitizer_libc.h for details.
1111//===----------------------------------------------------------------------===//
1212
13// Do not redefine builtins; this file is defining the builtin replacements.
14#define SANITIZER_COMMON_NO_REDEFINE_BUILTINS
15
1316#include "sanitizer_allocator_internal.h"
1417#include "sanitizer_common.h"
1518#include "sanitizer_libc.h"
......@@ -46,7 +49,10 @@ int internal_memcmp(const void* s1, const void* s2, uptr n) {
4649 return 0;
4750}
4851
49void *internal_memcpy(void *dest, const void *src, uptr n) {
52extern "C" {
53SANITIZER_INTERFACE_ATTRIBUTE void *__sanitizer_internal_memcpy(void *dest,
54 const void *src,
55 uptr n) {
5056 char *d = (char*)dest;
5157 const char *s = (const char *)src;
5258 for (uptr i = 0; i < n; ++i)
......@@ -54,7 +60,8 @@ void *internal_memcpy(void *dest, const void *src, uptr n) {
5460 return dest;
5561}
5662
57void *internal_memmove(void *dest, const void *src, uptr n) {
63SANITIZER_INTERFACE_ATTRIBUTE void *__sanitizer_internal_memmove(
64 void *dest, const void *src, uptr n) {
5865 char *d = (char*)dest;
5966 const char *s = (const char *)src;
6067 sptr i, signed_n = (sptr)n;
......@@ -72,7 +79,8 @@ void *internal_memmove(void *dest, const void *src, uptr n) {
7279 return dest;
7380}
7481
75void *internal_memset(void* s, int c, uptr n) {
82SANITIZER_INTERFACE_ATTRIBUTE void *__sanitizer_internal_memset(void *s, int c,
83 uptr n) {
7684 // Optimize for the most performance-critical case:
7785 if ((reinterpret_cast<uptr>(s) % 16) == 0 && (n % 16) == 0) {
7886 u64 *p = reinterpret_cast<u64*>(s);
......@@ -95,6 +103,7 @@ void *internal_memset(void* s, int c, uptr n) {
95103 }
96104 return s;
97105}
106} // extern "C"
98107
99108uptr internal_strcspn(const char *s, const char *reject) {
100109 uptr i;
......@@ -258,6 +267,18 @@ s64 internal_simple_strtoll(const char *nptr, const char **endptr, int base) {
258267 }
259268}
260269
270uptr internal_wcslen(const wchar_t *s) {
271 uptr i = 0;
272 while (s[i]) i++;
273 return i;
274}
275
276uptr internal_wcsnlen(const wchar_t *s, uptr maxlen) {
277 uptr i = 0;
278 while (i < maxlen && s[i]) i++;
279 return i;
280}
281
261282bool mem_is_zero(const char *beg, uptr size) {
262283 CHECK_LE(size, 1ULL << FIRST_32_SECOND_64(30, 40)); // Sanity check.
263284 const char *end = beg + size;
lib/tsan/sanitizer_common/sanitizer_libc.h+25-4
......@@ -24,15 +24,33 @@ namespace __sanitizer {
2424
2525// internal_X() is a custom implementation of X() for use in RTL.
2626
27extern "C" {
28// These are used as builtin replacements; see sanitizer_redefine_builtins.h.
29// In normal runtime code, use the __sanitizer::internal_X() aliases instead.
30SANITIZER_INTERFACE_ATTRIBUTE void *__sanitizer_internal_memcpy(void *dest,
31 const void *src,
32 uptr n);
33SANITIZER_INTERFACE_ATTRIBUTE void *__sanitizer_internal_memmove(
34 void *dest, const void *src, uptr n);
35SANITIZER_INTERFACE_ATTRIBUTE void *__sanitizer_internal_memset(void *s, int c,
36 uptr n);
37} // extern "C"
38
2739// String functions
2840s64 internal_atoll(const char *nptr);
2941void *internal_memchr(const void *s, int c, uptr n);
3042void *internal_memrchr(const void *s, int c, uptr n);
3143int internal_memcmp(const void* s1, const void* s2, uptr n);
32void *internal_memcpy(void *dest, const void *src, uptr n);
33void *internal_memmove(void *dest, const void *src, uptr n);
44ALWAYS_INLINE void *internal_memcpy(void *dest, const void *src, uptr n) {
45 return __sanitizer_internal_memcpy(dest, src, n);
46}
47ALWAYS_INLINE void *internal_memmove(void *dest, const void *src, uptr n) {
48 return __sanitizer_internal_memmove(dest, src, n);
49}
3450// Should not be used in performance-critical places.
35void *internal_memset(void *s, int c, uptr n);
51ALWAYS_INLINE void *internal_memset(void *s, int c, uptr n) {
52 return __sanitizer_internal_memset(s, c, n);
53}
3654char* internal_strchr(const char *s, int c);
3755char *internal_strchrnul(const char *s, int c);
3856int internal_strcmp(const char *s1, const char *s2);
......@@ -49,7 +67,10 @@ char *internal_strrchr(const char *s, int c);
4967char *internal_strstr(const char *haystack, const char *needle);
5068// Works only for base=10 and doesn't set errno.
5169s64 internal_simple_strtoll(const char *nptr, const char **endptr, int base);
52int internal_snprintf(char *buffer, uptr length, const char *format, ...);
70int internal_snprintf(char *buffer, uptr length, const char *format, ...)
71 FORMAT(3, 4);
72uptr internal_wcslen(const wchar_t *s);
73uptr internal_wcsnlen(const wchar_t *s, uptr maxlen);
5374
5475// Return true if all bytes in [mem, mem+size) are zero.
5576// Optimized for the case when the result is true.
lib/tsan/sanitizer_common/sanitizer_libignore.cpp+6-6
......@@ -8,7 +8,7 @@
88
99#include "sanitizer_platform.h"
1010
11#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_MAC || \
11#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_APPLE || \
1212 SANITIZER_NETBSD
1313
1414#include "sanitizer_libignore.h"
......@@ -22,9 +22,9 @@ LibIgnore::LibIgnore(LinkerInitialized) {
2222}
2323
2424void LibIgnore::AddIgnoredLibrary(const char *name_templ) {
25 BlockingMutexLock lock(&mutex_);
25 Lock lock(&mutex_);
2626 if (count_ >= kMaxLibs) {
27 Report("%s: too many ignored libraries (max: %d)\n", SanitizerToolName,
27 Report("%s: too many ignored libraries (max: %zu)\n", SanitizerToolName,
2828 kMaxLibs);
2929 Die();
3030 }
......@@ -36,7 +36,7 @@ void LibIgnore::AddIgnoredLibrary(const char *name_templ) {
3636}
3737
3838void LibIgnore::OnLibraryLoaded(const char *name) {
39 BlockingMutexLock lock(&mutex_);
39 Lock lock(&mutex_);
4040 // Try to match suppressions with symlink target.
4141 InternalMmapVector<char> buf(kMaxPathLength);
4242 if (name && internal_readlink(name, buf.data(), buf.size() - 1) > 0 &&
......@@ -105,7 +105,7 @@ void LibIgnore::OnLibraryLoaded(const char *name) {
105105 continue;
106106 if (IsPcInstrumented(range.beg) && IsPcInstrumented(range.end - 1))
107107 continue;
108 VReport(1, "Adding instrumented range %p-%p from library '%s'\n",
108 VReport(1, "Adding instrumented range 0x%zx-0x%zx from library '%s'\n",
109109 range.beg, range.end, mod.full_name());
110110 const uptr idx =
111111 atomic_load(&instrumented_ranges_count_, memory_order_relaxed);
......@@ -125,5 +125,5 @@ void LibIgnore::OnLibraryUnloaded() {
125125
126126} // namespace __sanitizer
127127
128#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_MAC ||
128#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_APPLE ||
129129 // SANITIZER_NETBSD
lib/tsan/sanitizer_common/sanitizer_libignore.h+1-1
......@@ -77,7 +77,7 @@ class LibIgnore {
7777 LibCodeRange instrumented_code_ranges_[kMaxInstrumentedRanges];
7878
7979 // Cold part:
80 BlockingMutex mutex_;
80 Mutex mutex_;
8181 uptr count_;
8282 Lib libs_[kMaxLibs];
8383 bool track_instrumented_libs_;
lib/tsan/sanitizer_common/sanitizer_linux.cpp+317-193
......@@ -34,7 +34,7 @@
3434// format. Struct kernel_stat is defined as 'struct stat' in asm/stat.h. To
3535// access stat from asm/stat.h, without conflicting with definition in
3636// sys/stat.h, we use this trick.
37#if defined(__mips64)
37#if SANITIZER_MIPS64
3838#include <asm/unistd.h>
3939#include <sys/types.h>
4040#define stat kernel_stat
......@@ -78,8 +78,13 @@
7878#include <sys/personality.h>
7979#endif
8080
81#if SANITIZER_LINUX && defined(__loongarch__)
82# include <sys/sysmacros.h>
83#endif
84
8185#if SANITIZER_FREEBSD
8286#include <sys/exec.h>
87#include <sys/procctl.h>
8388#include <sys/sysctl.h>
8489#include <machine/atomic.h>
8590extern "C" {
......@@ -123,8 +128,9 @@ const int FUTEX_WAKE_PRIVATE = FUTEX_WAKE | FUTEX_PRIVATE_FLAG;
123128// Are we using 32-bit or 64-bit Linux syscalls?
124129// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32
125130// but it still needs to use 64-bit syscalls.
126#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__powerpc64__) || \
127 SANITIZER_WORDSIZE == 64)
131#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__powerpc64__) || \
132 SANITIZER_WORDSIZE == 64 || \
133 (defined(__mips__) && _MIPS_SIM == _ABIN32))
128134# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1
129135#else
130136# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
......@@ -150,17 +156,51 @@ const int FUTEX_WAKE_PRIVATE = FUTEX_WAKE | FUTEX_PRIVATE_FLAG;
150156
151157namespace __sanitizer {
152158
153#if SANITIZER_LINUX && defined(__x86_64__)
154#include "sanitizer_syscall_linux_x86_64.inc"
155#elif SANITIZER_LINUX && SANITIZER_RISCV64
156#include "sanitizer_syscall_linux_riscv64.inc"
157#elif SANITIZER_LINUX && defined(__aarch64__)
158#include "sanitizer_syscall_linux_aarch64.inc"
159#elif SANITIZER_LINUX && defined(__arm__)
160#include "sanitizer_syscall_linux_arm.inc"
161#else
162#include "sanitizer_syscall_generic.inc"
163#endif
159void SetSigProcMask(__sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset) {
160 CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, set, oldset));
161}
162
163void BlockSignals(__sanitizer_sigset_t *oldset) {
164 __sanitizer_sigset_t set;
165 internal_sigfillset(&set);
166# if SANITIZER_LINUX && !SANITIZER_ANDROID
167 // Glibc uses SIGSETXID signal during setuid call. If this signal is blocked
168 // on any thread, setuid call hangs.
169 // See test/sanitizer_common/TestCases/Linux/setuid.c.
170 internal_sigdelset(&set, 33);
171# endif
172# if SANITIZER_LINUX
173 // Seccomp-BPF-sandboxed processes rely on SIGSYS to handle trapped syscalls.
174 // If this signal is blocked, such calls cannot be handled and the process may
175 // hang.
176 internal_sigdelset(&set, 31);
177# endif
178 SetSigProcMask(&set, oldset);
179}
180
181ScopedBlockSignals::ScopedBlockSignals(__sanitizer_sigset_t *copy) {
182 BlockSignals(&saved_);
183 if (copy)
184 internal_memcpy(copy, &saved_, sizeof(saved_));
185}
186
187ScopedBlockSignals::~ScopedBlockSignals() { SetSigProcMask(&saved_, nullptr); }
188
189# if SANITIZER_LINUX && defined(__x86_64__)
190# include "sanitizer_syscall_linux_x86_64.inc"
191# elif SANITIZER_LINUX && SANITIZER_RISCV64
192# include "sanitizer_syscall_linux_riscv64.inc"
193# elif SANITIZER_LINUX && defined(__aarch64__)
194# include "sanitizer_syscall_linux_aarch64.inc"
195# elif SANITIZER_LINUX && defined(__arm__)
196# include "sanitizer_syscall_linux_arm.inc"
197# elif SANITIZER_LINUX && defined(__hexagon__)
198# include "sanitizer_syscall_linux_hexagon.inc"
199# elif SANITIZER_LINUX && SANITIZER_LOONGARCH64
200# include "sanitizer_syscall_linux_loongarch64.inc"
201# else
202# include "sanitizer_syscall_generic.inc"
203# endif
164204
165205// --------------- sanitizer_libc.h
166206#if !SANITIZER_SOLARIS && !SANITIZER_NETBSD
......@@ -204,7 +244,7 @@ uptr internal_close(fd_t fd) {
204244}
205245
206246uptr internal_open(const char *filename, int flags) {
207#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
247# if SANITIZER_LINUX
208248 return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags);
209249#else
210250 return internal_syscall(SYSCALL(open), (uptr)filename, flags);
......@@ -212,7 +252,7 @@ uptr internal_open(const char *filename, int flags) {
212252}
213253
214254uptr internal_open(const char *filename, int flags, u32 mode) {
215#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
255# if SANITIZER_LINUX
216256 return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags,
217257 mode);
218258#else
......@@ -241,7 +281,7 @@ uptr internal_ftruncate(fd_t fd, uptr size) {
241281 return res;
242282}
243283
244#if !SANITIZER_LINUX_USES_64BIT_SYSCALLS && SANITIZER_LINUX
284#if (!SANITIZER_LINUX_USES_64BIT_SYSCALLS || SANITIZER_SPARC) && SANITIZER_LINUX
245285static void stat64_to_stat(struct stat64 *in, struct stat *out) {
246286 internal_memset(out, 0, sizeof(*out));
247287 out->st_dev = in->st_dev;
......@@ -260,7 +300,29 @@ static void stat64_to_stat(struct stat64 *in, struct stat *out) {
260300}
261301#endif
262302
263#if defined(__mips64)
303#if SANITIZER_LINUX && defined(__loongarch__)
304static void statx_to_stat(struct statx *in, struct stat *out) {
305 internal_memset(out, 0, sizeof(*out));
306 out->st_dev = makedev(in->stx_dev_major, in->stx_dev_minor);
307 out->st_ino = in->stx_ino;
308 out->st_mode = in->stx_mode;
309 out->st_nlink = in->stx_nlink;
310 out->st_uid = in->stx_uid;
311 out->st_gid = in->stx_gid;
312 out->st_rdev = makedev(in->stx_rdev_major, in->stx_rdev_minor);
313 out->st_size = in->stx_size;
314 out->st_blksize = in->stx_blksize;
315 out->st_blocks = in->stx_blocks;
316 out->st_atime = in->stx_atime.tv_sec;
317 out->st_atim.tv_nsec = in->stx_atime.tv_nsec;
318 out->st_mtime = in->stx_mtime.tv_sec;
319 out->st_mtim.tv_nsec = in->stx_mtime.tv_nsec;
320 out->st_ctime = in->stx_ctime.tv_sec;
321 out->st_ctim.tv_nsec = in->stx_ctime.tv_nsec;
322}
323#endif
324
325#if SANITIZER_MIPS64
264326// Undefine compatibility macros from <sys/stat.h>
265327// so that they would not clash with the kernel_stat
266328// st_[a|m|c]time fields
......@@ -311,52 +373,65 @@ static void kernel_stat_to_stat(struct kernel_stat *in, struct stat *out) {
311373#endif
312374
313375uptr internal_stat(const char *path, void *buf) {
314#if SANITIZER_FREEBSD
376# if SANITIZER_FREEBSD
315377 return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf, 0);
316#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
378# elif SANITIZER_LINUX
379# if defined(__loongarch__)
380 struct statx bufx;
381 int res = internal_syscall(SYSCALL(statx), AT_FDCWD, (uptr)path,
382 AT_NO_AUTOMOUNT, STATX_BASIC_STATS, (uptr)&bufx);
383 statx_to_stat(&bufx, (struct stat *)buf);
384 return res;
385# elif (SANITIZER_WORDSIZE == 64 || SANITIZER_X32 || \
386 (defined(__mips__) && _MIPS_SIM == _ABIN32)) && \
387 !SANITIZER_SPARC
317388 return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf,
318389 0);
319#elif SANITIZER_LINUX_USES_64BIT_SYSCALLS
320# if defined(__mips64)
321 // For mips64, stat syscall fills buffer in the format of kernel_stat
322 struct kernel_stat kbuf;
323 int res = internal_syscall(SYSCALL(stat), path, &kbuf);
324 kernel_stat_to_stat(&kbuf, (struct stat *)buf);
390# else
391 struct stat64 buf64;
392 int res = internal_syscall(SYSCALL(fstatat64), AT_FDCWD, (uptr)path,
393 (uptr)&buf64, 0);
394 stat64_to_stat(&buf64, (struct stat *)buf);
325395 return res;
326# else
327 return internal_syscall(SYSCALL(stat), (uptr)path, (uptr)buf);
328# endif
329#else
396# endif
397# else
330398 struct stat64 buf64;
331399 int res = internal_syscall(SYSCALL(stat64), path, &buf64);
332400 stat64_to_stat(&buf64, (struct stat *)buf);
333401 return res;
334#endif
402# endif
335403}
336404
337405uptr internal_lstat(const char *path, void *buf) {
338#if SANITIZER_FREEBSD
406# if SANITIZER_FREEBSD
339407 return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf,
340408 AT_SYMLINK_NOFOLLOW);
341#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
409# elif SANITIZER_LINUX
410# if defined(__loongarch__)
411 struct statx bufx;
412 int res = internal_syscall(SYSCALL(statx), AT_FDCWD, (uptr)path,
413 AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT,
414 STATX_BASIC_STATS, (uptr)&bufx);
415 statx_to_stat(&bufx, (struct stat *)buf);
416 return res;
417# elif (defined(_LP64) || SANITIZER_X32 || \
418 (defined(__mips__) && _MIPS_SIM == _ABIN32)) && \
419 !SANITIZER_SPARC
342420 return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf,
343421 AT_SYMLINK_NOFOLLOW);
344#elif SANITIZER_LINUX_USES_64BIT_SYSCALLS
345# if SANITIZER_MIPS64
346 // For mips64, lstat syscall fills buffer in the format of kernel_stat
347 struct kernel_stat kbuf;
348 int res = internal_syscall(SYSCALL(lstat), path, &kbuf);
349 kernel_stat_to_stat(&kbuf, (struct stat *)buf);
422# else
423 struct stat64 buf64;
424 int res = internal_syscall(SYSCALL(fstatat64), AT_FDCWD, (uptr)path,
425 (uptr)&buf64, AT_SYMLINK_NOFOLLOW);
426 stat64_to_stat(&buf64, (struct stat *)buf);
350427 return res;
351# else
352 return internal_syscall(SYSCALL(lstat), (uptr)path, (uptr)buf);
353# endif
354#else
428# endif
429# else
355430 struct stat64 buf64;
356431 int res = internal_syscall(SYSCALL(lstat64), path, &buf64);
357432 stat64_to_stat(&buf64, (struct stat *)buf);
358433 return res;
359#endif
434# endif
360435}
361436
362437uptr internal_fstat(fd_t fd, void *buf) {
......@@ -367,9 +442,15 @@ uptr internal_fstat(fd_t fd, void *buf) {
367442 int res = internal_syscall(SYSCALL(fstat), fd, &kbuf);
368443 kernel_stat_to_stat(&kbuf, (struct stat *)buf);
369444 return res;
370# else
445# elif SANITIZER_LINUX && defined(__loongarch__)
446 struct statx bufx;
447 int res = internal_syscall(SYSCALL(statx), fd, "", AT_EMPTY_PATH,
448 STATX_BASIC_STATS, (uptr)&bufx);
449 statx_to_stat(&bufx, (struct stat *)buf);
450 return res;
451# else
371452 return internal_syscall(SYSCALL(fstat), fd, (uptr)buf);
372# endif
453# endif
373454#else
374455 struct stat64 buf64;
375456 int res = internal_syscall(SYSCALL(fstat64), fd, &buf64);
......@@ -390,7 +471,7 @@ uptr internal_dup(int oldfd) {
390471}
391472
392473uptr internal_dup2(int oldfd, int newfd) {
393#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
474# if SANITIZER_LINUX
394475 return internal_syscall(SYSCALL(dup3), oldfd, newfd, 0);
395476#else
396477 return internal_syscall(SYSCALL(dup2), oldfd, newfd);
......@@ -398,7 +479,7 @@ uptr internal_dup2(int oldfd, int newfd) {
398479}
399480
400481uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
401#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
482# if SANITIZER_LINUX
402483 return internal_syscall(SYSCALL(readlinkat), AT_FDCWD, (uptr)path, (uptr)buf,
403484 bufsize);
404485#else
......@@ -407,7 +488,7 @@ uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
407488}
408489
409490uptr internal_unlink(const char *path) {
410#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
491# if SANITIZER_LINUX
411492 return internal_syscall(SYSCALL(unlinkat), AT_FDCWD, (uptr)path, 0);
412493#else
413494 return internal_syscall(SYSCALL(unlink), (uptr)path);
......@@ -415,15 +496,15 @@ uptr internal_unlink(const char *path) {
415496}
416497
417498uptr internal_rename(const char *oldpath, const char *newpath) {
418#if defined(__riscv)
499# if (defined(__riscv) || defined(__loongarch__)) && defined(__linux__)
419500 return internal_syscall(SYSCALL(renameat2), AT_FDCWD, (uptr)oldpath, AT_FDCWD,
420501 (uptr)newpath, 0);
421#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
502# elif SANITIZER_LINUX
422503 return internal_syscall(SYSCALL(renameat), AT_FDCWD, (uptr)oldpath, AT_FDCWD,
423504 (uptr)newpath);
424#else
505# else
425506 return internal_syscall(SYSCALL(rename), (uptr)oldpath, (uptr)newpath);
426#endif
507# endif
427508}
428509
429510uptr internal_sched_yield() {
......@@ -460,17 +541,20 @@ bool FileExists(const char *filename) {
460541 if (ShouldMockFailureToOpen(filename))
461542 return false;
462543 struct stat st;
463#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
464 if (internal_syscall(SYSCALL(newfstatat), AT_FDCWD, filename, &st, 0))
465#else
466544 if (internal_stat(filename, &st))
467#endif
468545 return false;
469546 // Sanity check: filename is a regular file.
470547 return S_ISREG(st.st_mode);
471548}
472549
473#if !SANITIZER_NETBSD
550bool DirExists(const char *path) {
551 struct stat st;
552 if (internal_stat(path, &st))
553 return false;
554 return S_ISDIR(st.st_mode);
555}
556
557# if !SANITIZER_NETBSD
474558tid_t GetTid() {
475559#if SANITIZER_FREEBSD
476560 long Tid;
......@@ -659,48 +743,6 @@ void FutexWake(atomic_uint32_t *p, u32 count) {
659743# endif
660744}
661745
662enum { MtxUnlocked = 0, MtxLocked = 1, MtxSleeping = 2 };
663
664BlockingMutex::BlockingMutex() {
665 internal_memset(this, 0, sizeof(*this));
666}
667
668void BlockingMutex::Lock() {
669 CHECK_EQ(owner_, 0);
670 atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
671 if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked)
672 return;
673 while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) {
674#if SANITIZER_FREEBSD
675 _umtx_op(m, UMTX_OP_WAIT_UINT, MtxSleeping, 0, 0);
676#elif SANITIZER_NETBSD
677 sched_yield(); /* No userspace futex-like synchronization */
678#else
679 internal_syscall(SYSCALL(futex), (uptr)m, FUTEX_WAIT_PRIVATE, MtxSleeping,
680 0, 0, 0);
681#endif
682 }
683}
684
685void BlockingMutex::Unlock() {
686 atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
687 u32 v = atomic_exchange(m, MtxUnlocked, memory_order_release);
688 CHECK_NE(v, MtxUnlocked);
689 if (v == MtxSleeping) {
690#if SANITIZER_FREEBSD
691 _umtx_op(m, UMTX_OP_WAKE, 1, 0, 0);
692#elif SANITIZER_NETBSD
693 /* No userspace futex-like synchronization */
694#else
695 internal_syscall(SYSCALL(futex), (uptr)m, FUTEX_WAKE_PRIVATE, 1, 0, 0, 0);
696#endif
697 }
698}
699
700void BlockingMutex::CheckLocked() const {
701 auto m = reinterpret_cast<atomic_uint32_t const *>(&opaque_storage_);
702 CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed));
703}
704746# endif // !SANITIZER_SOLARIS
705747
706748// ----------------- sanitizer_linux.h
......@@ -711,17 +753,17 @@ void BlockingMutex::CheckLocked() const {
711753// Not used
712754#else
713755struct linux_dirent {
714#if SANITIZER_X32 || defined(__aarch64__) || SANITIZER_RISCV64
756# if SANITIZER_X32 || SANITIZER_LINUX
715757 u64 d_ino;
716758 u64 d_off;
717#else
759# else
718760 unsigned long d_ino;
719761 unsigned long d_off;
720#endif
762# endif
721763 unsigned short d_reclen;
722#if defined(__aarch64__) || SANITIZER_RISCV64
764# if SANITIZER_LINUX
723765 unsigned char d_type;
724#endif
766# endif
725767 char d_name[256];
726768};
727769#endif
......@@ -757,11 +799,11 @@ int internal_dlinfo(void *handle, int request, void *p) {
757799uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) {
758800#if SANITIZER_FREEBSD
759801 return internal_syscall(SYSCALL(getdirentries), fd, (uptr)dirp, count, NULL);
760#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
802# elif SANITIZER_LINUX
761803 return internal_syscall(SYSCALL(getdents64), fd, (uptr)dirp, count);
762#else
804# else
763805 return internal_syscall(SYSCALL(getdents), fd, (uptr)dirp, count);
764#endif
806# endif
765807}
766808
767809uptr internal_lseek(fd_t fd, OFF_T offset, int whence) {
......@@ -772,18 +814,29 @@ uptr internal_lseek(fd_t fd, OFF_T offset, int whence) {
772814uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) {
773815 return internal_syscall(SYSCALL(prctl), option, arg2, arg3, arg4, arg5);
774816}
775#endif
817# if defined(__x86_64__)
818# include <asm/unistd_64.h>
819// Currently internal_arch_prctl() is only needed on x86_64.
820uptr internal_arch_prctl(int option, uptr arg2) {
821 return internal_syscall(__NR_arch_prctl, option, arg2);
822}
823# endif
824# endif
776825
777826uptr internal_sigaltstack(const void *ss, void *oss) {
778827 return internal_syscall(SYSCALL(sigaltstack), (uptr)ss, (uptr)oss);
779828}
780829
781830int internal_fork() {
782#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
831# if SANITIZER_LINUX
832# if SANITIZER_S390
833 return internal_syscall(SYSCALL(clone), 0, SIGCHLD);
834# else
783835 return internal_syscall(SYSCALL(clone), SIGCHLD, 0);
784#else
836# endif
837# else
785838 return internal_syscall(SYSCALL(fork));
786#endif
839# endif
787840}
788841
789842#if SANITIZER_FREEBSD
......@@ -911,6 +964,10 @@ bool internal_sigismember(__sanitizer_sigset_t *set, int signum) {
911964 return k_set->sig[idx] & ((uptr)1 << bit);
912965}
913966#elif SANITIZER_FREEBSD
967uptr internal_procctl(int type, int id, int cmd, void *data) {
968 return internal_syscall(SYSCALL(procctl), type, id, cmd, data);
969}
970
914971void internal_sigdelset(__sanitizer_sigset_t *set, int signum) {
915972 sigset_t *rset = reinterpret_cast<sigset_t *>(set);
916973 sigdelset(rset, signum);
......@@ -1052,7 +1109,7 @@ uptr GetMaxVirtualAddress() {
10521109#if SANITIZER_NETBSD && defined(__x86_64__)
10531110 return 0x7f7ffffff000ULL; // (0x00007f8000000000 - PAGE_SIZE)
10541111#elif SANITIZER_WORDSIZE == 64
1055# if defined(__powerpc64__) || defined(__aarch64__)
1112# if defined(__powerpc64__) || defined(__aarch64__) || defined(__loongarch__)
10561113 // On PowerPC64 we have two different address space layouts: 44- and 46-bit.
10571114 // We somehow need to figure out which one we are using now and choose
10581115 // one of 0x00000fffffffffffUL and 0x00003fffffffffffUL.
......@@ -1060,10 +1117,11 @@ uptr GetMaxVirtualAddress() {
10601117 // of the address space, so simply checking the stack address is not enough.
10611118 // This should (does) work for both PowerPC64 Endian modes.
10621119 // Similarly, aarch64 has multiple address space layouts: 39, 42 and 47-bit.
1120 // loongarch64 also has multiple address space layouts: default is 47-bit.
10631121 return (1ULL << (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1)) - 1;
10641122#elif SANITIZER_RISCV64
10651123 return (1ULL << 38) - 1;
1066# elif defined(__mips64)
1124# elif SANITIZER_MIPS64
10671125 return (1ULL << 40) - 1; // 0x000000ffffffffffUL;
10681126# elif defined(__s390x__)
10691127 return (1ULL << 53) - 1; // 0x001fffffffffffffUL;
......@@ -1217,7 +1275,8 @@ void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) {
12171275}
12181276#endif
12191277
1220#if defined(__x86_64__) && SANITIZER_LINUX
1278#if SANITIZER_LINUX
1279#if defined(__x86_64__)
12211280// We cannot use glibc's clone wrapper, because it messes with the child
12221281// task's TLS. It writes the PID and TID of the child task to its thread
12231282// descriptor, but in our case the child task shares the thread descriptor with
......@@ -1399,7 +1458,7 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
13991458#elif defined(__aarch64__)
14001459uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
14011460 int *parent_tidptr, void *newtls, int *child_tidptr) {
1402 long long res;
1461 register long long res __asm__("x0");
14031462 if (!fn || !child_stack)
14041463 return -EINVAL;
14051464 CHECK_EQ(0, (uptr)child_stack % 16);
......@@ -1447,6 +1506,47 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
14471506 : "x30", "memory");
14481507 return res;
14491508}
1509#elif SANITIZER_LOONGARCH64
1510uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
1511 int *parent_tidptr, void *newtls, int *child_tidptr) {
1512 if (!fn || !child_stack)
1513 return -EINVAL;
1514
1515 CHECK_EQ(0, (uptr)child_stack % 16);
1516
1517 register int res __asm__("$a0");
1518 register int __flags __asm__("$a0") = flags;
1519 register void *__stack __asm__("$a1") = child_stack;
1520 register int *__ptid __asm__("$a2") = parent_tidptr;
1521 register int *__ctid __asm__("$a3") = child_tidptr;
1522 register void *__tls __asm__("$a4") = newtls;
1523 register int (*__fn)(void *) __asm__("$a5") = fn;
1524 register void *__arg __asm__("$a6") = arg;
1525 register int nr_clone __asm__("$a7") = __NR_clone;
1526
1527 __asm__ __volatile__(
1528 "syscall 0\n"
1529
1530 // if ($a0 != 0)
1531 // return $a0;
1532 "bnez $a0, 1f\n"
1533
1534 // In the child, now. Call "fn(arg)".
1535 "move $a0, $a6\n"
1536 "jirl $ra, $a5, 0\n"
1537
1538 // Call _exit($a0).
1539 "addi.d $a7, $zero, %9\n"
1540 "syscall 0\n"
1541
1542 "1:\n"
1543
1544 : "=r"(res)
1545 : "0"(__flags), "r"(__stack), "r"(__ptid), "r"(__ctid), "r"(__tls),
1546 "r"(__fn), "r"(__arg), "r"(nr_clone), "i"(__NR_exit)
1547 : "memory", "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8");
1548 return res;
1549}
14501550#elif defined(__powerpc64__)
14511551uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
14521552 int *parent_tidptr, void *newtls, int *child_tidptr) {
......@@ -1556,7 +1656,7 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
15561656 : "cr0", "cr1", "memory", "ctr", "r0", "r27", "r28", "r29");
15571657 return res;
15581658}
1559#elif defined(__i386__) && SANITIZER_LINUX
1659#elif defined(__i386__)
15601660uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
15611661 int *parent_tidptr, void *newtls, int *child_tidptr) {
15621662 int res;
......@@ -1621,7 +1721,7 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
16211721 : "memory");
16221722 return res;
16231723}
1624#elif defined(__arm__) && SANITIZER_LINUX
1724#elif defined(__arm__)
16251725uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
16261726 int *parent_tidptr, void *newtls, int *child_tidptr) {
16271727 unsigned int res;
......@@ -1687,7 +1787,8 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
16871787 : "memory");
16881788 return res;
16891789}
1690#endif // defined(__x86_64__) && SANITIZER_LINUX
1790#endif
1791#endif // SANITIZER_LINUX
16911792
16921793#if SANITIZER_LINUX
16931794int internal_uname(struct utsname *buf) {
......@@ -1778,23 +1879,18 @@ HandleSignalMode GetHandleSignalMode(int signum) {
17781879
17791880#if !SANITIZER_GO
17801881void *internal_start_thread(void *(*func)(void *arg), void *arg) {
1882 if (&real_pthread_create == 0)
1883 return nullptr;
17811884 // Start the thread with signals blocked, otherwise it can steal user signals.
1782 __sanitizer_sigset_t set, old;
1783 internal_sigfillset(&set);
1784#if SANITIZER_LINUX && !SANITIZER_ANDROID
1785 // Glibc uses SIGSETXID signal during setuid call. If this signal is blocked
1786 // on any thread, setuid call hangs (see test/tsan/setuid.c).
1787 internal_sigdelset(&set, 33);
1788#endif
1789 internal_sigprocmask(SIG_SETMASK, &set, &old);
1885 ScopedBlockSignals block(nullptr);
17901886 void *th;
17911887 real_pthread_create(&th, nullptr, func, arg);
1792 internal_sigprocmask(SIG_SETMASK, &old, nullptr);
17931888 return th;
17941889}
17951890
17961891void internal_join_thread(void *th) {
1797 real_pthread_join(th, nullptr);
1892 if (&real_pthread_join)
1893 real_pthread_join(th, nullptr);
17981894}
17991895#else
18001896void *internal_start_thread(void *(*func)(void *), void *arg) { return 0; }
......@@ -1802,7 +1898,7 @@ void *internal_start_thread(void *(*func)(void *), void *arg) { return 0; }
18021898void internal_join_thread(void *th) {}
18031899#endif
18041900
1805#if defined(__aarch64__)
1901#if SANITIZER_LINUX && defined(__aarch64__)
18061902// Android headers in the older NDK releases miss this definition.
18071903struct __sanitizer_esr_context {
18081904 struct _aarch64_ctx head;
......@@ -1811,7 +1907,7 @@ struct __sanitizer_esr_context {
18111907
18121908static bool Aarch64GetESR(ucontext_t *ucontext, u64 *esr) {
18131909 static const u32 kEsrMagic = 0x45535201;
1814 u8 *aux = ucontext->uc_mcontext.__reserved;
1910 u8 *aux = reinterpret_cast<u8 *>(ucontext->uc_mcontext.__reserved);
18151911 while (true) {
18161912 _aarch64_ctx *ctx = (_aarch64_ctx *)aux;
18171913 if (ctx->size == 0) break;
......@@ -1823,6 +1919,11 @@ static bool Aarch64GetESR(ucontext_t *ucontext, u64 *esr) {
18231919 }
18241920 return false;
18251921}
1922#elif SANITIZER_FREEBSD && defined(__aarch64__)
1923// FreeBSD doesn't provide ESR in the ucontext.
1924static bool Aarch64GetESR(ucontext_t *ucontext, u64 *esr) {
1925 return false;
1926}
18261927#endif
18271928
18281929using Context = ucontext_t;
......@@ -1841,7 +1942,7 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
18411942#else
18421943 uptr err = ucontext->uc_mcontext.gregs[REG_ERR];
18431944#endif // SANITIZER_FREEBSD
1844 return err & PF_WRITE ? WRITE : READ;
1945 return err & PF_WRITE ? Write : Read;
18451946#elif defined(__mips__)
18461947 uint32_t *exception_source;
18471948 uint32_t faulty_instruction;
......@@ -1864,7 +1965,7 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
18641965 case 0x2a: // swl
18651966 case 0x2e: // swr
18661967#endif
1867 return SignalContext::WRITE;
1968 return SignalContext::Write;
18681969
18691970 case 0x20: // lb
18701971 case 0x24: // lbu
......@@ -1879,27 +1980,34 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
18791980 case 0x22: // lwl
18801981 case 0x26: // lwr
18811982#endif
1882 return SignalContext::READ;
1983 return SignalContext::Read;
18831984#if __mips_isa_rev == 6
18841985 case 0x3b: // pcrel
18851986 op_code = (faulty_instruction >> 19) & 0x3;
18861987 switch (op_code) {
18871988 case 0x1: // lwpc
18881989 case 0x2: // lwupc
1889 return SignalContext::READ;
1990 return SignalContext::Read;
18901991 }
18911992#endif
18921993 }
1893 return SignalContext::UNKNOWN;
1994 return SignalContext::Unknown;
18941995#elif defined(__arm__)
18951996 static const uptr FSR_WRITE = 1U << 11;
18961997 uptr fsr = ucontext->uc_mcontext.error_code;
1897 return fsr & FSR_WRITE ? WRITE : READ;
1998 return fsr & FSR_WRITE ? Write : Read;
18981999#elif defined(__aarch64__)
18992000 static const u64 ESR_ELx_WNR = 1U << 6;
19002001 u64 esr;
1901 if (!Aarch64GetESR(ucontext, &esr)) return UNKNOWN;
1902 return esr & ESR_ELx_WNR ? WRITE : READ;
2002 if (!Aarch64GetESR(ucontext, &esr)) return Unknown;
2003 return esr & ESR_ELx_WNR ? Write : Read;
2004#elif defined(__loongarch__)
2005 u32 flags = ucontext->uc_mcontext.__flags;
2006 if (flags & SC_ADDRERR_RD)
2007 return SignalContext::Read;
2008 if (flags & SC_ADDRERR_WR)
2009 return SignalContext::Write;
2010 return SignalContext::Unknown;
19032011#elif defined(__sparc__)
19042012 // Decode the instruction to determine the access type.
19052013 // From OpenSolaris $SRC/uts/sun4/os/trap.c (get_accesstype).
......@@ -1915,9 +2023,13 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
19152023#endif
19162024#endif
19172025 u32 instr = *(u32 *)pc;
1918 return (instr >> 21) & 1 ? WRITE: READ;
2026 return (instr >> 21) & 1 ? Write: Read;
19192027#elif defined(__riscv)
2028#if SANITIZER_FREEBSD
2029 unsigned long pc = ucontext->uc_mcontext.mc_gpregs.gp_sepc;
2030#else
19202031 unsigned long pc = ucontext->uc_mcontext.__gregs[REG_PC];
2032#endif
19212033 unsigned faulty_instruction = *(uint16_t *)pc;
19222034
19232035#if defined(__riscv_compressed)
......@@ -1931,7 +2043,7 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
19312043#if __riscv_xlen == 64
19322044 case 0b10'011: // c.ldsp (rd != x0)
19332045#endif
1934 return rd ? SignalContext::READ : SignalContext::UNKNOWN;
2046 return rd ? SignalContext::Read : SignalContext::Unknown;
19352047 case 0b00'010: // c.lw
19362048#if __riscv_flen >= 32 && __riscv_xlen == 32
19372049 case 0b10'011: // c.flwsp
......@@ -1943,7 +2055,7 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
19432055 case 0b00'001: // c.fld
19442056 case 0b10'001: // c.fldsp
19452057#endif
1946 return SignalContext::READ;
2058 return SignalContext::Read;
19472059 case 0b00'110: // c.sw
19482060 case 0b10'110: // c.swsp
19492061#if __riscv_flen >= 32 || __riscv_xlen == 64
......@@ -1954,9 +2066,9 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
19542066 case 0b00'101: // c.fsd
19552067 case 0b10'101: // c.fsdsp
19562068#endif
1957 return SignalContext::WRITE;
2069 return SignalContext::Write;
19582070 default:
1959 return SignalContext::UNKNOWN;
2071 return SignalContext::Unknown;
19602072 }
19612073 }
19622074#endif
......@@ -1974,9 +2086,9 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
19742086#endif
19752087 case 0b100: // lbu
19762088 case 0b101: // lhu
1977 return SignalContext::READ;
2089 return SignalContext::Read;
19782090 default:
1979 return SignalContext::UNKNOWN;
2091 return SignalContext::Unknown;
19802092 }
19812093 case 0b0100011: // stores
19822094 switch (funct3) {
......@@ -1986,9 +2098,9 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
19862098#if __riscv_xlen == 64
19872099 case 0b011: // sd
19882100#endif
1989 return SignalContext::WRITE;
2101 return SignalContext::Write;
19902102 default:
1991 return SignalContext::UNKNOWN;
2103 return SignalContext::Unknown;
19922104 }
19932105#if __riscv_flen >= 32
19942106 case 0b0000111: // floating-point loads
......@@ -1997,9 +2109,9 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
19972109#if __riscv_flen == 64
19982110 case 0b011: // fld
19992111#endif
2000 return SignalContext::READ;
2112 return SignalContext::Read;
20012113 default:
2002 return SignalContext::UNKNOWN;
2114 return SignalContext::Unknown;
20032115 }
20042116 case 0b0100111: // floating-point stores
20052117 switch (funct3) {
......@@ -2007,17 +2119,17 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
20072119#if __riscv_flen == 64
20082120 case 0b011: // fsd
20092121#endif
2010 return SignalContext::WRITE;
2122 return SignalContext::Write;
20112123 default:
2012 return SignalContext::UNKNOWN;
2124 return SignalContext::Unknown;
20132125 }
20142126#endif
20152127 default:
2016 return SignalContext::UNKNOWN;
2128 return SignalContext::Unknown;
20172129 }
20182130#else
20192131 (void)ucontext;
2020 return UNKNOWN; // FIXME: Implement.
2132 return Unknown; // FIXME: Implement.
20212133#endif
20222134}
20232135
......@@ -2044,10 +2156,17 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
20442156 *bp = ucontext->uc_mcontext.arm_fp;
20452157 *sp = ucontext->uc_mcontext.arm_sp;
20462158#elif defined(__aarch64__)
2159# if SANITIZER_FREEBSD
2160 ucontext_t *ucontext = (ucontext_t*)context;
2161 *pc = ucontext->uc_mcontext.mc_gpregs.gp_elr;
2162 *bp = ucontext->uc_mcontext.mc_gpregs.gp_x[29];
2163 *sp = ucontext->uc_mcontext.mc_gpregs.gp_sp;
2164# else
20472165 ucontext_t *ucontext = (ucontext_t*)context;
20482166 *pc = ucontext->uc_mcontext.pc;
20492167 *bp = ucontext->uc_mcontext.regs[29];
20502168 *sp = ucontext->uc_mcontext.sp;
2169# endif
20512170#elif defined(__hppa__)
20522171 ucontext_t *ucontext = (ucontext_t*)context;
20532172 *pc = ucontext->uc_mcontext.sc_iaoq[0];
......@@ -2092,12 +2211,19 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
20922211 *sp = ucontext->uc_mcontext.gregs[REG_UESP];
20932212# endif
20942213#elif defined(__powerpc__) || defined(__powerpc64__)
2214# if SANITIZER_FREEBSD
2215 ucontext_t *ucontext = (ucontext_t *)context;
2216 *pc = ucontext->uc_mcontext.mc_srr0;
2217 *sp = ucontext->uc_mcontext.mc_frame[1];
2218 *bp = ucontext->uc_mcontext.mc_frame[31];
2219# else
20952220 ucontext_t *ucontext = (ucontext_t*)context;
20962221 *pc = ucontext->uc_mcontext.regs->nip;
20972222 *sp = ucontext->uc_mcontext.regs->gpr[PT_R1];
20982223 // The powerpc{,64}-linux ABIs do not specify r31 as the frame
20992224 // pointer, but GCC always uses r31 when we need a frame pointer.
21002225 *bp = ucontext->uc_mcontext.regs->gpr[PT_R31];
2226# endif
21012227#elif defined(__sparc__)
21022228#if defined(__arch64__) || defined(__sparcv9)
21032229#define STACK_BIAS 2047
......@@ -2136,12 +2262,28 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
21362262 *sp = ucontext->uc_mcontext.gregs[15];
21372263#elif defined(__riscv)
21382264 ucontext_t *ucontext = (ucontext_t*)context;
2265# if SANITIZER_FREEBSD
2266 *pc = ucontext->uc_mcontext.mc_gpregs.gp_sepc;
2267 *bp = ucontext->uc_mcontext.mc_gpregs.gp_s[0];
2268 *sp = ucontext->uc_mcontext.mc_gpregs.gp_sp;
2269# else
21392270 *pc = ucontext->uc_mcontext.__gregs[REG_PC];
21402271 *bp = ucontext->uc_mcontext.__gregs[REG_S0];
21412272 *sp = ucontext->uc_mcontext.__gregs[REG_SP];
2142#else
2143# error "Unsupported arch"
2144#endif
2273# endif
2274# elif defined(__hexagon__)
2275 ucontext_t *ucontext = (ucontext_t *)context;
2276 *pc = ucontext->uc_mcontext.pc;
2277 *bp = ucontext->uc_mcontext.r30;
2278 *sp = ucontext->uc_mcontext.r29;
2279# elif defined(__loongarch__)
2280 ucontext_t *ucontext = (ucontext_t *)context;
2281 *pc = ucontext->uc_mcontext.__pc;
2282 *bp = ucontext->uc_mcontext.__gregs[22];
2283 *sp = ucontext->uc_mcontext.__gregs[3];
2284# else
2285# error "Unsupported arch"
2286# endif
21452287}
21462288
21472289void SignalContext::InitPcSpBp() { GetPcSpBp(context, &pc, &sp, &bp); }
......@@ -2150,10 +2292,6 @@ void InitializePlatformEarly() {
21502292 // Do nothing.
21512293}
21522294
2153void MaybeReexec() {
2154 // No need to re-exec on Linux.
2155}
2156
21572295void CheckASLR() {
21582296#if SANITIZER_NETBSD
21592297 int mib[3];
......@@ -2175,49 +2313,35 @@ void CheckASLR() {
21752313 GetArgv()[0]);
21762314 Die();
21772315 }
2178#elif SANITIZER_PPC64V2
2179 // Disable ASLR for Linux PPC64LE.
2180 int old_personality = personality(0xffffffff);
2181 if (old_personality != -1 && (old_personality & ADDR_NO_RANDOMIZE) == 0) {
2182 VReport(1, "WARNING: Program is being run with address space layout "
2183 "randomization (ASLR) enabled which prevents the thread and "
2184 "memory sanitizers from working on powerpc64le.\n"
2185 "ASLR will be disabled and the program re-executed.\n");
2186 CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1);
2187 ReExec();
2188 }
21892316#elif SANITIZER_FREEBSD
2190 int aslr_pie;
2191 uptr len = sizeof(aslr_pie);
2192#if SANITIZER_WORDSIZE == 64
2193 if (UNLIKELY(internal_sysctlbyname("kern.elf64.aslr.pie_enable",
2194 &aslr_pie, &len, NULL, 0) == -1)) {
2317 int aslr_status;
2318 int r = internal_procctl(P_PID, 0, PROC_ASLR_STATUS, &aslr_status);
2319 if (UNLIKELY(r == -1)) {
21952320 // We're making things less 'dramatic' here since
2196 // the OID is not necessarily guaranteed to be here
2321 // the cmd is not necessarily guaranteed to be here
21972322 // just yet regarding FreeBSD release
21982323 return;
21992324 }
2200
2201 if (aslr_pie > 0) {
2325 if ((aslr_status & PROC_ASLR_ACTIVE) != 0) {
22022326 Printf("This sanitizer is not compatible with enabled ASLR "
22032327 "and binaries compiled with PIE\n");
22042328 Die();
22052329 }
2206#endif
2207 // there might be 32 bits compat for 64 bits
2208 if (UNLIKELY(internal_sysctlbyname("kern.elf32.aslr.pie_enable",
2209 &aslr_pie, &len, NULL, 0) == -1)) {
2210 return;
2211 }
2212
2213 if (aslr_pie > 0) {
2214 Printf("This sanitizer is not compatible with enabled ASLR "
2215 "and binaries compiled with PIE\n");
2216 Die();
2330# elif SANITIZER_PPC64V2
2331 // Disable ASLR for Linux PPC64LE.
2332 int old_personality = personality(0xffffffff);
2333 if (old_personality != -1 && (old_personality & ADDR_NO_RANDOMIZE) == 0) {
2334 VReport(1,
2335 "WARNING: Program is being run with address space layout "
2336 "randomization (ASLR) enabled which prevents the thread and "
2337 "memory sanitizers from working on powerpc64le.\n"
2338 "ASLR will be disabled and the program re-executed.\n");
2339 CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1);
2340 ReExec();
22172341 }
2218#else
2342# else
22192343 // Do nothing
2220#endif
2344# endif
22212345}
22222346
22232347void CheckMPROTECT() {
lib/tsan/sanitizer_common/sanitizer_linux.h+25-4
......@@ -49,26 +49,44 @@ uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count);
4949uptr internal_sigaltstack(const void* ss, void* oss);
5050uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
5151 __sanitizer_sigset_t *oldset);
52#if SANITIZER_GLIBC
52
53void SetSigProcMask(__sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset);
54void BlockSignals(__sanitizer_sigset_t *oldset = nullptr);
55struct ScopedBlockSignals {
56 explicit ScopedBlockSignals(__sanitizer_sigset_t *copy);
57 ~ScopedBlockSignals();
58
59 ScopedBlockSignals &operator=(const ScopedBlockSignals &) = delete;
60 ScopedBlockSignals(const ScopedBlockSignals &) = delete;
61
62 private:
63 __sanitizer_sigset_t saved_;
64};
65
66# if SANITIZER_GLIBC
5367uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp);
5468#endif
5569
5670// Linux-only syscalls.
5771#if SANITIZER_LINUX
5872uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5);
73# if defined(__x86_64__)
74uptr internal_arch_prctl(int option, uptr arg2);
75# endif
5976// Used only by sanitizer_stoptheworld. Signal handlers that are actually used
6077// (like the process-wide error reporting SEGV handler) must use
6178// internal_sigaction instead.
6279int internal_sigaction_norestorer(int signum, const void *act, void *oldact);
6380void internal_sigdelset(__sanitizer_sigset_t *set, int signum);
64#if defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) || \
65 defined(__powerpc64__) || defined(__s390__) || defined(__i386__) || \
66 defined(__arm__) || SANITIZER_RISCV64
81# if defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) || \
82 defined(__powerpc64__) || defined(__s390__) || defined(__i386__) || \
83 defined(__arm__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64
6784uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
6885 int *parent_tidptr, void *newtls, int *child_tidptr);
6986#endif
7087int internal_uname(struct utsname *buf);
7188#elif SANITIZER_FREEBSD
89uptr internal_procctl(int type, int id, int cmd, void *data);
7290void internal_sigdelset(__sanitizer_sigset_t *set, int signum);
7391#elif SANITIZER_NETBSD
7492void internal_sigdelset(__sanitizer_sigset_t *set, int signum);
......@@ -135,6 +153,9 @@ inline void ReleaseMemoryPagesToOSAndZeroFill(uptr beg, uptr end) {
135153 "rdhwr %0,$29\n" \
136154 ".set pop\n" : "=r"(__v)); \
137155 __v; })
156#elif defined (__riscv)
157# define __get_tls() \
158 ({ void** __v; __asm__("mv %0, tp" : "=r"(__v)); __v; })
138159#elif defined(__i386__)
139160# define __get_tls() \
140161 ({ void** __v; __asm__("movl %%gs:0, %0" : "=r"(__v)); __v; })
lib/tsan/sanitizer_common/sanitizer_linux_libcdep.cpp+109-30
......@@ -27,6 +27,7 @@
2727#include "sanitizer_linux.h"
2828#include "sanitizer_placement_new.h"
2929#include "sanitizer_procmaps.h"
30#include "sanitizer_solaris.h"
3031
3132#if SANITIZER_NETBSD
3233#define _RTLD_SOURCE // for __lwp_gettcb_fast() / __lwp_getprivate_fast()
......@@ -62,6 +63,7 @@
6263#endif
6364
6465#if SANITIZER_SOLARIS
66#include <stddef.h>
6567#include <stdlib.h>
6668#include <thread.h>
6769#endif
......@@ -146,7 +148,7 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
146148 pthread_attr_t attr;
147149 pthread_attr_init(&attr);
148150 CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0);
149 my_pthread_attr_getstack(&attr, &stackaddr, &stacksize);
151 internal_pthread_attr_getstack(&attr, &stackaddr, &stacksize);
150152 pthread_attr_destroy(&attr);
151153#endif // SANITIZER_SOLARIS
152154
......@@ -203,7 +205,8 @@ void InitTlsSize() {
203205 g_use_dlpi_tls_data =
204206 GetLibcVersion(&major, &minor, &patch) && major == 2 && minor >= 25;
205207
206#if defined(__aarch64__) || defined(__x86_64__) || defined(__powerpc64__)
208#if defined(__aarch64__) || defined(__x86_64__) || defined(__powerpc64__) || \
209 defined(__loongarch__)
207210 void *get_tls_static_info = dlsym(RTLD_NEXT, "_dl_get_tls_static_info");
208211 size_t tls_align;
209212 ((void (*)(size_t *, size_t *))get_tls_static_info)(&g_tls_size, &tls_align);
......@@ -216,14 +219,13 @@ void InitTlsSize() { }
216219// On glibc x86_64, ThreadDescriptorSize() needs to be precise due to the usage
217220// of g_tls_size. On other targets, ThreadDescriptorSize() is only used by lsan
218221// to get the pointer to thread-specific data keys in the thread control block.
219#if (SANITIZER_FREEBSD || SANITIZER_LINUX) && !SANITIZER_ANDROID
222#if (SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_SOLARIS) && \
223 !SANITIZER_ANDROID && !SANITIZER_GO
220224// sizeof(struct pthread) from glibc.
221225static atomic_uintptr_t thread_descriptor_size;
222226
223uptr ThreadDescriptorSize() {
224 uptr val = atomic_load_relaxed(&thread_descriptor_size);
225 if (val)
226 return val;
227static uptr ThreadDescriptorSizeFallback() {
228 uptr val = 0;
227229#if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
228230 int major;
229231 int minor;
......@@ -264,6 +266,8 @@ uptr ThreadDescriptorSize() {
264266#elif defined(__mips__)
265267 // TODO(sagarthakur): add more values as per different glibc versions.
266268 val = FIRST_32_SECOND_64(1152, 1776);
269#elif SANITIZER_LOONGARCH64
270 val = 1856; // from glibc 2.36
267271#elif SANITIZER_RISCV64
268272 int major;
269273 int minor;
......@@ -285,12 +289,26 @@ uptr ThreadDescriptorSize() {
285289#elif defined(__powerpc64__)
286290 val = 1776; // from glibc.ppc64le 2.20-8.fc21
287291#endif
292 return val;
293}
294
295uptr ThreadDescriptorSize() {
296 uptr val = atomic_load_relaxed(&thread_descriptor_size);
288297 if (val)
289 atomic_store_relaxed(&thread_descriptor_size, val);
298 return val;
299 // _thread_db_sizeof_pthread is a GLIBC_PRIVATE symbol that is exported in
300 // glibc 2.34 and later.
301 if (unsigned *psizeof = static_cast<unsigned *>(
302 dlsym(RTLD_DEFAULT, "_thread_db_sizeof_pthread")))
303 val = *psizeof;
304 if (!val)
305 val = ThreadDescriptorSizeFallback();
306 atomic_store_relaxed(&thread_descriptor_size, val);
290307 return val;
291308}
292309
293#if defined(__mips__) || defined(__powerpc64__) || SANITIZER_RISCV64
310#if defined(__mips__) || defined(__powerpc64__) || SANITIZER_RISCV64 || \
311 SANITIZER_LOONGARCH64
294312// TlsPreTcbSize includes size of struct pthread_descr and size of tcb
295313// head structure. It lies before the static tls blocks.
296314static uptr TlsPreTcbSize() {
......@@ -300,6 +318,8 @@ static uptr TlsPreTcbSize() {
300318 const uptr kTcbHead = 88; // sizeof (tcbhead_t)
301319#elif SANITIZER_RISCV64
302320 const uptr kTcbHead = 16; // sizeof (tcbhead_t)
321#elif SANITIZER_LOONGARCH64
322 const uptr kTcbHead = 16; // sizeof (tcbhead_t)
303323#endif
304324 const uptr kTlsAlign = 16;
305325 const uptr kTlsPreTcbSize =
......@@ -308,7 +328,6 @@ static uptr TlsPreTcbSize() {
308328}
309329#endif
310330
311#if !SANITIZER_GO
312331namespace {
313332struct TlsBlock {
314333 uptr begin, end, align;
......@@ -339,19 +358,43 @@ static uptr TlsGetOffset(uptr ti_module, uptr ti_offset) {
339358extern "C" void *__tls_get_addr(size_t *);
340359#endif
341360
361static size_t main_tls_modid;
362
342363static int CollectStaticTlsBlocks(struct dl_phdr_info *info, size_t size,
343364 void *data) {
344 if (!info->dlpi_tls_modid)
365 size_t tls_modid;
366#if SANITIZER_SOLARIS
367 // dlpi_tls_modid is only available since Solaris 11.4 SRU 10. Use
368 // dlinfo(RTLD_DI_LINKMAP) instead which works on all of Solaris 11.3,
369 // 11.4, and Illumos. The tlsmodid of the executable was changed to 1 in
370 // 11.4 to match other implementations.
371 if (size >= offsetof(dl_phdr_info_test, dlpi_tls_modid))
372 main_tls_modid = 1;
373 else
374 main_tls_modid = 0;
375 g_use_dlpi_tls_data = 0;
376 Rt_map *map;
377 dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &map);
378 tls_modid = map->rt_tlsmodid;
379#else
380 main_tls_modid = 1;
381 tls_modid = info->dlpi_tls_modid;
382#endif
383
384 if (tls_modid < main_tls_modid)
345385 return 0;
346 uptr begin = (uptr)info->dlpi_tls_data;
386 uptr begin;
387#if !SANITIZER_SOLARIS
388 begin = (uptr)info->dlpi_tls_data;
389#endif
347390 if (!g_use_dlpi_tls_data) {
348391 // Call __tls_get_addr as a fallback. This forces TLS allocation on glibc
349392 // and FreeBSD.
350393#ifdef __s390__
351394 begin = (uptr)__builtin_thread_pointer() +
352 TlsGetOffset(info->dlpi_tls_modid, 0);
395 TlsGetOffset(tls_modid, 0);
353396#else
354 size_t mod_and_off[2] = {info->dlpi_tls_modid, 0};
397 size_t mod_and_off[2] = {tls_modid, 0};
355398 begin = (uptr)__tls_get_addr(mod_and_off);
356399#endif
357400 }
......@@ -359,7 +402,7 @@ static int CollectStaticTlsBlocks(struct dl_phdr_info *info, size_t size,
359402 if (info->dlpi_phdr[i].p_type == PT_TLS) {
360403 static_cast<InternalMmapVector<TlsBlock> *>(data)->push_back(
361404 TlsBlock{begin, begin + info->dlpi_phdr[i].p_memsz,
362 info->dlpi_phdr[i].p_align, info->dlpi_tls_modid});
405 info->dlpi_phdr[i].p_align, tls_modid});
363406 break;
364407 }
365408 return 0;
......@@ -371,11 +414,11 @@ __attribute__((unused)) static void GetStaticTlsBoundary(uptr *addr, uptr *size,
371414 dl_iterate_phdr(CollectStaticTlsBlocks, &ranges);
372415 uptr len = ranges.size();
373416 Sort(ranges.begin(), len);
374 // Find the range with tls_modid=1. For glibc, because libc.so uses PT_TLS,
375 // this module is guaranteed to exist and is one of the initially loaded
376 // modules.
417 // Find the range with tls_modid == main_tls_modid. For glibc, because
418 // libc.so uses PT_TLS, this module is guaranteed to exist and is one of
419 // the initially loaded modules.
377420 uptr one = 0;
378 while (one != len && ranges[one].tls_modid != 1) ++one;
421 while (one != len && ranges[one].tls_modid != main_tls_modid) ++one;
379422 if (one == len) {
380423 // This may happen with musl if no module uses PT_TLS.
381424 *addr = 0;
......@@ -384,21 +427,20 @@ __attribute__((unused)) static void GetStaticTlsBoundary(uptr *addr, uptr *size,
384427 return;
385428 }
386429 // Find the maximum consecutive ranges. We consider two modules consecutive if
387 // the gap is smaller than the alignment. The dynamic loader places static TLS
388 // blocks this way not to waste space.
430 // the gap is smaller than the alignment of the latter range. The dynamic
431 // loader places static TLS blocks this way not to waste space.
389432 uptr l = one;
390433 *align = ranges[l].align;
391 while (l != 0 && ranges[l].begin < ranges[l - 1].end + ranges[l - 1].align)
434 while (l != 0 && ranges[l].begin < ranges[l - 1].end + ranges[l].align)
392435 *align = Max(*align, ranges[--l].align);
393436 uptr r = one + 1;
394 while (r != len && ranges[r].begin < ranges[r - 1].end + ranges[r - 1].align)
437 while (r != len && ranges[r].begin < ranges[r - 1].end + ranges[r].align)
395438 *align = Max(*align, ranges[r++].align);
396439 *addr = ranges[l].begin;
397440 *size = ranges[r - 1].end - ranges[l].begin;
398441}
399#endif // !SANITIZER_GO
400442#endif // (x86_64 || i386 || mips || ...) && (SANITIZER_FREEBSD ||
401 // SANITIZER_LINUX) && !SANITIZER_ANDROID
443 // SANITIZER_LINUX) && !SANITIZER_ANDROID && !SANITIZER_GO
402444
403445#if SANITIZER_NETBSD
404446static struct tls_tcb * ThreadSelfTlsTcb() {
......@@ -452,7 +494,11 @@ static void GetTls(uptr *addr, uptr *size) {
452494#elif SANITIZER_GLIBC && defined(__x86_64__)
453495 // For aarch64 and x86-64, use an O(1) approach which requires relatively
454496 // precise ThreadDescriptorSize. g_tls_size was initialized in InitTlsSize.
497# if SANITIZER_X32
498 asm("mov %%fs:8,%0" : "=r"(*addr));
499# else
455500 asm("mov %%fs:16,%0" : "=r"(*addr));
501# endif
456502 *size = g_tls_size;
457503 *addr -= *size;
458504 *addr += ThreadDescriptorSize();
......@@ -460,6 +506,15 @@ static void GetTls(uptr *addr, uptr *size) {
460506 *addr = reinterpret_cast<uptr>(__builtin_thread_pointer()) -
461507 ThreadDescriptorSize();
462508 *size = g_tls_size + ThreadDescriptorSize();
509#elif SANITIZER_GLIBC && defined(__loongarch__)
510# ifdef __clang__
511 *addr = reinterpret_cast<uptr>(__builtin_thread_pointer()) -
512 ThreadDescriptorSize();
513# else
514 asm("or %0,$tp,$zero" : "=r"(*addr));
515 *addr -= ThreadDescriptorSize();
516# endif
517 *size = g_tls_size + ThreadDescriptorSize();
463518#elif SANITIZER_GLIBC && defined(__powerpc64__)
464519 // Workaround for glibc<2.25(?). 2.27 is known to not need this.
465520 uptr tp;
......@@ -467,7 +522,7 @@ static void GetTls(uptr *addr, uptr *size) {
467522 const uptr pre_tcb_size = TlsPreTcbSize();
468523 *addr = tp - pre_tcb_size;
469524 *size = g_tls_size + pre_tcb_size;
470#elif SANITIZER_FREEBSD || SANITIZER_LINUX
525#elif SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_SOLARIS
471526 uptr align;
472527 GetStaticTlsBoundary(addr, size, &align);
473528#if defined(__x86_64__) || defined(__i386__) || defined(__s390__) || \
......@@ -528,10 +583,6 @@ static void GetTls(uptr *addr, uptr *size) {
528583 *addr = (uptr)tcb->tcb_dtv[1];
529584 }
530585 }
531#elif SANITIZER_SOLARIS
532 // FIXME
533 *addr = 0;
534 *size = 0;
535586#else
536587#error "Unknown OS"
537588#endif
......@@ -603,6 +654,34 @@ static int AddModuleSegments(const char *module_name, dl_phdr_info *info,
603654 bool writable = phdr->p_flags & PF_W;
604655 cur_module.addAddressRange(cur_beg, cur_end, executable,
605656 writable);
657 } else if (phdr->p_type == PT_NOTE) {
658# ifdef NT_GNU_BUILD_ID
659 uptr off = 0;
660 while (off + sizeof(ElfW(Nhdr)) < phdr->p_memsz) {
661 auto *nhdr = reinterpret_cast<const ElfW(Nhdr) *>(info->dlpi_addr +
662 phdr->p_vaddr + off);
663 constexpr auto kGnuNamesz = 4; // "GNU" with NUL-byte.
664 static_assert(kGnuNamesz % 4 == 0, "kGnuNameSize is aligned to 4.");
665 if (nhdr->n_type == NT_GNU_BUILD_ID && nhdr->n_namesz == kGnuNamesz) {
666 if (off + sizeof(ElfW(Nhdr)) + nhdr->n_namesz + nhdr->n_descsz >
667 phdr->p_memsz) {
668 // Something is very wrong, bail out instead of reading potentially
669 // arbitrary memory.
670 break;
671 }
672 const char *name =
673 reinterpret_cast<const char *>(nhdr) + sizeof(*nhdr);
674 if (internal_memcmp(name, "GNU", 3) == 0) {
675 const char *value = reinterpret_cast<const char *>(nhdr) +
676 sizeof(*nhdr) + kGnuNamesz;
677 cur_module.setUuid(value, nhdr->n_descsz);
678 break;
679 }
680 }
681 off += sizeof(*nhdr) + RoundUpTo(nhdr->n_namesz, 4) +
682 RoundUpTo(nhdr->n_descsz, 4);
683 }
684# endif
606685 }
607686 }
608687 modules->push_back(cur_module);
lib/tsan/sanitizer_common/sanitizer_linux_s390.cpp+10-4
......@@ -57,8 +57,10 @@ uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
5757
5858uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
5959 int *parent_tidptr, void *newtls, int *child_tidptr) {
60 if (!fn || !child_stack)
61 return -EINVAL;
60 if (!fn || !child_stack) {
61 errno = EINVAL;
62 return -1;
63 }
6264 CHECK_EQ(0, (uptr)child_stack % 16);
6365 // Minimum frame size.
6466#ifdef __s390x__
......@@ -71,9 +73,9 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
7173 // And pass parameters.
7274 ((unsigned long *)child_stack)[1] = (uptr)fn;
7375 ((unsigned long *)child_stack)[2] = (uptr)arg;
74 register long res __asm__("r2");
76 register uptr res __asm__("r2");
7577 register void *__cstack __asm__("r2") = child_stack;
76 register int __flags __asm__("r3") = flags;
78 register long __flags __asm__("r3") = flags;
7779 register int * __ptidptr __asm__("r4") = parent_tidptr;
7880 register int * __ctidptr __asm__("r5") = child_tidptr;
7981 register void * __newtls __asm__("r6") = newtls;
......@@ -113,6 +115,10 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
113115 "r"(__ctidptr),
114116 "r"(__newtls)
115117 : "memory", "cc");
118 if (res >= (uptr)-4095) {
119 errno = -res;
120 return -1;
121 }
116122 return res;
117123}
118124
lib/tsan/sanitizer_common/sanitizer_local_address_space_view.h+1-1
......@@ -17,7 +17,7 @@
1717// instantiated with the `LocalAddressSpaceView` type. This type is used to
1818// load any pointers in instance methods. This implementation is effectively
1919// a no-op. When an object is to be used in an out-of-process manner it is
20// instansiated with the `RemoteAddressSpaceView` type.
20// instantiated with the `RemoteAddressSpaceView` type.
2121//
2222// By making `AddressSpaceView` a template parameter of an object, it can
2323// change its implementation at compile time which has no run time overhead.
lib/tsan/sanitizer_common/sanitizer_lzw.h created+159
......@@ -0,0 +1,159 @@
1//===-- sanitizer_lzw.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// Lempel–Ziv–Welch encoding/decoding
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef SANITIZER_LZW_H
14#define SANITIZER_LZW_H
15
16#include "sanitizer_dense_map.h"
17
18namespace __sanitizer {
19
20using LzwCodeType = u32;
21
22template <class T, class ItIn, class ItOut>
23ItOut LzwEncode(ItIn begin, ItIn end, ItOut out) {
24 using Substring =
25 detail::DenseMapPair<LzwCodeType /* Prefix */, T /* Next input */>;
26
27 // Sentinel value for substrings of len 1.
28 static constexpr LzwCodeType kNoPrefix =
29 Min(DenseMapInfo<Substring>::getEmptyKey().first,
30 DenseMapInfo<Substring>::getTombstoneKey().first) -
31 1;
32 DenseMap<Substring, LzwCodeType> prefix_to_code;
33 {
34 // Add all substring of len 1 as initial dictionary.
35 InternalMmapVector<T> dict_len1;
36 for (auto it = begin; it != end; ++it)
37 if (prefix_to_code.try_emplace({kNoPrefix, *it}, 0).second)
38 dict_len1.push_back(*it);
39
40 // Slightly helps with later delta encoding.
41 Sort(dict_len1.data(), dict_len1.size());
42
43 // For large sizeof(T) we have to store dict_len1. Smaller types like u8 can
44 // just generate them.
45 *out = dict_len1.size();
46 ++out;
47
48 for (uptr i = 0; i != dict_len1.size(); ++i) {
49 // Remap after the Sort.
50 prefix_to_code[{kNoPrefix, dict_len1[i]}] = i;
51 *out = dict_len1[i];
52 ++out;
53 }
54 CHECK_EQ(prefix_to_code.size(), dict_len1.size());
55 }
56
57 if (begin == end)
58 return out;
59
60 // Main LZW encoding loop.
61 LzwCodeType match = prefix_to_code.find({kNoPrefix, *begin})->second;
62 ++begin;
63 for (auto it = begin; it != end; ++it) {
64 // Extend match with the new item.
65 auto ins = prefix_to_code.try_emplace({match, *it}, prefix_to_code.size());
66 if (ins.second) {
67 // This is a new substring, but emit the code for the current match
68 // (before extend). This allows LZW decoder to recover the dictionary.
69 *out = match;
70 ++out;
71 // Reset the match to a single item, which must be already in the map.
72 match = prefix_to_code.find({kNoPrefix, *it})->second;
73 } else {
74 // Already known, use as the current match.
75 match = ins.first->second;
76 }
77 }
78
79 *out = match;
80 ++out;
81
82 return out;
83}
84
85template <class T, class ItIn, class ItOut>
86ItOut LzwDecode(ItIn begin, ItIn end, ItOut out) {
87 if (begin == end)
88 return out;
89
90 // Load dictionary of len 1 substrings. Theses correspont to lowest codes.
91 InternalMmapVector<T> dict_len1(*begin);
92 ++begin;
93
94 if (begin == end)
95 return out;
96
97 for (auto& v : dict_len1) {
98 v = *begin;
99 ++begin;
100 }
101
102 // Substrings of len 2 and up. Indexes are shifted because [0,
103 // dict_len1.size()) stored in dict_len1. Substings get here after being
104 // emitted to the output, so we can use output position.
105 InternalMmapVector<detail::DenseMapPair<ItOut /* begin. */, ItOut /* end */>>
106 code_to_substr;
107
108 // Copies already emitted substrings into the output again.
109 auto copy = [&code_to_substr, &dict_len1](LzwCodeType code, ItOut out) {
110 if (code < dict_len1.size()) {
111 *out = dict_len1[code];
112 ++out;
113 return out;
114 }
115 const auto& s = code_to_substr[code - dict_len1.size()];
116
117 for (ItOut it = s.first; it != s.second; ++it, ++out) *out = *it;
118 return out;
119 };
120
121 // Returns lens of the substring with the given code.
122 auto code_to_len = [&code_to_substr, &dict_len1](LzwCodeType code) -> uptr {
123 if (code < dict_len1.size())
124 return 1;
125 const auto& s = code_to_substr[code - dict_len1.size()];
126 return s.second - s.first;
127 };
128
129 // Main LZW decoding loop.
130 LzwCodeType prev_code = *begin;
131 ++begin;
132 out = copy(prev_code, out);
133 for (auto it = begin; it != end; ++it) {
134 LzwCodeType code = *it;
135 auto start = out;
136 if (code == dict_len1.size() + code_to_substr.size()) {
137 // Special LZW case. The code is not in the dictionary yet. This is
138 // possible only when the new substring is the same as previous one plus
139 // the first item of the previous substring. We can emit that in two
140 // steps.
141 out = copy(prev_code, out);
142 *out = *start;
143 ++out;
144 } else {
145 out = copy(code, out);
146 }
147
148 // Every time encoded emits the code, it also creates substing of len + 1
149 // including the first item of the just emmited substring. Do the same here.
150 uptr len = code_to_len(prev_code);
151 code_to_substr.push_back({start - len, start + 1});
152
153 prev_code = code;
154 }
155 return out;
156}
157
158} // namespace __sanitizer
159#endif
lib/tsan/sanitizer_common/sanitizer_mac.cpp+229-210
......@@ -11,80 +11,82 @@
1111//===----------------------------------------------------------------------===//
1212
1313#include "sanitizer_platform.h"
14#if SANITIZER_MAC
15#include "sanitizer_mac.h"
16#include "interception/interception.h"
14#if SANITIZER_APPLE
15# include "interception/interception.h"
16# include "sanitizer_mac.h"
1717
1818// Use 64-bit inodes in file operations. ASan does not support OS X 10.5, so
1919// the clients will most certainly use 64-bit ones as well.
20#ifndef _DARWIN_USE_64_BIT_INODE
21#define _DARWIN_USE_64_BIT_INODE 1
22#endif
23#include <stdio.h>
24
25#include "sanitizer_common.h"
26#include "sanitizer_file.h"
27#include "sanitizer_flags.h"
28#include "sanitizer_internal_defs.h"
29#include "sanitizer_libc.h"
30#include "sanitizer_platform_limits_posix.h"
31#include "sanitizer_procmaps.h"
32#include "sanitizer_ptrauth.h"
33
34#if !SANITIZER_IOS
35#include <crt_externs.h> // for _NSGetEnviron
36#else
20# ifndef _DARWIN_USE_64_BIT_INODE
21# define _DARWIN_USE_64_BIT_INODE 1
22# endif
23# include <stdio.h>
24
25# include "sanitizer_common.h"
26# include "sanitizer_file.h"
27# include "sanitizer_flags.h"
28# include "sanitizer_interface_internal.h"
29# include "sanitizer_internal_defs.h"
30# include "sanitizer_libc.h"
31# include "sanitizer_platform_limits_posix.h"
32# include "sanitizer_procmaps.h"
33# include "sanitizer_ptrauth.h"
34
35# if !SANITIZER_IOS
36# include <crt_externs.h> // for _NSGetEnviron
37# else
3738extern char **environ;
38#endif
39# endif
3940
40#if defined(__has_include) && __has_include(<os/trace.h>)
41#define SANITIZER_OS_TRACE 1
42#include <os/trace.h>
43#else
44#define SANITIZER_OS_TRACE 0
45#endif
41# if defined(__has_include) && __has_include(<os/trace.h>)
42# define SANITIZER_OS_TRACE 1
43# include <os/trace.h>
44# else
45# define SANITIZER_OS_TRACE 0
46# endif
4647
4748// import new crash reporting api
48#if defined(__has_include) && __has_include(<CrashReporterClient.h>)
49#define HAVE_CRASHREPORTERCLIENT_H 1
50#include <CrashReporterClient.h>
51#else
52#define HAVE_CRASHREPORTERCLIENT_H 0
53#endif
54
55#if !SANITIZER_IOS
56#include <crt_externs.h> // for _NSGetArgv and _NSGetEnviron
57#else
49# if defined(__has_include) && __has_include(<CrashReporterClient.h>)
50# define HAVE_CRASHREPORTERCLIENT_H 1
51# include <CrashReporterClient.h>
52# else
53# define HAVE_CRASHREPORTERCLIENT_H 0
54# endif
55
56# if !SANITIZER_IOS
57# include <crt_externs.h> // for _NSGetArgv and _NSGetEnviron
58# else
5859extern "C" {
59 extern char ***_NSGetArgv(void);
60}
61#endif
62
63#include <asl.h>
64#include <dlfcn.h> // for dladdr()
65#include <errno.h>
66#include <fcntl.h>
67#include <libkern/OSAtomic.h>
68#include <mach-o/dyld.h>
69#include <mach/mach.h>
70#include <mach/mach_time.h>
71#include <mach/vm_statistics.h>
72#include <malloc/malloc.h>
73#include <os/log.h>
74#include <pthread.h>
75#include <sched.h>
76#include <signal.h>
77#include <spawn.h>
78#include <stdlib.h>
79#include <sys/ioctl.h>
80#include <sys/mman.h>
81#include <sys/resource.h>
82#include <sys/stat.h>
83#include <sys/sysctl.h>
84#include <sys/types.h>
85#include <sys/wait.h>
86#include <unistd.h>
87#include <util.h>
60extern char ***_NSGetArgv(void);
61}
62# endif
63
64# include <asl.h>
65# include <dlfcn.h> // for dladdr()
66# include <errno.h>
67# include <fcntl.h>
68# include <libkern/OSAtomic.h>
69# include <mach-o/dyld.h>
70# include <mach/mach.h>
71# include <mach/mach_time.h>
72# include <mach/vm_statistics.h>
73# include <malloc/malloc.h>
74# include <os/log.h>
75# include <pthread.h>
76# include <pthread/introspection.h>
77# include <sched.h>
78# include <signal.h>
79# include <spawn.h>
80# include <stdlib.h>
81# include <sys/ioctl.h>
82# include <sys/mman.h>
83# include <sys/resource.h>
84# include <sys/stat.h>
85# include <sys/sysctl.h>
86# include <sys/types.h>
87# include <sys/wait.h>
88# include <unistd.h>
89# include <util.h>
8890
8991// From <crt_externs.h>, but we don't have that file on iOS.
9092extern "C" {
......@@ -265,30 +267,32 @@ int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
265267
266268static fd_t internal_spawn_impl(const char *argv[], const char *envp[],
267269 pid_t *pid) {
268 fd_t master_fd = kInvalidFd;
269 fd_t slave_fd = kInvalidFd;
270 fd_t primary_fd = kInvalidFd;
271 fd_t secondary_fd = kInvalidFd;
270272
271273 auto fd_closer = at_scope_exit([&] {
272 internal_close(master_fd);
273 internal_close(slave_fd);
274 internal_close(primary_fd);
275 internal_close(secondary_fd);
274276 });
275277
276278 // We need a new pseudoterminal to avoid buffering problems. The 'atos' tool
277279 // in particular detects when it's talking to a pipe and forgets to flush the
278280 // output stream after sending a response.
279 master_fd = posix_openpt(O_RDWR);
280 if (master_fd == kInvalidFd) return kInvalidFd;
281 primary_fd = posix_openpt(O_RDWR);
282 if (primary_fd == kInvalidFd)
283 return kInvalidFd;
281284
282 int res = grantpt(master_fd) || unlockpt(master_fd);
285 int res = grantpt(primary_fd) || unlockpt(primary_fd);
283286 if (res != 0) return kInvalidFd;
284287
285288 // Use TIOCPTYGNAME instead of ptsname() to avoid threading problems.
286 char slave_pty_name[128];
287 res = ioctl(master_fd, TIOCPTYGNAME, slave_pty_name);
289 char secondary_pty_name[128];
290 res = ioctl(primary_fd, TIOCPTYGNAME, secondary_pty_name);
288291 if (res == -1) return kInvalidFd;
289292
290 slave_fd = internal_open(slave_pty_name, O_RDWR);
291 if (slave_fd == kInvalidFd) return kInvalidFd;
293 secondary_fd = internal_open(secondary_pty_name, O_RDWR);
294 if (secondary_fd == kInvalidFd)
295 return kInvalidFd;
292296
293297 // File descriptor actions
294298 posix_spawn_file_actions_t acts;
......@@ -299,9 +303,9 @@ static fd_t internal_spawn_impl(const char *argv[], const char *envp[],
299303 posix_spawn_file_actions_destroy(&acts);
300304 });
301305
302 res = posix_spawn_file_actions_adddup2(&acts, slave_fd, STDIN_FILENO) ||
303 posix_spawn_file_actions_adddup2(&acts, slave_fd, STDOUT_FILENO) ||
304 posix_spawn_file_actions_addclose(&acts, slave_fd);
306 res = posix_spawn_file_actions_adddup2(&acts, secondary_fd, STDIN_FILENO) ||
307 posix_spawn_file_actions_adddup2(&acts, secondary_fd, STDOUT_FILENO) ||
308 posix_spawn_file_actions_addclose(&acts, secondary_fd);
305309 if (res != 0) return kInvalidFd;
306310
307311 // Spawn attributes
......@@ -326,14 +330,14 @@ static fd_t internal_spawn_impl(const char *argv[], const char *envp[],
326330
327331 // Disable echo in the new terminal, disable CR.
328332 struct termios termflags;
329 tcgetattr(master_fd, &termflags);
333 tcgetattr(primary_fd, &termflags);
330334 termflags.c_oflag &= ~ONLCR;
331335 termflags.c_lflag &= ~ECHO;
332 tcsetattr(master_fd, TCSANOW, &termflags);
336 tcsetattr(primary_fd, TCSANOW, &termflags);
333337
334 // On success, do not close master_fd on scope exit.
335 fd_t fd = master_fd;
336 master_fd = kInvalidFd;
338 // On success, do not close primary_fd on scope exit.
339 fd_t fd = primary_fd;
340 primary_fd = kInvalidFd;
337341
338342 return fd;
339343}
......@@ -390,6 +394,13 @@ bool FileExists(const char *filename) {
390394 return S_ISREG(st.st_mode);
391395}
392396
397bool DirExists(const char *path) {
398 struct stat st;
399 if (stat(path, &st))
400 return false;
401 return S_ISDIR(st.st_mode);
402}
403
393404tid_t GetTid() {
394405 tid_t tid;
395406 pthread_threadid_np(nullptr, &tid);
......@@ -516,25 +527,6 @@ void FutexWait(atomic_uint32_t *p, u32 cmp) {
516527
517528void FutexWake(atomic_uint32_t *p, u32 count) {}
518529
519BlockingMutex::BlockingMutex() {
520 internal_memset(this, 0, sizeof(*this));
521}
522
523void BlockingMutex::Lock() {
524 CHECK(sizeof(OSSpinLock) <= sizeof(opaque_storage_));
525 CHECK_EQ(OS_SPINLOCK_INIT, 0);
526 CHECK_EQ(owner_, 0);
527 OSSpinLockLock((OSSpinLock*)&opaque_storage_);
528}
529
530void BlockingMutex::Unlock() {
531 OSSpinLockUnlock((OSSpinLock*)&opaque_storage_);
532}
533
534void BlockingMutex::CheckLocked() const {
535 CHECK_NE(*(const OSSpinLock*)&opaque_storage_, 0);
536}
537
538530u64 NanoTime() {
539531 timeval tv;
540532 internal_memset(&tv, 0, sizeof(tv));
......@@ -562,6 +554,9 @@ uptr TlsBaseAddr() {
562554 asm("movq %%gs:0,%0" : "=r"(segbase));
563555#elif defined(__i386__)
564556 asm("movl %%gs:0,%0" : "=r"(segbase));
557#elif defined(__aarch64__)
558 asm("mrs %x0, tpidrro_el0" : "=r"(segbase));
559 segbase &= 0x07ul; // clearing lower bits, cpu id stored there
565560#endif
566561 return segbase;
567562}
......@@ -784,8 +779,8 @@ void *internal_start_thread(void *(*func)(void *arg), void *arg) {
784779void internal_join_thread(void *th) { pthread_join((pthread_t)th, 0); }
785780
786781#if !SANITIZER_GO
787static BlockingMutex syslog_lock(LINKER_INITIALIZED);
788#endif
782static Mutex syslog_lock;
783# endif
789784
790785void WriteOneLineToSyslog(const char *s) {
791786#if !SANITIZER_GO
......@@ -800,7 +795,7 @@ void WriteOneLineToSyslog(const char *s) {
800795
801796// buffer to store crash report application information
802797static char crashreporter_info_buff[__sanitizer::kErrorMessageBufferSize] = {};
803static BlockingMutex crashreporter_info_mutex(LINKER_INITIALIZED);
798static Mutex crashreporter_info_mutex;
804799
805800extern "C" {
806801// Integrate with crash reporter libraries.
......@@ -830,7 +825,7 @@ asm(".desc ___crashreporter_info__, 0x10");
830825} // extern "C"
831826
832827static void CRAppendCrashLogMessage(const char *msg) {
833 BlockingMutexLock l(&crashreporter_info_mutex);
828 Lock l(&crashreporter_info_mutex);
834829 internal_strlcat(crashreporter_info_buff, msg,
835830 sizeof(crashreporter_info_buff));
836831#if HAVE_CRASHREPORTERCLIENT_H
......@@ -874,7 +869,7 @@ void LogFullErrorReport(const char *buffer) {
874869 // the reporting thread holds the thread registry mutex, and asl_log waits
875870 // for GCD to dispatch a new thread, the process will deadlock, because the
876871 // pthread_create wrapper needs to acquire the lock as well.
877 BlockingMutexLock l(&syslog_lock);
872 Lock l(&syslog_lock);
878873 if (common_flags()->log_to_syslog)
879874 WriteToSyslog(buffer);
880875
......@@ -885,9 +880,12 @@ void LogFullErrorReport(const char *buffer) {
885880SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
886881#if defined(__x86_64__) || defined(__i386__)
887882 ucontext_t *ucontext = static_cast<ucontext_t*>(context);
888 return ucontext->uc_mcontext->__es.__err & 2 /*T_PF_WRITE*/ ? WRITE : READ;
883 return ucontext->uc_mcontext->__es.__err & 2 /*T_PF_WRITE*/ ? Write : Read;
884#elif defined(__arm64__)
885 ucontext_t *ucontext = static_cast<ucontext_t*>(context);
886 return ucontext->uc_mcontext->__es.__esr & 0x40 /*ISS_DA_WNR*/ ? Write : Read;
889887#else
890 return UNKNOWN;
888 return Unknown;
891889#endif
892890}
893891
......@@ -902,18 +900,14 @@ bool SignalContext::IsTrueFaultingAddress() const {
902900 (uptr)ptrauth_strip( \
903901 (void *)arm_thread_state64_get_##r(ucontext->uc_mcontext->__ss), 0)
904902#else
905 #define AARCH64_GET_REG(r) ucontext->uc_mcontext->__ss.__##r
903 #define AARCH64_GET_REG(r) (uptr)ucontext->uc_mcontext->__ss.__##r
906904#endif
907905
908906static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
909907 ucontext_t *ucontext = (ucontext_t*)context;
910908# if defined(__aarch64__)
911909 *pc = AARCH64_GET_REG(pc);
912# if defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0
913910 *bp = AARCH64_GET_REG(fp);
914# else
915 *bp = AARCH64_GET_REG(lr);
916# endif
917911 *sp = AARCH64_GET_REG(sp);
918912# elif defined(__x86_64__)
919913 *pc = ucontext->uc_mcontext->__ss.__rip;
......@@ -950,6 +944,9 @@ static void DisableMmapExcGuardExceptions() {
950944 set_behavior(mach_task_self(), task_exc_guard_none);
951945}
952946
947static void VerifyInterceptorsWorking();
948static void StripEnv();
949
953950void InitializePlatformEarly() {
954951 // Only use xnu_fast_mmap when on x86_64 and the kernel supports it.
955952 use_xnu_fast_mmap =
......@@ -960,17 +957,54 @@ void InitializePlatformEarly() {
960957#endif
961958 if (GetDarwinKernelVersion() >= DarwinKernelVersion(19, 0))
962959 DisableMmapExcGuardExceptions();
960
961# if !SANITIZER_GO
962 MonotonicNanoTime(); // Call to initialize mach_timebase_info
963 VerifyInterceptorsWorking();
964 StripEnv();
965# endif
963966}
964967
965968#if !SANITIZER_GO
966969static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES";
967970LowLevelAllocator allocator_for_env;
968971
972static bool ShouldCheckInterceptors() {
973 // Restrict "interceptors working?" check to ASan and TSan.
974 const char *sanitizer_names[] = {"AddressSanitizer", "ThreadSanitizer"};
975 size_t count = sizeof(sanitizer_names) / sizeof(sanitizer_names[0]);
976 for (size_t i = 0; i < count; i++) {
977 if (internal_strcmp(sanitizer_names[i], SanitizerToolName) == 0)
978 return true;
979 }
980 return false;
981}
982
983static void VerifyInterceptorsWorking() {
984 if (!common_flags()->verify_interceptors || !ShouldCheckInterceptors())
985 return;
986
987 // Verify that interceptors really work. We'll use dlsym to locate
988 // "puts", if interceptors are working, it should really point to
989 // "wrap_puts" within our own dylib.
990 Dl_info info_puts, info_runtime;
991 RAW_CHECK(dladdr(dlsym(RTLD_DEFAULT, "puts"), &info_puts));
992 RAW_CHECK(dladdr((void *)&VerifyInterceptorsWorking, &info_runtime));
993 if (internal_strcmp(info_puts.dli_fname, info_runtime.dli_fname) != 0) {
994 Report(
995 "ERROR: Interceptors are not working. This may be because %s is "
996 "loaded too late (e.g. via dlopen). Please launch the executable "
997 "with:\n%s=%s\n",
998 SanitizerToolName, kDyldInsertLibraries, info_runtime.dli_fname);
999 RAW_CHECK("interceptors not installed" && 0);
1000 }
1001}
1002
9691003// Change the value of the env var |name|, leaking the original value.
9701004// If |name_value| is NULL, the variable is deleted from the environment,
9711005// otherwise the corresponding "NAME=value" string is replaced with
9721006// |name_value|.
973void LeakyResetEnv(const char *name, const char *name_value) {
1007static void LeakyResetEnv(const char *name, const char *name_value) {
9741008 char **env = GetEnviron();
9751009 uptr name_len = internal_strlen(name);
9761010 while (*env != 0) {
......@@ -995,100 +1029,28 @@ void LeakyResetEnv(const char *name, const char *name_value) {
9951029 }
9961030}
9971031
998SANITIZER_WEAK_CXX_DEFAULT_IMPL
999bool ReexecDisabled() {
1000 return false;
1001}
1002
1003static bool DyldNeedsEnvVariable() {
1004 // If running on OS X 10.11+ or iOS 9.0+, dyld will interpose even if
1005 // DYLD_INSERT_LIBRARIES is not set.
1006 return GetMacosAlignedVersion() < MacosVersion(10, 11);
1007}
1008
1009void MaybeReexec() {
1010 // FIXME: This should really live in some "InitializePlatform" method.
1011 MonotonicNanoTime();
1032static void StripEnv() {
1033 if (!common_flags()->strip_env)
1034 return;
10121035
1013 if (ReexecDisabled()) return;
1036 char *dyld_insert_libraries =
1037 const_cast<char *>(GetEnv(kDyldInsertLibraries));
1038 if (!dyld_insert_libraries)
1039 return;
10141040
1015 // Make sure the dynamic runtime library is preloaded so that the
1016 // wrappers work. If it is not, set DYLD_INSERT_LIBRARIES and re-exec
1017 // ourselves.
10181041 Dl_info info;
1019 RAW_CHECK(dladdr((void*)((uptr)&__sanitizer_report_error_summary), &info));
1020 char *dyld_insert_libraries =
1021 const_cast<char*>(GetEnv(kDyldInsertLibraries));
1022 uptr old_env_len = dyld_insert_libraries ?
1023 internal_strlen(dyld_insert_libraries) : 0;
1024 uptr fname_len = internal_strlen(info.dli_fname);
1042 RAW_CHECK(dladdr((void *)&StripEnv, &info));
10251043 const char *dylib_name = StripModuleName(info.dli_fname);
1026 uptr dylib_name_len = internal_strlen(dylib_name);
1027
1028 bool lib_is_in_env = dyld_insert_libraries &&
1029 internal_strstr(dyld_insert_libraries, dylib_name);
1030 if (DyldNeedsEnvVariable() && !lib_is_in_env) {
1031 // DYLD_INSERT_LIBRARIES is not set or does not contain the runtime
1032 // library.
1033 InternalMmapVector<char> program_name(1024);
1034 uint32_t buf_size = program_name.size();
1035 _NSGetExecutablePath(program_name.data(), &buf_size);
1036 char *new_env = const_cast<char*>(info.dli_fname);
1037 if (dyld_insert_libraries) {
1038 // Append the runtime dylib name to the existing value of
1039 // DYLD_INSERT_LIBRARIES.
1040 new_env = (char*)allocator_for_env.Allocate(old_env_len + fname_len + 2);
1041 internal_strncpy(new_env, dyld_insert_libraries, old_env_len);
1042 new_env[old_env_len] = ':';
1043 // Copy fname_len and add a trailing zero.
1044 internal_strncpy(new_env + old_env_len + 1, info.dli_fname,
1045 fname_len + 1);
1046 // Ok to use setenv() since the wrappers don't depend on the value of
1047 // asan_inited.
1048 setenv(kDyldInsertLibraries, new_env, /*overwrite*/1);
1049 } else {
1050 // Set DYLD_INSERT_LIBRARIES equal to the runtime dylib name.
1051 setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0);
1052 }
1053 VReport(1, "exec()-ing the program with\n");
1054 VReport(1, "%s=%s\n", kDyldInsertLibraries, new_env);
1055 VReport(1, "to enable wrappers.\n");
1056 execv(program_name.data(), *_NSGetArgv());
1057
1058 // We get here only if execv() failed.
1059 Report("ERROR: The process is launched without DYLD_INSERT_LIBRARIES, "
1060 "which is required for the sanitizer to work. We tried to set the "
1061 "environment variable and re-execute itself, but execv() failed, "
1062 "possibly because of sandbox restrictions. Make sure to launch the "
1063 "executable with:\n%s=%s\n", kDyldInsertLibraries, new_env);
1064 RAW_CHECK("execv failed" && 0);
1065 }
1066
1067 // Verify that interceptors really work. We'll use dlsym to locate
1068 // "pthread_create", if interceptors are working, it should really point to
1069 // "wrap_pthread_create" within our own dylib.
1070 Dl_info info_pthread_create;
1071 void *dlopen_addr = dlsym(RTLD_DEFAULT, "pthread_create");
1072 RAW_CHECK(dladdr(dlopen_addr, &info_pthread_create));
1073 if (internal_strcmp(info.dli_fname, info_pthread_create.dli_fname) != 0) {
1074 Report(
1075 "ERROR: Interceptors are not working. This may be because %s is "
1076 "loaded too late (e.g. via dlopen). Please launch the executable "
1077 "with:\n%s=%s\n",
1078 SanitizerToolName, kDyldInsertLibraries, info.dli_fname);
1079 RAW_CHECK("interceptors not installed" && 0);
1080 }
1081
1044 bool lib_is_in_env = internal_strstr(dyld_insert_libraries, dylib_name);
10821045 if (!lib_is_in_env)
10831046 return;
10841047
1085 if (!common_flags()->strip_env)
1086 return;
1087
10881048 // DYLD_INSERT_LIBRARIES is set and contains the runtime library. Let's remove
10891049 // the dylib from the environment variable, because interceptors are installed
10901050 // and we don't want our children to inherit the variable.
10911051
1052 uptr old_env_len = internal_strlen(dyld_insert_libraries);
1053 uptr dylib_name_len = internal_strlen(dylib_name);
10921054 uptr env_name_len = internal_strlen(kDyldInsertLibraries);
10931055 // Allocate memory to hold the previous env var name, its value, the '='
10941056 // sign and the '\0' char.
......@@ -1237,7 +1199,7 @@ uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
12371199
12381200 uptr largest_gap_found = 0;
12391201 uptr max_occupied_addr = 0;
1240 VReport(2, "FindDynamicShadowStart, space_size = %p\n", space_size);
1202 VReport(2, "FindDynamicShadowStart, space_size = %p\n", (void *)space_size);
12411203 uptr shadow_start =
12421204 FindAvailableMemoryRange(space_size, alignment, granularity,
12431205 &largest_gap_found, &max_occupied_addr);
......@@ -1246,20 +1208,21 @@ uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
12461208 VReport(
12471209 2,
12481210 "Shadow doesn't fit, largest_gap_found = %p, max_occupied_addr = %p\n",
1249 largest_gap_found, max_occupied_addr);
1211 (void *)largest_gap_found, (void *)max_occupied_addr);
12501212 uptr new_max_vm = RoundDownTo(largest_gap_found << shadow_scale, alignment);
12511213 if (new_max_vm < max_occupied_addr) {
12521214 Report("Unable to find a memory range for dynamic shadow.\n");
12531215 Report(
12541216 "space_size = %p, largest_gap_found = %p, max_occupied_addr = %p, "
12551217 "new_max_vm = %p\n",
1256 space_size, largest_gap_found, max_occupied_addr, new_max_vm);
1218 (void *)space_size, (void *)largest_gap_found,
1219 (void *)max_occupied_addr, (void *)new_max_vm);
12571220 CHECK(0 && "cannot place shadow");
12581221 }
12591222 RestrictMemoryToMaxAddress(new_max_vm);
12601223 high_mem_end = new_max_vm - 1;
12611224 space_size = (high_mem_end >> shadow_scale) + left_padding;
1262 VReport(2, "FindDynamicShadowStart, space_size = %p\n", space_size);
1225 VReport(2, "FindDynamicShadowStart, space_size = %p\n", (void *)space_size);
12631226 shadow_start = FindAvailableMemoryRange(space_size, alignment, granularity,
12641227 nullptr, nullptr);
12651228 if (shadow_start == 0) {
......@@ -1288,6 +1251,7 @@ uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
12881251 mach_vm_address_t start_address =
12891252 (SANITIZER_WORDSIZE == 32) ? 0x000000001000 : 0x000100000000;
12901253
1254 const mach_vm_address_t max_vm_address = GetMaxVirtualAddress() + 1;
12911255 mach_vm_address_t address = start_address;
12921256 mach_vm_address_t free_begin = start_address;
12931257 kern_return_t kr = KERN_SUCCESS;
......@@ -1302,7 +1266,7 @@ uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
13021266 (vm_region_info_t)&vminfo, &count);
13031267 if (kr == KERN_INVALID_ADDRESS) {
13041268 // No more regions beyond "address", consider the gap at the end of VM.
1305 address = GetMaxVirtualAddress() + 1;
1269 address = max_vm_address;
13061270 vmsize = 0;
13071271 } else {
13081272 if (max_occupied_addr) *max_occupied_addr = address + vmsize;
......@@ -1310,7 +1274,7 @@ uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
13101274 if (free_begin != address) {
13111275 // We found a free region [free_begin..address-1].
13121276 uptr gap_start = RoundUpTo((uptr)free_begin + left_padding, alignment);
1313 uptr gap_end = RoundDownTo((uptr)address, alignment);
1277 uptr gap_end = RoundDownTo((uptr)Min(address, max_vm_address), alignment);
13141278 uptr gap_size = gap_end > gap_start ? gap_end - gap_start : 0;
13151279 if (size < gap_size) {
13161280 return gap_start;
......@@ -1330,7 +1294,7 @@ uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
13301294}
13311295
13321296// FIXME implement on this platform.
1333void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) { }
1297void GetMemoryProfile(fill_profile_f cb, uptr *stats) {}
13341298
13351299void SignalContext::DumpAllRegisters(void *context) {
13361300 Report("Register values:\n");
......@@ -1339,7 +1303,7 @@ void SignalContext::DumpAllRegisters(void *context) {
13391303# define DUMPREG64(r) \
13401304 Printf("%s = 0x%016llx ", #r, ucontext->uc_mcontext->__ss.__ ## r);
13411305# define DUMPREGA64(r) \
1342 Printf(" %s = 0x%016llx ", #r, AARCH64_GET_REG(r));
1306 Printf(" %s = 0x%016lx ", #r, AARCH64_GET_REG(r));
13431307# define DUMPREG32(r) \
13441308 Printf("%s = 0x%08x ", #r, ucontext->uc_mcontext->__ss.__ ## r);
13451309# define DUMPREG_(r) Printf(" "); DUMPREG(r);
......@@ -1409,7 +1373,7 @@ void DumpProcessMap() {
14091373 char uuid_str[128];
14101374 FormatUUID(uuid_str, sizeof(uuid_str), modules[i].uuid());
14111375 Printf("0x%zx-0x%zx %s (%s) %s\n", modules[i].base_address(),
1412 modules[i].max_executable_address(), modules[i].full_name(),
1376 modules[i].max_address(), modules[i].full_name(),
14131377 ModuleArchToString(modules[i].arch()), uuid_str);
14141378 }
14151379 Printf("End of module map.\n");
......@@ -1433,6 +1397,61 @@ u32 GetNumberOfCPUs() {
14331397
14341398void InitializePlatformCommonFlags(CommonFlags *cf) {}
14351399
1400// Pthread introspection hook
1401//
1402// * GCD worker threads are created without a call to pthread_create(), but we
1403// still need to register these threads (with ThreadCreate/Start()).
1404// * We use the "pthread introspection hook" below to observe the creation of
1405// such threads.
1406// * GCD worker threads don't have parent threads and the CREATE event is
1407// delivered in the context of the thread itself. CREATE events for regular
1408// threads, are delivered on the parent. We use this to tell apart which
1409// threads are GCD workers with `thread == pthread_self()`.
1410//
1411static pthread_introspection_hook_t prev_pthread_introspection_hook;
1412static ThreadEventCallbacks thread_event_callbacks;
1413
1414static void sanitizer_pthread_introspection_hook(unsigned int event,
1415 pthread_t thread, void *addr,
1416 size_t size) {
1417 // create -> start -> terminate -> destroy
1418 // * create/destroy are usually (not guaranteed) delivered on the parent and
1419 // track resource allocation/reclamation
1420 // * start/terminate are guaranteed to be delivered in the context of the
1421 // thread and give hooks into "just after (before) thread starts (stops)
1422 // executing"
1423 DCHECK(event >= PTHREAD_INTROSPECTION_THREAD_CREATE &&
1424 event <= PTHREAD_INTROSPECTION_THREAD_DESTROY);
1425
1426 if (event == PTHREAD_INTROSPECTION_THREAD_CREATE) {
1427 bool gcd_worker = (thread == pthread_self());
1428 if (thread_event_callbacks.create)
1429 thread_event_callbacks.create((uptr)thread, gcd_worker);
1430 } else if (event == PTHREAD_INTROSPECTION_THREAD_START) {
1431 CHECK_EQ(thread, pthread_self());
1432 if (thread_event_callbacks.start)
1433 thread_event_callbacks.start((uptr)thread);
1434 }
1435
1436 if (prev_pthread_introspection_hook)
1437 prev_pthread_introspection_hook(event, thread, addr, size);
1438
1439 if (event == PTHREAD_INTROSPECTION_THREAD_TERMINATE) {
1440 CHECK_EQ(thread, pthread_self());
1441 if (thread_event_callbacks.terminate)
1442 thread_event_callbacks.terminate((uptr)thread);
1443 } else if (event == PTHREAD_INTROSPECTION_THREAD_DESTROY) {
1444 if (thread_event_callbacks.destroy)
1445 thread_event_callbacks.destroy((uptr)thread);
1446 }
1447}
1448
1449void InstallPthreadIntrospectionHook(const ThreadEventCallbacks &callbacks) {
1450 thread_event_callbacks = callbacks;
1451 prev_pthread_introspection_hook =
1452 pthread_introspection_hook_install(&sanitizer_pthread_introspection_hook);
1453}
1454
14361455} // namespace __sanitizer
14371456
1438#endif // SANITIZER_MAC
1457#endif // SANITIZER_APPLE
lib/tsan/sanitizer_common/sanitizer_mac.h+16-5
......@@ -9,12 +9,12 @@
99// This file is shared between various sanitizers' runtime libraries and
1010// provides definitions for OSX-specific functions.
1111//===----------------------------------------------------------------------===//
12#ifndef SANITIZER_MAC_H
13#define SANITIZER_MAC_H
12#ifndef SANITIZER_APPLE_H
13#define SANITIZER_APPLE_H
1414
1515#include "sanitizer_common.h"
1616#include "sanitizer_platform.h"
17#if SANITIZER_MAC
17#if SANITIZER_APPLE
1818#include "sanitizer_posix.h"
1919
2020namespace __sanitizer {
......@@ -62,7 +62,18 @@ char **GetEnviron();
6262
6363void RestrictMemoryToMaxAddress(uptr max_address);
6464
65using ThreadEventCallback = void (*)(uptr thread);
66using ThreadCreateEventCallback = void (*)(uptr thread, bool gcd_worker);
67struct ThreadEventCallbacks {
68 ThreadCreateEventCallback create;
69 ThreadEventCallback start;
70 ThreadEventCallback terminate;
71 ThreadEventCallback destroy;
72};
73
74void InstallPthreadIntrospectionHook(const ThreadEventCallbacks &callbacks);
75
6576} // namespace __sanitizer
6677
67#endif // SANITIZER_MAC
68#endif // SANITIZER_MAC_H
78#endif // SANITIZER_APPLE
79#endif // SANITIZER_APPLE_H
lib/tsan/sanitizer_common/sanitizer_mac_libcdep.cpp+2-2
......@@ -11,7 +11,7 @@
1111//===----------------------------------------------------------------------===//
1212
1313#include "sanitizer_platform.h"
14#if SANITIZER_MAC
14#if SANITIZER_APPLE
1515#include "sanitizer_mac.h"
1616
1717#include <sys/mman.h>
......@@ -26,4 +26,4 @@ void RestrictMemoryToMaxAddress(uptr max_address) {
2626
2727} // namespace __sanitizer
2828
29#endif // SANITIZER_MAC
29#endif // SANITIZER_APPLE
lib/tsan/sanitizer_common/sanitizer_mallinfo.h created+38
......@@ -0,0 +1,38 @@
1//===-- sanitizer_mallinfo.h ----------------------------------------------===//
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 Sanitizer common code.
10//
11// Definition for mallinfo on different platforms.
12//===----------------------------------------------------------------------===//
13
14#ifndef SANITIZER_MALLINFO_H
15#define SANITIZER_MALLINFO_H
16
17#include "sanitizer_internal_defs.h"
18#include "sanitizer_platform.h"
19
20namespace __sanitizer {
21
22#if SANITIZER_ANDROID
23
24struct __sanitizer_struct_mallinfo {
25 uptr v[10];
26};
27
28#elif SANITIZER_LINUX || SANITIZER_APPLE || SANITIZER_FUCHSIA
29
30struct __sanitizer_struct_mallinfo {
31 int v[10];
32};
33
34#endif
35
36} // namespace __sanitizer
37
38#endif // SANITIZER_MALLINFO_H
lib/tsan/sanitizer_common/sanitizer_malloc_mac.inc+10-12
......@@ -12,7 +12,7 @@
1212//===----------------------------------------------------------------------===//
1313
1414#include "sanitizer_common/sanitizer_platform.h"
15#if !SANITIZER_MAC
15#if !SANITIZER_APPLE
1616#error "This file should only be compiled on Darwin."
1717#endif
1818
......@@ -23,6 +23,7 @@
2323#include <sys/mman.h>
2424
2525#include "interception/interception.h"
26#include "sanitizer_common/sanitizer_allocator_dlsym.h"
2627#include "sanitizer_common/sanitizer_mac.h"
2728
2829// Similar code is used in Google Perftools,
......@@ -192,20 +193,15 @@ void *__sanitizer_mz_malloc(malloc_zone_t *zone, uptr size) {
192193 return p;
193194}
194195
196struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {
197 static bool UseImpl() { return !COMMON_MALLOC_SANITIZER_INITIALIZED; }
198};
199
195200extern "C"
196201SANITIZER_INTERFACE_ATTRIBUTE
197202void *__sanitizer_mz_calloc(malloc_zone_t *zone, size_t nmemb, size_t size) {
198 if (UNLIKELY(!COMMON_MALLOC_SANITIZER_INITIALIZED)) {
199 // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
200 const size_t kCallocPoolSize = 1024;
201 static uptr calloc_memory_for_dlsym[kCallocPoolSize];
202 static size_t allocated;
203 size_t size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize;
204 void *mem = (void*)&calloc_memory_for_dlsym[allocated];
205 allocated += size_in_words;
206 CHECK(allocated < kCallocPoolSize);
207 return mem;
208 }
203 if (DlsymAlloc::Use())
204 return DlsymAlloc::Callocate(nmemb, size);
209205 COMMON_MALLOC_CALLOC(nmemb, size);
210206 return p;
211207}
......@@ -223,6 +219,8 @@ extern "C"
223219SANITIZER_INTERFACE_ATTRIBUTE
224220void __sanitizer_mz_free(malloc_zone_t *zone, void *ptr) {
225221 if (!ptr) return;
222 if (DlsymAlloc::PointerIsMine(ptr))
223 return DlsymAlloc::Free(ptr);
226224 COMMON_MALLOC_FREE(ptr);
227225}
228226
lib/tsan/sanitizer_common/sanitizer_mutex.cpp+2-2
......@@ -73,7 +73,7 @@ void DebugMutexInit() {
7373 // Build adjacency matrix.
7474 bool leaf[kMutexTypeMax];
7575 internal_memset(&leaf, 0, sizeof(leaf));
76 int cnt[kMutexTypeMax] = {};
76 int cnt[kMutexTypeMax];
7777 internal_memset(&cnt, 0, sizeof(cnt));
7878 for (int t = 0; t < kMutexTypeMax; t++) {
7979 mutex_type_count = t;
......@@ -174,7 +174,7 @@ struct InternalDeadlockDetector {
174174 if (max_idx != MutexInvalid && !mutex_can_lock[max_idx][type]) {
175175 Printf("%s: internal deadlock: can't lock %s under %s mutex\n", SanitizerToolName,
176176 mutex_meta[type].name, mutex_meta[max_idx].name);
177 PrintMutexPC(pc);
177 PrintMutexPC(locked[max_idx].pc);
178178 CHECK(0);
179179 }
180180 locked[type].seq = ++sequence;
lib/tsan/sanitizer_common/sanitizer_mutex.h+120-161
......@@ -20,25 +20,27 @@
2020
2121namespace __sanitizer {
2222
23class MUTEX StaticSpinMutex {
23class SANITIZER_MUTEX StaticSpinMutex {
2424 public:
2525 void Init() {
2626 atomic_store(&state_, 0, memory_order_relaxed);
2727 }
2828
29 void Lock() ACQUIRE() {
29 void Lock() SANITIZER_ACQUIRE() {
3030 if (LIKELY(TryLock()))
3131 return;
3232 LockSlow();
3333 }
3434
35 bool TryLock() TRY_ACQUIRE(true) {
35 bool TryLock() SANITIZER_TRY_ACQUIRE(true) {
3636 return atomic_exchange(&state_, 1, memory_order_acquire) == 0;
3737 }
3838
39 void Unlock() RELEASE() { atomic_store(&state_, 0, memory_order_release); }
39 void Unlock() SANITIZER_RELEASE() {
40 atomic_store(&state_, 0, memory_order_release);
41 }
4042
41 void CheckLocked() const CHECK_LOCKED() {
43 void CheckLocked() const SANITIZER_CHECK_LOCKED() {
4244 CHECK_EQ(atomic_load(&state_, memory_order_relaxed), 1);
4345 }
4446
......@@ -48,7 +50,7 @@ class MUTEX StaticSpinMutex {
4850 void LockSlow();
4951};
5052
51class MUTEX SpinMutex : public StaticSpinMutex {
53class SANITIZER_MUTEX SpinMutex : public StaticSpinMutex {
5254 public:
5355 SpinMutex() {
5456 Init();
......@@ -95,7 +97,11 @@ enum {
9597
9698// Go linker does not support THREADLOCAL variables,
9799// so we can't use per-thread state.
98#define SANITIZER_CHECK_DEADLOCKS (SANITIZER_DEBUG && !SANITIZER_GO)
100// Disable checked locks on Darwin. Although Darwin platforms support
101// THREADLOCAL variables they are not usable early on during process init when
102// `__sanitizer::Mutex` is used.
103#define SANITIZER_CHECK_DEADLOCKS \
104 (SANITIZER_DEBUG && !SANITIZER_GO && SANITIZER_SUPPORTS_THREADLOCAL && !SANITIZER_APPLE)
99105
100106#if SANITIZER_CHECK_DEADLOCKS
101107struct MutexMeta {
......@@ -111,7 +117,7 @@ struct MutexMeta {
111117
112118class CheckedMutex {
113119 public:
114 constexpr CheckedMutex(MutexType type)
120 explicit constexpr CheckedMutex(MutexType type)
115121#if SANITIZER_CHECK_DEADLOCKS
116122 : type_(type)
117123#endif
......@@ -152,15 +158,15 @@ class CheckedMutex {
152158// Derive from CheckedMutex for the purposes of EBO.
153159// We could make it a field marked with [[no_unique_address]],
154160// but this attribute is not supported by some older compilers.
155class MUTEX Mutex : CheckedMutex {
161class SANITIZER_MUTEX Mutex : CheckedMutex {
156162 public:
157 constexpr Mutex(MutexType type = MutexUnchecked) : CheckedMutex(type) {}
163 explicit constexpr Mutex(MutexType type = MutexUnchecked)
164 : CheckedMutex(type) {}
158165
159 void Lock() ACQUIRE() {
166 void Lock() SANITIZER_ACQUIRE() {
160167 CheckedMutex::Lock();
161168 u64 reset_mask = ~0ull;
162169 u64 state = atomic_load_relaxed(&state_);
163 const uptr kMaxSpinIters = 1500;
164170 for (uptr spin_iters = 0;; spin_iters++) {
165171 u64 new_state;
166172 bool locked = (state & (kWriterLock | kReaderLockMask)) != 0;
......@@ -189,8 +195,6 @@ class MUTEX Mutex : CheckedMutex {
189195 // We've incremented waiting writers, so now block.
190196 writers_.Wait();
191197 spin_iters = 0;
192 state = atomic_load(&state_, memory_order_relaxed);
193 DCHECK_NE(state & kWriterSpinWait, 0);
194198 } else {
195199 // We've set kWriterSpinWait, but we are still in active spinning.
196200 }
......@@ -199,10 +203,26 @@ class MUTEX Mutex : CheckedMutex {
199203 // Either way we need to reset kWriterSpinWait
200204 // next time we take the lock or block again.
201205 reset_mask = ~kWriterSpinWait;
206 state = atomic_load(&state_, memory_order_relaxed);
207 DCHECK_NE(state & kWriterSpinWait, 0);
208 }
209 }
210
211 bool TryLock() SANITIZER_TRY_ACQUIRE(true) {
212 u64 state = atomic_load_relaxed(&state_);
213 for (;;) {
214 if (UNLIKELY(state & (kWriterLock | kReaderLockMask)))
215 return false;
216 // The mutex is not read-/write-locked, try to lock.
217 if (LIKELY(atomic_compare_exchange_weak(
218 &state_, &state, state | kWriterLock, memory_order_acquire))) {
219 CheckedMutex::Lock();
220 return true;
221 }
202222 }
203223 }
204224
205 void Unlock() RELEASE() {
225 void Unlock() SANITIZER_RELEASE() {
206226 CheckedMutex::Unlock();
207227 bool wake_writer;
208228 u64 wake_readers;
......@@ -212,17 +232,16 @@ class MUTEX Mutex : CheckedMutex {
212232 DCHECK_NE(state & kWriterLock, 0);
213233 DCHECK_EQ(state & kReaderLockMask, 0);
214234 new_state = state & ~kWriterLock;
215 wake_writer =
216 (state & kWriterSpinWait) == 0 && (state & kWaitingWriterMask) != 0;
235 wake_writer = (state & (kWriterSpinWait | kReaderSpinWait)) == 0 &&
236 (state & kWaitingWriterMask) != 0;
217237 if (wake_writer)
218238 new_state = (new_state - kWaitingWriterInc) | kWriterSpinWait;
219239 wake_readers =
220 (state & (kWriterSpinWait | kWaitingWriterMask)) != 0
240 wake_writer || (state & kWriterSpinWait) != 0
221241 ? 0
222242 : ((state & kWaitingReaderMask) >> kWaitingReaderShift);
223243 if (wake_readers)
224 new_state = (new_state & ~kWaitingReaderMask) +
225 (wake_readers << kReaderLockShift);
244 new_state = (new_state & ~kWaitingReaderMask) | kReaderSpinWait;
226245 } while (UNLIKELY(!atomic_compare_exchange_weak(&state_, &state, new_state,
227246 memory_order_release)));
228247 if (UNLIKELY(wake_writer))
......@@ -231,37 +250,54 @@ class MUTEX Mutex : CheckedMutex {
231250 readers_.Post(wake_readers);
232251 }
233252
234 void ReadLock() ACQUIRE_SHARED() {
253 void ReadLock() SANITIZER_ACQUIRE_SHARED() {
235254 CheckedMutex::Lock();
236 bool locked;
237 u64 new_state;
255 u64 reset_mask = ~0ull;
238256 u64 state = atomic_load_relaxed(&state_);
239 do {
240 locked =
241 (state & kReaderLockMask) == 0 &&
242 (state & (kWriterLock | kWriterSpinWait | kWaitingWriterMask)) != 0;
257 for (uptr spin_iters = 0;; spin_iters++) {
258 bool locked = (state & kWriterLock) != 0;
259 u64 new_state;
260 if (LIKELY(!locked)) {
261 new_state = (state + kReaderLockInc) & reset_mask;
262 } else if (spin_iters > kMaxSpinIters) {
263 new_state = (state + kWaitingReaderInc) & reset_mask;
264 } else if ((state & kReaderSpinWait) == 0) {
265 // Active spinning, but denote our presence so that unlocking
266 // thread does not wake up other threads.
267 new_state = state | kReaderSpinWait;
268 } else {
269 // Active spinning.
270 state = atomic_load(&state_, memory_order_relaxed);
271 continue;
272 }
273 if (UNLIKELY(!atomic_compare_exchange_weak(&state_, &state, new_state,
274 memory_order_acquire)))
275 continue;
243276 if (LIKELY(!locked))
244 new_state = state + kReaderLockInc;
245 else
246 new_state = state + kWaitingReaderInc;
247 } while (UNLIKELY(!atomic_compare_exchange_weak(&state_, &state, new_state,
248 memory_order_acquire)));
249 if (UNLIKELY(locked))
250 readers_.Wait();
251 DCHECK_EQ(atomic_load_relaxed(&state_) & kWriterLock, 0);
252 DCHECK_NE(atomic_load_relaxed(&state_) & kReaderLockMask, 0);
277 return; // We've locked the mutex.
278 if (spin_iters > kMaxSpinIters) {
279 // We've incremented waiting readers, so now block.
280 readers_.Wait();
281 spin_iters = 0;
282 } else {
283 // We've set kReaderSpinWait, but we are still in active spinning.
284 }
285 reset_mask = ~kReaderSpinWait;
286 state = atomic_load(&state_, memory_order_relaxed);
287 }
253288 }
254289
255 void ReadUnlock() RELEASE_SHARED() {
290 void ReadUnlock() SANITIZER_RELEASE_SHARED() {
256291 CheckedMutex::Unlock();
257292 bool wake;
258293 u64 new_state;
259294 u64 state = atomic_load_relaxed(&state_);
260295 do {
261296 DCHECK_NE(state & kReaderLockMask, 0);
262 DCHECK_EQ(state & (kWaitingReaderMask | kWriterLock), 0);
297 DCHECK_EQ(state & kWriterLock, 0);
263298 new_state = state - kReaderLockInc;
264 wake = (new_state & (kReaderLockMask | kWriterSpinWait)) == 0 &&
299 wake = (new_state &
300 (kReaderLockMask | kWriterSpinWait | kReaderSpinWait)) == 0 &&
265301 (new_state & kWaitingWriterMask) != 0;
266302 if (wake)
267303 new_state = (new_state - kWaitingWriterInc) | kWriterSpinWait;
......@@ -277,13 +313,13 @@ class MUTEX Mutex : CheckedMutex {
277313 // owns the mutex but a child checks that it is locked. Rather than
278314 // maintaining complex state to work around those situations, the check only
279315 // checks that the mutex is owned.
280 void CheckWriteLocked() const CHECK_LOCKED() {
316 void CheckWriteLocked() const SANITIZER_CHECK_LOCKED() {
281317 CHECK(atomic_load(&state_, memory_order_relaxed) & kWriterLock);
282318 }
283319
284 void CheckLocked() const CHECK_LOCKED() { CheckWriteLocked(); }
320 void CheckLocked() const SANITIZER_CHECK_LOCKED() { CheckWriteLocked(); }
285321
286 void CheckReadLocked() const CHECK_LOCKED() {
322 void CheckReadLocked() const SANITIZER_CHECK_LOCKED() {
287323 CHECK(atomic_load(&state_, memory_order_relaxed) & kReaderLockMask);
288324 }
289325
......@@ -305,16 +341,14 @@ class MUTEX Mutex : CheckedMutex {
305341 // - a writer is awake and spin-waiting
306342 // the flag is used to prevent thundering herd problem
307343 // (new writers are not woken if this flag is set)
344 // - a reader is awake and spin-waiting
308345 //
309 // Writer support active spinning, readers does not.
346 // Both writers and readers use active spinning before blocking.
310347 // But readers are more aggressive and always take the mutex
311348 // if there are any other readers.
312 // Writers hand off the mutex to readers: after wake up readers
313 // already assume ownership of the mutex (don't need to do any
314 // state updates). But the mutex is not handed off to writers,
315 // after wake up writers compete to lock the mutex again.
316 // This is needed to allow repeated write locks even in presence
317 // of other blocked writers.
349 // After wake up both writers and readers compete to lock the
350 // mutex again. This is needed to allow repeated locks even in presence
351 // of other blocked threads.
318352 static constexpr u64 kCounterWidth = 20;
319353 static constexpr u64 kReaderLockShift = 0;
320354 static constexpr u64 kReaderLockInc = 1ull << kReaderLockShift;
......@@ -330,7 +364,11 @@ class MUTEX Mutex : CheckedMutex {
330364 << kWaitingWriterShift;
331365 static constexpr u64 kWriterLock = 1ull << (3 * kCounterWidth);
332366 static constexpr u64 kWriterSpinWait = 1ull << (3 * kCounterWidth + 1);
367 static constexpr u64 kReaderSpinWait = 1ull << (3 * kCounterWidth + 2);
368
369 static constexpr uptr kMaxSpinIters = 1500;
333370
371 Mutex(LinkerInitialized) = delete;
334372 Mutex(const Mutex &) = delete;
335373 void operator=(const Mutex &) = delete;
336374};
......@@ -338,149 +376,70 @@ class MUTEX Mutex : CheckedMutex {
338376void FutexWait(atomic_uint32_t *p, u32 cmp);
339377void FutexWake(atomic_uint32_t *p, u32 count);
340378
341class MUTEX BlockingMutex {
342 public:
343 explicit constexpr BlockingMutex(LinkerInitialized)
344 : opaque_storage_ {0, }, owner_ {0} {}
345 BlockingMutex();
346 void Lock() ACQUIRE();
347 void Unlock() RELEASE();
348
349 // This function does not guarantee an explicit check that the calling thread
350 // is the thread which owns the mutex. This behavior, while more strictly
351 // correct, causes problems in cases like StopTheWorld, where a parent thread
352 // owns the mutex but a child checks that it is locked. Rather than
353 // maintaining complex state to work around those situations, the check only
354 // checks that the mutex is owned, and assumes callers to be generally
355 // well-behaved.
356 void CheckLocked() const CHECK_LOCKED();
357
358 private:
359 // Solaris mutex_t has a member that requires 64-bit alignment.
360 ALIGNED(8) uptr opaque_storage_[10];
361 uptr owner_; // for debugging
362};
363
364// Reader-writer spin mutex.
365class MUTEX RWMutex {
379template <typename MutexType>
380class SANITIZER_SCOPED_LOCK GenericScopedLock {
366381 public:
367 RWMutex() {
368 atomic_store(&state_, kUnlocked, memory_order_relaxed);
369 }
370
371 ~RWMutex() {
372 CHECK_EQ(atomic_load(&state_, memory_order_relaxed), kUnlocked);
373 }
374
375 void Lock() ACQUIRE() {
376 u32 cmp = kUnlocked;
377 if (atomic_compare_exchange_strong(&state_, &cmp, kWriteLock,
378 memory_order_acquire))
379 return;
380 LockSlow();
381 }
382
383 void Unlock() RELEASE() {
384 u32 prev = atomic_fetch_sub(&state_, kWriteLock, memory_order_release);
385 DCHECK_NE(prev & kWriteLock, 0);
386 (void)prev;
387 }
388
389 void ReadLock() ACQUIRE_SHARED() {
390 u32 prev = atomic_fetch_add(&state_, kReadLock, memory_order_acquire);
391 if ((prev & kWriteLock) == 0)
392 return;
393 ReadLockSlow();
394 }
395
396 void ReadUnlock() RELEASE_SHARED() {
397 u32 prev = atomic_fetch_sub(&state_, kReadLock, memory_order_release);
398 DCHECK_EQ(prev & kWriteLock, 0);
399 DCHECK_GT(prev & ~kWriteLock, 0);
400 (void)prev;
382 explicit GenericScopedLock(MutexType *mu) SANITIZER_ACQUIRE(mu) : mu_(mu) {
383 mu_->Lock();
401384 }
402385
403 void CheckLocked() const CHECK_LOCKED() {
404 CHECK_NE(atomic_load(&state_, memory_order_relaxed), kUnlocked);
405 }
386 ~GenericScopedLock() SANITIZER_RELEASE() { mu_->Unlock(); }
406387
407388 private:
408 atomic_uint32_t state_;
409
410 enum {
411 kUnlocked = 0,
412 kWriteLock = 1,
413 kReadLock = 2
414 };
415
416 void NOINLINE LockSlow() {
417 for (int i = 0;; i++) {
418 if (i < 10)
419 proc_yield(10);
420 else
421 internal_sched_yield();
422 u32 cmp = atomic_load(&state_, memory_order_relaxed);
423 if (cmp == kUnlocked &&
424 atomic_compare_exchange_weak(&state_, &cmp, kWriteLock,
425 memory_order_acquire))
426 return;
427 }
428 }
429
430 void NOINLINE ReadLockSlow() {
431 for (int i = 0;; i++) {
432 if (i < 10)
433 proc_yield(10);
434 else
435 internal_sched_yield();
436 u32 prev = atomic_load(&state_, memory_order_acquire);
437 if ((prev & kWriteLock) == 0)
438 return;
439 }
440 }
389 MutexType *mu_;
441390
442 RWMutex(const RWMutex &) = delete;
443 void operator=(const RWMutex &) = delete;
391 GenericScopedLock(const GenericScopedLock &) = delete;
392 void operator=(const GenericScopedLock &) = delete;
444393};
445394
446395template <typename MutexType>
447class SCOPED_LOCK GenericScopedLock {
396class SANITIZER_SCOPED_LOCK GenericScopedReadLock {
448397 public:
449 explicit GenericScopedLock(MutexType *mu) ACQUIRE(mu) : mu_(mu) {
450 mu_->Lock();
398 explicit GenericScopedReadLock(MutexType *mu) SANITIZER_ACQUIRE(mu)
399 : mu_(mu) {
400 mu_->ReadLock();
451401 }
452402
453 ~GenericScopedLock() RELEASE() { mu_->Unlock(); }
403 ~GenericScopedReadLock() SANITIZER_RELEASE() { mu_->ReadUnlock(); }
454404
455405 private:
456406 MutexType *mu_;
457407
458 GenericScopedLock(const GenericScopedLock &) = delete;
459 void operator=(const GenericScopedLock &) = delete;
408 GenericScopedReadLock(const GenericScopedReadLock &) = delete;
409 void operator=(const GenericScopedReadLock &) = delete;
460410};
461411
462412template <typename MutexType>
463class SCOPED_LOCK GenericScopedReadLock {
413class SANITIZER_SCOPED_LOCK GenericScopedRWLock {
464414 public:
465 explicit GenericScopedReadLock(MutexType *mu) ACQUIRE(mu) : mu_(mu) {
466 mu_->ReadLock();
415 ALWAYS_INLINE explicit GenericScopedRWLock(MutexType *mu, bool write)
416 SANITIZER_ACQUIRE(mu)
417 : mu_(mu), write_(write) {
418 if (write_)
419 mu_->Lock();
420 else
421 mu_->ReadLock();
467422 }
468423
469 ~GenericScopedReadLock() RELEASE() { mu_->ReadUnlock(); }
424 ALWAYS_INLINE ~GenericScopedRWLock() SANITIZER_RELEASE() {
425 if (write_)
426 mu_->Unlock();
427 else
428 mu_->ReadUnlock();
429 }
470430
471431 private:
472432 MutexType *mu_;
433 bool write_;
473434
474 GenericScopedReadLock(const GenericScopedReadLock &) = delete;
475 void operator=(const GenericScopedReadLock &) = delete;
435 GenericScopedRWLock(const GenericScopedRWLock &) = delete;
436 void operator=(const GenericScopedRWLock &) = delete;
476437};
477438
478439typedef GenericScopedLock<StaticSpinMutex> SpinMutexLock;
479typedef GenericScopedLock<BlockingMutex> BlockingMutexLock;
480typedef GenericScopedLock<RWMutex> RWMutexLock;
481typedef GenericScopedReadLock<RWMutex> RWMutexReadLock;
482440typedef GenericScopedLock<Mutex> Lock;
483441typedef GenericScopedReadLock<Mutex> ReadLock;
442typedef GenericScopedRWLock<Mutex> RWLock;
484443
485444} // namespace __sanitizer
486445
lib/tsan/sanitizer_common/sanitizer_openbsd.cpp deleted
lib/tsan/sanitizer_common/sanitizer_persistent_allocator.cpp deleted-18
......@@ -1,18 +0,0 @@
1//===-- sanitizer_persistent_allocator.cpp ----------------------*- 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 shared between AddressSanitizer and ThreadSanitizer
10// run-time libraries.
11//===----------------------------------------------------------------------===//
12#include "sanitizer_persistent_allocator.h"
13
14namespace __sanitizer {
15
16PersistentAllocator thePersistentAllocator;
17
18} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_persistent_allocator.h deleted-71
......@@ -1,71 +0,0 @@
1//===-- sanitizer_persistent_allocator.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// A fast memory allocator that does not support free() nor realloc().
10// All allocations are forever.
11//===----------------------------------------------------------------------===//
12
13#ifndef SANITIZER_PERSISTENT_ALLOCATOR_H
14#define SANITIZER_PERSISTENT_ALLOCATOR_H
15
16#include "sanitizer_internal_defs.h"
17#include "sanitizer_mutex.h"
18#include "sanitizer_atomic.h"
19#include "sanitizer_common.h"
20
21namespace __sanitizer {
22
23class PersistentAllocator {
24 public:
25 void *alloc(uptr size);
26
27 private:
28 void *tryAlloc(uptr size);
29 StaticSpinMutex mtx; // Protects alloc of new blocks for region allocator.
30 atomic_uintptr_t region_pos; // Region allocator for Node's.
31 atomic_uintptr_t region_end;
32};
33
34inline void *PersistentAllocator::tryAlloc(uptr size) {
35 // Optimisic lock-free allocation, essentially try to bump the region ptr.
36 for (;;) {
37 uptr cmp = atomic_load(&region_pos, memory_order_acquire);
38 uptr end = atomic_load(&region_end, memory_order_acquire);
39 if (cmp == 0 || cmp + size > end) return nullptr;
40 if (atomic_compare_exchange_weak(&region_pos, &cmp, cmp + size,
41 memory_order_acquire))
42 return (void *)cmp;
43 }
44}
45
46inline void *PersistentAllocator::alloc(uptr size) {
47 // First, try to allocate optimisitically.
48 void *s = tryAlloc(size);
49 if (s) return s;
50 // If failed, lock, retry and alloc new superblock.
51 SpinMutexLock l(&mtx);
52 for (;;) {
53 s = tryAlloc(size);
54 if (s) return s;
55 atomic_store(&region_pos, 0, memory_order_relaxed);
56 uptr allocsz = 64 * 1024;
57 if (allocsz < size) allocsz = size;
58 uptr mem = (uptr)MmapOrDie(allocsz, "stack depot");
59 atomic_store(&region_end, mem + allocsz, memory_order_release);
60 atomic_store(&region_pos, mem, memory_order_release);
61 }
62}
63
64extern PersistentAllocator thePersistentAllocator;
65inline void *PersistentAlloc(uptr sz) {
66 return thePersistentAllocator.alloc(sz);
67}
68
69} // namespace __sanitizer
70
71#endif // SANITIZER_PERSISTENT_ALLOCATOR_H
lib/tsan/sanitizer_common/sanitizer_platform.h+234-166
......@@ -22,103 +22,123 @@
2222// function declarations into a .S file which doesn't compile.
2323// https://crbug.com/1162741
2424#if __has_include(<features.h>) && !defined(__ANDROID__)
25#include <features.h>
25# include <features.h>
2626#endif
2727
2828#if defined(__linux__)
29# define SANITIZER_LINUX 1
29# define SANITIZER_LINUX 1
3030#else
31# define SANITIZER_LINUX 0
31# define SANITIZER_LINUX 0
3232#endif
3333
3434#if defined(__GLIBC__)
35# define SANITIZER_GLIBC 1
35# define SANITIZER_GLIBC 1
3636#else
37# define SANITIZER_GLIBC 0
37# define SANITIZER_GLIBC 0
3838#endif
3939
4040#if defined(__FreeBSD__)
41# define SANITIZER_FREEBSD 1
41# define SANITIZER_FREEBSD 1
4242#else
43# define SANITIZER_FREEBSD 0
43# define SANITIZER_FREEBSD 0
4444#endif
4545
4646#if defined(__NetBSD__)
47# define SANITIZER_NETBSD 1
47# define SANITIZER_NETBSD 1
4848#else
49# define SANITIZER_NETBSD 0
49# define SANITIZER_NETBSD 0
5050#endif
5151
5252#if defined(__sun__) && defined(__svr4__)
53# define SANITIZER_SOLARIS 1
53# define SANITIZER_SOLARIS 1
5454#else
55# define SANITIZER_SOLARIS 0
55# define SANITIZER_SOLARIS 0
5656#endif
5757
58// - SANITIZER_APPLE: all Apple code
59// - TARGET_OS_OSX: macOS
60// - SANITIZER_IOS: devices (iOS and iOS-like)
61// - SANITIZER_WATCHOS
62// - SANITIZER_TVOS
63// - SANITIZER_IOSSIM: simulators (iOS and iOS-like)
64// - SANITIZER_DRIVERKIT
5865#if defined(__APPLE__)
59# define SANITIZER_MAC 1
60# include <TargetConditionals.h>
61# if TARGET_OS_OSX
62# define SANITIZER_OSX 1
63# else
64# define SANITIZER_OSX 0
65# endif
66# if TARGET_OS_IPHONE
67# define SANITIZER_IOS 1
68# else
69# define SANITIZER_IOS 0
70# endif
71# if TARGET_OS_SIMULATOR
72# define SANITIZER_IOSSIM 1
73# else
74# define SANITIZER_IOSSIM 0
75# endif
76#else
77# define SANITIZER_MAC 0
78# define SANITIZER_IOS 0
79# define SANITIZER_IOSSIM 0
80# define SANITIZER_OSX 0
81#endif
82
83#if defined(__APPLE__) && TARGET_OS_IPHONE && TARGET_OS_WATCH
84# define SANITIZER_WATCHOS 1
85#else
86# define SANITIZER_WATCHOS 0
87#endif
88
89#if defined(__APPLE__) && TARGET_OS_IPHONE && TARGET_OS_TV
90# define SANITIZER_TVOS 1
66# define SANITIZER_APPLE 1
67# include <TargetConditionals.h>
68# if TARGET_OS_OSX
69# define SANITIZER_OSX 1
70# else
71# define SANITIZER_OSX 0
72# endif
73# if TARGET_OS_IPHONE
74# define SANITIZER_IOS 1
75# else
76# define SANITIZER_IOS 0
77# endif
78# if TARGET_OS_WATCH
79# define SANITIZER_WATCHOS 1
80# else
81# define SANITIZER_WATCHOS 0
82# endif
83# if TARGET_OS_TV
84# define SANITIZER_TVOS 1
85# else
86# define SANITIZER_TVOS 0
87# endif
88# if TARGET_OS_SIMULATOR
89# define SANITIZER_IOSSIM 1
90# else
91# define SANITIZER_IOSSIM 0
92# endif
93# if defined(TARGET_OS_DRIVERKIT) && TARGET_OS_DRIVERKIT
94# define SANITIZER_DRIVERKIT 1
95# else
96# define SANITIZER_DRIVERKIT 0
97# endif
9198#else
92# define SANITIZER_TVOS 0
99# define SANITIZER_APPLE 0
100# define SANITIZER_OSX 0
101# define SANITIZER_IOS 0
102# define SANITIZER_WATCHOS 0
103# define SANITIZER_TVOS 0
104# define SANITIZER_IOSSIM 0
105# define SANITIZER_DRIVERKIT 0
93106#endif
94107
95108#if defined(_WIN32)
96# define SANITIZER_WINDOWS 1
109# define SANITIZER_WINDOWS 1
97110#else
98# define SANITIZER_WINDOWS 0
111# define SANITIZER_WINDOWS 0
99112#endif
100113
101114#if defined(_WIN64)
102# define SANITIZER_WINDOWS64 1
115# define SANITIZER_WINDOWS64 1
103116#else
104# define SANITIZER_WINDOWS64 0
117# define SANITIZER_WINDOWS64 0
105118#endif
106119
107120#if defined(__ANDROID__)
108# define SANITIZER_ANDROID 1
121# define SANITIZER_ANDROID 1
109122#else
110# define SANITIZER_ANDROID 0
123# define SANITIZER_ANDROID 0
111124#endif
112125
113126#if defined(__Fuchsia__)
114# define SANITIZER_FUCHSIA 1
127# define SANITIZER_FUCHSIA 1
115128#else
116# define SANITIZER_FUCHSIA 0
129# define SANITIZER_FUCHSIA 0
117130#endif
118131
119#define SANITIZER_POSIX \
120 (SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_MAC || \
121 SANITIZER_NETBSD || SANITIZER_SOLARIS)
132// Assume linux that is not glibc or android is musl libc.
133#if SANITIZER_LINUX && !SANITIZER_GLIBC && !SANITIZER_ANDROID
134# define SANITIZER_MUSL 1
135#else
136# define SANITIZER_MUSL 0
137#endif
138
139#define SANITIZER_POSIX \
140 (SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_APPLE || \
141 SANITIZER_NETBSD || SANITIZER_SOLARIS)
122142
123143#if __LP64__ || defined(_WIN64)
124144# define SANITIZER_WORDSIZE 64
......@@ -127,58 +147,79 @@
127147#endif
128148
129149#if SANITIZER_WORDSIZE == 64
130# define FIRST_32_SECOND_64(a, b) (b)
150# define FIRST_32_SECOND_64(a, b) (b)
131151#else
132# define FIRST_32_SECOND_64(a, b) (a)
152# define FIRST_32_SECOND_64(a, b) (a)
133153#endif
134154
135155#if defined(__x86_64__) && !defined(_LP64)
136# define SANITIZER_X32 1
156# define SANITIZER_X32 1
137157#else
138# define SANITIZER_X32 0
158# define SANITIZER_X32 0
159#endif
160
161#if defined(__x86_64__) || defined(_M_X64)
162# define SANITIZER_X64 1
163#else
164# define SANITIZER_X64 0
139165#endif
140166
141167#if defined(__i386__) || defined(_M_IX86)
142# define SANITIZER_I386 1
168# define SANITIZER_I386 1
143169#else
144# define SANITIZER_I386 0
170# define SANITIZER_I386 0
145171#endif
146172
147173#if defined(__mips__)
148# define SANITIZER_MIPS 1
149# if defined(__mips64)
174# define SANITIZER_MIPS 1
175# if defined(__mips64) && _MIPS_SIM == _ABI64
176# define SANITIZER_MIPS32 0
177# define SANITIZER_MIPS64 1
178# else
179# define SANITIZER_MIPS32 1
180# define SANITIZER_MIPS64 0
181# endif
182#else
183# define SANITIZER_MIPS 0
150184# define SANITIZER_MIPS32 0
151# define SANITIZER_MIPS64 1
152# else
153# define SANITIZER_MIPS32 1
154185# define SANITIZER_MIPS64 0
155# endif
156#else
157# define SANITIZER_MIPS 0
158# define SANITIZER_MIPS32 0
159# define SANITIZER_MIPS64 0
160186#endif
161187
162188#if defined(__s390__)
163# define SANITIZER_S390 1
164# if defined(__s390x__)
189# define SANITIZER_S390 1
190# if defined(__s390x__)
191# define SANITIZER_S390_31 0
192# define SANITIZER_S390_64 1
193# else
194# define SANITIZER_S390_31 1
195# define SANITIZER_S390_64 0
196# endif
197#else
198# define SANITIZER_S390 0
165199# define SANITIZER_S390_31 0
166# define SANITIZER_S390_64 1
167# else
168# define SANITIZER_S390_31 1
169200# define SANITIZER_S390_64 0
170# endif
201#endif
202
203#if defined(__sparc__)
204# define SANITIZER_SPARC 1
205# if defined(__arch64__)
206# define SANITIZER_SPARC32 0
207# define SANITIZER_SPARC64 1
208# else
209# define SANITIZER_SPARC32 1
210# define SANITIZER_SPARC64 0
211# endif
171212#else
172# define SANITIZER_S390 0
173# define SANITIZER_S390_31 0
174# define SANITIZER_S390_64 0
213# define SANITIZER_SPARC 0
214# define SANITIZER_SPARC32 0
215# define SANITIZER_SPARC64 0
175216#endif
176217
177218#if defined(__powerpc__)
178# define SANITIZER_PPC 1
179# if defined(__powerpc64__)
180# define SANITIZER_PPC32 0
181# define SANITIZER_PPC64 1
219# define SANITIZER_PPC 1
220# if defined(__powerpc64__)
221# define SANITIZER_PPC32 0
222# define SANITIZER_PPC64 1
182223// 64-bit PPC has two ABIs (v1 and v2). The old powerpc64 target is
183224// big-endian, and uses v1 ABI (known for its function descriptors),
184225// while the new powerpc64le target is little-endian and uses v2.
......@@ -186,106 +227,109 @@
186227// (eg. big-endian v2), but you won't find such combinations in the wild
187228// (it'd require bootstrapping a whole system, which would be quite painful
188229// - there's no target triple for that). LLVM doesn't support them either.
189# if _CALL_ELF == 2
190# define SANITIZER_PPC64V1 0
191# define SANITIZER_PPC64V2 1
230# if _CALL_ELF == 2
231# define SANITIZER_PPC64V1 0
232# define SANITIZER_PPC64V2 1
233# else
234# define SANITIZER_PPC64V1 1
235# define SANITIZER_PPC64V2 0
236# endif
192237# else
193# define SANITIZER_PPC64V1 1
194# define SANITIZER_PPC64V2 0
238# define SANITIZER_PPC32 1
239# define SANITIZER_PPC64 0
240# define SANITIZER_PPC64V1 0
241# define SANITIZER_PPC64V2 0
195242# endif
196# else
197# define SANITIZER_PPC32 1
243#else
244# define SANITIZER_PPC 0
245# define SANITIZER_PPC32 0
198246# define SANITIZER_PPC64 0
199247# define SANITIZER_PPC64V1 0
200248# define SANITIZER_PPC64V2 0
201# endif
249#endif
250
251#if defined(__arm__) || defined(_M_ARM)
252# define SANITIZER_ARM 1
202253#else
203# define SANITIZER_PPC 0
204# define SANITIZER_PPC32 0
205# define SANITIZER_PPC64 0
206# define SANITIZER_PPC64V1 0
207# define SANITIZER_PPC64V2 0
254# define SANITIZER_ARM 0
208255#endif
209256
210#if defined(__arm__)
211# define SANITIZER_ARM 1
257#if defined(__aarch64__) || defined(_M_ARM64)
258# define SANITIZER_ARM64 1
212259#else
213# define SANITIZER_ARM 0
260# define SANITIZER_ARM64 0
214261#endif
215262
216263#if SANITIZER_SOLARIS && SANITIZER_WORDSIZE == 32
217# define SANITIZER_SOLARIS32 1
264# define SANITIZER_SOLARIS32 1
218265#else
219# define SANITIZER_SOLARIS32 0
266# define SANITIZER_SOLARIS32 0
220267#endif
221268
222269#if defined(__riscv) && (__riscv_xlen == 64)
223#define SANITIZER_RISCV64 1
270# define SANITIZER_RISCV64 1
224271#else
225#define SANITIZER_RISCV64 0
272# define SANITIZER_RISCV64 0
273#endif
274
275#if defined(__loongarch_lp64)
276# define SANITIZER_LOONGARCH64 1
277#else
278# define SANITIZER_LOONGARCH64 0
226279#endif
227280
228281// By default we allow to use SizeClassAllocator64 on 64-bit platform.
229// But in some cases (e.g. AArch64's 39-bit address space) SizeClassAllocator64
230// does not work well and we need to fallback to SizeClassAllocator32.
282// But in some cases SizeClassAllocator64 does not work well and we need to
283// fallback to SizeClassAllocator32.
231284// For such platforms build this code with -DSANITIZER_CAN_USE_ALLOCATOR64=0 or
232285// change the definition of SANITIZER_CAN_USE_ALLOCATOR64 here.
233286#ifndef SANITIZER_CAN_USE_ALLOCATOR64
234# if (SANITIZER_ANDROID && defined(__aarch64__)) || SANITIZER_FUCHSIA
235# define SANITIZER_CAN_USE_ALLOCATOR64 1
236# elif defined(__mips64) || defined(__aarch64__)
237# define SANITIZER_CAN_USE_ALLOCATOR64 0
238# else
239# define SANITIZER_CAN_USE_ALLOCATOR64 (SANITIZER_WORDSIZE == 64)
240# endif
287# if SANITIZER_RISCV64 || SANITIZER_IOS
288# define SANITIZER_CAN_USE_ALLOCATOR64 0
289# elif defined(__mips64) || defined(__hexagon__)
290# define SANITIZER_CAN_USE_ALLOCATOR64 0
291# else
292# define SANITIZER_CAN_USE_ALLOCATOR64 (SANITIZER_WORDSIZE == 64)
293# endif
241294#endif
242295
243296// The range of addresses which can be returned my mmap.
244297// FIXME: this value should be different on different platforms. Larger values
245298// will still work but will consume more memory for TwoLevelByteMap.
246299#if defined(__mips__)
247#if SANITIZER_GO && defined(__mips64)
248#define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 47)
249#else
250# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 40)
251#endif
300# if SANITIZER_GO && defined(__mips64)
301# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 47)
302# else
303# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 40)
304# endif
252305#elif SANITIZER_RISCV64
253#define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 38)
306# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 38)
254307#elif defined(__aarch64__)
255# if SANITIZER_MAC
256# if SANITIZER_OSX || SANITIZER_IOSSIM
257# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 47)
308# if SANITIZER_APPLE
309# if SANITIZER_OSX || SANITIZER_IOSSIM
310# define SANITIZER_MMAP_RANGE_SIZE \
311 FIRST_32_SECOND_64(1ULL << 32, 1ULL << 47)
312# else
313// Darwin iOS/ARM64 has a 36-bit VMA, 64GiB VM
314# define SANITIZER_MMAP_RANGE_SIZE \
315 FIRST_32_SECOND_64(1ULL << 32, 1ULL << 36)
316# endif
258317# else
259 // Darwin iOS/ARM64 has a 36-bit VMA, 64GiB VM
260# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 36)
318# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 48)
261319# endif
262# else
263# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 48)
264# endif
265320#elif defined(__sparc__)
266#define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 52)
321# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 52)
267322#else
268# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 47)
323# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 47)
269324#endif
270325
271326// Whether the addresses are sign-extended from the VMA range to the word.
272327// The SPARC64 Linux port implements this to split the VMA space into two
273328// non-contiguous halves with a huge hole in the middle.
274329#if defined(__sparc__) && SANITIZER_WORDSIZE == 64
275#define SANITIZER_SIGN_EXTENDED_ADDRESSES 1
330# define SANITIZER_SIGN_EXTENDED_ADDRESSES 1
276331#else
277#define SANITIZER_SIGN_EXTENDED_ADDRESSES 0
278#endif
279
280// The AArch64 and RISC-V linux ports use the canonical syscall set as
281// mandated by the upstream linux community for all new ports. Other ports
282// may still use legacy syscalls.
283#ifndef SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
284# if (defined(__aarch64__) || defined(__riscv)) && SANITIZER_LINUX
285# define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 1
286# else
287# define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 0
288# endif
332# define SANITIZER_SIGN_EXTENDED_ADDRESSES 0
289333#endif
290334
291335// udi16 syscalls can only be used when the following conditions are
......@@ -296,15 +340,15 @@
296340// Since we don't want to include libc headers here, we check the
297341// target only.
298342#if defined(__arm__) || SANITIZER_X32 || defined(__sparc__)
299#define SANITIZER_USES_UID16_SYSCALLS 1
343# define SANITIZER_USES_UID16_SYSCALLS 1
300344#else
301#define SANITIZER_USES_UID16_SYSCALLS 0
345# define SANITIZER_USES_UID16_SYSCALLS 0
302346#endif
303347
304348#if defined(__mips__)
305# define SANITIZER_POINTER_FORMAT_LENGTH FIRST_32_SECOND_64(8, 10)
349# define SANITIZER_POINTER_FORMAT_LENGTH FIRST_32_SECOND_64(8, 10)
306350#else
307# define SANITIZER_POINTER_FORMAT_LENGTH FIRST_32_SECOND_64(8, 12)
351# define SANITIZER_POINTER_FORMAT_LENGTH FIRST_32_SECOND_64(8, 12)
308352#endif
309353
310354/// \macro MSC_PREREQ
......@@ -313,15 +357,15 @@
313357/// * 1800: Microsoft Visual Studio 2013 / 12.0
314358/// * 1900: Microsoft Visual Studio 2015 / 14.0
315359#ifdef _MSC_VER
316# define MSC_PREREQ(version) (_MSC_VER >= (version))
360# define MSC_PREREQ(version) (_MSC_VER >= (version))
317361#else
318# define MSC_PREREQ(version) 0
362# define MSC_PREREQ(version) 0
319363#endif
320364
321#if SANITIZER_MAC && !(defined(__arm64__) && SANITIZER_IOS)
322# define SANITIZER_NON_UNIQUE_TYPEINFO 0
365#if SANITIZER_APPLE && defined(__x86_64__)
366# define SANITIZER_NON_UNIQUE_TYPEINFO 0
323367#else
324# define SANITIZER_NON_UNIQUE_TYPEINFO 1
368# define SANITIZER_NON_UNIQUE_TYPEINFO 1
325369#endif
326370
327371// On linux, some architectures had an ABI transition from 64-bit long double
......@@ -329,11 +373,11 @@
329373// involving long doubles come in two versions, and we need to pass the
330374// correct one to dlvsym when intercepting them.
331375#if SANITIZER_LINUX && (SANITIZER_S390 || SANITIZER_PPC32 || SANITIZER_PPC64V1)
332#define SANITIZER_NLDBL_VERSION "GLIBC_2.4"
376# define SANITIZER_NLDBL_VERSION "GLIBC_2.4"
333377#endif
334378
335379#if SANITIZER_GO == 0
336# define SANITIZER_GO 0
380# define SANITIZER_GO 0
337381#endif
338382
339383// On PowerPC and ARM Thumb, calling pthread_exit() causes LSan to detect leaks.
......@@ -341,40 +385,64 @@
341385// dlopen mallocs "libgcc_s.so" string which confuses LSan, it fails to realize
342386// that this allocation happens in dynamic linker and should be ignored.
343387#if SANITIZER_PPC || defined(__thumb__)
344# define SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT 1
388# define SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT 1
345389#else
346# define SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT 0
390# define SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT 0
347391#endif
348392
349#if SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_NETBSD || \
350 SANITIZER_SOLARIS
351# define SANITIZER_MADVISE_DONTNEED MADV_FREE
393#if SANITIZER_FREEBSD || SANITIZER_APPLE || SANITIZER_NETBSD || SANITIZER_SOLARIS
394# define SANITIZER_MADVISE_DONTNEED MADV_FREE
352395#else
353# define SANITIZER_MADVISE_DONTNEED MADV_DONTNEED
396# define SANITIZER_MADVISE_DONTNEED MADV_DONTNEED
354397#endif
355398
356399// Older gcc have issues aligning to a constexpr, and require an integer.
357400// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56859 among others.
358401#if defined(__powerpc__) || defined(__powerpc64__)
359# define SANITIZER_CACHE_LINE_SIZE 128
402# define SANITIZER_CACHE_LINE_SIZE 128
360403#else
361# define SANITIZER_CACHE_LINE_SIZE 64
404# define SANITIZER_CACHE_LINE_SIZE 64
362405#endif
363406
364407// Enable offline markup symbolizer for Fuchsia.
365408#if SANITIZER_FUCHSIA
366409# define SANITIZER_SYMBOLIZER_MARKUP 1
367410#else
368#define SANITIZER_SYMBOLIZER_MARKUP 0
411# define SANITIZER_SYMBOLIZER_MARKUP 0
369412#endif
370413
371414// Enable ability to support sanitizer initialization that is
372415// compatible with the sanitizer library being loaded via
373416// `dlopen()`.
374#if SANITIZER_MAC
375#define SANITIZER_SUPPORTS_INIT_FOR_DLOPEN 1
417#if SANITIZER_APPLE
418# define SANITIZER_SUPPORTS_INIT_FOR_DLOPEN 1
419#else
420# define SANITIZER_SUPPORTS_INIT_FOR_DLOPEN 0
421#endif
422
423// SANITIZER_SUPPORTS_THREADLOCAL
424// 1 - THREADLOCAL macro is supported by target
425// 0 - THREADLOCAL macro is not supported by target
426#ifndef __has_feature
427// TODO: Support other compilers here
428# define SANITIZER_SUPPORTS_THREADLOCAL 1
429#else
430# if __has_feature(tls)
431# define SANITIZER_SUPPORTS_THREADLOCAL 1
432# else
433# define SANITIZER_SUPPORTS_THREADLOCAL 0
434# endif
435#endif
436
437#if defined(__thumb__) && defined(__linux__)
438// Workaround for
439// https://lab.llvm.org/buildbot/#/builders/clang-thumbv7-full-2stage
440// or
441// https://lab.llvm.org/staging/#/builders/clang-thumbv7-full-2stage
442// It fails *rss_limit_mb_test* without meaningful errors.
443# define SANITIZER_START_BACKGROUND_THREAD_IN_ASAN_INTERNAL 1
376444#else
377#define SANITIZER_SUPPORTS_INIT_FOR_DLOPEN 0
445# define SANITIZER_START_BACKGROUND_THREAD_IN_ASAN_INTERNAL 0
378446#endif
379447
380#endif // SANITIZER_PLATFORM_H
448#endif // SANITIZER_PLATFORM_H
lib/tsan/sanitizer_common/sanitizer_platform_interceptors.h+53-34
......@@ -76,7 +76,7 @@
7676#define SI_LINUX 0
7777#endif
7878
79#if SANITIZER_MAC
79#if SANITIZER_APPLE
8080#define SI_MAC 1
8181#define SI_NOT_MAC 0
8282#else
......@@ -126,7 +126,7 @@
126126#define SI_SOLARIS32 0
127127#endif
128128
129#if SANITIZER_POSIX && !SANITIZER_MAC
129#if SANITIZER_POSIX && !SANITIZER_APPLE
130130#define SI_POSIX_NOT_MAC 1
131131#else
132132#define SI_POSIX_NOT_MAC 0
......@@ -229,11 +229,15 @@
229229 (SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
230230#define SANITIZER_INTERCEPT_CLOCK_GETTIME \
231231 (SI_FREEBSD || SI_NETBSD || SI_LINUX || SI_SOLARIS)
232#define SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID SI_LINUX
232#define SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID \
233 (SI_LINUX || SI_FREEBSD || SI_NETBSD)
233234#define SANITIZER_INTERCEPT_GETITIMER SI_POSIX
234235#define SANITIZER_INTERCEPT_TIME SI_POSIX
235236#define SANITIZER_INTERCEPT_GLOB (SI_GLIBC || SI_SOLARIS)
236237#define SANITIZER_INTERCEPT_GLOB64 SI_GLIBC
238#define SANITIZER_INTERCEPT___B64_TO SI_LINUX_NOT_ANDROID
239#define SANITIZER_INTERCEPT_DN_COMP_EXPAND SI_LINUX_NOT_ANDROID
240#define SANITIZER_INTERCEPT_POSIX_SPAWN SI_POSIX
237241#define SANITIZER_INTERCEPT_WAIT SI_POSIX
238242#define SANITIZER_INTERCEPT_INET SI_POSIX
239243#define SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM SI_POSIX
......@@ -251,7 +255,8 @@
251255#define SANITIZER_INTERCEPT_GETHOSTENT_R (SI_FREEBSD || SI_GLIBC || SI_SOLARIS)
252256#define SANITIZER_INTERCEPT_GETSOCKOPT SI_POSIX
253257#define SANITIZER_INTERCEPT_ACCEPT SI_POSIX
254#define SANITIZER_INTERCEPT_ACCEPT4 (SI_LINUX_NOT_ANDROID || SI_NETBSD)
258#define SANITIZER_INTERCEPT_ACCEPT4 \
259 (SI_LINUX_NOT_ANDROID || SI_NETBSD || SI_FREEBSD)
255260#define SANITIZER_INTERCEPT_PACCEPT SI_NETBSD
256261#define SANITIZER_INTERCEPT_MODF SI_POSIX
257262#define SANITIZER_INTERCEPT_RECVMSG SI_POSIX
......@@ -264,11 +269,11 @@
264269#define SANITIZER_INTERCEPT_INET_ATON SI_POSIX
265270#define SANITIZER_INTERCEPT_SYSINFO SI_LINUX
266271#define SANITIZER_INTERCEPT_READDIR SI_POSIX
267#define SANITIZER_INTERCEPT_READDIR64 SI_LINUX_NOT_ANDROID || SI_SOLARIS32
272#define SANITIZER_INTERCEPT_READDIR64 SI_GLIBC || SI_SOLARIS32
268273#if SI_LINUX_NOT_ANDROID && \
269274 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
270275 defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \
271 defined(__s390__) || SANITIZER_RISCV64)
276 defined(__s390__) || defined(__loongarch__) || SANITIZER_RISCV64)
272277#define SANITIZER_INTERCEPT_PTRACE 1
273278#else
274279#define SANITIZER_INTERCEPT_PTRACE 0
......@@ -303,13 +308,13 @@
303308#define SANITIZER_INTERCEPT_XPG_STRERROR_R SI_LINUX_NOT_ANDROID
304309#define SANITIZER_INTERCEPT_SCANDIR \
305310 (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
306#define SANITIZER_INTERCEPT_SCANDIR64 SI_LINUX_NOT_ANDROID || SI_SOLARIS32
311#define SANITIZER_INTERCEPT_SCANDIR64 SI_GLIBC || SI_SOLARIS32
307312#define SANITIZER_INTERCEPT_GETGROUPS SI_POSIX
308313#define SANITIZER_INTERCEPT_POLL SI_POSIX
309314#define SANITIZER_INTERCEPT_PPOLL SI_LINUX_NOT_ANDROID || SI_SOLARIS
310315#define SANITIZER_INTERCEPT_WORDEXP \
311316 (SI_FREEBSD || SI_NETBSD || (SI_MAC && !SI_IOS) || SI_LINUX_NOT_ANDROID || \
312 SI_SOLARIS) // NOLINT
317 SI_SOLARIS)
313318#define SANITIZER_INTERCEPT_SIGWAIT SI_POSIX
314319#define SANITIZER_INTERCEPT_SIGWAITINFO SI_LINUX_NOT_ANDROID || SI_SOLARIS
315320#define SANITIZER_INTERCEPT_SIGTIMEDWAIT SI_LINUX_NOT_ANDROID || SI_SOLARIS
......@@ -325,11 +330,10 @@
325330#define SANITIZER_INTERCEPT_GETMNTENT_R SI_LINUX_NOT_ANDROID
326331#define SANITIZER_INTERCEPT_STATFS \
327332 (SI_FREEBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
328#define SANITIZER_INTERCEPT_STATFS64 \
329 (((SI_MAC && !TARGET_CPU_ARM64) && !SI_IOS) || SI_LINUX_NOT_ANDROID)
333#define SANITIZER_INTERCEPT_STATFS64 SI_GLIBC && SANITIZER_HAS_STATFS64
330334#define SANITIZER_INTERCEPT_STATVFS \
331335 (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID)
332#define SANITIZER_INTERCEPT_STATVFS64 SI_LINUX_NOT_ANDROID
336#define SANITIZER_INTERCEPT_STATVFS64 SI_GLIBC
333337#define SANITIZER_INTERCEPT_INITGROUPS SI_POSIX
334338#define SANITIZER_INTERCEPT_ETHER_NTOA_ATON SI_POSIX
335339#define SANITIZER_INTERCEPT_ETHER_HOST \
......@@ -337,12 +341,14 @@
337341#define SANITIZER_INTERCEPT_ETHER_R (SI_FREEBSD || SI_LINUX_NOT_ANDROID)
338342#define SANITIZER_INTERCEPT_SHMCTL \
339343 (((SI_FREEBSD || SI_LINUX_NOT_ANDROID) && SANITIZER_WORDSIZE == 64) || \
340 SI_NETBSD || SI_SOLARIS) // NOLINT
344 SI_NETBSD || SI_SOLARIS)
341345#define SANITIZER_INTERCEPT_RANDOM_R SI_GLIBC
342346#define SANITIZER_INTERCEPT_PTHREAD_ATTR_GET SI_POSIX
343347#define SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSCHED \
344348 (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
345349#define SANITIZER_INTERCEPT_PTHREAD_ATTR_GETAFFINITY_NP SI_GLIBC
350#define SANITIZER_INTERCEPT_PTHREAD_GETAFFINITY_NP \
351 (SI_LINUX_NOT_ANDROID || SI_FREEBSD)
346352#define SANITIZER_INTERCEPT_PTHREAD_ATTR_GET_SCHED SI_POSIX
347353#define SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPSHARED \
348354 (SI_POSIX && !SI_NETBSD)
......@@ -362,6 +368,8 @@
362368 (SI_LINUX_NOT_ANDROID || SI_SOLARIS)
363369#define SANITIZER_INTERCEPT_PTHREAD_BARRIERATTR_GETPSHARED \
364370 (SI_LINUX_NOT_ANDROID && !SI_NETBSD)
371#define SANITIZER_INTERCEPT_TRYJOIN SI_GLIBC
372#define SANITIZER_INTERCEPT_TIMEDJOIN SI_GLIBC
365373#define SANITIZER_INTERCEPT_THR_EXIT SI_FREEBSD
366374#define SANITIZER_INTERCEPT_TMPNAM SI_POSIX
367375#define SANITIZER_INTERCEPT_TMPNAM_R (SI_GLIBC || SI_SOLARIS)
......@@ -391,8 +399,6 @@
391399#define SANITIZER_INTERCEPT__EXIT \
392400 (SI_LINUX || SI_FREEBSD || SI_NETBSD || SI_MAC || SI_SOLARIS)
393401
394#define SANITIZER_INTERCEPT_PTHREAD_MUTEX SI_POSIX
395#define SANITIZER_INTERCEPT___PTHREAD_MUTEX SI_GLIBC
396402#define SANITIZER_INTERCEPT___LIBC_MUTEX SI_NETBSD
397403#define SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP \
398404 (SI_FREEBSD || SI_NETBSD || SI_GLIBC || SI_SOLARIS)
......@@ -400,7 +406,7 @@
400406 (SI_FREEBSD || SI_NETBSD || SI_GLIBC || SI_SOLARIS)
401407
402408#define SANITIZER_INTERCEPT_TLS_GET_ADDR \
403 (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
409 (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID)
404410
405411#define SANITIZER_INTERCEPT_LISTXATTR SI_LINUX
406412#define SANITIZER_INTERCEPT_GETXATTR SI_LINUX
......@@ -445,7 +451,8 @@
445451#define SANITIZER_INTERCEPT_SEM \
446452 (SI_LINUX || SI_FREEBSD || SI_NETBSD || SI_SOLARIS)
447453#define SANITIZER_INTERCEPT_PTHREAD_SETCANCEL SI_POSIX
448#define SANITIZER_INTERCEPT_MINCORE (SI_LINUX || SI_NETBSD || SI_SOLARIS)
454#define SANITIZER_INTERCEPT_MINCORE \
455 (SI_LINUX || SI_NETBSD || SI_FREEBSD || SI_SOLARIS)
449456#define SANITIZER_INTERCEPT_PROCESS_VM_READV SI_LINUX
450457#define SANITIZER_INTERCEPT_CTERMID \
451458 (SI_LINUX || SI_MAC || SI_FREEBSD || SI_NETBSD || SI_SOLARIS)
......@@ -457,13 +464,17 @@
457464#define SANITIZER_INTERCEPT_SEND_SENDTO SI_POSIX
458465#define SANITIZER_INTERCEPT_EVENTFD_READ_WRITE SI_LINUX
459466
460#define SANITIZER_INTERCEPT_STAT \
461 (SI_FREEBSD || SI_MAC || SI_ANDROID || SI_NETBSD || SI_SOLARIS)
462#define SANITIZER_INTERCEPT_LSTAT (SI_NETBSD || SI_FREEBSD)
463#define SANITIZER_INTERCEPT___XSTAT (!SANITIZER_INTERCEPT_STAT && SI_POSIX)
464#define SANITIZER_INTERCEPT___XSTAT64 SI_LINUX_NOT_ANDROID
467#define SI_STAT_LINUX (SI_LINUX && __GLIBC_PREREQ(2, 33))
468#define SANITIZER_INTERCEPT_STAT \
469 (SI_FREEBSD || SI_MAC || SI_ANDROID || SI_NETBSD || SI_SOLARIS || \
470 SI_STAT_LINUX)
471#define SANITIZER_INTERCEPT_STAT64 SI_STAT_LINUX && SANITIZER_HAS_STAT64
472#define SANITIZER_INTERCEPT_LSTAT (SI_NETBSD || SI_FREEBSD || SI_STAT_LINUX)
473#define SANITIZER_INTERCEPT___XSTAT \
474 ((!SANITIZER_INTERCEPT_STAT && SI_POSIX) || SI_STAT_LINUX)
475#define SANITIZER_INTERCEPT___XSTAT64 SI_GLIBC
465476#define SANITIZER_INTERCEPT___LXSTAT SANITIZER_INTERCEPT___XSTAT
466#define SANITIZER_INTERCEPT___LXSTAT64 SI_LINUX_NOT_ANDROID
477#define SANITIZER_INTERCEPT___LXSTAT64 SI_GLIBC
467478
468479#define SANITIZER_INTERCEPT_UTMP \
469480 (SI_POSIX && !SI_MAC && !SI_FREEBSD && !SI_NETBSD)
......@@ -474,7 +485,7 @@
474485 (SI_LINUX_NOT_ANDROID || SI_MAC || SI_FREEBSD || SI_NETBSD)
475486
476487#define SANITIZER_INTERCEPT_MMAP SI_POSIX
477#define SANITIZER_INTERCEPT_MMAP64 SI_LINUX_NOT_ANDROID
488#define SANITIZER_INTERCEPT_MMAP64 SI_GLIBC || SI_SOLARIS
478489#define SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO (SI_GLIBC || SI_ANDROID)
479490#define SANITIZER_INTERCEPT_MEMALIGN (!SI_FREEBSD && !SI_MAC && !SI_NETBSD)
480491#define SANITIZER_INTERCEPT___LIBC_MEMALIGN SI_GLIBC
......@@ -484,6 +495,7 @@
484495#define SANITIZER_INTERCEPT_ALIGNED_ALLOC (!SI_MAC)
485496#define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE (!SI_MAC && !SI_NETBSD)
486497#define SANITIZER_INTERCEPT_MCHECK_MPROBE SI_LINUX_NOT_ANDROID
498#define SANITIZER_INTERCEPT_WCSLEN 1
487499#define SANITIZER_INTERCEPT_WCSCAT SI_POSIX
488500#define SANITIZER_INTERCEPT_WCSDUP SI_POSIX
489501#define SANITIZER_INTERCEPT_SIGNAL_AND_SIGACTION (!SI_WINDOWS && SI_NOT_FUCHSIA)
......@@ -496,7 +508,8 @@
496508#define SANITIZER_INTERCEPT_GID_FROM_GROUP SI_NETBSD
497509#define SANITIZER_INTERCEPT_ACCESS (SI_NETBSD || SI_FREEBSD)
498510#define SANITIZER_INTERCEPT_FACCESSAT (SI_NETBSD || SI_FREEBSD)
499#define SANITIZER_INTERCEPT_GETGROUPLIST SI_NETBSD
511#define SANITIZER_INTERCEPT_GETGROUPLIST \
512 (SI_NETBSD || SI_FREEBSD || SI_LINUX)
500513#define SANITIZER_INTERCEPT_STRLCPY \
501514 (SI_NETBSD || SI_FREEBSD || SI_MAC || SI_ANDROID)
502515
......@@ -517,10 +530,11 @@
517530#define SANITIZER_INTERCEPT_DEVNAME_R (SI_NETBSD || SI_FREEBSD)
518531#define SANITIZER_INTERCEPT_FGETLN (SI_NETBSD || SI_FREEBSD)
519532#define SANITIZER_INTERCEPT_STRMODE (SI_NETBSD || SI_FREEBSD)
520#define SANITIZER_INTERCEPT_TTYENT SI_NETBSD
521#define SANITIZER_INTERCEPT_PROTOENT (SI_NETBSD || SI_LINUX)
533#define SANITIZER_INTERCEPT_TTYENT (SI_NETBSD || SI_FREEBSD)
534#define SANITIZER_INTERCEPT_TTYENTPATH SI_NETBSD
535#define SANITIZER_INTERCEPT_PROTOENT (SI_LINUX || SI_NETBSD || SI_FREEBSD)
522536#define SANITIZER_INTERCEPT_PROTOENT_R SI_GLIBC
523#define SANITIZER_INTERCEPT_NETENT SI_NETBSD
537#define SANITIZER_INTERCEPT_NETENT (SI_LINUX || SI_NETBSD || SI_FREEBSD)
524538#define SANITIZER_INTERCEPT_SETVBUF \
525539 (SI_NETBSD || SI_FREEBSD || SI_LINUX || SI_MAC)
526540#define SANITIZER_INTERCEPT_GETMNTINFO (SI_NETBSD || SI_FREEBSD || SI_MAC)
......@@ -536,17 +550,17 @@
536550#define SANITIZER_INTERCEPT_MODCTL SI_NETBSD
537551#define SANITIZER_INTERCEPT_CAPSICUM SI_FREEBSD
538552#define SANITIZER_INTERCEPT_STRTONUM (SI_NETBSD || SI_FREEBSD)
539#define SANITIZER_INTERCEPT_FPARSELN SI_NETBSD
553#define SANITIZER_INTERCEPT_FPARSELN (SI_NETBSD || SI_FREEBSD)
540554#define SANITIZER_INTERCEPT_STATVFS1 SI_NETBSD
541555#define SANITIZER_INTERCEPT_STRTOI SI_NETBSD
542556#define SANITIZER_INTERCEPT_CAPSICUM SI_FREEBSD
543557#define SANITIZER_INTERCEPT_SHA1 SI_NETBSD
544558#define SANITIZER_INTERCEPT_MD4 SI_NETBSD
545559#define SANITIZER_INTERCEPT_RMD160 SI_NETBSD
546#define SANITIZER_INTERCEPT_MD5 SI_NETBSD
560#define SANITIZER_INTERCEPT_MD5 (SI_NETBSD || SI_FREEBSD)
547561#define SANITIZER_INTERCEPT_FSEEK (SI_NETBSD || SI_FREEBSD)
548562#define SANITIZER_INTERCEPT_MD2 SI_NETBSD
549#define SANITIZER_INTERCEPT_SHA2 SI_NETBSD
563#define SANITIZER_INTERCEPT_SHA2 (SI_NETBSD || SI_FREEBSD)
550564#define SANITIZER_INTERCEPT_CDB SI_NETBSD
551565#define SANITIZER_INTERCEPT_VIS (SI_NETBSD || SI_FREEBSD)
552566#define SANITIZER_INTERCEPT_POPEN SI_POSIX
......@@ -559,25 +573,30 @@
559573#define SANITIZER_INTERCEPT_FDEVNAME SI_FREEBSD
560574#define SANITIZER_INTERCEPT_GETUSERSHELL (SI_POSIX && !SI_ANDROID)
561575#define SANITIZER_INTERCEPT_SL_INIT (SI_FREEBSD || SI_NETBSD)
562#define SANITIZER_INTERCEPT_CRYPT (SI_POSIX && !SI_ANDROID)
563#define SANITIZER_INTERCEPT_CRYPT_R (SI_LINUX && !SI_ANDROID)
564576
565577#define SANITIZER_INTERCEPT_GETRANDOM \
566578 ((SI_LINUX && __GLIBC_PREREQ(2, 25)) || SI_FREEBSD)
567579#define SANITIZER_INTERCEPT___CXA_ATEXIT SI_NETBSD
568580#define SANITIZER_INTERCEPT_ATEXIT SI_NETBSD
569581#define SANITIZER_INTERCEPT_PTHREAD_ATFORK SI_NETBSD
570#define SANITIZER_INTERCEPT_GETENTROPY SI_FREEBSD
582#define SANITIZER_INTERCEPT_GETENTROPY \
583 ((SI_LINUX && __GLIBC_PREREQ(2, 25)) || SI_FREEBSD)
571584#define SANITIZER_INTERCEPT_QSORT \
572585 (SI_POSIX && !SI_IOSSIM && !SI_WATCHOS && !SI_TVOS && !SI_ANDROID)
573586#define SANITIZER_INTERCEPT_QSORT_R SI_GLIBC
587#define SANITIZER_INTERCEPT_BSEARCH \
588 (SI_POSIX && !SI_IOSSIM && !SI_WATCHOS && !SI_TVOS && !SI_ANDROID)
574589// sigaltstack on i386 macOS cannot be intercepted due to setjmp()
575590// calling it and assuming that it does not clobber registers.
576591#define SANITIZER_INTERCEPT_SIGALTSTACK \
577 (SI_POSIX && !(SANITIZER_MAC && SANITIZER_I386))
592 (SI_POSIX && !(SANITIZER_APPLE && SANITIZER_I386))
578593#define SANITIZER_INTERCEPT_UNAME (SI_POSIX && !SI_FREEBSD)
579594#define SANITIZER_INTERCEPT___XUNAME SI_FREEBSD
580595#define SANITIZER_INTERCEPT_FLOPEN SI_FREEBSD
596#define SANITIZER_INTERCEPT_PROCCTL SI_FREEBSD
597#define SANITIZER_INTERCEPT_HEXDUMP SI_FREEBSD
598#define SANITIZER_INTERCEPT_ARGP_PARSE SI_GLIBC
599#define SANITIZER_INTERCEPT_CPUSET_GETAFFINITY SI_FREEBSD
581600
582601// This macro gives a way for downstream users to override the above
583602// interceptor macros irrespective of the platform they are on. They have
lib/tsan/sanitizer_common/sanitizer_platform_limits_freebsd.cpp+39-1
......@@ -17,6 +17,7 @@
1717
1818#include <sys/capsicum.h>
1919#include <sys/consio.h>
20#include <sys/cpuset.h>
2021#include <sys/filio.h>
2122#include <sys/ipc.h>
2223#include <sys/kbio.h>
......@@ -69,11 +70,17 @@
6970#include <semaphore.h>
7071#include <signal.h>
7172#include <stddef.h>
73#include <md5.h>
74#include <sha224.h>
75#include <sha256.h>
76#include <sha384.h>
77#include <sha512.h>
7278#include <stdio.h>
7379#include <stringlist.h>
7480#include <term.h>
7581#include <termios.h>
7682#include <time.h>
83#include <ttyent.h>
7784#include <utime.h>
7885#include <utmpx.h>
7986#include <vis.h>
......@@ -97,6 +104,7 @@ void *__sanitizer_get_link_map_by_dlopen_handle(void *handle) {
97104 return internal_dlinfo(handle, RTLD_DI_LINKMAP, &p) == 0 ? p : nullptr;
98105}
99106
107unsigned struct_cpuset_sz = sizeof(cpuset_t);
100108unsigned struct_cap_rights_sz = sizeof(cap_rights_t);
101109unsigned struct_utsname_sz = sizeof(struct utsname);
102110unsigned struct_stat_sz = sizeof(struct stat);
......@@ -124,7 +132,7 @@ unsigned struct_sigevent_sz = sizeof(struct sigevent);
124132unsigned struct_sched_param_sz = sizeof(struct sched_param);
125133unsigned struct_statfs_sz = sizeof(struct statfs);
126134unsigned struct_sockaddr_sz = sizeof(struct sockaddr);
127unsigned ucontext_t_sz = sizeof(ucontext_t);
135unsigned ucontext_t_sz(void *ctx) { return sizeof(ucontext_t); }
128136unsigned struct_rlimit_sz = sizeof(struct rlimit);
129137unsigned struct_timespec_sz = sizeof(struct timespec);
130138unsigned struct_utimbuf_sz = sizeof(struct utimbuf);
......@@ -167,12 +175,21 @@ uptr __sanitizer_in_addr_sz(int af) {
167175 return 0;
168176}
169177
178// For FreeBSD the actual size of a directory entry is not always in d_reclen.
179// Use the appropriate macro to get the correct size for all cases (e.g. NFS).
180u16 __sanitizer_dirsiz(const __sanitizer_dirent *dp) {
181 return _GENERIC_DIRSIZ(dp);
182}
183
170184unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
171185int glob_nomatch = GLOB_NOMATCH;
172186int glob_altdirfunc = GLOB_ALTDIRFUNC;
187const int wordexp_wrde_dooffs = WRDE_DOOFFS;
173188
174189unsigned path_max = PATH_MAX;
175190
191int struct_ttyent_sz = sizeof(struct ttyent);
192
176193// ioctl arguments
177194unsigned struct_ifreq_sz = sizeof(struct ifreq);
178195unsigned struct_termios_sz = sizeof(struct termios);
......@@ -196,6 +213,10 @@ unsigned struct_audio_buf_info_sz = sizeof(struct audio_buf_info);
196213unsigned struct_ppp_stats_sz = sizeof(struct ppp_stats);
197214unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req);
198215unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req);
216unsigned struct_procctl_reaper_status_sz = sizeof(struct __sanitizer_procctl_reaper_status);
217unsigned struct_procctl_reaper_pidinfo_sz = sizeof(struct __sanitizer_procctl_reaper_pidinfo);
218unsigned struct_procctl_reaper_pids_sz = sizeof(struct __sanitizer_procctl_reaper_pids);
219unsigned struct_procctl_reaper_kill_sz = sizeof(struct __sanitizer_procctl_reaper_kill);
199220const unsigned long __sanitizer_bufsiz = BUFSIZ;
200221
201222const unsigned IOCTL_NOT_PRESENT = 0;
......@@ -357,6 +378,22 @@ const int si_SEGV_MAPERR = SEGV_MAPERR;
357378const int si_SEGV_ACCERR = SEGV_ACCERR;
358379const int unvis_valid = UNVIS_VALID;
359380const int unvis_validpush = UNVIS_VALIDPUSH;
381
382const unsigned MD5_CTX_sz = sizeof(MD5_CTX);
383const unsigned MD5_return_length = MD5_DIGEST_STRING_LENGTH;
384
385#define SHA2_CONST(LEN) \
386 const unsigned SHA##LEN##_CTX_sz = sizeof(SHA##LEN##_CTX); \
387 const unsigned SHA##LEN##_return_length = SHA##LEN##_DIGEST_STRING_LENGTH; \
388 const unsigned SHA##LEN##_block_length = SHA##LEN##_BLOCK_LENGTH; \
389 const unsigned SHA##LEN##_digest_length = SHA##LEN##_DIGEST_LENGTH
390
391SHA2_CONST(224);
392SHA2_CONST(256);
393SHA2_CONST(384);
394SHA2_CONST(512);
395
396#undef SHA2_CONST
360397} // namespace __sanitizer
361398
362399using namespace __sanitizer;
......@@ -529,4 +566,5 @@ COMPILER_CHECK(__sanitizer_XDR_FREE == XDR_FREE);
529566CHECK_TYPE_SIZE(sem_t);
530567
531568COMPILER_CHECK(sizeof(__sanitizer_cap_rights_t) >= sizeof(cap_rights_t));
569COMPILER_CHECK(sizeof(__sanitizer_cpuset_t) >= sizeof(cpuset_t));
532570#endif // SANITIZER_FREEBSD
lib/tsan/sanitizer_common/sanitizer_platform_limits_freebsd.h+167-71
......@@ -16,26 +16,26 @@
1616
1717#if SANITIZER_FREEBSD
1818
19#include "sanitizer_internal_defs.h"
20#include "sanitizer_platform.h"
21#include "sanitizer_platform_limits_posix.h"
19# include "sanitizer_internal_defs.h"
20# include "sanitizer_platform.h"
21# include "sanitizer_platform_limits_posix.h"
2222
2323// Get sys/_types.h, because that tells us whether 64-bit inodes are
2424// used in struct dirent below.
25#include <sys/_types.h>
25# include <sys/_types.h>
2626
2727namespace __sanitizer {
2828void *__sanitizer_get_link_map_by_dlopen_handle(void *handle);
29#define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) \
30 (link_map *)__sanitizer_get_link_map_by_dlopen_handle(handle)
29# define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) \
30 (link_map *)__sanitizer_get_link_map_by_dlopen_handle(handle)
3131
3232extern unsigned struct_utsname_sz;
3333extern unsigned struct_stat_sz;
34#if defined(__powerpc64__)
34# if defined(__powerpc64__)
3535const unsigned struct___old_kernel_stat_sz = 0;
36#else
36# else
3737const unsigned struct___old_kernel_stat_sz = 32;
38#endif
38# endif
3939extern unsigned struct_rusage_sz;
4040extern unsigned siginfo_t_sz;
4141extern unsigned struct_itimerval_sz;
......@@ -57,7 +57,7 @@ extern unsigned struct_sched_param_sz;
5757extern unsigned struct_statfs64_sz;
5858extern unsigned struct_statfs_sz;
5959extern unsigned struct_sockaddr_sz;
60extern unsigned ucontext_t_sz;
60unsigned ucontext_t_sz(void *ctx);
6161extern unsigned struct_rlimit_sz;
6262extern unsigned struct_utimbuf_sz;
6363extern unsigned struct_timespec_sz;
......@@ -114,11 +114,24 @@ struct __sanitizer_ipc_perm {
114114 long key;
115115};
116116
117#if !defined(__i386__)
117struct __sanitizer_protoent {
118 char *p_name;
119 char **p_aliases;
120 int p_proto;
121};
122
123struct __sanitizer_netent {
124 char *n_name;
125 char **n_aliases;
126 int n_addrtype;
127 u32 n_net;
128};
129
130# if !defined(__i386__)
118131typedef long long __sanitizer_time_t;
119#else
132# else
120133typedef long __sanitizer_time_t;
121#endif
134# endif
122135
123136struct __sanitizer_shmid_ds {
124137 __sanitizer_ipc_perm shm_perm;
......@@ -147,7 +160,7 @@ struct __sanitizer_ifaddrs {
147160 unsigned int ifa_flags;
148161 void *ifa_addr; // (struct sockaddr *)
149162 void *ifa_netmask; // (struct sockaddr *)
150#undef ifa_dstaddr
163# undef ifa_dstaddr
151164 void *ifa_dstaddr; // (struct sockaddr *)
152165 void *ifa_data;
153166};
......@@ -229,37 +242,43 @@ struct __sanitizer_cmsghdr {
229242};
230243
231244struct __sanitizer_dirent {
232#if defined(__INO64)
245# if defined(__INO64)
233246 unsigned long long d_fileno;
234247 unsigned long long d_off;
235#else
248# else
236249 unsigned int d_fileno;
237#endif
250# endif
238251 unsigned short d_reclen;
239 // more fields that we don't care about
252 u8 d_type;
253 u8 d_pad0;
254 u16 d_namlen;
255 u16 d_pad1;
256 char d_name[256];
240257};
241258
259u16 __sanitizer_dirsiz(const __sanitizer_dirent *dp);
260
242261// 'clock_t' is 32 bits wide on x64 FreeBSD
243262typedef int __sanitizer_clock_t;
244263typedef int __sanitizer_clockid_t;
245264
246#if defined(_LP64) || defined(__x86_64__) || defined(__powerpc__) || \
247 defined(__mips__)
265# if defined(_LP64) || defined(__x86_64__) || defined(__powerpc__) || \
266 defined(__mips__)
248267typedef unsigned __sanitizer___kernel_uid_t;
249268typedef unsigned __sanitizer___kernel_gid_t;
250#else
269# else
251270typedef unsigned short __sanitizer___kernel_uid_t;
252271typedef unsigned short __sanitizer___kernel_gid_t;
253#endif
272# endif
254273typedef long long __sanitizer___kernel_off_t;
255274
256#if defined(__powerpc__) || defined(__mips__)
275# if defined(__powerpc__) || defined(__mips__)
257276typedef unsigned int __sanitizer___kernel_old_uid_t;
258277typedef unsigned int __sanitizer___kernel_old_gid_t;
259#else
278# else
260279typedef unsigned short __sanitizer___kernel_old_uid_t;
261280typedef unsigned short __sanitizer___kernel_old_gid_t;
262#endif
281# endif
263282
264283typedef long long __sanitizer___kernel_loff_t;
265284typedef struct {
......@@ -366,9 +385,12 @@ struct __sanitizer_glob_t {
366385
367386extern int glob_nomatch;
368387extern int glob_altdirfunc;
388extern const int wordexp_wrde_dooffs;
369389
370390extern unsigned path_max;
371391
392extern int struct_ttyent_sz;
393
372394struct __sanitizer_wordexp_t {
373395 uptr we_wordc;
374396 char **we_wordv;
......@@ -398,39 +420,81 @@ struct __sanitizer_ifconf {
398420 } ifc_ifcu;
399421};
400422
401#define IOC_NRBITS 8
402#define IOC_TYPEBITS 8
403#if defined(__powerpc__) || defined(__powerpc64__) || defined(__mips__)
404#define IOC_SIZEBITS 13
405#define IOC_DIRBITS 3
406#define IOC_NONE 1U
407#define IOC_WRITE 4U
408#define IOC_READ 2U
409#else
410#define IOC_SIZEBITS 14
411#define IOC_DIRBITS 2
412#define IOC_NONE 0U
413#define IOC_WRITE 1U
414#define IOC_READ 2U
415#endif
416#define IOC_NRMASK ((1 << IOC_NRBITS) - 1)
417#define IOC_TYPEMASK ((1 << IOC_TYPEBITS) - 1)
418#define IOC_SIZEMASK ((1 << IOC_SIZEBITS) - 1)
419#if defined(IOC_DIRMASK)
420#undef IOC_DIRMASK
421#endif
422#define IOC_DIRMASK ((1 << IOC_DIRBITS) - 1)
423#define IOC_NRSHIFT 0
424#define IOC_TYPESHIFT (IOC_NRSHIFT + IOC_NRBITS)
425#define IOC_SIZESHIFT (IOC_TYPESHIFT + IOC_TYPEBITS)
426#define IOC_DIRSHIFT (IOC_SIZESHIFT + IOC_SIZEBITS)
427#define EVIOC_EV_MAX 0x1f
428#define EVIOC_ABS_MAX 0x3f
429
430#define IOC_DIR(nr) (((nr) >> IOC_DIRSHIFT) & IOC_DIRMASK)
431#define IOC_TYPE(nr) (((nr) >> IOC_TYPESHIFT) & IOC_TYPEMASK)
432#define IOC_NR(nr) (((nr) >> IOC_NRSHIFT) & IOC_NRMASK)
433#define IOC_SIZE(nr) (((nr) >> IOC_SIZESHIFT) & IOC_SIZEMASK)
423struct __sanitizer__ttyent {
424 char *ty_name;
425 char *ty_getty;
426 char *ty_type;
427 int ty_status;
428 char *ty_window;
429 char *ty_comment;
430 char *ty_group;
431};
432
433// procctl reaper data for PROCCTL_REAPER flags
434struct __sanitizer_procctl_reaper_status {
435 unsigned int rs_flags;
436 unsigned int rs_children;
437 unsigned int rs_descendants;
438 pid_t rs_reaper;
439 pid_t rs_pid;
440 unsigned int rs_pad0[15];
441};
442
443struct __sanitizer_procctl_reaper_pidinfo {
444 pid_t pi_pid;
445 pid_t pi_subtree;
446 unsigned int pi_flags;
447 unsigned int pi_pad0[15];
448};
449
450struct __sanitizer_procctl_reaper_pids {
451 unsigned int rp_count;
452 unsigned int rp_pad0[15];
453 struct __sanitize_procctl_reapper_pidinfo *rp_pids;
454};
455
456struct __sanitizer_procctl_reaper_kill {
457 int rk_sig;
458 unsigned int rk_flags;
459 pid_t rk_subtree;
460 unsigned int rk_killed;
461 pid_t rk_fpid;
462 unsigned int rk_pad[15];
463};
464
465# define IOC_NRBITS 8
466# define IOC_TYPEBITS 8
467# if defined(__powerpc__) || defined(__powerpc64__) || defined(__mips__)
468# define IOC_SIZEBITS 13
469# define IOC_DIRBITS 3
470# define IOC_NONE 1U
471# define IOC_WRITE 4U
472# define IOC_READ 2U
473# else
474# define IOC_SIZEBITS 14
475# define IOC_DIRBITS 2
476# define IOC_NONE 0U
477# define IOC_WRITE 1U
478# define IOC_READ 2U
479# endif
480# define IOC_NRMASK ((1 << IOC_NRBITS) - 1)
481# define IOC_TYPEMASK ((1 << IOC_TYPEBITS) - 1)
482# define IOC_SIZEMASK ((1 << IOC_SIZEBITS) - 1)
483# if defined(IOC_DIRMASK)
484# undef IOC_DIRMASK
485# endif
486# define IOC_DIRMASK ((1 << IOC_DIRBITS) - 1)
487# define IOC_NRSHIFT 0
488# define IOC_TYPESHIFT (IOC_NRSHIFT + IOC_NRBITS)
489# define IOC_SIZESHIFT (IOC_TYPESHIFT + IOC_TYPEBITS)
490# define IOC_DIRSHIFT (IOC_SIZESHIFT + IOC_SIZEBITS)
491# define EVIOC_EV_MAX 0x1f
492# define EVIOC_ABS_MAX 0x3f
493
494# define IOC_DIR(nr) (((nr) >> IOC_DIRSHIFT) & IOC_DIRMASK)
495# define IOC_TYPE(nr) (((nr) >> IOC_TYPESHIFT) & IOC_TYPEMASK)
496# define IOC_NR(nr) (((nr) >> IOC_NRSHIFT) & IOC_NRMASK)
497# define IOC_SIZE(nr) (((nr) >> IOC_SIZESHIFT) & IOC_SIZEMASK)
434498
435499extern unsigned struct_ifreq_sz;
436500extern unsigned struct_termios_sz;
......@@ -454,6 +518,11 @@ extern unsigned struct_ppp_stats_sz;
454518extern unsigned struct_sioc_sg_req_sz;
455519extern unsigned struct_sioc_vif_req_sz;
456520
521extern unsigned struct_procctl_reaper_status_sz;
522extern unsigned struct_procctl_reaper_pidinfo_sz;
523extern unsigned struct_procctl_reaper_pids_sz;
524extern unsigned struct_procctl_reaper_kill_sz;
525
457526// ioctl request identifiers
458527
459528// A special value to mark ioctls that are not present on the target platform,
......@@ -621,6 +690,22 @@ extern unsigned IOCTL_KDSKBMODE;
621690extern const int si_SEGV_MAPERR;
622691extern const int si_SEGV_ACCERR;
623692
693extern const unsigned MD5_CTX_sz;
694extern const unsigned MD5_return_length;
695
696#define SHA2_EXTERN(LEN) \
697 extern const unsigned SHA##LEN##_CTX_sz; \
698 extern const unsigned SHA##LEN##_return_length; \
699 extern const unsigned SHA##LEN##_block_length; \
700 extern const unsigned SHA##LEN##_digest_length
701
702SHA2_EXTERN(224);
703SHA2_EXTERN(256);
704SHA2_EXTERN(384);
705SHA2_EXTERN(512);
706
707#undef SHA2_EXTERN
708
624709struct __sanitizer_cap_rights {
625710 u64 cr_rights[2];
626711};
......@@ -630,26 +715,37 @@ extern unsigned struct_cap_rights_sz;
630715
631716extern unsigned struct_fstab_sz;
632717extern unsigned struct_StringList_sz;
718
719struct __sanitizer_cpuset {
720#if __FreeBSD_version >= 1400090
721 long __bits[(1024 + (sizeof(long) * 8) - 1) / (sizeof(long) * 8)];
722#else
723 long __bits[(256 + (sizeof(long) * 8) - 1) / (sizeof(long) * 8)];
724#endif
725};
726
727typedef struct __sanitizer_cpuset __sanitizer_cpuset_t;
728extern unsigned struct_cpuset_sz;
633729} // namespace __sanitizer
634730
635#define CHECK_TYPE_SIZE(TYPE) \
636 COMPILER_CHECK(sizeof(__sanitizer_##TYPE) == sizeof(TYPE))
731# define CHECK_TYPE_SIZE(TYPE) \
732 COMPILER_CHECK(sizeof(__sanitizer_##TYPE) == sizeof(TYPE))
637733
638#define CHECK_SIZE_AND_OFFSET(CLASS, MEMBER) \
639 COMPILER_CHECK(sizeof(((__sanitizer_##CLASS *)NULL)->MEMBER) == \
640 sizeof(((CLASS *)NULL)->MEMBER)); \
641 COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) == \
642 offsetof(CLASS, MEMBER))
734# define CHECK_SIZE_AND_OFFSET(CLASS, MEMBER) \
735 COMPILER_CHECK(sizeof(((__sanitizer_##CLASS *)NULL)->MEMBER) == \
736 sizeof(((CLASS *)NULL)->MEMBER)); \
737 COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) == \
738 offsetof(CLASS, MEMBER))
643739
644740// For sigaction, which is a function and struct at the same time,
645741// and thus requires explicit "struct" in sizeof() expression.
646#define CHECK_STRUCT_SIZE_AND_OFFSET(CLASS, MEMBER) \
647 COMPILER_CHECK(sizeof(((struct __sanitizer_##CLASS *)NULL)->MEMBER) == \
648 sizeof(((struct CLASS *)NULL)->MEMBER)); \
649 COMPILER_CHECK(offsetof(struct __sanitizer_##CLASS, MEMBER) == \
650 offsetof(struct CLASS, MEMBER))
742# define CHECK_STRUCT_SIZE_AND_OFFSET(CLASS, MEMBER) \
743 COMPILER_CHECK(sizeof(((struct __sanitizer_##CLASS *)NULL)->MEMBER) == \
744 sizeof(((struct CLASS *)NULL)->MEMBER)); \
745 COMPILER_CHECK(offsetof(struct __sanitizer_##CLASS, MEMBER) == \
746 offsetof(struct CLASS, MEMBER))
651747
652#define SIGACTION_SYMNAME sigaction
748# define SIGACTION_SYMNAME sigaction
653749
654750#endif
655751
lib/tsan/sanitizer_common/sanitizer_platform_limits_linux.cpp+29-34
......@@ -28,44 +28,39 @@
2828// are not defined anywhere in userspace headers. Fake them. This seems to work
2929// fine with newer headers, too.
3030#include <linux/posix_types.h>
31#if defined(__x86_64__) || defined(__mips__)
32#include <sys/stat.h>
33#else
34#define ino_t __kernel_ino_t
35#define mode_t __kernel_mode_t
36#define nlink_t __kernel_nlink_t
37#define uid_t __kernel_uid_t
38#define gid_t __kernel_gid_t
39#define off_t __kernel_off_t
40#define time_t __kernel_time_t
31# if defined(__x86_64__) || defined(__mips__) || defined(__hexagon__)
32# include <sys/stat.h>
33# else
34# define ino_t __kernel_ino_t
35# define mode_t __kernel_mode_t
36# define nlink_t __kernel_nlink_t
37# define uid_t __kernel_uid_t
38# define gid_t __kernel_gid_t
39# define off_t __kernel_off_t
40# define time_t __kernel_time_t
4141// This header seems to contain the definitions of _kernel_ stat* structs.
42#include <asm/stat.h>
43#undef ino_t
44#undef mode_t
45#undef nlink_t
46#undef uid_t
47#undef gid_t
48#undef off_t
49#endif
50
51#include <linux/aio_abi.h>
52
53#if !SANITIZER_ANDROID
54#include <sys/statfs.h>
55#include <linux/perf_event.h>
56#endif
42# include <asm/stat.h>
43# undef ino_t
44# undef mode_t
45# undef nlink_t
46# undef uid_t
47# undef gid_t
48# undef off_t
49# endif
50
51# include <linux/aio_abi.h>
52
53# if !SANITIZER_ANDROID
54# include <sys/statfs.h>
55# include <linux/perf_event.h>
56# endif
5757
5858using namespace __sanitizer;
5959
60namespace __sanitizer {
61#if !SANITIZER_ANDROID
62 unsigned struct_statfs64_sz = sizeof(struct statfs64);
63#endif
64} // namespace __sanitizer
65
66#if !defined(__powerpc64__) && !defined(__x86_64__) && !defined(__aarch64__)\
67 && !defined(__mips__) && !defined(__s390__)\
68 && !defined(__sparc__) && !defined(__riscv)
60# if !defined(__powerpc64__) && !defined(__x86_64__) && \
61 !defined(__aarch64__) && !defined(__mips__) && !defined(__s390__) && \
62 !defined(__sparc__) && !defined(__riscv) && !defined(__hexagon__) && \
63 !defined(__loongarch__)
6964COMPILER_CHECK(struct___old_kernel_stat_sz == sizeof(struct __old_kernel_stat));
7065#endif
7166
lib/tsan/sanitizer_common/sanitizer_platform_limits_netbsd.cpp+2-3
......@@ -554,7 +554,7 @@ unsigned struct_tms_sz = sizeof(struct tms);
554554unsigned struct_sigevent_sz = sizeof(struct sigevent);
555555unsigned struct_sched_param_sz = sizeof(struct sched_param);
556556unsigned struct_sockaddr_sz = sizeof(struct sockaddr);
557unsigned ucontext_t_sz = sizeof(ucontext_t);
557unsigned ucontext_t_sz(void *ctx) { return sizeof(ucontext_t); }
558558unsigned struct_rlimit_sz = sizeof(struct rlimit);
559559unsigned struct_timespec_sz = sizeof(struct timespec);
560560unsigned struct_sembuf_sz = sizeof(struct sembuf);
......@@ -666,6 +666,7 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
666666
667667int glob_nomatch = GLOB_NOMATCH;
668668int glob_altdirfunc = GLOB_ALTDIRFUNC;
669const int wordexp_wrde_dooffs = WRDE_DOOFFS;
669670
670671unsigned path_max = PATH_MAX;
671672
......@@ -2341,8 +2342,6 @@ unsigned IOCTL_TIOCDRAIN = TIOCDRAIN;
23412342unsigned IOCTL_TIOCGFLAGS = TIOCGFLAGS;
23422343unsigned IOCTL_TIOCSFLAGS = TIOCSFLAGS;
23432344unsigned IOCTL_TIOCDCDTIMESTAMP = TIOCDCDTIMESTAMP;
2344unsigned IOCTL_TIOCRCVFRAME = TIOCRCVFRAME;
2345unsigned IOCTL_TIOCXMTFRAME = TIOCXMTFRAME;
23462345unsigned IOCTL_TIOCPTMGET = TIOCPTMGET;
23472346unsigned IOCTL_TIOCGRANTPT = TIOCGRANTPT;
23482347unsigned IOCTL_TIOCPTSNAME = TIOCPTSNAME;
lib/tsan/sanitizer_common/sanitizer_platform_limits_netbsd.h+2-3
......@@ -45,7 +45,7 @@ extern unsigned struct_stack_t_sz;
4545extern unsigned struct_sched_param_sz;
4646extern unsigned struct_statfs_sz;
4747extern unsigned struct_sockaddr_sz;
48extern unsigned ucontext_t_sz;
48unsigned ucontext_t_sz(void *ctx);
4949
5050extern unsigned struct_rlimit_sz;
5151extern unsigned struct_utimbuf_sz;
......@@ -394,6 +394,7 @@ struct __sanitizer_glob_t {
394394
395395extern int glob_nomatch;
396396extern int glob_altdirfunc;
397extern const int wordexp_wrde_dooffs;
397398
398399extern unsigned path_max;
399400
......@@ -2194,8 +2195,6 @@ extern unsigned IOCTL_TIOCDRAIN;
21942195extern unsigned IOCTL_TIOCGFLAGS;
21952196extern unsigned IOCTL_TIOCSFLAGS;
21962197extern unsigned IOCTL_TIOCDCDTIMESTAMP;
2197extern unsigned IOCTL_TIOCRCVFRAME;
2198extern unsigned IOCTL_TIOCXMTFRAME;
21992198extern unsigned IOCTL_TIOCPTMGET;
22002199extern unsigned IOCTL_TIOCGRANTPT;
22012200extern unsigned IOCTL_TIOCPTSNAME;
lib/tsan/sanitizer_common/sanitizer_platform_limits_posix.cpp+110-44
......@@ -18,12 +18,13 @@
1818// depends on _FILE_OFFSET_BITS setting.
1919// To get this "true" dirent definition, we undefine _FILE_OFFSET_BITS below.
2020#undef _FILE_OFFSET_BITS
21#undef _TIME_BITS
2122#endif
2223
2324// Must go after undef _FILE_OFFSET_BITS.
2425#include "sanitizer_platform.h"
2526
26#if SANITIZER_LINUX || SANITIZER_MAC
27#if SANITIZER_LINUX || SANITIZER_APPLE
2728// Must go after undef _FILE_OFFSET_BITS.
2829#include "sanitizer_glibc_version.h"
2930
......@@ -51,7 +52,7 @@
5152#include <time.h>
5253#include <wchar.h>
5354#include <regex.h>
54#if !SANITIZER_MAC
55#if !SANITIZER_APPLE
5556#include <utmp.h>
5657#endif
5758
......@@ -73,7 +74,9 @@
7374#include <sys/vt.h>
7475#include <linux/cdrom.h>
7576#include <linux/fd.h>
77#if SANITIZER_ANDROID
7678#include <linux/fs.h>
79#endif
7780#include <linux/hdreg.h>
7881#include <linux/input.h>
7982#include <linux/ioctl.h>
......@@ -91,10 +94,10 @@
9194#if SANITIZER_LINUX
9295# include <utime.h>
9396# include <sys/ptrace.h>
94#if defined(__mips64) || defined(__aarch64__) || defined(__arm__) || \
95 SANITIZER_RISCV64
96# include <asm/ptrace.h>
97# ifdef __arm__
97# if defined(__mips64) || defined(__aarch64__) || defined(__arm__) || \
98 defined(__hexagon__) || defined(__loongarch__) ||SANITIZER_RISCV64
99# include <asm/ptrace.h>
100# ifdef __arm__
98101typedef struct user_fpregs elf_fpregset_t;
99102# define ARM_VFPREGS_SIZE_ASAN (32 * 8 /*fpregs*/ + 4 /*fpscr*/)
100103# if !defined(ARM_VFPREGS_SIZE)
......@@ -152,7 +155,6 @@ typedef struct user_fpregs elf_fpregset_t;
152155#include <linux/serial.h>
153156#include <sys/msg.h>
154157#include <sys/ipc.h>
155#include <crypt.h>
156158#endif // SANITIZER_ANDROID
157159
158160#include <link.h>
......@@ -163,22 +165,24 @@ typedef struct user_fpregs elf_fpregset_t;
163165#include <fstab.h>
164166#endif // SANITIZER_LINUX
165167
166#if SANITIZER_MAC
168#if SANITIZER_APPLE
167169#include <net/ethernet.h>
168170#include <sys/filio.h>
169171#include <sys/sockio.h>
170172#endif
171173
172174// Include these after system headers to avoid name clashes and ambiguities.
173#include "sanitizer_internal_defs.h"
174#include "sanitizer_platform_limits_posix.h"
175# include "sanitizer_common.h"
176# include "sanitizer_internal_defs.h"
177# include "sanitizer_platform_interceptors.h"
178# include "sanitizer_platform_limits_posix.h"
175179
176180namespace __sanitizer {
177181 unsigned struct_utsname_sz = sizeof(struct utsname);
178182 unsigned struct_stat_sz = sizeof(struct stat);
179#if !SANITIZER_IOS && !(SANITIZER_MAC && TARGET_CPU_ARM64)
183#if SANITIZER_HAS_STAT64
180184 unsigned struct_stat64_sz = sizeof(struct stat64);
181#endif // !SANITIZER_IOS && !(SANITIZER_MAC && TARGET_CPU_ARM64)
185#endif // SANITIZER_HAS_STAT64
182186 unsigned struct_rusage_sz = sizeof(struct rusage);
183187 unsigned struct_tm_sz = sizeof(struct tm);
184188 unsigned struct_passwd_sz = sizeof(struct passwd);
......@@ -203,26 +207,60 @@ namespace __sanitizer {
203207 unsigned struct_regex_sz = sizeof(regex_t);
204208 unsigned struct_regmatch_sz = sizeof(regmatch_t);
205209
206#if (SANITIZER_MAC && !TARGET_CPU_ARM64) && !SANITIZER_IOS
210#if SANITIZER_HAS_STATFS64
207211 unsigned struct_statfs64_sz = sizeof(struct statfs64);
208#endif // (SANITIZER_MAC && !TARGET_CPU_ARM64) && !SANITIZER_IOS
212#endif // SANITIZER_HAS_STATFS64
209213
210#if SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_MAC
214#if SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_APPLE
211215 unsigned struct_fstab_sz = sizeof(struct fstab);
212216#endif // SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD ||
213 // SANITIZER_MAC
217 // SANITIZER_APPLE
214218#if !SANITIZER_ANDROID
215219 unsigned struct_statfs_sz = sizeof(struct statfs);
216220 unsigned struct_sockaddr_sz = sizeof(struct sockaddr);
217 unsigned ucontext_t_sz = sizeof(ucontext_t);
218#endif // !SANITIZER_ANDROID
219221
220#if SANITIZER_LINUX
222 unsigned ucontext_t_sz(void *ctx) {
223# if SANITIZER_GLIBC && SANITIZER_X64
224 // Added in Linux kernel 3.4.0, merged to glibc in 2.16
225# ifndef FP_XSTATE_MAGIC1
226# define FP_XSTATE_MAGIC1 0x46505853U
227# endif
228 // See kernel arch/x86/kernel/fpu/signal.c for details.
229 const auto *fpregs = static_cast<ucontext_t *>(ctx)->uc_mcontext.fpregs;
230 // The member names differ across header versions, but the actual layout
231 // is always the same. So avoid using members, just use arithmetic.
232 const uint32_t *after_xmm =
233 reinterpret_cast<const uint32_t *>(fpregs + 1) - 24;
234 if (after_xmm[12] == FP_XSTATE_MAGIC1)
235 return reinterpret_cast<const char *>(fpregs) + after_xmm[13] -
236 static_cast<const char *>(ctx);
237# endif
238 return sizeof(ucontext_t);
239 }
240# endif // !SANITIZER_ANDROID
241
242# if SANITIZER_LINUX
221243 unsigned struct_epoll_event_sz = sizeof(struct epoll_event);
222244 unsigned struct_sysinfo_sz = sizeof(struct sysinfo);
223245 unsigned __user_cap_header_struct_sz =
224246 sizeof(struct __user_cap_header_struct);
225 unsigned __user_cap_data_struct_sz = sizeof(struct __user_cap_data_struct);
247 unsigned __user_cap_data_struct_sz(void *hdrp) {
248 int u32s = 0;
249 if (hdrp) {
250 switch (((struct __user_cap_header_struct *)hdrp)->version) {
251 case _LINUX_CAPABILITY_VERSION_1:
252 u32s = _LINUX_CAPABILITY_U32S_1;
253 break;
254 case _LINUX_CAPABILITY_VERSION_2:
255 u32s = _LINUX_CAPABILITY_U32S_2;
256 break;
257 case _LINUX_CAPABILITY_VERSION_3:
258 u32s = _LINUX_CAPABILITY_U32S_3;
259 break;
260 }
261 }
262 return sizeof(struct __user_cap_data_struct) * u32s;
263 }
226264 unsigned struct_new_utsname_sz = sizeof(struct new_utsname);
227265 unsigned struct_old_utsname_sz = sizeof(struct old_utsname);
228266 unsigned struct_oldold_utsname_sz = sizeof(struct oldold_utsname);
......@@ -235,24 +273,28 @@ namespace __sanitizer {
235273 unsigned struct_itimerspec_sz = sizeof(struct itimerspec);
236274#endif // SANITIZER_LINUX
237275
238#if SANITIZER_LINUX && !SANITIZER_ANDROID
276#if SANITIZER_GLIBC
239277 // Use pre-computed size of struct ustat to avoid <sys/ustat.h> which
240278 // has been removed from glibc 2.28.
241279#if defined(__aarch64__) || defined(__s390x__) || defined(__mips64) || \
242280 defined(__powerpc64__) || defined(__arch64__) || defined(__sparcv9) || \
243281 defined(__x86_64__) || SANITIZER_RISCV64
244282#define SIZEOF_STRUCT_USTAT 32
245#elif defined(__arm__) || defined(__i386__) || defined(__mips__) \
246 || defined(__powerpc__) || defined(__s390__) || defined(__sparc__)
247#define SIZEOF_STRUCT_USTAT 20
248#else
249#error Unknown size of struct ustat
250#endif
283# elif defined(__arm__) || defined(__i386__) || defined(__mips__) || \
284 defined(__powerpc__) || defined(__s390__) || defined(__sparc__) || \
285 defined(__hexagon__)
286# define SIZEOF_STRUCT_USTAT 20
287# elif defined(__loongarch__)
288 // Not used. The minimum Glibc version available for LoongArch is 2.36
289 // so ustat() wrapper is already gone.
290# define SIZEOF_STRUCT_USTAT 0
291# else
292# error Unknown size of struct ustat
293# endif
251294 unsigned struct_ustat_sz = SIZEOF_STRUCT_USTAT;
252295 unsigned struct_rlimit64_sz = sizeof(struct rlimit64);
253296 unsigned struct_statvfs64_sz = sizeof(struct statvfs64);
254 unsigned struct_crypt_data_sz = sizeof(struct crypt_data);
255#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
297#endif // SANITIZER_GLIBC
256298
257299#if SANITIZER_LINUX && !SANITIZER_ANDROID
258300 unsigned struct_timex_sz = sizeof(struct timex);
......@@ -280,7 +322,7 @@ namespace __sanitizer {
280322 int shmctl_shm_stat = (int)SHM_STAT;
281323#endif
282324
283#if !SANITIZER_MAC && !SANITIZER_FREEBSD
325#if !SANITIZER_APPLE && !SANITIZER_FREEBSD
284326 unsigned struct_utmp_sz = sizeof(struct utmp);
285327#endif
286328#if !SANITIZER_ANDROID
......@@ -312,10 +354,14 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
312354 int glob_altdirfunc = GLOB_ALTDIRFUNC;
313355#endif
314356
357# if !SANITIZER_ANDROID
358 const int wordexp_wrde_dooffs = WRDE_DOOFFS;
359# endif // !SANITIZER_ANDROID
360
315361#if SANITIZER_LINUX && !SANITIZER_ANDROID && \
316362 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
317363 defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \
318 defined(__s390__) || SANITIZER_RISCV64)
364 defined(__s390__) || defined(__loongarch__)|| SANITIZER_RISCV64)
319365#if defined(__mips64) || defined(__powerpc64__) || defined(__arm__)
320366 unsigned struct_user_regs_struct_sz = sizeof(struct pt_regs);
321367 unsigned struct_user_fpregs_struct_sz = sizeof(elf_fpregset_t);
......@@ -325,21 +371,24 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
325371#elif defined(__aarch64__)
326372 unsigned struct_user_regs_struct_sz = sizeof(struct user_pt_regs);
327373 unsigned struct_user_fpregs_struct_sz = sizeof(struct user_fpsimd_state);
374#elif defined(__loongarch__)
375 unsigned struct_user_regs_struct_sz = sizeof(struct user_pt_regs);
376 unsigned struct_user_fpregs_struct_sz = sizeof(struct user_fp_state);
328377#elif defined(__s390__)
329378 unsigned struct_user_regs_struct_sz = sizeof(struct _user_regs_struct);
330379 unsigned struct_user_fpregs_struct_sz = sizeof(struct _user_fpregs_struct);
331380#else
332381 unsigned struct_user_regs_struct_sz = sizeof(struct user_regs_struct);
333382 unsigned struct_user_fpregs_struct_sz = sizeof(struct user_fpregs_struct);
334#endif // __mips64 || __powerpc64__ || __aarch64__
383#endif // __mips64 || __powerpc64__ || __aarch64__ || __loongarch__
335384#if defined(__x86_64) || defined(__mips64) || defined(__powerpc64__) || \
336385 defined(__aarch64__) || defined(__arm__) || defined(__s390__) || \
337 SANITIZER_RISCV64
386 defined(__loongarch__) || SANITIZER_RISCV64
338387 unsigned struct_user_fpxregs_struct_sz = 0;
339388#else
340389 unsigned struct_user_fpxregs_struct_sz = sizeof(struct user_fpxregs_struct);
341390#endif // __x86_64 || __mips64 || __powerpc64__ || __aarch64__ || __arm__
342// || __s390__
391// || __s390__ || __loongarch__
343392#ifdef __arm__
344393 unsigned struct_user_vfpregs_struct_sz = ARM_VFPREGS_SIZE;
345394#else
......@@ -484,7 +533,7 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
484533 unsigned struct_ppp_stats_sz = sizeof(struct ppp_stats);
485534#endif // SANITIZER_GLIBC
486535
487#if !SANITIZER_ANDROID && !SANITIZER_MAC
536#if !SANITIZER_ANDROID && !SANITIZER_APPLE
488537 unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req);
489538 unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req);
490539#endif
......@@ -570,6 +619,14 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
570619 unsigned IOCTL_BLKROGET = BLKROGET;
571620 unsigned IOCTL_BLKROSET = BLKROSET;
572621 unsigned IOCTL_BLKRRPART = BLKRRPART;
622 unsigned IOCTL_BLKFRASET = BLKFRASET;
623 unsigned IOCTL_BLKFRAGET = BLKFRAGET;
624 unsigned IOCTL_BLKSECTSET = BLKSECTSET;
625 unsigned IOCTL_BLKSECTGET = BLKSECTGET;
626 unsigned IOCTL_BLKSSZGET = BLKSSZGET;
627 unsigned IOCTL_BLKBSZGET = BLKBSZGET;
628 unsigned IOCTL_BLKBSZSET = BLKBSZSET;
629 unsigned IOCTL_BLKGETSIZE64 = BLKGETSIZE64;
573630 unsigned IOCTL_CDROMAUDIOBUFSIZ = CDROMAUDIOBUFSIZ;
574631 unsigned IOCTL_CDROMEJECT = CDROMEJECT;
575632 unsigned IOCTL_CDROMEJECT_SW = CDROMEJECT_SW;
......@@ -837,10 +894,10 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
837894 unsigned IOCTL_EVIOCGPROP = IOCTL_NOT_PRESENT;
838895 unsigned IOCTL_EVIOCSKEYCODE_V2 = IOCTL_NOT_PRESENT;
839896#endif
840 unsigned IOCTL_FS_IOC_GETFLAGS = FS_IOC_GETFLAGS;
841 unsigned IOCTL_FS_IOC_GETVERSION = FS_IOC_GETVERSION;
842 unsigned IOCTL_FS_IOC_SETFLAGS = FS_IOC_SETFLAGS;
843 unsigned IOCTL_FS_IOC_SETVERSION = FS_IOC_SETVERSION;
897 unsigned IOCTL_FS_IOC_GETFLAGS = _IOR('f', 1, long);
898 unsigned IOCTL_FS_IOC_GETVERSION = _IOR('v', 1, long);
899 unsigned IOCTL_FS_IOC_SETFLAGS = _IOW('f', 2, long);
900 unsigned IOCTL_FS_IOC_SETVERSION = _IOW('v', 2, long);
844901 unsigned IOCTL_GIO_CMAP = GIO_CMAP;
845902 unsigned IOCTL_GIO_FONT = GIO_FONT;
846903 unsigned IOCTL_GIO_UNIMAP = GIO_UNIMAP;
......@@ -1035,7 +1092,7 @@ CHECK_SIZE_AND_OFFSET(mmsghdr, msg_len);
10351092
10361093COMPILER_CHECK(sizeof(__sanitizer_dirent) <= sizeof(dirent));
10371094CHECK_SIZE_AND_OFFSET(dirent, d_ino);
1038#if SANITIZER_MAC
1095#if SANITIZER_APPLE
10391096CHECK_SIZE_AND_OFFSET(dirent, d_seekoff);
10401097#elif SANITIZER_FREEBSD
10411098// There is no 'd_off' field on FreeBSD.
......@@ -1044,7 +1101,7 @@ CHECK_SIZE_AND_OFFSET(dirent, d_off);
10441101#endif
10451102CHECK_SIZE_AND_OFFSET(dirent, d_reclen);
10461103
1047#if SANITIZER_LINUX && !SANITIZER_ANDROID
1104#if SANITIZER_GLIBC
10481105COMPILER_CHECK(sizeof(__sanitizer_dirent64) <= sizeof(dirent64));
10491106CHECK_SIZE_AND_OFFSET(dirent64, d_ino);
10501107CHECK_SIZE_AND_OFFSET(dirent64, d_off);
......@@ -1077,6 +1134,15 @@ CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_flags);
10771134CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_restorer);
10781135#endif
10791136
1137#if SANITIZER_HAS_SIGINFO
1138COMPILER_CHECK(alignof(siginfo_t) == alignof(__sanitizer_siginfo));
1139using __sanitizer_siginfo_t = __sanitizer_siginfo;
1140CHECK_TYPE_SIZE(siginfo_t);
1141CHECK_SIZE_AND_OFFSET(siginfo_t, si_signo);
1142CHECK_SIZE_AND_OFFSET(siginfo_t, si_errno);
1143CHECK_SIZE_AND_OFFSET(siginfo_t, si_code);
1144#endif
1145
10801146#if SANITIZER_LINUX
10811147CHECK_TYPE_SIZE(__sysctl_args);
10821148CHECK_SIZE_AND_OFFSET(__sysctl_args, name);
......@@ -1217,7 +1283,7 @@ CHECK_SIZE_AND_OFFSET(passwd, pw_shell);
12171283CHECK_SIZE_AND_OFFSET(passwd, pw_gecos);
12181284#endif
12191285
1220#if SANITIZER_MAC
1286#if SANITIZER_APPLE
12211287CHECK_SIZE_AND_OFFSET(passwd, pw_change);
12221288CHECK_SIZE_AND_OFFSET(passwd, pw_expire);
12231289CHECK_SIZE_AND_OFFSET(passwd, pw_class);
......@@ -1230,7 +1296,7 @@ CHECK_SIZE_AND_OFFSET(group, gr_passwd);
12301296CHECK_SIZE_AND_OFFSET(group, gr_gid);
12311297CHECK_SIZE_AND_OFFSET(group, gr_mem);
12321298
1233#if HAVE_RPC_XDR_H
1299#if HAVE_RPC_XDR_H && !SANITIZER_APPLE
12341300CHECK_TYPE_SIZE(XDR);
12351301CHECK_SIZE_AND_OFFSET(XDR, x_op);
12361302CHECK_SIZE_AND_OFFSET(XDR, x_ops);
......@@ -1285,4 +1351,4 @@ CHECK_TYPE_SIZE(sem_t);
12851351COMPILER_CHECK(ARM_VFPREGS_SIZE == ARM_VFPREGS_SIZE_ASAN);
12861352#endif
12871353
1288#endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_MAC
1354#endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_APPLE
lib/tsan/sanitizer_common/sanitizer_platform_limits_posix.h+105-46
......@@ -14,10 +14,25 @@
1414#ifndef SANITIZER_PLATFORM_LIMITS_POSIX_H
1515#define SANITIZER_PLATFORM_LIMITS_POSIX_H
1616
17#if SANITIZER_LINUX || SANITIZER_MAC
17#if SANITIZER_LINUX || SANITIZER_APPLE
1818
1919#include "sanitizer_internal_defs.h"
2020#include "sanitizer_platform.h"
21#include "sanitizer_mallinfo.h"
22
23#if SANITIZER_APPLE
24#include <sys/cdefs.h>
25#if !__DARWIN_ONLY_64_BIT_INO_T
26#define SANITIZER_HAS_STAT64 1
27#define SANITIZER_HAS_STATFS64 1
28#else
29#define SANITIZER_HAS_STAT64 0
30#define SANITIZER_HAS_STATFS64 0
31#endif
32#elif SANITIZER_GLIBC || SANITIZER_ANDROID
33#define SANITIZER_HAS_STAT64 1
34#define SANITIZER_HAS_STATFS64 1
35#endif
2136
2237#if defined(__sparc__)
2338// FIXME: This can't be included from tsan which does not support sparc yet.
......@@ -29,7 +44,7 @@
2944namespace __sanitizer {
3045extern unsigned struct_utsname_sz;
3146extern unsigned struct_stat_sz;
32#if !SANITIZER_IOS
47#if SANITIZER_HAS_STAT64
3348extern unsigned struct_stat64_sz;
3449#endif
3550extern unsigned struct_rusage_sz;
......@@ -49,7 +64,9 @@ extern unsigned struct_itimerspec_sz;
4964extern unsigned struct_sigevent_sz;
5065extern unsigned struct_stack_t_sz;
5166extern unsigned struct_sched_param_sz;
67#if SANITIZER_HAS_STATFS64
5268extern unsigned struct_statfs64_sz;
69#endif
5370extern unsigned struct_regex_sz;
5471extern unsigned struct_regmatch_sz;
5572
......@@ -57,12 +74,12 @@ extern unsigned struct_regmatch_sz;
5774extern unsigned struct_fstab_sz;
5875extern unsigned struct_statfs_sz;
5976extern unsigned struct_sockaddr_sz;
60extern unsigned ucontext_t_sz;
61#endif // !SANITIZER_ANDROID
77unsigned ucontext_t_sz(void *uctx);
78# endif // !SANITIZER_ANDROID
6279
63#if SANITIZER_LINUX
80# if SANITIZER_LINUX
6481
65#if defined(__x86_64__)
82# if defined(__x86_64__)
6683const unsigned struct_kernel_stat_sz = 144;
6784const unsigned struct_kernel_stat64_sz = 0;
6885#elif defined(__i386__)
......@@ -81,9 +98,10 @@ const unsigned struct_kernel_stat64_sz = 104;
8198const unsigned struct_kernel_stat_sz = 144;
8299const unsigned struct_kernel_stat64_sz = 104;
83100#elif defined(__mips__)
84const unsigned struct_kernel_stat_sz = SANITIZER_ANDROID
85 ? FIRST_32_SECOND_64(104, 128)
86 : FIRST_32_SECOND_64(160, 216);
101const unsigned struct_kernel_stat_sz =
102 SANITIZER_ANDROID
103 ? FIRST_32_SECOND_64(104, 128)
104 : FIRST_32_SECOND_64((_MIPS_SIM == _ABIN32) ? 176 : 160, 216);
87105const unsigned struct_kernel_stat64_sz = 104;
88106#elif defined(__s390__) && !defined(__s390x__)
89107const unsigned struct_kernel_stat_sz = 64;
......@@ -102,7 +120,13 @@ const unsigned struct_kernel_stat64_sz = 104;
102120#elif SANITIZER_RISCV64
103121const unsigned struct_kernel_stat_sz = 128;
104122const unsigned struct_kernel_stat64_sz = 0; // RISCV64 does not use stat64
105#endif
123# elif defined(__hexagon__)
124const unsigned struct_kernel_stat_sz = 128;
125const unsigned struct_kernel_stat64_sz = 0;
126# elif defined(__loongarch__)
127const unsigned struct_kernel_stat_sz = 128;
128const unsigned struct_kernel_stat64_sz = 0;
129# endif
106130struct __sanitizer_perf_event_attr {
107131 unsigned type;
108132 unsigned size;
......@@ -112,7 +136,7 @@ struct __sanitizer_perf_event_attr {
112136extern unsigned struct_epoll_event_sz;
113137extern unsigned struct_sysinfo_sz;
114138extern unsigned __user_cap_header_struct_sz;
115extern unsigned __user_cap_data_struct_sz;
139extern unsigned __user_cap_data_struct_sz(void *hdrp);
116140extern unsigned struct_new_utsname_sz;
117141extern unsigned struct_old_utsname_sz;
118142extern unsigned struct_oldold_utsname_sz;
......@@ -122,7 +146,7 @@ const unsigned struct_kexec_segment_sz = 4 * sizeof(unsigned long);
122146
123147#if SANITIZER_LINUX
124148
125#if defined(__powerpc64__) || defined(__s390__)
149#if defined(__powerpc64__) || defined(__s390__) || defined(__loongarch__)
126150const unsigned struct___old_kernel_stat_sz = 0;
127151#elif !defined(__sparc__)
128152const unsigned struct___old_kernel_stat_sz = 32;
......@@ -181,17 +205,7 @@ struct __sanitizer_sem_t {
181205};
182206#endif // SANITIZER_LINUX
183207
184#if SANITIZER_ANDROID
185struct __sanitizer_struct_mallinfo {
186 uptr v[10];
187};
188#endif
189
190208#if SANITIZER_LINUX && !SANITIZER_ANDROID
191struct __sanitizer_struct_mallinfo {
192 int v[10];
193};
194
195209extern unsigned struct_ustat_sz;
196210extern unsigned struct_rlimit64_sz;
197211extern unsigned struct_statvfs64_sz;
......@@ -295,7 +309,6 @@ extern unsigned struct_msqid_ds_sz;
295309extern unsigned struct_mq_attr_sz;
296310extern unsigned struct_timex_sz;
297311extern unsigned struct_statvfs_sz;
298extern unsigned struct_crypt_data_sz;
299312#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
300313
301314struct __sanitizer_iovec {
......@@ -319,7 +332,7 @@ struct __sanitizer_ifaddrs {
319332};
320333#endif // !SANITIZER_ANDROID
321334
322#if SANITIZER_MAC
335#if SANITIZER_APPLE
323336typedef unsigned long __sanitizer_pthread_key_t;
324337#else
325338typedef unsigned __sanitizer_pthread_key_t;
......@@ -346,7 +359,7 @@ struct __sanitizer_passwd {
346359 char *pw_passwd;
347360 int pw_uid;
348361 int pw_gid;
349#if SANITIZER_MAC
362#if SANITIZER_APPLE
350363 long pw_change;
351364 char *pw_class;
352365#endif
......@@ -355,7 +368,7 @@ struct __sanitizer_passwd {
355368#endif
356369 char *pw_dir;
357370 char *pw_shell;
358#if SANITIZER_MAC
371#if SANITIZER_APPLE
359372 long pw_expire;
360373#endif
361374};
......@@ -367,7 +380,8 @@ struct __sanitizer_group {
367380 char **gr_mem;
368381};
369382
370#if defined(__x86_64__) && !defined(_LP64)
383# if (SANITIZER_LINUX && !SANITIZER_GLIBC && !SANITIZER_ANDROID) || \
384 (defined(__x86_64__) && !defined(_LP64)) || defined(__hexagon__)
371385typedef long long __sanitizer_time_t;
372386#else
373387typedef long __sanitizer_time_t;
......@@ -427,7 +441,7 @@ struct __sanitizer_file_handle {
427441};
428442#endif
429443
430#if SANITIZER_MAC
444#if SANITIZER_APPLE
431445struct __sanitizer_msghdr {
432446 void *msg_name;
433447 unsigned msg_namelen;
......@@ -468,30 +482,31 @@ struct __sanitizer_mmsghdr {
468482};
469483#endif
470484
471#if SANITIZER_MAC
485#if SANITIZER_APPLE
472486struct __sanitizer_dirent {
473487 unsigned long long d_ino;
474488 unsigned long long d_seekoff;
475489 unsigned short d_reclen;
476490 // more fields that we don't care about
477491};
478#elif SANITIZER_ANDROID || defined(__x86_64__)
492# elif (SANITIZER_LINUX && !SANITIZER_GLIBC) || defined(__x86_64__) || \
493 defined(__hexagon__)
479494struct __sanitizer_dirent {
480495 unsigned long long d_ino;
481496 unsigned long long d_off;
482497 unsigned short d_reclen;
483498 // more fields that we don't care about
484499};
485#else
500# else
486501struct __sanitizer_dirent {
487502 uptr d_ino;
488503 uptr d_off;
489504 unsigned short d_reclen;
490505 // more fields that we don't care about
491506};
492#endif
507# endif
493508
494#if SANITIZER_LINUX && !SANITIZER_ANDROID
509# if SANITIZER_GLIBC
495510struct __sanitizer_dirent64 {
496511 unsigned long long d_ino;
497512 unsigned long long d_off;
......@@ -511,8 +526,8 @@ typedef int __sanitizer_clockid_t;
511526#endif
512527
513528#if SANITIZER_LINUX
514#if defined(_LP64) || defined(__x86_64__) || defined(__powerpc__) || \
515 defined(__mips__)
529# if defined(_LP64) || defined(__x86_64__) || defined(__powerpc__) || \
530 defined(__mips__) || defined(__hexagon__)
516531typedef unsigned __sanitizer___kernel_uid_t;
517532typedef unsigned __sanitizer___kernel_gid_t;
518533#else
......@@ -552,7 +567,7 @@ typedef unsigned long __sanitizer_sigset_t[16 / sizeof(unsigned long)];
552567# else
553568typedef unsigned long __sanitizer_sigset_t;
554569# endif
555#elif SANITIZER_MAC
570#elif SANITIZER_APPLE
556571typedef unsigned __sanitizer_sigset_t;
557572#elif SANITIZER_LINUX
558573struct __sanitizer_sigset_t {
......@@ -561,10 +576,35 @@ struct __sanitizer_sigset_t {
561576};
562577#endif
563578
564struct __sanitizer_siginfo {
565 // The size is determined by looking at sizeof of real siginfo_t on linux.
566 u64 opaque[128 / sizeof(u64)];
579struct __sanitizer_siginfo_pad {
580#if SANITIZER_X32
581 // x32 siginfo_t is aligned to 8 bytes.
582 u64 pad[128 / sizeof(u64)];
583#else
584 // Require uptr, because siginfo_t is always pointer-size aligned on Linux.
585 uptr pad[128 / sizeof(uptr)];
586#endif
587};
588
589#if SANITIZER_LINUX
590# define SANITIZER_HAS_SIGINFO 1
591union __sanitizer_siginfo {
592 struct {
593 int si_signo;
594# if SANITIZER_MIPS
595 int si_code;
596 int si_errno;
597# else
598 int si_errno;
599 int si_code;
600# endif
601 };
602 __sanitizer_siginfo_pad pad;
567603};
604#else
605# define SANITIZER_HAS_SIGINFO 0
606typedef __sanitizer_siginfo_pad __sanitizer_siginfo;
607#endif
568608
569609using __sanitizer_sighandler_ptr = void (*)(int sig);
570610using __sanitizer_sigactionhandler_ptr = void (*)(int sig,
......@@ -712,12 +752,19 @@ struct __sanitizer_protoent {
712752 int p_proto;
713753};
714754
755struct __sanitizer_netent {
756 char *n_name;
757 char **n_aliases;
758 int n_addrtype;
759 u32 n_net;
760};
761
715762struct __sanitizer_addrinfo {
716763 int ai_flags;
717764 int ai_family;
718765 int ai_socktype;
719766 int ai_protocol;
720#if SANITIZER_ANDROID || SANITIZER_MAC
767#if SANITIZER_ANDROID || SANITIZER_APPLE
721768 unsigned ai_addrlen;
722769 char *ai_canonname;
723770 void *ai_addr;
......@@ -743,7 +790,7 @@ struct __sanitizer_pollfd {
743790 short revents;
744791};
745792
746#if SANITIZER_ANDROID || SANITIZER_MAC
793#if SANITIZER_ANDROID || SANITIZER_APPLE
747794typedef unsigned __sanitizer_nfds_t;
748795#else
749796typedef unsigned long __sanitizer_nfds_t;
......@@ -773,6 +820,10 @@ extern int glob_altdirfunc;
773820
774821extern unsigned path_max;
775822
823# if !SANITIZER_ANDROID
824extern const int wordexp_wrde_dooffs;
825# endif // !SANITIZER_ANDROID
826
776827struct __sanitizer_wordexp_t {
777828 uptr we_wordc;
778829 char **we_wordv;
......@@ -806,7 +857,7 @@ typedef void __sanitizer_FILE;
806857#if SANITIZER_LINUX && !SANITIZER_ANDROID && \
807858 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
808859 defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \
809 defined(__s390__) || SANITIZER_RISCV64)
860 defined(__s390__) || defined(__loongarch__) || SANITIZER_RISCV64)
810861extern unsigned struct_user_regs_struct_sz;
811862extern unsigned struct_user_fpregs_struct_sz;
812863extern unsigned struct_user_fpxregs_struct_sz;
......@@ -839,7 +890,7 @@ extern int shmctl_shm_info;
839890extern int shmctl_shm_stat;
840891#endif
841892
842#if !SANITIZER_MAC && !SANITIZER_FREEBSD
893#if !SANITIZER_APPLE && !SANITIZER_FREEBSD
843894extern unsigned struct_utmp_sz;
844895#endif
845896#if !SANITIZER_ANDROID
......@@ -854,7 +905,7 @@ struct __sanitizer_ifconf {
854905 union {
855906 void *ifcu_req;
856907 } ifc_ifcu;
857#if SANITIZER_MAC
908#if SANITIZER_APPLE
858909} __attribute__((packed));
859910#else
860911};
......@@ -1007,7 +1058,7 @@ extern unsigned struct_audio_buf_info_sz;
10071058extern unsigned struct_ppp_stats_sz;
10081059#endif // (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
10091060
1010#if !SANITIZER_ANDROID && !SANITIZER_MAC
1061#if !SANITIZER_ANDROID && !SANITIZER_APPLE
10111062extern unsigned struct_sioc_sg_req_sz;
10121063extern unsigned struct_sioc_vif_req_sz;
10131064#endif
......@@ -1094,6 +1145,14 @@ extern unsigned IOCTL_BLKRASET;
10941145extern unsigned IOCTL_BLKROGET;
10951146extern unsigned IOCTL_BLKROSET;
10961147extern unsigned IOCTL_BLKRRPART;
1148extern unsigned IOCTL_BLKFRASET;
1149extern unsigned IOCTL_BLKFRAGET;
1150extern unsigned IOCTL_BLKSECTSET;
1151extern unsigned IOCTL_BLKSECTGET;
1152extern unsigned IOCTL_BLKSSZGET;
1153extern unsigned IOCTL_BLKBSZGET;
1154extern unsigned IOCTL_BLKBSZSET;
1155extern unsigned IOCTL_BLKGETSIZE64;
10971156extern unsigned IOCTL_CDROMAUDIOBUFSIZ;
10981157extern unsigned IOCTL_CDROMEJECT;
10991158extern unsigned IOCTL_CDROMEJECT_SW;
......@@ -1440,6 +1499,6 @@ extern const int si_SEGV_ACCERR;
14401499
14411500#define SIGACTION_SYMNAME sigaction
14421501
1443#endif // SANITIZER_LINUX || SANITIZER_MAC
1502#endif // SANITIZER_LINUX || SANITIZER_APPLE
14441503
14451504#endif
lib/tsan/sanitizer_common/sanitizer_platform_limits_solaris.cpp+2-1
......@@ -89,7 +89,7 @@ namespace __sanitizer {
8989 unsigned struct_sched_param_sz = sizeof(struct sched_param);
9090 unsigned struct_statfs_sz = sizeof(struct statfs);
9191 unsigned struct_sockaddr_sz = sizeof(struct sockaddr);
92 unsigned ucontext_t_sz = sizeof(ucontext_t);
92 unsigned ucontext_t_sz(void *ctx) { return sizeof(ucontext_t); }
9393 unsigned struct_timespec_sz = sizeof(struct timespec);
9494#if SANITIZER_SOLARIS32
9595 unsigned struct_statvfs64_sz = sizeof(struct statvfs64);
......@@ -123,6 +123,7 @@ namespace __sanitizer {
123123 unsigned struct_ElfW_Phdr_sz = sizeof(ElfW(Phdr));
124124
125125 int glob_nomatch = GLOB_NOMATCH;
126 const int wordexp_wrde_dooffs = WRDE_DOOFFS;
126127
127128 unsigned path_max = PATH_MAX;
128129
lib/tsan/sanitizer_common/sanitizer_platform_limits_solaris.h+2-1
......@@ -43,7 +43,7 @@ extern unsigned struct_sched_param_sz;
4343extern unsigned struct_statfs64_sz;
4444extern unsigned struct_statfs_sz;
4545extern unsigned struct_sockaddr_sz;
46extern unsigned ucontext_t_sz;
46unsigned ucontext_t_sz(void *ctx);
4747
4848extern unsigned struct_timespec_sz;
4949extern unsigned struct_rlimit_sz;
......@@ -341,6 +341,7 @@ struct __sanitizer_glob_t {
341341
342342extern int glob_nomatch;
343343extern int glob_altdirfunc;
344extern const int wordexp_wrde_dooffs;
344345
345346extern unsigned path_max;
346347
lib/tsan/sanitizer_common/sanitizer_posix.cpp+21-9
......@@ -41,6 +41,8 @@ uptr GetMmapGranularity() {
4141 return GetPageSize();
4242}
4343
44bool ErrorIsOOM(error_t err) { return err == ENOMEM; }
45
4446void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) {
4547 size = RoundUpTo(size, GetPageSizeCached());
4648 uptr res = MmapNamed(nullptr, size, PROT_READ | PROT_WRITE,
......@@ -55,11 +57,9 @@ void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) {
5557void UnmapOrDie(void *addr, uptr size) {
5658 if (!addr || !size) return;
5759 uptr res = internal_munmap(addr, size);
58 if (UNLIKELY(internal_iserror(res))) {
59 Report("ERROR: %s failed to deallocate 0x%zx (%zd) bytes at address %p\n",
60 SanitizerToolName, size, size, addr);
61 CHECK("unable to unmap" && 0);
62 }
60 int reserrno;
61 if (UNLIKELY(internal_iserror(res, &reserrno)))
62 ReportMunmapFailureAndDie(addr, size, reserrno);
6363 DecreaseTotalMmap(size);
6464}
6565
......@@ -85,18 +85,26 @@ void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
8585 CHECK(IsPowerOfTwo(size));
8686 CHECK(IsPowerOfTwo(alignment));
8787 uptr map_size = size + alignment;
88 // mmap maps entire pages and rounds up map_size needs to be a an integral
89 // number of pages.
90 // We need to be aware of this size for calculating end and for unmapping
91 // fragments before and after the alignment region.
92 map_size = RoundUpTo(map_size, GetPageSizeCached());
8893 uptr map_res = (uptr)MmapOrDieOnFatalError(map_size, mem_type);
8994 if (UNLIKELY(!map_res))
9095 return nullptr;
91 uptr map_end = map_res + map_size;
9296 uptr res = map_res;
9397 if (!IsAligned(res, alignment)) {
9498 res = (map_res + alignment - 1) & ~(alignment - 1);
9599 UnmapOrDie((void*)map_res, res - map_res);
96100 }
101 uptr map_end = map_res + map_size;
97102 uptr end = res + size;
98 if (end != map_end)
103 end = RoundUpTo(end, GetPageSizeCached());
104 if (end != map_end) {
105 CHECK_LT(end, map_end);
99106 UnmapOrDie((void*)end, map_end - end);
107 }
100108 return (void*)res;
101109}
102110
......@@ -146,7 +154,11 @@ bool MprotectReadOnly(uptr addr, uptr size) {
146154 return 0 == internal_mprotect((void *)addr, size, PROT_READ);
147155}
148156
149#if !SANITIZER_MAC
157bool MprotectReadWrite(uptr addr, uptr size) {
158 return 0 == internal_mprotect((void *)addr, size, PROT_READ | PROT_WRITE);
159}
160
161#if !SANITIZER_APPLE
150162void MprotectMallocZones(void *addr, int prot) {}
151163#endif
152164
......@@ -239,7 +251,7 @@ bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
239251 return true;
240252}
241253
242#if !SANITIZER_MAC
254#if !SANITIZER_APPLE
243255void DumpProcessMap() {
244256 MemoryMappingLayout proc_maps(/*cache_enabled*/true);
245257 const sptr kBufSize = 4095;
lib/tsan/sanitizer_common/sanitizer_posix.h+7-5
......@@ -20,10 +20,7 @@
2020#include "sanitizer_platform_limits_posix.h"
2121#include "sanitizer_platform_limits_solaris.h"
2222
23#if !SANITIZER_POSIX
24// Make it hard to accidentally use any of functions declared in this file:
25#error This file should only be included on POSIX
26#endif
23#if SANITIZER_POSIX
2724
2825namespace __sanitizer {
2926
......@@ -93,7 +90,7 @@ int real_pthread_join(void *th, void **ret);
9390 } \
9491 } // namespace __sanitizer
9592
96int my_pthread_attr_getstack(void *attr, void **addr, uptr *size);
93int internal_pthread_attr_getstack(void *attr, void **addr, uptr *size);
9794
9895// A routine named real_sigaction() must be implemented by each sanitizer in
9996// order for internal_sigaction() to bypass interceptors.
......@@ -123,7 +120,12 @@ int GetNamedMappingFd(const char *name, uptr size, int *flags);
123120// alive at least as long as the mapping exists.
124121void DecorateMapping(uptr addr, uptr size, const char *name);
125122
123# if !SANITIZER_FREEBSD
124# define __sanitizer_dirsiz(dp) ((dp)->d_reclen)
125# endif
126126
127127} // namespace __sanitizer
128128
129#endif // SANITIZER_POSIX
130
129131#endif // SANITIZER_POSIX_H
lib/tsan/sanitizer_common/sanitizer_posix_libcdep.cpp+6-4
......@@ -151,6 +151,8 @@ int Atexit(void (*function)(void)) {
151151#endif
152152}
153153
154bool CreateDir(const char *pathname) { return mkdir(pathname, 0755) == 0; }
155
154156bool SupportsColoredOutput(fd_t fd) {
155157 return isatty(fd) != 0;
156158}
......@@ -288,7 +290,7 @@ bool IsAccessibleMemoryRange(uptr beg, uptr size) {
288290 return result;
289291}
290292
291void PlatformPrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
293void PlatformPrepareForSandboxing(void *args) {
292294 // Some kinds of sandboxes may forbid filesystem access, so we won't be able
293295 // to read the file mappings from /proc/self/maps. Luckily, neither the
294296 // process will be able to load additional libraries, so it's fine to use the
......@@ -381,8 +383,8 @@ SANITIZER_WEAK_ATTRIBUTE int
381383real_pthread_attr_getstack(void *attr, void **addr, size_t *size);
382384} // extern "C"
383385
384int my_pthread_attr_getstack(void *attr, void **addr, uptr *size) {
385#if !SANITIZER_GO && !SANITIZER_MAC
386int internal_pthread_attr_getstack(void *attr, void **addr, uptr *size) {
387#if !SANITIZER_GO && !SANITIZER_APPLE
386388 if (&real_pthread_attr_getstack)
387389 return real_pthread_attr_getstack((pthread_attr_t *)attr, addr,
388390 (size_t *)size);
......@@ -395,7 +397,7 @@ void AdjustStackSize(void *attr_) {
395397 pthread_attr_t *attr = (pthread_attr_t *)attr_;
396398 uptr stackaddr = 0;
397399 uptr stacksize = 0;
398 my_pthread_attr_getstack(attr, (void**)&stackaddr, &stacksize);
400 internal_pthread_attr_getstack(attr, (void **)&stackaddr, &stacksize);
399401 // GLibC will return (0 - stacksize) as the stack address in the case when
400402 // stacksize is set, but stackaddr is not.
401403 bool stack_set = (stackaddr != 0) && (stackaddr + stacksize != 0);
lib/tsan/sanitizer_common/sanitizer_printf.cpp+13-24
......@@ -20,10 +20,6 @@
2020#include <stdio.h>
2121#include <stdarg.h>
2222
23#if defined(__x86_64__)
24# include <emmintrin.h>
25#endif
26
2723#if SANITIZER_WINDOWS && defined(_MSC_VER) && _MSC_VER < 1800 && \
2824 !defined(va_copy)
2925# define va_copy(dst, src) ((dst) = (src))
......@@ -132,8 +128,8 @@ static int AppendPointer(char **buff, const char *buff_end, u64 ptr_value) {
132128int VSNPrintf(char *buff, int buff_length,
133129 const char *format, va_list args) {
134130 static const char *kPrintfFormatsHelp =
135 "Supported Printf formats: %([0-9]*)?(z|ll)?{d,u,x,X,V}; %p; "
136 "%[-]([0-9]*)?(\\.\\*)?s; %c\n";
131 "Supported Printf formats: %([0-9]*)?(z|l|ll)?{d,u,x,X}; %p; "
132 "%[-]([0-9]*)?(\\.\\*)?s; %c\nProvided format: ";
137133 RAW_CHECK(format);
138134 RAW_CHECK(buff_length > 0);
139135 const char *buff_end = &buff[buff_length - 1];
......@@ -164,9 +160,11 @@ int VSNPrintf(char *buff, int buff_length,
164160 }
165161 bool have_z = (*cur == 'z');
166162 cur += have_z;
167 bool have_ll = !have_z && (cur[0] == 'l' && cur[1] == 'l');
163 bool have_l = cur[0] == 'l' && cur[1] != 'l';
164 cur += have_l;
165 bool have_ll = cur[0] == 'l' && cur[1] == 'l';
168166 cur += have_ll * 2;
169 const bool have_length = have_z || have_ll;
167 const bool have_length = have_z || have_l || have_ll;
170168 const bool have_flags = have_width || have_length;
171169 // At the moment only %s supports precision and left-justification.
172170 CHECK(!((precision >= 0 || left_justified) && *cur != 's'));
......@@ -174,6 +172,7 @@ int VSNPrintf(char *buff, int buff_length,
174172 case 'd': {
175173 s64 dval = have_ll ? va_arg(args, s64)
176174 : have_z ? va_arg(args, sptr)
175 : have_l ? va_arg(args, long)
177176 : va_arg(args, int);
178177 result += AppendSignedDecimal(&buff, buff_end, dval, width,
179178 pad_with_zero);
......@@ -184,26 +183,20 @@ int VSNPrintf(char *buff, int buff_length,
184183 case 'X': {
185184 u64 uval = have_ll ? va_arg(args, u64)
186185 : have_z ? va_arg(args, uptr)
186 : have_l ? va_arg(args, unsigned long)
187187 : va_arg(args, unsigned);
188188 bool uppercase = (*cur == 'X');
189189 result += AppendUnsigned(&buff, buff_end, uval, (*cur == 'u') ? 10 : 16,
190190 width, pad_with_zero, uppercase);
191191 break;
192192 }
193 case 'V': {
194 for (uptr i = 0; i < 16; i++) {
195 unsigned x = va_arg(args, unsigned);
196 result += AppendUnsigned(&buff, buff_end, x, 16, 2, true, false);
197 }
198 break;
199 }
200193 case 'p': {
201 RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp);
194 RAW_CHECK_VA(!have_flags, kPrintfFormatsHelp, format);
202195 result += AppendPointer(&buff, buff_end, va_arg(args, uptr));
203196 break;
204197 }
205198 case 's': {
206 RAW_CHECK_MSG(!have_length, kPrintfFormatsHelp);
199 RAW_CHECK_VA(!have_length, kPrintfFormatsHelp, format);
207200 // Only left-justified width is supported.
208201 CHECK(!have_width || left_justified);
209202 result += AppendString(&buff, buff_end, left_justified ? -width : width,
......@@ -211,17 +204,17 @@ int VSNPrintf(char *buff, int buff_length,
211204 break;
212205 }
213206 case 'c': {
214 RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp);
207 RAW_CHECK_VA(!have_flags, kPrintfFormatsHelp, format);
215208 result += AppendChar(&buff, buff_end, va_arg(args, int));
216209 break;
217210 }
218211 case '%' : {
219 RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp);
212 RAW_CHECK_VA(!have_flags, kPrintfFormatsHelp, format);
220213 result += AppendChar(&buff, buff_end, '%');
221214 break;
222215 }
223216 default: {
224 RAW_CHECK_MSG(false, kPrintfFormatsHelp);
217 RAW_CHECK_VA(false, kPrintfFormatsHelp, format);
225218 }
226219 }
227220 }
......@@ -317,7 +310,6 @@ static void NOINLINE SharedPrintfCode(bool append_pid, const char *format,
317310 format, args);
318311}
319312
320FORMAT(1, 2)
321313void Printf(const char *format, ...) {
322314 va_list args;
323315 va_start(args, format);
......@@ -326,7 +318,6 @@ void Printf(const char *format, ...) {
326318}
327319
328320// Like Printf, but prints the current PID before the output string.
329FORMAT(1, 2)
330321void Report(const char *format, ...) {
331322 va_list args;
332323 va_start(args, format);
......@@ -338,7 +329,6 @@ void Report(const char *format, ...) {
338329// Returns the number of symbols that should have been written to buffer
339330// (not including trailing '\0'). Thus, the string is truncated
340331// iff return value is not less than "length".
341FORMAT(3, 4)
342332int internal_snprintf(char *buffer, uptr length, const char *format, ...) {
343333 va_list args;
344334 va_start(args, format);
......@@ -347,7 +337,6 @@ int internal_snprintf(char *buffer, uptr length, const char *format, ...) {
347337 return needed_length;
348338}
349339
350FORMAT(2, 3)
351340void InternalScopedString::append(const char *format, ...) {
352341 uptr prev_len = length();
353342
lib/tsan/sanitizer_common/sanitizer_procmaps.h+35-7
......@@ -16,7 +16,7 @@
1616#include "sanitizer_platform.h"
1717
1818#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
19 SANITIZER_MAC || SANITIZER_SOLARIS || \
19 SANITIZER_APPLE || SANITIZER_SOLARIS || \
2020 SANITIZER_FUCHSIA
2121
2222#include "sanitizer_common.h"
......@@ -65,13 +65,37 @@ class MemoryMappedSegment {
6565 MemoryMappedSegmentData *data_;
6666};
6767
68class MemoryMappingLayout {
68struct ImageHeader;
69
70class MemoryMappingLayoutBase {
71 public:
72 virtual bool Next(MemoryMappedSegment *segment) { UNIMPLEMENTED(); }
73 virtual bool Error() const { UNIMPLEMENTED(); };
74 virtual void Reset() { UNIMPLEMENTED(); }
75
76 protected:
77 ~MemoryMappingLayoutBase() {}
78};
79
80class MemoryMappingLayout : public MemoryMappingLayoutBase {
6981 public:
7082 explicit MemoryMappingLayout(bool cache_enabled);
83
84// This destructor cannot be virtual, as it would cause an operator new() linking
85// failures in hwasan test cases. However non-virtual destructors emit warnings
86// in macOS build, hence disabling those
87#ifdef __clang__
88#pragma clang diagnostic push
89#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
90#endif
7191 ~MemoryMappingLayout();
72 bool Next(MemoryMappedSegment *segment);
73 bool Error() const;
74 void Reset();
92#ifdef __clang__
93#pragma clang diagnostic pop
94#endif
95
96 virtual bool Next(MemoryMappedSegment *segment) override;
97 virtual bool Error() const override;
98 virtual void Reset() override;
7599 // In some cases, e.g. when running under a sandbox on Linux, ASan is unable
76100 // to obtain the memory mappings. It should fall back to pre-cached data
77101 // instead of aborting.
......@@ -80,10 +104,14 @@ class MemoryMappingLayout {
80104 // Adds all mapped objects into a vector.
81105 void DumpListOfModules(InternalMmapVectorNoCtor<LoadedModule> *modules);
82106
107 protected:
108#if SANITIZER_APPLE
109 virtual const ImageHeader *CurrentImageHeader();
110#endif
111 MemoryMappingLayoutData data_;
112
83113 private:
84114 void LoadFromCache();
85
86 MemoryMappingLayoutData data_;
87115};
88116
89117// Returns code range for the specified module.
lib/tsan/sanitizer_common/sanitizer_procmaps_bsd.cpp+16
......@@ -39,6 +39,22 @@
3939
4040namespace __sanitizer {
4141
42#if SANITIZER_FREEBSD
43void GetMemoryProfile(fill_profile_f cb, uptr *stats) {
44 const int Mib[] = {
45 CTL_KERN,
46 KERN_PROC,
47 KERN_PROC_PID,
48 getpid()
49 };
50
51 struct kinfo_proc InfoProc;
52 uptr Len = sizeof(InfoProc);
53 CHECK_EQ(internal_sysctl(Mib, ARRAY_SIZE(Mib), nullptr, (uptr *)&InfoProc, &Len, 0), 0);
54 cb(0, InfoProc.ki_rssize * GetPageSizeCached(), false, stats);
55}
56#endif
57
4258void ReadProcMaps(ProcSelfMapsBuff *proc_maps) {
4359 const int Mib[] = {
4460#if SANITIZER_FREEBSD
lib/tsan/sanitizer_common/sanitizer_procmaps_common.cpp+23-5
......@@ -145,29 +145,47 @@ void MemoryMappingLayout::DumpListOfModules(
145145 }
146146}
147147
148void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) {
148#if SANITIZER_LINUX || SANITIZER_ANDROID || SANITIZER_SOLARIS || SANITIZER_NETBSD
149void GetMemoryProfile(fill_profile_f cb, uptr *stats) {
149150 char *smaps = nullptr;
150151 uptr smaps_cap = 0;
151152 uptr smaps_len = 0;
152153 if (!ReadFileToBuffer("/proc/self/smaps", &smaps, &smaps_cap, &smaps_len))
153154 return;
155 ParseUnixMemoryProfile(cb, stats, smaps, smaps_len);
156 UnmapOrDie(smaps, smaps_cap);
157}
158
159void ParseUnixMemoryProfile(fill_profile_f cb, uptr *stats, char *smaps,
160 uptr smaps_len) {
154161 uptr start = 0;
155162 bool file = false;
156163 const char *pos = smaps;
157 while (pos < smaps + smaps_len) {
164 char *end = smaps + smaps_len;
165 if (smaps_len < 2)
166 return;
167 // The following parsing can crash on almost every line
168 // in the case of malformed/truncated input.
169 // Fixing that is hard b/c e.g. ParseDecimal does not
170 // even accept end of the buffer and assumes well-formed input.
171 // So instead we patch end of the input a bit,
172 // it does not affect well-formed complete inputs.
173 *--end = 0;
174 *--end = '\n';
175 while (pos < end) {
158176 if (IsHex(pos[0])) {
159177 start = ParseHex(&pos);
160178 for (; *pos != '/' && *pos > '\n'; pos++) {}
161179 file = *pos == '/';
162180 } else if (internal_strncmp(pos, "Rss:", 4) == 0) {
163 while (!IsDecimal(*pos)) pos++;
181 while (pos < end && !IsDecimal(*pos)) pos++;
164182 uptr rss = ParseDecimal(&pos) * 1024;
165 cb(start, rss, file, stats, stats_size);
183 cb(start, rss, file, stats);
166184 }
167185 while (*pos++ != '\n') {}
168186 }
169 UnmapOrDie(smaps, smaps_cap);
170187}
188#endif
171189
172190} // namespace __sanitizer
173191
lib/tsan/sanitizer_common/sanitizer_procmaps_mac.cpp+91-17
......@@ -10,7 +10,7 @@
1010//===----------------------------------------------------------------------===//
1111
1212#include "sanitizer_platform.h"
13#if SANITIZER_MAC
13#if SANITIZER_APPLE
1414#include "sanitizer_common.h"
1515#include "sanitizer_placement_new.h"
1616#include "sanitizer_procmaps.h"
......@@ -136,29 +136,34 @@ void MemoryMappingLayout::LoadFromCache() {
136136 // No-op on Mac for now.
137137}
138138
139static bool IsDyldHdr(const mach_header *hdr) {
140 return (hdr->magic == MH_MAGIC || hdr->magic == MH_MAGIC_64) &&
141 hdr->filetype == MH_DYLINKER;
142}
143
139144// _dyld_get_image_header() and related APIs don't report dyld itself.
140145// We work around this by manually recursing through the memory map
141146// until we hit a Mach header matching dyld instead. These recurse
142147// calls are expensive, but the first memory map generation occurs
143148// early in the process, when dyld is one of the only images loaded,
144// so it will be hit after only a few iterations.
145static mach_header *get_dyld_image_header() {
146 unsigned depth = 1;
147 vm_size_t size = 0;
149// so it will be hit after only a few iterations. These assumptions don't hold
150// on macOS 13+ anymore (dyld itself has moved into the shared cache).
151static mach_header *GetDyldImageHeaderViaVMRegion() {
148152 vm_address_t address = 0;
149 kern_return_t err = KERN_SUCCESS;
150 mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64;
151153
152154 while (true) {
155 vm_size_t size = 0;
156 unsigned depth = 1;
153157 struct vm_region_submap_info_64 info;
154 err = vm_region_recurse_64(mach_task_self(), &address, &size, &depth,
155 (vm_region_info_t)&info, &count);
158 mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64;
159 kern_return_t err =
160 vm_region_recurse_64(mach_task_self(), &address, &size, &depth,
161 (vm_region_info_t)&info, &count);
156162 if (err != KERN_SUCCESS) return nullptr;
157163
158164 if (size >= sizeof(mach_header) && info.protection & kProtectionRead) {
159165 mach_header *hdr = (mach_header *)address;
160 if ((hdr->magic == MH_MAGIC || hdr->magic == MH_MAGIC_64) &&
161 hdr->filetype == MH_DYLINKER) {
166 if (IsDyldHdr(hdr)) {
162167 return hdr;
163168 }
164169 }
......@@ -166,8 +171,69 @@ static mach_header *get_dyld_image_header() {
166171 }
167172}
168173
174extern "C" {
175struct dyld_shared_cache_dylib_text_info {
176 uint64_t version; // current version 2
177 // following fields all exist in version 1
178 uint64_t loadAddressUnslid;
179 uint64_t textSegmentSize;
180 uuid_t dylibUuid;
181 const char *path; // pointer invalid at end of iterations
182 // following fields all exist in version 2
183 uint64_t textSegmentOffset; // offset from start of cache
184};
185typedef struct dyld_shared_cache_dylib_text_info
186 dyld_shared_cache_dylib_text_info;
187
188extern bool _dyld_get_shared_cache_uuid(uuid_t uuid);
189extern const void *_dyld_get_shared_cache_range(size_t *length);
190extern int dyld_shared_cache_iterate_text(
191 const uuid_t cacheUuid,
192 void (^callback)(const dyld_shared_cache_dylib_text_info *info));
193} // extern "C"
194
195static mach_header *GetDyldImageHeaderViaSharedCache() {
196 uuid_t uuid;
197 bool hasCache = _dyld_get_shared_cache_uuid(uuid);
198 if (!hasCache)
199 return nullptr;
200
201 size_t cacheLength;
202 __block uptr cacheStart = (uptr)_dyld_get_shared_cache_range(&cacheLength);
203 CHECK(cacheStart && cacheLength);
204
205 __block mach_header *dyldHdr = nullptr;
206 int res = dyld_shared_cache_iterate_text(
207 uuid, ^(const dyld_shared_cache_dylib_text_info *info) {
208 CHECK_GE(info->version, 2);
209 mach_header *hdr =
210 (mach_header *)(cacheStart + info->textSegmentOffset);
211 if (IsDyldHdr(hdr))
212 dyldHdr = hdr;
213 });
214 CHECK_EQ(res, 0);
215
216 return dyldHdr;
217}
218
169219const mach_header *get_dyld_hdr() {
170 if (!dyld_hdr) dyld_hdr = get_dyld_image_header();
220 if (!dyld_hdr) {
221 // On macOS 13+, dyld itself has moved into the shared cache. Looking it up
222 // via vm_region_recurse_64() causes spins/hangs/crashes.
223 if (GetMacosAlignedVersion() >= MacosVersion(13, 0)) {
224 dyld_hdr = GetDyldImageHeaderViaSharedCache();
225 if (!dyld_hdr) {
226 VReport(1,
227 "Failed to lookup the dyld image header in the shared cache on "
228 "macOS 13+ (or no shared cache in use). Falling back to "
229 "lookup via vm_region_recurse_64().\n");
230 dyld_hdr = GetDyldImageHeaderViaVMRegion();
231 }
232 } else {
233 dyld_hdr = GetDyldImageHeaderViaVMRegion();
234 }
235 CHECK(dyld_hdr);
236 }
171237
172238 return dyld_hdr;
173239}
......@@ -184,7 +250,9 @@ static bool NextSegmentLoad(MemoryMappedSegment *segment,
184250 MemoryMappedSegmentData *seg_data,
185251 MemoryMappingLayoutData *layout_data) {
186252 const char *lc = layout_data->current_load_cmd_addr;
253
187254 layout_data->current_load_cmd_addr += ((const load_command *)lc)->cmdsize;
255 layout_data->current_load_cmd_count--;
188256 if (((const load_command *)lc)->cmd == kLCSegment) {
189257 const SegmentCommand* sc = (const SegmentCommand *)lc;
190258 uptr base_virt_addr, addr_mask;
......@@ -292,11 +360,16 @@ static bool IsModuleInstrumented(const load_command *first_lc) {
292360 return false;
293361}
294362
363const ImageHeader *MemoryMappingLayout::CurrentImageHeader() {
364 const mach_header *hdr = (data_.current_image == kDyldImageIdx)
365 ? get_dyld_hdr()
366 : _dyld_get_image_header(data_.current_image);
367 return (const ImageHeader *)hdr;
368}
369
295370bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
296371 for (; data_.current_image >= kDyldImageIdx; data_.current_image--) {
297 const mach_header *hdr = (data_.current_image == kDyldImageIdx)
298 ? get_dyld_hdr()
299 : _dyld_get_image_header(data_.current_image);
372 const mach_header *hdr = (const mach_header *)CurrentImageHeader();
300373 if (!hdr) continue;
301374 if (data_.current_load_cmd_count < 0) {
302375 // Set up for this image;
......@@ -326,7 +399,7 @@ bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
326399 (const load_command *)data_.current_load_cmd_addr);
327400 }
328401
329 for (; data_.current_load_cmd_count >= 0; data_.current_load_cmd_count--) {
402 while (data_.current_load_cmd_count > 0) {
330403 switch (data_.current_magic) {
331404 // data_.current_magic may be only one of MH_MAGIC, MH_MAGIC_64.
332405#ifdef MH_MAGIC_64
......@@ -347,6 +420,7 @@ bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
347420 }
348421 // If we get here, no more load_cmd's in this image talk about
349422 // segments. Go on to the next image.
423 data_.current_load_cmd_count = -1; // This will trigger loading next image
350424 }
351425 return false;
352426}
......@@ -376,4 +450,4 @@ void MemoryMappingLayout::DumpListOfModules(
376450
377451} // namespace __sanitizer
378452
379#endif // SANITIZER_MAC
453#endif // SANITIZER_APPLE
lib/tsan/sanitizer_common/sanitizer_procmaps_solaris.cpp+37-13
......@@ -13,21 +13,30 @@
1313#undef _FILE_OFFSET_BITS
1414#include "sanitizer_platform.h"
1515#if SANITIZER_SOLARIS
16#include "sanitizer_common.h"
17#include "sanitizer_procmaps.h"
16# include <fcntl.h>
17# include <limits.h>
18# include <procfs.h>
1819
19#include <procfs.h>
20#include <limits.h>
20# include "sanitizer_common.h"
21# include "sanitizer_procmaps.h"
2122
2223namespace __sanitizer {
2324
2425void ReadProcMaps(ProcSelfMapsBuff *proc_maps) {
25 if (!ReadFileToBuffer("/proc/self/xmap", &proc_maps->data,
26 &proc_maps->mmaped_size, &proc_maps->len)) {
27 proc_maps->data = nullptr;
28 proc_maps->mmaped_size = 0;
29 proc_maps->len = 0;
30 }
26 uptr fd = internal_open("/proc/self/xmap", O_RDONLY);
27 CHECK_NE(fd, -1);
28 uptr Size = internal_filesize(fd);
29 CHECK_GT(Size, 0);
30
31 // Allow for additional entries by following mmap.
32 size_t MmapedSize = Size * 4 / 3;
33 void *VmMap = MmapOrDie(MmapedSize, "ReadProcMaps()");
34 Size = internal_read(fd, VmMap, MmapedSize);
35 CHECK_NE(Size, -1);
36 internal_close(fd);
37 proc_maps->data = (char *)VmMap;
38 proc_maps->mmaped_size = MmapedSize;
39 proc_maps->len = Size;
3140}
3241
3342bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
......@@ -49,13 +58,28 @@ bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
4958 segment->protection |= kProtectionWrite;
5059 if ((xmapentry->pr_mflags & MA_EXEC) != 0)
5160 segment->protection |= kProtectionExecute;
61 if ((xmapentry->pr_mflags & MA_SHARED) != 0)
62 segment->protection |= kProtectionShared;
5263
5364 if (segment->filename != NULL && segment->filename_size > 0) {
5465 char proc_path[PATH_MAX + 1];
5566
56 internal_snprintf(proc_path, sizeof(proc_path), "/proc/self/path/%s",
57 xmapentry->pr_mapname);
58 internal_readlink(proc_path, segment->filename, segment->filename_size);
67 // Avoid unnecessary readlink on unnamed entires.
68 if (xmapentry->pr_mapname[0] == '\0')
69 segment->filename[0] = '\0';
70 else {
71 internal_snprintf(proc_path, sizeof(proc_path), "/proc/self/path/%s",
72 xmapentry->pr_mapname);
73 ssize_t sz = internal_readlink(proc_path, segment->filename,
74 segment->filename_size - 1);
75
76 // If readlink failed, the map is anonymous.
77 if (sz == -1)
78 segment->filename[0] = '\0';
79 else if ((size_t)sz < segment->filename_size)
80 // readlink doesn't NUL-terminate.
81 segment->filename[sz] = '\0';
82 }
5983 }
6084
6185 data_.current += sizeof(prxmap_t);
lib/tsan/sanitizer_common/sanitizer_quarantine.h+12-17
......@@ -68,10 +68,6 @@ struct QuarantineBatch {
6868
6969COMPILER_CHECK(sizeof(QuarantineBatch) <= (1 << 13)); // 8Kb.
7070
71// The callback interface is:
72// void Callback::Recycle(Node *ptr);
73// void *cb.Allocate(uptr size);
74// void cb.Deallocate(void *ptr);
7571template<typename Callback, typename Node>
7672class Quarantine {
7773 public:
......@@ -94,21 +90,20 @@ class Quarantine {
9490 recycle_mutex_.Init();
9591 }
9692
97 uptr GetSize() const { return atomic_load_relaxed(&max_size_); }
98 uptr GetCacheSize() const {
99 return atomic_load_relaxed(&max_cache_size_);
100 }
93 uptr GetMaxSize() const { return atomic_load_relaxed(&max_size_); }
94 uptr GetMaxCacheSize() const { return atomic_load_relaxed(&max_cache_size_); }
10195
10296 void Put(Cache *c, Callback cb, Node *ptr, uptr size) {
103 uptr cache_size = GetCacheSize();
104 if (cache_size) {
97 uptr max_cache_size = GetMaxCacheSize();
98 if (max_cache_size && size <= GetMaxSize()) {
99 cb.PreQuarantine(ptr);
105100 c->Enqueue(cb, ptr, size);
106101 } else {
107 // GetCacheSize() == 0 only when GetSize() == 0 (see Init).
108 cb.Recycle(ptr);
102 // GetMaxCacheSize() == 0 only when GetMaxSize() == 0 (see Init).
103 cb.RecyclePassThrough(ptr);
109104 }
110105 // Check cache size anyway to accommodate for runtime cache_size change.
111 if (c->Size() > cache_size)
106 if (c->Size() > max_cache_size)
112107 Drain(c, cb);
113108 }
114109
......@@ -117,7 +112,7 @@ class Quarantine {
117112 SpinMutexLock l(&cache_mutex_);
118113 cache_.Transfer(c);
119114 }
120 if (cache_.Size() > GetSize() && recycle_mutex_.TryLock())
115 if (cache_.Size() > GetMaxSize() && recycle_mutex_.TryLock())
121116 Recycle(atomic_load_relaxed(&min_size_), cb);
122117 }
123118
......@@ -133,7 +128,7 @@ class Quarantine {
133128 void PrintStats() const {
134129 // It assumes that the world is stopped, just as the allocator's PrintStats.
135130 Printf("Quarantine limits: global: %zdMb; thread local: %zdKb\n",
136 GetSize() >> 20, GetCacheSize() >> 10);
131 GetMaxSize() >> 20, GetMaxCacheSize() >> 10);
137132 cache_.PrintStats();
138133 }
139134
......@@ -149,8 +144,8 @@ class Quarantine {
149144 Cache cache_;
150145 char pad2_[kCacheLineSize];
151146
152 void NOINLINE Recycle(uptr min_size, Callback cb) REQUIRES(recycle_mutex_)
153 RELEASE(recycle_mutex_) {
147 void NOINLINE Recycle(uptr min_size, Callback cb)
148 SANITIZER_REQUIRES(recycle_mutex_) SANITIZER_RELEASE(recycle_mutex_) {
154149 Cache tmp;
155150 {
156151 SpinMutexLock l(&cache_mutex_);
lib/tsan/sanitizer_common/sanitizer_range.cpp created+62
......@@ -0,0 +1,62 @@
1//===-- sanitizer_range.cpp -----------------------------------------------===//
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#include "sanitizer_range.h"
10
11#include "sanitizer_common/sanitizer_array_ref.h"
12
13namespace __sanitizer {
14
15void Intersect(ArrayRef<Range> a, ArrayRef<Range> b,
16 InternalMmapVectorNoCtor<Range> &output) {
17 output.clear();
18
19 struct Event {
20 uptr val;
21 s8 diff1;
22 s8 diff2;
23 };
24
25 InternalMmapVector<Event> events;
26 for (const Range &r : a) {
27 CHECK_LE(r.begin, r.end);
28 events.push_back({r.begin, 1, 0});
29 events.push_back({r.end, -1, 0});
30 }
31
32 for (const Range &r : b) {
33 CHECK_LE(r.begin, r.end);
34 events.push_back({r.begin, 0, 1});
35 events.push_back({r.end, 0, -1});
36 }
37
38 Sort(events.data(), events.size(),
39 [](const Event &lh, const Event &rh) { return lh.val < rh.val; });
40
41 uptr start = 0;
42 sptr state1 = 0;
43 sptr state2 = 0;
44 for (const auto &e : events) {
45 if (e.val != start) {
46 DCHECK_GE(state1, 0);
47 DCHECK_GE(state2, 0);
48 if (state1 && state2) {
49 if (!output.empty() && start == output.back().end)
50 output.back().end = e.val;
51 else
52 output.push_back({start, e.val});
53 }
54 start = e.val;
55 }
56
57 state1 += e.diff1;
58 state2 += e.diff2;
59 }
60}
61
62} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_range.h created+40
......@@ -0,0 +1,40 @@
1//===-- sanitizer_range.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// Contais Range and related utilities.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef SANITIZER_RANGE_H
14#define SANITIZER_RANGE_H
15
16#include "sanitizer_common.h"
17#include "sanitizer_common/sanitizer_array_ref.h"
18
19namespace __sanitizer {
20
21struct Range {
22 uptr begin;
23 uptr end;
24};
25
26inline bool operator==(const Range &lhs, const Range &rhs) {
27 return lhs.begin == rhs.begin && lhs.end == rhs.end;
28}
29
30inline bool operator!=(const Range &lhs, const Range &rhs) {
31 return !(lhs == rhs);
32}
33
34// Calculates intersection of two sets of regions in O(N log N) time.
35void Intersect(ArrayRef<Range> a, ArrayRef<Range> b,
36 InternalMmapVectorNoCtor<Range> &output);
37
38} // namespace __sanitizer
39
40#endif // SANITIZER_RANGE_H
lib/tsan/sanitizer_common/sanitizer_redefine_builtins.h created+52
......@@ -0,0 +1,52 @@
1//===-- sanitizer_redefine_builtins.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// Redefine builtin functions to use internal versions. This is needed where
10// compiler optimizations end up producing unwanted libcalls!
11//
12//===----------------------------------------------------------------------===//
13#ifndef SANITIZER_COMMON_NO_REDEFINE_BUILTINS
14#ifndef SANITIZER_REDEFINE_BUILTINS_H
15#define SANITIZER_REDEFINE_BUILTINS_H
16
17// The asm hack only works with GCC and Clang.
18#if !defined(_WIN32)
19
20asm("memcpy = __sanitizer_internal_memcpy");
21asm("memmove = __sanitizer_internal_memmove");
22asm("memset = __sanitizer_internal_memset");
23
24// The builtins should not be redefined in source files that make use of C++
25// standard libraries, in particular where C++STL headers with inline functions
26// are used. The redefinition in such cases would lead to ODR violations.
27//
28// Try to break the build in common cases where builtins shouldn't be redefined.
29namespace std {
30class Define_SANITIZER_COMMON_NO_REDEFINE_BUILTINS_in_cpp_file {
31 Define_SANITIZER_COMMON_NO_REDEFINE_BUILTINS_in_cpp_file(
32 const Define_SANITIZER_COMMON_NO_REDEFINE_BUILTINS_in_cpp_file&) = delete;
33 Define_SANITIZER_COMMON_NO_REDEFINE_BUILTINS_in_cpp_file& operator=(
34 const Define_SANITIZER_COMMON_NO_REDEFINE_BUILTINS_in_cpp_file&) = delete;
35};
36using array = Define_SANITIZER_COMMON_NO_REDEFINE_BUILTINS_in_cpp_file;
37using atomic = Define_SANITIZER_COMMON_NO_REDEFINE_BUILTINS_in_cpp_file;
38using function = Define_SANITIZER_COMMON_NO_REDEFINE_BUILTINS_in_cpp_file;
39using map = Define_SANITIZER_COMMON_NO_REDEFINE_BUILTINS_in_cpp_file;
40using set = Define_SANITIZER_COMMON_NO_REDEFINE_BUILTINS_in_cpp_file;
41using shared_ptr = Define_SANITIZER_COMMON_NO_REDEFINE_BUILTINS_in_cpp_file;
42using string = Define_SANITIZER_COMMON_NO_REDEFINE_BUILTINS_in_cpp_file;
43using unique_ptr = Define_SANITIZER_COMMON_NO_REDEFINE_BUILTINS_in_cpp_file;
44using unordered_map = Define_SANITIZER_COMMON_NO_REDEFINE_BUILTINS_in_cpp_file;
45using unordered_set = Define_SANITIZER_COMMON_NO_REDEFINE_BUILTINS_in_cpp_file;
46using vector = Define_SANITIZER_COMMON_NO_REDEFINE_BUILTINS_in_cpp_file;
47} // namespace std
48
49#endif // !_WIN32
50
51#endif // SANITIZER_REDEFINE_BUILTINS_H
52#endif // SANITIZER_COMMON_NO_REDEFINE_BUILTINS
lib/tsan/sanitizer_common/sanitizer_ring_buffer.h+9-4
......@@ -86,10 +86,13 @@ class CompactRingBuffer {
8686 // Lower bytes store the address of the next buffer element.
8787 static constexpr int kPageSizeBits = 12;
8888 static constexpr int kSizeShift = 56;
89 static constexpr int kSizeBits = 64 - kSizeShift;
8990 static constexpr uptr kNextMask = (1ULL << kSizeShift) - 1;
9091
9192 uptr GetStorageSize() const { return (long_ >> kSizeShift) << kPageSizeBits; }
9293
94 static uptr SignExtend(uptr x) { return ((sptr)x) << kSizeBits >> kSizeBits; }
95
9396 void Init(void *storage, uptr size) {
9497 CHECK_EQ(sizeof(CompactRingBuffer<T>), sizeof(void *));
9598 CHECK(IsPowerOfTwo(size));
......@@ -97,12 +100,14 @@ class CompactRingBuffer {
97100 CHECK_LE(size, 128 << kPageSizeBits);
98101 CHECK_EQ(size % 4096, 0);
99102 CHECK_EQ(size % sizeof(T), 0);
100 CHECK_EQ((uptr)storage % (size * 2), 0);
101 long_ = (uptr)storage | ((size >> kPageSizeBits) << kSizeShift);
103 uptr st = (uptr)storage;
104 CHECK_EQ(st % (size * 2), 0);
105 CHECK_EQ(st, SignExtend(st & kNextMask));
106 long_ = (st & kNextMask) | ((size >> kPageSizeBits) << kSizeShift);
102107 }
103108
104109 void SetNext(const T *next) {
105 long_ = (long_ & ~kNextMask) | (uptr)next;
110 long_ = (long_ & ~kNextMask) | ((uptr)next & kNextMask);
106111 }
107112
108113 public:
......@@ -119,7 +124,7 @@ class CompactRingBuffer {
119124 SetNext((const T *)storage + Idx);
120125 }
121126
122 T *Next() const { return (T *)(long_ & kNextMask); }
127 T *Next() const { return (T *)(SignExtend(long_ & kNextMask)); }
123128
124129 void *StartOfStorage() const {
125130 return (void *)((uptr)Next() & ~(GetStorageSize() - 1));
lib/tsan/sanitizer_common/sanitizer_signal_interceptors.inc+13-2
......@@ -29,12 +29,21 @@ using namespace __sanitizer;
2929#endif
3030
3131#ifndef SIGNAL_INTERCEPTOR_SIGACTION_IMPL
32#define SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signum, act, oldact) \
33 { return REAL(sigaction_symname)(signum, act, oldact); }
32# define SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signum, act, oldact) \
33 { \
34 if (!REAL(sigaction_symname)) { \
35 Printf( \
36 "Warning: REAL(sigaction_symname) == nullptr. This may happen " \
37 "if you link with ubsan statically. Sigaction will not work.\n"); \
38 return -1; \
39 } \
40 return REAL(sigaction_symname)(signum, act, oldact); \
41 }
3442#endif
3543
3644#if SANITIZER_INTERCEPT_BSD_SIGNAL
3745INTERCEPTOR(uptr, bsd_signal, int signum, uptr handler) {
46 SIGNAL_INTERCEPTOR_ENTER();
3847 if (GetHandleSignalMode(signum) == kHandleSignalExclusive) return 0;
3948 SIGNAL_INTERCEPTOR_SIGNAL_IMPL(bsd_signal, signum, handler);
4049}
......@@ -45,6 +54,7 @@ INTERCEPTOR(uptr, bsd_signal, int signum, uptr handler) {
4554
4655#if SANITIZER_INTERCEPT_SIGNAL_AND_SIGACTION
4756INTERCEPTOR(uptr, signal, int signum, uptr handler) {
57 SIGNAL_INTERCEPTOR_ENTER();
4858 if (GetHandleSignalMode(signum) == kHandleSignalExclusive)
4959 return (uptr) nullptr;
5060 SIGNAL_INTERCEPTOR_SIGNAL_IMPL(signal, signum, handler);
......@@ -53,6 +63,7 @@ INTERCEPTOR(uptr, signal, int signum, uptr handler) {
5363
5464INTERCEPTOR(int, sigaction_symname, int signum,
5565 const __sanitizer_sigaction *act, __sanitizer_sigaction *oldact) {
66 SIGNAL_INTERCEPTOR_ENTER();
5667 if (GetHandleSignalMode(signum) == kHandleSignalExclusive) {
5768 if (!oldact) return 0;
5869 act = nullptr;
lib/tsan/sanitizer_common/sanitizer_solaris.cpp-22
......@@ -225,28 +225,6 @@ void FutexWait(atomic_uint32_t *p, u32 cmp) {
225225
226226void FutexWake(atomic_uint32_t *p, u32 count) {}
227227
228BlockingMutex::BlockingMutex() {
229 CHECK(sizeof(mutex_t) <= sizeof(opaque_storage_));
230 internal_memset(this, 0, sizeof(*this));
231 CHECK_EQ(mutex_init((mutex_t *)&opaque_storage_, USYNC_THREAD, NULL), 0);
232}
233
234void BlockingMutex::Lock() {
235 CHECK(sizeof(mutex_t) <= sizeof(opaque_storage_));
236 CHECK_NE(owner_, (uptr)thr_self());
237 CHECK_EQ(mutex_lock((mutex_t *)&opaque_storage_), 0);
238 CHECK(!owner_);
239 owner_ = (uptr)thr_self();
240}
241
242void BlockingMutex::Unlock() {
243 CHECK(owner_ == (uptr)thr_self());
244 owner_ = 0;
245 CHECK_EQ(mutex_unlock((mutex_t *)&opaque_storage_), 0);
246}
247
248void BlockingMutex::CheckLocked() const { CHECK_EQ((uptr)thr_self(), owner_); }
249
250228} // namespace __sanitizer
251229
252230#endif // SANITIZER_SOLARIS
lib/tsan/sanitizer_common/sanitizer_solaris.h created+56
......@@ -0,0 +1,56 @@
1//===-- sanitizer_solaris.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 Sanitizer runtime. It contains Solaris-specific
10// definitions.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef SANITIZER_SOLARIS_H
15#define SANITIZER_SOLARIS_H
16
17#include "sanitizer_internal_defs.h"
18
19#if SANITIZER_SOLARIS
20
21#include <link.h>
22
23namespace __sanitizer {
24
25// Beginning of declaration from OpenSolaris/Illumos
26// $SRC/cmd/sgs/include/rtld.h.
27struct Rt_map {
28 Link_map rt_public;
29 const char *rt_pathname;
30 ulong_t rt_padstart;
31 ulong_t rt_padimlen;
32 ulong_t rt_msize;
33 uint_t rt_flags;
34 uint_t rt_flags1;
35 ulong_t rt_tlsmodid;
36};
37
38// Structure matching the Solaris 11.4 struct dl_phdr_info used to determine
39// presence of dlpi_tls_modid field at runtime. Cf. Solaris 11.4
40// dl_iterate_phdr(3C), Example 2.
41struct dl_phdr_info_test {
42 ElfW(Addr) dlpi_addr;
43 const char *dlpi_name;
44 const ElfW(Phdr) * dlpi_phdr;
45 ElfW(Half) dlpi_phnum;
46 u_longlong_t dlpi_adds;
47 u_longlong_t dlpi_subs;
48 size_t dlpi_tls_modid;
49 void *dlpi_tls_data;
50};
51
52} // namespace __sanitizer
53
54#endif // SANITIZER_SOLARIS
55
56#endif // SANITIZER_SOLARIS_H
lib/tsan/sanitizer_common/sanitizer_stack_store.cpp created+379
......@@ -0,0 +1,379 @@
1//===-- sanitizer_stack_store.cpp -------------------------------*- 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#include "sanitizer_stack_store.h"
10
11#include "sanitizer_atomic.h"
12#include "sanitizer_common.h"
13#include "sanitizer_internal_defs.h"
14#include "sanitizer_leb128.h"
15#include "sanitizer_lzw.h"
16#include "sanitizer_placement_new.h"
17#include "sanitizer_stacktrace.h"
18
19namespace __sanitizer {
20
21namespace {
22struct StackTraceHeader {
23 static constexpr u32 kStackSizeBits = 8;
24
25 u8 size;
26 u8 tag;
27 explicit StackTraceHeader(const StackTrace &trace)
28 : size(Min<uptr>(trace.size, (1u << 8) - 1)), tag(trace.tag) {
29 CHECK_EQ(trace.tag, static_cast<uptr>(tag));
30 }
31 explicit StackTraceHeader(uptr h)
32 : size(h & ((1 << kStackSizeBits) - 1)), tag(h >> kStackSizeBits) {}
33
34 uptr ToUptr() const {
35 return static_cast<uptr>(size) | (static_cast<uptr>(tag) << kStackSizeBits);
36 }
37};
38} // namespace
39
40StackStore::Id StackStore::Store(const StackTrace &trace, uptr *pack) {
41 if (!trace.size && !trace.tag)
42 return 0;
43 StackTraceHeader h(trace);
44 uptr idx = 0;
45 *pack = 0;
46 uptr *stack_trace = Alloc(h.size + 1, &idx, pack);
47 *stack_trace = h.ToUptr();
48 internal_memcpy(stack_trace + 1, trace.trace, h.size * sizeof(uptr));
49 *pack += blocks_[GetBlockIdx(idx)].Stored(h.size + 1);
50 return OffsetToId(idx);
51}
52
53StackTrace StackStore::Load(Id id) {
54 if (!id)
55 return {};
56 uptr idx = IdToOffset(id);
57 uptr block_idx = GetBlockIdx(idx);
58 CHECK_LT(block_idx, ARRAY_SIZE(blocks_));
59 const uptr *stack_trace = blocks_[block_idx].GetOrUnpack(this);
60 if (!stack_trace)
61 return {};
62 stack_trace += GetInBlockIdx(idx);
63 StackTraceHeader h(*stack_trace);
64 return StackTrace(stack_trace + 1, h.size, h.tag);
65}
66
67uptr StackStore::Allocated() const {
68 return atomic_load_relaxed(&allocated_) + sizeof(*this);
69}
70
71uptr *StackStore::Alloc(uptr count, uptr *idx, uptr *pack) {
72 for (;;) {
73 // Optimisic lock-free allocation, essentially try to bump the
74 // total_frames_.
75 uptr start = atomic_fetch_add(&total_frames_, count, memory_order_relaxed);
76 uptr block_idx = GetBlockIdx(start);
77 uptr last_idx = GetBlockIdx(start + count - 1);
78 if (LIKELY(block_idx == last_idx)) {
79 // Fits into the a single block.
80 CHECK_LT(block_idx, ARRAY_SIZE(blocks_));
81 *idx = start;
82 return blocks_[block_idx].GetOrCreate(this) + GetInBlockIdx(start);
83 }
84
85 // Retry. We can't use range allocated in two different blocks.
86 CHECK_LE(count, kBlockSizeFrames);
87 uptr in_first = kBlockSizeFrames - GetInBlockIdx(start);
88 // Mark tail/head of these blocks as "stored".to avoid waiting before we can
89 // Pack().
90 *pack += blocks_[block_idx].Stored(in_first);
91 *pack += blocks_[last_idx].Stored(count - in_first);
92 }
93}
94
95void *StackStore::Map(uptr size, const char *mem_type) {
96 atomic_fetch_add(&allocated_, size, memory_order_relaxed);
97 return MmapNoReserveOrDie(size, mem_type);
98}
99
100void StackStore::Unmap(void *addr, uptr size) {
101 atomic_fetch_sub(&allocated_, size, memory_order_relaxed);
102 UnmapOrDie(addr, size);
103}
104
105uptr StackStore::Pack(Compression type) {
106 uptr res = 0;
107 for (BlockInfo &b : blocks_) res += b.Pack(type, this);
108 return res;
109}
110
111void StackStore::LockAll() {
112 for (BlockInfo &b : blocks_) b.Lock();
113}
114
115void StackStore::UnlockAll() {
116 for (BlockInfo &b : blocks_) b.Unlock();
117}
118
119void StackStore::TestOnlyUnmap() {
120 for (BlockInfo &b : blocks_) b.TestOnlyUnmap(this);
121 internal_memset(this, 0, sizeof(*this));
122}
123
124uptr *StackStore::BlockInfo::Get() const {
125 // Idiomatic double-checked locking uses memory_order_acquire here. But
126 // relaxed is fine for us, justification is similar to
127 // TwoLevelMap::GetOrCreate.
128 return reinterpret_cast<uptr *>(atomic_load_relaxed(&data_));
129}
130
131uptr *StackStore::BlockInfo::Create(StackStore *store) {
132 SpinMutexLock l(&mtx_);
133 uptr *ptr = Get();
134 if (!ptr) {
135 ptr = reinterpret_cast<uptr *>(store->Map(kBlockSizeBytes, "StackStore"));
136 atomic_store(&data_, reinterpret_cast<uptr>(ptr), memory_order_release);
137 }
138 return ptr;
139}
140
141uptr *StackStore::BlockInfo::GetOrCreate(StackStore *store) {
142 uptr *ptr = Get();
143 if (LIKELY(ptr))
144 return ptr;
145 return Create(store);
146}
147
148class SLeb128Encoder {
149 public:
150 SLeb128Encoder(u8 *begin, u8 *end) : begin(begin), end(end) {}
151
152 bool operator==(const SLeb128Encoder &other) const {
153 return begin == other.begin;
154 }
155
156 bool operator!=(const SLeb128Encoder &other) const {
157 return begin != other.begin;
158 }
159
160 SLeb128Encoder &operator=(uptr v) {
161 sptr diff = v - previous;
162 begin = EncodeSLEB128(diff, begin, end);
163 previous = v;
164 return *this;
165 }
166 SLeb128Encoder &operator*() { return *this; }
167 SLeb128Encoder &operator++() { return *this; }
168
169 u8 *base() const { return begin; }
170
171 private:
172 u8 *begin;
173 u8 *end;
174 uptr previous = 0;
175};
176
177class SLeb128Decoder {
178 public:
179 SLeb128Decoder(const u8 *begin, const u8 *end) : begin(begin), end(end) {}
180
181 bool operator==(const SLeb128Decoder &other) const {
182 return begin == other.begin;
183 }
184
185 bool operator!=(const SLeb128Decoder &other) const {
186 return begin != other.begin;
187 }
188
189 uptr operator*() {
190 sptr diff;
191 begin = DecodeSLEB128(begin, end, &diff);
192 previous += diff;
193 return previous;
194 }
195 SLeb128Decoder &operator++() { return *this; }
196
197 SLeb128Decoder operator++(int) { return *this; }
198
199 private:
200 const u8 *begin;
201 const u8 *end;
202 uptr previous = 0;
203};
204
205static u8 *CompressDelta(const uptr *from, const uptr *from_end, u8 *to,
206 u8 *to_end) {
207 SLeb128Encoder encoder(to, to_end);
208 for (; from != from_end; ++from, ++encoder) *encoder = *from;
209 return encoder.base();
210}
211
212static uptr *UncompressDelta(const u8 *from, const u8 *from_end, uptr *to,
213 uptr *to_end) {
214 SLeb128Decoder decoder(from, from_end);
215 SLeb128Decoder end(from_end, from_end);
216 for (; decoder != end; ++to, ++decoder) *to = *decoder;
217 CHECK_EQ(to, to_end);
218 return to;
219}
220
221static u8 *CompressLzw(const uptr *from, const uptr *from_end, u8 *to,
222 u8 *to_end) {
223 SLeb128Encoder encoder(to, to_end);
224 encoder = LzwEncode<uptr>(from, from_end, encoder);
225 return encoder.base();
226}
227
228static uptr *UncompressLzw(const u8 *from, const u8 *from_end, uptr *to,
229 uptr *to_end) {
230 SLeb128Decoder decoder(from, from_end);
231 SLeb128Decoder end(from_end, from_end);
232 to = LzwDecode<uptr>(decoder, end, to);
233 CHECK_EQ(to, to_end);
234 return to;
235}
236
237#if defined(_MSC_VER) && !defined(__clang__)
238# pragma warning(push)
239// Disable 'nonstandard extension used: zero-sized array in struct/union'.
240# pragma warning(disable : 4200)
241#endif
242namespace {
243struct PackedHeader {
244 uptr size;
245 StackStore::Compression type;
246 u8 data[];
247};
248} // namespace
249#if defined(_MSC_VER) && !defined(__clang__)
250# pragma warning(pop)
251#endif
252
253uptr *StackStore::BlockInfo::GetOrUnpack(StackStore *store) {
254 SpinMutexLock l(&mtx_);
255 switch (state) {
256 case State::Storing:
257 state = State::Unpacked;
258 FALLTHROUGH;
259 case State::Unpacked:
260 return Get();
261 case State::Packed:
262 break;
263 }
264
265 u8 *ptr = reinterpret_cast<u8 *>(Get());
266 CHECK_NE(nullptr, ptr);
267 const PackedHeader *header = reinterpret_cast<const PackedHeader *>(ptr);
268 CHECK_LE(header->size, kBlockSizeBytes);
269 CHECK_GE(header->size, sizeof(PackedHeader));
270
271 uptr packed_size_aligned = RoundUpTo(header->size, GetPageSizeCached());
272
273 uptr *unpacked =
274 reinterpret_cast<uptr *>(store->Map(kBlockSizeBytes, "StackStoreUnpack"));
275
276 uptr *unpacked_end;
277 switch (header->type) {
278 case Compression::Delta:
279 unpacked_end = UncompressDelta(header->data, ptr + header->size, unpacked,
280 unpacked + kBlockSizeFrames);
281 break;
282 case Compression::LZW:
283 unpacked_end = UncompressLzw(header->data, ptr + header->size, unpacked,
284 unpacked + kBlockSizeFrames);
285 break;
286 default:
287 UNREACHABLE("Unexpected type");
288 break;
289 }
290
291 CHECK_EQ(kBlockSizeFrames, unpacked_end - unpacked);
292
293 MprotectReadOnly(reinterpret_cast<uptr>(unpacked), kBlockSizeBytes);
294 atomic_store(&data_, reinterpret_cast<uptr>(unpacked), memory_order_release);
295 store->Unmap(ptr, packed_size_aligned);
296
297 state = State::Unpacked;
298 return Get();
299}
300
301uptr StackStore::BlockInfo::Pack(Compression type, StackStore *store) {
302 if (type == Compression::None)
303 return 0;
304
305 SpinMutexLock l(&mtx_);
306 switch (state) {
307 case State::Unpacked:
308 case State::Packed:
309 return 0;
310 case State::Storing:
311 break;
312 }
313
314 uptr *ptr = Get();
315 if (!ptr || !Stored(0))
316 return 0;
317
318 u8 *packed =
319 reinterpret_cast<u8 *>(store->Map(kBlockSizeBytes, "StackStorePack"));
320 PackedHeader *header = reinterpret_cast<PackedHeader *>(packed);
321 u8 *alloc_end = packed + kBlockSizeBytes;
322
323 u8 *packed_end = nullptr;
324 switch (type) {
325 case Compression::Delta:
326 packed_end =
327 CompressDelta(ptr, ptr + kBlockSizeFrames, header->data, alloc_end);
328 break;
329 case Compression::LZW:
330 packed_end =
331 CompressLzw(ptr, ptr + kBlockSizeFrames, header->data, alloc_end);
332 break;
333 default:
334 UNREACHABLE("Unexpected type");
335 break;
336 }
337
338 header->type = type;
339 header->size = packed_end - packed;
340
341 VPrintf(1, "Packed block of %zu KiB to %zu KiB\n", kBlockSizeBytes >> 10,
342 header->size >> 10);
343
344 if (kBlockSizeBytes - header->size < kBlockSizeBytes / 8) {
345 VPrintf(1, "Undo and keep block unpacked\n");
346 MprotectReadOnly(reinterpret_cast<uptr>(ptr), kBlockSizeBytes);
347 store->Unmap(packed, kBlockSizeBytes);
348 state = State::Unpacked;
349 return 0;
350 }
351
352 uptr packed_size_aligned = RoundUpTo(header->size, GetPageSizeCached());
353 store->Unmap(packed + packed_size_aligned,
354 kBlockSizeBytes - packed_size_aligned);
355 MprotectReadOnly(reinterpret_cast<uptr>(packed), packed_size_aligned);
356
357 atomic_store(&data_, reinterpret_cast<uptr>(packed), memory_order_release);
358 store->Unmap(ptr, kBlockSizeBytes);
359
360 state = State::Packed;
361 return kBlockSizeBytes - packed_size_aligned;
362}
363
364void StackStore::BlockInfo::TestOnlyUnmap(StackStore *store) {
365 if (uptr *ptr = Get())
366 store->Unmap(ptr, kBlockSizeBytes);
367}
368
369bool StackStore::BlockInfo::Stored(uptr n) {
370 return n + atomic_fetch_add(&stored_, n, memory_order_release) ==
371 kBlockSizeFrames;
372}
373
374bool StackStore::BlockInfo::IsPacked() const {
375 SpinMutexLock l(&mtx_);
376 return state == State::Packed;
377}
378
379} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_stack_store.h created+121
......@@ -0,0 +1,121 @@
1//===-- sanitizer_stack_store.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#ifndef SANITIZER_STACK_STORE_H
10#define SANITIZER_STACK_STORE_H
11
12#include "sanitizer_atomic.h"
13#include "sanitizer_common.h"
14#include "sanitizer_internal_defs.h"
15#include "sanitizer_mutex.h"
16#include "sanitizer_stacktrace.h"
17
18namespace __sanitizer {
19
20class StackStore {
21 static constexpr uptr kBlockSizeFrames = 0x100000;
22 static constexpr uptr kBlockCount = 0x1000;
23 static constexpr uptr kBlockSizeBytes = kBlockSizeFrames * sizeof(uptr);
24
25 public:
26 enum class Compression : u8 {
27 None = 0,
28 Delta,
29 LZW,
30 };
31
32 constexpr StackStore() = default;
33
34 using Id = u32; // Enough for 2^32 * sizeof(uptr) bytes of traces.
35 static_assert(u64(kBlockCount) * kBlockSizeFrames == 1ull << (sizeof(Id) * 8),
36 "");
37
38 Id Store(const StackTrace &trace,
39 uptr *pack /* number of blocks completed by this call */);
40 StackTrace Load(Id id);
41 uptr Allocated() const;
42
43 // Packs all blocks which don't expect any more writes. A block is going to be
44 // packed once. As soon trace from that block was requested, it will unpack
45 // and stay unpacked after that.
46 // Returns the number of released bytes.
47 uptr Pack(Compression type);
48
49 void LockAll();
50 void UnlockAll();
51
52 void TestOnlyUnmap();
53
54 private:
55 friend class StackStoreTest;
56 static constexpr uptr GetBlockIdx(uptr frame_idx) {
57 return frame_idx / kBlockSizeFrames;
58 }
59
60 static constexpr uptr GetInBlockIdx(uptr frame_idx) {
61 return frame_idx % kBlockSizeFrames;
62 }
63
64 static constexpr uptr IdToOffset(Id id) {
65 CHECK_NE(id, 0);
66 return id - 1; // Avoid zero as id.
67 }
68
69 static constexpr uptr OffsetToId(Id id) {
70 // This makes UINT32_MAX to 0 and it will be retrived as and empty stack.
71 // But this is not a problem as we will not be able to store anything after
72 // that anyway.
73 return id + 1; // Avoid zero as id.
74 }
75
76 uptr *Alloc(uptr count, uptr *idx, uptr *pack);
77
78 void *Map(uptr size, const char *mem_type);
79 void Unmap(void *addr, uptr size);
80
81 // Total number of allocated frames.
82 atomic_uintptr_t total_frames_ = {};
83
84 // Tracks total allocated memory in bytes.
85 atomic_uintptr_t allocated_ = {};
86
87 // Each block will hold pointer to exactly kBlockSizeFrames.
88 class BlockInfo {
89 atomic_uintptr_t data_;
90 // Counter to track store progress to know when we can Pack() the block.
91 atomic_uint32_t stored_;
92 // Protects alloc of new blocks.
93 mutable StaticSpinMutex mtx_;
94
95 enum class State : u8 {
96 Storing = 0,
97 Packed,
98 Unpacked,
99 };
100 State state SANITIZER_GUARDED_BY(mtx_);
101
102 uptr *Create(StackStore *store);
103
104 public:
105 uptr *Get() const;
106 uptr *GetOrCreate(StackStore *store);
107 uptr *GetOrUnpack(StackStore *store);
108 uptr Pack(Compression type, StackStore *store);
109 void TestOnlyUnmap(StackStore *store);
110 bool Stored(uptr n);
111 bool IsPacked() const;
112 void Lock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS { mtx_.Lock(); }
113 void Unlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS { mtx_.Unlock(); }
114 };
115
116 BlockInfo blocks_[kBlockCount] = {};
117};
118
119} // namespace __sanitizer
120
121#endif // SANITIZER_STACK_STORE_H
lib/tsan/sanitizer_common/sanitizer_stackdepot.cpp+174-81
......@@ -12,95 +12,203 @@
1212
1313#include "sanitizer_stackdepot.h"
1414
15#include "sanitizer_atomic.h"
1516#include "sanitizer_common.h"
1617#include "sanitizer_hash.h"
18#include "sanitizer_mutex.h"
19#include "sanitizer_stack_store.h"
1720#include "sanitizer_stackdepotbase.h"
1821
1922namespace __sanitizer {
2023
2124struct StackDepotNode {
22 StackDepotNode *link;
23 u32 id;
24 atomic_uint32_t hash_and_use_count; // hash_bits : 12; use_count : 20;
25 u32 size;
26 u32 tag;
27 uptr stack[1]; // [size]
25 using hash_type = u64;
26 hash_type stack_hash;
27 u32 link;
28 StackStore::Id store_id;
2829
2930 static const u32 kTabSizeLog = SANITIZER_ANDROID ? 16 : 20;
30 // Lower kTabSizeLog bits are equal for all items in one bucket.
31 // We use these bits to store the per-stack use counter.
32 static const u32 kUseCountBits = kTabSizeLog;
33 static const u32 kMaxUseCount = 1 << kUseCountBits;
34 static const u32 kUseCountMask = (1 << kUseCountBits) - 1;
35 static const u32 kHashMask = ~kUseCountMask;
3631
3732 typedef StackTrace args_type;
38 bool eq(u32 hash, const args_type &args) const {
39 u32 hash_bits =
40 atomic_load(&hash_and_use_count, memory_order_relaxed) & kHashMask;
41 if ((hash & kHashMask) != hash_bits || args.size != size || args.tag != tag)
42 return false;
43 uptr i = 0;
44 for (; i < size; i++) {
45 if (stack[i] != args.trace[i]) return false;
46 }
47 return true;
48 }
49 static uptr storage_size(const args_type &args) {
50 return sizeof(StackDepotNode) + (args.size - 1) * sizeof(uptr);
33 bool eq(hash_type hash, const args_type &args) const {
34 return hash == stack_hash;
5135 }
52 static u32 hash(const args_type &args) {
53 MurMur2HashBuilder H(args.size * sizeof(uptr));
36 static uptr allocated();
37 static hash_type hash(const args_type &args) {
38 MurMur2Hash64Builder H(args.size * sizeof(uptr));
5439 for (uptr i = 0; i < args.size; i++) H.add(args.trace[i]);
40 H.add(args.tag);
5541 return H.get();
5642 }
5743 static bool is_valid(const args_type &args) {
5844 return args.size > 0 && args.trace;
5945 }
60 void store(const args_type &args, u32 hash) {
61 atomic_store(&hash_and_use_count, hash & kHashMask, memory_order_relaxed);
62 size = args.size;
63 tag = args.tag;
64 internal_memcpy(stack, args.trace, size * sizeof(uptr));
65 }
66 args_type load() const {
67 return args_type(&stack[0], size, tag);
68 }
69 StackDepotHandle get_handle() { return StackDepotHandle(this); }
46 void store(u32 id, const args_type &args, hash_type hash);
47 args_type load(u32 id) const;
48 static StackDepotHandle get_handle(u32 id);
7049
7150 typedef StackDepotHandle handle_type;
7251};
7352
74COMPILER_CHECK(StackDepotNode::kMaxUseCount == (u32)kStackDepotMaxUseCount);
75
76u32 StackDepotHandle::id() { return node_->id; }
77int StackDepotHandle::use_count() {
78 return atomic_load(&node_->hash_and_use_count, memory_order_relaxed) &
79 StackDepotNode::kUseCountMask;
80}
81void StackDepotHandle::inc_use_count_unsafe() {
82 u32 prev =
83 atomic_fetch_add(&node_->hash_and_use_count, 1, memory_order_relaxed) &
84 StackDepotNode::kUseCountMask;
85 CHECK_LT(prev + 1, StackDepotNode::kMaxUseCount);
86}
53static StackStore stackStore;
8754
8855// FIXME(dvyukov): this single reserved bit is used in TSan.
8956typedef StackDepotBase<StackDepotNode, 1, StackDepotNode::kTabSizeLog>
9057 StackDepot;
9158static StackDepot theDepot;
59// Keep mutable data out of frequently access nodes to improve caching
60// efficiency.
61static TwoLevelMap<atomic_uint32_t, StackDepot::kNodesSize1,
62 StackDepot::kNodesSize2>
63 useCounts;
64
65int StackDepotHandle::use_count() const {
66 return atomic_load_relaxed(&useCounts[id_]);
67}
68
69void StackDepotHandle::inc_use_count_unsafe() {
70 atomic_fetch_add(&useCounts[id_], 1, memory_order_relaxed);
71}
72
73uptr StackDepotNode::allocated() {
74 return stackStore.Allocated() + useCounts.MemoryUsage();
75}
76
77static void CompressStackStore() {
78 u64 start = Verbosity() >= 1 ? MonotonicNanoTime() : 0;
79 uptr diff = stackStore.Pack(static_cast<StackStore::Compression>(
80 Abs(common_flags()->compress_stack_depot)));
81 if (!diff)
82 return;
83 if (Verbosity() >= 1) {
84 u64 finish = MonotonicNanoTime();
85 uptr total_before = theDepot.GetStats().allocated + diff;
86 VPrintf(1, "%s: StackDepot released %zu KiB out of %zu KiB in %llu ms\n",
87 SanitizerToolName, diff >> 10, total_before >> 10,
88 (finish - start) / 1000000);
89 }
90}
91
92namespace {
93
94class CompressThread {
95 public:
96 constexpr CompressThread() = default;
97 void NewWorkNotify();
98 void Stop();
99 void LockAndStop() SANITIZER_NO_THREAD_SAFETY_ANALYSIS;
100 void Unlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS;
101
102 private:
103 enum class State {
104 NotStarted = 0,
105 Started,
106 Failed,
107 Stopped,
108 };
109
110 void Run();
111
112 bool WaitForWork() {
113 semaphore_.Wait();
114 return atomic_load(&run_, memory_order_acquire);
115 }
116
117 Semaphore semaphore_ = {};
118 StaticSpinMutex mutex_ = {};
119 State state_ SANITIZER_GUARDED_BY(mutex_) = State::NotStarted;
120 void *thread_ SANITIZER_GUARDED_BY(mutex_) = nullptr;
121 atomic_uint8_t run_ = {};
122};
123
124static CompressThread compress_thread;
125
126void CompressThread::NewWorkNotify() {
127 int compress = common_flags()->compress_stack_depot;
128 if (!compress)
129 return;
130 if (compress > 0 /* for testing or debugging */) {
131 SpinMutexLock l(&mutex_);
132 if (state_ == State::NotStarted) {
133 atomic_store(&run_, 1, memory_order_release);
134 CHECK_EQ(nullptr, thread_);
135 thread_ = internal_start_thread(
136 [](void *arg) -> void * {
137 reinterpret_cast<CompressThread *>(arg)->Run();
138 return nullptr;
139 },
140 this);
141 state_ = thread_ ? State::Started : State::Failed;
142 }
143 if (state_ == State::Started) {
144 semaphore_.Post();
145 return;
146 }
147 }
148 CompressStackStore();
149}
150
151void CompressThread::Run() {
152 VPrintf(1, "%s: StackDepot compression thread started\n", SanitizerToolName);
153 while (WaitForWork()) CompressStackStore();
154 VPrintf(1, "%s: StackDepot compression thread stopped\n", SanitizerToolName);
155}
156
157void CompressThread::Stop() {
158 void *t = nullptr;
159 {
160 SpinMutexLock l(&mutex_);
161 if (state_ != State::Started)
162 return;
163 state_ = State::Stopped;
164 CHECK_NE(nullptr, thread_);
165 t = thread_;
166 thread_ = nullptr;
167 }
168 atomic_store(&run_, 0, memory_order_release);
169 semaphore_.Post();
170 internal_join_thread(t);
171}
172
173void CompressThread::LockAndStop() {
174 mutex_.Lock();
175 if (state_ != State::Started)
176 return;
177 CHECK_NE(nullptr, thread_);
178
179 atomic_store(&run_, 0, memory_order_release);
180 semaphore_.Post();
181 internal_join_thread(thread_);
182 // Allow to restart after Unlock() if needed.
183 state_ = State::NotStarted;
184 thread_ = nullptr;
185}
186
187void CompressThread::Unlock() { mutex_.Unlock(); }
188
189} // namespace
92190
93StackDepotStats *StackDepotGetStats() {
94 return theDepot.GetStats();
191void StackDepotNode::store(u32 id, const args_type &args, hash_type hash) {
192 stack_hash = hash;
193 uptr pack = 0;
194 store_id = stackStore.Store(args, &pack);
195 if (LIKELY(!pack))
196 return;
197 compress_thread.NewWorkNotify();
95198}
96199
97u32 StackDepotPut(StackTrace stack) {
98 StackDepotHandle h = theDepot.Put(stack);
99 return h.valid() ? h.id() : 0;
200StackDepotNode::args_type StackDepotNode::load(u32 id) const {
201 if (!store_id)
202 return {};
203 return stackStore.Load(store_id);
100204}
101205
206StackDepotStats StackDepotGetStats() { return theDepot.GetStats(); }
207
208u32 StackDepotPut(StackTrace stack) { return theDepot.Put(stack); }
209
102210StackDepotHandle StackDepotPut_WithHandle(StackTrace stack) {
103 return theDepot.Put(stack);
211 return StackDepotNode::get_handle(theDepot.Put(stack));
104212}
105213
106214StackTrace StackDepotGet(u32 id) {
......@@ -109,9 +217,13 @@ StackTrace StackDepotGet(u32 id) {
109217
110218void StackDepotLockAll() {
111219 theDepot.LockAll();
220 compress_thread.LockAndStop();
221 stackStore.LockAll();
112222}
113223
114224void StackDepotUnlockAll() {
225 stackStore.UnlockAll();
226 compress_thread.Unlock();
115227 theDepot.UnlockAll();
116228}
117229
......@@ -121,34 +233,15 @@ void StackDepotPrintAll() {
121233#endif
122234}
123235
124bool StackDepotReverseMap::IdDescPair::IdComparator(
125 const StackDepotReverseMap::IdDescPair &a,
126 const StackDepotReverseMap::IdDescPair &b) {
127 return a.id < b.id;
128}
236void StackDepotStopBackgroundThread() { compress_thread.Stop(); }
129237
130StackDepotReverseMap::StackDepotReverseMap() {
131 map_.reserve(StackDepotGetStats()->n_uniq_ids + 100);
132 for (int idx = 0; idx < StackDepot::kTabSize; idx++) {
133 atomic_uintptr_t *p = &theDepot.tab[idx];
134 uptr v = atomic_load(p, memory_order_consume);
135 StackDepotNode *s = (StackDepotNode*)(v & ~1);
136 for (; s; s = s->link) {
137 IdDescPair pair = {s->id, s};
138 map_.push_back(pair);
139 }
140 }
141 Sort(map_.data(), map_.size(), &IdDescPair::IdComparator);
238StackDepotHandle StackDepotNode::get_handle(u32 id) {
239 return StackDepotHandle(&theDepot.nodes[id], id);
142240}
143241
144StackTrace StackDepotReverseMap::Get(u32 id) {
145 if (!map_.size())
146 return StackTrace();
147 IdDescPair pair = {id, nullptr};
148 uptr idx = InternalLowerBound(map_, pair, IdDescPair::IdComparator);
149 if (idx > map_.size() || map_[idx].id != id)
150 return StackTrace();
151 return map_[idx].desc->load();
242void StackDepotTestOnlyUnmap() {
243 theDepot.TestOnlyUnmap();
244 stackStore.TestOnlyUnmap();
152245}
153246
154247} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_stackdepot.h+9-30
......@@ -22,18 +22,18 @@ namespace __sanitizer {
2222// StackDepot efficiently stores huge amounts of stack traces.
2323struct StackDepotNode;
2424struct StackDepotHandle {
25 StackDepotNode *node_;
26 StackDepotHandle() : node_(nullptr) {}
27 explicit StackDepotHandle(StackDepotNode *node) : node_(node) {}
28 bool valid() { return node_; }
29 u32 id();
30 int use_count();
25 StackDepotNode *node_ = nullptr;
26 u32 id_ = 0;
27 StackDepotHandle(StackDepotNode *node, u32 id) : node_(node), id_(id) {}
28 bool valid() const { return node_; }
29 u32 id() const { return id_; }
30 int use_count() const;
3131 void inc_use_count_unsafe();
3232};
3333
3434const int kStackDepotMaxUseCount = 1U << (SANITIZER_ANDROID ? 16 : 20);
3535
36StackDepotStats *StackDepotGetStats();
36StackDepotStats StackDepotGetStats();
3737u32 StackDepotPut(StackTrace stack);
3838StackDepotHandle StackDepotPut_WithHandle(StackTrace stack);
3939// Retrieves a stored stack trace by the id.
......@@ -42,30 +42,9 @@ StackTrace StackDepotGet(u32 id);
4242void StackDepotLockAll();
4343void StackDepotUnlockAll();
4444void StackDepotPrintAll();
45void StackDepotStopBackgroundThread();
4546
46// Instantiating this class creates a snapshot of StackDepot which can be
47// efficiently queried with StackDepotGet(). You can use it concurrently with
48// StackDepot, but the snapshot is only guaranteed to contain those stack traces
49// which were stored before it was instantiated.
50class StackDepotReverseMap {
51 public:
52 StackDepotReverseMap();
53 StackTrace Get(u32 id);
54
55 private:
56 struct IdDescPair {
57 u32 id;
58 StackDepotNode *desc;
59
60 static bool IdComparator(const IdDescPair &a, const IdDescPair &b);
61 };
62
63 InternalMmapVector<IdDescPair> map_;
64
65 // Disallow evil constructors.
66 StackDepotReverseMap(const StackDepotReverseMap&);
67 void operator=(const StackDepotReverseMap&);
68};
47void StackDepotTestOnlyUnmap();
6948
7049} // namespace __sanitizer
7150
lib/tsan/sanitizer_common/sanitizer_stackdepotbase.h+86-87
......@@ -16,71 +16,87 @@
1616#include <stdio.h>
1717
1818#include "sanitizer_atomic.h"
19#include "sanitizer_flat_map.h"
1920#include "sanitizer_internal_defs.h"
2021#include "sanitizer_mutex.h"
21#include "sanitizer_persistent_allocator.h"
2222
2323namespace __sanitizer {
2424
2525template <class Node, int kReservedBits, int kTabSizeLog>
2626class StackDepotBase {
27 static constexpr u32 kIdSizeLog =
28 sizeof(u32) * 8 - Max(kReservedBits, 1 /* At least 1 bit for locking. */);
29 static constexpr u32 kNodesSize1Log = kIdSizeLog / 2;
30 static constexpr u32 kNodesSize2Log = kIdSizeLog - kNodesSize1Log;
31 static constexpr int kTabSize = 1 << kTabSizeLog; // Hash table size.
32 static constexpr u32 kUnlockMask = (1ull << kIdSizeLog) - 1;
33 static constexpr u32 kLockMask = ~kUnlockMask;
34
2735 public:
2836 typedef typename Node::args_type args_type;
2937 typedef typename Node::handle_type handle_type;
38 typedef typename Node::hash_type hash_type;
39
40 static constexpr u64 kNodesSize1 = 1ull << kNodesSize1Log;
41 static constexpr u64 kNodesSize2 = 1ull << kNodesSize2Log;
42
3043 // Maps stack trace to an unique id.
31 handle_type Put(args_type args, bool *inserted = nullptr);
44 u32 Put(args_type args, bool *inserted = nullptr);
3245 // Retrieves a stored stack trace by the id.
3346 args_type Get(u32 id);
3447
35 StackDepotStats *GetStats() { return &stats; }
48 StackDepotStats GetStats() const {
49 return {
50 atomic_load_relaxed(&n_uniq_ids),
51 nodes.MemoryUsage() + Node::allocated(),
52 };
53 }
3654
3755 void LockAll();
3856 void UnlockAll();
3957 void PrintAll();
4058
41 private:
42 static Node *find(Node *s, args_type args, u32 hash);
43 static Node *lock(atomic_uintptr_t *p);
44 static void unlock(atomic_uintptr_t *p, Node *s);
59 void TestOnlyUnmap() {
60 nodes.TestOnlyUnmap();
61 internal_memset(this, 0, sizeof(*this));
62 }
4563
46 static const int kTabSize = 1 << kTabSizeLog; // Hash table size.
47 static const int kPartBits = 8;
48 static const int kPartShift = sizeof(u32) * 8 - kPartBits - kReservedBits;
49 static const int kPartCount =
50 1 << kPartBits; // Number of subparts in the table.
51 static const int kPartSize = kTabSize / kPartCount;
52 static const int kMaxId = 1 << kPartShift;
64 private:
65 friend Node;
66 u32 find(u32 s, args_type args, hash_type hash) const;
67 static u32 lock(atomic_uint32_t *p);
68 static void unlock(atomic_uint32_t *p, u32 s);
69 atomic_uint32_t tab[kTabSize]; // Hash table of Node's.
5370
54 atomic_uintptr_t tab[kTabSize]; // Hash table of Node's.
55 atomic_uint32_t seq[kPartCount]; // Unique id generators.
71 atomic_uint32_t n_uniq_ids;
5672
57 StackDepotStats stats;
73 TwoLevelMap<Node, kNodesSize1, kNodesSize2> nodes;
5874
5975 friend class StackDepotReverseMap;
6076};
6177
6278template <class Node, int kReservedBits, int kTabSizeLog>
63Node *StackDepotBase<Node, kReservedBits, kTabSizeLog>::find(Node *s,
64 args_type args,
65 u32 hash) {
79u32 StackDepotBase<Node, kReservedBits, kTabSizeLog>::find(
80 u32 s, args_type args, hash_type hash) const {
6681 // Searches linked list s for the stack, returns its id.
67 for (; s; s = s->link) {
68 if (s->eq(hash, args)) {
82 for (; s;) {
83 const Node &node = nodes[s];
84 if (node.eq(hash, args))
6985 return s;
70 }
86 s = node.link;
7187 }
72 return nullptr;
88 return 0;
7389}
7490
7591template <class Node, int kReservedBits, int kTabSizeLog>
76Node *StackDepotBase<Node, kReservedBits, kTabSizeLog>::lock(
77 atomic_uintptr_t *p) {
92u32 StackDepotBase<Node, kReservedBits, kTabSizeLog>::lock(atomic_uint32_t *p) {
7893 // Uses the pointer lsb as mutex.
7994 for (int i = 0;; i++) {
80 uptr cmp = atomic_load(p, memory_order_relaxed);
81 if ((cmp & 1) == 0 &&
82 atomic_compare_exchange_weak(p, &cmp, cmp | 1, memory_order_acquire))
83 return (Node *)cmp;
95 u32 cmp = atomic_load(p, memory_order_relaxed);
96 if ((cmp & kLockMask) == 0 &&
97 atomic_compare_exchange_weak(p, &cmp, cmp | kLockMask,
98 memory_order_acquire))
99 return cmp;
84100 if (i < 10)
85101 proc_yield(10);
86102 else
......@@ -90,73 +106,57 @@ Node *StackDepotBase<Node, kReservedBits, kTabSizeLog>::lock(
90106
91107template <class Node, int kReservedBits, int kTabSizeLog>
92108void StackDepotBase<Node, kReservedBits, kTabSizeLog>::unlock(
93 atomic_uintptr_t *p, Node *s) {
94 DCHECK_EQ((uptr)s & 1, 0);
95 atomic_store(p, (uptr)s, memory_order_release);
109 atomic_uint32_t *p, u32 s) {
110 DCHECK_EQ(s & kLockMask, 0);
111 atomic_store(p, s, memory_order_release);
96112}
97113
98114template <class Node, int kReservedBits, int kTabSizeLog>
99typename StackDepotBase<Node, kReservedBits, kTabSizeLog>::handle_type
100StackDepotBase<Node, kReservedBits, kTabSizeLog>::Put(args_type args,
101 bool *inserted) {
102 if (inserted) *inserted = false;
103 if (!Node::is_valid(args)) return handle_type();
104 uptr h = Node::hash(args);
105 atomic_uintptr_t *p = &tab[h % kTabSize];
106 uptr v = atomic_load(p, memory_order_consume);
107 Node *s = (Node *)(v & ~1);
115u32 StackDepotBase<Node, kReservedBits, kTabSizeLog>::Put(args_type args,
116 bool *inserted) {
117 if (inserted)
118 *inserted = false;
119 if (!LIKELY(Node::is_valid(args)))
120 return 0;
121 hash_type h = Node::hash(args);
122 atomic_uint32_t *p = &tab[h % kTabSize];
123 u32 v = atomic_load(p, memory_order_consume);
124 u32 s = v & kUnlockMask;
108125 // First, try to find the existing stack.
109 Node *node = find(s, args, h);
110 if (node) return node->get_handle();
126 u32 node = find(s, args, h);
127 if (LIKELY(node))
128 return node;
129
111130 // If failed, lock, retry and insert new.
112 Node *s2 = lock(p);
131 u32 s2 = lock(p);
113132 if (s2 != s) {
114133 node = find(s2, args, h);
115134 if (node) {
116135 unlock(p, s2);
117 return node->get_handle();
136 return node;
118137 }
119138 }
120 uptr part = (h % kTabSize) / kPartSize;
121 u32 id = atomic_fetch_add(&seq[part], 1, memory_order_relaxed) + 1;
122 stats.n_uniq_ids++;
123 CHECK_LT(id, kMaxId);
124 id |= part << kPartShift;
125 CHECK_NE(id, 0);
126 CHECK_EQ(id & (((u32)-1) >> kReservedBits), id);
127 uptr memsz = Node::storage_size(args);
128 s = (Node *)PersistentAlloc(memsz);
129 stats.allocated += memsz;
130 s->id = id;
131 s->store(args, h);
132 s->link = s2;
139 s = atomic_fetch_add(&n_uniq_ids, 1, memory_order_relaxed) + 1;
140 CHECK_EQ(s & kUnlockMask, s);
141 CHECK_EQ(s & (((u32)-1) >> kReservedBits), s);
142 Node &new_node = nodes[s];
143 new_node.store(s, args, h);
144 new_node.link = s2;
133145 unlock(p, s);
134146 if (inserted) *inserted = true;
135 return s->get_handle();
147 return s;
136148}
137149
138150template <class Node, int kReservedBits, int kTabSizeLog>
139151typename StackDepotBase<Node, kReservedBits, kTabSizeLog>::args_type
140152StackDepotBase<Node, kReservedBits, kTabSizeLog>::Get(u32 id) {
141 if (id == 0) {
153 if (id == 0)
142154 return args_type();
143 }
144155 CHECK_EQ(id & (((u32)-1) >> kReservedBits), id);
145 // High kPartBits contain part id, so we need to scan at most kPartSize lists.
146 uptr part = id >> kPartShift;
147 for (int i = 0; i != kPartSize; i++) {
148 uptr idx = part * kPartSize + i;
149 CHECK_LT(idx, kTabSize);
150 atomic_uintptr_t *p = &tab[idx];
151 uptr v = atomic_load(p, memory_order_consume);
152 Node *s = (Node *)(v & ~1);
153 for (; s; s = s->link) {
154 if (s->id == id) {
155 return s->load();
156 }
157 }
158 }
159 return args_type();
156 if (!nodes.contains(id))
157 return args_type();
158 const Node &node = nodes[id];
159 return node.load(id);
160160}
161161
162162template <class Node, int kReservedBits, int kTabSizeLog>
......@@ -169,24 +169,23 @@ void StackDepotBase<Node, kReservedBits, kTabSizeLog>::LockAll() {
169169template <class Node, int kReservedBits, int kTabSizeLog>
170170void StackDepotBase<Node, kReservedBits, kTabSizeLog>::UnlockAll() {
171171 for (int i = 0; i < kTabSize; ++i) {
172 atomic_uintptr_t *p = &tab[i];
172 atomic_uint32_t *p = &tab[i];
173173 uptr s = atomic_load(p, memory_order_relaxed);
174 unlock(p, (Node *)(s & ~1UL));
174 unlock(p, s & kUnlockMask);
175175 }
176176}
177177
178178template <class Node, int kReservedBits, int kTabSizeLog>
179179void StackDepotBase<Node, kReservedBits, kTabSizeLog>::PrintAll() {
180180 for (int i = 0; i < kTabSize; ++i) {
181 atomic_uintptr_t *p = &tab[i];
182 lock(p);
183 uptr v = atomic_load(p, memory_order_relaxed);
184 Node *s = (Node *)(v & ~1UL);
185 for (; s; s = s->link) {
186 Printf("Stack for id %u:\n", s->id);
187 s->load().Print();
181 atomic_uint32_t *p = &tab[i];
182 u32 s = atomic_load(p, memory_order_consume) & kUnlockMask;
183 for (; s;) {
184 const Node &node = nodes[s];
185 Printf("Stack for id %u:\n", s);
186 node.load(s).Print();
187 s = node.link;
188188 }
189 unlock(p, s);
190189 }
191190}
192191
lib/tsan/sanitizer_common/sanitizer_stacktrace.cpp+9-7
......@@ -20,10 +20,10 @@
2020namespace __sanitizer {
2121
2222uptr StackTrace::GetNextInstructionPc(uptr pc) {
23#if defined(__sparc__) || defined(__mips__)
23#if defined(__aarch64__)
24 return STRIP_PAC_PC((void *)pc) + 4;
25#elif defined(__sparc__) || defined(__mips__)
2426 return pc + 8;
25#elif defined(__powerpc__) || defined(__arm__) || defined(__aarch64__)
26 return pc + 4;
2727#elif SANITIZER_RISCV64
2828 // Current check order is 4 -> 2 -> 6 -> 8
2929 u8 InsnByte = *(u8 *)(pc);
......@@ -46,8 +46,10 @@ uptr StackTrace::GetNextInstructionPc(uptr pc) {
4646 }
4747 // bail-out if could not figure out the instruction size
4848 return 0;
49#else
49#elif SANITIZER_S390 || SANITIZER_I386 || SANITIZER_X32 || SANITIZER_X64
5050 return pc + 1;
51#else
52 return pc + 4;
5153#endif
5254}
5355
......@@ -64,7 +66,7 @@ void BufferedStackTrace::Init(const uptr *pcs, uptr cnt, uptr extra_top_pc) {
6466 top_frame_bp = 0;
6567}
6668
67// Sparc implemention is in its own file.
69// Sparc implementation is in its own file.
6870#if !defined(__sparc__)
6971
7072// In GCC on ARM bp points to saved lr, not fp, so we should check the next
......@@ -119,7 +121,7 @@ void BufferedStackTrace::UnwindFast(uptr pc, uptr bp, uptr stack_top,
119121 uhwptr pc1 = caller_frame[2];
120122#elif defined(__s390__)
121123 uhwptr pc1 = frame[14];
122#elif defined(__riscv)
124#elif defined(__loongarch__) || defined(__riscv)
123125 // frame[-1] contains the return address
124126 uhwptr pc1 = frame[-1];
125127#else
......@@ -134,7 +136,7 @@ void BufferedStackTrace::UnwindFast(uptr pc, uptr bp, uptr stack_top,
134136 trace_buffer[size++] = (uptr) pc1;
135137 }
136138 bottom = (uptr)frame;
137#if defined(__riscv)
139#if defined(__loongarch__) || defined(__riscv)
138140 // frame[-2] contain fp of the previous frame
139141 uptr new_bp = (uptr)frame[-2];
140142#else
lib/tsan/sanitizer_common/sanitizer_stacktrace.h+9-10
......@@ -20,7 +20,7 @@ namespace __sanitizer {
2020
2121struct BufferedStackTrace;
2222
23static const u32 kStackTraceMax = 256;
23static const u32 kStackTraceMax = 255;
2424
2525#if SANITIZER_LINUX && defined(__mips__)
2626# define SANITIZER_CAN_FAST_UNWIND 0
......@@ -33,7 +33,7 @@ static const u32 kStackTraceMax = 256;
3333// Fast unwind is the only option on Mac for now; we will need to
3434// revisit this macro when slow unwind works on Mac, see
3535// https://github.com/google/sanitizers/issues/137
36#if SANITIZER_MAC
36#if SANITIZER_APPLE
3737# define SANITIZER_CAN_SLOW_UNWIND 0
3838#else
3939# define SANITIZER_CAN_SLOW_UNWIND 1
......@@ -88,21 +88,20 @@ uptr StackTrace::GetPreviousInstructionPc(uptr pc) {
8888 // so we return (pc-2) in that case in order to be safe.
8989 // For A32 mode we return (pc-4) because all instructions are 32 bit long.
9090 return (pc - 3) & (~1);
91#elif defined(__powerpc__) || defined(__powerpc64__) || defined(__aarch64__)
92 // PCs are always 4 byte aligned.
93 return pc - 4;
9491#elif defined(__sparc__) || defined(__mips__)
9592 return pc - 8;
9693#elif SANITIZER_RISCV64
97 // RV-64 has variable instruciton length...
94 // RV-64 has variable instruction length...
9895 // C extentions gives us 2-byte instructoins
9996 // RV-64 has 4-byte instructions
100 // + RISCV architecture allows instructions up to 8 bytes
97 // + RISC-V architecture allows instructions up to 8 bytes
10198 // It seems difficult to figure out the exact instruction length -
10299 // pc - 2 seems like a safe option for the purposes of stack tracing
103100 return pc - 2;
104#else
101#elif SANITIZER_S390 || SANITIZER_I386 || SANITIZER_X32 || SANITIZER_X64
105102 return pc - 1;
103#else
104 return pc - 4;
106105#endif
107106}
108107
......@@ -209,11 +208,11 @@ static inline bool IsValidFrame(uptr frame, uptr stack_top, uptr stack_bottom) {
209208// StackTrace::GetCurrentPc() faster.
210209#if defined(__x86_64__)
211210# define GET_CURRENT_PC() \
212 ({ \
211 (__extension__({ \
213212 uptr pc; \
214213 asm("lea 0(%%rip), %0" : "=r"(pc)); \
215214 pc; \
216 })
215 }))
217216#else
218217# define GET_CURRENT_PC() StackTrace::GetCurrentPc()
219218#endif
lib/tsan/sanitizer_common/sanitizer_stacktrace_libcdep.cpp+8-7
......@@ -64,7 +64,7 @@ class StackTraceTextPrinter {
6464 if (dedup_token_->length())
6565 dedup_token_->append("--");
6666 if (stack->info.function != nullptr)
67 dedup_token_->append(stack->info.function);
67 dedup_token_->append("%s", stack->info.function);
6868 }
6969 }
7070
......@@ -166,8 +166,8 @@ void BufferedStackTrace::Unwind(u32 max_depth, uptr pc, uptr bp, void *context,
166166 UnwindFast(pc, bp, stack_top, stack_bottom, max_depth);
167167}
168168
169static int GetModuleAndOffsetForPc(uptr pc, char *module_name,
170 uptr module_name_len, uptr *pc_offset) {
169int GetModuleAndOffsetForPc(uptr pc, char *module_name, uptr module_name_len,
170 uptr *pc_offset) {
171171 const char *found_module_name = nullptr;
172172 bool ok = Symbolizer::GetOrInit()->GetModuleNameAndOffsetForPC(
173173 pc, &found_module_name, pc_offset);
......@@ -216,10 +216,11 @@ void __sanitizer_symbolize_global(uptr data_addr, const char *fmt,
216216}
217217
218218SANITIZER_INTERFACE_ATTRIBUTE
219int __sanitizer_get_module_and_offset_for_pc(uptr pc, char *module_name,
219int __sanitizer_get_module_and_offset_for_pc(void *pc, char *module_name,
220220 uptr module_name_len,
221 uptr *pc_offset) {
222 return __sanitizer::GetModuleAndOffsetForPc(pc, module_name, module_name_len,
223 pc_offset);
221 void **pc_offset) {
222 return __sanitizer::GetModuleAndOffsetForPc(
223 reinterpret_cast<uptr>(pc), module_name, module_name_len,
224 reinterpret_cast<uptr *>(pc_offset));
224225}
225226} // extern "C"
lib/tsan/sanitizer_common/sanitizer_stacktrace_printer.cpp+66-21
......@@ -11,25 +11,47 @@
1111//===----------------------------------------------------------------------===//
1212
1313#include "sanitizer_stacktrace_printer.h"
14
1415#include "sanitizer_file.h"
16#include "sanitizer_flags.h"
1517#include "sanitizer_fuchsia.h"
1618
1719namespace __sanitizer {
1820
19// sanitizer_symbolizer_markup.cpp implements these differently.
20#if !SANITIZER_SYMBOLIZER_MARKUP
21
22static const char *StripFunctionName(const char *function, const char *prefix) {
23 if (!function) return nullptr;
24 if (!prefix) return function;
25 uptr prefix_len = internal_strlen(prefix);
26 if (0 == internal_strncmp(function, prefix, prefix_len))
27 return function + prefix_len;
21const char *StripFunctionName(const char *function) {
22 if (!common_flags()->demangle)
23 return function;
24 if (!function)
25 return nullptr;
26 auto try_strip = [function](const char *prefix) -> const char * {
27 const uptr prefix_len = internal_strlen(prefix);
28 if (!internal_strncmp(function, prefix, prefix_len))
29 return function + prefix_len;
30 return nullptr;
31 };
32 if (SANITIZER_APPLE) {
33 if (const char *s = try_strip("wrap_"))
34 return s;
35 } else if (SANITIZER_WINDOWS) {
36 if (const char *s = try_strip("__asan_wrap_"))
37 return s;
38 } else {
39 if (const char *s = try_strip("___interceptor_"))
40 return s;
41 if (const char *s = try_strip("__interceptor_"))
42 return s;
43 }
2844 return function;
2945}
3046
47// sanitizer_symbolizer_markup.cpp implements these differently.
48#if !SANITIZER_SYMBOLIZER_MARKUP
49
3150static const char *DemangleFunctionName(const char *function) {
32 if (!function) return nullptr;
51 if (!common_flags()->demangle)
52 return function;
53 if (!function)
54 return nullptr;
3355
3456 // NetBSD uses indirection for old threading functions for historical reasons
3557 // The mangled names are internal implementation detail and should not be
......@@ -104,11 +126,24 @@ static const char *DemangleFunctionName(const char *function) {
104126 return function;
105127}
106128
129static void MaybeBuildIdToBuffer(const AddressInfo &info, bool PrefixSpace,
130 InternalScopedString *buffer) {
131 if (info.uuid_size) {
132 if (PrefixSpace)
133 buffer->append(" ");
134 buffer->append("(BuildId: ");
135 for (uptr i = 0; i < info.uuid_size; ++i) {
136 buffer->append("%02x", info.uuid[i]);
137 }
138 buffer->append(")");
139 }
140}
141
107142static const char kDefaultFormat[] = " #%n %p %F %L";
108143
109144void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
110145 uptr address, const AddressInfo *info, bool vs_style,
111 const char *strip_path_prefix, const char *strip_func_prefix) {
146 const char *strip_path_prefix) {
112147 // info will be null in the case where symbolization is not needed for the
113148 // given format. This ensures that the code below will get a hard failure
114149 // rather than print incorrect information in case RenderNeedsSymbolization
......@@ -129,7 +164,7 @@ void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
129164 break;
130165 // Frame number and all fields of AddressInfo structure.
131166 case 'n':
132 buffer->append("%zu", frame_no);
167 buffer->append("%u", frame_no);
133168 break;
134169 case 'p':
135170 buffer->append("0x%zx", address);
......@@ -140,9 +175,12 @@ void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
140175 case 'o':
141176 buffer->append("0x%zx", info->module_offset);
142177 break;
178 case 'b':
179 MaybeBuildIdToBuffer(*info, /*PrefixSpace=*/false, buffer);
180 break;
143181 case 'f':
144 buffer->append("%s", DemangleFunctionName(StripFunctionName(
145 info->function, strip_func_prefix)));
182 buffer->append("%s",
183 DemangleFunctionName(StripFunctionName(info->function)));
146184 break;
147185 case 'q':
148186 buffer->append("0x%zx", info->function_offset != AddressInfo::kUnknown
......@@ -162,8 +200,8 @@ void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
162200 case 'F':
163201 // Function name and offset, if file is unknown.
164202 if (info->function) {
165 buffer->append("in %s", DemangleFunctionName(StripFunctionName(
166 info->function, strip_func_prefix)));
203 buffer->append("in %s",
204 DemangleFunctionName(StripFunctionName(info->function)));
167205 if (!info->file && info->function_offset != AddressInfo::kUnknown)
168206 buffer->append("+0x%zx", info->function_offset);
169207 }
......@@ -181,6 +219,10 @@ void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
181219 } else if (info->module) {
182220 RenderModuleLocation(buffer, info->module, info->module_offset,
183221 info->module_arch, strip_path_prefix);
222
223#if !SANITIZER_APPLE
224 MaybeBuildIdToBuffer(*info, /*PrefixSpace=*/true, buffer);
225#endif
184226 } else {
185227 buffer->append("(<unknown module>)");
186228 }
......@@ -193,13 +235,16 @@ void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
193235 // Always strip the module name for %M.
194236 RenderModuleLocation(buffer, StripModuleName(info->module),
195237 info->module_offset, info->module_arch, "");
238#if !SANITIZER_APPLE
239 MaybeBuildIdToBuffer(*info, /*PrefixSpace=*/true, buffer);
240#endif
196241 } else {
197242 buffer->append("(%p)", (void *)address);
198243 }
199244 break;
200245 default:
201 Report("Unsupported specifier in stack frame format: %c (0x%zx)!\n", *p,
202 *p);
246 Report("Unsupported specifier in stack frame format: %c (%p)!\n", *p,
247 (void *)p);
203248 Die();
204249 }
205250 }
......@@ -244,14 +289,14 @@ void RenderData(InternalScopedString *buffer, const char *format,
244289 buffer->append("%s", StripPathPrefix(DI->file, strip_path_prefix));
245290 break;
246291 case 'l':
247 buffer->append("%d", DI->line);
292 buffer->append("%zu", DI->line);
248293 break;
249294 case 'g':
250295 buffer->append("%s", DI->name);
251296 break;
252297 default:
253 Report("Unsupported specifier in stack frame format: %c (0x%zx)!\n", *p,
254 *p);
298 Report("Unsupported specifier in stack frame format: %c (%p)!\n", *p,
299 (void *)p);
255300 Die();
256301 }
257302 }
lib/tsan/sanitizer_common/sanitizer_stacktrace_printer.h+5-4
......@@ -17,6 +17,9 @@
1717
1818namespace __sanitizer {
1919
20// Strip interceptor prefixes from function name.
21const char *StripFunctionName(const char *function);
22
2023// Render the contents of "info" structure, which represents the contents of
2124// stack frame "frame_no" and appends it to the "buffer". "format" is a
2225// string with placeholders, which is copied to the output with
......@@ -26,8 +29,7 @@ namespace __sanitizer {
2629// will be turned into
2730// " frame 10: function foo::bar() at my/file.cc:10"
2831// You may additionally pass "strip_path_prefix" to strip prefixes of paths to
29// source files and modules, and "strip_func_prefix" to strip prefixes of
30// function names.
32// source files and modules.
3133// Here's the full list of available placeholders:
3234// %% - represents a '%' character;
3335// %n - frame number (copy of frame_no);
......@@ -48,8 +50,7 @@ namespace __sanitizer {
4850// %M - prints module basename and offset, if it is known, or PC.
4951void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
5052 uptr address, const AddressInfo *info, bool vs_style,
51 const char *strip_path_prefix = "",
52 const char *strip_func_prefix = "");
53 const char *strip_path_prefix = "");
5354
5455bool RenderNeedsSymbolization(const char *format);
5556
lib/tsan/sanitizer_common/sanitizer_stacktrace_sparc.cpp+1-7
......@@ -9,7 +9,7 @@
99// This file is shared between AddressSanitizer and ThreadSanitizer
1010// run-time libraries.
1111//
12// Implemention of fast stack unwinding for Sparc.
12// Implementation of fast stack unwinding for Sparc.
1313//===----------------------------------------------------------------------===//
1414
1515#if defined(__sparc__)
......@@ -30,13 +30,7 @@ void BufferedStackTrace::UnwindFast(uptr pc, uptr bp, uptr stack_top,
3030 // TODO(yln): add arg sanity check for stack_top/stack_bottom
3131 CHECK_GE(max_depth, 2);
3232 const uptr kPageSize = GetPageSizeCached();
33#if defined(__GNUC__)
34 // __builtin_return_address returns the address of the call instruction
35 // on the SPARC and not the return address, so we need to compensate.
36 trace_buffer[0] = GetNextInstructionPc(pc);
37#else
3833 trace_buffer[0] = pc;
39#endif
4034 size = 1;
4135 if (stack_top < 4096) return; // Sanity check for stack top.
4236 // Flush register windows to memory
lib/tsan/sanitizer_common/sanitizer_stoptheworld_fuchsia.h created+20
......@@ -0,0 +1,20 @@
1//===-- sanitizer_stoptheworld_fuchsia.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#ifndef SANITIZER_STOPTHEWORLD_FUCHSIA_H
10#define SANITIZER_STOPTHEWORLD_FUCHSIA_H
11
12#include "sanitizer_stoptheworld.h"
13
14namespace __sanitizer {
15
16class SuspendedThreadsListFuchsia final : public SuspendedThreadsList {};
17
18} // namespace __sanitizer
19
20#endif // SANITIZER_STOPTHEWORLD_FUCHSIA_H
lib/tsan/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp+11-3
......@@ -16,7 +16,7 @@
1616#if SANITIZER_LINUX && \
1717 (defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) || \
1818 defined(__powerpc64__) || defined(__s390__) || defined(__i386__) || \
19 defined(__arm__) || SANITIZER_RISCV64)
19 defined(__arm__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64)
2020
2121#include "sanitizer_stoptheworld.h"
2222
......@@ -31,7 +31,8 @@
3131#include <sys/types.h> // for pid_t
3232#include <sys/uio.h> // for iovec
3333#include <elf.h> // for NT_PRSTATUS
34#if (defined(__aarch64__) || SANITIZER_RISCV64) && !SANITIZER_ANDROID
34#if (defined(__aarch64__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64) && \
35 !SANITIZER_ANDROID
3536// GLIBC 2.20+ sys/user does not include asm/ptrace.h
3637# include <asm/ptrace.h>
3738#endif
......@@ -108,7 +109,7 @@ struct TracerThreadArgument {
108109 void *callback_argument;
109110 // The tracer thread waits on this mutex while the parent finishes its
110111 // preparations.
111 BlockingMutex mutex;
112 Mutex mutex;
112113 // Tracer thread signals its completion by setting done.
113114 atomic_uintptr_t done;
114115 uptr parent_pid;
......@@ -514,6 +515,12 @@ typedef struct user_pt_regs regs_struct;
514515static constexpr uptr kExtraRegs[] = {0};
515516#define ARCH_IOVEC_FOR_GETREGSET
516517
518#elif defined(__loongarch__)
519typedef struct user_pt_regs regs_struct;
520#define REG_SP regs[3]
521static constexpr uptr kExtraRegs[] = {0};
522#define ARCH_IOVEC_FOR_GETREGSET
523
517524#elif SANITIZER_RISCV64
518525typedef struct user_regs_struct regs_struct;
519526// sys/ucontext.h already defines REG_SP as 2. Undefine it first.
......@@ -621,3 +628,4 @@ PtraceRegistersStatus SuspendedThreadsListLinux::GetRegistersAndSP(
621628#endif // SANITIZER_LINUX && (defined(__x86_64__) || defined(__mips__)
622629 // || defined(__aarch64__) || defined(__powerpc64__)
623630 // || defined(__s390__) || defined(__i386__) || defined(__arm__)
631 // || SANITIZER_LOONGARCH64
lib/tsan/sanitizer_common/sanitizer_stoptheworld_mac.cpp+10-9
......@@ -12,7 +12,7 @@
1212
1313#include "sanitizer_platform.h"
1414
15#if SANITIZER_MAC && (defined(__x86_64__) || defined(__aarch64__) || \
15#if SANITIZER_APPLE && (defined(__x86_64__) || defined(__aarch64__) || \
1616 defined(__i386))
1717
1818#include <mach/mach.h>
......@@ -29,7 +29,7 @@ typedef struct {
2929
3030class SuspendedThreadsListMac final : public SuspendedThreadsList {
3131 public:
32 SuspendedThreadsListMac() : threads_(1024) {}
32 SuspendedThreadsListMac() = default;
3333
3434 tid_t GetThreadID(uptr index) const override;
3535 thread_t GetThread(uptr index) const;
......@@ -87,11 +87,13 @@ void StopTheWorld(StopTheWorldCallback callback, void *argument) {
8787
8888#if defined(__x86_64__)
8989typedef x86_thread_state64_t regs_struct;
90#define regs_flavor x86_THREAD_STATE64
9091
9192#define SP_REG __rsp
9293
9394#elif defined(__aarch64__)
9495typedef arm_thread_state64_t regs_struct;
96#define regs_flavor ARM_THREAD_STATE64
9597
9698# if __DARWIN_UNIX03
9799# define SP_REG __sp
......@@ -101,6 +103,7 @@ typedef arm_thread_state64_t regs_struct;
101103
102104#elif defined(__i386)
103105typedef x86_thread_state32_t regs_struct;
106#define regs_flavor x86_THREAD_STATE32
104107
105108#define SP_REG __esp
106109
......@@ -146,17 +149,15 @@ PtraceRegistersStatus SuspendedThreadsListMac::GetRegistersAndSP(
146149 thread_t thread = GetThread(index);
147150 regs_struct regs;
148151 int err;
149 mach_msg_type_number_t reg_count = MACHINE_THREAD_STATE_COUNT;
150 err = thread_get_state(thread, MACHINE_THREAD_STATE, (thread_state_t)&regs,
152 mach_msg_type_number_t reg_count = sizeof(regs) / sizeof(natural_t);
153 err = thread_get_state(thread, regs_flavor, (thread_state_t)&regs,
151154 &reg_count);
152155 if (err != KERN_SUCCESS) {
153156 VReport(1, "Error - unable to get registers for a thread\n");
154 // KERN_INVALID_ARGUMENT indicates that either the flavor is invalid,
155 // or the thread does not exist. The other possible error case,
156157 // MIG_ARRAY_TOO_LARGE, means that the state is too large, but it's
157158 // still safe to proceed.
158 return err == KERN_INVALID_ARGUMENT ? REGISTERS_UNAVAILABLE_FATAL
159 : REGISTERS_UNAVAILABLE;
159 return err == MIG_ARRAY_TOO_LARGE ? REGISTERS_UNAVAILABLE
160 : REGISTERS_UNAVAILABLE_FATAL;
160161 }
161162
162163 buffer->resize(RoundUpTo(sizeof(regs), sizeof(uptr)) / sizeof(uptr));
......@@ -176,5 +177,5 @@ PtraceRegistersStatus SuspendedThreadsListMac::GetRegistersAndSP(
176177
177178} // namespace __sanitizer
178179
179#endif // SANITIZER_MAC && (defined(__x86_64__) || defined(__aarch64__)) ||
180#endif // SANITIZER_APPLE && (defined(__x86_64__) || defined(__aarch64__)) ||
180181 // defined(__i386))
lib/tsan/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp+1-1
......@@ -68,7 +68,7 @@ class SuspendedThreadsListNetBSD final : public SuspendedThreadsList {
6868struct TracerThreadArgument {
6969 StopTheWorldCallback callback;
7070 void *callback_argument;
71 BlockingMutex mutex;
71 Mutex mutex;
7272 atomic_uintptr_t done;
7373 uptr parent_pid;
7474};
lib/tsan/sanitizer_common/sanitizer_stoptheworld_win.cpp created+175
......@@ -0,0 +1,175 @@
1//===-- sanitizer_stoptheworld_win.cpp ------------------------------------===//
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// See sanitizer_stoptheworld.h for details.
10//
11//===----------------------------------------------------------------------===//
12
13#include "sanitizer_platform.h"
14
15#if SANITIZER_WINDOWS
16
17# define WIN32_LEAN_AND_MEAN
18# include <windows.h>
19// windows.h needs to be included before tlhelp32.h
20# include <tlhelp32.h>
21
22# include "sanitizer_stoptheworld.h"
23
24namespace __sanitizer {
25
26namespace {
27
28struct SuspendedThreadsListWindows final : public SuspendedThreadsList {
29 InternalMmapVector<HANDLE> threadHandles;
30 InternalMmapVector<DWORD> threadIds;
31
32 SuspendedThreadsListWindows() {
33 threadIds.reserve(1024);
34 threadHandles.reserve(1024);
35 }
36
37 PtraceRegistersStatus GetRegistersAndSP(uptr index,
38 InternalMmapVector<uptr> *buffer,
39 uptr *sp) const override;
40
41 tid_t GetThreadID(uptr index) const override;
42 uptr ThreadCount() const override;
43};
44
45// Stack Pointer register names on different architectures
46# if SANITIZER_X64
47# define SP_REG Rsp
48# elif SANITIZER_I386
49# define SP_REG Esp
50# elif SANITIZER_ARM | SANITIZER_ARM64
51# define SP_REG Sp
52# else
53# error Architecture not supported!
54# endif
55
56PtraceRegistersStatus SuspendedThreadsListWindows::GetRegistersAndSP(
57 uptr index, InternalMmapVector<uptr> *buffer, uptr *sp) const {
58 CHECK_LT(index, threadHandles.size());
59
60 buffer->resize(RoundUpTo(sizeof(CONTEXT), sizeof(uptr)) / sizeof(uptr));
61 CONTEXT *thread_context = reinterpret_cast<CONTEXT *>(buffer->data());
62 thread_context->ContextFlags = CONTEXT_ALL;
63 CHECK(GetThreadContext(threadHandles[index], thread_context));
64 *sp = thread_context->SP_REG;
65
66 return REGISTERS_AVAILABLE;
67}
68
69tid_t SuspendedThreadsListWindows::GetThreadID(uptr index) const {
70 CHECK_LT(index, threadIds.size());
71 return threadIds[index];
72}
73
74uptr SuspendedThreadsListWindows::ThreadCount() const {
75 return threadIds.size();
76}
77
78struct RunThreadArgs {
79 StopTheWorldCallback callback;
80 void *argument;
81};
82
83DWORD WINAPI RunThread(void *argument) {
84 RunThreadArgs *run_args = (RunThreadArgs *)argument;
85
86 const DWORD this_thread = GetCurrentThreadId();
87 const DWORD this_process = GetCurrentProcessId();
88
89 SuspendedThreadsListWindows suspended_threads_list;
90 bool new_thread_found;
91
92 do {
93 // Take a snapshot of all Threads
94 const HANDLE threads = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
95 CHECK(threads != INVALID_HANDLE_VALUE);
96
97 THREADENTRY32 thread_entry;
98 thread_entry.dwSize = sizeof(thread_entry);
99 new_thread_found = false;
100
101 if (!Thread32First(threads, &thread_entry))
102 break;
103
104 do {
105 if (thread_entry.th32ThreadID == this_thread ||
106 thread_entry.th32OwnerProcessID != this_process)
107 continue;
108
109 bool suspended_thread = false;
110 for (const auto thread_id : suspended_threads_list.threadIds) {
111 if (thread_id == thread_entry.th32ThreadID) {
112 suspended_thread = true;
113 break;
114 }
115 }
116
117 // Skip the Thread if it was already suspended
118 if (suspended_thread)
119 continue;
120
121 const HANDLE thread =
122 OpenThread(THREAD_ALL_ACCESS, FALSE, thread_entry.th32ThreadID);
123 CHECK(thread);
124
125 if (SuspendThread(thread) == (DWORD)-1) {
126 DWORD last_error = GetLastError();
127
128 VPrintf(1, "Could not suspend thread %lu (error %lu)",
129 thread_entry.th32ThreadID, last_error);
130 continue;
131 }
132
133 suspended_threads_list.threadIds.push_back(thread_entry.th32ThreadID);
134 suspended_threads_list.threadHandles.push_back(thread);
135 new_thread_found = true;
136 } while (Thread32Next(threads, &thread_entry));
137
138 CloseHandle(threads);
139
140 // Between the call to `CreateToolhelp32Snapshot` and suspending the
141 // relevant Threads, new Threads could have potentially been created. So
142 // continue to find and suspend new Threads until we don't find any.
143 } while (new_thread_found);
144
145 // Now all Threads of this Process except of this Thread should be suspended.
146 // Execute the callback function.
147 run_args->callback(suspended_threads_list, run_args->argument);
148
149 // Resume all Threads
150 for (const auto suspended_thread_handle :
151 suspended_threads_list.threadHandles) {
152 CHECK_NE(ResumeThread(suspended_thread_handle), -1);
153 CloseHandle(suspended_thread_handle);
154 }
155
156 return 0;
157}
158
159} // namespace
160
161void StopTheWorld(StopTheWorldCallback callback, void *argument) {
162 struct RunThreadArgs arg = {callback, argument};
163 DWORD trace_thread_id;
164
165 auto trace_thread =
166 CreateThread(nullptr, 0, RunThread, &arg, 0, &trace_thread_id);
167 CHECK(trace_thread);
168
169 WaitForSingleObject(trace_thread, INFINITE);
170 CloseHandle(trace_thread);
171}
172
173} // namespace __sanitizer
174
175#endif // SANITIZER_WINDOWS
lib/tsan/sanitizer_common/sanitizer_suppressions.cpp+1
......@@ -86,6 +86,7 @@ void SuppressionContext::ParseFromFile(const char *filename) {
8686 }
8787
8888 Parse(file_contents);
89 UnmapOrDie(file_contents, contents_size);
8990}
9091
9192bool SuppressionContext::Match(const char *str, const char *type,
lib/tsan/sanitizer_common/sanitizer_symbolizer.cpp+13-7
......@@ -11,10 +11,11 @@
1111//===----------------------------------------------------------------------===//
1212
1313#include "sanitizer_allocator_internal.h"
14#include "sanitizer_platform.h"
14#include "sanitizer_common.h"
1515#include "sanitizer_internal_defs.h"
1616#include "sanitizer_libc.h"
1717#include "sanitizer_placement_new.h"
18#include "sanitizer_platform.h"
1819#include "sanitizer_symbolizer_internal.h"
1920
2021namespace __sanitizer {
......@@ -30,6 +31,7 @@ void AddressInfo::Clear() {
3031 InternalFree(file);
3132 internal_memset(this, 0, sizeof(AddressInfo));
3233 function_offset = kUnknown;
34 uuid_size = 0;
3335}
3436
3537void AddressInfo::FillModuleInfo(const char *mod_name, uptr mod_offset,
......@@ -37,6 +39,16 @@ void AddressInfo::FillModuleInfo(const char *mod_name, uptr mod_offset,
3739 module = internal_strdup(mod_name);
3840 module_offset = mod_offset;
3941 module_arch = mod_arch;
42 uuid_size = 0;
43}
44
45void AddressInfo::FillModuleInfo(const LoadedModule &mod) {
46 module = internal_strdup(mod.full_name());
47 module_offset = address - mod.base_address();
48 module_arch = mod.arch();
49 if (mod.uuid_size())
50 internal_memcpy(uuid, mod.uuid(), mod.uuid_size());
51 uuid_size = mod.uuid_size();
4052}
4153
4254SymbolizedStack::SymbolizedStack() : next(nullptr), info() {}
......@@ -126,10 +138,4 @@ Symbolizer::SymbolizerScope::~SymbolizerScope() {
126138 sym_->end_hook_();
127139}
128140
129void Symbolizer::LateInitializeTools() {
130 for (auto &tool : tools_) {
131 tool.LateInitialize();
132 }
133}
134
135141} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_symbolizer.h+7-6
......@@ -32,6 +32,8 @@ struct AddressInfo {
3232 char *module;
3333 uptr module_offset;
3434 ModuleArch module_arch;
35 u8 uuid[kModuleUUIDSize];
36 uptr uuid_size;
3537
3638 static const uptr kUnknown = ~(uptr)0;
3739 char *function;
......@@ -45,6 +47,8 @@ struct AddressInfo {
4547 // Deletes all strings and resets all fields.
4648 void Clear();
4749 void FillModuleInfo(const char *mod_name, uptr mod_offset, ModuleArch arch);
50 void FillModuleInfo(const LoadedModule &mod);
51 uptr module_base() const { return address - module_offset; }
4852};
4953
5054// Linked list of symbolized frames (each frame is described by AddressInfo).
......@@ -158,7 +162,7 @@ class Symbolizer final {
158162 // its method should be protected by |mu_|.
159163 class ModuleNameOwner {
160164 public:
161 explicit ModuleNameOwner(BlockingMutex *synchronized_by)
165 explicit ModuleNameOwner(Mutex *synchronized_by)
162166 : last_match_(nullptr), mu_(synchronized_by) {
163167 storage_.reserve(kInitialCapacity);
164168 }
......@@ -169,7 +173,7 @@ class Symbolizer final {
169173 InternalMmapVector<const char*> storage_;
170174 const char *last_match_;
171175
172 BlockingMutex *mu_;
176 Mutex *mu_;
173177 } module_names_;
174178
175179 /// Platform-specific function for creating a Symbolizer object.
......@@ -192,7 +196,7 @@ class Symbolizer final {
192196 // Mutex locked from public methods of |Symbolizer|, so that the internals
193197 // (including individual symbolizer tools and platform-specific methods) are
194198 // always synchronized.
195 BlockingMutex mu_;
199 Mutex mu_;
196200
197201 IntrusiveList<SymbolizerTool> tools_;
198202
......@@ -209,9 +213,6 @@ class Symbolizer final {
209213 private:
210214 const Symbolizer *sym_;
211215 };
212
213 // Calls `LateInitialize()` on all items in `tools_`.
214 void LateInitializeTools();
215216};
216217
217218#ifdef SANITIZER_WINDOWS
lib/tsan/sanitizer_common/sanitizer_symbolizer_internal.h+6-11
......@@ -13,15 +13,15 @@
1313#ifndef SANITIZER_SYMBOLIZER_INTERNAL_H
1414#define SANITIZER_SYMBOLIZER_INTERNAL_H
1515
16#include "sanitizer_symbolizer.h"
1716#include "sanitizer_file.h"
17#include "sanitizer_symbolizer.h"
1818#include "sanitizer_vector.h"
1919
2020namespace __sanitizer {
2121
2222// Parsing helpers, 'str' is searched for delimiter(s) and a string or uptr
2323// is extracted. When extracting a string, a newly allocated (using
24// InternalAlloc) and null-terminataed buffer is returned. They return a pointer
24// InternalAlloc) and null-terminated buffer is returned. They return a pointer
2525// to the next characted after the found delimiter.
2626const char *ExtractToken(const char *str, const char *delims, char **result);
2727const char *ExtractInt(const char *str, const char *delims, int *result);
......@@ -70,11 +70,6 @@ class SymbolizerTool {
7070 return nullptr;
7171 }
7272
73 // Called during the LateInitialize phase of Sanitizer initialization.
74 // Usually this is a safe place to call code that might need to use user
75 // memory allocators.
76 virtual void LateInitialize() {}
77
7873 protected:
7974 ~SymbolizerTool() {}
8075};
......@@ -91,13 +86,14 @@ class SymbolizerProcess {
9186 ~SymbolizerProcess() {}
9287
9388 /// The maximum number of arguments required to invoke a tool process.
94 static const unsigned kArgVMax = 6;
89 static const unsigned kArgVMax = 16;
9590
9691 // Customizable by subclasses.
9792 virtual bool StartSymbolizerSubprocess();
98 virtual bool ReadFromSymbolizer(char *buffer, uptr max_length);
93 virtual bool ReadFromSymbolizer();
9994 // Return the environment to run the symbolizer in.
10095 virtual char **GetEnvP() { return GetEnviron(); }
96 InternalMmapVector<char> &GetBuff() { return buffer_; }
10197
10298 private:
10399 virtual bool ReachedEndOfOutput(const char *buffer, uptr length) const {
......@@ -118,8 +114,7 @@ class SymbolizerProcess {
118114 fd_t input_fd_;
119115 fd_t output_fd_;
120116
121 static const uptr kBufferSize = 16 * 1024;
122 char buffer_[kBufferSize];
117 InternalMmapVector<char> buffer_;
123118
124119 static const uptr kMaxTimesRestarted = 5;
125120 static const int kSymbolizerStartupTimeMillis = 10;
lib/tsan/sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp+2-2
......@@ -11,11 +11,11 @@
1111// Libbacktrace implementation of symbolizer parts.
1212//===----------------------------------------------------------------------===//
1313
14#include "sanitizer_platform.h"
14#include "sanitizer_symbolizer_libbacktrace.h"
1515
1616#include "sanitizer_internal_defs.h"
17#include "sanitizer_platform.h"
1718#include "sanitizer_symbolizer.h"
18#include "sanitizer_symbolizer_libbacktrace.h"
1919
2020#if SANITIZER_LIBBACKTRACE
2121# include "backtrace-supported.h"
lib/tsan/sanitizer_common/sanitizer_symbolizer_libcdep.cpp+51-40
......@@ -83,16 +83,13 @@ const char *ExtractTokenUpToDelimiter(const char *str, const char *delimiter,
8383}
8484
8585SymbolizedStack *Symbolizer::SymbolizePC(uptr addr) {
86 BlockingMutexLock l(&mu_);
87 const char *module_name = nullptr;
88 uptr module_offset;
89 ModuleArch arch;
86 Lock l(&mu_);
9087 SymbolizedStack *res = SymbolizedStack::New(addr);
91 if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset,
92 &arch))
88 auto *mod = FindModuleForAddress(addr);
89 if (!mod)
9390 return res;
9491 // Always fill data about module name and offset.
95 res->info.FillModuleInfo(module_name, module_offset, arch);
92 res->info.FillModuleInfo(*mod);
9693 for (auto &tool : tools_) {
9794 SymbolizerScope sym_scope(this);
9895 if (tool.SymbolizePC(addr, res)) {
......@@ -103,7 +100,7 @@ SymbolizedStack *Symbolizer::SymbolizePC(uptr addr) {
103100}
104101
105102bool Symbolizer::SymbolizeData(uptr addr, DataInfo *info) {
106 BlockingMutexLock l(&mu_);
103 Lock l(&mu_);
107104 const char *module_name = nullptr;
108105 uptr module_offset;
109106 ModuleArch arch;
......@@ -124,7 +121,7 @@ bool Symbolizer::SymbolizeData(uptr addr, DataInfo *info) {
124121}
125122
126123bool Symbolizer::SymbolizeFrame(uptr addr, FrameInfo *info) {
127 BlockingMutexLock l(&mu_);
124 Lock l(&mu_);
128125 const char *module_name = nullptr;
129126 if (!FindModuleNameAndOffsetForAddress(
130127 addr, &module_name, &info->module_offset, &info->module_arch))
......@@ -141,7 +138,7 @@ bool Symbolizer::SymbolizeFrame(uptr addr, FrameInfo *info) {
141138
142139bool Symbolizer::GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
143140 uptr *module_address) {
144 BlockingMutexLock l(&mu_);
141 Lock l(&mu_);
145142 const char *internal_module_name = nullptr;
146143 ModuleArch arch;
147144 if (!FindModuleNameAndOffsetForAddress(pc, &internal_module_name,
......@@ -154,7 +151,7 @@ bool Symbolizer::GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
154151}
155152
156153void Symbolizer::Flush() {
157 BlockingMutexLock l(&mu_);
154 Lock l(&mu_);
158155 for (auto &tool : tools_) {
159156 SymbolizerScope sym_scope(this);
160157 tool.Flush();
......@@ -162,7 +159,7 @@ void Symbolizer::Flush() {
162159}
163160
164161const char *Symbolizer::Demangle(const char *name) {
165 BlockingMutexLock l(&mu_);
162 Lock l(&mu_);
166163 for (auto &tool : tools_) {
167164 SymbolizerScope sym_scope(this);
168165 if (const char *demangled = tool.Demangle(name))
......@@ -240,7 +237,7 @@ const LoadedModule *Symbolizer::FindModuleForAddress(uptr address) {
240237class LLVMSymbolizerProcess final : public SymbolizerProcess {
241238 public:
242239 explicit LLVMSymbolizerProcess(const char *path)
243 : SymbolizerProcess(path, /*use_posix_spawn=*/SANITIZER_MAC) {}
240 : SymbolizerProcess(path, /*use_posix_spawn=*/SANITIZER_APPLE) {}
244241
245242 private:
246243 bool ReachedEndOfOutput(const char *buffer, uptr length) const override {
......@@ -259,6 +256,8 @@ class LLVMSymbolizerProcess final : public SymbolizerProcess {
259256 const char* const kSymbolizerArch = "--default-arch=x86_64";
260257#elif defined(__i386__)
261258 const char* const kSymbolizerArch = "--default-arch=i386";
259#elif SANITIZER_LOONGARCH64
260 const char *const kSymbolizerArch = "--default-arch=loongarch64";
262261#elif SANITIZER_RISCV64
263262 const char *const kSymbolizerArch = "--default-arch=riscv64";
264263#elif defined(__aarch64__)
......@@ -277,14 +276,17 @@ class LLVMSymbolizerProcess final : public SymbolizerProcess {
277276 const char* const kSymbolizerArch = "--default-arch=unknown";
278277#endif
279278
280 const char *const inline_flag = common_flags()->symbolize_inline_frames
281 ? "--inlines"
282 : "--no-inlines";
279 const char *const demangle_flag =
280 common_flags()->demangle ? "--demangle" : "--no-demangle";
281 const char *const inline_flag =
282 common_flags()->symbolize_inline_frames ? "--inlines" : "--no-inlines";
283283 int i = 0;
284284 argv[i++] = path_to_binary;
285 argv[i++] = demangle_flag;
285286 argv[i++] = inline_flag;
286287 argv[i++] = kSymbolizerArch;
287288 argv[i++] = nullptr;
289 CHECK_LE(i, kArgVMax);
288290 }
289291};
290292
......@@ -363,14 +365,21 @@ void ParseSymbolizePCOutput(const char *str, SymbolizedStack *res) {
363365 }
364366}
365367
366// Parses a two-line string in the following format:
368// Parses a two- or three-line string in the following format:
367369// <symbol_name>
368370// <start_address> <size>
369// Used by LLVMSymbolizer and InternalSymbolizer.
371// <filename>:<column>
372// Used by LLVMSymbolizer and InternalSymbolizer. LLVMSymbolizer added support
373// for symbolizing the third line in D123538, but we support the older two-line
374// information as well.
370375void ParseSymbolizeDataOutput(const char *str, DataInfo *info) {
371376 str = ExtractToken(str, "\n", &info->name);
372377 str = ExtractUptr(str, " ", &info->start);
373378 str = ExtractUptr(str, "\n", &info->size);
379 // Note: If the third line isn't present, these calls will set info.{file,
380 // line} to empty strings.
381 str = ExtractToken(str, ":", &info->file);
382 str = ExtractUptr(str, "\n", &info->line);
374383}
375384
376385static void ParseSymbolizeFrameOutput(const char *str,
......@@ -500,9 +509,9 @@ const char *SymbolizerProcess::SendCommandImpl(const char *command) {
500509 return nullptr;
501510 if (!WriteToSymbolizer(command, internal_strlen(command)))
502511 return nullptr;
503 if (!ReadFromSymbolizer(buffer_, kBufferSize))
504 return nullptr;
505 return buffer_;
512 if (!ReadFromSymbolizer())
513 return nullptr;
514 return buffer_.data();
506515}
507516
508517bool SymbolizerProcess::Restart() {
......@@ -513,31 +522,33 @@ bool SymbolizerProcess::Restart() {
513522 return StartSymbolizerSubprocess();
514523}
515524
516bool SymbolizerProcess::ReadFromSymbolizer(char *buffer, uptr max_length) {
517 if (max_length == 0)
518 return true;
519 uptr read_len = 0;
520 while (true) {
525bool SymbolizerProcess::ReadFromSymbolizer() {
526 buffer_.clear();
527 constexpr uptr max_length = 1024;
528 bool ret = true;
529 do {
521530 uptr just_read = 0;
522 bool success = ReadFromFile(input_fd_, buffer + read_len,
523 max_length - read_len - 1, &just_read);
531 uptr size_before = buffer_.size();
532 buffer_.resize(size_before + max_length);
533 buffer_.resize(buffer_.capacity());
534 bool ret = ReadFromFile(input_fd_, &buffer_[size_before],
535 buffer_.size() - size_before, &just_read);
536
537 if (!ret)
538 just_read = 0;
539
540 buffer_.resize(size_before + just_read);
541
524542 // We can't read 0 bytes, as we don't expect external symbolizer to close
525543 // its stdout.
526 if (!success || just_read == 0) {
544 if (just_read == 0) {
527545 Report("WARNING: Can't read from symbolizer at fd %d\n", input_fd_);
528 return false;
529 }
530 read_len += just_read;
531 if (ReachedEndOfOutput(buffer, read_len))
532 break;
533 if (read_len + 1 == max_length) {
534 Report("WARNING: Symbolizer buffer too small\n");
535 read_len = 0;
546 ret = false;
536547 break;
537548 }
538 }
539 buffer[read_len] = '\0';
540 return true;
549 } while (!ReachedEndOfOutput(buffer_.data(), buffer_.size()));
550 buffer_.push_back('\0');
551 return ret;
541552}
542553
543554bool SymbolizerProcess::WriteToSymbolizer(const char *buffer, uptr length) {
lib/tsan/sanitizer_common/sanitizer_symbolizer_mac.cpp+15-66
......@@ -12,19 +12,18 @@
1212//===----------------------------------------------------------------------===//
1313
1414#include "sanitizer_platform.h"
15#if SANITIZER_MAC
15#if SANITIZER_APPLE
1616
17#include "sanitizer_allocator_internal.h"
18#include "sanitizer_mac.h"
19#include "sanitizer_symbolizer_mac.h"
17# include <dlfcn.h>
18# include <errno.h>
19# include <stdlib.h>
20# include <sys/wait.h>
21# include <unistd.h>
22# include <util.h>
2023
21#include <dlfcn.h>
22#include <errno.h>
23#include <mach/mach.h>
24#include <stdlib.h>
25#include <sys/wait.h>
26#include <unistd.h>
27#include <util.h>
24# include "sanitizer_allocator_internal.h"
25# include "sanitizer_mac.h"
26# include "sanitizer_symbolizer_mac.h"
2827
2928namespace __sanitizer {
3029
......@@ -58,13 +57,6 @@ bool DlAddrSymbolizer::SymbolizeData(uptr addr, DataInfo *datainfo) {
5857 return true;
5958}
6059
61#define K_ATOS_ENV_VAR "__check_mach_ports_lookup"
62
63// This cannot live in `AtosSymbolizerProcess` because instances of that object
64// are allocated by the internal allocator which under ASan is poisoned with
65// kAsanInternalHeapMagic.
66static char kAtosMachPortEnvEntry[] = K_ATOS_ENV_VAR "=000000000000000";
67
6860class AtosSymbolizerProcess final : public SymbolizerProcess {
6961 public:
7062 explicit AtosSymbolizerProcess(const char *path)
......@@ -72,51 +64,13 @@ class AtosSymbolizerProcess final : public SymbolizerProcess {
7264 pid_str_[0] = '\0';
7365 }
7466
75 void LateInitialize() {
76 if (SANITIZER_IOSSIM) {
77 // `putenv()` may call malloc/realloc so it is only safe to do this
78 // during LateInitialize() or later (i.e. we can't do this in the
79 // constructor). We also can't do this in `StartSymbolizerSubprocess()`
80 // because in TSan we switch allocators when we're symbolizing.
81 // We use `putenv()` rather than `setenv()` so that we can later directly
82 // write into the storage without LibC getting involved to change what the
83 // variable is set to
84 int result = putenv(kAtosMachPortEnvEntry);
85 CHECK_EQ(result, 0);
86 }
87 }
88
8967 private:
9068 bool StartSymbolizerSubprocess() override {
91 // Configure sandbox before starting atos process.
92
9369 // Put the string command line argument in the object so that it outlives
9470 // the call to GetArgV.
95 internal_snprintf(pid_str_, sizeof(pid_str_), "%d", internal_getpid());
96
97 if (SANITIZER_IOSSIM) {
98 // `atos` in the simulator is restricted in its ability to retrieve the
99 // task port for the target process (us) so we need to do extra work
100 // to pass our task port to it.
101 mach_port_t ports[]{mach_task_self()};
102 kern_return_t ret =
103 mach_ports_register(mach_task_self(), ports, /*count=*/1);
104 CHECK_EQ(ret, KERN_SUCCESS);
105
106 // Set environment variable that signals to `atos` that it should look
107 // for our task port. We can't call `setenv()` here because it might call
108 // malloc/realloc. To avoid that we instead update the
109 // `mach_port_env_var_entry_` variable with our current PID.
110 uptr count = internal_snprintf(kAtosMachPortEnvEntry,
111 sizeof(kAtosMachPortEnvEntry),
112 K_ATOS_ENV_VAR "=%s", pid_str_);
113 CHECK_GE(count, sizeof(K_ATOS_ENV_VAR) + internal_strlen(pid_str_));
114 // Document our assumption but without calling `getenv()` in normal
115 // builds.
116 DCHECK(getenv(K_ATOS_ENV_VAR));
117 DCHECK_EQ(internal_strcmp(getenv(K_ATOS_ENV_VAR), pid_str_), 0);
118 }
71 internal_snprintf(pid_str_, sizeof(pid_str_), "%d", (int)internal_getpid());
11972
73 // Configure sandbox before starting atos process.
12074 return SymbolizerProcess::StartSymbolizerSubprocess();
12175 }
12276
......@@ -137,13 +91,10 @@ class AtosSymbolizerProcess final : public SymbolizerProcess {
13791 argv[i++] = "-d";
13892 }
13993 argv[i++] = nullptr;
94 CHECK_LE(i, kArgVMax);
14095 }
14196
14297 char pid_str_[16];
143 // Space for `\0` in `K_ATOS_ENV_VAR` is reused for `=`.
144 static_assert(sizeof(kAtosMachPortEnvEntry) ==
145 (sizeof(K_ATOS_ENV_VAR) + sizeof(pid_str_)),
146 "sizes should match");
14798};
14899
149100#undef K_ATOS_ENV_VAR
......@@ -212,7 +163,7 @@ bool AtosSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
212163 uptr start_address = AddressInfo::kUnknown;
213164 if (!ParseCommandOutput(buf, addr, &stack->info.function, &stack->info.module,
214165 &stack->info.file, &line, &start_address)) {
215 process_ = nullptr;
166 Report("WARNING: atos failed to symbolize address \"0x%zx\"\n", addr);
216167 return false;
217168 }
218169 stack->info.line = (int)line;
......@@ -249,8 +200,6 @@ bool AtosSymbolizer::SymbolizeData(uptr addr, DataInfo *info) {
249200 return true;
250201}
251202
252void AtosSymbolizer::LateInitialize() { process_->LateInitialize(); }
253
254203} // namespace __sanitizer
255204
256#endif // SANITIZER_MAC
205#endif // SANITIZER_APPLE
lib/tsan/sanitizer_common/sanitizer_symbolizer_mac.h+2-3
......@@ -15,7 +15,7 @@
1515#define SANITIZER_SYMBOLIZER_MAC_H
1616
1717#include "sanitizer_platform.h"
18#if SANITIZER_MAC
18#if SANITIZER_APPLE
1919
2020#include "sanitizer_symbolizer_internal.h"
2121
......@@ -35,7 +35,6 @@ class AtosSymbolizer final : public SymbolizerTool {
3535
3636 bool SymbolizePC(uptr addr, SymbolizedStack *stack) override;
3737 bool SymbolizeData(uptr addr, DataInfo *info) override;
38 void LateInitialize() override;
3938
4039 private:
4140 AtosSymbolizerProcess *process_;
......@@ -43,6 +42,6 @@ class AtosSymbolizer final : public SymbolizerTool {
4342
4443} // namespace __sanitizer
4544
46#endif // SANITIZER_MAC
45#endif // SANITIZER_APPLE
4746
4847#endif // SANITIZER_SYMBOLIZER_MAC_H
lib/tsan/sanitizer_common/sanitizer_symbolizer_markup.cpp+2-4
......@@ -91,7 +91,7 @@ bool RenderNeedsSymbolization(const char *format) { return false; }
9191// We don't support the stack_trace_format flag at all.
9292void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
9393 uptr address, const AddressInfo *info, bool vs_style,
94 const char *strip_path_prefix, const char *strip_func_prefix) {
94 const char *strip_path_prefix) {
9595 CHECK(!RenderNeedsSymbolization(format));
9696 buffer->append(kFormatFrame, frame_no, address);
9797}
......@@ -100,9 +100,7 @@ Symbolizer *Symbolizer::PlatformInit() {
100100 return new (symbolizer_allocator_) Symbolizer({});
101101}
102102
103void Symbolizer::LateInitialize() {
104 Symbolizer::GetOrInit()->LateInitializeTools();
105}
103void Symbolizer::LateInitialize() { Symbolizer::GetOrInit(); }
106104
107105void StartReportDeadlySignal() {}
108106void ReportDeadlySignal(const SignalContext &sig, u32 tid,
lib/tsan/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp+71-62
......@@ -13,25 +13,25 @@
1313
1414#include "sanitizer_platform.h"
1515#if SANITIZER_POSIX
16#include "sanitizer_allocator_internal.h"
17#include "sanitizer_common.h"
18#include "sanitizer_file.h"
19#include "sanitizer_flags.h"
20#include "sanitizer_internal_defs.h"
21#include "sanitizer_linux.h"
22#include "sanitizer_placement_new.h"
23#include "sanitizer_posix.h"
24#include "sanitizer_procmaps.h"
25#include "sanitizer_symbolizer_internal.h"
26#include "sanitizer_symbolizer_libbacktrace.h"
27#include "sanitizer_symbolizer_mac.h"
28
29#include <dlfcn.h> // for dlsym()
30#include <errno.h>
31#include <stdint.h>
32#include <stdlib.h>
33#include <sys/wait.h>
34#include <unistd.h>
16# include <dlfcn.h> // for dlsym()
17# include <errno.h>
18# include <stdint.h>
19# include <stdlib.h>
20# include <sys/wait.h>
21# include <unistd.h>
22
23# include "sanitizer_allocator_internal.h"
24# include "sanitizer_common.h"
25# include "sanitizer_file.h"
26# include "sanitizer_flags.h"
27# include "sanitizer_internal_defs.h"
28# include "sanitizer_linux.h"
29# include "sanitizer_placement_new.h"
30# include "sanitizer_posix.h"
31# include "sanitizer_procmaps.h"
32# include "sanitizer_symbolizer_internal.h"
33# include "sanitizer_symbolizer_libbacktrace.h"
34# include "sanitizer_symbolizer_mac.h"
3535
3636// C++ demangling function, as required by Itanium C++ ABI. This is weak,
3737// because we do not require a C++ ABI library to be linked to a program
......@@ -72,7 +72,6 @@ static swift_demangle_ft swift_demangle_f;
7272// symbolication.
7373static void InitializeSwiftDemangler() {
7474 swift_demangle_f = (swift_demangle_ft)dlsym(RTLD_DEFAULT, "swift_demangle");
75 (void)dlerror(); // Cleanup error message in case of failure
7675}
7776
7877// Attempts to demangle a Swift name. The demangler will return nullptr if a
......@@ -155,7 +154,7 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {
155154 }
156155
157156 if (use_posix_spawn_) {
158#if SANITIZER_MAC
157#if SANITIZER_APPLE
159158 fd_t fd = internal_spawn(argv, const_cast<const char **>(GetEnvP()), &pid);
160159 if (fd == kInvalidFd) {
161160 Report("WARNING: failed to spawn external symbolizer (errno: %d)\n",
......@@ -165,9 +164,9 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {
165164
166165 input_fd_ = fd;
167166 output_fd_ = fd;
168#else // SANITIZER_MAC
167#else // SANITIZER_APPLE
169168 UNIMPLEMENTED();
170#endif // SANITIZER_MAC
169#endif // SANITIZER_APPLE
171170 } else {
172171 fd_t infd[2] = {}, outfd[2] = {};
173172 if (!CreateTwoHighNumberedPipes(infd, outfd)) {
......@@ -213,31 +212,36 @@ class Addr2LineProcess final : public SymbolizerProcess {
213212 const char *(&argv)[kArgVMax]) const override {
214213 int i = 0;
215214 argv[i++] = path_to_binary;
216 argv[i++] = "-iCfe";
215 if (common_flags()->demangle)
216 argv[i++] = "-C";
217 if (common_flags()->symbolize_inline_frames)
218 argv[i++] = "-i";
219 argv[i++] = "-fe";
217220 argv[i++] = module_name_;
218221 argv[i++] = nullptr;
222 CHECK_LE(i, kArgVMax);
219223 }
220224
221225 bool ReachedEndOfOutput(const char *buffer, uptr length) const override;
222226
223 bool ReadFromSymbolizer(char *buffer, uptr max_length) override {
224 if (!SymbolizerProcess::ReadFromSymbolizer(buffer, max_length))
227 bool ReadFromSymbolizer() override {
228 if (!SymbolizerProcess::ReadFromSymbolizer())
225229 return false;
226 // The returned buffer is empty when output is valid, but exceeds
227 // max_length.
228 if (*buffer == '\0')
229 return true;
230 auto &buff = GetBuff();
230231 // We should cut out output_terminator_ at the end of given buffer,
231232 // appended by addr2line to mark the end of its meaningful output.
232233 // We cannot scan buffer from it's beginning, because it is legal for it
233234 // to start with output_terminator_ in case given offset is invalid. So,
234235 // scanning from second character.
235 char *garbage = internal_strstr(buffer + 1, output_terminator_);
236 char *garbage = internal_strstr(buff.data() + 1, output_terminator_);
236237 // This should never be NULL since buffer must end up with
237238 // output_terminator_.
238239 CHECK(garbage);
240
239241 // Trim the buffer.
240 garbage[0] = '\0';
242 uintptr_t new_size = garbage - buff.data();
243 GetBuff().resize(new_size);
244 GetBuff().push_back('\0');
241245 return true;
242246 }
243247
......@@ -312,37 +316,42 @@ class Addr2LinePool final : public SymbolizerTool {
312316 FIRST_32_SECOND_64(UINT32_MAX, UINT64_MAX);
313317};
314318
315#if SANITIZER_SUPPORTS_WEAK_HOOKS
319# if SANITIZER_SUPPORTS_WEAK_HOOKS
316320extern "C" {
317321SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE bool
318322__sanitizer_symbolize_code(const char *ModuleName, u64 ModuleOffset,
319 char *Buffer, int MaxLength,
320 bool SymbolizeInlineFrames);
321SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
322bool __sanitizer_symbolize_data(const char *ModuleName, u64 ModuleOffset,
323 char *Buffer, int MaxLength);
324SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
325void __sanitizer_symbolize_flush();
326SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
327int __sanitizer_symbolize_demangle(const char *Name, char *Buffer,
328 int MaxLength);
323 char *Buffer, int MaxLength);
324SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE bool
325__sanitizer_symbolize_data(const char *ModuleName, u64 ModuleOffset,
326 char *Buffer, int MaxLength);
327SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
328__sanitizer_symbolize_flush();
329SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE int
330__sanitizer_symbolize_demangle(const char *Name, char *Buffer, int MaxLength);
331SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE bool
332__sanitizer_symbolize_set_demangle(bool Demangle);
333SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE bool
334__sanitizer_symbolize_set_inline_frames(bool InlineFrames);
329335} // extern "C"
330336
331337class InternalSymbolizer final : public SymbolizerTool {
332338 public:
333339 static InternalSymbolizer *get(LowLevelAllocator *alloc) {
334 if (__sanitizer_symbolize_code != 0 &&
335 __sanitizer_symbolize_data != 0) {
336 return new(*alloc) InternalSymbolizer();
337 }
340 if (__sanitizer_symbolize_set_demangle)
341 CHECK(__sanitizer_symbolize_set_demangle(common_flags()->demangle));
342 if (__sanitizer_symbolize_set_inline_frames)
343 CHECK(__sanitizer_symbolize_set_inline_frames(
344 common_flags()->symbolize_inline_frames));
345 if (__sanitizer_symbolize_code && __sanitizer_symbolize_data)
346 return new (*alloc) InternalSymbolizer();
338347 return 0;
339348 }
340349
341350 bool SymbolizePC(uptr addr, SymbolizedStack *stack) override {
342351 bool result = __sanitizer_symbolize_code(
343 stack->info.module, stack->info.module_offset, buffer_, kBufferSize,
344 common_flags()->symbolize_inline_frames);
345 if (result) ParseSymbolizePCOutput(buffer_, stack);
352 stack->info.module, stack->info.module_offset, buffer_, kBufferSize);
353 if (result)
354 ParseSymbolizePCOutput(buffer_, stack);
346355 return result;
347356 }
348357
......@@ -365,7 +374,7 @@ class InternalSymbolizer final : public SymbolizerTool {
365374 if (__sanitizer_symbolize_demangle) {
366375 for (uptr res_length = 1024;
367376 res_length <= InternalSizeClassMap::kMaxSize;) {
368 char *res_buff = static_cast<char*>(InternalAlloc(res_length));
377 char *res_buff = static_cast<char *>(InternalAlloc(res_length));
369378 uptr req_length =
370379 __sanitizer_symbolize_demangle(name, res_buff, res_length);
371380 if (req_length > res_length) {
......@@ -380,19 +389,19 @@ class InternalSymbolizer final : public SymbolizerTool {
380389 }
381390
382391 private:
383 InternalSymbolizer() { }
392 InternalSymbolizer() {}
384393
385394 static const int kBufferSize = 16 * 1024;
386395 char buffer_[kBufferSize];
387396};
388#else // SANITIZER_SUPPORTS_WEAK_HOOKS
397# else // SANITIZER_SUPPORTS_WEAK_HOOKS
389398
390399class InternalSymbolizer final : public SymbolizerTool {
391400 public:
392401 static InternalSymbolizer *get(LowLevelAllocator *alloc) { return 0; }
393402};
394403
395#endif // SANITIZER_SUPPORTS_WEAK_HOOKS
404# endif // SANITIZER_SUPPORTS_WEAK_HOOKS
396405
397406const char *Symbolizer::PlatformDemangle(const char *name) {
398407 return DemangleSwiftAndCXX(name);
......@@ -417,13 +426,13 @@ static SymbolizerTool *ChooseExternalSymbolizer(LowLevelAllocator *allocator) {
417426 VReport(2, "Using llvm-symbolizer at user-specified path: %s\n", path);
418427 return new(*allocator) LLVMSymbolizer(path, allocator);
419428 } else if (!internal_strcmp(binary_name, "atos")) {
420#if SANITIZER_MAC
429#if SANITIZER_APPLE
421430 VReport(2, "Using atos at user-specified path: %s\n", path);
422431 return new(*allocator) AtosSymbolizer(path, allocator);
423#else // SANITIZER_MAC
432#else // SANITIZER_APPLE
424433 Report("ERROR: Using `atos` is only supported on Darwin.\n");
425434 Die();
426#endif // SANITIZER_MAC
435#endif // SANITIZER_APPLE
427436 } else if (!internal_strcmp(binary_name, "addr2line")) {
428437 VReport(2, "Using addr2line at user-specified path: %s\n", path);
429438 return new(*allocator) Addr2LinePool(path, allocator);
......@@ -436,12 +445,12 @@ static SymbolizerTool *ChooseExternalSymbolizer(LowLevelAllocator *allocator) {
436445
437446 // Otherwise symbolizer program is unknown, let's search $PATH
438447 CHECK(path == nullptr);
439#if SANITIZER_MAC
448#if SANITIZER_APPLE
440449 if (const char *found_path = FindPathToBinary("atos")) {
441450 VReport(2, "Using atos found at: %s\n", found_path);
442451 return new(*allocator) AtosSymbolizer(found_path, allocator);
443452 }
444#endif // SANITIZER_MAC
453#endif // SANITIZER_APPLE
445454 if (const char *found_path = FindPathToBinary("llvm-symbolizer")) {
446455 VReport(2, "Using llvm-symbolizer found at: %s\n", found_path);
447456 return new(*allocator) LLVMSymbolizer(found_path, allocator);
......@@ -478,10 +487,10 @@ static void ChooseSymbolizerTools(IntrusiveList<SymbolizerTool> *list,
478487 list->push_back(tool);
479488 }
480489
481#if SANITIZER_MAC
490#if SANITIZER_APPLE
482491 VReport(2, "Using dladdr symbolizer.\n");
483492 list->push_back(new(*allocator) DlAddrSymbolizer());
484#endif // SANITIZER_MAC
493#endif // SANITIZER_APPLE
485494}
486495
487496Symbolizer *Symbolizer::PlatformInit() {
......@@ -492,7 +501,7 @@ Symbolizer *Symbolizer::PlatformInit() {
492501}
493502
494503void Symbolizer::LateInitialize() {
495 Symbolizer::GetOrInit()->LateInitializeTools();
504 Symbolizer::GetOrInit();
496505 InitializeSwiftDemangler();
497506}
498507
lib/tsan/sanitizer_common/sanitizer_symbolizer_report.cpp+11-6
......@@ -88,11 +88,17 @@ void ReportErrorSummary(const char *error_type, const StackTrace *stack,
8888#endif
8989}
9090
91void ReportMmapWriteExec(int prot) {
91void ReportMmapWriteExec(int prot, int flags) {
9292#if SANITIZER_POSIX && (!SANITIZER_GO && !SANITIZER_ANDROID)
93 if ((prot & (PROT_WRITE | PROT_EXEC)) != (PROT_WRITE | PROT_EXEC))
93 int pflags = (PROT_WRITE | PROT_EXEC);
94 if ((prot & pflags) != pflags)
9495 return;
9596
97# if SANITIZER_APPLE && defined(MAP_JIT)
98 if ((flags & MAP_JIT) == MAP_JIT)
99 return;
100# endif
101
96102 ScopedErrorReportLock l;
97103 SanitizerCommonDecorator d;
98104
......@@ -101,8 +107,7 @@ void ReportMmapWriteExec(int prot) {
101107 stack->Reset();
102108 uptr top = 0;
103109 uptr bottom = 0;
104 GET_CALLER_PC_BP_SP;
105 (void)sp;
110 GET_CALLER_PC_BP;
106111 bool fast = common_flags()->fast_unwind_on_fatal;
107112 if (StackTrace::WillUseFastUnwind(fast)) {
108113 GetThreadStackTopAndBottom(false, &top, &bottom);
......@@ -205,9 +210,9 @@ static void ReportDeadlySignalImpl(const SignalContext &sig, u32 tid,
205210 Report("Hint: pc points to the zero page.\n");
206211 if (sig.is_memory_access) {
207212 const char *access_type =
208 sig.write_flag == SignalContext::WRITE
213 sig.write_flag == SignalContext::Write
209214 ? "WRITE"
210 : (sig.write_flag == SignalContext::READ ? "READ" : "UNKNOWN");
215 : (sig.write_flag == SignalContext::Read ? "READ" : "UNKNOWN");
211216 Report("The signal is caused by a %s memory access.\n", access_type);
212217 if (!sig.is_true_faulting_addr)
213218 Report("Hint: this fault was caused by a dereference of a high value "
lib/tsan/sanitizer_common/sanitizer_symbolizer_win.cpp+8-10
......@@ -14,8 +14,8 @@
1414#include "sanitizer_platform.h"
1515#if SANITIZER_WINDOWS
1616
17#include "sanitizer_dbghelp.h"
18#include "sanitizer_symbolizer_internal.h"
17# include "sanitizer_dbghelp.h"
18# include "sanitizer_symbolizer_internal.h"
1919
2020namespace __sanitizer {
2121
......@@ -231,8 +231,6 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {
231231 // Check that tool command lines are simple and that complete escaping is
232232 // unnecessary.
233233 CHECK(!internal_strchr(arg, '"') && "quotes in args unsupported");
234 CHECK(!internal_strstr(arg, "\\\\") &&
235 "double backslashes in args unsupported");
236234 CHECK(arglen > 0 && arg[arglen - 1] != '\\' &&
237235 "args ending in backslash and empty args unsupported");
238236 command_line.append("\"%s\" ", arg);
......@@ -294,15 +292,15 @@ static void ChooseSymbolizerTools(IntrusiveList<SymbolizerTool> *list,
294292 const char *path =
295293 user_path ? user_path : FindPathToBinary("llvm-symbolizer.exe");
296294 if (path) {
297 VReport(2, "Using llvm-symbolizer at %spath: %s\n",
298 user_path ? "user-specified " : "", path);
299 list->push_back(new(*allocator) LLVMSymbolizer(path, allocator));
300 } else {
301295 if (user_path && user_path[0] == '\0') {
302296 VReport(2, "External symbolizer is explicitly disabled.\n");
303297 } else {
304 VReport(2, "External symbolizer is not present.\n");
298 VReport(2, "Using llvm-symbolizer at %spath: %s\n",
299 user_path ? "user-specified " : "", path);
300 list->push_back(new (*allocator) LLVMSymbolizer(path, allocator));
305301 }
302 } else {
303 VReport(2, "External symbolizer is not present.\n");
306304 }
307305
308306 // Add the dbghelp based symbolizer.
......@@ -318,7 +316,7 @@ Symbolizer *Symbolizer::PlatformInit() {
318316}
319317
320318void Symbolizer::LateInitialize() {
321 Symbolizer::GetOrInit()->LateInitializeTools();
319 Symbolizer::GetOrInit();
322320}
323321
324322} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_syscall_generic.inc+3-2
......@@ -13,13 +13,14 @@
1313// NetBSD uses libc calls directly
1414#if !SANITIZER_NETBSD
1515
16#if SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_SOLARIS
16#if SANITIZER_FREEBSD || SANITIZER_APPLE || SANITIZER_SOLARIS
1717# define SYSCALL(name) SYS_ ## name
1818#else
1919# define SYSCALL(name) __NR_ ## name
2020#endif
2121
22#if defined(__x86_64__) && (SANITIZER_FREEBSD || SANITIZER_MAC)
22#if (defined(__x86_64__) && (SANITIZER_FREEBSD || SANITIZER_APPLE)) || \
23 (defined(__aarch64__) && SANITIZER_FREEBSD)
2324# define internal_syscall __syscall
2425# else
2526# define internal_syscall syscall
lib/tsan/sanitizer_common/sanitizer_syscalls_netbsd.inc+2-2
......@@ -2255,13 +2255,13 @@ PRE_SYSCALL(getcontext)(void *ucp_) { /* Nothing to do */ }
22552255POST_SYSCALL(getcontext)(long long res, void *ucp_) { /* Nothing to do */ }
22562256PRE_SYSCALL(setcontext)(void *ucp_) {
22572257 if (ucp_) {
2258 PRE_READ(ucp_, ucontext_t_sz);
2258 PRE_READ(ucp_, ucontext_t_sz(ucp_));
22592259 }
22602260}
22612261POST_SYSCALL(setcontext)(long long res, void *ucp_) {}
22622262PRE_SYSCALL(_lwp_create)(void *ucp_, long long flags_, void *new_lwp_) {
22632263 if (ucp_) {
2264 PRE_READ(ucp_, ucontext_t_sz);
2264 PRE_READ(ucp_, ucontext_t_sz(ucp_));
22652265 }
22662266}
22672267POST_SYSCALL(_lwp_create)
lib/tsan/sanitizer_common/sanitizer_thread_arg_retval.cpp created+94
......@@ -0,0 +1,94 @@
1//===-- sanitizer_thread_arg_retval.cpp -------------------------*- 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 shared between sanitizer tools.
10//
11// Tracks thread arguments and return value for leak checking.
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_thread_arg_retval.h"
15
16#include "sanitizer_placement_new.h"
17
18namespace __sanitizer {
19
20void ThreadArgRetval::CreateLocked(uptr thread, bool detached,
21 const Args& args) {
22 CheckLocked();
23 Data& t = data_[thread];
24 t = {};
25 t.gen = gen_++;
26 t.detached = detached;
27 t.args = args;
28}
29
30ThreadArgRetval::Args ThreadArgRetval::GetArgs(uptr thread) const {
31 __sanitizer::Lock lock(&mtx_);
32 auto t = data_.find(thread);
33 CHECK(t);
34 if (t->second.done)
35 return {};
36 return t->second.args;
37}
38
39void ThreadArgRetval::Finish(uptr thread, void* retval) {
40 __sanitizer::Lock lock(&mtx_);
41 auto t = data_.find(thread);
42 if (!t)
43 return;
44 if (t->second.detached) {
45 // Retval of detached thread connot be retrieved.
46 data_.erase(t);
47 return;
48 }
49 t->second.done = true;
50 t->second.args.arg_retval = retval;
51}
52
53u32 ThreadArgRetval::BeforeJoin(uptr thread) const {
54 __sanitizer::Lock lock(&mtx_);
55 auto t = data_.find(thread);
56 CHECK(t);
57 CHECK(!t->second.detached);
58 return t->second.gen;
59}
60
61void ThreadArgRetval::AfterJoin(uptr thread, u32 gen) {
62 __sanitizer::Lock lock(&mtx_);
63 auto t = data_.find(thread);
64 if (!t || gen != t->second.gen) {
65 // Thread was reused and erased by any other event.
66 return;
67 }
68 CHECK(!t->second.detached);
69 data_.erase(t);
70}
71
72void ThreadArgRetval::DetachLocked(uptr thread) {
73 CheckLocked();
74 auto t = data_.find(thread);
75 CHECK(t);
76 CHECK(!t->second.detached);
77 if (t->second.done) {
78 // We can't retrive retval after detached thread finished.
79 data_.erase(t);
80 return;
81 }
82 t->second.detached = true;
83}
84
85void ThreadArgRetval::GetAllPtrsLocked(InternalMmapVector<uptr>* ptrs) {
86 CheckLocked();
87 CHECK(ptrs);
88 data_.forEach([&](DenseMap<uptr, Data>::value_type& kv) -> bool {
89 ptrs->push_back((uptr)kv.second.args.arg_retval);
90 return true;
91 });
92}
93
94} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_thread_arg_retval.h created+116
......@@ -0,0 +1,116 @@
1//===-- sanitizer_thread_arg_retval.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 shared between sanitizer tools.
10//
11// Tracks thread arguments and return value for leak checking.
12//===----------------------------------------------------------------------===//
13
14#ifndef SANITIZER_THREAD_ARG_RETVAL_H
15#define SANITIZER_THREAD_ARG_RETVAL_H
16
17#include "sanitizer_common.h"
18#include "sanitizer_dense_map.h"
19#include "sanitizer_list.h"
20#include "sanitizer_mutex.h"
21
22namespace __sanitizer {
23
24// Primary goal of the class is to keep alive arg and retval pointer for leak
25// checking. However it can be used to pass those pointer into wrappers used by
26// interceptors. The difference from ThreadRegistry/ThreadList is that this
27// class keeps data up to the detach or join, as exited thread still can be
28// joined to retrive retval. ThreadRegistry/ThreadList can discard exited
29// threads immediately.
30class SANITIZER_MUTEX ThreadArgRetval {
31 public:
32 struct Args {
33 void* (*routine)(void*);
34 void* arg_retval; // Either arg or retval.
35 };
36 void Lock() SANITIZER_ACQUIRE() { mtx_.Lock(); }
37 void CheckLocked() const SANITIZER_CHECK_LOCKED() { mtx_.CheckLocked(); }
38 void Unlock() SANITIZER_RELEASE() { mtx_.Unlock(); }
39
40 // Wraps pthread_create or similar. We need to keep object locked, to
41 // prevent child thread from proceeding without thread handle.
42 template <typename CreateFn /* returns thread id on success, or 0 */>
43 void Create(bool detached, const Args& args, const CreateFn& fn) {
44 // No need to track detached threads with no args, but we will to do as it's
45 // not expensive and less edge-cases.
46 __sanitizer::Lock lock(&mtx_);
47 if (uptr thread = fn())
48 CreateLocked(thread, detached, args);
49 }
50
51 // Returns thread arg and routine.
52 Args GetArgs(uptr thread) const;
53
54 // Mark thread as done and stores retval or remove if detached. Should be
55 // called by the thread.
56 void Finish(uptr thread, void* retval);
57
58 // Mark thread as detached or remove if done.
59 template <typename DetachFn /* returns true on success */>
60 void Detach(uptr thread, const DetachFn& fn) {
61 // Lock to prevent re-use of the thread between fn() and DetachLocked()
62 // calls.
63 __sanitizer::Lock lock(&mtx_);
64 if (fn())
65 DetachLocked(thread);
66 }
67
68 // Joins the thread.
69 template <typename JoinFn /* returns true on success */>
70 void Join(uptr thread, const JoinFn& fn) {
71 // Remember internal id of the thread to prevent re-use of the thread
72 // between fn() and AfterJoin() calls. Locking JoinFn, like in
73 // Detach(), implementation can cause deadlock.
74 auto gen = BeforeJoin(thread);
75 if (fn())
76 AfterJoin(thread, gen);
77 }
78
79 // Returns all arg and retval which are considered alive.
80 void GetAllPtrsLocked(InternalMmapVector<uptr>* ptrs);
81
82 uptr size() const {
83 __sanitizer::Lock lock(&mtx_);
84 return data_.size();
85 }
86
87 // FIXME: Add fork support. Expected users of the class are sloppy with forks
88 // anyway. We likely should lock/unlock the object to avoid deadlocks, and
89 // erase all but the current threads, so we can detect leaked arg or retval in
90 // child process.
91
92 // FIXME: Add cancelation support. Now if a thread was canceled, the class
93 // will keep pointers alive forever, missing leaks caused by cancelation.
94
95 private:
96 struct Data {
97 Args args;
98 u32 gen; // Avoid collision if thread id re-used.
99 bool detached;
100 bool done;
101 };
102
103 void CreateLocked(uptr thread, bool detached, const Args& args);
104 u32 BeforeJoin(uptr thread) const;
105 void AfterJoin(uptr thread, u32 gen);
106 void DetachLocked(uptr thread);
107
108 mutable Mutex mtx_;
109
110 DenseMap<uptr, Data> data_;
111 u32 gen_ = 0;
112};
113
114} // namespace __sanitizer
115
116#endif // SANITIZER_THREAD_ARG_RETVAL_H
lib/tsan/sanitizer_common/sanitizer_thread_registry.cpp+59-21
......@@ -13,6 +13,8 @@
1313
1414#include "sanitizer_thread_registry.h"
1515
16#include "sanitizer_placement_new.h"
17
1618namespace __sanitizer {
1719
1820ThreadContextBase::ThreadContextBase(u32 tid)
......@@ -108,7 +110,7 @@ ThreadRegistry::ThreadRegistry(ThreadContextFactory factory, u32 max_threads,
108110 max_threads_(max_threads),
109111 thread_quarantine_size_(thread_quarantine_size),
110112 max_reuse_(max_reuse),
111 mtx_(),
113 mtx_(MutexThreadRegistry),
112114 total_threads_(0),
113115 alive_threads_(0),
114116 max_alive_threads_(0),
......@@ -119,7 +121,7 @@ ThreadRegistry::ThreadRegistry(ThreadContextFactory factory, u32 max_threads,
119121
120122void ThreadRegistry::GetNumberOfThreads(uptr *total, uptr *running,
121123 uptr *alive) {
122 BlockingMutexLock l(&mtx_);
124 ThreadRegistryLock l(this);
123125 if (total)
124126 *total = threads_.size();
125127 if (running) *running = running_threads_;
......@@ -127,13 +129,13 @@ void ThreadRegistry::GetNumberOfThreads(uptr *total, uptr *running,
127129}
128130
129131uptr ThreadRegistry::GetMaxAliveThreads() {
130 BlockingMutexLock l(&mtx_);
132 ThreadRegistryLock l(this);
131133 return max_alive_threads_;
132134}
133135
134136u32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid,
135137 void *arg) {
136 BlockingMutexLock l(&mtx_);
138 ThreadRegistryLock l(this);
137139 u32 tid = kInvalidTid;
138140 ThreadContextBase *tctx = QuarantinePop();
139141 if (tctx) {
......@@ -162,6 +164,12 @@ u32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid,
162164 max_alive_threads_++;
163165 CHECK_EQ(alive_threads_, max_alive_threads_);
164166 }
167 if (user_id) {
168 // Ensure that user_id is unique. If it's not the case we are screwed.
169 // Ignoring this situation may lead to very hard to debug false
170 // positives later (e.g. if we join a wrong thread).
171 CHECK(live_.try_emplace(user_id, tid).second);
172 }
165173 tctx->SetCreated(user_id, total_threads_++, detached,
166174 parent_tid, arg);
167175 return tid;
......@@ -179,7 +187,7 @@ void ThreadRegistry::RunCallbackForEachThreadLocked(ThreadCallback cb,
179187}
180188
181189u32 ThreadRegistry::FindThread(FindThreadCallback cb, void *arg) {
182 BlockingMutexLock l(&mtx_);
190 ThreadRegistryLock l(this);
183191 for (u32 tid = 0; tid < threads_.size(); tid++) {
184192 ThreadContextBase *tctx = threads_[tid];
185193 if (tctx != 0 && cb(tctx, arg))
......@@ -211,7 +219,7 @@ ThreadContextBase *ThreadRegistry::FindThreadContextByOsIDLocked(tid_t os_id) {
211219}
212220
213221void ThreadRegistry::SetThreadName(u32 tid, const char *name) {
214 BlockingMutexLock l(&mtx_);
222 ThreadRegistryLock l(this);
215223 ThreadContextBase *tctx = threads_[tid];
216224 CHECK_NE(tctx, 0);
217225 CHECK_EQ(SANITIZER_FUCHSIA ? ThreadStatusCreated : ThreadStatusRunning,
......@@ -220,19 +228,13 @@ void ThreadRegistry::SetThreadName(u32 tid, const char *name) {
220228}
221229
222230void ThreadRegistry::SetThreadNameByUserId(uptr user_id, const char *name) {
223 BlockingMutexLock l(&mtx_);
224 for (u32 tid = 0; tid < threads_.size(); tid++) {
225 ThreadContextBase *tctx = threads_[tid];
226 if (tctx != 0 && tctx->user_id == user_id &&
227 tctx->status != ThreadStatusInvalid) {
228 tctx->SetName(name);
229 return;
230 }
231 }
231 ThreadRegistryLock l(this);
232 if (const auto *tid = live_.find(user_id))
233 threads_[tid->second]->SetName(name);
232234}
233235
234236void ThreadRegistry::DetachThread(u32 tid, void *arg) {
235 BlockingMutexLock l(&mtx_);
237 ThreadRegistryLock l(this);
236238 ThreadContextBase *tctx = threads_[tid];
237239 CHECK_NE(tctx, 0);
238240 if (tctx->status == ThreadStatusInvalid) {
......@@ -241,6 +243,8 @@ void ThreadRegistry::DetachThread(u32 tid, void *arg) {
241243 }
242244 tctx->OnDetached(arg);
243245 if (tctx->status == ThreadStatusFinished) {
246 if (tctx->user_id)
247 live_.erase(tctx->user_id);
244248 tctx->SetDead();
245249 QuarantinePush(tctx);
246250 } else {
......@@ -252,7 +256,7 @@ void ThreadRegistry::JoinThread(u32 tid, void *arg) {
252256 bool destroyed = false;
253257 do {
254258 {
255 BlockingMutexLock l(&mtx_);
259 ThreadRegistryLock l(this);
256260 ThreadContextBase *tctx = threads_[tid];
257261 CHECK_NE(tctx, 0);
258262 if (tctx->status == ThreadStatusInvalid) {
......@@ -260,6 +264,8 @@ void ThreadRegistry::JoinThread(u32 tid, void *arg) {
260264 return;
261265 }
262266 if ((destroyed = tctx->GetDestroyed())) {
267 if (tctx->user_id)
268 live_.erase(tctx->user_id);
263269 tctx->SetJoined(arg);
264270 QuarantinePush(tctx);
265271 }
......@@ -275,7 +281,7 @@ void ThreadRegistry::JoinThread(u32 tid, void *arg) {
275281// thread before trying to create it, and then failed to actually
276282// create it, and so never called StartThread.
277283ThreadStatus ThreadRegistry::FinishThread(u32 tid) {
278 BlockingMutexLock l(&mtx_);
284 ThreadRegistryLock l(this);
279285 CHECK_GT(alive_threads_, 0);
280286 alive_threads_--;
281287 ThreadContextBase *tctx = threads_[tid];
......@@ -292,6 +298,8 @@ ThreadStatus ThreadRegistry::FinishThread(u32 tid) {
292298 }
293299 tctx->SetFinished();
294300 if (dead) {
301 if (tctx->user_id)
302 live_.erase(tctx->user_id);
295303 tctx->SetDead();
296304 QuarantinePush(tctx);
297305 }
......@@ -301,7 +309,7 @@ ThreadStatus ThreadRegistry::FinishThread(u32 tid) {
301309
302310void ThreadRegistry::StartThread(u32 tid, tid_t os_id, ThreadType thread_type,
303311 void *arg) {
304 BlockingMutexLock l(&mtx_);
312 ThreadRegistryLock l(this);
305313 running_threads_++;
306314 ThreadContextBase *tctx = threads_[tid];
307315 CHECK_NE(tctx, 0);
......@@ -327,20 +335,50 @@ void ThreadRegistry::QuarantinePush(ThreadContextBase *tctx) {
327335
328336ThreadContextBase *ThreadRegistry::QuarantinePop() {
329337 if (invalid_threads_.size() == 0)
330 return 0;
338 return nullptr;
331339 ThreadContextBase *tctx = invalid_threads_.front();
332340 invalid_threads_.pop_front();
333341 return tctx;
334342}
335343
344u32 ThreadRegistry::ConsumeThreadUserId(uptr user_id) {
345 ThreadRegistryLock l(this);
346 u32 tid;
347 auto *t = live_.find(user_id);
348 CHECK(t);
349 tid = t->second;
350 live_.erase(t);
351 auto *tctx = threads_[tid];
352 CHECK_EQ(tctx->user_id, user_id);
353 tctx->user_id = 0;
354 return tid;
355}
356
336357void ThreadRegistry::SetThreadUserId(u32 tid, uptr user_id) {
337 BlockingMutexLock l(&mtx_);
358 ThreadRegistryLock l(this);
338359 ThreadContextBase *tctx = threads_[tid];
339360 CHECK_NE(tctx, 0);
340361 CHECK_NE(tctx->status, ThreadStatusInvalid);
341362 CHECK_NE(tctx->status, ThreadStatusDead);
342363 CHECK_EQ(tctx->user_id, 0);
343364 tctx->user_id = user_id;
365 CHECK(live_.try_emplace(user_id, tctx->tid).second);
366}
367
368u32 ThreadRegistry::OnFork(u32 tid) {
369 ThreadRegistryLock l(this);
370 // We only purge user_id (pthread_t) of live threads because
371 // they cause CHECK failures if new threads with matching pthread_t
372 // created after fork.
373 // Potentially we could purge more info (ThreadContextBase themselves),
374 // but it's hard to test and easy to introduce new issues by doing this.
375 for (auto *tctx : threads_) {
376 if (tctx->tid == tid || !tctx->user_id)
377 continue;
378 CHECK(live_.erase(tctx->user_id));
379 tctx->user_id = 0;
380 }
381 return alive_threads_;
344382}
345383
346384} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_thread_registry.h+15-5
......@@ -15,6 +15,7 @@
1515#define SANITIZER_THREAD_REGISTRY_H
1616
1717#include "sanitizer_common.h"
18#include "sanitizer_dense_map.h"
1819#include "sanitizer_list.h"
1920#include "sanitizer_mutex.h"
2021
......@@ -85,7 +86,7 @@ class ThreadContextBase {
8586
8687typedef ThreadContextBase* (*ThreadContextFactory)(u32 tid);
8788
88class MUTEX ThreadRegistry {
89class SANITIZER_MUTEX ThreadRegistry {
8990 public:
9091 ThreadRegistry(ThreadContextFactory factory);
9192 ThreadRegistry(ThreadContextFactory factory, u32 max_threads,
......@@ -94,15 +95,17 @@ class MUTEX ThreadRegistry {
9495 uptr *alive = nullptr);
9596 uptr GetMaxAliveThreads();
9697
97 void Lock() ACQUIRE() { mtx_.Lock(); }
98 void CheckLocked() const CHECK_LOCKED() { mtx_.CheckLocked(); }
99 void Unlock() RELEASE() { mtx_.Unlock(); }
98 void Lock() SANITIZER_ACQUIRE() { mtx_.Lock(); }
99 void CheckLocked() const SANITIZER_CHECK_LOCKED() { mtx_.CheckLocked(); }
100 void Unlock() SANITIZER_RELEASE() { mtx_.Unlock(); }
100101
101102 // Should be guarded by ThreadRegistryLock.
102103 ThreadContextBase *GetThreadLocked(u32 tid) {
103104 return threads_.empty() ? nullptr : threads_[tid];
104105 }
105106
107 u32 NumThreadsLocked() const { return threads_.size(); }
108
106109 u32 CreateThread(uptr user_id, bool detached, u32 parent_tid, void *arg);
107110
108111 typedef void (*ThreadCallback)(ThreadContextBase *tctx, void *arg);
......@@ -127,15 +130,21 @@ class MUTEX ThreadRegistry {
127130 // Finishes thread and returns previous status.
128131 ThreadStatus FinishThread(u32 tid);
129132 void StartThread(u32 tid, tid_t os_id, ThreadType thread_type, void *arg);
133 u32 ConsumeThreadUserId(uptr user_id);
130134 void SetThreadUserId(u32 tid, uptr user_id);
131135
136 // OnFork must be called in the child process after fork to purge old
137 // threads that don't exist anymore (except for the current thread tid).
138 // Returns number of alive threads before fork.
139 u32 OnFork(u32 tid);
140
132141 private:
133142 const ThreadContextFactory context_factory_;
134143 const u32 max_threads_;
135144 const u32 thread_quarantine_size_;
136145 const u32 max_reuse_;
137146
138 BlockingMutex mtx_;
147 Mutex mtx_;
139148
140149 u64 total_threads_; // Total number of created threads. May be greater than
141150 // max_threads_ if contexts were reused.
......@@ -146,6 +155,7 @@ class MUTEX ThreadRegistry {
146155 InternalMmapVector<ThreadContextBase *> threads_;
147156 IntrusiveList<ThreadContextBase> dead_threads_;
148157 IntrusiveList<ThreadContextBase> invalid_threads_;
158 DenseMap<uptr, Tid> live_;
149159
150160 void QuarantinePush(ThreadContextBase *tctx);
151161 ThreadContextBase *QuarantinePop();
lib/tsan/sanitizer_common/sanitizer_thread_safety.h+26-19
......@@ -16,27 +16,34 @@
1616#define SANITIZER_THREAD_SAFETY_H
1717
1818#if defined(__clang__)
19# define THREAD_ANNOTATION(x) __attribute__((x))
19# define SANITIZER_THREAD_ANNOTATION(x) __attribute__((x))
2020#else
21# define THREAD_ANNOTATION(x)
21# define SANITIZER_THREAD_ANNOTATION(x)
2222#endif
2323
24#define MUTEX THREAD_ANNOTATION(capability("mutex"))
25#define SCOPED_LOCK THREAD_ANNOTATION(scoped_lockable)
26#define GUARDED_BY(x) THREAD_ANNOTATION(guarded_by(x))
27#define PT_GUARDED_BY(x) THREAD_ANNOTATION(pt_guarded_by(x))
28#define REQUIRES(...) THREAD_ANNOTATION(requires_capability(__VA_ARGS__))
29#define REQUIRES_SHARED(...) \
30 THREAD_ANNOTATION(requires_shared_capability(__VA_ARGS__))
31#define ACQUIRE(...) THREAD_ANNOTATION(acquire_capability(__VA_ARGS__))
32#define ACQUIRE_SHARED(...) \
33 THREAD_ANNOTATION(acquire_shared_capability(__VA_ARGS__))
34#define TRY_ACQUIRE(...) THREAD_ANNOTATION(try_acquire_capability(__VA_ARGS__))
35#define RELEASE(...) THREAD_ANNOTATION(release_capability(__VA_ARGS__))
36#define RELEASE_SHARED(...) \
37 THREAD_ANNOTATION(release_shared_capability(__VA_ARGS__))
38#define EXCLUDES(...) THREAD_ANNOTATION(locks_excluded(__VA_ARGS__))
39#define CHECK_LOCKED(...) THREAD_ANNOTATION(assert_capability(__VA_ARGS__))
40#define NO_THREAD_SAFETY_ANALYSIS THREAD_ANNOTATION(no_thread_safety_analysis)
24#define SANITIZER_MUTEX SANITIZER_THREAD_ANNOTATION(capability("mutex"))
25#define SANITIZER_SCOPED_LOCK SANITIZER_THREAD_ANNOTATION(scoped_lockable)
26#define SANITIZER_GUARDED_BY(x) SANITIZER_THREAD_ANNOTATION(guarded_by(x))
27#define SANITIZER_PT_GUARDED_BY(x) SANITIZER_THREAD_ANNOTATION(pt_guarded_by(x))
28#define SANITIZER_REQUIRES(...) \
29 SANITIZER_THREAD_ANNOTATION(requires_capability(__VA_ARGS__))
30#define SANITIZER_REQUIRES_SHARED(...) \
31 SANITIZER_THREAD_ANNOTATION(requires_shared_capability(__VA_ARGS__))
32#define SANITIZER_ACQUIRE(...) \
33 SANITIZER_THREAD_ANNOTATION(acquire_capability(__VA_ARGS__))
34#define SANITIZER_ACQUIRE_SHARED(...) \
35 SANITIZER_THREAD_ANNOTATION(acquire_shared_capability(__VA_ARGS__))
36#define SANITIZER_TRY_ACQUIRE(...) \
37 SANITIZER_THREAD_ANNOTATION(try_acquire_capability(__VA_ARGS__))
38#define SANITIZER_RELEASE(...) \
39 SANITIZER_THREAD_ANNOTATION(release_capability(__VA_ARGS__))
40#define SANITIZER_RELEASE_SHARED(...) \
41 SANITIZER_THREAD_ANNOTATION(release_shared_capability(__VA_ARGS__))
42#define SANITIZER_EXCLUDES(...) \
43 SANITIZER_THREAD_ANNOTATION(locks_excluded(__VA_ARGS__))
44#define SANITIZER_CHECK_LOCKED(...) \
45 SANITIZER_THREAD_ANNOTATION(assert_capability(__VA_ARGS__))
46#define SANITIZER_NO_THREAD_SAFETY_ANALYSIS \
47 SANITIZER_THREAD_ANNOTATION(no_thread_safety_analysis)
4148
4249#endif
lib/tsan/sanitizer_common/sanitizer_tls_get_addr.cpp+28-25
......@@ -12,6 +12,7 @@
1212
1313#include "sanitizer_tls_get_addr.h"
1414
15#include "sanitizer_allocator_interface.h"
1516#include "sanitizer_atomic.h"
1617#include "sanitizer_flags.h"
1718#include "sanitizer_platform_interceptors.h"
......@@ -26,13 +27,6 @@ struct TlsGetAddrParam {
2627 uptr offset;
2728};
2829
29// Glibc starting from 2.19 allocates tls using __signal_safe_memalign,
30// which has such header.
31struct Glibc_2_19_tls_header {
32 uptr size;
33 uptr start;
34};
35
3630// This must be static TLS
3731__attribute__((tls_model("initial-exec")))
3832static __thread DTLS dtls;
......@@ -44,7 +38,7 @@ static atomic_uintptr_t number_of_live_dtls;
4438static const uptr kDestroyedThread = -1;
4539
4640static void DTLS_Deallocate(DTLS::DTVBlock *block) {
47 VReport(2, "__tls_get_addr: DTLS_Deallocate %p %zd\n", block);
41 VReport(2, "__tls_get_addr: DTLS_Deallocate %p\n", (void *)block);
4842 UnmapOrDie(block, sizeof(DTLS::DTVBlock));
4943 atomic_fetch_sub(&number_of_live_dtls, 1, memory_order_relaxed);
5044}
......@@ -66,12 +60,13 @@ static DTLS::DTVBlock *DTLS_NextBlock(atomic_uintptr_t *cur) {
6660 }
6761 uptr num_live_dtls =
6862 atomic_fetch_add(&number_of_live_dtls, 1, memory_order_relaxed);
69 VReport(2, "__tls_get_addr: DTLS_NextBlock %p %zd\n", &dtls, num_live_dtls);
63 VReport(2, "__tls_get_addr: DTLS_NextBlock %p %zd\n", (void *)&dtls,
64 num_live_dtls);
7065 return new_dtv;
7166}
7267
7368static DTLS::DTV *DTLS_Find(uptr id) {
74 VReport(2, "__tls_get_addr: DTLS_Find %p %zd\n", &dtls, id);
69 VReport(2, "__tls_get_addr: DTLS_Find %p %zd\n", (void *)&dtls, id);
7570 static constexpr uptr kPerBlock = ARRAY_SIZE(DTLS::DTVBlock::dtvs);
7671 DTLS::DTVBlock *cur = DTLS_NextBlock(&dtls.dtv_block);
7772 if (!cur)
......@@ -82,7 +77,7 @@ static DTLS::DTV *DTLS_Find(uptr id) {
8277
8378void DTLS_Destroy() {
8479 if (!common_flags()->intercept_tls_get_addr) return;
85 VReport(2, "__tls_get_addr: DTLS_Destroy %p\n", &dtls);
80 VReport(2, "__tls_get_addr: DTLS_Destroy %p\n", (void *)&dtls);
8681 DTLS::DTVBlock *block = (DTLS::DTVBlock *)atomic_exchange(
8782 &dtls.dtv_block, kDestroyedThread, memory_order_release);
8883 while (block) {
......@@ -107,6 +102,14 @@ static const uptr kDtvOffset = 0x800;
107102static const uptr kDtvOffset = 0;
108103#endif
109104
105extern "C" {
106SANITIZER_WEAK_ATTRIBUTE
107uptr __sanitizer_get_allocated_size(const void *p);
108
109SANITIZER_WEAK_ATTRIBUTE
110const void *__sanitizer_get_allocated_begin(const void *p);
111}
112
110113DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res,
111114 uptr static_tls_begin, uptr static_tls_end) {
112115 if (!common_flags()->intercept_tls_get_addr) return 0;
......@@ -117,26 +120,26 @@ DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res,
117120 return 0;
118121 uptr tls_size = 0;
119122 uptr tls_beg = reinterpret_cast<uptr>(res) - arg->offset - kDtvOffset;
120 VReport(2, "__tls_get_addr: %p {%p,%p} => %p; tls_beg: %p; sp: %p "
121 "num_live_dtls %zd\n",
122 arg, arg->dso_id, arg->offset, res, tls_beg, &tls_beg,
123 VReport(2,
124 "__tls_get_addr: %p {0x%zx,0x%zx} => %p; tls_beg: 0x%zx; sp: %p "
125 "num_live_dtls %zd\n",
126 (void *)arg, arg->dso_id, arg->offset, res, tls_beg, (void *)&tls_beg,
123127 atomic_load(&number_of_live_dtls, memory_order_relaxed));
124128 if (dtls.last_memalign_ptr == tls_beg) {
125129 tls_size = dtls.last_memalign_size;
126 VReport(2, "__tls_get_addr: glibc <=2.18 suspected; tls={%p,%p}\n",
127 tls_beg, tls_size);
130 VReport(2, "__tls_get_addr: glibc <=2.24 suspected; tls={0x%zx,0x%zx}\n",
131 tls_beg, tls_size);
128132 } else if (tls_beg >= static_tls_begin && tls_beg < static_tls_end) {
129133 // This is the static TLS block which was initialized / unpoisoned at thread
130134 // creation.
131 VReport(2, "__tls_get_addr: static tls: %p\n", tls_beg);
135 VReport(2, "__tls_get_addr: static tls: 0x%zx\n", tls_beg);
132136 tls_size = 0;
133 } else if ((tls_beg % 4096) == sizeof(Glibc_2_19_tls_header)) {
134 // We may want to check gnu_get_libc_version().
135 Glibc_2_19_tls_header *header = (Glibc_2_19_tls_header *)tls_beg - 1;
136 tls_size = header->size;
137 tls_beg = header->start;
138 VReport(2, "__tls_get_addr: glibc >=2.19 suspected; tls={%p %p}\n",
139 tls_beg, tls_size);
137 } else if (const void *start =
138 __sanitizer_get_allocated_begin((void *)tls_beg)) {
139 tls_beg = (uptr)start;
140 tls_size = __sanitizer_get_allocated_size(start);
141 VReport(2, "__tls_get_addr: glibc >=2.25 suspected; tls={0x%zx,0x%zx}\n",
142 tls_beg, tls_size);
140143 } else {
141144 VReport(2, "__tls_get_addr: Can't guess glibc version\n");
142145 // This may happen inside the DTOR of main thread, so just ignore it.
......@@ -149,7 +152,7 @@ DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res,
149152
150153void DTLS_on_libc_memalign(void *ptr, uptr size) {
151154 if (!common_flags()->intercept_tls_get_addr) return;
152 VReport(2, "DTLS_on_libc_memalign: %p %p\n", ptr, size);
155 VReport(2, "DTLS_on_libc_memalign: %p 0x%zx\n", ptr, size);
153156 dtls.last_memalign_ptr = reinterpret_cast<uptr>(ptr);
154157 dtls.last_memalign_size = size;
155158}
lib/tsan/sanitizer_common/sanitizer_tls_get_addr.h+17-9
......@@ -12,16 +12,24 @@
1212// the lack of interface that would tell us about the Dynamic TLS (DTLS).
1313// https://sourceware.org/bugzilla/show_bug.cgi?id=16291
1414//
15// The matters get worse because the glibc implementation changed between
16// 2.18 and 2.19:
17// https://groups.google.com/forum/#!topic/address-sanitizer/BfwYD8HMxTM
18//
19// Before 2.19, every DTLS chunk is allocated with __libc_memalign,
15// Before 2.25: every DTLS chunk is allocated with __libc_memalign,
2016// which we intercept and thus know where is the DTLS.
21// Since 2.19, DTLS chunks are allocated with __signal_safe_memalign,
22// which is an internal function that wraps a mmap call, neither of which
23// we can intercept. Luckily, __signal_safe_memalign has a simple parseable
24// header which we can use.
17//
18// Since 2.25: DTLS chunks are allocated with malloc. We could co-opt
19// the malloc interceptor to keep track of the last allocation, similar
20// to how we handle __libc_memalign; however, this adds some overhead
21// (since malloc, unlike __libc_memalign, is commonly called), and
22// requires care to avoid false negatives for LeakSanitizer.
23// Instead, we rely on our internal allocators - which keep track of all
24// its allocations - to determine if an address points to a malloc
25// allocation.
26//
27// There exists a since-deprecated version of Google's internal glibc fork
28// that used __signal_safe_memalign. DTLS_on_tls_get_addr relied on a
29// heuristic check (is the allocation 16 bytes from the start of a page
30// boundary?), which was sometimes erroneous:
31// https://bugs.chromium.org/p/chromium/issues/detail?id=1275223#c15
32// Since that check has no practical use anymore, we have removed it.
2533//
2634//===----------------------------------------------------------------------===//
2735
lib/tsan/sanitizer_common/sanitizer_type_traits.h+79
......@@ -13,6 +13,8 @@
1313#ifndef SANITIZER_TYPE_TRAITS_H
1414#define SANITIZER_TYPE_TRAITS_H
1515
16#include "sanitizer_common/sanitizer_internal_defs.h"
17
1618namespace __sanitizer {
1719
1820struct true_type {
......@@ -57,6 +59,83 @@ struct conditional<false, T, F> {
5759 using type = F;
5860};
5961
62template <class T>
63struct remove_reference {
64 using type = T;
65};
66template <class T>
67struct remove_reference<T&> {
68 using type = T;
69};
70template <class T>
71struct remove_reference<T&&> {
72 using type = T;
73};
74
75template <class T>
76WARN_UNUSED_RESULT inline typename remove_reference<T>::type&& move(T&& t) {
77 return static_cast<typename remove_reference<T>::type&&>(t);
78}
79
80template <class T>
81WARN_UNUSED_RESULT inline constexpr T&& forward(
82 typename remove_reference<T>::type& t) {
83 return static_cast<T&&>(t);
84}
85
86template <class T>
87WARN_UNUSED_RESULT inline constexpr T&& forward(
88 typename remove_reference<T>::type&& t) {
89 return static_cast<T&&>(t);
90}
91
92template <class T, T v>
93struct integral_constant {
94 static constexpr const T value = v;
95 typedef T value_type;
96 typedef integral_constant type;
97 constexpr operator value_type() const { return value; }
98 constexpr value_type operator()() const { return value; }
99};
100
101#ifndef __has_builtin
102# define __has_builtin(x) 0
103#endif
104
105#if __has_builtin(__is_trivially_destructible)
106
107template <class T>
108struct is_trivially_destructible
109 : public integral_constant<bool, __is_trivially_destructible(T)> {};
110
111#elif __has_builtin(__has_trivial_destructor)
112
113template <class T>
114struct is_trivially_destructible
115 : public integral_constant<bool, __has_trivial_destructor(T)> {};
116
117#else
118
119template <class T>
120struct is_trivially_destructible
121 : public integral_constant<bool, /* less efficient fallback */ false> {};
122
123#endif
124
125#if __has_builtin(__is_trivially_copyable)
126
127template <class T>
128struct is_trivially_copyable
129 : public integral_constant<bool, __is_trivially_copyable(T)> {};
130
131#else
132
133template <class T>
134struct is_trivially_copyable
135 : public integral_constant<bool, /* less efficient fallback */ false> {};
136
137#endif
138
60139} // namespace __sanitizer
61140
62141#endif
lib/tsan/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp+1-7
......@@ -58,7 +58,7 @@ unwind_backtrace_signal_arch_func unwind_backtrace_signal_arch;
5858#endif
5959
6060uptr Unwind_GetIP(struct _Unwind_Context *ctx) {
61#if defined(__arm__) && !SANITIZER_MAC
61#if defined(__arm__) && !SANITIZER_APPLE
6262 uptr val;
6363 _Unwind_VRS_Result res = _Unwind_VRS_Get(ctx, _UVRSC_CORE,
6464 15 /* r15 = PC */, _UVRSD_UINT32, &val);
......@@ -139,13 +139,7 @@ void BufferedStackTrace::UnwindSlow(uptr pc, u32 max_depth) {
139139 if (to_pop == 0 && size > 1)
140140 to_pop = 1;
141141 PopStackFrames(to_pop);
142#if defined(__GNUC__) && defined(__sparc__)
143 // __builtin_return_address returns the address of the call instruction
144 // on the SPARC and not the return address, so we need to compensate.
145 trace_buffer[0] = GetNextInstructionPc(pc);
146#else
147142 trace_buffer[0] = pc;
148#endif
149143}
150144
151145void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) {
lib/tsan/sanitizer_common/sanitizer_unwind_win.cpp+17-10
......@@ -57,30 +57,37 @@ void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) {
5757 InitializeDbgHelpIfNeeded();
5858
5959 size = 0;
60#if defined(_WIN64)
60# if SANITIZER_WINDOWS64
61# if SANITIZER_ARM64
62 int machine_type = IMAGE_FILE_MACHINE_ARM64;
63 stack_frame.AddrPC.Offset = ctx.Pc;
64 stack_frame.AddrFrame.Offset = ctx.Fp;
65 stack_frame.AddrStack.Offset = ctx.Sp;
66# else
6167 int machine_type = IMAGE_FILE_MACHINE_AMD64;
6268 stack_frame.AddrPC.Offset = ctx.Rip;
6369 stack_frame.AddrFrame.Offset = ctx.Rbp;
6470 stack_frame.AddrStack.Offset = ctx.Rsp;
65#else
71# endif
72# else
6673 int machine_type = IMAGE_FILE_MACHINE_I386;
6774 stack_frame.AddrPC.Offset = ctx.Eip;
6875 stack_frame.AddrFrame.Offset = ctx.Ebp;
6976 stack_frame.AddrStack.Offset = ctx.Esp;
70#endif
77# endif
7178 stack_frame.AddrPC.Mode = AddrModeFlat;
7279 stack_frame.AddrFrame.Mode = AddrModeFlat;
7380 stack_frame.AddrStack.Mode = AddrModeFlat;
7481 while (StackWalk64(machine_type, GetCurrentProcess(), GetCurrentThread(),
75 &stack_frame, &ctx, NULL, SymFunctionTableAccess64,
76 SymGetModuleBase64, NULL) &&
77 size < Min(max_depth, kStackTraceMax)) {
82 &stack_frame, &ctx, NULL, SymFunctionTableAccess64,
83 SymGetModuleBase64, NULL) &&
84 size < Min(max_depth, kStackTraceMax)) {
7885 trace_buffer[size++] = (uptr)stack_frame.AddrPC.Offset;
7986 }
8087}
81#ifdef __clang__
82#pragma clang diagnostic pop
83#endif
84#endif // #if !SANITIZER_GO
88# ifdef __clang__
89# pragma clang diagnostic pop
90# endif
91# endif // #if !SANITIZER_GO
8592
8693#endif // SANITIZER_WINDOWS
lib/tsan/sanitizer_common/sanitizer_vector.h+2-2
......@@ -83,8 +83,8 @@ class Vector {
8383 }
8484 EnsureSize(size);
8585 if (old_size < size) {
86 for (uptr i = old_size; i < size; i++)
87 internal_memset(&begin_[i], 0, sizeof(begin_[i]));
86 internal_memset(&begin_[old_size], 0,
87 sizeof(begin_[old_size]) * (size - old_size));
8888 }
8989 }
9090
lib/tsan/sanitizer_common/sanitizer_win.cpp+62-36
......@@ -93,6 +93,11 @@ bool FileExists(const char *filename) {
9393 return ::GetFileAttributesA(filename) != INVALID_FILE_ATTRIBUTES;
9494}
9595
96bool DirExists(const char *path) {
97 auto attr = ::GetFileAttributesA(path);
98 return (attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY);
99}
100
96101uptr internal_getpid() {
97102 return GetProcessId(GetCurrentProcess());
98103}
......@@ -126,6 +131,11 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
126131}
127132#endif // #if !SANITIZER_GO
128133
134bool ErrorIsOOM(error_t err) {
135 // TODO: This should check which `err`s correspond to OOM.
136 return false;
137}
138
129139void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) {
130140 void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
131141 if (rv == 0)
......@@ -224,6 +234,17 @@ void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
224234 return (void *)mapped_addr;
225235}
226236
237// ZeroMmapFixedRegion zero's out a region of memory previously returned from a
238// call to one of the MmapFixed* helpers. On non-windows systems this would be
239// done with another mmap, but on windows remapping is not an option.
240// VirtualFree(DECOMMIT)+VirtualAlloc(RECOMMIT) would also be a way to zero the
241// memory, but we can't do this atomically, so instead we fall back to using
242// internal_memset.
243bool ZeroMmapFixedRegion(uptr fixed_addr, uptr size) {
244 internal_memset((void*) fixed_addr, 0, size);
245 return true;
246}
247
227248bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
228249 // FIXME: is this really "NoReserve"? On Win32 this does not matter much,
229250 // but on Win64 it does.
......@@ -336,6 +357,16 @@ bool MprotectNoAccess(uptr addr, uptr size) {
336357 return VirtualProtect((LPVOID)addr, size, PAGE_NOACCESS, &old_protection);
337358}
338359
360bool MprotectReadOnly(uptr addr, uptr size) {
361 DWORD old_protection;
362 return VirtualProtect((LPVOID)addr, size, PAGE_READONLY, &old_protection);
363}
364
365bool MprotectReadWrite(uptr addr, uptr size) {
366 DWORD old_protection;
367 return VirtualProtect((LPVOID)addr, size, PAGE_READWRITE, &old_protection);
368}
369
339370void ReleaseMemoryPagesToOS(uptr beg, uptr end) {
340371 uptr beg_aligned = RoundDownTo(beg, GetPageSizeCached()),
341372 end_aligned = RoundDownTo(end, GetPageSizeCached());
......@@ -512,7 +543,7 @@ void ReExec() {
512543 UNIMPLEMENTED();
513544}
514545
515void PlatformPrepareForSandboxing(__sanitizer_sandbox_arguments *args) {}
546void PlatformPrepareForSandboxing(void *args) {}
516547
517548bool StackSizeIsUnlimited() {
518549 UNIMPLEMENTED();
......@@ -565,6 +596,10 @@ void Abort() {
565596 internal__exit(3);
566597}
567598
599bool CreateDir(const char *pathname) {
600 return CreateDirectoryA(pathname, nullptr) != 0;
601}
602
568603#if !SANITIZER_GO
569604// Read the file to extract the ImageBase field from the PE header. If ASLR is
570605// disabled and this virtual address is available, the loader will typically
......@@ -688,13 +723,24 @@ void ListOfModules::fallbackInit() { clear(); }
688723// atexit() as soon as it is ready for use (i.e. after .CRT$XIC initializers).
689724InternalMmapVectorNoCtor<void (*)(void)> atexit_functions;
690725
691int Atexit(void (*function)(void)) {
726static int queueAtexit(void (*function)(void)) {
692727 atexit_functions.push_back(function);
693728 return 0;
694729}
695730
731// If Atexit() is being called after RunAtexit() has already been run, it needs
732// to be able to call atexit() directly. Here we use a function ponter to
733// switch out its behaviour.
734// An example of where this is needed is the asan_dynamic runtime on MinGW-w64.
735// On this environment, __asan_init is called during global constructor phase,
736// way after calling the .CRT$XID initializer.
737static int (*volatile queueOrCallAtExit)(void (*)(void)) = &queueAtexit;
738
739int Atexit(void (*function)(void)) { return queueOrCallAtExit(function); }
740
696741static int RunAtexit() {
697742 TraceLoggingUnregister(g_asan_provider);
743 queueOrCallAtExit = &atexit;
698744 int ret = 0;
699745 for (uptr i = 0; i < atexit_functions.size(); ++i) {
700746 ret |= atexit(atexit_functions[i]);
......@@ -827,27 +873,6 @@ void FutexWake(atomic_uint32_t *p, u32 count) {
827873 WakeByAddressAll(p);
828874}
829875
830// ---------------------- BlockingMutex ---------------- {{{1
831
832BlockingMutex::BlockingMutex() {
833 CHECK(sizeof(SRWLOCK) <= sizeof(opaque_storage_));
834 internal_memset(this, 0, sizeof(*this));
835}
836
837void BlockingMutex::Lock() {
838 AcquireSRWLockExclusive((PSRWLOCK)opaque_storage_);
839 CHECK_EQ(owner_, 0);
840 owner_ = GetThreadSelf();
841}
842
843void BlockingMutex::Unlock() {
844 CheckLocked();
845 owner_ = 0;
846 ReleaseSRWLockExclusive((PSRWLOCK)opaque_storage_);
847}
848
849void BlockingMutex::CheckLocked() const { CHECK_EQ(owner_, GetThreadSelf()); }
850
851876uptr GetTlsSize() {
852877 return 0;
853878}
......@@ -962,13 +987,18 @@ void SignalContext::InitPcSpBp() {
962987 CONTEXT *context_record = (CONTEXT *)context;
963988
964989 pc = (uptr)exception_record->ExceptionAddress;
965#ifdef _WIN64
990# if SANITIZER_WINDOWS64
991# if SANITIZER_ARM64
992 bp = (uptr)context_record->Fp;
993 sp = (uptr)context_record->Sp;
994# else
966995 bp = (uptr)context_record->Rbp;
967996 sp = (uptr)context_record->Rsp;
968#else
997# endif
998# else
969999 bp = (uptr)context_record->Ebp;
9701000 sp = (uptr)context_record->Esp;
971#endif
1001# endif
9721002}
9731003
9741004uptr SignalContext::GetAddress() const {
......@@ -990,7 +1020,7 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
9901020
9911021 // The write flag is only available for access violation exceptions.
9921022 if (exception_record->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
993 return SignalContext::UNKNOWN;
1023 return SignalContext::Unknown;
9941024
9951025 // The contents of this array are documented at
9961026 // https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-exception_record
......@@ -998,13 +1028,13 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
9981028 // second element is the faulting address.
9991029 switch (exception_record->ExceptionInformation[0]) {
10001030 case 0:
1001 return SignalContext::READ;
1031 return SignalContext::Read;
10021032 case 1:
1003 return SignalContext::WRITE;
1033 return SignalContext::Write;
10041034 case 8:
1005 return SignalContext::UNKNOWN;
1035 return SignalContext::Unknown;
10061036 }
1007 return SignalContext::UNKNOWN;
1037 return SignalContext::Unknown;
10081038}
10091039
10101040void SignalContext::DumpAllRegisters(void *context) {
......@@ -1091,10 +1121,6 @@ void InitializePlatformEarly() {
10911121 // Do nothing.
10921122}
10931123
1094void MaybeReexec() {
1095 // No need to re-exec on Windows.
1096}
1097
10981124void CheckASLR() {
10991125 // Do nothing
11001126}
......@@ -1131,7 +1157,7 @@ bool IsProcessRunning(pid_t pid) {
11311157int WaitForProcess(pid_t pid) { return -1; }
11321158
11331159// FIXME implement on this platform.
1134void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) { }
1160void GetMemoryProfile(fill_profile_f cb, uptr *stats) {}
11351161
11361162void CheckNoDeepBind(const char *filename, int flag) {
11371163 // Do nothing.
lib/tsan/sanitizer_common/sanitizer_win_dll_thunk.cpp created+101
......@@ -0,0 +1,101 @@
1//===-- sanitizer_win_dll_thunk.cpp ---------------------------------------===//
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// This file defines a family of thunks that should be statically linked into
9// the DLLs that have instrumentation in order to delegate the calls to the
10// shared runtime that lives in the main binary.
11// See https://github.com/google/sanitizers/issues/209 for the details.
12//===----------------------------------------------------------------------===//
13
14#ifdef SANITIZER_DLL_THUNK
15#include "sanitizer_win_defs.h"
16#include "sanitizer_win_dll_thunk.h"
17#include "interception/interception.h"
18
19extern "C" {
20void *WINAPI GetModuleHandleA(const char *module_name);
21void abort();
22}
23
24namespace __sanitizer {
25uptr dllThunkGetRealAddrOrDie(const char *name) {
26 uptr ret =
27 __interception::InternalGetProcAddress((void *)GetModuleHandleA(0), name);
28 if (!ret)
29 abort();
30 return ret;
31}
32
33int dllThunkIntercept(const char* main_function, uptr dll_function) {
34 uptr wrapper = dllThunkGetRealAddrOrDie(main_function);
35 if (!__interception::OverrideFunction(dll_function, wrapper, 0))
36 abort();
37 return 0;
38}
39
40int dllThunkInterceptWhenPossible(const char* main_function,
41 const char* default_function, uptr dll_function) {
42 uptr wrapper = __interception::InternalGetProcAddress(
43 (void *)GetModuleHandleA(0), main_function);
44 if (!wrapper)
45 wrapper = dllThunkGetRealAddrOrDie(default_function);
46 if (!__interception::OverrideFunction(dll_function, wrapper, 0))
47 abort();
48 return 0;
49}
50} // namespace __sanitizer
51
52// Include Sanitizer Common interface.
53#define INTERFACE_FUNCTION(Name) INTERCEPT_SANITIZER_FUNCTION(Name)
54#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name)
55#include "sanitizer_common_interface.inc"
56
57#pragma section(".DLLTH$A", read)
58#pragma section(".DLLTH$Z", read)
59
60typedef void (*DllThunkCB)();
61extern "C" {
62__declspec(allocate(".DLLTH$A")) DllThunkCB __start_dll_thunk;
63__declspec(allocate(".DLLTH$Z")) DllThunkCB __stop_dll_thunk;
64}
65
66// Disable compiler warnings that show up if we declare our own version
67// of a compiler intrinsic (e.g. strlen).
68#pragma warning(disable: 4391)
69#pragma warning(disable: 4392)
70
71extern "C" int __dll_thunk_init() {
72 static bool flag = false;
73 // __dll_thunk_init is expected to be called by only one thread.
74 if (flag) return 0;
75 flag = true;
76
77 for (DllThunkCB *it = &__start_dll_thunk; it < &__stop_dll_thunk; ++it)
78 if (*it)
79 (*it)();
80
81 // In DLLs, the callbacks are expected to return 0,
82 // otherwise CRT initialization fails.
83 return 0;
84}
85
86// We want to call dll_thunk_init before C/C++ initializers / constructors are
87// executed, otherwise functions like memset might be invoked.
88#pragma section(".CRT$XIB", long, read)
89__declspec(allocate(".CRT$XIB")) int (*__dll_thunk_preinit)() =
90 __dll_thunk_init;
91
92static void WINAPI dll_thunk_thread_init(void *mod, unsigned long reason,
93 void *reserved) {
94 if (reason == /*DLL_PROCESS_ATTACH=*/1) __dll_thunk_init();
95}
96
97#pragma section(".CRT$XLAB", long, read)
98__declspec(allocate(".CRT$XLAB")) void (WINAPI *__dll_thunk_tls_init)(void *,
99 unsigned long, void *) = dll_thunk_thread_init;
100
101#endif // SANITIZER_DLL_THUNK
lib/tsan/sanitizer_common/sanitizer_win_dll_thunk.h+1-1
......@@ -84,7 +84,7 @@ extern "C" int __dll_thunk_init();
8484// which isn't a big deal.
8585#define INTERCEPT_LIBRARY_FUNCTION(name) \
8686 extern "C" void name(); \
87 INTERCEPT_OR_DIE(WRAPPER_NAME(name), name)
87 INTERCEPT_OR_DIE(STRINGIFY(WRAP(name)), name)
8888
8989// Use these macros for functions that could be called before __dll_thunk_init()
9090// is executed and don't lead to errors if defined (free, malloc, etc).
lib/tsan/sanitizer_common/sanitizer_win_dynamic_runtime_thunk.cpp created+26
......@@ -0,0 +1,26 @@
1//===-- santizer_win_dynamic_runtime_thunk.cpp ----------------------------===//
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 defines things that need to be present in the application modules
10// to interact with Sanitizer Common, when it is included in a dll.
11//
12//===----------------------------------------------------------------------===//
13#ifdef SANITIZER_DYNAMIC_RUNTIME_THUNK
14#define SANITIZER_IMPORT_INTERFACE 1
15#include "sanitizer_win_defs.h"
16// Define weak alias for all weak functions imported from sanitizer common.
17#define INTERFACE_FUNCTION(Name)
18#define INTERFACE_WEAK_FUNCTION(Name) WIN_WEAK_IMPORT_DEF(Name)
19#include "sanitizer_common_interface.inc"
20#endif // SANITIZER_DYNAMIC_RUNTIME_THUNK
21
22namespace __sanitizer {
23// Add one, otherwise unused, external symbol to this object file so that the
24// Visual C++ linker includes it and reads the .drective section.
25void ForceWholeArchiveIncludeForSanitizerCommon() {}
26}
lib/tsan/sanitizer_common/sanitizer_win_weak_interception.cpp created+94
......@@ -0,0 +1,94 @@
1//===-- sanitizer_win_weak_interception.cpp -------------------------------===//
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// This module should be included in the sanitizer when it is implemented as a
9// shared library on Windows (dll), in order to delegate the calls of weak
10// functions to the implementation in the main executable when a strong
11// definition is provided.
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_platform.h"
15#if SANITIZER_WINDOWS && SANITIZER_DYNAMIC
16#include "sanitizer_win_weak_interception.h"
17#include "sanitizer_allocator_interface.h"
18#include "sanitizer_interface_internal.h"
19#include "sanitizer_win_defs.h"
20#include "interception/interception.h"
21
22extern "C" {
23void *WINAPI GetModuleHandleA(const char *module_name);
24void abort();
25}
26
27namespace __sanitizer {
28// Try to get a pointer to real_function in the main module and override
29// dll_function with that pointer. If the function isn't found, nothing changes.
30int interceptWhenPossible(uptr dll_function, const char *real_function) {
31 uptr real = __interception::InternalGetProcAddress(
32 (void *)GetModuleHandleA(0), real_function);
33 if (real && !__interception::OverrideFunction((uptr)dll_function, real, 0))
34 abort();
35 return 0;
36}
37} // namespace __sanitizer
38
39// Declare weak hooks.
40extern "C" {
41void __sanitizer_on_print(const char *str);
42void __sanitizer_weak_hook_memcmp(uptr called_pc, const void *s1,
43 const void *s2, uptr n, int result);
44void __sanitizer_weak_hook_strcmp(uptr called_pc, const char *s1,
45 const char *s2, int result);
46void __sanitizer_weak_hook_strncmp(uptr called_pc, const char *s1,
47 const char *s2, uptr n, int result);
48void __sanitizer_weak_hook_strstr(uptr called_pc, const char *s1,
49 const char *s2, char *result);
50}
51
52// Include Sanitizer Common interface.
53#define INTERFACE_FUNCTION(Name)
54#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name)
55#include "sanitizer_common_interface.inc"
56
57#pragma section(".WEAK$A", read)
58#pragma section(".WEAK$Z", read)
59
60typedef void (*InterceptCB)();
61extern "C" {
62__declspec(allocate(".WEAK$A")) InterceptCB __start_weak_list;
63__declspec(allocate(".WEAK$Z")) InterceptCB __stop_weak_list;
64}
65
66static int weak_intercept_init() {
67 static bool flag = false;
68 // weak_interception_init is expected to be called by only one thread.
69 if (flag) return 0;
70 flag = true;
71
72 for (InterceptCB *it = &__start_weak_list; it < &__stop_weak_list; ++it)
73 if (*it)
74 (*it)();
75
76 // In DLLs, the callbacks are expected to return 0,
77 // otherwise CRT initialization fails.
78 return 0;
79}
80
81#pragma section(".CRT$XIB", long, read)
82__declspec(allocate(".CRT$XIB")) int (*__weak_intercept_preinit)() =
83 weak_intercept_init;
84
85static void WINAPI weak_intercept_thread_init(void *mod, unsigned long reason,
86 void *reserved) {
87 if (reason == /*DLL_PROCESS_ATTACH=*/1) weak_intercept_init();
88}
89
90#pragma section(".CRT$XLAB", long, read)
91__declspec(allocate(".CRT$XLAB")) void(WINAPI *__weak_intercept_tls_init)(
92 void *, unsigned long, void *) = weak_intercept_thread_init;
93
94#endif // SANITIZER_WINDOWS && SANITIZER_DYNAMIC
lib/tsan/tsan_clock.cpp deleted-625
......@@ -1,625 +0,0 @@
1//===-- tsan_clock.cpp ----------------------------------------------------===//
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#include "tsan_clock.h"
13#include "tsan_rtl.h"
14#include "sanitizer_common/sanitizer_placement_new.h"
15
16// SyncClock and ThreadClock implement vector clocks for sync variables
17// (mutexes, atomic variables, file descriptors, etc) and threads, respectively.
18// ThreadClock contains fixed-size vector clock for maximum number of threads.
19// SyncClock contains growable vector clock for currently necessary number of
20// threads.
21// Together they implement very simple model of operations, namely:
22//
23// void ThreadClock::acquire(const SyncClock *src) {
24// for (int i = 0; i < kMaxThreads; i++)
25// clock[i] = max(clock[i], src->clock[i]);
26// }
27//
28// void ThreadClock::release(SyncClock *dst) const {
29// for (int i = 0; i < kMaxThreads; i++)
30// dst->clock[i] = max(dst->clock[i], clock[i]);
31// }
32//
33// void ThreadClock::releaseStoreAcquire(SyncClock *sc) const {
34// for (int i = 0; i < kMaxThreads; i++) {
35// tmp = clock[i];
36// clock[i] = max(clock[i], sc->clock[i]);
37// sc->clock[i] = tmp;
38// }
39// }
40//
41// void ThreadClock::ReleaseStore(SyncClock *dst) const {
42// for (int i = 0; i < kMaxThreads; i++)
43// dst->clock[i] = clock[i];
44// }
45//
46// void ThreadClock::acq_rel(SyncClock *dst) {
47// acquire(dst);
48// release(dst);
49// }
50//
51// Conformance to this model is extensively verified in tsan_clock_test.cpp.
52// However, the implementation is significantly more complex. The complexity
53// allows to implement important classes of use cases in O(1) instead of O(N).
54//
55// The use cases are:
56// 1. Singleton/once atomic that has a single release-store operation followed
57// by zillions of acquire-loads (the acquire-load is O(1)).
58// 2. Thread-local mutex (both lock and unlock can be O(1)).
59// 3. Leaf mutex (unlock is O(1)).
60// 4. A mutex shared by 2 threads (both lock and unlock can be O(1)).
61// 5. An atomic with a single writer (writes can be O(1)).
62// The implementation dynamically adopts to workload. So if an atomic is in
63// read-only phase, these reads will be O(1); if it later switches to read/write
64// phase, the implementation will correctly handle that by switching to O(N).
65//
66// Thread-safety note: all const operations on SyncClock's are conducted under
67// a shared lock; all non-const operations on SyncClock's are conducted under
68// an exclusive lock; ThreadClock's are private to respective threads and so
69// do not need any protection.
70//
71// Description of SyncClock state:
72// clk_ - variable size vector clock, low kClkBits hold timestamp,
73// the remaining bits hold "acquired" flag (the actual value is thread's
74// reused counter);
75// if acquried == thr->reused_, then the respective thread has already
76// acquired this clock (except possibly for dirty elements).
77// dirty_ - holds up to two indeces in the vector clock that other threads
78// need to acquire regardless of "acquired" flag value;
79// release_store_tid_ - denotes that the clock state is a result of
80// release-store operation by the thread with release_store_tid_ index.
81// release_store_reused_ - reuse count of release_store_tid_.
82
83namespace __tsan {
84
85static atomic_uint32_t *ref_ptr(ClockBlock *cb) {
86 return reinterpret_cast<atomic_uint32_t *>(&cb->table[ClockBlock::kRefIdx]);
87}
88
89// Drop reference to the first level block idx.
90static void UnrefClockBlock(ClockCache *c, u32 idx, uptr blocks) {
91 ClockBlock *cb = ctx->clock_alloc.Map(idx);
92 atomic_uint32_t *ref = ref_ptr(cb);
93 u32 v = atomic_load(ref, memory_order_acquire);
94 for (;;) {
95 CHECK_GT(v, 0);
96 if (v == 1)
97 break;
98 if (atomic_compare_exchange_strong(ref, &v, v - 1, memory_order_acq_rel))
99 return;
100 }
101 // First level block owns second level blocks, so them as well.
102 for (uptr i = 0; i < blocks; i++)
103 ctx->clock_alloc.Free(c, cb->table[ClockBlock::kBlockIdx - i]);
104 ctx->clock_alloc.Free(c, idx);
105}
106
107ThreadClock::ThreadClock(unsigned tid, unsigned reused)
108 : tid_(tid)
109 , reused_(reused + 1) // 0 has special meaning
110 , last_acquire_()
111 , global_acquire_()
112 , cached_idx_()
113 , cached_size_()
114 , cached_blocks_() {
115 CHECK_LT(tid, kMaxTidInClock);
116 CHECK_EQ(reused_, ((u64)reused_ << kClkBits) >> kClkBits);
117 nclk_ = tid_ + 1;
118 internal_memset(clk_, 0, sizeof(clk_));
119}
120
121void ThreadClock::ResetCached(ClockCache *c) {
122 if (cached_idx_) {
123 UnrefClockBlock(c, cached_idx_, cached_blocks_);
124 cached_idx_ = 0;
125 cached_size_ = 0;
126 cached_blocks_ = 0;
127 }
128}
129
130void ThreadClock::acquire(ClockCache *c, SyncClock *src) {
131 DCHECK_LE(nclk_, kMaxTid);
132 DCHECK_LE(src->size_, kMaxTid);
133
134 // Check if it's empty -> no need to do anything.
135 const uptr nclk = src->size_;
136 if (nclk == 0)
137 return;
138
139 bool acquired = false;
140 for (unsigned i = 0; i < kDirtyTids; i++) {
141 SyncClock::Dirty dirty = src->dirty_[i];
142 unsigned tid = dirty.tid();
143 if (tid != kInvalidTid) {
144 if (clk_[tid] < dirty.epoch) {
145 clk_[tid] = dirty.epoch;
146 acquired = true;
147 }
148 }
149 }
150
151 // Check if we've already acquired src after the last release operation on src
152 if (tid_ >= nclk || src->elem(tid_).reused != reused_) {
153 // O(N) acquire.
154 nclk_ = max(nclk_, nclk);
155 u64 *dst_pos = &clk_[0];
156 for (ClockElem &src_elem : *src) {
157 u64 epoch = src_elem.epoch;
158 if (*dst_pos < epoch) {
159 *dst_pos = epoch;
160 acquired = true;
161 }
162 dst_pos++;
163 }
164
165 // Remember that this thread has acquired this clock.
166 if (nclk > tid_)
167 src->elem(tid_).reused = reused_;
168 }
169
170 if (acquired) {
171 last_acquire_ = clk_[tid_];
172 ResetCached(c);
173 }
174}
175
176void ThreadClock::releaseStoreAcquire(ClockCache *c, SyncClock *sc) {
177 DCHECK_LE(nclk_, kMaxTid);
178 DCHECK_LE(sc->size_, kMaxTid);
179
180 if (sc->size_ == 0) {
181 // ReleaseStore will correctly set release_store_tid_,
182 // which can be important for future operations.
183 ReleaseStore(c, sc);
184 return;
185 }
186
187 nclk_ = max(nclk_, (uptr) sc->size_);
188
189 // Check if we need to resize sc.
190 if (sc->size_ < nclk_)
191 sc->Resize(c, nclk_);
192
193 bool acquired = false;
194
195 sc->Unshare(c);
196 // Update sc->clk_.
197 sc->FlushDirty();
198 uptr i = 0;
199 for (ClockElem &ce : *sc) {
200 u64 tmp = clk_[i];
201 if (clk_[i] < ce.epoch) {
202 clk_[i] = ce.epoch;
203 acquired = true;
204 }
205 ce.epoch = tmp;
206 ce.reused = 0;
207 i++;
208 }
209 sc->release_store_tid_ = kInvalidTid;
210 sc->release_store_reused_ = 0;
211
212 if (acquired) {
213 last_acquire_ = clk_[tid_];
214 ResetCached(c);
215 }
216}
217
218void ThreadClock::release(ClockCache *c, SyncClock *dst) {
219 DCHECK_LE(nclk_, kMaxTid);
220 DCHECK_LE(dst->size_, kMaxTid);
221
222 if (dst->size_ == 0) {
223 // ReleaseStore will correctly set release_store_tid_,
224 // which can be important for future operations.
225 ReleaseStore(c, dst);
226 return;
227 }
228
229 // Check if we need to resize dst.
230 if (dst->size_ < nclk_)
231 dst->Resize(c, nclk_);
232
233 // Check if we had not acquired anything from other threads
234 // since the last release on dst. If so, we need to update
235 // only dst->elem(tid_).
236 if (!HasAcquiredAfterRelease(dst)) {
237 UpdateCurrentThread(c, dst);
238 if (dst->release_store_tid_ != tid_ ||
239 dst->release_store_reused_ != reused_)
240 dst->release_store_tid_ = kInvalidTid;
241 return;
242 }
243
244 // O(N) release.
245 dst->Unshare(c);
246 // First, remember whether we've acquired dst.
247 bool acquired = IsAlreadyAcquired(dst);
248 // Update dst->clk_.
249 dst->FlushDirty();
250 uptr i = 0;
251 for (ClockElem &ce : *dst) {
252 ce.epoch = max(ce.epoch, clk_[i]);
253 ce.reused = 0;
254 i++;
255 }
256 // Clear 'acquired' flag in the remaining elements.
257 dst->release_store_tid_ = kInvalidTid;
258 dst->release_store_reused_ = 0;
259 // If we've acquired dst, remember this fact,
260 // so that we don't need to acquire it on next acquire.
261 if (acquired)
262 dst->elem(tid_).reused = reused_;
263}
264
265void ThreadClock::ReleaseStore(ClockCache *c, SyncClock *dst) {
266 DCHECK_LE(nclk_, kMaxTid);
267 DCHECK_LE(dst->size_, kMaxTid);
268
269 if (dst->size_ == 0 && cached_idx_ != 0) {
270 // Reuse the cached clock.
271 // Note: we could reuse/cache the cached clock in more cases:
272 // we could update the existing clock and cache it, or replace it with the
273 // currently cached clock and release the old one. And for a shared
274 // existing clock, we could replace it with the currently cached;
275 // or unshare, update and cache. But, for simplicity, we currnetly reuse
276 // cached clock only when the target clock is empty.
277 dst->tab_ = ctx->clock_alloc.Map(cached_idx_);
278 dst->tab_idx_ = cached_idx_;
279 dst->size_ = cached_size_;
280 dst->blocks_ = cached_blocks_;
281 CHECK_EQ(dst->dirty_[0].tid(), kInvalidTid);
282 // The cached clock is shared (immutable),
283 // so this is where we store the current clock.
284 dst->dirty_[0].set_tid(tid_);
285 dst->dirty_[0].epoch = clk_[tid_];
286 dst->release_store_tid_ = tid_;
287 dst->release_store_reused_ = reused_;
288 // Rememeber that we don't need to acquire it in future.
289 dst->elem(tid_).reused = reused_;
290 // Grab a reference.
291 atomic_fetch_add(ref_ptr(dst->tab_), 1, memory_order_relaxed);
292 return;
293 }
294
295 // Check if we need to resize dst.
296 if (dst->size_ < nclk_)
297 dst->Resize(c, nclk_);
298
299 if (dst->release_store_tid_ == tid_ &&
300 dst->release_store_reused_ == reused_ &&
301 !HasAcquiredAfterRelease(dst)) {
302 UpdateCurrentThread(c, dst);
303 return;
304 }
305
306 // O(N) release-store.
307 dst->Unshare(c);
308 // Note: dst can be larger than this ThreadClock.
309 // This is fine since clk_ beyond size is all zeros.
310 uptr i = 0;
311 for (ClockElem &ce : *dst) {
312 ce.epoch = clk_[i];
313 ce.reused = 0;
314 i++;
315 }
316 for (uptr i = 0; i < kDirtyTids; i++) dst->dirty_[i].set_tid(kInvalidTid);
317 dst->release_store_tid_ = tid_;
318 dst->release_store_reused_ = reused_;
319 // Rememeber that we don't need to acquire it in future.
320 dst->elem(tid_).reused = reused_;
321
322 // If the resulting clock is cachable, cache it for future release operations.
323 // The clock is always cachable if we released to an empty sync object.
324 if (cached_idx_ == 0 && dst->Cachable()) {
325 // Grab a reference to the ClockBlock.
326 atomic_uint32_t *ref = ref_ptr(dst->tab_);
327 if (atomic_load(ref, memory_order_acquire) == 1)
328 atomic_store_relaxed(ref, 2);
329 else
330 atomic_fetch_add(ref_ptr(dst->tab_), 1, memory_order_relaxed);
331 cached_idx_ = dst->tab_idx_;
332 cached_size_ = dst->size_;
333 cached_blocks_ = dst->blocks_;
334 }
335}
336
337void ThreadClock::acq_rel(ClockCache *c, SyncClock *dst) {
338 acquire(c, dst);
339 ReleaseStore(c, dst);
340}
341
342// Updates only single element related to the current thread in dst->clk_.
343void ThreadClock::UpdateCurrentThread(ClockCache *c, SyncClock *dst) const {
344 // Update the threads time, but preserve 'acquired' flag.
345 for (unsigned i = 0; i < kDirtyTids; i++) {
346 SyncClock::Dirty *dirty = &dst->dirty_[i];
347 const unsigned tid = dirty->tid();
348 if (tid == tid_ || tid == kInvalidTid) {
349 dirty->set_tid(tid_);
350 dirty->epoch = clk_[tid_];
351 return;
352 }
353 }
354 // Reset all 'acquired' flags, O(N).
355 // We are going to touch dst elements, so we need to unshare it.
356 dst->Unshare(c);
357 dst->elem(tid_).epoch = clk_[tid_];
358 for (uptr i = 0; i < dst->size_; i++)
359 dst->elem(i).reused = 0;
360 dst->FlushDirty();
361}
362
363// Checks whether the current thread has already acquired src.
364bool ThreadClock::IsAlreadyAcquired(const SyncClock *src) const {
365 if (src->elem(tid_).reused != reused_)
366 return false;
367 for (unsigned i = 0; i < kDirtyTids; i++) {
368 SyncClock::Dirty dirty = src->dirty_[i];
369 if (dirty.tid() != kInvalidTid) {
370 if (clk_[dirty.tid()] < dirty.epoch)
371 return false;
372 }
373 }
374 return true;
375}
376
377// Checks whether the current thread has acquired anything
378// from other clocks after releasing to dst (directly or indirectly).
379bool ThreadClock::HasAcquiredAfterRelease(const SyncClock *dst) const {
380 const u64 my_epoch = dst->elem(tid_).epoch;
381 return my_epoch <= last_acquire_ ||
382 my_epoch <= atomic_load_relaxed(&global_acquire_);
383}
384
385// Sets a single element in the vector clock.
386// This function is called only from weird places like AcquireGlobal.
387void ThreadClock::set(ClockCache *c, unsigned tid, u64 v) {
388 DCHECK_LT(tid, kMaxTid);
389 DCHECK_GE(v, clk_[tid]);
390 clk_[tid] = v;
391 if (nclk_ <= tid)
392 nclk_ = tid + 1;
393 last_acquire_ = clk_[tid_];
394 ResetCached(c);
395}
396
397void ThreadClock::DebugDump(int(*printf)(const char *s, ...)) {
398 printf("clock=[");
399 for (uptr i = 0; i < nclk_; i++)
400 printf("%s%llu", i == 0 ? "" : ",", clk_[i]);
401 printf("] tid=%u/%u last_acq=%llu", tid_, reused_, last_acquire_);
402}
403
404SyncClock::SyncClock() {
405 ResetImpl();
406}
407
408SyncClock::~SyncClock() {
409 // Reset must be called before dtor.
410 CHECK_EQ(size_, 0);
411 CHECK_EQ(blocks_, 0);
412 CHECK_EQ(tab_, 0);
413 CHECK_EQ(tab_idx_, 0);
414}
415
416void SyncClock::Reset(ClockCache *c) {
417 if (size_)
418 UnrefClockBlock(c, tab_idx_, blocks_);
419 ResetImpl();
420}
421
422void SyncClock::ResetImpl() {
423 tab_ = 0;
424 tab_idx_ = 0;
425 size_ = 0;
426 blocks_ = 0;
427 release_store_tid_ = kInvalidTid;
428 release_store_reused_ = 0;
429 for (uptr i = 0; i < kDirtyTids; i++) dirty_[i].set_tid(kInvalidTid);
430}
431
432void SyncClock::Resize(ClockCache *c, uptr nclk) {
433 Unshare(c);
434 if (nclk <= capacity()) {
435 // Memory is already allocated, just increase the size.
436 size_ = nclk;
437 return;
438 }
439 if (size_ == 0) {
440 // Grow from 0 to one-level table.
441 CHECK_EQ(size_, 0);
442 CHECK_EQ(blocks_, 0);
443 CHECK_EQ(tab_, 0);
444 CHECK_EQ(tab_idx_, 0);
445 tab_idx_ = ctx->clock_alloc.Alloc(c);
446 tab_ = ctx->clock_alloc.Map(tab_idx_);
447 internal_memset(tab_, 0, sizeof(*tab_));
448 atomic_store_relaxed(ref_ptr(tab_), 1);
449 size_ = 1;
450 } else if (size_ > blocks_ * ClockBlock::kClockCount) {
451 u32 idx = ctx->clock_alloc.Alloc(c);
452 ClockBlock *new_cb = ctx->clock_alloc.Map(idx);
453 uptr top = size_ - blocks_ * ClockBlock::kClockCount;
454 CHECK_LT(top, ClockBlock::kClockCount);
455 const uptr move = top * sizeof(tab_->clock[0]);
456 internal_memcpy(&new_cb->clock[0], tab_->clock, move);
457 internal_memset(&new_cb->clock[top], 0, sizeof(*new_cb) - move);
458 internal_memset(tab_->clock, 0, move);
459 append_block(idx);
460 }
461 // At this point we have first level table allocated and all clock elements
462 // are evacuated from it to a second level block.
463 // Add second level tables as necessary.
464 while (nclk > capacity()) {
465 u32 idx = ctx->clock_alloc.Alloc(c);
466 ClockBlock *cb = ctx->clock_alloc.Map(idx);
467 internal_memset(cb, 0, sizeof(*cb));
468 append_block(idx);
469 }
470 size_ = nclk;
471}
472
473// Flushes all dirty elements into the main clock array.
474void SyncClock::FlushDirty() {
475 for (unsigned i = 0; i < kDirtyTids; i++) {
476 Dirty *dirty = &dirty_[i];
477 if (dirty->tid() != kInvalidTid) {
478 CHECK_LT(dirty->tid(), size_);
479 elem(dirty->tid()).epoch = dirty->epoch;
480 dirty->set_tid(kInvalidTid);
481 }
482 }
483}
484
485bool SyncClock::IsShared() const {
486 if (size_ == 0)
487 return false;
488 atomic_uint32_t *ref = ref_ptr(tab_);
489 u32 v = atomic_load(ref, memory_order_acquire);
490 CHECK_GT(v, 0);
491 return v > 1;
492}
493
494// Unshares the current clock if it's shared.
495// Shared clocks are immutable, so they need to be unshared before any updates.
496// Note: this does not apply to dirty entries as they are not shared.
497void SyncClock::Unshare(ClockCache *c) {
498 if (!IsShared())
499 return;
500 // First, copy current state into old.
501 SyncClock old;
502 old.tab_ = tab_;
503 old.tab_idx_ = tab_idx_;
504 old.size_ = size_;
505 old.blocks_ = blocks_;
506 old.release_store_tid_ = release_store_tid_;
507 old.release_store_reused_ = release_store_reused_;
508 for (unsigned i = 0; i < kDirtyTids; i++)
509 old.dirty_[i] = dirty_[i];
510 // Then, clear current object.
511 ResetImpl();
512 // Allocate brand new clock in the current object.
513 Resize(c, old.size_);
514 // Now copy state back into this object.
515 Iter old_iter(&old);
516 for (ClockElem &ce : *this) {
517 ce = *old_iter;
518 ++old_iter;
519 }
520 release_store_tid_ = old.release_store_tid_;
521 release_store_reused_ = old.release_store_reused_;
522 for (unsigned i = 0; i < kDirtyTids; i++)
523 dirty_[i] = old.dirty_[i];
524 // Drop reference to old and delete if necessary.
525 old.Reset(c);
526}
527
528// Can we cache this clock for future release operations?
529ALWAYS_INLINE bool SyncClock::Cachable() const {
530 if (size_ == 0)
531 return false;
532 for (unsigned i = 0; i < kDirtyTids; i++) {
533 if (dirty_[i].tid() != kInvalidTid)
534 return false;
535 }
536 return atomic_load_relaxed(ref_ptr(tab_)) == 1;
537}
538
539// elem linearizes the two-level structure into linear array.
540// Note: this is used only for one time accesses, vector operations use
541// the iterator as it is much faster.
542ALWAYS_INLINE ClockElem &SyncClock::elem(unsigned tid) const {
543 DCHECK_LT(tid, size_);
544 const uptr block = tid / ClockBlock::kClockCount;
545 DCHECK_LE(block, blocks_);
546 tid %= ClockBlock::kClockCount;
547 if (block == blocks_)
548 return tab_->clock[tid];
549 u32 idx = get_block(block);
550 ClockBlock *cb = ctx->clock_alloc.Map(idx);
551 return cb->clock[tid];
552}
553
554ALWAYS_INLINE uptr SyncClock::capacity() const {
555 if (size_ == 0)
556 return 0;
557 uptr ratio = sizeof(ClockBlock::clock[0]) / sizeof(ClockBlock::table[0]);
558 // How many clock elements we can fit into the first level block.
559 // +1 for ref counter.
560 uptr top = ClockBlock::kClockCount - RoundUpTo(blocks_ + 1, ratio) / ratio;
561 return blocks_ * ClockBlock::kClockCount + top;
562}
563
564ALWAYS_INLINE u32 SyncClock::get_block(uptr bi) const {
565 DCHECK(size_);
566 DCHECK_LT(bi, blocks_);
567 return tab_->table[ClockBlock::kBlockIdx - bi];
568}
569
570ALWAYS_INLINE void SyncClock::append_block(u32 idx) {
571 uptr bi = blocks_++;
572 CHECK_EQ(get_block(bi), 0);
573 tab_->table[ClockBlock::kBlockIdx - bi] = idx;
574}
575
576// Used only by tests.
577u64 SyncClock::get(unsigned tid) const {
578 for (unsigned i = 0; i < kDirtyTids; i++) {
579 Dirty dirty = dirty_[i];
580 if (dirty.tid() == tid)
581 return dirty.epoch;
582 }
583 return elem(tid).epoch;
584}
585
586// Used only by Iter test.
587u64 SyncClock::get_clean(unsigned tid) const {
588 return elem(tid).epoch;
589}
590
591void SyncClock::DebugDump(int(*printf)(const char *s, ...)) {
592 printf("clock=[");
593 for (uptr i = 0; i < size_; i++)
594 printf("%s%llu", i == 0 ? "" : ",", elem(i).epoch);
595 printf("] reused=[");
596 for (uptr i = 0; i < size_; i++)
597 printf("%s%llu", i == 0 ? "" : ",", elem(i).reused);
598 printf("] release_store_tid=%d/%d dirty_tids=%d[%llu]/%d[%llu]",
599 release_store_tid_, release_store_reused_, dirty_[0].tid(),
600 dirty_[0].epoch, dirty_[1].tid(), dirty_[1].epoch);
601}
602
603void SyncClock::Iter::Next() {
604 // Finished with the current block, move on to the next one.
605 block_++;
606 if (block_ < parent_->blocks_) {
607 // Iterate over the next second level block.
608 u32 idx = parent_->get_block(block_);
609 ClockBlock *cb = ctx->clock_alloc.Map(idx);
610 pos_ = &cb->clock[0];
611 end_ = pos_ + min(parent_->size_ - block_ * ClockBlock::kClockCount,
612 ClockBlock::kClockCount);
613 return;
614 }
615 if (block_ == parent_->blocks_ &&
616 parent_->size_ > parent_->blocks_ * ClockBlock::kClockCount) {
617 // Iterate over elements in the first level block.
618 pos_ = &parent_->tab_->clock[0];
619 end_ = pos_ + min(parent_->size_ - block_ * ClockBlock::kClockCount,
620 ClockBlock::kClockCount);
621 return;
622 }
623 parent_ = nullptr; // denotes end
624}
625} // namespace __tsan
lib/tsan/tsan_clock.h deleted-293
......@@ -1,293 +0,0 @@
1//===-- tsan_clock.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_CLOCK_H
13#define TSAN_CLOCK_H
14
15#include "tsan_defs.h"
16#include "tsan_dense_alloc.h"
17
18namespace __tsan {
19
20typedef DenseSlabAlloc<ClockBlock, 1 << 22, 1 << 10> ClockAlloc;
21typedef DenseSlabAllocCache ClockCache;
22
23// The clock that lives in sync variables (mutexes, atomics, etc).
24class SyncClock {
25 public:
26 SyncClock();
27 ~SyncClock();
28
29 uptr size() const;
30
31 // These are used only in tests.
32 u64 get(unsigned tid) const;
33 u64 get_clean(unsigned tid) const;
34
35 void Resize(ClockCache *c, uptr nclk);
36 void Reset(ClockCache *c);
37
38 void DebugDump(int(*printf)(const char *s, ...));
39
40 // Clock element iterator.
41 // Note: it iterates only over the table without regard to dirty entries.
42 class Iter {
43 public:
44 explicit Iter(SyncClock* parent);
45 Iter& operator++();
46 bool operator!=(const Iter& other);
47 ClockElem &operator*();
48
49 private:
50 SyncClock *parent_;
51 // [pos_, end_) is the current continuous range of clock elements.
52 ClockElem *pos_;
53 ClockElem *end_;
54 int block_; // Current number of second level block.
55
56 NOINLINE void Next();
57 };
58
59 Iter begin();
60 Iter end();
61
62 private:
63 friend class ThreadClock;
64 friend class Iter;
65 static const uptr kDirtyTids = 2;
66
67 struct Dirty {
68 u32 tid() const { return tid_ == kShortInvalidTid ? kInvalidTid : tid_; }
69 void set_tid(u32 tid) {
70 tid_ = tid == kInvalidTid ? kShortInvalidTid : tid;
71 }
72 u64 epoch : kClkBits;
73
74 private:
75 // Full kInvalidTid won't fit into Dirty::tid.
76 static const u64 kShortInvalidTid = (1ull << (64 - kClkBits)) - 1;
77 u64 tid_ : 64 - kClkBits; // kInvalidId if not active
78 };
79
80 static_assert(sizeof(Dirty) == 8, "Dirty is not 64bit");
81
82 unsigned release_store_tid_;
83 unsigned release_store_reused_;
84 Dirty dirty_[kDirtyTids];
85 // If size_ is 0, tab_ is nullptr.
86 // If size <= 64 (kClockCount), tab_ contains pointer to an array with
87 // 64 ClockElem's (ClockBlock::clock).
88 // Otherwise, tab_ points to an array with up to 127 u32 elements,
89 // each pointing to the second-level 512b block with 64 ClockElem's.
90 // Unused space in the first level ClockBlock is used to store additional
91 // clock elements.
92 // The last u32 element in the first level ClockBlock is always used as
93 // reference counter.
94 //
95 // See the following scheme for details.
96 // All memory blocks are 512 bytes (allocated from ClockAlloc).
97 // Clock (clk) elements are 64 bits.
98 // Idx and ref are 32 bits.
99 //
100 // tab_
101 // |
102 // \/
103 // +----------------------------------------------------+
104 // | clk128 | clk129 | ...unused... | idx1 | idx0 | ref |
105 // +----------------------------------------------------+
106 // | |
107 // | \/
108 // | +----------------+
109 // | | clk0 ... clk63 |
110 // | +----------------+
111 // \/
112 // +------------------+
113 // | clk64 ... clk127 |
114 // +------------------+
115 //
116 // Note: dirty entries, if active, always override what's stored in the clock.
117 ClockBlock *tab_;
118 u32 tab_idx_;
119 u16 size_;
120 u16 blocks_; // Number of second level blocks.
121
122 void Unshare(ClockCache *c);
123 bool IsShared() const;
124 bool Cachable() const;
125 void ResetImpl();
126 void FlushDirty();
127 uptr capacity() const;
128 u32 get_block(uptr bi) const;
129 void append_block(u32 idx);
130 ClockElem &elem(unsigned tid) const;
131};
132
133// The clock that lives in threads.
134class ThreadClock {
135 public:
136 typedef DenseSlabAllocCache Cache;
137
138 explicit ThreadClock(unsigned tid, unsigned reused = 0);
139
140 u64 get(unsigned tid) const;
141 void set(ClockCache *c, unsigned tid, u64 v);
142 void set(u64 v);
143 void tick();
144 uptr size() const;
145
146 void acquire(ClockCache *c, SyncClock *src);
147 void releaseStoreAcquire(ClockCache *c, SyncClock *src);
148 void release(ClockCache *c, SyncClock *dst);
149 void acq_rel(ClockCache *c, SyncClock *dst);
150 void ReleaseStore(ClockCache *c, SyncClock *dst);
151 void ResetCached(ClockCache *c);
152 void NoteGlobalAcquire(u64 v);
153
154 void DebugReset();
155 void DebugDump(int(*printf)(const char *s, ...));
156
157 private:
158 static const uptr kDirtyTids = SyncClock::kDirtyTids;
159 // Index of the thread associated with he clock ("current thread").
160 const unsigned tid_;
161 const unsigned reused_; // tid_ reuse count.
162 // Current thread time when it acquired something from other threads.
163 u64 last_acquire_;
164
165 // Last time another thread has done a global acquire of this thread's clock.
166 // It helps to avoid problem described in:
167 // https://github.com/golang/go/issues/39186
168 // See test/tsan/java_finalizer2.cpp for a regression test.
169 // Note the failuire is _extremely_ hard to hit, so if you are trying
170 // to reproduce it, you may want to run something like:
171 // $ go get golang.org/x/tools/cmd/stress
172 // $ stress -p=64 ./a.out
173 //
174 // The crux of the problem is roughly as follows.
175 // A number of O(1) optimizations in the clocks algorithm assume proper
176 // transitive cumulative propagation of clock values. The AcquireGlobal
177 // operation may produce an inconsistent non-linearazable view of
178 // thread clocks. Namely, it may acquire a later value from a thread
179 // with a higher ID, but fail to acquire an earlier value from a thread
180 // with a lower ID. If a thread that executed AcquireGlobal then releases
181 // to a sync clock, it will spoil the sync clock with the inconsistent
182 // values. If another thread later releases to the sync clock, the optimized
183 // algorithm may break.
184 //
185 // The exact sequence of events that leads to the failure.
186 // - thread 1 executes AcquireGlobal
187 // - thread 1 acquires value 1 for thread 2
188 // - thread 2 increments clock to 2
189 // - thread 2 releases to sync object 1
190 // - thread 3 at time 1
191 // - thread 3 acquires from sync object 1
192 // - thread 3 increments clock to 2
193 // - thread 1 acquires value 2 for thread 3
194 // - thread 1 releases to sync object 2
195 // - sync object 2 clock has 1 for thread 2 and 2 for thread 3
196 // - thread 3 releases to sync object 2
197 // - thread 3 sees value 2 in the clock for itself
198 // and decides that it has already released to the clock
199 // and did not acquire anything from other threads after that
200 // (the last_acquire_ check in release operation)
201 // - thread 3 does not update the value for thread 2 in the clock from 1 to 2
202 // - thread 4 acquires from sync object 2
203 // - thread 4 detects a false race with thread 2
204 // as it should have been synchronized with thread 2 up to time 2,
205 // but because of the broken clock it is now synchronized only up to time 1
206 //
207 // The global_acquire_ value helps to prevent this scenario.
208 // Namely, thread 3 will not trust any own clock values up to global_acquire_
209 // for the purposes of the last_acquire_ optimization.
210 atomic_uint64_t global_acquire_;
211
212 // Cached SyncClock (without dirty entries and release_store_tid_).
213 // We reuse it for subsequent store-release operations without intervening
214 // acquire operations. Since it is shared (and thus constant), clock value
215 // for the current thread is then stored in dirty entries in the SyncClock.
216 // We host a refernece to the table while it is cached here.
217 u32 cached_idx_;
218 u16 cached_size_;
219 u16 cached_blocks_;
220
221 // Number of active elements in the clk_ table (the rest is zeros).
222 uptr nclk_;
223 u64 clk_[kMaxTidInClock]; // Fixed size vector clock.
224
225 bool IsAlreadyAcquired(const SyncClock *src) const;
226 bool HasAcquiredAfterRelease(const SyncClock *dst) const;
227 void UpdateCurrentThread(ClockCache *c, SyncClock *dst) const;
228};
229
230ALWAYS_INLINE u64 ThreadClock::get(unsigned tid) const {
231 DCHECK_LT(tid, kMaxTidInClock);
232 return clk_[tid];
233}
234
235ALWAYS_INLINE void ThreadClock::set(u64 v) {
236 DCHECK_GE(v, clk_[tid_]);
237 clk_[tid_] = v;
238}
239
240ALWAYS_INLINE void ThreadClock::tick() {
241 clk_[tid_]++;
242}
243
244ALWAYS_INLINE uptr ThreadClock::size() const {
245 return nclk_;
246}
247
248ALWAYS_INLINE void ThreadClock::NoteGlobalAcquire(u64 v) {
249 // Here we rely on the fact that AcquireGlobal is protected by
250 // ThreadRegistryLock, thus only one thread at a time executes it
251 // and values passed to this function should not go backwards.
252 CHECK_LE(atomic_load_relaxed(&global_acquire_), v);
253 atomic_store_relaxed(&global_acquire_, v);
254}
255
256ALWAYS_INLINE SyncClock::Iter SyncClock::begin() {
257 return Iter(this);
258}
259
260ALWAYS_INLINE SyncClock::Iter SyncClock::end() {
261 return Iter(nullptr);
262}
263
264ALWAYS_INLINE uptr SyncClock::size() const {
265 return size_;
266}
267
268ALWAYS_INLINE SyncClock::Iter::Iter(SyncClock* parent)
269 : parent_(parent)
270 , pos_(nullptr)
271 , end_(nullptr)
272 , block_(-1) {
273 if (parent)
274 Next();
275}
276
277ALWAYS_INLINE SyncClock::Iter& SyncClock::Iter::operator++() {
278 pos_++;
279 if (UNLIKELY(pos_ >= end_))
280 Next();
281 return *this;
282}
283
284ALWAYS_INLINE bool SyncClock::Iter::operator!=(const SyncClock::Iter& other) {
285 return parent_ != other.parent_;
286}
287
288ALWAYS_INLINE ClockElem &SyncClock::Iter::operator*() {
289 return *pos_;
290}
291} // namespace __tsan
292
293#endif // TSAN_CLOCK_H
lib/tsan/tsan_debugging.cpp+6-6
......@@ -157,7 +157,7 @@ int __tsan_get_report_mutex(void *report, uptr idx, uptr *mutex_id, void **addr,
157157 ReportMutex *mutex = rep->mutexes[idx];
158158 *mutex_id = mutex->id;
159159 *addr = (void *)mutex->addr;
160 *destroyed = mutex->destroyed;
160 *destroyed = false;
161161 if (mutex->stack) CopyTrace(mutex->stack->frames, trace, trace_size);
162162 return 1;
163163}
......@@ -195,9 +195,9 @@ const char *__tsan_locate_address(uptr addr, char *name, uptr name_size,
195195 const char *region_kind = nullptr;
196196 if (name && name_size > 0) name[0] = 0;
197197
198 if (IsMetaMem(addr)) {
198 if (IsMetaMem(reinterpret_cast<u32 *>(addr))) {
199199 region_kind = "meta shadow";
200 } else if (IsShadowMem(addr)) {
200 } else if (IsShadowMem(reinterpret_cast<RawShadow *>(addr))) {
201201 region_kind = "shadow";
202202 } else {
203203 bool is_stack = false;
......@@ -215,9 +215,9 @@ const char *__tsan_locate_address(uptr addr, char *name, uptr name_size,
215215 } else {
216216 // TODO(kuba.brecka): We should not lock. This is supposed to be called
217217 // from within the debugger when other threads are stopped.
218 ctx->thread_registry->Lock();
218 ctx->thread_registry.Lock();
219219 ThreadContext *tctx = IsThreadStackOrTls(addr, &is_stack);
220 ctx->thread_registry->Unlock();
220 ctx->thread_registry.Unlock();
221221 if (tctx) {
222222 region_kind = is_stack ? "stack" : "tls";
223223 } else {
......@@ -252,7 +252,7 @@ int __tsan_get_alloc_stack(uptr addr, uptr *trace, uptr size, int *thread_id,
252252 *thread_id = b->tid;
253253 // No locking. This is supposed to be called from within the debugger when
254254 // other threads are stopped.
255 ThreadContextBase *tctx = ctx->thread_registry->GetThreadLocked(b->tid);
255 ThreadContextBase *tctx = ctx->thread_registry.GetThreadLocked(b->tid);
256256 *os_id = tctx->os_id;
257257
258258 StackTrace stack = StackDepotGet(b->stk);
lib/tsan/tsan_defs.h+64-36
......@@ -18,6 +18,24 @@
1818#include "sanitizer_common/sanitizer_mutex.h"
1919#include "ubsan/ubsan_platform.h"
2020
21#ifndef TSAN_VECTORIZE
22# define TSAN_VECTORIZE __SSE4_2__
23#endif
24
25#if TSAN_VECTORIZE
26// <emmintrin.h> transitively includes <stdlib.h>,
27// and it's prohibited to include std headers into tsan runtime.
28// So we do this dirty trick.
29# define _MM_MALLOC_H_INCLUDED
30# define __MM_MALLOC_H
31# include <emmintrin.h>
32# include <smmintrin.h>
33# define VECTOR_ALIGNED ALIGNED(16)
34typedef __m128i m128;
35#else
36# define VECTOR_ALIGNED
37#endif
38
2139// Setup defaults for compile definitions.
2240#ifndef TSAN_NO_HISTORY
2341# define TSAN_NO_HISTORY 0
......@@ -33,40 +51,26 @@
3351
3452namespace __tsan {
3553
36const int kClkBits = 42;
37const unsigned kMaxTidReuse = (1 << (64 - kClkBits)) - 1;
54constexpr uptr kByteBits = 8;
3855
39struct ClockElem {
40 u64 epoch : kClkBits;
41 u64 reused : 64 - kClkBits; // tid reuse count
42};
56// Thread slot ID.
57enum class Sid : u8 {};
58constexpr uptr kThreadSlotCount = 256;
59constexpr Sid kFreeSid = static_cast<Sid>(255);
4360
44struct ClockBlock {
45 static const uptr kSize = 512;
46 static const uptr kTableSize = kSize / sizeof(u32);
47 static const uptr kClockCount = kSize / sizeof(ClockElem);
48 static const uptr kRefIdx = kTableSize - 1;
49 static const uptr kBlockIdx = kTableSize - 2;
61// Abstract time unit, vector clock element.
62enum class Epoch : u16 {};
63constexpr uptr kEpochBits = 14;
64constexpr Epoch kEpochZero = static_cast<Epoch>(0);
65constexpr Epoch kEpochOver = static_cast<Epoch>(1 << kEpochBits);
66constexpr Epoch kEpochLast = static_cast<Epoch>((1 << kEpochBits) - 1);
5067
51 union {
52 u32 table[kTableSize];
53 ClockElem clock[kClockCount];
54 };
68inline Epoch EpochInc(Epoch epoch) {
69 return static_cast<Epoch>(static_cast<u16>(epoch) + 1);
70}
5571
56 ClockBlock() {
57 }
58};
72inline bool EpochOverflow(Epoch epoch) { return epoch == kEpochOver; }
5973
60const int kTidBits = 13;
61// Reduce kMaxTid by kClockCount because one slot in ClockBlock table is
62// occupied by reference counter, so total number of elements we can store
63// in SyncClock is kClockCount * (kTableSize - 1).
64const unsigned kMaxTid = (1 << kTidBits) - ClockBlock::kClockCount;
65#if !SANITIZER_GO
66const unsigned kMaxTidInClock = kMaxTid * 2; // This includes msb 'freed' bit.
67#else
68const unsigned kMaxTidInClock = kMaxTid; // Go does not track freed memory.
69#endif
7074const uptr kShadowStackSize = 64 * 1024;
7175
7276// Count of shadow values in a shadow cell.
......@@ -75,8 +79,9 @@ const uptr kShadowCnt = 4;
7579// That many user bytes are mapped onto a single shadow cell.
7680const uptr kShadowCell = 8;
7781
78// Size of a single shadow value (u64).
79const uptr kShadowSize = 8;
82// Single shadow value.
83enum class RawShadow : u32 {};
84const uptr kShadowSize = sizeof(RawShadow);
8085
8186// Shadow memory is kShadowMultiplier times larger than user memory.
8287const uptr kShadowMultiplier = kShadowSize * kShadowCnt / kShadowCell;
......@@ -88,6 +93,9 @@ const uptr kMetaShadowCell = 8;
8893// Size of a single meta shadow value (u32).
8994const uptr kMetaShadowSize = 4;
9095
96// All addresses and PCs are assumed to be compressable to that many bits.
97const uptr kCompressedAddrBits = 44;
98
9199#if TSAN_NO_HISTORY
92100const bool kCollectHistory = false;
93101#else
......@@ -149,17 +157,34 @@ MD5Hash md5_hash(const void *data, uptr size);
149157struct Processor;
150158struct ThreadState;
151159class ThreadContext;
160struct TidSlot;
152161struct Context;
153162struct ReportStack;
154163class ReportDesc;
155164class RegionAlloc;
165struct Trace;
166struct TracePart;
167
168typedef uptr AccessType;
169
170enum : AccessType {
171 kAccessWrite = 0,
172 kAccessRead = 1 << 0,
173 kAccessAtomic = 1 << 1,
174 kAccessVptr = 1 << 2, // read or write of an object virtual table pointer
175 kAccessFree = 1 << 3, // synthetic memory access during memory freeing
176 kAccessExternalPC = 1 << 4, // access PC can have kExternalPCBit set
177 kAccessCheckOnly = 1 << 5, // check for races, but don't store
178 kAccessNoRodata = 1 << 6, // don't check for .rodata marker
179 kAccessSlotLocked = 1 << 7, // memory access with TidSlot locked
180};
156181
157182// Descriptor of user's memory block.
158183struct MBlock {
159184 u64 siz : 48;
160185 u64 tag : 16;
161 u32 stk;
162 u16 tid;
186 StackID stk;
187 Tid tid;
163188};
164189
165190COMPILER_CHECK(sizeof(MBlock) == 16);
......@@ -173,15 +198,18 @@ enum ExternalTag : uptr {
173198 // as 16-bit values, see tsan_defs.h.
174199};
175200
176enum MutexType {
177 MutexTypeTrace = MutexLastCommon,
178 MutexTypeReport,
201enum {
202 MutexTypeReport = MutexLastCommon,
179203 MutexTypeSyncVar,
180204 MutexTypeAnnotations,
181205 MutexTypeAtExit,
182206 MutexTypeFired,
183207 MutexTypeRacy,
184208 MutexTypeGlobalProc,
209 MutexTypeInternalAlloc,
210 MutexTypeTrace,
211 MutexTypeSlot,
212 MutexTypeSlots,
185213};
186214
187215} // namespace __tsan
lib/tsan/tsan_dense_alloc.h+89-45
......@@ -49,11 +49,7 @@ class DenseSlabAlloc {
4949 static_assert(sizeof(T) > sizeof(IndexT),
5050 "it doesn't make sense to use dense alloc");
5151
52 explicit DenseSlabAlloc(LinkerInitialized, const char *name) {
53 freelist_ = 0;
54 fillpos_ = 0;
55 name_ = name;
56 }
52 DenseSlabAlloc(LinkerInitialized, const char *name) : name_(name) {}
5753
5854 explicit DenseSlabAlloc(const char *name)
5955 : DenseSlabAlloc(LINKER_INITIALIZED, name) {
......@@ -89,12 +85,7 @@ class DenseSlabAlloc {
8985 }
9086
9187 void FlushCache(Cache *c) {
92 SpinMutexLock lock(&mtx_);
93 while (c->pos) {
94 IndexT idx = c->cache[--c->pos];
95 *(IndexT*)Map(idx) = freelist_;
96 freelist_ = idx;
97 }
88 while (c->pos) Drain(c);
9889 }
9990
10091 void InitCache(Cache *c) {
......@@ -102,48 +93,101 @@ class DenseSlabAlloc {
10293 internal_memset(c->cache, 0, sizeof(c->cache));
10394 }
10495
96 uptr AllocatedMemory() const {
97 return atomic_load_relaxed(&fillpos_) * kL2Size * sizeof(T);
98 }
99
100 template <typename Func>
101 void ForEach(Func func) {
102 Lock lock(&mtx_);
103 uptr fillpos = atomic_load_relaxed(&fillpos_);
104 for (uptr l1 = 0; l1 < fillpos; l1++) {
105 for (IndexT l2 = l1 == 0 ? 1 : 0; l2 < kL2Size; l2++) func(&map_[l1][l2]);
106 }
107 }
108
105109 private:
106110 T *map_[kL1Size];
107 SpinMutex mtx_;
108 IndexT freelist_;
109 uptr fillpos_;
110 const char *name_;
111
112 void Refill(Cache *c) {
113 SpinMutexLock lock(&mtx_);
114 if (freelist_ == 0) {
115 if (fillpos_ == kL1Size) {
116 Printf("ThreadSanitizer: %s overflow (%zu*%zu). Dying.\n",
117 name_, kL1Size, kL2Size);
118 Die();
119 }
120 VPrintf(2, "ThreadSanitizer: growing %s: %zu out of %zu*%zu\n",
121 name_, fillpos_, kL1Size, kL2Size);
122 T *batch = (T*)MmapOrDie(kL2Size * sizeof(T), name_);
123 // Reserve 0 as invalid index.
124 IndexT start = fillpos_ == 0 ? 1 : 0;
125 for (IndexT i = start; i < kL2Size; i++) {
126 new(batch + i) T;
127 *(IndexT*)(batch + i) = i + 1 + fillpos_ * kL2Size;
128 }
129 *(IndexT*)(batch + kL2Size - 1) = 0;
130 freelist_ = fillpos_ * kL2Size + start;
131 map_[fillpos_++] = batch;
132 }
133 for (uptr i = 0; i < Cache::kSize / 2 && freelist_ != 0; i++) {
134 IndexT idx = freelist_;
111 Mutex mtx_;
112 // The freelist is organized as a lock-free stack of batches of nodes.
113 // The stack itself uses Block::next links, while the batch within each
114 // stack node uses Block::batch links.
115 // Low 32-bits of freelist_ is the node index, top 32-bits is ABA-counter.
116 atomic_uint64_t freelist_ = {0};
117 atomic_uintptr_t fillpos_ = {0};
118 const char *const name_;
119
120 struct Block {
121 IndexT next;
122 IndexT batch;
123 };
124
125 Block *MapBlock(IndexT idx) { return reinterpret_cast<Block *>(Map(idx)); }
126
127 static constexpr u64 kCounterInc = 1ull << 32;
128 static constexpr u64 kCounterMask = ~(kCounterInc - 1);
129
130 NOINLINE void Refill(Cache *c) {
131 // Pop 1 batch of nodes from the freelist.
132 IndexT idx;
133 u64 xchg;
134 u64 cmp = atomic_load(&freelist_, memory_order_acquire);
135 do {
136 idx = static_cast<IndexT>(cmp);
137 if (!idx)
138 return AllocSuperBlock(c);
139 Block *ptr = MapBlock(idx);
140 xchg = ptr->next | (cmp & kCounterMask);
141 } while (!atomic_compare_exchange_weak(&freelist_, &cmp, xchg,
142 memory_order_acq_rel));
143 // Unpack it into c->cache.
144 while (idx) {
135145 c->cache[c->pos++] = idx;
136 freelist_ = *(IndexT*)Map(idx);
146 idx = MapBlock(idx)->batch;
137147 }
138148 }
139149
140 void Drain(Cache *c) {
141 SpinMutexLock lock(&mtx_);
142 for (uptr i = 0; i < Cache::kSize / 2; i++) {
150 NOINLINE void Drain(Cache *c) {
151 // Build a batch of at most Cache::kSize / 2 nodes linked by Block::batch.
152 IndexT head_idx = 0;
153 for (uptr i = 0; i < Cache::kSize / 2 && c->pos; i++) {
143154 IndexT idx = c->cache[--c->pos];
144 *(IndexT*)Map(idx) = freelist_;
145 freelist_ = idx;
155 Block *ptr = MapBlock(idx);
156 ptr->batch = head_idx;
157 head_idx = idx;
158 }
159 // Push it onto the freelist stack.
160 Block *head = MapBlock(head_idx);
161 u64 xchg;
162 u64 cmp = atomic_load(&freelist_, memory_order_acquire);
163 do {
164 head->next = static_cast<IndexT>(cmp);
165 xchg = head_idx | (cmp & kCounterMask) + kCounterInc;
166 } while (!atomic_compare_exchange_weak(&freelist_, &cmp, xchg,
167 memory_order_acq_rel));
168 }
169
170 NOINLINE void AllocSuperBlock(Cache *c) {
171 Lock lock(&mtx_);
172 uptr fillpos = atomic_load_relaxed(&fillpos_);
173 if (fillpos == kL1Size) {
174 Printf("ThreadSanitizer: %s overflow (%zu*%zu). Dying.\n", name_, kL1Size,
175 kL2Size);
176 Die();
177 }
178 VPrintf(2, "ThreadSanitizer: growing %s: %zu out of %zu*%zu\n", name_,
179 fillpos, kL1Size, kL2Size);
180 T *batch = (T *)MmapOrDie(kL2Size * sizeof(T), name_);
181 map_[fillpos] = batch;
182 // Reserve 0 as invalid index.
183 for (IndexT i = fillpos ? 0 : 1; i < kL2Size; i++) {
184 new (batch + i) T;
185 c->cache[c->pos++] = i + fillpos * kL2Size;
186 if (c->pos == Cache::kSize)
187 Drain(c);
146188 }
189 atomic_store_relaxed(&fillpos_, fillpos + 1);
190 CHECK(c->pos);
147191 }
148192};
149193
lib/tsan/tsan_dispatch_defs.h created+73
......@@ -0,0 +1,73 @@
1//===-- tsan_dispatch_defs.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_DISPATCH_DEFS_H
13#define TSAN_DISPATCH_DEFS_H
14
15#include "sanitizer_common/sanitizer_internal_defs.h"
16
17typedef struct dispatch_object_s {} *dispatch_object_t;
18
19#define DISPATCH_DECL(name) \
20 typedef struct name##_s : public dispatch_object_s {} *name##_t
21
22DISPATCH_DECL(dispatch_queue);
23DISPATCH_DECL(dispatch_source);
24DISPATCH_DECL(dispatch_group);
25DISPATCH_DECL(dispatch_data);
26DISPATCH_DECL(dispatch_semaphore);
27DISPATCH_DECL(dispatch_io);
28
29typedef void (*dispatch_function_t)(void *arg);
30typedef void (^dispatch_block_t)(void);
31typedef void (^dispatch_io_handler_t)(bool done, dispatch_data_t data,
32 int error);
33
34typedef long dispatch_once_t;
35typedef __sanitizer::u64 dispatch_time_t;
36typedef int dispatch_fd_t;
37typedef unsigned long dispatch_io_type_t;
38typedef unsigned long dispatch_io_close_flags_t;
39
40extern "C" {
41void *dispatch_get_context(dispatch_object_t object);
42void dispatch_retain(dispatch_object_t object);
43void dispatch_release(dispatch_object_t object);
44
45extern const dispatch_block_t _dispatch_data_destructor_free;
46extern const dispatch_block_t _dispatch_data_destructor_munmap;
47} // extern "C"
48
49#define DISPATCH_DATA_DESTRUCTOR_DEFAULT nullptr
50#define DISPATCH_DATA_DESTRUCTOR_FREE _dispatch_data_destructor_free
51#define DISPATCH_DATA_DESTRUCTOR_MUNMAP _dispatch_data_destructor_munmap
52
53#if __has_attribute(noescape)
54# define DISPATCH_NOESCAPE __attribute__((__noescape__))
55#else
56# define DISPATCH_NOESCAPE
57#endif
58
59#if SANITIZER_APPLE
60# define SANITIZER_WEAK_IMPORT extern "C" __attribute((weak_import))
61#else
62# define SANITIZER_WEAK_IMPORT extern "C" __attribute((weak))
63#endif
64
65
66// Data types used in dispatch APIs
67typedef unsigned long size_t;
68typedef unsigned long uintptr_t;
69typedef __sanitizer::s64 off_t;
70typedef __sanitizer::u16 mode_t;
71typedef long long_t;
72
73#endif // TSAN_DISPATCH_DEFS_H
lib/tsan/tsan_external.cpp+24-16
......@@ -10,9 +10,12 @@
1010//
1111//===----------------------------------------------------------------------===//
1212#include "tsan_rtl.h"
13#include "tsan_interceptors.h"
1413#include "sanitizer_common/sanitizer_ptrauth.h"
1514
15#if !SANITIZER_GO
16# include "tsan_interceptors.h"
17#endif
18
1619namespace __tsan {
1720
1821#define CALLERPC ((uptr)__builtin_return_address(0))
......@@ -43,10 +46,6 @@ const char *GetReportHeaderFromTag(uptr tag) {
4346 return tag_data ? tag_data->header : nullptr;
4447}
4548
46void InsertShadowStackFrameForTag(ThreadState *thr, uptr tag) {
47 FuncEntry(thr, (uptr)&registered_tags[tag]);
48}
49
5049uptr TagFromShadowStackFrame(uptr pc) {
5150 uptr tag_count = atomic_load(&used_tags, memory_order_relaxed);
5251 void *pc_ptr = (void *)pc;
......@@ -57,17 +56,26 @@ uptr TagFromShadowStackFrame(uptr pc) {
5756
5857#if !SANITIZER_GO
5958
60typedef void(*AccessFunc)(ThreadState *, uptr, uptr, int);
61void ExternalAccess(void *addr, uptr caller_pc, void *tag, AccessFunc access) {
59// We need to track tags for individual memory accesses, but there is no space
60// in the shadow cells for them. Instead we push/pop them onto the thread
61// traces and ignore the extra tag frames when printing reports.
62static void PushTag(ThreadState *thr, uptr tag) {
63 FuncEntry(thr, (uptr)&registered_tags[tag]);
64}
65static void PopTag(ThreadState *thr) { FuncExit(thr); }
66
67static void ExternalAccess(void *addr, uptr caller_pc, uptr tsan_caller_pc,
68 void *tag, AccessType typ) {
6269 CHECK_LT(tag, atomic_load(&used_tags, memory_order_relaxed));
70 bool in_ignored_lib;
71 if (caller_pc && libignore()->IsIgnored(caller_pc, &in_ignored_lib))
72 return;
73
6374 ThreadState *thr = cur_thread();
6475 if (caller_pc) FuncEntry(thr, caller_pc);
65 InsertShadowStackFrameForTag(thr, (uptr)tag);
66 bool in_ignored_lib;
67 if (!caller_pc || !libignore()->IsIgnored(caller_pc, &in_ignored_lib)) {
68 access(thr, CALLERPC, (uptr)addr, kSizeLog1);
69 }
70 FuncExit(thr);
76 PushTag(thr, (uptr)tag);
77 MemoryAccess(thr, tsan_caller_pc, (uptr)addr, 1, typ);
78 PopTag(thr);
7179 if (caller_pc) FuncExit(thr);
7280}
7381
......@@ -92,7 +100,7 @@ void __tsan_external_register_header(void *tag, const char *header) {
92100 header = internal_strdup(header);
93101 char *old_header =
94102 (char *)atomic_exchange(header_ptr, (uptr)header, memory_order_seq_cst);
95 if (old_header) internal_free(old_header);
103 Free(old_header);
96104}
97105
98106SANITIZER_INTERFACE_ATTRIBUTE
......@@ -111,12 +119,12 @@ void __tsan_external_assign_tag(void *addr, void *tag) {
111119
112120SANITIZER_INTERFACE_ATTRIBUTE
113121void __tsan_external_read(void *addr, void *caller_pc, void *tag) {
114 ExternalAccess(addr, STRIP_PAC_PC(caller_pc), tag, MemoryRead);
122 ExternalAccess(addr, STRIP_PAC_PC(caller_pc), CALLERPC, tag, kAccessRead);
115123}
116124
117125SANITIZER_INTERFACE_ATTRIBUTE
118126void __tsan_external_write(void *addr, void *caller_pc, void *tag) {
119 ExternalAccess(addr, STRIP_PAC_PC(caller_pc), tag, MemoryWrite);
127 ExternalAccess(addr, STRIP_PAC_PC(caller_pc), CALLERPC, tag, kAccessWrite);
120128}
121129} // extern "C"
122130
lib/tsan/tsan_fd.cpp+86-27
......@@ -11,9 +11,12 @@
1111//===----------------------------------------------------------------------===//
1212
1313#include "tsan_fd.h"
14#include "tsan_rtl.h"
14
1515#include <sanitizer_common/sanitizer_atomic.h>
1616
17#include "tsan_interceptors.h"
18#include "tsan_rtl.h"
19
1720namespace __tsan {
1821
1922const int kTableSizeL1 = 1024;
......@@ -26,8 +29,12 @@ struct FdSync {
2629
2730struct FdDesc {
2831 FdSync *sync;
29 int creation_tid;
30 u32 creation_stack;
32 // This is used to establish write -> epoll_wait synchronization
33 // where epoll_wait receives notification about the write.
34 atomic_uintptr_t aux_sync; // FdSync*
35 Tid creation_tid;
36 StackID creation_stack;
37 bool closed;
3138};
3239
3340struct FdContext {
......@@ -100,6 +107,10 @@ static void init(ThreadState *thr, uptr pc, int fd, FdSync *s,
100107 unref(thr, pc, d->sync);
101108 d->sync = 0;
102109 }
110 unref(thr, pc,
111 reinterpret_cast<FdSync *>(
112 atomic_load(&d->aux_sync, memory_order_relaxed)));
113 atomic_store(&d->aux_sync, 0, memory_order_relaxed);
103114 if (flags()->io_sync == 0) {
104115 unref(thr, pc, s);
105116 } else if (flags()->io_sync == 1) {
......@@ -110,12 +121,18 @@ static void init(ThreadState *thr, uptr pc, int fd, FdSync *s,
110121 }
111122 d->creation_tid = thr->tid;
112123 d->creation_stack = CurrentStackId(thr, pc);
124 d->closed = false;
125 // This prevents false positives on fd_close_norace3.cpp test.
126 // The mechanics of the false positive are not completely clear,
127 // but it happens only if global reset is enabled (flush_memory_ms=1)
128 // and may be related to lost writes during asynchronous MADV_DONTNEED.
129 SlotLocker locker(thr);
113130 if (write) {
114131 // To catch races between fd usage and open.
115132 MemoryRangeImitateWrite(thr, pc, (uptr)d, 8);
116133 } else {
117134 // See the dup-related comment in FdClose.
118 MemoryRead(thr, pc, (uptr)d, kSizeLog8);
135 MemoryAccess(thr, pc, (uptr)d, 8, kAccessRead | kAccessSlotLocked);
119136 }
120137}
121138
......@@ -140,7 +157,7 @@ void FdOnFork(ThreadState *thr, uptr pc) {
140157 }
141158}
142159
143bool FdLocation(uptr addr, int *fd, int *tid, u32 *stack) {
160bool FdLocation(uptr addr, int *fd, Tid *tid, StackID *stack, bool *closed) {
144161 for (int l1 = 0; l1 < kTableSizeL1; l1++) {
145162 FdDesc *tab = (FdDesc*)atomic_load(&fdctx.tab[l1], memory_order_relaxed);
146163 if (tab == 0)
......@@ -151,6 +168,7 @@ bool FdLocation(uptr addr, int *fd, int *tid, u32 *stack) {
151168 *fd = l1 * kTableSizeL1 + l2;
152169 *tid = d->creation_tid;
153170 *stack = d->creation_stack;
171 *closed = d->closed;
154172 return true;
155173 }
156174 }
......@@ -163,7 +181,7 @@ void FdAcquire(ThreadState *thr, uptr pc, int fd) {
163181 FdDesc *d = fddesc(thr, pc, fd);
164182 FdSync *s = d->sync;
165183 DPrintf("#%d: FdAcquire(%d) -> %p\n", thr->tid, fd, s);
166 MemoryRead(thr, pc, (uptr)d, kSizeLog8);
184 MemoryAccess(thr, pc, (uptr)d, 8, kAccessRead);
167185 if (s)
168186 Acquire(thr, pc, (uptr)s);
169187}
......@@ -174,9 +192,11 @@ void FdRelease(ThreadState *thr, uptr pc, int fd) {
174192 FdDesc *d = fddesc(thr, pc, fd);
175193 FdSync *s = d->sync;
176194 DPrintf("#%d: FdRelease(%d) -> %p\n", thr->tid, fd, s);
177 MemoryRead(thr, pc, (uptr)d, kSizeLog8);
195 MemoryAccess(thr, pc, (uptr)d, 8, kAccessRead);
178196 if (s)
179197 Release(thr, pc, (uptr)s);
198 if (uptr aux_sync = atomic_load(&d->aux_sync, memory_order_acquire))
199 Release(thr, pc, aux_sync);
180200}
181201
182202void FdAccess(ThreadState *thr, uptr pc, int fd) {
......@@ -184,7 +204,7 @@ void FdAccess(ThreadState *thr, uptr pc, int fd) {
184204 if (bogusfd(fd))
185205 return;
186206 FdDesc *d = fddesc(thr, pc, fd);
187 MemoryRead(thr, pc, (uptr)d, kSizeLog8);
207 MemoryAccess(thr, pc, (uptr)d, 8, kAccessRead);
188208}
189209
190210void FdClose(ThreadState *thr, uptr pc, int fd, bool write) {
......@@ -192,27 +212,42 @@ void FdClose(ThreadState *thr, uptr pc, int fd, bool write) {
192212 if (bogusfd(fd))
193213 return;
194214 FdDesc *d = fddesc(thr, pc, fd);
195 if (write) {
196 // To catch races between fd usage and close.
197 MemoryWrite(thr, pc, (uptr)d, kSizeLog8);
198 } else {
199 // This path is used only by dup2/dup3 calls.
200 // We do read instead of write because there is a number of legitimate
201 // cases where write would lead to false positives:
202 // 1. Some software dups a closed pipe in place of a socket before closing
203 // the socket (to prevent races actually).
204 // 2. Some daemons dup /dev/null in place of stdin/stdout.
205 // On the other hand we have not seen cases when write here catches real
206 // bugs.
207 MemoryRead(thr, pc, (uptr)d, kSizeLog8);
215 {
216 // Need to lock the slot to make MemoryAccess and MemoryResetRange atomic
217 // with respect to global reset. See the comment in MemoryRangeFreed.
218 SlotLocker locker(thr);
219 if (!MustIgnoreInterceptor(thr)) {
220 if (write) {
221 // To catch races between fd usage and close.
222 MemoryAccess(thr, pc, (uptr)d, 8,
223 kAccessWrite | kAccessCheckOnly | kAccessSlotLocked);
224 } else {
225 // This path is used only by dup2/dup3 calls.
226 // We do read instead of write because there is a number of legitimate
227 // cases where write would lead to false positives:
228 // 1. Some software dups a closed pipe in place of a socket before
229 // closing
230 // the socket (to prevent races actually).
231 // 2. Some daemons dup /dev/null in place of stdin/stdout.
232 // On the other hand we have not seen cases when write here catches real
233 // bugs.
234 MemoryAccess(thr, pc, (uptr)d, 8,
235 kAccessRead | kAccessCheckOnly | kAccessSlotLocked);
236 }
237 }
238 // We need to clear it, because if we do not intercept any call out there
239 // that creates fd, we will hit false postives.
240 MemoryResetRange(thr, pc, (uptr)d, 8);
208241 }
209 // We need to clear it, because if we do not intercept any call out there
210 // that creates fd, we will hit false postives.
211 MemoryResetRange(thr, pc, (uptr)d, 8);
212242 unref(thr, pc, d->sync);
213243 d->sync = 0;
214 d->creation_tid = 0;
215 d->creation_stack = 0;
244 unref(thr, pc,
245 reinterpret_cast<FdSync *>(
246 atomic_load(&d->aux_sync, memory_order_relaxed)));
247 atomic_store(&d->aux_sync, 0, memory_order_relaxed);
248 d->closed = true;
249 d->creation_tid = thr->tid;
250 d->creation_stack = CurrentStackId(thr, pc);
216251}
217252
218253void FdFileCreate(ThreadState *thr, uptr pc, int fd) {
......@@ -228,7 +263,7 @@ void FdDup(ThreadState *thr, uptr pc, int oldfd, int newfd, bool write) {
228263 return;
229264 // Ignore the case when user dups not yet connected socket.
230265 FdDesc *od = fddesc(thr, pc, oldfd);
231 MemoryRead(thr, pc, (uptr)od, kSizeLog8);
266 MemoryAccess(thr, pc, (uptr)od, 8, kAccessRead);
232267 FdClose(thr, pc, newfd, write);
233268 init(thr, pc, newfd, ref(od->sync), write);
234269}
......@@ -269,6 +304,30 @@ void FdPollCreate(ThreadState *thr, uptr pc, int fd) {
269304 init(thr, pc, fd, allocsync(thr, pc));
270305}
271306
307void FdPollAdd(ThreadState *thr, uptr pc, int epfd, int fd) {
308 DPrintf("#%d: FdPollAdd(%d, %d)\n", thr->tid, epfd, fd);
309 if (bogusfd(epfd) || bogusfd(fd))
310 return;
311 FdDesc *d = fddesc(thr, pc, fd);
312 // Associate fd with epoll fd only once.
313 // While an fd can be associated with multiple epolls at the same time,
314 // or with different epolls during different phases of lifetime,
315 // synchronization semantics (and examples) of this are unclear.
316 // So we don't support this for now.
317 // If we change the association, it will also create lifetime management
318 // problem for FdRelease which accesses the aux_sync.
319 if (atomic_load(&d->aux_sync, memory_order_relaxed))
320 return;
321 FdDesc *epd = fddesc(thr, pc, epfd);
322 FdSync *s = epd->sync;
323 if (!s)
324 return;
325 uptr cmp = 0;
326 if (atomic_compare_exchange_strong(
327 &d->aux_sync, &cmp, reinterpret_cast<uptr>(s), memory_order_release))
328 ref(s);
329}
330
272331void FdSocketCreate(ThreadState *thr, uptr pc, int fd) {
273332 DPrintf("#%d: FdSocketCreate(%d)\n", thr->tid, fd);
274333 if (bogusfd(fd))
lib/tsan/tsan_fd.h+2-1
......@@ -49,11 +49,12 @@ void FdEventCreate(ThreadState *thr, uptr pc, int fd);
4949void FdSignalCreate(ThreadState *thr, uptr pc, int fd);
5050void FdInotifyCreate(ThreadState *thr, uptr pc, int fd);
5151void FdPollCreate(ThreadState *thr, uptr pc, int fd);
52void FdPollAdd(ThreadState *thr, uptr pc, int epfd, int fd);
5253void FdSocketCreate(ThreadState *thr, uptr pc, int fd);
5354void FdSocketAccept(ThreadState *thr, uptr pc, int fd, int newfd);
5455void FdSocketConnecting(ThreadState *thr, uptr pc, int fd);
5556void FdSocketConnect(ThreadState *thr, uptr pc, int fd);
56bool FdLocation(uptr addr, int *fd, int *tid, u32 *stack);
57bool FdLocation(uptr addr, int *fd, Tid *tid, StackID *stack, bool *closed);
5758void FdOnFork(ThreadState *thr, uptr pc);
5859
5960uptr File2addr(const char *path);
lib/tsan/tsan_flags.cpp+8-11
......@@ -10,19 +10,21 @@
1010//
1111//===----------------------------------------------------------------------===//
1212
13#include "sanitizer_common/sanitizer_flags.h"
13#include "tsan_flags.h"
14
1415#include "sanitizer_common/sanitizer_flag_parser.h"
16#include "sanitizer_common/sanitizer_flags.h"
1517#include "sanitizer_common/sanitizer_libc.h"
16#include "tsan_flags.h"
17#include "tsan_rtl.h"
18#include "tsan_interface.h"
1819#include "tsan_mman.h"
20#include "tsan_rtl.h"
1921#include "ubsan/ubsan_flags.h"
2022
2123namespace __tsan {
2224
2325// Can be overriden in frontend.
2426#ifdef TSAN_EXTERNAL_HOOKS
25extern "C" const char* __tsan_default_options();
27extern "C" const char *__tsan_default_options();
2628#else
2729SANITIZER_WEAK_DEFAULT_IMPL
2830const char *__tsan_default_options() {
......@@ -55,6 +57,7 @@ void InitializeFlags(Flags *f, const char *env, const char *env_option_name) {
5557 // Override some common flags defaults.
5658 CommonFlags cf;
5759 cf.CopyFrom(*common_flags());
60 cf.external_symbolizer_path = GetEnv("TSAN_SYMBOLIZER_PATH");
5861 cf.allow_addr2line = true;
5962 if (SANITIZER_GO) {
6063 // Does not work as expected for Go: runtime handles SIGABRT and crashes.
......@@ -96,7 +99,7 @@ void InitializeFlags(Flags *f, const char *env, const char *env_option_name) {
9699 ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS");
97100#endif
98101
99 // Sanity check.
102 // Check flags.
100103 if (!f->report_bugs) {
101104 f->report_thread_leaks = false;
102105 f->report_destroy_locked = false;
......@@ -109,12 +112,6 @@ void InitializeFlags(Flags *f, const char *env, const char *env_option_name) {
109112
110113 if (common_flags()->help) parser.PrintFlagDescriptions();
111114
112 if (f->history_size < 0 || f->history_size > 7) {
113 Printf("ThreadSanitizer: incorrect value for history_size"
114 " (must be [0..7])\n");
115 Die();
116 }
117
118115 if (f->io_sync < 0 || f->io_sync > 2) {
119116 Printf("ThreadSanitizer: incorrect value for io_sync"
120117 " (must be [0..2])\n");
lib/tsan/tsan_flags.inc+11-14
......@@ -23,10 +23,6 @@ TSAN_FLAG(bool, enable_annotations, true,
2323TSAN_FLAG(bool, suppress_equal_stacks, true,
2424 "Suppress a race report if we've already output another race report "
2525 "with the same stack.")
26TSAN_FLAG(bool, suppress_equal_addresses, true,
27 "Suppress a race report if we've already output another race report "
28 "on the same address.")
29
3026TSAN_FLAG(bool, report_bugs, true,
3127 "Turns off bug reporting entirely (useful for benchmarking).")
3228TSAN_FLAG(bool, report_thread_leaks, true, "Report thread leaks at exit?")
......@@ -43,7 +39,9 @@ TSAN_FLAG(
4339 bool, force_seq_cst_atomics, false,
4440 "If set, all atomics are effectively sequentially consistent (seq_cst), "
4541 "regardless of what user actually specified.")
46TSAN_FLAG(bool, print_benign, false, "Print matched \"benign\" races at exit.")
42TSAN_FLAG(bool, force_background_thread, false,
43 "If set, eagerly launch a background thread for memory reclamation "
44 "instead of waiting for a user call to pthread_create.")
4745TSAN_FLAG(bool, halt_on_error, false, "Exit after first reported error.")
4846TSAN_FLAG(int, atexit_sleep_ms, 1000,
4947 "Sleep in main thread before exiting for that many ms "
......@@ -60,14 +58,10 @@ TSAN_FLAG(bool, stop_on_start, false,
6058 "Stops on start until __tsan_resume() is called (for debugging).")
6159TSAN_FLAG(bool, running_on_valgrind, false,
6260 "Controls whether RunningOnValgrind() returns true or false.")
63// There are a lot of goroutines in Go, so we use smaller history.
6461TSAN_FLAG(
65 int, history_size, SANITIZER_GO ? 1 : 3,
66 "Per-thread history size, controls how many previous memory accesses "
67 "are remembered per thread. Possible values are [0..7]. "
68 "history_size=0 amounts to 32K memory accesses. Each next value doubles "
69 "the amount of memory accesses, up to history_size=7 that amounts to "
70 "4M memory accesses. The default value is 2 (128K memory accesses).")
62 uptr, history_size, 0,
63 "Per-thread history size,"
64 " controls how many extra previous memory accesses are remembered per thread.")
7165TSAN_FLAG(int, io_sync, 1,
7266 "Controls level of synchronization implied by IO operations. "
7367 "0 - no synchronization "
......@@ -76,10 +70,13 @@ TSAN_FLAG(int, io_sync, 1,
7670TSAN_FLAG(bool, die_after_fork, true,
7771 "Die after multi-threaded fork if the child creates new threads.")
7872TSAN_FLAG(const char *, suppressions, "", "Suppressions file name.")
79TSAN_FLAG(bool, ignore_interceptors_accesses, SANITIZER_MAC ? true : false,
73TSAN_FLAG(bool, ignore_interceptors_accesses, SANITIZER_APPLE ? true : false,
8074 "Ignore reads and writes from all interceptors.")
81TSAN_FLAG(bool, ignore_noninstrumented_modules, SANITIZER_MAC ? true : false,
75TSAN_FLAG(bool, ignore_noninstrumented_modules, SANITIZER_APPLE ? true : false,
8276 "Interceptors should only detect races when called from instrumented "
8377 "modules.")
8478TSAN_FLAG(bool, shared_ptr_interceptor, true,
8579 "Track atomic reference counting in libc++ shared_ptr and weak_ptr.")
80TSAN_FLAG(bool, print_full_thread_history, false,
81 "If set, prints thread creation stacks for the threads involved in "
82 "the report and their ancestors up to the main thread.")
lib/tsan/tsan_ignoreset.cpp+2-10
......@@ -19,7 +19,7 @@ IgnoreSet::IgnoreSet()
1919 : size_() {
2020}
2121
22void IgnoreSet::Add(u32 stack_id) {
22void IgnoreSet::Add(StackID stack_id) {
2323 if (size_ == kMaxSize)
2424 return;
2525 for (uptr i = 0; i < size_; i++) {
......@@ -29,15 +29,7 @@ void IgnoreSet::Add(u32 stack_id) {
2929 stacks_[size_++] = stack_id;
3030}
3131
32void IgnoreSet::Reset() {
33 size_ = 0;
34}
35
36uptr IgnoreSet::Size() const {
37 return size_;
38}
39
40u32 IgnoreSet::At(uptr i) const {
32StackID IgnoreSet::At(uptr i) const {
4133 CHECK_LT(i, size_);
4234 CHECK_LE(size_, kMaxSize);
4335 return stacks_[i];
lib/tsan/tsan_ignoreset.h+6-7
......@@ -19,17 +19,16 @@ namespace __tsan {
1919
2020class IgnoreSet {
2121 public:
22 static const uptr kMaxSize = 16;
23
2422 IgnoreSet();
25 void Add(u32 stack_id);
26 void Reset();
27 uptr Size() const;
28 u32 At(uptr i) const;
23 void Add(StackID stack_id);
24 void Reset() { size_ = 0; }
25 uptr Size() const { return size_; }
26 StackID At(uptr i) const;
2927
3028 private:
29 static constexpr uptr kMaxSize = 16;
3130 uptr size_;
32 u32 stacks_[kMaxSize];
31 StackID stacks_[kMaxSize];
3332};
3433
3534} // namespace __tsan
lib/tsan/tsan_ilist.h created+189
......@@ -0,0 +1,189 @@
1//===-- tsan_ilist.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_ILIST_H
13#define TSAN_ILIST_H
14
15#include "sanitizer_common/sanitizer_internal_defs.h"
16
17namespace __tsan {
18
19class INode {
20 public:
21 INode() = default;
22
23 private:
24 INode* next_ = nullptr;
25 INode* prev_ = nullptr;
26
27 template <typename Base, INode Base::*Node, typename Elem>
28 friend class IList;
29 INode(const INode&) = delete;
30 void operator=(const INode&) = delete;
31};
32
33// Intrusive doubly-linked list.
34//
35// The node class (MyNode) needs to include "INode foo" field,
36// then the list can be declared as IList<MyNode, &MyNode::foo>.
37// This design allows to link MyNode into multiple lists using
38// different INode fields.
39// The optional Elem template argument allows to specify node MDT
40// (most derived type) if it's different from MyNode.
41template <typename Base, INode Base::*Node, typename Elem = Base>
42class IList {
43 public:
44 IList();
45
46 void PushFront(Elem* e);
47 void PushBack(Elem* e);
48 void Remove(Elem* e);
49
50 Elem* PopFront();
51 Elem* PopBack();
52 Elem* Front();
53 Elem* Back();
54
55 // Prev links point towards front of the queue.
56 Elem* Prev(Elem* e);
57 // Next links point towards back of the queue.
58 Elem* Next(Elem* e);
59
60 uptr Size() const;
61 bool Empty() const;
62 bool Queued(Elem* e) const;
63
64 private:
65 INode node_;
66 uptr size_ = 0;
67
68 void Push(Elem* e, INode* after);
69 static INode* ToNode(Elem* e);
70 static Elem* ToElem(INode* n);
71
72 IList(const IList&) = delete;
73 void operator=(const IList&) = delete;
74};
75
76template <typename Base, INode Base::*Node, typename Elem>
77IList<Base, Node, Elem>::IList() {
78 node_.next_ = node_.prev_ = &node_;
79}
80
81template <typename Base, INode Base::*Node, typename Elem>
82void IList<Base, Node, Elem>::PushFront(Elem* e) {
83 Push(e, &node_);
84}
85
86template <typename Base, INode Base::*Node, typename Elem>
87void IList<Base, Node, Elem>::PushBack(Elem* e) {
88 Push(e, node_.prev_);
89}
90
91template <typename Base, INode Base::*Node, typename Elem>
92void IList<Base, Node, Elem>::Push(Elem* e, INode* after) {
93 INode* n = ToNode(e);
94 DCHECK_EQ(n->next_, nullptr);
95 DCHECK_EQ(n->prev_, nullptr);
96 INode* next = after->next_;
97 n->next_ = next;
98 n->prev_ = after;
99 next->prev_ = n;
100 after->next_ = n;
101 size_++;
102}
103
104template <typename Base, INode Base::*Node, typename Elem>
105void IList<Base, Node, Elem>::Remove(Elem* e) {
106 INode* n = ToNode(e);
107 INode* next = n->next_;
108 INode* prev = n->prev_;
109 DCHECK(next);
110 DCHECK(prev);
111 DCHECK(size_);
112 next->prev_ = prev;
113 prev->next_ = next;
114 n->prev_ = n->next_ = nullptr;
115 size_--;
116}
117
118template <typename Base, INode Base::*Node, typename Elem>
119Elem* IList<Base, Node, Elem>::PopFront() {
120 Elem* e = Front();
121 if (e)
122 Remove(e);
123 return e;
124}
125
126template <typename Base, INode Base::*Node, typename Elem>
127Elem* IList<Base, Node, Elem>::PopBack() {
128 Elem* e = Back();
129 if (e)
130 Remove(e);
131 return e;
132}
133
134template <typename Base, INode Base::*Node, typename Elem>
135Elem* IList<Base, Node, Elem>::Front() {
136 return size_ ? ToElem(node_.next_) : nullptr;
137}
138
139template <typename Base, INode Base::*Node, typename Elem>
140Elem* IList<Base, Node, Elem>::Back() {
141 return size_ ? ToElem(node_.prev_) : nullptr;
142}
143
144template <typename Base, INode Base::*Node, typename Elem>
145Elem* IList<Base, Node, Elem>::Prev(Elem* e) {
146 INode* n = ToNode(e);
147 DCHECK(n->prev_);
148 return n->prev_ != &node_ ? ToElem(n->prev_) : nullptr;
149}
150
151template <typename Base, INode Base::*Node, typename Elem>
152Elem* IList<Base, Node, Elem>::Next(Elem* e) {
153 INode* n = ToNode(e);
154 DCHECK(n->next_);
155 return n->next_ != &node_ ? ToElem(n->next_) : nullptr;
156}
157
158template <typename Base, INode Base::*Node, typename Elem>
159uptr IList<Base, Node, Elem>::Size() const {
160 return size_;
161}
162
163template <typename Base, INode Base::*Node, typename Elem>
164bool IList<Base, Node, Elem>::Empty() const {
165 return size_ == 0;
166}
167
168template <typename Base, INode Base::*Node, typename Elem>
169bool IList<Base, Node, Elem>::Queued(Elem* e) const {
170 INode* n = ToNode(e);
171 DCHECK_EQ(!n->next_, !n->prev_);
172 return n->next_;
173}
174
175template <typename Base, INode Base::*Node, typename Elem>
176INode* IList<Base, Node, Elem>::ToNode(Elem* e) {
177 return &(e->*Node);
178}
179
180template <typename Base, INode Base::*Node, typename Elem>
181Elem* IList<Base, Node, Elem>::ToElem(INode* n) {
182 return static_cast<Elem*>(reinterpret_cast<Base*>(
183 reinterpret_cast<uptr>(n) -
184 reinterpret_cast<uptr>(&(reinterpret_cast<Elem*>(0)->*Node))));
185}
186
187} // namespace __tsan
188
189#endif
lib/tsan/tsan_interceptors.h+83-27
......@@ -10,44 +10,71 @@ class ScopedInterceptor {
1010 public:
1111 ScopedInterceptor(ThreadState *thr, const char *fname, uptr pc);
1212 ~ScopedInterceptor();
13 void DisableIgnores();
14 void EnableIgnores();
13 void DisableIgnores() {
14 if (UNLIKELY(ignoring_))
15 DisableIgnoresImpl();
16 }
17 void EnableIgnores() {
18 if (UNLIKELY(ignoring_))
19 EnableIgnoresImpl();
20 }
21
1522 private:
1623 ThreadState *const thr_;
17 const uptr pc_;
18 bool in_ignored_lib_;
19 bool ignoring_;
24 bool in_ignored_lib_ = false;
25 bool in_blocking_func_ = false;
26 bool ignoring_ = false;
27
28 void DisableIgnoresImpl();
29 void EnableIgnoresImpl();
30};
31
32struct TsanInterceptorContext {
33 ThreadState *thr;
34 const uptr pc;
2035};
2136
2237LibIgnore *libignore();
2338
2439#if !SANITIZER_GO
2540inline bool in_symbolizer() {
26 cur_thread_init();
27 return UNLIKELY(cur_thread()->in_symbolizer);
41 return UNLIKELY(cur_thread_init()->in_symbolizer);
2842}
2943#endif
3044
45inline bool MustIgnoreInterceptor(ThreadState *thr) {
46 return !thr->is_inited || thr->ignore_interceptors || thr->in_ignored_lib;
47}
48
3149} // namespace __tsan
3250
33#define SCOPED_INTERCEPTOR_RAW(func, ...) \
34 cur_thread_init(); \
35 ThreadState *thr = cur_thread(); \
36 const uptr caller_pc = GET_CALLER_PC(); \
37 ScopedInterceptor si(thr, #func, caller_pc); \
38 const uptr pc = GET_CURRENT_PC(); \
39 (void)pc; \
40 /**/
41
42#define SCOPED_TSAN_INTERCEPTOR(func, ...) \
43 SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \
44 if (REAL(func) == 0) { \
51#define SCOPED_INTERCEPTOR_RAW(func, ...) \
52 ThreadState *thr = cur_thread_init(); \
53 ScopedInterceptor si(thr, #func, GET_CALLER_PC()); \
54 UNUSED const uptr pc = GET_CURRENT_PC();
55
56#ifdef __powerpc64__
57// Debugging of crashes on powerpc after commit:
58// c80604f7a3 ("tsan: remove real func check from interceptors")
59// Somehow replacing if with DCHECK leads to strange failures in:
60// SanitizerCommon-tsan-powerpc64le-Linux :: Linux/ptrace.cpp
61// https://lab.llvm.org/buildbot/#/builders/105
62// https://lab.llvm.org/buildbot/#/builders/121
63// https://lab.llvm.org/buildbot/#/builders/57
64# define CHECK_REAL_FUNC(func) \
65 if (REAL(func) == 0) { \
4566 Report("FATAL: ThreadSanitizer: failed to intercept %s\n", #func); \
46 Die(); \
47 } \
48 if (!thr->is_inited || thr->ignore_interceptors || thr->in_ignored_lib) \
49 return REAL(func)(__VA_ARGS__); \
50/**/
67 Die(); \
68 }
69#else
70# define CHECK_REAL_FUNC(func) DCHECK(REAL(func))
71#endif
72
73#define SCOPED_TSAN_INTERCEPTOR(func, ...) \
74 SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \
75 CHECK_REAL_FUNC(func); \
76 if (MustIgnoreInterceptor(thr)) \
77 return REAL(func)(__VA_ARGS__);
5178
5279#define SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START() \
5380 si.DisableIgnores();
......@@ -57,20 +84,49 @@ inline bool in_symbolizer() {
5784
5885#define TSAN_INTERCEPTOR(ret, func, ...) INTERCEPTOR(ret, func, __VA_ARGS__)
5986
87#if SANITIZER_FREEBSD
88# define TSAN_INTERCEPTOR_FREEBSD_ALIAS(ret, func, ...) \
89 TSAN_INTERCEPTOR(ret, _pthread_##func, __VA_ARGS__) \
90 ALIAS(WRAP(pthread_##func));
91#else
92# define TSAN_INTERCEPTOR_FREEBSD_ALIAS(ret, func, ...)
93#endif
94
6095#if SANITIZER_NETBSD
6196# define TSAN_INTERCEPTOR_NETBSD_ALIAS(ret, func, ...) \
6297 TSAN_INTERCEPTOR(ret, __libc_##func, __VA_ARGS__) \
63 ALIAS(WRAPPER_NAME(pthread_##func));
98 ALIAS(WRAP(pthread_##func));
6499# define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR(ret, func, ...) \
65100 TSAN_INTERCEPTOR(ret, __libc_thr_##func, __VA_ARGS__) \
66 ALIAS(WRAPPER_NAME(pthread_##func));
101 ALIAS(WRAP(pthread_##func));
67102# define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR2(ret, func, func2, ...) \
68103 TSAN_INTERCEPTOR(ret, __libc_thr_##func, __VA_ARGS__) \
69 ALIAS(WRAPPER_NAME(pthread_##func2));
104 ALIAS(WRAP(pthread_##func2));
70105#else
71106# define TSAN_INTERCEPTOR_NETBSD_ALIAS(ret, func, ...)
72107# define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR(ret, func, ...)
73108# define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR2(ret, func, func2, ...)
74109#endif
75110
111#define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name)
112
113#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED \
114 (!cur_thread_init()->is_inited)
115
116#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
117 MemoryAccessRange(((TsanInterceptorContext *)ctx)->thr, \
118 ((TsanInterceptorContext *)ctx)->pc, (uptr)ptr, size, \
119 true)
120
121#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
122 MemoryAccessRange(((TsanInterceptorContext *) ctx)->thr, \
123 ((TsanInterceptorContext *) ctx)->pc, (uptr) ptr, size, \
124 false)
125
126#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
127 SCOPED_TSAN_INTERCEPTOR(func, __VA_ARGS__); \
128 TsanInterceptorContext _ctx = {thr, pc}; \
129 ctx = (void *)&_ctx; \
130 (void)ctx;
131
76132#endif // TSAN_INTERCEPTORS_H
lib/tsan/tsan_interceptors_mac.cpp+6-5
......@@ -12,12 +12,13 @@
1212//===----------------------------------------------------------------------===//
1313
1414#include "sanitizer_common/sanitizer_platform.h"
15#if SANITIZER_MAC
15#if SANITIZER_APPLE
1616
1717#include "interception/interception.h"
1818#include "tsan_interceptors.h"
1919#include "tsan_interface.h"
2020#include "tsan_interface_ann.h"
21#include "tsan_spinlock_defs_mac.h"
2122#include "sanitizer_common/sanitizer_addrhashmap.h"
2223
2324#include <errno.h>
......@@ -365,7 +366,7 @@ static uptr GetOrCreateSyncAddress(uptr addr, ThreadState *thr, uptr pc) {
365366 if (h.created()) {
366367 ThreadIgnoreBegin(thr, pc);
367368 *h = (uptr) user_alloc(thr, pc, /*size=*/1);
368 ThreadIgnoreEnd(thr, pc);
369 ThreadIgnoreEnd(thr);
369370 }
370371 return *h;
371372}
......@@ -405,8 +406,8 @@ TSAN_INTERCEPTOR(int, swapcontext, ucontext_t *oucp, const ucontext_t *ucp) {
405406 {
406407 SCOPED_INTERCEPTOR_RAW(swapcontext, oucp, ucp);
407408 }
408 // Bacause of swapcontext() semantics we have no option but to copy its
409 // impementation here
409 // Because of swapcontext() semantics we have no option but to copy its
410 // implementation here
410411 if (!oucp || !ucp) {
411412 errno = EINVAL;
412413 return -1;
......@@ -518,4 +519,4 @@ STDCXX_INTERCEPTOR(void, _ZNSt3__111__call_onceERVmPvPFvS2_E, void *flag,
518519
519520} // namespace __tsan
520521
521#endif // SANITIZER_MAC
522#endif // SANITIZER_APPLE
lib/tsan/tsan_interceptors_memintrinsics.cpp created+43
......@@ -0,0 +1,43 @@
1//===-- tsan_interceptors_posix.cpp ---------------------------------------===//
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
13#define SANITIZER_COMMON_NO_REDEFINE_BUILTINS
14
15#include "tsan_interceptors.h"
16#include "tsan_interface.h"
17
18using namespace __tsan;
19
20#include "sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc"
21
22extern "C" {
23
24void *__tsan_memcpy(void *dst, const void *src, uptr size) {
25 void *ctx;
26#if PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE
27 COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size);
28#else
29 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
30#endif
31}
32
33void *__tsan_memset(void *dst, int c, uptr size) {
34 void *ctx;
35 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, c, size);
36}
37
38void *__tsan_memmove(void *dst, const void *src, uptr size) {
39 void *ctx;
40 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
41}
42
43} // extern "C"
lib/tsan/tsan_interceptors_posix.cpp+616-440
......@@ -35,7 +35,10 @@
3535
3636using namespace __tsan;
3737
38#if SANITIZER_FREEBSD || SANITIZER_MAC
38DECLARE_REAL(void *, memcpy, void *to, const void *from, SIZE_T size)
39DECLARE_REAL(void *, memset, void *block, int c, SIZE_T size)
40
41#if SANITIZER_FREEBSD || SANITIZER_APPLE
3942#define stdout __stdoutp
4043#define stderr __stderrp
4144#endif
......@@ -76,6 +79,8 @@ struct ucontext_t {
7679#define PTHREAD_ABI_BASE "GLIBC_2.3.2"
7780#elif defined(__aarch64__) || SANITIZER_PPC64V2
7881#define PTHREAD_ABI_BASE "GLIBC_2.17"
82#elif SANITIZER_LOONGARCH64
83#define PTHREAD_ABI_BASE "GLIBC_2.36"
7984#endif
8085
8186extern "C" int pthread_attr_init(void *attr);
......@@ -90,28 +95,26 @@ DECLARE_REAL(int, pthread_mutexattr_gettype, void *, void *)
9095DECLARE_REAL(int, fflush, __sanitizer_FILE *fp)
9196DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr size)
9297DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr)
98extern "C" int pthread_equal(void *t1, void *t2);
9399extern "C" void *pthread_self();
94100extern "C" void _exit(int status);
95101#if !SANITIZER_NETBSD
96102extern "C" int fileno_unlocked(void *stream);
97103extern "C" int dirfd(void *dirp);
98104#endif
99#if SANITIZER_GLIBC
100extern "C" int mallopt(int param, int value);
101#endif
102105#if SANITIZER_NETBSD
103106extern __sanitizer_FILE __sF[];
104107#else
105108extern __sanitizer_FILE *stdout, *stderr;
106109#endif
107#if !SANITIZER_FREEBSD && !SANITIZER_MAC && !SANITIZER_NETBSD
110#if !SANITIZER_FREEBSD && !SANITIZER_APPLE && !SANITIZER_NETBSD
108111const int PTHREAD_MUTEX_RECURSIVE = 1;
109112const int PTHREAD_MUTEX_RECURSIVE_NP = 1;
110113#else
111114const int PTHREAD_MUTEX_RECURSIVE = 2;
112115const int PTHREAD_MUTEX_RECURSIVE_NP = 2;
113116#endif
114#if !SANITIZER_FREEBSD && !SANITIZER_MAC && !SANITIZER_NETBSD
117#if !SANITIZER_FREEBSD && !SANITIZER_APPLE && !SANITIZER_NETBSD
115118const int EPOLL_CTL_ADD = 1;
116119#endif
117120const int SIGILL = 4;
......@@ -121,17 +124,20 @@ const int SIGFPE = 8;
121124const int SIGSEGV = 11;
122125const int SIGPIPE = 13;
123126const int SIGTERM = 15;
124#if defined(__mips__) || SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_NETBSD
127#if defined(__mips__) || SANITIZER_FREEBSD || SANITIZER_APPLE || SANITIZER_NETBSD
125128const int SIGBUS = 10;
126129const int SIGSYS = 12;
127130#else
128131const int SIGBUS = 7;
129132const int SIGSYS = 31;
130133#endif
134#if SANITIZER_HAS_SIGINFO
135const int SI_TIMER = -2;
136#endif
131137void *const MAP_FAILED = (void*)-1;
132138#if SANITIZER_NETBSD
133139const int PTHREAD_BARRIER_SERIAL_THREAD = 1234567;
134#elif !SANITIZER_MAC
140#elif !SANITIZER_APPLE
135141const int PTHREAD_BARRIER_SERIAL_THREAD = -1;
136142#endif
137143const int MAP_FIXED = 0x10;
......@@ -144,7 +150,7 @@ typedef __sanitizer::u16 mode_t;
144150# define F_TLOCK 2 /* Test and lock a region for exclusive use. */
145151# define F_TEST 3 /* Test a region for other processes locks. */
146152
147#if SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_NETBSD
153#if SANITIZER_FREEBSD || SANITIZER_APPLE || SANITIZER_NETBSD
148154const int SA_SIGINFO = 0x40;
149155const int SIG_SETMASK = 3;
150156#elif defined(__mips__)
......@@ -155,32 +161,41 @@ const int SA_SIGINFO = 4;
155161const int SIG_SETMASK = 2;
156162#endif
157163
158#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED \
159 (cur_thread_init(), !cur_thread()->is_inited)
160
161164namespace __tsan {
162165struct SignalDesc {
163166 bool armed;
164 bool sigaction;
165167 __sanitizer_siginfo siginfo;
166168 ucontext_t ctx;
167169};
168170
169171struct ThreadSignalContext {
170172 int int_signal_send;
171 atomic_uintptr_t in_blocking_func;
172 atomic_uintptr_t have_pending_signals;
173173 SignalDesc pending_signals[kSigCount];
174174 // emptyset and oldset are too big for stack.
175175 __sanitizer_sigset_t emptyset;
176176 __sanitizer_sigset_t oldset;
177177};
178178
179void EnterBlockingFunc(ThreadState *thr) {
180 for (;;) {
181 // The order is important to not delay a signal infinitely if it's
182 // delivered right before we set in_blocking_func. Note: we can't call
183 // ProcessPendingSignals when in_blocking_func is set, or we can handle
184 // a signal synchronously when we are already handling a signal.
185 atomic_store(&thr->in_blocking_func, 1, memory_order_relaxed);
186 if (atomic_load(&thr->pending_signals, memory_order_relaxed) == 0)
187 break;
188 atomic_store(&thr->in_blocking_func, 0, memory_order_relaxed);
189 ProcessPendingSignals(thr);
190 }
191}
192
179193// The sole reason tsan wraps atexit callbacks is to establish synchronization
180194// between callback setup and callback execution.
181195struct AtExitCtx {
182196 void (*f)();
183197 void *arg;
198 uptr pc;
184199};
185200
186201// InterceptorContext holds all global data required for interceptors.
......@@ -192,7 +207,7 @@ struct InterceptorContext {
192207 // in a single cache line if possible (it's accessed in every interceptor).
193208 ALIGNED(64) LibIgnore libignore;
194209 __sanitizer_sigaction sigactions[kSigCount];
195#if !SANITIZER_MAC && !SANITIZER_NETBSD
210#if !SANITIZER_APPLE && !SANITIZER_NETBSD
196211 unsigned finalize_key;
197212#endif
198213
......@@ -237,19 +252,37 @@ SANITIZER_WEAK_CXX_DEFAULT_IMPL void OnPotentiallyBlockingRegionEnd() {}
237252} // namespace __tsan
238253
239254static ThreadSignalContext *SigCtx(ThreadState *thr) {
240 ThreadSignalContext *ctx = (ThreadSignalContext*)thr->signal_ctx;
255 // This function may be called reentrantly if it is interrupted by a signal
256 // handler. Use CAS to handle the race.
257 uptr ctx = atomic_load(&thr->signal_ctx, memory_order_relaxed);
241258 if (ctx == 0 && !thr->is_dead) {
242 ctx = (ThreadSignalContext*)MmapOrDie(sizeof(*ctx), "ThreadSignalContext");
243 MemoryResetRange(thr, (uptr)&SigCtx, (uptr)ctx, sizeof(*ctx));
244 thr->signal_ctx = ctx;
259 uptr pctx =
260 (uptr)MmapOrDie(sizeof(ThreadSignalContext), "ThreadSignalContext");
261 MemoryResetRange(thr, (uptr)&SigCtx, pctx, sizeof(ThreadSignalContext));
262 if (atomic_compare_exchange_strong(&thr->signal_ctx, &ctx, pctx,
263 memory_order_relaxed)) {
264 ctx = pctx;
265 } else {
266 UnmapOrDie((ThreadSignalContext *)pctx, sizeof(ThreadSignalContext));
267 }
245268 }
246 return ctx;
269 return (ThreadSignalContext *)ctx;
247270}
248271
249272ScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname,
250273 uptr pc)
251 : thr_(thr), pc_(pc), in_ignored_lib_(false), ignoring_(false) {
252 Initialize(thr);
274 : thr_(thr) {
275 LazyInitialize(thr);
276 if (UNLIKELY(atomic_load(&thr->in_blocking_func, memory_order_relaxed))) {
277 // pthread_join is marked as blocking, but it's also known to call other
278 // intercepted functions (mmap, free). If we don't reset in_blocking_func
279 // we can get deadlocks and memory corruptions if we deliver a synchronous
280 // signal inside of an mmap/free interceptor.
281 // So reset it and restore it back in the destructor.
282 // See https://github.com/google/sanitizers/issues/1540
283 atomic_store(&thr->in_blocking_func, 0, memory_order_relaxed);
284 in_blocking_func_ = true;
285 }
253286 if (!thr_->is_inited) return;
254287 if (!thr_->ignore_interceptors) FuncEntry(thr, pc);
255288 DPrintf("#%d: intercept %s()\n", thr_->tid, fname);
......@@ -262,6 +295,8 @@ ScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname,
262295ScopedInterceptor::~ScopedInterceptor() {
263296 if (!thr_->is_inited) return;
264297 DisableIgnores();
298 if (UNLIKELY(in_blocking_func_))
299 EnterBlockingFunc(thr_);
265300 if (!thr_->ignore_interceptors) {
266301 ProcessPendingSignals(thr_);
267302 FuncExit(thr_);
......@@ -269,43 +304,48 @@ ScopedInterceptor::~ScopedInterceptor() {
269304 }
270305}
271306
272void ScopedInterceptor::EnableIgnores() {
273 if (ignoring_) {
274 ThreadIgnoreBegin(thr_, pc_, /*save_stack=*/false);
275 if (flags()->ignore_noninstrumented_modules) thr_->suppress_reports++;
276 if (in_ignored_lib_) {
277 DCHECK(!thr_->in_ignored_lib);
278 thr_->in_ignored_lib = true;
279 }
307NOINLINE
308void ScopedInterceptor::EnableIgnoresImpl() {
309 ThreadIgnoreBegin(thr_, 0);
310 if (flags()->ignore_noninstrumented_modules)
311 thr_->suppress_reports++;
312 if (in_ignored_lib_) {
313 DCHECK(!thr_->in_ignored_lib);
314 thr_->in_ignored_lib = true;
280315 }
281316}
282317
283void ScopedInterceptor::DisableIgnores() {
284 if (ignoring_) {
285 ThreadIgnoreEnd(thr_, pc_);
286 if (flags()->ignore_noninstrumented_modules) thr_->suppress_reports--;
287 if (in_ignored_lib_) {
288 DCHECK(thr_->in_ignored_lib);
289 thr_->in_ignored_lib = false;
290 }
318NOINLINE
319void ScopedInterceptor::DisableIgnoresImpl() {
320 ThreadIgnoreEnd(thr_);
321 if (flags()->ignore_noninstrumented_modules)
322 thr_->suppress_reports--;
323 if (in_ignored_lib_) {
324 DCHECK(thr_->in_ignored_lib);
325 thr_->in_ignored_lib = false;
291326 }
292327}
293328
294329#define TSAN_INTERCEPT(func) INTERCEPT_FUNCTION(func)
330#if SANITIZER_FREEBSD || SANITIZER_NETBSD
331# define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION(func)
332#else
333# define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION_VER(func, ver)
334#endif
295335#if SANITIZER_FREEBSD
296# define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION(func)
297# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(func)
298# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS_THR(func)
299#elif SANITIZER_NETBSD
300# define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION(func)
301# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(func) \
302 INTERCEPT_FUNCTION(__libc_##func)
303# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS_THR(func) \
304 INTERCEPT_FUNCTION(__libc_thr_##func)
336# define TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(func) \
337 INTERCEPT_FUNCTION(_pthread_##func)
305338#else
306# define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION_VER(func, ver)
307# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(func)
308# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS_THR(func)
339# define TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(func)
340#endif
341#if SANITIZER_NETBSD
342# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(func) \
343 INTERCEPT_FUNCTION(__libc_##func)
344# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS_THR(func) \
345 INTERCEPT_FUNCTION(__libc_thr_##func)
346#else
347# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(func)
348# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS_THR(func)
309349#endif
310350
311351#define READ_STRING_OF_LEN(thr, pc, s, len, n) \
......@@ -319,15 +359,8 @@ void ScopedInterceptor::DisableIgnores() {
319359
320360struct BlockingCall {
321361 explicit BlockingCall(ThreadState *thr)
322 : thr(thr)
323 , ctx(SigCtx(thr)) {
324 for (;;) {
325 atomic_store(&ctx->in_blocking_func, 1, memory_order_relaxed);
326 if (atomic_load(&ctx->have_pending_signals, memory_order_relaxed) == 0)
327 break;
328 atomic_store(&ctx->in_blocking_func, 0, memory_order_relaxed);
329 ProcessPendingSignals(thr);
330 }
362 : thr(thr) {
363 EnterBlockingFunc(thr);
331364 // When we are in a "blocking call", we process signals asynchronously
332365 // (right when they arrive). In this context we do not expect to be
333366 // executing any user/runtime code. The known interceptor sequence when
......@@ -338,11 +371,10 @@ struct BlockingCall {
338371
339372 ~BlockingCall() {
340373 thr->ignore_interceptors--;
341 atomic_store(&ctx->in_blocking_func, 0, memory_order_relaxed);
374 atomic_store(&thr->in_blocking_func, 0, memory_order_relaxed);
342375 }
343376
344377 ThreadState *thr;
345 ThreadSignalContext *ctx;
346378};
347379
348380TSAN_INTERCEPTOR(unsigned, sleep, unsigned sec) {
......@@ -371,7 +403,10 @@ TSAN_INTERCEPTOR(int, pause, int fake) {
371403 return BLOCK_REAL(pause)(fake);
372404}
373405
374static void at_exit_wrapper() {
406// Note: we specifically call the function in such strange way
407// with "installed_at" because in reports it will appear between
408// callback frames and the frame that installed the callback.
409static void at_exit_callback_installed_at() {
375410 AtExitCtx *ctx;
376411 {
377412 // Ensure thread-safety.
......@@ -383,16 +418,22 @@ static void at_exit_wrapper() {
383418 interceptor_ctx()->AtExitStack.PopBack();
384419 }
385420
386 Acquire(cur_thread(), (uptr)0, (uptr)ctx);
421 ThreadState *thr = cur_thread();
422 Acquire(thr, ctx->pc, (uptr)ctx);
423 FuncEntry(thr, ctx->pc);
387424 ((void(*)())ctx->f)();
388 InternalFree(ctx);
425 FuncExit(thr);
426 Free(ctx);
389427}
390428
391static void cxa_at_exit_wrapper(void *arg) {
392 Acquire(cur_thread(), 0, (uptr)arg);
429static void cxa_at_exit_callback_installed_at(void *arg) {
430 ThreadState *thr = cur_thread();
393431 AtExitCtx *ctx = (AtExitCtx*)arg;
432 Acquire(thr, ctx->pc, (uptr)arg);
433 FuncEntry(thr, ctx->pc);
394434 ((void(*)(void *arg))ctx->f)(ctx->arg);
395 InternalFree(ctx);
435 FuncExit(thr);
436 Free(ctx);
396437}
397438
398439static int setup_at_exit_wrapper(ThreadState *thr, uptr pc, void(*f)(),
......@@ -405,7 +446,7 @@ TSAN_INTERCEPTOR(int, atexit, void (*f)()) {
405446 // We want to setup the atexit callback even if we are in ignored lib
406447 // or after fork.
407448 SCOPED_INTERCEPTOR_RAW(atexit, f);
408 return setup_at_exit_wrapper(thr, pc, (void(*)())f, 0, 0);
449 return setup_at_exit_wrapper(thr, GET_CALLER_PC(), (void (*)())f, 0, 0);
409450}
410451#endif
411452
......@@ -413,14 +454,15 @@ TSAN_INTERCEPTOR(int, __cxa_atexit, void (*f)(void *a), void *arg, void *dso) {
413454 if (in_symbolizer())
414455 return 0;
415456 SCOPED_TSAN_INTERCEPTOR(__cxa_atexit, f, arg, dso);
416 return setup_at_exit_wrapper(thr, pc, (void(*)())f, arg, dso);
457 return setup_at_exit_wrapper(thr, GET_CALLER_PC(), (void (*)())f, arg, dso);
417458}
418459
419460static int setup_at_exit_wrapper(ThreadState *thr, uptr pc, void(*f)(),
420461 void *arg, void *dso) {
421 AtExitCtx *ctx = (AtExitCtx*)InternalAlloc(sizeof(AtExitCtx));
462 auto *ctx = New<AtExitCtx>();
422463 ctx->f = f;
423464 ctx->arg = arg;
465 ctx->pc = pc;
424466 Release(thr, pc, (uptr)ctx);
425467 // Memory allocation in __cxa_atexit will race with free during exit,
426468 // because we do not see synchronization around atexit callback list.
......@@ -436,41 +478,44 @@ static int setup_at_exit_wrapper(ThreadState *thr, uptr pc, void(*f)(),
436478 // due to atexit_mu held on exit from the calloc interceptor.
437479 ScopedIgnoreInterceptors ignore;
438480
439 res = REAL(__cxa_atexit)((void (*)(void *a))at_exit_wrapper, 0, 0);
481 res = REAL(__cxa_atexit)((void (*)(void *a))at_exit_callback_installed_at,
482 0, 0);
440483 // Push AtExitCtx on the top of the stack of callback functions
441484 if (!res) {
442485 interceptor_ctx()->AtExitStack.PushBack(ctx);
443486 }
444487 } else {
445 res = REAL(__cxa_atexit)(cxa_at_exit_wrapper, ctx, dso);
488 res = REAL(__cxa_atexit)(cxa_at_exit_callback_installed_at, ctx, dso);
446489 }
447 ThreadIgnoreEnd(thr, pc);
490 ThreadIgnoreEnd(thr);
448491 return res;
449492}
450493
451#if !SANITIZER_MAC && !SANITIZER_NETBSD
452static void on_exit_wrapper(int status, void *arg) {
494#if !SANITIZER_APPLE && !SANITIZER_NETBSD
495static void on_exit_callback_installed_at(int status, void *arg) {
453496 ThreadState *thr = cur_thread();
454 uptr pc = 0;
455 Acquire(thr, pc, (uptr)arg);
456497 AtExitCtx *ctx = (AtExitCtx*)arg;
498 Acquire(thr, ctx->pc, (uptr)arg);
499 FuncEntry(thr, ctx->pc);
457500 ((void(*)(int status, void *arg))ctx->f)(status, ctx->arg);
458 InternalFree(ctx);
501 FuncExit(thr);
502 Free(ctx);
459503}
460504
461505TSAN_INTERCEPTOR(int, on_exit, void(*f)(int, void*), void *arg) {
462506 if (in_symbolizer())
463507 return 0;
464508 SCOPED_TSAN_INTERCEPTOR(on_exit, f, arg);
465 AtExitCtx *ctx = (AtExitCtx*)InternalAlloc(sizeof(AtExitCtx));
509 auto *ctx = New<AtExitCtx>();
466510 ctx->f = (void(*)())f;
467511 ctx->arg = arg;
512 ctx->pc = GET_CALLER_PC();
468513 Release(thr, pc, (uptr)ctx);
469514 // Memory allocation in __cxa_atexit will race with free during exit,
470515 // because we do not see synchronization around atexit callback list.
471516 ThreadIgnoreBegin(thr, pc);
472 int res = REAL(on_exit)(on_exit_wrapper, ctx);
473 ThreadIgnoreEnd(thr, pc);
517 int res = REAL(on_exit)(on_exit_callback_installed_at, ctx);
518 ThreadIgnoreEnd(thr);
474519 return res;
475520}
476521#define TSAN_MAYBE_INTERCEPT_ON_EXIT TSAN_INTERCEPT(on_exit)
......@@ -502,9 +547,7 @@ static void SetJmp(ThreadState *thr, uptr sp) {
502547 buf->shadow_stack_pos = thr->shadow_stack_pos;
503548 ThreadSignalContext *sctx = SigCtx(thr);
504549 buf->int_signal_send = sctx ? sctx->int_signal_send : 0;
505 buf->in_blocking_func = sctx ?
506 atomic_load(&sctx->in_blocking_func, memory_order_relaxed) :
507 false;
550 buf->in_blocking_func = atomic_load(&thr->in_blocking_func, memory_order_relaxed);
508551 buf->in_signal_handler = atomic_load(&thr->in_signal_handler,
509552 memory_order_relaxed);
510553}
......@@ -520,11 +563,10 @@ static void LongJmp(ThreadState *thr, uptr *env) {
520563 while (thr->shadow_stack_pos > buf->shadow_stack_pos)
521564 FuncExit(thr);
522565 ThreadSignalContext *sctx = SigCtx(thr);
523 if (sctx) {
566 if (sctx)
524567 sctx->int_signal_send = buf->int_signal_send;
525 atomic_store(&sctx->in_blocking_func, buf->in_blocking_func,
526 memory_order_relaxed);
527 }
568 atomic_store(&thr->in_blocking_func, buf->in_blocking_func,
569 memory_order_relaxed);
528570 atomic_store(&thr->in_signal_handler, buf->in_signal_handler,
529571 memory_order_relaxed);
530572 JmpBufGarbageCollect(thr, buf->sp - 1); // do not collect buf->sp
......@@ -536,16 +578,13 @@ static void LongJmp(ThreadState *thr, uptr *env) {
536578}
537579
538580// FIXME: put everything below into a common extern "C" block?
539extern "C" void __tsan_setjmp(uptr sp) {
540 cur_thread_init();
541 SetJmp(cur_thread(), sp);
542}
581extern "C" void __tsan_setjmp(uptr sp) { SetJmp(cur_thread_init(), sp); }
543582
544#if SANITIZER_MAC
583#if SANITIZER_APPLE
545584TSAN_INTERCEPTOR(int, setjmp, void *env);
546585TSAN_INTERCEPTOR(int, _setjmp, void *env);
547586TSAN_INTERCEPTOR(int, sigsetjmp, void *env);
548#else // SANITIZER_MAC
587#else // SANITIZER_APPLE
549588
550589#if SANITIZER_NETBSD
551590#define setjmp_symname __setjmp14
......@@ -555,59 +594,28 @@ TSAN_INTERCEPTOR(int, sigsetjmp, void *env);
555594#define sigsetjmp_symname sigsetjmp
556595#endif
557596
558#define TSAN_INTERCEPTOR_SETJMP_(x) __interceptor_ ## x
559#define TSAN_INTERCEPTOR_SETJMP__(x) TSAN_INTERCEPTOR_SETJMP_(x)
560#define TSAN_INTERCEPTOR_SETJMP TSAN_INTERCEPTOR_SETJMP__(setjmp_symname)
561#define TSAN_INTERCEPTOR_SIGSETJMP TSAN_INTERCEPTOR_SETJMP__(sigsetjmp_symname)
562
563#define TSAN_STRING_SETJMP SANITIZER_STRINGIFY(setjmp_symname)
564#define TSAN_STRING_SIGSETJMP SANITIZER_STRINGIFY(sigsetjmp_symname)
565
566// Not called. Merely to satisfy TSAN_INTERCEPT().
567extern "C" SANITIZER_INTERFACE_ATTRIBUTE
568int TSAN_INTERCEPTOR_SETJMP(void *env);
569extern "C" int TSAN_INTERCEPTOR_SETJMP(void *env) {
570 CHECK(0);
571 return 0;
572}
573
574// FIXME: any reason to have a separate declaration?
575extern "C" SANITIZER_INTERFACE_ATTRIBUTE
576int __interceptor__setjmp(void *env);
577extern "C" int __interceptor__setjmp(void *env) {
578 CHECK(0);
579 return 0;
580}
581
582extern "C" SANITIZER_INTERFACE_ATTRIBUTE
583int TSAN_INTERCEPTOR_SIGSETJMP(void *env);
584extern "C" int TSAN_INTERCEPTOR_SIGSETJMP(void *env) {
585 CHECK(0);
586 return 0;
587}
588
589#if !SANITIZER_NETBSD
590extern "C" SANITIZER_INTERFACE_ATTRIBUTE
591int __interceptor___sigsetjmp(void *env);
592extern "C" int __interceptor___sigsetjmp(void *env) {
593 CHECK(0);
594 return 0;
595}
596#endif
597
598extern "C" int setjmp_symname(void *env);
599extern "C" int _setjmp(void *env);
600extern "C" int sigsetjmp_symname(void *env);
601#if !SANITIZER_NETBSD
602extern "C" int __sigsetjmp(void *env);
603#endif
604597DEFINE_REAL(int, setjmp_symname, void *env)
605598DEFINE_REAL(int, _setjmp, void *env)
606599DEFINE_REAL(int, sigsetjmp_symname, void *env)
607600#if !SANITIZER_NETBSD
608601DEFINE_REAL(int, __sigsetjmp, void *env)
609602#endif
610#endif // SANITIZER_MAC
603
604// The real interceptor for setjmp is special, and implemented in pure asm. We
605// just need to initialize the REAL functions so that they can be used in asm.
606static void InitializeSetjmpInterceptors() {
607 // We can not use TSAN_INTERCEPT to get setjmp addr, because it does &setjmp and
608 // setjmp is not present in some versions of libc.
609 using __interception::InterceptFunction;
610 InterceptFunction(SANITIZER_STRINGIFY(setjmp_symname), (uptr*)&REAL(setjmp_symname), 0, 0);
611 InterceptFunction("_setjmp", (uptr*)&REAL(_setjmp), 0, 0);
612 InterceptFunction(SANITIZER_STRINGIFY(sigsetjmp_symname), (uptr*)&REAL(sigsetjmp_symname), 0,
613 0);
614#if !SANITIZER_NETBSD
615 InterceptFunction("__sigsetjmp", (uptr*)&REAL(__sigsetjmp), 0, 0);
616#endif
617}
618#endif // SANITIZER_APPLE
611619
612620#if SANITIZER_NETBSD
613621#define longjmp_symname __longjmp14
......@@ -646,7 +654,7 @@ TSAN_INTERCEPTOR(void, _longjmp, uptr *env, int val) {
646654}
647655#endif
648656
649#if !SANITIZER_MAC
657#if !SANITIZER_APPLE
650658TSAN_INTERCEPTOR(void*, malloc, uptr size) {
651659 if (in_symbolizer())
652660 return InternalAlloc(size);
......@@ -787,10 +795,11 @@ static void *mmap_interceptor(ThreadState *thr, uptr pc, Mmap real_mmap,
787795 return res;
788796}
789797
790TSAN_INTERCEPTOR(int, munmap, void *addr, long_t sz) {
791 SCOPED_TSAN_INTERCEPTOR(munmap, addr, sz);
798template <class Munmap>
799static int munmap_interceptor(ThreadState *thr, uptr pc, Munmap real_munmap,
800 void *addr, SIZE_T sz) {
792801 UnmapShadow(thr, (uptr)addr, sz);
793 int res = REAL(munmap)(addr, sz);
802 int res = real_munmap(addr, sz);
794803 return res;
795804}
796805
......@@ -804,7 +813,7 @@ TSAN_INTERCEPTOR(void*, memalign, uptr align, uptr sz) {
804813#define TSAN_MAYBE_INTERCEPT_MEMALIGN
805814#endif
806815
807#if !SANITIZER_MAC
816#if !SANITIZER_APPLE
808817TSAN_INTERCEPTOR(void*, aligned_alloc, uptr align, uptr sz) {
809818 if (in_symbolizer())
810819 return InternalAlloc(sz, nullptr, align);
......@@ -835,7 +844,7 @@ TSAN_INTERCEPTOR(void*, pvalloc, uptr sz) {
835844#define TSAN_MAYBE_INTERCEPT_PVALLOC
836845#endif
837846
838#if !SANITIZER_MAC
847#if !SANITIZER_APPLE
839848TSAN_INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr sz) {
840849 if (in_symbolizer()) {
841850 void *p = InternalAlloc(sz, nullptr, align);
......@@ -849,6 +858,54 @@ TSAN_INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr sz) {
849858}
850859#endif
851860
861// Both __cxa_guard_acquire and pthread_once 0-initialize
862// the object initially. pthread_once does not have any
863// other ABI requirements. __cxa_guard_acquire assumes
864// that any non-0 value in the first byte means that
865// initialization is completed. Contents of the remaining
866// bytes are up to us.
867constexpr u32 kGuardInit = 0;
868constexpr u32 kGuardDone = 1;
869constexpr u32 kGuardRunning = 1 << 16;
870constexpr u32 kGuardWaiter = 1 << 17;
871
872static int guard_acquire(ThreadState *thr, uptr pc, atomic_uint32_t *g,
873 bool blocking_hooks = true) {
874 if (blocking_hooks)
875 OnPotentiallyBlockingRegionBegin();
876 auto on_exit = at_scope_exit([blocking_hooks] {
877 if (blocking_hooks)
878 OnPotentiallyBlockingRegionEnd();
879 });
880
881 for (;;) {
882 u32 cmp = atomic_load(g, memory_order_acquire);
883 if (cmp == kGuardInit) {
884 if (atomic_compare_exchange_strong(g, &cmp, kGuardRunning,
885 memory_order_relaxed))
886 return 1;
887 } else if (cmp == kGuardDone) {
888 if (!thr->in_ignored_lib)
889 Acquire(thr, pc, (uptr)g);
890 return 0;
891 } else {
892 if ((cmp & kGuardWaiter) ||
893 atomic_compare_exchange_strong(g, &cmp, cmp | kGuardWaiter,
894 memory_order_relaxed))
895 FutexWait(g, cmp | kGuardWaiter);
896 }
897 }
898}
899
900static void guard_release(ThreadState *thr, uptr pc, atomic_uint32_t *g,
901 u32 v) {
902 if (!thr->in_ignored_lib)
903 Release(thr, pc, (uptr)g);
904 u32 old = atomic_exchange(g, v, memory_order_release);
905 if (old & kGuardWaiter)
906 FutexWake(g, 1 << 30);
907}
908
852909// __cxa_guard_acquire and friends need to be intercepted in a special way -
853910// regular interceptors will break statically-linked libstdc++. Linux
854911// interceptors are especially defined as weak functions (so that they don't
......@@ -859,7 +916,7 @@ TSAN_INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr sz) {
859916// these interceptors with INTERFACE_ATTRIBUTE.
860917// On OS X, we don't support statically linking, so we just use a regular
861918// interceptor.
862#if SANITIZER_MAC
919#if SANITIZER_APPLE
863920#define STDCXX_INTERCEPTOR TSAN_INTERCEPTOR
864921#else
865922#define STDCXX_INTERCEPTOR(rettype, name, ...) \
......@@ -869,31 +926,17 @@ TSAN_INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr sz) {
869926// Used in thread-safe function static initialization.
870927STDCXX_INTERCEPTOR(int, __cxa_guard_acquire, atomic_uint32_t *g) {
871928 SCOPED_INTERCEPTOR_RAW(__cxa_guard_acquire, g);
872 OnPotentiallyBlockingRegionBegin();
873 auto on_exit = at_scope_exit(&OnPotentiallyBlockingRegionEnd);
874 for (;;) {
875 u32 cmp = atomic_load(g, memory_order_acquire);
876 if (cmp == 0) {
877 if (atomic_compare_exchange_strong(g, &cmp, 1<<16, memory_order_relaxed))
878 return 1;
879 } else if (cmp == 1) {
880 Acquire(thr, pc, (uptr)g);
881 return 0;
882 } else {
883 internal_sched_yield();
884 }
885 }
929 return guard_acquire(thr, pc, g);
886930}
887931
888932STDCXX_INTERCEPTOR(void, __cxa_guard_release, atomic_uint32_t *g) {
889933 SCOPED_INTERCEPTOR_RAW(__cxa_guard_release, g);
890 Release(thr, pc, (uptr)g);
891 atomic_store(g, 1, memory_order_release);
934 guard_release(thr, pc, g, kGuardDone);
892935}
893936
894937STDCXX_INTERCEPTOR(void, __cxa_guard_abort, atomic_uint32_t *g) {
895938 SCOPED_INTERCEPTOR_RAW(__cxa_guard_abort, g);
896 atomic_store(g, 0, memory_order_relaxed);
939 guard_release(thr, pc, g, kGuardInit);
897940}
898941
899942namespace __tsan {
......@@ -908,15 +951,16 @@ void DestroyThreadState() {
908951}
909952
910953void PlatformCleanUpThreadState(ThreadState *thr) {
911 ThreadSignalContext *sctx = thr->signal_ctx;
954 ThreadSignalContext *sctx = (ThreadSignalContext *)atomic_load(
955 &thr->signal_ctx, memory_order_relaxed);
912956 if (sctx) {
913 thr->signal_ctx = 0;
957 atomic_store(&thr->signal_ctx, 0, memory_order_relaxed);
914958 UnmapOrDie(sctx, sizeof(*sctx));
915959 }
916960}
917961} // namespace __tsan
918962
919#if !SANITIZER_MAC && !SANITIZER_NETBSD && !SANITIZER_FREEBSD
963#if !SANITIZER_APPLE && !SANITIZER_NETBSD && !SANITIZER_FREEBSD
920964static void thread_finalize(void *v) {
921965 uptr iter = (uptr)v;
922966 if (iter > 1) {
......@@ -935,34 +979,33 @@ static void thread_finalize(void *v) {
935979struct ThreadParam {
936980 void* (*callback)(void *arg);
937981 void *param;
938 atomic_uintptr_t tid;
982 Tid tid;
983 Semaphore created;
984 Semaphore started;
939985};
940986
941987extern "C" void *__tsan_thread_start_func(void *arg) {
942988 ThreadParam *p = (ThreadParam*)arg;
943989 void* (*callback)(void *arg) = p->callback;
944990 void *param = p->param;
945 int tid = 0;
946991 {
947 cur_thread_init();
948 ThreadState *thr = cur_thread();
992 ThreadState *thr = cur_thread_init();
949993 // Thread-local state is not initialized yet.
950994 ScopedIgnoreInterceptors ignore;
951#if !SANITIZER_MAC && !SANITIZER_NETBSD && !SANITIZER_FREEBSD
995#if !SANITIZER_APPLE && !SANITIZER_NETBSD && !SANITIZER_FREEBSD
952996 ThreadIgnoreBegin(thr, 0);
953997 if (pthread_setspecific(interceptor_ctx()->finalize_key,
954998 (void *)GetPthreadDestructorIterations())) {
955999 Printf("ThreadSanitizer: failed to set thread key\n");
9561000 Die();
9571001 }
958 ThreadIgnoreEnd(thr, 0);
1002 ThreadIgnoreEnd(thr);
9591003#endif
960 while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0)
961 internal_sched_yield();
1004 p->created.Wait();
9621005 Processor *proc = ProcCreate();
9631006 ProcWire(proc, thr);
964 ThreadStart(thr, tid, GetTid(), ThreadType::Regular);
965 atomic_store(&p->tid, 0, memory_order_release);
1007 ThreadStart(thr, p->tid, GetTid(), ThreadType::Regular);
1008 p->started.Post();
9661009 }
9671010 void *res = callback(param);
9681011 // Prevent the callback from being tail called,
......@@ -984,9 +1027,11 @@ TSAN_INTERCEPTOR(int, pthread_create,
9841027 "fork is not supported. Dying (set die_after_fork=0 to override)\n");
9851028 Die();
9861029 } else {
987 VPrintf(1, "ThreadSanitizer: starting new threads after multi-threaded "
988 "fork is not supported (pid %d). Continuing because of "
989 "die_after_fork=0, but you are on your own\n", internal_getpid());
1030 VPrintf(1,
1031 "ThreadSanitizer: starting new threads after multi-threaded "
1032 "fork is not supported (pid %lu). Continuing because of "
1033 "die_after_fork=0, but you are on your own\n",
1034 internal_getpid());
9901035 }
9911036 }
9921037 __sanitizer_pthread_attr_t myattr;
......@@ -1001,18 +1046,18 @@ TSAN_INTERCEPTOR(int, pthread_create,
10011046 ThreadParam p;
10021047 p.callback = callback;
10031048 p.param = param;
1004 atomic_store(&p.tid, 0, memory_order_relaxed);
1049 p.tid = kMainTid;
10051050 int res = -1;
10061051 {
10071052 // Otherwise we see false positives in pthread stack manipulation.
10081053 ScopedIgnoreInterceptors ignore;
10091054 ThreadIgnoreBegin(thr, pc);
10101055 res = REAL(pthread_create)(th, attr, __tsan_thread_start_func, &p);
1011 ThreadIgnoreEnd(thr, pc);
1056 ThreadIgnoreEnd(thr);
10121057 }
10131058 if (res == 0) {
1014 int tid = ThreadCreate(thr, pc, *(uptr*)th, IsStateDetached(detached));
1015 CHECK_NE(tid, 0);
1059 p.tid = ThreadCreate(thr, pc, *(uptr *)th, IsStateDetached(detached));
1060 CHECK_NE(p.tid, kMainTid);
10161061 // Synchronization on p.tid serves two purposes:
10171062 // 1. ThreadCreate must finish before the new thread starts.
10181063 // Otherwise the new thread can call pthread_detach, but the pthread_t
......@@ -1020,9 +1065,8 @@ TSAN_INTERCEPTOR(int, pthread_create,
10201065 // 2. ThreadStart must finish before this thread continues.
10211066 // Otherwise, this thread can call pthread_detach and reset thr->sync
10221067 // before the new thread got a chance to acquire from it in ThreadStart.
1023 atomic_store(&p.tid, tid, memory_order_release);
1024 while (atomic_load(&p.tid, memory_order_acquire) != 0)
1025 internal_sched_yield();
1068 p.created.Post();
1069 p.started.Wait();
10261070 }
10271071 if (attr == &myattr)
10281072 pthread_attr_destroy(&myattr);
......@@ -1031,10 +1075,10 @@ TSAN_INTERCEPTOR(int, pthread_create,
10311075
10321076TSAN_INTERCEPTOR(int, pthread_join, void *th, void **ret) {
10331077 SCOPED_INTERCEPTOR_RAW(pthread_join, th, ret);
1034 int tid = ThreadConsumeTid(thr, pc, (uptr)th);
1078 Tid tid = ThreadConsumeTid(thr, pc, (uptr)th);
10351079 ThreadIgnoreBegin(thr, pc);
10361080 int res = BLOCK_REAL(pthread_join)(th, ret);
1037 ThreadIgnoreEnd(thr, pc);
1081 ThreadIgnoreEnd(thr);
10381082 if (res == 0) {
10391083 ThreadJoin(thr, pc, tid);
10401084 }
......@@ -1045,7 +1089,7 @@ DEFINE_REAL_PTHREAD_FUNCTIONS
10451089
10461090TSAN_INTERCEPTOR(int, pthread_detach, void *th) {
10471091 SCOPED_INTERCEPTOR_RAW(pthread_detach, th);
1048 int tid = ThreadConsumeTid(thr, pc, (uptr)th);
1092 Tid tid = ThreadConsumeTid(thr, pc, (uptr)th);
10491093 int res = REAL(pthread_detach)(th);
10501094 if (res == 0) {
10511095 ThreadDetach(thr, pc, tid);
......@@ -1056,7 +1100,7 @@ TSAN_INTERCEPTOR(int, pthread_detach, void *th) {
10561100TSAN_INTERCEPTOR(void, pthread_exit, void *retval) {
10571101 {
10581102 SCOPED_INTERCEPTOR_RAW(pthread_exit, retval);
1059#if !SANITIZER_MAC && !SANITIZER_ANDROID
1103#if !SANITIZER_APPLE && !SANITIZER_ANDROID
10601104 CHECK_EQ(thr, &cur_thread_placeholder);
10611105#endif
10621106 }
......@@ -1066,10 +1110,10 @@ TSAN_INTERCEPTOR(void, pthread_exit, void *retval) {
10661110#if SANITIZER_LINUX
10671111TSAN_INTERCEPTOR(int, pthread_tryjoin_np, void *th, void **ret) {
10681112 SCOPED_INTERCEPTOR_RAW(pthread_tryjoin_np, th, ret);
1069 int tid = ThreadConsumeTid(thr, pc, (uptr)th);
1113 Tid tid = ThreadConsumeTid(thr, pc, (uptr)th);
10701114 ThreadIgnoreBegin(thr, pc);
10711115 int res = REAL(pthread_tryjoin_np)(th, ret);
1072 ThreadIgnoreEnd(thr, pc);
1116 ThreadIgnoreEnd(thr);
10731117 if (res == 0)
10741118 ThreadJoin(thr, pc, tid);
10751119 else
......@@ -1080,10 +1124,10 @@ TSAN_INTERCEPTOR(int, pthread_tryjoin_np, void *th, void **ret) {
10801124TSAN_INTERCEPTOR(int, pthread_timedjoin_np, void *th, void **ret,
10811125 const struct timespec *abstime) {
10821126 SCOPED_INTERCEPTOR_RAW(pthread_timedjoin_np, th, ret, abstime);
1083 int tid = ThreadConsumeTid(thr, pc, (uptr)th);
1127 Tid tid = ThreadConsumeTid(thr, pc, (uptr)th);
10841128 ThreadIgnoreBegin(thr, pc);
10851129 int res = BLOCK_REAL(pthread_timedjoin_np)(th, ret, abstime);
1086 ThreadIgnoreEnd(thr, pc);
1130 ThreadIgnoreEnd(thr);
10871131 if (res == 0)
10881132 ThreadJoin(thr, pc, tid);
10891133 else
......@@ -1152,9 +1196,8 @@ void CondMutexUnlockCtx<Fn>::Unlock() const {
11521196 // tsan code. Also ScopedInterceptor and BlockingCall destructors won't run
11531197 // since the thread is cancelled, so we have to manually execute them
11541198 // (the thread still can run some user code due to pthread_cleanup_push).
1155 ThreadSignalContext *ctx = SigCtx(thr);
1156 CHECK_EQ(atomic_load(&ctx->in_blocking_func, memory_order_relaxed), 1);
1157 atomic_store(&ctx->in_blocking_func, 0, memory_order_relaxed);
1199 CHECK_EQ(atomic_load(&thr->in_blocking_func, memory_order_relaxed), 1);
1200 atomic_store(&thr->in_blocking_func, 0, memory_order_relaxed);
11581201 MutexPostLock(thr, pc, (uptr)m, MutexFlagDoPreLockOnPostLock);
11591202 // Undo BlockingCall ctor effects.
11601203 thr->ignore_interceptors--;
......@@ -1225,7 +1268,7 @@ INTERCEPTOR(int, pthread_cond_clockwait, void *c, void *m,
12251268#define TSAN_MAYBE_PTHREAD_COND_CLOCKWAIT
12261269#endif
12271270
1228#if SANITIZER_MAC
1271#if SANITIZER_APPLE
12291272INTERCEPTOR(int, pthread_cond_timedwait_relative_np, void *c, void *m,
12301273 void *reltime) {
12311274 void *cond = init_cond(c);
......@@ -1292,6 +1335,19 @@ TSAN_INTERCEPTOR(int, pthread_mutex_destroy, void *m) {
12921335 return res;
12931336}
12941337
1338TSAN_INTERCEPTOR(int, pthread_mutex_lock, void *m) {
1339 SCOPED_TSAN_INTERCEPTOR(pthread_mutex_lock, m);
1340 MutexPreLock(thr, pc, (uptr)m);
1341 int res = REAL(pthread_mutex_lock)(m);
1342 if (res == errno_EOWNERDEAD)
1343 MutexRepair(thr, pc, (uptr)m);
1344 if (res == 0 || res == errno_EOWNERDEAD)
1345 MutexPostLock(thr, pc, (uptr)m);
1346 if (res == errno_EINVAL)
1347 MutexInvalidAccess(thr, pc, (uptr)m);
1348 return res;
1349}
1350
12951351TSAN_INTERCEPTOR(int, pthread_mutex_trylock, void *m) {
12961352 SCOPED_TSAN_INTERCEPTOR(pthread_mutex_trylock, m);
12971353 int res = REAL(pthread_mutex_trylock)(m);
......@@ -1302,7 +1358,7 @@ TSAN_INTERCEPTOR(int, pthread_mutex_trylock, void *m) {
13021358 return res;
13031359}
13041360
1305#if !SANITIZER_MAC
1361#if !SANITIZER_APPLE
13061362TSAN_INTERCEPTOR(int, pthread_mutex_timedlock, void *m, void *abstime) {
13071363 SCOPED_TSAN_INTERCEPTOR(pthread_mutex_timedlock, m, abstime);
13081364 int res = REAL(pthread_mutex_timedlock)(m, abstime);
......@@ -1313,7 +1369,44 @@ TSAN_INTERCEPTOR(int, pthread_mutex_timedlock, void *m, void *abstime) {
13131369}
13141370#endif
13151371
1316#if !SANITIZER_MAC
1372TSAN_INTERCEPTOR(int, pthread_mutex_unlock, void *m) {
1373 SCOPED_TSAN_INTERCEPTOR(pthread_mutex_unlock, m);
1374 MutexUnlock(thr, pc, (uptr)m);
1375 int res = REAL(pthread_mutex_unlock)(m);
1376 if (res == errno_EINVAL)
1377 MutexInvalidAccess(thr, pc, (uptr)m);
1378 return res;
1379}
1380
1381#if SANITIZER_GLIBC
1382# if !__GLIBC_PREREQ(2, 34)
1383// glibc 2.34 applies a non-default version for the two functions. They are no
1384// longer expected to be intercepted by programs.
1385TSAN_INTERCEPTOR(int, __pthread_mutex_lock, void *m) {
1386 SCOPED_TSAN_INTERCEPTOR(__pthread_mutex_lock, m);
1387 MutexPreLock(thr, pc, (uptr)m);
1388 int res = REAL(__pthread_mutex_lock)(m);
1389 if (res == errno_EOWNERDEAD)
1390 MutexRepair(thr, pc, (uptr)m);
1391 if (res == 0 || res == errno_EOWNERDEAD)
1392 MutexPostLock(thr, pc, (uptr)m);
1393 if (res == errno_EINVAL)
1394 MutexInvalidAccess(thr, pc, (uptr)m);
1395 return res;
1396}
1397
1398TSAN_INTERCEPTOR(int, __pthread_mutex_unlock, void *m) {
1399 SCOPED_TSAN_INTERCEPTOR(__pthread_mutex_unlock, m);
1400 MutexUnlock(thr, pc, (uptr)m);
1401 int res = REAL(__pthread_mutex_unlock)(m);
1402 if (res == errno_EINVAL)
1403 MutexInvalidAccess(thr, pc, (uptr)m);
1404 return res;
1405}
1406# endif
1407#endif
1408
1409#if !SANITIZER_APPLE
13171410TSAN_INTERCEPTOR(int, pthread_spin_init, void *m, int pshared) {
13181411 SCOPED_TSAN_INTERCEPTOR(pthread_spin_init, m, pshared);
13191412 int res = REAL(pthread_spin_init)(m, pshared);
......@@ -1396,7 +1489,7 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_tryrdlock, void *m) {
13961489 return res;
13971490}
13981491
1399#if !SANITIZER_MAC
1492#if !SANITIZER_APPLE
14001493TSAN_INTERCEPTOR(int, pthread_rwlock_timedrdlock, void *m, void *abstime) {
14011494 SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedrdlock, m, abstime);
14021495 int res = REAL(pthread_rwlock_timedrdlock)(m, abstime);
......@@ -1426,7 +1519,7 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_trywrlock, void *m) {
14261519 return res;
14271520}
14281521
1429#if !SANITIZER_MAC
1522#if !SANITIZER_APPLE
14301523TSAN_INTERCEPTOR(int, pthread_rwlock_timedwrlock, void *m, void *abstime) {
14311524 SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedwrlock, m, abstime);
14321525 int res = REAL(pthread_rwlock_timedwrlock)(m, abstime);
......@@ -1444,17 +1537,17 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_unlock, void *m) {
14441537 return res;
14451538}
14461539
1447#if !SANITIZER_MAC
1540#if !SANITIZER_APPLE
14481541TSAN_INTERCEPTOR(int, pthread_barrier_init, void *b, void *a, unsigned count) {
14491542 SCOPED_TSAN_INTERCEPTOR(pthread_barrier_init, b, a, count);
1450 MemoryWrite(thr, pc, (uptr)b, kSizeLog1);
1543 MemoryAccess(thr, pc, (uptr)b, 1, kAccessWrite);
14511544 int res = REAL(pthread_barrier_init)(b, a, count);
14521545 return res;
14531546}
14541547
14551548TSAN_INTERCEPTOR(int, pthread_barrier_destroy, void *b) {
14561549 SCOPED_TSAN_INTERCEPTOR(pthread_barrier_destroy, b);
1457 MemoryWrite(thr, pc, (uptr)b, kSizeLog1);
1550 MemoryAccess(thr, pc, (uptr)b, 1, kAccessWrite);
14581551 int res = REAL(pthread_barrier_destroy)(b);
14591552 return res;
14601553}
......@@ -1462,9 +1555,9 @@ TSAN_INTERCEPTOR(int, pthread_barrier_destroy, void *b) {
14621555TSAN_INTERCEPTOR(int, pthread_barrier_wait, void *b) {
14631556 SCOPED_TSAN_INTERCEPTOR(pthread_barrier_wait, b);
14641557 Release(thr, pc, (uptr)b);
1465 MemoryRead(thr, pc, (uptr)b, kSizeLog1);
1558 MemoryAccess(thr, pc, (uptr)b, 1, kAccessRead);
14661559 int res = REAL(pthread_barrier_wait)(b);
1467 MemoryRead(thr, pc, (uptr)b, kSizeLog1);
1560 MemoryAccess(thr, pc, (uptr)b, 1, kAccessRead);
14681561 if (res == 0 || res == PTHREAD_BARRIER_SERIAL_THREAD) {
14691562 Acquire(thr, pc, (uptr)b);
14701563 }
......@@ -1478,7 +1571,7 @@ TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) {
14781571 return errno_EINVAL;
14791572 atomic_uint32_t *a;
14801573
1481 if (SANITIZER_MAC)
1574 if (SANITIZER_APPLE)
14821575 a = static_cast<atomic_uint32_t*>((void *)((char *)o + sizeof(long_t)));
14831576 else if (SANITIZER_NETBSD)
14841577 a = static_cast<atomic_uint32_t*>
......@@ -1486,25 +1579,16 @@ TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) {
14861579 else
14871580 a = static_cast<atomic_uint32_t*>(o);
14881581
1489 u32 v = atomic_load(a, memory_order_acquire);
1490 if (v == 0 && atomic_compare_exchange_strong(a, &v, 1,
1491 memory_order_relaxed)) {
1582 // Mac OS X appears to use pthread_once() where calling BlockingRegion hooks
1583 // result in crashes due to too little stack space.
1584 if (guard_acquire(thr, pc, a, !SANITIZER_APPLE)) {
14921585 (*f)();
1493 if (!thr->in_ignored_lib)
1494 Release(thr, pc, (uptr)o);
1495 atomic_store(a, 2, memory_order_release);
1496 } else {
1497 while (v != 2) {
1498 internal_sched_yield();
1499 v = atomic_load(a, memory_order_acquire);
1500 }
1501 if (!thr->in_ignored_lib)
1502 Acquire(thr, pc, (uptr)o);
1586 guard_release(thr, pc, a, kGuardDone);
15031587 }
15041588 return 0;
15051589}
15061590
1507#if SANITIZER_LINUX && !SANITIZER_ANDROID
1591#if SANITIZER_GLIBC
15081592TSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) {
15091593 SCOPED_TSAN_INTERCEPTOR(__fxstat, version, fd, buf);
15101594 if (fd > 0)
......@@ -1517,20 +1601,20 @@ TSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) {
15171601#endif
15181602
15191603TSAN_INTERCEPTOR(int, fstat, int fd, void *buf) {
1520#if SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_ANDROID || SANITIZER_NETBSD
1521 SCOPED_TSAN_INTERCEPTOR(fstat, fd, buf);
1604#if SANITIZER_GLIBC
1605 SCOPED_TSAN_INTERCEPTOR(__fxstat, 0, fd, buf);
15221606 if (fd > 0)
15231607 FdAccess(thr, pc, fd);
1524 return REAL(fstat)(fd, buf);
1608 return REAL(__fxstat)(0, fd, buf);
15251609#else
1526 SCOPED_TSAN_INTERCEPTOR(__fxstat, 0, fd, buf);
1610 SCOPED_TSAN_INTERCEPTOR(fstat, fd, buf);
15271611 if (fd > 0)
15281612 FdAccess(thr, pc, fd);
1529 return REAL(__fxstat)(0, fd, buf);
1613 return REAL(fstat)(fd, buf);
15301614#endif
15311615}
15321616
1533#if SANITIZER_LINUX && !SANITIZER_ANDROID
1617#if SANITIZER_GLIBC
15341618TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) {
15351619 SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf);
15361620 if (fd > 0)
......@@ -1542,7 +1626,7 @@ TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) {
15421626#define TSAN_MAYBE_INTERCEPT___FXSTAT64
15431627#endif
15441628
1545#if SANITIZER_LINUX && !SANITIZER_ANDROID
1629#if SANITIZER_GLIBC
15461630TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) {
15471631 SCOPED_TSAN_INTERCEPTOR(__fxstat64, 0, fd, buf);
15481632 if (fd > 0)
......@@ -1624,7 +1708,7 @@ TSAN_INTERCEPTOR(int, dup2, int oldfd, int newfd) {
16241708 return newfd2;
16251709}
16261710
1627#if !SANITIZER_MAC
1711#if !SANITIZER_APPLE
16281712TSAN_INTERCEPTOR(int, dup3, int oldfd, int newfd, int flags) {
16291713 SCOPED_TSAN_INTERCEPTOR(dup3, oldfd, newfd, flags);
16301714 int newfd2 = REAL(dup3)(oldfd, newfd, flags);
......@@ -1649,11 +1733,10 @@ TSAN_INTERCEPTOR(int, eventfd, unsigned initval, int flags) {
16491733
16501734#if SANITIZER_LINUX
16511735TSAN_INTERCEPTOR(int, signalfd, int fd, void *mask, int flags) {
1652 SCOPED_TSAN_INTERCEPTOR(signalfd, fd, mask, flags);
1653 if (fd >= 0)
1654 FdClose(thr, pc, fd);
1736 SCOPED_INTERCEPTOR_RAW(signalfd, fd, mask, flags);
1737 FdClose(thr, pc, fd);
16551738 fd = REAL(signalfd)(fd, mask, flags);
1656 if (fd >= 0)
1739 if (!MustIgnoreInterceptor(thr))
16571740 FdSignalCreate(thr, pc, fd);
16581741 return fd;
16591742}
......@@ -1730,17 +1813,16 @@ TSAN_INTERCEPTOR(int, listen, int fd, int backlog) {
17301813}
17311814
17321815TSAN_INTERCEPTOR(int, close, int fd) {
1733 SCOPED_TSAN_INTERCEPTOR(close, fd);
1734 if (fd >= 0)
1816 SCOPED_INTERCEPTOR_RAW(close, fd);
1817 if (!in_symbolizer())
17351818 FdClose(thr, pc, fd);
17361819 return REAL(close)(fd);
17371820}
17381821
17391822#if SANITIZER_LINUX
17401823TSAN_INTERCEPTOR(int, __close, int fd) {
1741 SCOPED_TSAN_INTERCEPTOR(__close, fd);
1742 if (fd >= 0)
1743 FdClose(thr, pc, fd);
1824 SCOPED_INTERCEPTOR_RAW(__close, fd);
1825 FdClose(thr, pc, fd);
17441826 return REAL(__close)(fd);
17451827}
17461828#define TSAN_MAYBE_INTERCEPT___CLOSE TSAN_INTERCEPT(__close)
......@@ -1751,13 +1833,10 @@ TSAN_INTERCEPTOR(int, __close, int fd) {
17511833// glibc guts
17521834#if SANITIZER_LINUX && !SANITIZER_ANDROID
17531835TSAN_INTERCEPTOR(void, __res_iclose, void *state, bool free_addr) {
1754 SCOPED_TSAN_INTERCEPTOR(__res_iclose, state, free_addr);
1836 SCOPED_INTERCEPTOR_RAW(__res_iclose, state, free_addr);
17551837 int fds[64];
17561838 int cnt = ExtractResolvFDs(state, fds, ARRAY_SIZE(fds));
1757 for (int i = 0; i < cnt; i++) {
1758 if (fds[i] > 0)
1759 FdClose(thr, pc, fds[i]);
1760 }
1839 for (int i = 0; i < cnt; i++) FdClose(thr, pc, fds[i]);
17611840 REAL(__res_iclose)(state, free_addr);
17621841}
17631842#define TSAN_MAYBE_INTERCEPT___RES_ICLOSE TSAN_INTERCEPT(__res_iclose)
......@@ -1773,7 +1852,7 @@ TSAN_INTERCEPTOR(int, pipe, int *pipefd) {
17731852 return res;
17741853}
17751854
1776#if !SANITIZER_MAC
1855#if !SANITIZER_APPLE
17771856TSAN_INTERCEPTOR(int, pipe2, int *pipefd, int flags) {
17781857 SCOPED_TSAN_INTERCEPTOR(pipe2, pipefd, flags);
17791858 int res = REAL(pipe2)(pipefd, flags);
......@@ -1838,7 +1917,7 @@ TSAN_INTERCEPTOR(int, rmdir, char *path) {
18381917}
18391918
18401919TSAN_INTERCEPTOR(int, closedir, void *dirp) {
1841 SCOPED_TSAN_INTERCEPTOR(closedir, dirp);
1920 SCOPED_INTERCEPTOR_RAW(closedir, dirp);
18421921 if (dirp) {
18431922 int fd = dirfd(dirp);
18441923 FdClose(thr, pc, fd);
......@@ -1869,8 +1948,10 @@ TSAN_INTERCEPTOR(int, epoll_ctl, int epfd, int op, int fd, void *ev) {
18691948 FdAccess(thr, pc, epfd);
18701949 if (epfd >= 0 && fd >= 0)
18711950 FdAccess(thr, pc, fd);
1872 if (op == EPOLL_CTL_ADD && epfd >= 0)
1951 if (op == EPOLL_CTL_ADD && epfd >= 0) {
1952 FdPollAdd(thr, pc, epfd, fd);
18731953 FdRelease(thr, pc, epfd);
1954 }
18741955 int res = REAL(epoll_ctl)(epfd, op, fd, ev);
18751956 return res;
18761957}
......@@ -1896,12 +1977,34 @@ TSAN_INTERCEPTOR(int, epoll_pwait, int epfd, void *ev, int cnt, int timeout,
18961977 return res;
18971978}
18981979
1899#define TSAN_MAYBE_INTERCEPT_EPOLL \
1900 TSAN_INTERCEPT(epoll_create); \
1901 TSAN_INTERCEPT(epoll_create1); \
1902 TSAN_INTERCEPT(epoll_ctl); \
1903 TSAN_INTERCEPT(epoll_wait); \
1904 TSAN_INTERCEPT(epoll_pwait)
1980TSAN_INTERCEPTOR(int, epoll_pwait2, int epfd, void *ev, int cnt, void *timeout,
1981 void *sigmask) {
1982 SCOPED_INTERCEPTOR_RAW(epoll_pwait2, epfd, ev, cnt, timeout, sigmask);
1983 // This function is new and may not be present in libc and/or kernel.
1984 // Since we effectively add it to libc (as will be probed by the program
1985 // using dlsym or a weak function pointer) we need to handle the case
1986 // when it's not present in the actual libc.
1987 if (!REAL(epoll_pwait2)) {
1988 errno = errno_ENOSYS;
1989 return -1;
1990 }
1991 if (MustIgnoreInterceptor(thr))
1992 REAL(epoll_pwait2)(epfd, ev, cnt, timeout, sigmask);
1993 if (epfd >= 0)
1994 FdAccess(thr, pc, epfd);
1995 int res = BLOCK_REAL(epoll_pwait2)(epfd, ev, cnt, timeout, sigmask);
1996 if (res > 0 && epfd >= 0)
1997 FdAcquire(thr, pc, epfd);
1998 return res;
1999}
2000
2001# define TSAN_MAYBE_INTERCEPT_EPOLL \
2002 TSAN_INTERCEPT(epoll_create); \
2003 TSAN_INTERCEPT(epoll_create1); \
2004 TSAN_INTERCEPT(epoll_ctl); \
2005 TSAN_INTERCEPT(epoll_wait); \
2006 TSAN_INTERCEPT(epoll_pwait); \
2007 TSAN_INTERCEPT(epoll_pwait2)
19052008#else
19062009#define TSAN_MAYBE_INTERCEPT_EPOLL
19072010#endif
......@@ -1933,24 +2036,47 @@ TSAN_INTERCEPTOR(int, pthread_sigmask, int how, const __sanitizer_sigset_t *set,
19332036
19342037namespace __tsan {
19352038
2039static void ReportErrnoSpoiling(ThreadState *thr, uptr pc, int sig) {
2040 VarSizeStackTrace stack;
2041 // StackTrace::GetNestInstructionPc(pc) is used because return address is
2042 // expected, OutputReport() will undo this.
2043 ObtainCurrentStack(thr, StackTrace::GetNextInstructionPc(pc), &stack);
2044 ThreadRegistryLock l(&ctx->thread_registry);
2045 ScopedReport rep(ReportTypeErrnoInSignal);
2046 rep.SetSigNum(sig);
2047 if (!IsFiredSuppression(ctx, ReportTypeErrnoInSignal, stack)) {
2048 rep.AddStack(stack, true);
2049 OutputReport(thr, rep);
2050 }
2051}
2052
19362053static void CallUserSignalHandler(ThreadState *thr, bool sync, bool acquire,
1937 bool sigact, int sig,
1938 __sanitizer_siginfo *info, void *uctx) {
2054 int sig, __sanitizer_siginfo *info,
2055 void *uctx) {
2056 CHECK(thr->slot);
19392057 __sanitizer_sigaction *sigactions = interceptor_ctx()->sigactions;
19402058 if (acquire)
19412059 Acquire(thr, 0, (uptr)&sigactions[sig]);
19422060 // Signals are generally asynchronous, so if we receive a signals when
19432061 // ignores are enabled we should disable ignores. This is critical for sync
1944 // and interceptors, because otherwise we can miss syncronization and report
2062 // and interceptors, because otherwise we can miss synchronization and report
19452063 // false races.
19462064 int ignore_reads_and_writes = thr->ignore_reads_and_writes;
19472065 int ignore_interceptors = thr->ignore_interceptors;
19482066 int ignore_sync = thr->ignore_sync;
2067 // For symbolizer we only process SIGSEGVs synchronously
2068 // (bug in symbolizer or in tsan). But we want to reset
2069 // in_symbolizer to fail gracefully. Symbolizer and user code
2070 // use different memory allocators, so if we don't reset
2071 // in_symbolizer we can get memory allocated with one being
2072 // feed with another, which can cause more crashes.
2073 int in_symbolizer = thr->in_symbolizer;
19492074 if (!ctx->after_multithreaded_fork) {
19502075 thr->ignore_reads_and_writes = 0;
19512076 thr->fast_state.ClearIgnoreBit();
19522077 thr->ignore_interceptors = 0;
19532078 thr->ignore_sync = 0;
2079 thr->in_symbolizer = 0;
19542080 }
19552081 // Ensure that the handler does not spoil errno.
19562082 const int saved_errno = errno;
......@@ -1958,13 +2084,14 @@ static void CallUserSignalHandler(ThreadState *thr, bool sync, bool acquire,
19582084 // This code races with sigaction. Be careful to not read sa_sigaction twice.
19592085 // Also need to remember pc for reporting before the call,
19602086 // because the handler can reset it.
1961 volatile uptr pc =
1962 sigact ? (uptr)sigactions[sig].sigaction : (uptr)sigactions[sig].handler;
2087 volatile uptr pc = (sigactions[sig].sa_flags & SA_SIGINFO)
2088 ? (uptr)sigactions[sig].sigaction
2089 : (uptr)sigactions[sig].handler;
19632090 if (pc != sig_dfl && pc != sig_ign) {
1964 if (sigact)
1965 ((__sanitizer_sigactionhandler_ptr)pc)(sig, info, uctx);
1966 else
1967 ((__sanitizer_sighandler_ptr)pc)(sig);
2091 // The callback can be either sa_handler or sa_sigaction.
2092 // They have different signatures, but we assume that passing
2093 // additional arguments to sa_handler works and is harmless.
2094 ((__sanitizer_sigactionhandler_ptr)pc)(sig, info, uctx);
19682095 }
19692096 if (!ctx->after_multithreaded_fork) {
19702097 thr->ignore_reads_and_writes = ignore_reads_and_writes;
......@@ -1972,6 +2099,7 @@ static void CallUserSignalHandler(ThreadState *thr, bool sync, bool acquire,
19722099 thr->fast_state.SetIgnoreBit();
19732100 thr->ignore_interceptors = ignore_interceptors;
19742101 thr->ignore_sync = ignore_sync;
2102 thr->in_symbolizer = in_symbolizer;
19752103 }
19762104 // We do not detect errno spoiling for SIGTERM,
19772105 // because some SIGTERM handlers do spoil errno but reraise SIGTERM,
......@@ -1981,27 +2109,16 @@ static void CallUserSignalHandler(ThreadState *thr, bool sync, bool acquire,
19812109 // from rtl_generic_sighandler) we have not yet received the reraised
19822110 // signal; and it looks too fragile to intercept all ways to reraise a signal.
19832111 if (ShouldReport(thr, ReportTypeErrnoInSignal) && !sync && sig != SIGTERM &&
1984 errno != 99) {
1985 VarSizeStackTrace stack;
1986 // StackTrace::GetNestInstructionPc(pc) is used because return address is
1987 // expected, OutputReport() will undo this.
1988 ObtainCurrentStack(thr, StackTrace::GetNextInstructionPc(pc), &stack);
1989 ThreadRegistryLock l(ctx->thread_registry);
1990 ScopedReport rep(ReportTypeErrnoInSignal);
1991 if (!IsFiredSuppression(ctx, ReportTypeErrnoInSignal, stack)) {
1992 rep.AddStack(stack, true);
1993 OutputReport(thr, rep);
1994 }
1995 }
2112 errno != 99)
2113 ReportErrnoSpoiling(thr, pc, sig);
19962114 errno = saved_errno;
19972115}
19982116
1999void ProcessPendingSignals(ThreadState *thr) {
2117void ProcessPendingSignalsImpl(ThreadState *thr) {
2118 atomic_store(&thr->pending_signals, 0, memory_order_relaxed);
20002119 ThreadSignalContext *sctx = SigCtx(thr);
2001 if (sctx == 0 ||
2002 atomic_load(&sctx->have_pending_signals, memory_order_relaxed) == 0)
2120 if (sctx == 0)
20032121 return;
2004 atomic_store(&sctx->have_pending_signals, 0, memory_order_relaxed);
20052122 atomic_fetch_add(&thr->in_signal_handler, 1, memory_order_relaxed);
20062123 internal_sigfillset(&sctx->emptyset);
20072124 int res = REAL(pthread_sigmask)(SIG_SETMASK, &sctx->emptyset, &sctx->oldset);
......@@ -2010,8 +2127,8 @@ void ProcessPendingSignals(ThreadState *thr) {
20102127 SignalDesc *signal = &sctx->pending_signals[sig];
20112128 if (signal->armed) {
20122129 signal->armed = false;
2013 CallUserSignalHandler(thr, false, true, signal->sigaction, sig,
2014 &signal->siginfo, &signal->ctx);
2130 CallUserSignalHandler(thr, false, true, sig, &signal->siginfo,
2131 &signal->ctx);
20152132 }
20162133 }
20172134 res = REAL(pthread_sigmask)(SIG_SETMASK, &sctx->oldset, 0);
......@@ -2021,35 +2138,40 @@ void ProcessPendingSignals(ThreadState *thr) {
20212138
20222139} // namespace __tsan
20232140
2024static bool is_sync_signal(ThreadSignalContext *sctx, int sig) {
2141static bool is_sync_signal(ThreadSignalContext *sctx, int sig,
2142 __sanitizer_siginfo *info) {
2143 // If we are sending signal to ourselves, we must process it now.
2144 if (sctx && sig == sctx->int_signal_send)
2145 return true;
2146#if SANITIZER_HAS_SIGINFO
2147 // POSIX timers can be configured to send any kind of signal; however, it
2148 // doesn't make any sense to consider a timer signal as synchronous!
2149 if (info->si_code == SI_TIMER)
2150 return false;
2151#endif
20252152 return sig == SIGSEGV || sig == SIGBUS || sig == SIGILL || sig == SIGTRAP ||
2026 sig == SIGABRT || sig == SIGFPE || sig == SIGPIPE || sig == SIGSYS ||
2027 // If we are sending signal to ourselves, we must process it now.
2028 (sctx && sig == sctx->int_signal_send);
2153 sig == SIGABRT || sig == SIGFPE || sig == SIGPIPE || sig == SIGSYS;
20292154}
20302155
2031void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig,
2032 __sanitizer_siginfo *info,
2033 void *ctx) {
2034 cur_thread_init();
2035 ThreadState *thr = cur_thread();
2156void sighandler(int sig, __sanitizer_siginfo *info, void *ctx) {
2157 ThreadState *thr = cur_thread_init();
20362158 ThreadSignalContext *sctx = SigCtx(thr);
20372159 if (sig < 0 || sig >= kSigCount) {
20382160 VPrintf(1, "ThreadSanitizer: ignoring signal %d\n", sig);
20392161 return;
20402162 }
20412163 // Don't mess with synchronous signals.
2042 const bool sync = is_sync_signal(sctx, sig);
2164 const bool sync = is_sync_signal(sctx, sig, info);
20432165 if (sync ||
20442166 // If we are in blocking function, we can safely process it now
20452167 // (but check if we are in a recursive interceptor,
20462168 // i.e. pthread_join()->munmap()).
2047 (sctx && atomic_load(&sctx->in_blocking_func, memory_order_relaxed))) {
2169 atomic_load(&thr->in_blocking_func, memory_order_relaxed)) {
20482170 atomic_fetch_add(&thr->in_signal_handler, 1, memory_order_relaxed);
2049 if (sctx && atomic_load(&sctx->in_blocking_func, memory_order_relaxed)) {
2050 atomic_store(&sctx->in_blocking_func, 0, memory_order_relaxed);
2051 CallUserSignalHandler(thr, sync, true, sigact, sig, info, ctx);
2052 atomic_store(&sctx->in_blocking_func, 1, memory_order_relaxed);
2171 if (atomic_load(&thr->in_blocking_func, memory_order_relaxed)) {
2172 atomic_store(&thr->in_blocking_func, 0, memory_order_relaxed);
2173 CallUserSignalHandler(thr, sync, true, sig, info, ctx);
2174 atomic_store(&thr->in_blocking_func, 1, memory_order_relaxed);
20532175 } else {
20542176 // Be very conservative with when we do acquire in this case.
20552177 // It's unsafe to do acquire in async handlers, because ThreadState
......@@ -2057,7 +2179,7 @@ void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig,
20572179 // SIGSYS looks relatively safe -- it's synchronous and can actually
20582180 // need some global state.
20592181 bool acq = (sig == SIGSYS);
2060 CallUserSignalHandler(thr, sync, acq, sigact, sig, info, ctx);
2182 CallUserSignalHandler(thr, sync, acq, sig, info, ctx);
20612183 }
20622184 atomic_fetch_add(&thr->in_signal_handler, -1, memory_order_relaxed);
20632185 return;
......@@ -2068,23 +2190,12 @@ void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig,
20682190 SignalDesc *signal = &sctx->pending_signals[sig];
20692191 if (signal->armed == false) {
20702192 signal->armed = true;
2071 signal->sigaction = sigact;
2072 if (info)
2073 internal_memcpy(&signal->siginfo, info, sizeof(*info));
2074 if (ctx)
2075 internal_memcpy(&signal->ctx, ctx, sizeof(signal->ctx));
2076 atomic_store(&sctx->have_pending_signals, 1, memory_order_relaxed);
2193 internal_memcpy(&signal->siginfo, info, sizeof(*info));
2194 internal_memcpy(&signal->ctx, ctx, sizeof(signal->ctx));
2195 atomic_store(&thr->pending_signals, 1, memory_order_relaxed);
20772196 }
20782197}
20792198
2080static void rtl_sighandler(int sig) {
2081 rtl_generic_sighandler(false, sig, 0, 0);
2082}
2083
2084static void rtl_sigaction(int sig, __sanitizer_siginfo *info, void *ctx) {
2085 rtl_generic_sighandler(true, sig, info, ctx);
2086}
2087
20882199TSAN_INTERCEPTOR(int, raise, int sig) {
20892200 SCOPED_TSAN_INTERCEPTOR(raise, sig);
20902201 ThreadSignalContext *sctx = SigCtx(thr);
......@@ -2118,11 +2229,11 @@ TSAN_INTERCEPTOR(int, pthread_kill, void *tid, int sig) {
21182229 ThreadSignalContext *sctx = SigCtx(thr);
21192230 CHECK_NE(sctx, 0);
21202231 int prev = sctx->int_signal_send;
2121 if (tid == pthread_self()) {
2232 bool self = pthread_equal(tid, pthread_self());
2233 if (self)
21222234 sctx->int_signal_send = sig;
2123 }
21242235 int res = REAL(pthread_kill)(tid, sig);
2125 if (tid == pthread_self()) {
2236 if (self) {
21262237 CHECK_EQ(sctx->int_signal_send, sig);
21272238 sctx->int_signal_send = prev;
21282239 }
......@@ -2143,7 +2254,7 @@ TSAN_INTERCEPTOR(int, getaddrinfo, void *node, void *service,
21432254 // inside of getaddrinfo. So ignore memory accesses.
21442255 ThreadIgnoreBegin(thr, pc);
21452256 int res = REAL(getaddrinfo)(node, service, hints, rv);
2146 ThreadIgnoreEnd(thr, pc);
2257 ThreadIgnoreEnd(thr);
21472258 return res;
21482259}
21492260
......@@ -2175,10 +2286,11 @@ void atfork_child() {
21752286 return;
21762287 ThreadState *thr = cur_thread();
21772288 const uptr pc = StackTrace::GetCurrentPc();
2178 ForkChildAfter(thr, pc);
2289 ForkChildAfter(thr, pc, true);
21792290 FdOnFork(thr, pc);
21802291}
21812292
2293#if !SANITIZER_IOS
21822294TSAN_INTERCEPTOR(int, vfork, int fake) {
21832295 // Some programs (e.g. openjdk) call close for all file descriptors
21842296 // in the child process. Under tsan it leads to false positives, because
......@@ -2195,8 +2307,40 @@ TSAN_INTERCEPTOR(int, vfork, int fake) {
21952307 // Instead we simply turn vfork into fork.
21962308 return WRAP(fork)(fake);
21972309}
2310#endif
2311
2312#if SANITIZER_LINUX
2313TSAN_INTERCEPTOR(int, clone, int (*fn)(void *), void *stack, int flags,
2314 void *arg, int *parent_tid, void *tls, pid_t *child_tid) {
2315 SCOPED_INTERCEPTOR_RAW(clone, fn, stack, flags, arg, parent_tid, tls,
2316 child_tid);
2317 struct Arg {
2318 int (*fn)(void *);
2319 void *arg;
2320 };
2321 auto wrapper = +[](void *p) -> int {
2322 auto *thr = cur_thread();
2323 uptr pc = GET_CURRENT_PC();
2324 // Start the background thread for fork, but not for clone.
2325 // For fork we did this always and it's known to work (or user code has
2326 // adopted). But if we do this for the new clone interceptor some code
2327 // (sandbox2) fails. So model we used to do for years and don't start the
2328 // background thread after clone.
2329 ForkChildAfter(thr, pc, false);
2330 FdOnFork(thr, pc);
2331 auto *arg = static_cast<Arg *>(p);
2332 return arg->fn(arg->arg);
2333 };
2334 ForkBefore(thr, pc);
2335 Arg arg_wrapper = {fn, arg};
2336 int pid = REAL(clone)(wrapper, stack, flags, &arg_wrapper, parent_tid, tls,
2337 child_tid);
2338 ForkParentAfter(thr, pc);
2339 return pid;
2340}
2341#endif
21982342
2199#if !SANITIZER_MAC && !SANITIZER_ANDROID
2343#if !SANITIZER_APPLE && !SANITIZER_ANDROID
22002344typedef int (*dl_iterate_phdr_cb_t)(__sanitizer_dl_phdr_info *info, SIZE_T size,
22012345 void *data);
22022346struct dl_iterate_phdr_data {
......@@ -2207,7 +2351,7 @@ struct dl_iterate_phdr_data {
22072351};
22082352
22092353static bool IsAppNotRodata(uptr addr) {
2210 return IsAppMem(addr) && *(u64*)MemToShadow(addr) != kShadowRodata;
2354 return IsAppMem(addr) && *MemToShadow(addr) != Shadow::kRodata;
22112355}
22122356
22132357static int dl_iterate_phdr_cb(__sanitizer_dl_phdr_info *info, SIZE_T size,
......@@ -2248,13 +2392,7 @@ static int OnExit(ThreadState *thr) {
22482392 return status;
22492393}
22502394
2251struct TsanInterceptorContext {
2252 ThreadState *thr;
2253 const uptr caller_pc;
2254 const uptr pc;
2255};
2256
2257#if !SANITIZER_MAC
2395#if !SANITIZER_APPLE
22582396static void HandleRecvmsg(ThreadState *thr, uptr pc,
22592397 __sanitizer_msghdr *msg) {
22602398 int fds[64];
......@@ -2275,33 +2413,16 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc,
22752413#define SANITIZER_INTERCEPT_TLS_GET_OFFSET 1
22762414#undef SANITIZER_INTERCEPT_PTHREAD_SIGMASK
22772415
2278#define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name)
22792416#define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
22802417 INTERCEPT_FUNCTION_VER(name, ver)
22812418#define COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(name, ver) \
22822419 (INTERCEPT_FUNCTION_VER(name, ver) || INTERCEPT_FUNCTION(name))
22832420
2284#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
2285 MemoryAccessRange(((TsanInterceptorContext *)ctx)->thr, \
2286 ((TsanInterceptorContext *)ctx)->pc, (uptr)ptr, size, \
2287 true)
2288
2289#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
2290 MemoryAccessRange(((TsanInterceptorContext *) ctx)->thr, \
2291 ((TsanInterceptorContext *) ctx)->pc, (uptr) ptr, size, \
2292 false)
2293
2294#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
2295 SCOPED_TSAN_INTERCEPTOR(func, __VA_ARGS__); \
2296 TsanInterceptorContext _ctx = {thr, caller_pc, pc}; \
2297 ctx = (void *)&_ctx; \
2298 (void) ctx;
2299
23002421#define COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, func, ...) \
23012422 SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \
2302 TsanInterceptorContext _ctx = {thr, caller_pc, pc}; \
2423 TsanInterceptorContext _ctx = {thr, pc}; \
23032424 ctx = (void *)&_ctx; \
2304 (void) ctx;
2425 (void)ctx;
23052426
23062427#define COMMON_INTERCEPTOR_FILE_OPEN(ctx, file, path) \
23072428 if (path) \
......@@ -2314,14 +2435,33 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc,
23142435#define COMMON_INTERCEPTOR_FILE_CLOSE(ctx, file) \
23152436 if (file) { \
23162437 int fd = fileno_unlocked(file); \
2317 if (fd >= 0) FdClose(thr, pc, fd); \
2318 }
2319
2438 FdClose(thr, pc, fd); \
2439 }
2440
2441#define COMMON_INTERCEPTOR_DLOPEN(filename, flag) \
2442 ({ \
2443 CheckNoDeepBind(filename, flag); \
2444 ThreadIgnoreBegin(thr, 0); \
2445 void *res = REAL(dlopen)(filename, flag); \
2446 ThreadIgnoreEnd(thr); \
2447 res; \
2448 })
2449
2450// Ignore interceptors in OnLibraryLoaded()/Unloaded(). These hooks use code
2451// (ListOfModules::init, MemoryMappingLayout::DumpListOfModules) that make
2452// intercepted calls, which can cause deadlockes with ReportRace() which also
2453// uses this code.
23202454#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \
2321 libignore()->OnLibraryLoaded(filename)
2455 ({ \
2456 ScopedIgnoreInterceptors ignore_interceptors; \
2457 libignore()->OnLibraryLoaded(filename); \
2458 })
23222459
2323#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() \
2324 libignore()->OnLibraryUnloaded()
2460#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() \
2461 ({ \
2462 ScopedIgnoreInterceptors ignore_interceptors; \
2463 libignore()->OnLibraryUnloaded(); \
2464 })
23252465
23262466#define COMMON_INTERCEPTOR_ACQUIRE(ctx, u) \
23272467 Acquire(((TsanInterceptorContext *) ctx)->thr, pc, u)
......@@ -2347,34 +2487,17 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc,
23472487#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
23482488 ThreadSetName(((TsanInterceptorContext *) ctx)->thr, name)
23492489
2350#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
2351 __tsan::ctx->thread_registry->SetThreadNameByUserId(thread, name)
2490#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
2491 if (pthread_equal(pthread_self(), reinterpret_cast<void *>(thread))) \
2492 COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name); \
2493 else \
2494 __tsan::ctx->thread_registry.SetThreadNameByUserId(thread, name)
23522495
23532496#define COMMON_INTERCEPTOR_BLOCK_REAL(name) BLOCK_REAL(name)
23542497
23552498#define COMMON_INTERCEPTOR_ON_EXIT(ctx) \
23562499 OnExit(((TsanInterceptorContext *) ctx)->thr)
23572500
2358#define COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m) \
2359 MutexPreLock(((TsanInterceptorContext *)ctx)->thr, \
2360 ((TsanInterceptorContext *)ctx)->pc, (uptr)m)
2361
2362#define COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m) \
2363 MutexPostLock(((TsanInterceptorContext *)ctx)->thr, \
2364 ((TsanInterceptorContext *)ctx)->pc, (uptr)m)
2365
2366#define COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m) \
2367 MutexUnlock(((TsanInterceptorContext *)ctx)->thr, \
2368 ((TsanInterceptorContext *)ctx)->pc, (uptr)m)
2369
2370#define COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m) \
2371 MutexRepair(((TsanInterceptorContext *)ctx)->thr, \
2372 ((TsanInterceptorContext *)ctx)->pc, (uptr)m)
2373
2374#define COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m) \
2375 MutexInvalidAccess(((TsanInterceptorContext *)ctx)->thr, \
2376 ((TsanInterceptorContext *)ctx)->pc, (uptr)m)
2377
23782501#define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, sz, prot, flags, fd, \
23792502 off) \
23802503 do { \
......@@ -2382,7 +2505,12 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc,
23822505 off); \
23832506 } while (false)
23842507
2385#if !SANITIZER_MAC
2508#define COMMON_INTERCEPTOR_MUNMAP_IMPL(ctx, addr, sz) \
2509 do { \
2510 return munmap_interceptor(thr, pc, REAL(munmap), addr, sz); \
2511 } while (false)
2512
2513#if !SANITIZER_APPLE
23862514#define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) \
23872515 HandleRecvmsg(((TsanInterceptorContext *)ctx)->thr, \
23882516 ((TsanInterceptorContext *)ctx)->pc, msg)
......@@ -2415,12 +2543,14 @@ static __sanitizer_sighandler_ptr signal_impl(int sig,
24152543#define SIGNAL_INTERCEPTOR_SIGNAL_IMPL(func, signo, handler) \
24162544 { return (uptr)signal_impl(signo, (__sanitizer_sighandler_ptr)handler); }
24172545
2546#define SIGNAL_INTERCEPTOR_ENTER() LazyInitialize(cur_thread_init())
2547
24182548#include "sanitizer_common/sanitizer_signal_interceptors.inc"
24192549
24202550int sigaction_impl(int sig, const __sanitizer_sigaction *act,
24212551 __sanitizer_sigaction *old) {
24222552 // Note: if we call REAL(sigaction) directly for any reason without proxying
2423 // the signal handler through rtl_sigaction, very bad things will happen.
2553 // the signal handler through sighandler, very bad things will happen.
24242554 // The handler will run synchronously and corrupt tsan per-thread state.
24252555 SCOPED_INTERCEPTOR_RAW(sigaction, sig, act, old);
24262556 if (sig <= 0 || sig >= kSigCount) {
......@@ -2443,27 +2573,22 @@ int sigaction_impl(int sig, const __sanitizer_sigaction *act,
24432573 sigactions[sig].sa_flags = *(volatile int const *)&act->sa_flags;
24442574 internal_memcpy(&sigactions[sig].sa_mask, &act->sa_mask,
24452575 sizeof(sigactions[sig].sa_mask));
2446#if !SANITIZER_FREEBSD && !SANITIZER_MAC && !SANITIZER_NETBSD
2576#if !SANITIZER_FREEBSD && !SANITIZER_APPLE && !SANITIZER_NETBSD
24472577 sigactions[sig].sa_restorer = act->sa_restorer;
24482578#endif
24492579 internal_memcpy(&newact, act, sizeof(newact));
24502580 internal_sigfillset(&newact.sa_mask);
2451 if ((uptr)act->handler != sig_ign && (uptr)act->handler != sig_dfl) {
2452 if (newact.sa_flags & SA_SIGINFO)
2453 newact.sigaction = rtl_sigaction;
2454 else
2455 newact.handler = rtl_sighandler;
2581 if ((act->sa_flags & SA_SIGINFO) ||
2582 ((uptr)act->handler != sig_ign && (uptr)act->handler != sig_dfl)) {
2583 newact.sa_flags |= SA_SIGINFO;
2584 newact.sigaction = sighandler;
24562585 }
24572586 ReleaseStore(thr, pc, (uptr)&sigactions[sig]);
24582587 act = &newact;
24592588 }
24602589 int res = REAL(sigaction)(sig, act, old);
2461 if (res == 0 && old) {
2462 uptr cb = (uptr)old->sigaction;
2463 if (cb == (uptr)rtl_sigaction || cb == (uptr)rtl_sighandler) {
2464 internal_memcpy(old, &old_stored, sizeof(*old));
2465 }
2466 }
2590 if (res == 0 && old && old->sigaction == sighandler)
2591 internal_memcpy(old, &old_stored, sizeof(*old));
24672592 return res;
24682593}
24692594
......@@ -2479,27 +2604,23 @@ static __sanitizer_sighandler_ptr signal_impl(int sig,
24792604 return old.handler;
24802605}
24812606
2482#define TSAN_SYSCALL() \
2607#define TSAN_SYSCALL() \
24832608 ThreadState *thr = cur_thread(); \
2484 if (thr->ignore_interceptors) \
2485 return; \
2486 ScopedSyscall scoped_syscall(thr) \
2487/**/
2609 if (thr->ignore_interceptors) \
2610 return; \
2611 ScopedSyscall scoped_syscall(thr)
24882612
24892613struct ScopedSyscall {
24902614 ThreadState *thr;
24912615
2492 explicit ScopedSyscall(ThreadState *thr)
2493 : thr(thr) {
2494 Initialize(thr);
2495 }
2616 explicit ScopedSyscall(ThreadState *thr) : thr(thr) { LazyInitialize(thr); }
24962617
24972618 ~ScopedSyscall() {
24982619 ProcessPendingSignals(thr);
24992620 }
25002621};
25012622
2502#if !SANITIZER_FREEBSD && !SANITIZER_MAC
2623#if !SANITIZER_FREEBSD && !SANITIZER_APPLE
25032624static void syscall_access_range(uptr pc, uptr p, uptr s, bool write) {
25042625 TSAN_SYSCALL();
25052626 MemoryAccessRange(thr, pc, p, s, write);
......@@ -2508,29 +2629,29 @@ static void syscall_access_range(uptr pc, uptr p, uptr s, bool write) {
25082629static USED void syscall_acquire(uptr pc, uptr addr) {
25092630 TSAN_SYSCALL();
25102631 Acquire(thr, pc, addr);
2511 DPrintf("syscall_acquire(%p)\n", addr);
2632 DPrintf("syscall_acquire(0x%zx))\n", addr);
25122633}
25132634
25142635static USED void syscall_release(uptr pc, uptr addr) {
25152636 TSAN_SYSCALL();
2516 DPrintf("syscall_release(%p)\n", addr);
2637 DPrintf("syscall_release(0x%zx)\n", addr);
25172638 Release(thr, pc, addr);
25182639}
25192640
25202641static void syscall_fd_close(uptr pc, int fd) {
2521 TSAN_SYSCALL();
2642 auto *thr = cur_thread();
25222643 FdClose(thr, pc, fd);
25232644}
25242645
25252646static USED void syscall_fd_acquire(uptr pc, int fd) {
25262647 TSAN_SYSCALL();
25272648 FdAcquire(thr, pc, fd);
2528 DPrintf("syscall_fd_acquire(%p)\n", fd);
2649 DPrintf("syscall_fd_acquire(%d)\n", fd);
25292650}
25302651
25312652static USED void syscall_fd_release(uptr pc, int fd) {
25322653 TSAN_SYSCALL();
2533 DPrintf("syscall_fd_release(%p)\n", fd);
2654 DPrintf("syscall_fd_release(%d)\n", fd);
25342655 FdRelease(thr, pc, fd);
25352656}
25362657
......@@ -2540,7 +2661,7 @@ static void syscall_post_fork(uptr pc, int pid) {
25402661 ThreadState *thr = cur_thread();
25412662 if (pid == 0) {
25422663 // child
2543 ForkChildAfter(thr, pc);
2664 ForkChildAfter(thr, pc, true);
25442665 FdOnFork(thr, pc);
25452666 } else if (pid > 0) {
25462667 // parent
......@@ -2653,6 +2774,26 @@ TSAN_INTERCEPTOR(void, thr_exit, tid_t *state) {
26532774#define TSAN_MAYBE_INTERCEPT_THR_EXIT
26542775#endif
26552776
2777TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, cond_init, void *c, void *a)
2778TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, cond_destroy, void *c)
2779TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, cond_signal, void *c)
2780TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, cond_broadcast, void *c)
2781TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, cond_wait, void *c, void *m)
2782TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, mutex_init, void *m, void *a)
2783TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, mutex_destroy, void *m)
2784TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, mutex_lock, void *m)
2785TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, mutex_trylock, void *m)
2786TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, mutex_unlock, void *m)
2787TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, rwlock_init, void *l, void *a)
2788TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, rwlock_destroy, void *l)
2789TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, rwlock_rdlock, void *l)
2790TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, rwlock_tryrdlock, void *l)
2791TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, rwlock_wrlock, void *l)
2792TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, rwlock_trywrlock, void *l)
2793TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, rwlock_unlock, void *l)
2794TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, once, void *o, void (*i)())
2795TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, sigmask, int f, void *n, void *o)
2796
26562797TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_init, void *c, void *a)
26572798TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_signal, void *c)
26582799TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_broadcast, void *c)
......@@ -2660,7 +2801,9 @@ TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_wait, void *c, void *m)
26602801TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_destroy, void *c)
26612802TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_init, void *m, void *a)
26622803TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_destroy, void *m)
2804TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_lock, void *m)
26632805TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_trylock, void *m)
2806TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_unlock, void *m)
26642807TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_init, void *m, void *a)
26652808TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_destroy, void *m)
26662809TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_rdlock, void *m)
......@@ -2683,7 +2826,7 @@ static void finalize(void *arg) {
26832826 Die();
26842827}
26852828
2686#if !SANITIZER_MAC && !SANITIZER_ANDROID
2829#if !SANITIZER_APPLE && !SANITIZER_ANDROID
26872830static void unreachable() {
26882831 Report("FATAL: ThreadSanitizer: unreachable called\n");
26892832 Die();
......@@ -2694,35 +2837,20 @@ static void unreachable() {
26942837SANITIZER_WEAK_ATTRIBUTE void InitializeLibdispatchInterceptors() {}
26952838
26962839void InitializeInterceptors() {
2697#if !SANITIZER_MAC
2840#if !SANITIZER_APPLE
26982841 // We need to setup it early, because functions like dlsym() can call it.
26992842 REAL(memset) = internal_memset;
27002843 REAL(memcpy) = internal_memcpy;
27012844#endif
27022845
2703 // Instruct libc malloc to consume less memory.
2704#if SANITIZER_GLIBC
2705 mallopt(1, 0); // M_MXFAST
2706 mallopt(-3, 32*1024); // M_MMAP_THRESHOLD
2707#endif
2708
27092846 new(interceptor_ctx()) InterceptorContext();
27102847
27112848 InitializeCommonInterceptors();
27122849 InitializeSignalInterceptors();
27132850 InitializeLibdispatchInterceptors();
27142851
2715#if !SANITIZER_MAC
2716 // We can not use TSAN_INTERCEPT to get setjmp addr,
2717 // because it does &setjmp and setjmp is not present in some versions of libc.
2718 using __interception::InterceptFunction;
2719 InterceptFunction(TSAN_STRING_SETJMP, (uptr*)&REAL(setjmp_symname), 0, 0);
2720 InterceptFunction("_setjmp", (uptr*)&REAL(_setjmp), 0, 0);
2721 InterceptFunction(TSAN_STRING_SIGSETJMP, (uptr*)&REAL(sigsetjmp_symname), 0,
2722 0);
2723#if !SANITIZER_NETBSD
2724 InterceptFunction("__sigsetjmp", (uptr*)&REAL(__sigsetjmp), 0, 0);
2725#endif
2852#if !SANITIZER_APPLE
2853 InitializeSetjmpInterceptors();
27262854#endif
27272855
27282856 TSAN_INTERCEPT(longjmp_symname);
......@@ -2768,8 +2896,16 @@ void InitializeInterceptors() {
27682896
27692897 TSAN_INTERCEPT(pthread_mutex_init);
27702898 TSAN_INTERCEPT(pthread_mutex_destroy);
2899 TSAN_INTERCEPT(pthread_mutex_lock);
27712900 TSAN_INTERCEPT(pthread_mutex_trylock);
27722901 TSAN_INTERCEPT(pthread_mutex_timedlock);
2902 TSAN_INTERCEPT(pthread_mutex_unlock);
2903#if SANITIZER_GLIBC
2904# if !__GLIBC_PREREQ(2, 34)
2905 TSAN_INTERCEPT(__pthread_mutex_lock);
2906 TSAN_INTERCEPT(__pthread_mutex_unlock);
2907# endif
2908#endif
27732909
27742910 TSAN_INTERCEPT(pthread_spin_init);
27752911 TSAN_INTERCEPT(pthread_spin_destroy);
......@@ -2843,6 +2979,9 @@ void InitializeInterceptors() {
28432979
28442980 TSAN_INTERCEPT(fork);
28452981 TSAN_INTERCEPT(vfork);
2982#if SANITIZER_LINUX
2983 TSAN_INTERCEPT(clone);
2984#endif
28462985#if !SANITIZER_ANDROID
28472986 TSAN_INTERCEPT(dl_iterate_phdr);
28482987#endif
......@@ -2862,7 +3001,7 @@ void InitializeInterceptors() {
28623001 TSAN_MAYBE_INTERCEPT__LWP_EXIT;
28633002 TSAN_MAYBE_INTERCEPT_THR_EXIT;
28643003
2865#if !SANITIZER_MAC && !SANITIZER_ANDROID
3004#if !SANITIZER_APPLE && !SANITIZER_ANDROID
28663005 // Need to setup it, because interceptors check that the function is resolved.
28673006 // But atexit is emitted directly into the module, so can't be resolved.
28683007 REAL(atexit) = (int(*)(void(*)()))unreachable;
......@@ -2877,13 +3016,33 @@ void InitializeInterceptors() {
28773016 Die();
28783017 }
28793018
2880#if !SANITIZER_MAC && !SANITIZER_NETBSD && !SANITIZER_FREEBSD
3019#if !SANITIZER_APPLE && !SANITIZER_NETBSD && !SANITIZER_FREEBSD
28813020 if (pthread_key_create(&interceptor_ctx()->finalize_key, &thread_finalize)) {
28823021 Printf("ThreadSanitizer: failed to create thread key\n");
28833022 Die();
28843023 }
28853024#endif
28863025
3026 TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(cond_init);
3027 TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(cond_destroy);
3028 TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(cond_signal);
3029 TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(cond_broadcast);
3030 TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(cond_wait);
3031 TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(mutex_init);
3032 TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(mutex_destroy);
3033 TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(mutex_lock);
3034 TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(mutex_trylock);
3035 TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(mutex_unlock);
3036 TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(rwlock_init);
3037 TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(rwlock_destroy);
3038 TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(rwlock_rdlock);
3039 TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(rwlock_tryrdlock);
3040 TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(rwlock_wrlock);
3041 TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(rwlock_trywrlock);
3042 TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(rwlock_unlock);
3043 TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(once);
3044 TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(sigmask);
3045
28873046 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_init);
28883047 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_signal);
28893048 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_broadcast);
......@@ -2891,7 +3050,9 @@ void InitializeInterceptors() {
28913050 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_destroy);
28923051 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_init);
28933052 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_destroy);
3053 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_lock);
28943054 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_trylock);
3055 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_unlock);
28953056 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_init);
28963057 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_destroy);
28973058 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_rdlock);
......@@ -2920,25 +3081,40 @@ void InitializeInterceptors() {
29203081// Note that no_sanitize_thread attribute does not turn off atomic interception
29213082// so attaching it to the function defined in user code does not help.
29223083// That's why we now have what we have.
2923extern "C" SANITIZER_INTERFACE_ATTRIBUTE
2924void __tsan_testonly_barrier_init(u64 *barrier, u32 count) {
2925 if (count >= (1 << 8)) {
2926 Printf("barrier_init: count is too large (%d)\n", count);
2927 Die();
3084constexpr u32 kBarrierThreadBits = 10;
3085constexpr u32 kBarrierThreads = 1 << kBarrierThreadBits;
3086
3087extern "C" {
3088
3089SANITIZER_INTERFACE_ATTRIBUTE void __tsan_testonly_barrier_init(
3090 atomic_uint32_t *barrier, u32 num_threads) {
3091 if (num_threads >= kBarrierThreads) {
3092 Printf("barrier_init: count is too large (%d)\n", num_threads);
3093 Die();
29283094 }
2929 // 8 lsb is thread count, the remaining are count of entered threads.
2930 *barrier = count;
3095 // kBarrierThreadBits lsb is thread count,
3096 // the remaining are count of entered threads.
3097 atomic_store(barrier, num_threads, memory_order_relaxed);
3098}
3099
3100static u32 barrier_epoch(u32 value) {
3101 return (value >> kBarrierThreadBits) / (value & (kBarrierThreads - 1));
29313102}
29323103
2933extern "C" SANITIZER_INTERFACE_ATTRIBUTE
2934void __tsan_testonly_barrier_wait(u64 *barrier) {
2935 unsigned old = __atomic_fetch_add(barrier, 1 << 8, __ATOMIC_RELAXED);
2936 unsigned old_epoch = (old >> 8) / (old & 0xff);
3104SANITIZER_INTERFACE_ATTRIBUTE void __tsan_testonly_barrier_wait(
3105 atomic_uint32_t *barrier) {
3106 u32 old = atomic_fetch_add(barrier, kBarrierThreads, memory_order_relaxed);
3107 u32 old_epoch = barrier_epoch(old);
3108 if (barrier_epoch(old + kBarrierThreads) != old_epoch) {
3109 FutexWake(barrier, (1 << 30));
3110 return;
3111 }
29373112 for (;;) {
2938 unsigned cur = __atomic_load_n(barrier, __ATOMIC_RELAXED);
2939 unsigned cur_epoch = (cur >> 8) / (cur & 0xff);
2940 if (cur_epoch != old_epoch)
3113 u32 cur = atomic_load(barrier, memory_order_relaxed);
3114 if (barrier_epoch(cur) != old_epoch)
29413115 return;
2942 internal_sched_yield();
3116 FutexWait(barrier, cur);
29433117 }
29443118}
3119
3120} // extern "C"
lib/tsan/tsan_interface.cpp+17-82
......@@ -20,108 +20,43 @@
2020
2121using namespace __tsan;
2222
23void __tsan_init() {
24 cur_thread_init();
25 Initialize(cur_thread());
26}
23void __tsan_init() { Initialize(cur_thread_init()); }
2724
2825void __tsan_flush_memory() {
2926 FlushShadowMemory();
3027}
3128
32void __tsan_read16(void *addr) {
33 MemoryRead(cur_thread(), CALLERPC, (uptr)addr, kSizeLog8);
34 MemoryRead(cur_thread(), CALLERPC, (uptr)addr + 8, kSizeLog8);
35}
36
37void __tsan_write16(void *addr) {
38 MemoryWrite(cur_thread(), CALLERPC, (uptr)addr, kSizeLog8);
39 MemoryWrite(cur_thread(), CALLERPC, (uptr)addr + 8, kSizeLog8);
40}
41
4229void __tsan_read16_pc(void *addr, void *pc) {
43 MemoryRead(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog8);
44 MemoryRead(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr + 8, kSizeLog8);
30 uptr pc_no_pac = STRIP_PAC_PC(pc);
31 ThreadState *thr = cur_thread();
32 MemoryAccess(thr, pc_no_pac, (uptr)addr, 8, kAccessRead);
33 MemoryAccess(thr, pc_no_pac, (uptr)addr + 8, 8, kAccessRead);
4534}
4635
4736void __tsan_write16_pc(void *addr, void *pc) {
48 MemoryWrite(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog8);
49 MemoryWrite(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr + 8, kSizeLog8);
37 uptr pc_no_pac = STRIP_PAC_PC(pc);
38 ThreadState *thr = cur_thread();
39 MemoryAccess(thr, pc_no_pac, (uptr)addr, 8, kAccessWrite);
40 MemoryAccess(thr, pc_no_pac, (uptr)addr + 8, 8, kAccessWrite);
5041}
5142
5243// __tsan_unaligned_read/write calls are emitted by compiler.
5344
54void __tsan_unaligned_read2(const void *addr) {
55 UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, false, false);
56}
57
58void __tsan_unaligned_read4(const void *addr) {
59 UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, false, false);
60}
61
62void __tsan_unaligned_read8(const void *addr) {
63 UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, false, false);
64}
65
6645void __tsan_unaligned_read16(const void *addr) {
67 UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 16, false, false);
68}
69
70void __tsan_unaligned_write2(void *addr) {
71 UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, true, false);
72}
73
74void __tsan_unaligned_write4(void *addr) {
75 UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, true, false);
76}
77
78void __tsan_unaligned_write8(void *addr) {
79 UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, true, false);
46 uptr pc = CALLERPC;
47 ThreadState *thr = cur_thread();
48 UnalignedMemoryAccess(thr, pc, (uptr)addr, 8, kAccessRead);
49 UnalignedMemoryAccess(thr, pc, (uptr)addr + 8, 8, kAccessRead);
8050}
8151
8252void __tsan_unaligned_write16(void *addr) {
83 UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 16, true, false);
53 uptr pc = CALLERPC;
54 ThreadState *thr = cur_thread();
55 UnalignedMemoryAccess(thr, pc, (uptr)addr, 8, kAccessWrite);
56 UnalignedMemoryAccess(thr, pc, (uptr)addr + 8, 8, kAccessWrite);
8457}
8558
86// __sanitizer_unaligned_load/store are for user instrumentation.
87
8859extern "C" {
89SANITIZER_INTERFACE_ATTRIBUTE
90u16 __sanitizer_unaligned_load16(const uu16 *addr) {
91 __tsan_unaligned_read2(addr);
92 return *addr;
93}
94
95SANITIZER_INTERFACE_ATTRIBUTE
96u32 __sanitizer_unaligned_load32(const uu32 *addr) {
97 __tsan_unaligned_read4(addr);
98 return *addr;
99}
100
101SANITIZER_INTERFACE_ATTRIBUTE
102u64 __sanitizer_unaligned_load64(const uu64 *addr) {
103 __tsan_unaligned_read8(addr);
104 return *addr;
105}
106
107SANITIZER_INTERFACE_ATTRIBUTE
108void __sanitizer_unaligned_store16(uu16 *addr, u16 v) {
109 __tsan_unaligned_write2(addr);
110 *addr = v;
111}
112
113SANITIZER_INTERFACE_ATTRIBUTE
114void __sanitizer_unaligned_store32(uu32 *addr, u32 v) {
115 __tsan_unaligned_write4(addr);
116 *addr = v;
117}
118
119SANITIZER_INTERFACE_ATTRIBUTE
120void __sanitizer_unaligned_store64(uu64 *addr, u64 v) {
121 __tsan_unaligned_write8(addr);
122 *addr = v;
123}
124
12560SANITIZER_INTERFACE_ATTRIBUTE
12661void *__tsan_get_current_fiber() {
12762 return cur_thread();
lib/tsan/tsan_interface.h+14-8
......@@ -32,6 +32,9 @@ extern "C" {
3232// before any instrumented code is executed and before any call to malloc.
3333SANITIZER_INTERFACE_ATTRIBUTE void __tsan_init();
3434
35SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE const char *
36__tsan_default_options();
37
3538SANITIZER_INTERFACE_ATTRIBUTE void __tsan_flush_memory();
3639
3740SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read1(void *addr);
......@@ -72,12 +75,21 @@ SANITIZER_INTERFACE_ATTRIBUTE void __tsan_vptr_read(void **vptr_p);
7275SANITIZER_INTERFACE_ATTRIBUTE
7376void __tsan_vptr_update(void **vptr_p, void *new_val);
7477
78SANITIZER_INTERFACE_ATTRIBUTE
79void *__tsan_memcpy(void *dest, const void *src, uptr count);
80SANITIZER_INTERFACE_ATTRIBUTE
81void *__tsan_memset(void *dest, int ch, uptr count);
82SANITIZER_INTERFACE_ATTRIBUTE
83void *__tsan_memmove(void *dest, const void *src, uptr count);
84
7585SANITIZER_INTERFACE_ATTRIBUTE void __tsan_func_entry(void *call_pc);
7686SANITIZER_INTERFACE_ATTRIBUTE void __tsan_func_exit();
7787
7888SANITIZER_INTERFACE_ATTRIBUTE void __tsan_ignore_thread_begin();
7989SANITIZER_INTERFACE_ATTRIBUTE void __tsan_ignore_thread_end();
8090
91SANITIZER_INTERFACE_ATTRIBUTE void __tsan_on_thread_idle();
92
8193SANITIZER_INTERFACE_ATTRIBUTE
8294void *__tsan_external_register_tag(const char *object_type);
8395SANITIZER_INTERFACE_ATTRIBUTE
......@@ -95,9 +107,9 @@ SANITIZER_INTERFACE_ATTRIBUTE
95107void __tsan_write_range(void *addr, unsigned long size);
96108
97109SANITIZER_INTERFACE_ATTRIBUTE
98void __tsan_read_range_pc(void *addr, unsigned long size, void *pc); // NOLINT
110void __tsan_read_range_pc(void *addr, unsigned long size, void *pc);
99111SANITIZER_INTERFACE_ATTRIBUTE
100void __tsan_write_range_pc(void *addr, unsigned long size, void *pc); // NOLINT
112void __tsan_write_range_pc(void *addr, unsigned long size, void *pc);
101113
102114// User may provide function that would be called right when TSan detects
103115// an error. The argument 'report' is an opaque pointer that can be used to
......@@ -417,12 +429,6 @@ SANITIZER_INTERFACE_ATTRIBUTE
417429void __tsan_go_atomic64_compare_exchange(ThreadState *thr, uptr cpc, uptr pc,
418430 u8 *a);
419431
420SANITIZER_INTERFACE_ATTRIBUTE
421void __tsan_on_initialize();
422
423SANITIZER_INTERFACE_ATTRIBUTE
424int __tsan_on_finalize(int failed);
425
426432} // extern "C"
427433
428434} // namespace __tsan
lib/tsan/tsan_interface.inc created+190
......@@ -0,0 +1,190 @@
1//===-- tsan_interface.inc --------------------------------------*- 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
13#include "sanitizer_common/sanitizer_ptrauth.h"
14#include "tsan_interface.h"
15#include "tsan_rtl.h"
16
17#define CALLERPC ((uptr)__builtin_return_address(0))
18
19using namespace __tsan;
20
21void __tsan_read1(void *addr) {
22 MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 1, kAccessRead);
23}
24
25void __tsan_read2(void *addr) {
26 MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, kAccessRead);
27}
28
29void __tsan_read4(void *addr) {
30 MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, kAccessRead);
31}
32
33void __tsan_read8(void *addr) {
34 MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, kAccessRead);
35}
36
37void __tsan_read16(void *addr) {
38 MemoryAccess16(cur_thread(), CALLERPC, (uptr)addr, kAccessRead);
39}
40
41void __tsan_write1(void *addr) {
42 MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 1, kAccessWrite);
43}
44
45void __tsan_write2(void *addr) {
46 MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, kAccessWrite);
47}
48
49void __tsan_write4(void *addr) {
50 MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, kAccessWrite);
51}
52
53void __tsan_write8(void *addr) {
54 MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, kAccessWrite);
55}
56
57void __tsan_write16(void *addr) {
58 MemoryAccess16(cur_thread(), CALLERPC, (uptr)addr, kAccessWrite);
59}
60
61void __tsan_read1_pc(void *addr, void *pc) {
62 MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 1, kAccessRead | kAccessExternalPC);
63}
64
65void __tsan_read2_pc(void *addr, void *pc) {
66 MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 2, kAccessRead | kAccessExternalPC);
67}
68
69void __tsan_read4_pc(void *addr, void *pc) {
70 MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 4, kAccessRead | kAccessExternalPC);
71}
72
73void __tsan_read8_pc(void *addr, void *pc) {
74 MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 8, kAccessRead | kAccessExternalPC);
75}
76
77void __tsan_write1_pc(void *addr, void *pc) {
78 MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 1, kAccessWrite | kAccessExternalPC);
79}
80
81void __tsan_write2_pc(void *addr, void *pc) {
82 MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 2, kAccessWrite | kAccessExternalPC);
83}
84
85void __tsan_write4_pc(void *addr, void *pc) {
86 MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 4, kAccessWrite | kAccessExternalPC);
87}
88
89void __tsan_write8_pc(void *addr, void *pc) {
90 MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 8, kAccessWrite | kAccessExternalPC);
91}
92
93ALWAYS_INLINE USED void __tsan_unaligned_read2(const void *addr) {
94 UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, kAccessRead);
95}
96
97ALWAYS_INLINE USED void __tsan_unaligned_read4(const void *addr) {
98 UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, kAccessRead);
99}
100
101ALWAYS_INLINE USED void __tsan_unaligned_read8(const void *addr) {
102 UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, kAccessRead);
103}
104
105ALWAYS_INLINE USED void __tsan_unaligned_write2(void *addr) {
106 UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, kAccessWrite);
107}
108
109ALWAYS_INLINE USED void __tsan_unaligned_write4(void *addr) {
110 UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, kAccessWrite);
111}
112
113ALWAYS_INLINE USED void __tsan_unaligned_write8(void *addr) {
114 UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, kAccessWrite);
115}
116
117extern "C" {
118// __sanitizer_unaligned_load/store are for user instrumentation.
119SANITIZER_INTERFACE_ATTRIBUTE
120u16 __sanitizer_unaligned_load16(const uu16 *addr) {
121 __tsan_unaligned_read2(addr);
122 return *addr;
123}
124
125SANITIZER_INTERFACE_ATTRIBUTE
126u32 __sanitizer_unaligned_load32(const uu32 *addr) {
127 __tsan_unaligned_read4(addr);
128 return *addr;
129}
130
131SANITIZER_INTERFACE_ATTRIBUTE
132u64 __sanitizer_unaligned_load64(const uu64 *addr) {
133 __tsan_unaligned_read8(addr);
134 return *addr;
135}
136
137SANITIZER_INTERFACE_ATTRIBUTE
138void __sanitizer_unaligned_store16(uu16 *addr, u16 v) {
139 *addr = v;
140 __tsan_unaligned_write2(addr);
141}
142
143SANITIZER_INTERFACE_ATTRIBUTE
144void __sanitizer_unaligned_store32(uu32 *addr, u32 v) {
145 *addr = v;
146 __tsan_unaligned_write4(addr);
147}
148
149SANITIZER_INTERFACE_ATTRIBUTE
150void __sanitizer_unaligned_store64(uu64 *addr, u64 v) {
151 *addr = v;
152 __tsan_unaligned_write8(addr);
153}
154}
155
156void __tsan_vptr_update(void **vptr_p, void *new_val) {
157 if (*vptr_p == new_val)
158 return;
159 MemoryAccess(cur_thread(), CALLERPC, (uptr)vptr_p, sizeof(*vptr_p),
160 kAccessWrite | kAccessVptr);
161}
162
163void __tsan_vptr_read(void **vptr_p) {
164 MemoryAccess(cur_thread(), CALLERPC, (uptr)vptr_p, sizeof(*vptr_p),
165 kAccessRead | kAccessVptr);
166}
167
168void __tsan_func_entry(void *pc) { FuncEntry(cur_thread(), STRIP_PAC_PC(pc)); }
169
170void __tsan_func_exit() { FuncExit(cur_thread()); }
171
172void __tsan_ignore_thread_begin() { ThreadIgnoreBegin(cur_thread(), CALLERPC); }
173
174void __tsan_ignore_thread_end() { ThreadIgnoreEnd(cur_thread()); }
175
176void __tsan_read_range(void *addr, uptr size) {
177 MemoryAccessRange(cur_thread(), CALLERPC, (uptr)addr, size, false);
178}
179
180void __tsan_write_range(void *addr, uptr size) {
181 MemoryAccessRange(cur_thread(), CALLERPC, (uptr)addr, size, true);
182}
183
184void __tsan_read_range_pc(void *addr, uptr size, void *pc) {
185 MemoryAccessRange(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, size, false);
186}
187
188void __tsan_write_range_pc(void *addr, uptr size, void *pc) {
189 MemoryAccessRange(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, size, true);
190}
lib/tsan/tsan_interface_ann.cpp+30-139
......@@ -43,15 +43,14 @@ class ScopedAnnotation {
4343 ThreadState *const thr_;
4444};
4545
46#define SCOPED_ANNOTATION_RET(typ, ret) \
47 if (!flags()->enable_annotations) \
48 return ret; \
49 ThreadState *thr = cur_thread(); \
50 const uptr caller_pc = (uptr)__builtin_return_address(0); \
51 ScopedAnnotation sa(thr, __func__, caller_pc); \
52 const uptr pc = StackTrace::GetCurrentPc(); \
53 (void)pc; \
54/**/
46#define SCOPED_ANNOTATION_RET(typ, ret) \
47 if (!flags()->enable_annotations) \
48 return ret; \
49 ThreadState *thr = cur_thread(); \
50 const uptr caller_pc = (uptr)__builtin_return_address(0); \
51 ScopedAnnotation sa(thr, __func__, caller_pc); \
52 const uptr pc = StackTrace::GetCurrentPc(); \
53 (void)pc;
5554
5655#define SCOPED_ANNOTATION(typ) SCOPED_ANNOTATION_RET(typ, )
5756
......@@ -71,7 +70,6 @@ struct ExpectRace {
7170
7271struct DynamicAnnContext {
7372 Mutex mtx;
74 ExpectRace expect;
7573 ExpectRace benign;
7674
7775 DynamicAnnContext() : mtx(MutexTypeAnnotations) {}
......@@ -90,7 +88,7 @@ static void AddExpectRace(ExpectRace *list,
9088 return;
9189 }
9290 }
93 race = (ExpectRace*)internal_alloc(MBlockExpectRace, sizeof(ExpectRace));
91 race = static_cast<ExpectRace *>(Alloc(sizeof(ExpectRace)));
9492 race->addr = addr;
9593 race->size = size;
9694 race->file = f;
......@@ -137,81 +135,12 @@ static void InitList(ExpectRace *list) {
137135
138136void InitializeDynamicAnnotations() {
139137 dyn_ann_ctx = new(dyn_ann_ctx_placeholder) DynamicAnnContext;
140 InitList(&dyn_ann_ctx->expect);
141138 InitList(&dyn_ann_ctx->benign);
142139}
143140
144141bool IsExpectedReport(uptr addr, uptr size) {
145142 ReadLock lock(&dyn_ann_ctx->mtx);
146 if (CheckContains(&dyn_ann_ctx->expect, addr, size))
147 return true;
148 if (CheckContains(&dyn_ann_ctx->benign, addr, size))
149 return true;
150 return false;
151}
152
153static void CollectMatchedBenignRaces(Vector<ExpectRace> *matched,
154 int *unique_count, int *hit_count, atomic_uintptr_t ExpectRace::*counter) {
155 ExpectRace *list = &dyn_ann_ctx->benign;
156 for (ExpectRace *race = list->next; race != list; race = race->next) {
157 (*unique_count)++;
158 const uptr cnt = atomic_load_relaxed(&(race->*counter));
159 if (cnt == 0)
160 continue;
161 *hit_count += cnt;
162 uptr i = 0;
163 for (; i < matched->Size(); i++) {
164 ExpectRace *race0 = &(*matched)[i];
165 if (race->line == race0->line
166 && internal_strcmp(race->file, race0->file) == 0
167 && internal_strcmp(race->desc, race0->desc) == 0) {
168 atomic_fetch_add(&(race0->*counter), cnt, memory_order_relaxed);
169 break;
170 }
171 }
172 if (i == matched->Size())
173 matched->PushBack(*race);
174 }
175}
176
177void PrintMatchedBenignRaces() {
178 Lock lock(&dyn_ann_ctx->mtx);
179 int unique_count = 0;
180 int hit_count = 0;
181 int add_count = 0;
182 Vector<ExpectRace> hit_matched;
183 CollectMatchedBenignRaces(&hit_matched, &unique_count, &hit_count,
184 &ExpectRace::hitcount);
185 Vector<ExpectRace> add_matched;
186 CollectMatchedBenignRaces(&add_matched, &unique_count, &add_count,
187 &ExpectRace::addcount);
188 if (hit_matched.Size()) {
189 Printf("ThreadSanitizer: Matched %d \"benign\" races (pid=%d):\n",
190 hit_count, (int)internal_getpid());
191 for (uptr i = 0; i < hit_matched.Size(); i++) {
192 Printf("%d %s:%d %s\n",
193 atomic_load_relaxed(&hit_matched[i].hitcount),
194 hit_matched[i].file, hit_matched[i].line, hit_matched[i].desc);
195 }
196 }
197 if (hit_matched.Size()) {
198 Printf("ThreadSanitizer: Annotated %d \"benign\" races, %d unique"
199 " (pid=%d):\n",
200 add_count, unique_count, (int)internal_getpid());
201 for (uptr i = 0; i < add_matched.Size(); i++) {
202 Printf("%d %s:%d %s\n",
203 atomic_load_relaxed(&add_matched[i].addcount),
204 add_matched[i].file, add_matched[i].line, add_matched[i].desc);
205 }
206 }
207}
208
209static void ReportMissedExpectedRace(ExpectRace *race) {
210 Printf("==================\n");
211 Printf("WARNING: ThreadSanitizer: missed expected data race\n");
212 Printf(" %s addr=%zx %s:%d\n",
213 race->desc, race->addr, race->file, race->line);
214 Printf("==================\n");
143 return CheckContains(&dyn_ann_ctx->benign, addr, size);
215144}
216145} // namespace __tsan
217146
......@@ -229,20 +158,16 @@ void INTERFACE_ATTRIBUTE AnnotateHappensAfter(char *f, int l, uptr addr) {
229158}
230159
231160void INTERFACE_ATTRIBUTE AnnotateCondVarSignal(char *f, int l, uptr cv) {
232 SCOPED_ANNOTATION(AnnotateCondVarSignal);
233161}
234162
235163void INTERFACE_ATTRIBUTE AnnotateCondVarSignalAll(char *f, int l, uptr cv) {
236 SCOPED_ANNOTATION(AnnotateCondVarSignalAll);
237164}
238165
239166void INTERFACE_ATTRIBUTE AnnotateMutexIsNotPHB(char *f, int l, uptr mu) {
240 SCOPED_ANNOTATION(AnnotateMutexIsNotPHB);
241167}
242168
243169void INTERFACE_ATTRIBUTE AnnotateCondVarWait(char *f, int l, uptr cv,
244170 uptr lock) {
245 SCOPED_ANNOTATION(AnnotateCondVarWait);
246171}
247172
248173void INTERFACE_ATTRIBUTE AnnotateRWLockCreate(char *f, int l, uptr m) {
......@@ -279,86 +204,56 @@ void INTERFACE_ATTRIBUTE AnnotateRWLockReleased(char *f, int l, uptr m,
279204}
280205
281206void INTERFACE_ATTRIBUTE AnnotateTraceMemory(char *f, int l, uptr mem) {
282 SCOPED_ANNOTATION(AnnotateTraceMemory);
283207}
284208
285209void INTERFACE_ATTRIBUTE AnnotateFlushState(char *f, int l) {
286 SCOPED_ANNOTATION(AnnotateFlushState);
287210}
288211
289212void INTERFACE_ATTRIBUTE AnnotateNewMemory(char *f, int l, uptr mem,
290213 uptr size) {
291 SCOPED_ANNOTATION(AnnotateNewMemory);
292214}
293215
294216void INTERFACE_ATTRIBUTE AnnotateNoOp(char *f, int l, uptr mem) {
295 SCOPED_ANNOTATION(AnnotateNoOp);
296217}
297218
298219void INTERFACE_ATTRIBUTE AnnotateFlushExpectedRaces(char *f, int l) {
299 SCOPED_ANNOTATION(AnnotateFlushExpectedRaces);
300 Lock lock(&dyn_ann_ctx->mtx);
301 while (dyn_ann_ctx->expect.next != &dyn_ann_ctx->expect) {
302 ExpectRace *race = dyn_ann_ctx->expect.next;
303 if (atomic_load_relaxed(&race->hitcount) == 0) {
304 ctx->nmissed_expected++;
305 ReportMissedExpectedRace(race);
306 }
307 race->prev->next = race->next;
308 race->next->prev = race->prev;
309 internal_free(race);
310 }
311220}
312221
313222void INTERFACE_ATTRIBUTE AnnotateEnableRaceDetection(
314223 char *f, int l, int enable) {
315 SCOPED_ANNOTATION(AnnotateEnableRaceDetection);
316 // FIXME: Reconsider this functionality later. It may be irrelevant.
317224}
318225
319226void INTERFACE_ATTRIBUTE AnnotateMutexIsUsedAsCondVar(
320227 char *f, int l, uptr mu) {
321 SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar);
322228}
323229
324230void INTERFACE_ATTRIBUTE AnnotatePCQGet(
325231 char *f, int l, uptr pcq) {
326 SCOPED_ANNOTATION(AnnotatePCQGet);
327232}
328233
329234void INTERFACE_ATTRIBUTE AnnotatePCQPut(
330235 char *f, int l, uptr pcq) {
331 SCOPED_ANNOTATION(AnnotatePCQPut);
332236}
333237
334238void INTERFACE_ATTRIBUTE AnnotatePCQDestroy(
335239 char *f, int l, uptr pcq) {
336 SCOPED_ANNOTATION(AnnotatePCQDestroy);
337240}
338241
339242void INTERFACE_ATTRIBUTE AnnotatePCQCreate(
340243 char *f, int l, uptr pcq) {
341 SCOPED_ANNOTATION(AnnotatePCQCreate);
342244}
343245
344246void INTERFACE_ATTRIBUTE AnnotateExpectRace(
345247 char *f, int l, uptr mem, char *desc) {
346 SCOPED_ANNOTATION(AnnotateExpectRace);
347 Lock lock(&dyn_ann_ctx->mtx);
348 AddExpectRace(&dyn_ann_ctx->expect,
349 f, l, mem, 1, desc);
350 DPrintf("Add expected race: %s addr=%zx %s:%d\n", desc, mem, f, l);
351248}
352249
353static void BenignRaceImpl(
354 char *f, int l, uptr mem, uptr size, char *desc) {
250static void BenignRaceImpl(char *f, int l, uptr mem, uptr size, char *desc) {
355251 Lock lock(&dyn_ann_ctx->mtx);
356252 AddExpectRace(&dyn_ann_ctx->benign,
357253 f, l, mem, size, desc);
358254 DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc, mem, f, l);
359255}
360256
361// FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm.
362257void INTERFACE_ATTRIBUTE AnnotateBenignRaceSized(
363258 char *f, int l, uptr mem, uptr size, char *desc) {
364259 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
......@@ -378,7 +273,7 @@ void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsBegin(char *f, int l) {
378273
379274void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsEnd(char *f, int l) {
380275 SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd);
381 ThreadIgnoreEnd(thr, pc);
276 ThreadIgnoreEnd(thr);
382277}
383278
384279void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesBegin(char *f, int l) {
......@@ -388,7 +283,7 @@ void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesBegin(char *f, int l) {
388283
389284void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesEnd(char *f, int l) {
390285 SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd);
391 ThreadIgnoreEnd(thr, pc);
286 ThreadIgnoreEnd(thr);
392287}
393288
394289void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncBegin(char *f, int l) {
......@@ -398,17 +293,15 @@ void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncBegin(char *f, int l) {
398293
399294void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncEnd(char *f, int l) {
400295 SCOPED_ANNOTATION(AnnotateIgnoreSyncEnd);
401 ThreadIgnoreSyncEnd(thr, pc);
296 ThreadIgnoreSyncEnd(thr);
402297}
403298
404299void INTERFACE_ATTRIBUTE AnnotatePublishMemoryRange(
405300 char *f, int l, uptr addr, uptr size) {
406 SCOPED_ANNOTATION(AnnotatePublishMemoryRange);
407301}
408302
409303void INTERFACE_ATTRIBUTE AnnotateUnpublishMemoryRange(
410304 char *f, int l, uptr addr, uptr size) {
411 SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange);
412305}
413306
414307void INTERFACE_ATTRIBUTE AnnotateThreadName(
......@@ -421,11 +314,9 @@ void INTERFACE_ATTRIBUTE AnnotateThreadName(
421314// WTFAnnotateHappensAfter(). Those are being used by Webkit to annotate
422315// atomic operations, which should be handled by ThreadSanitizer correctly.
423316void INTERFACE_ATTRIBUTE WTFAnnotateHappensBefore(char *f, int l, uptr addr) {
424 SCOPED_ANNOTATION(AnnotateHappensBefore);
425317}
426318
427319void INTERFACE_ATTRIBUTE WTFAnnotateHappensAfter(char *f, int l, uptr addr) {
428 SCOPED_ANNOTATION(AnnotateHappensAfter);
429320}
430321
431322void INTERFACE_ATTRIBUTE WTFAnnotateBenignRaceSized(
......@@ -477,15 +368,15 @@ void __tsan_mutex_pre_lock(void *m, unsigned flagz) {
477368 else
478369 MutexPreLock(thr, pc, (uptr)m);
479370 }
480 ThreadIgnoreBegin(thr, pc, /*save_stack=*/false);
481 ThreadIgnoreSyncBegin(thr, pc, /*save_stack=*/false);
371 ThreadIgnoreBegin(thr, 0);
372 ThreadIgnoreSyncBegin(thr, 0);
482373}
483374
484375INTERFACE_ATTRIBUTE
485376void __tsan_mutex_post_lock(void *m, unsigned flagz, int rec) {
486377 SCOPED_ANNOTATION(__tsan_mutex_post_lock);
487 ThreadIgnoreSyncEnd(thr, pc);
488 ThreadIgnoreEnd(thr, pc);
378 ThreadIgnoreSyncEnd(thr);
379 ThreadIgnoreEnd(thr);
489380 if (!(flagz & MutexFlagTryLockFailed)) {
490381 if (flagz & MutexFlagReadLock)
491382 MutexPostReadLock(thr, pc, (uptr)m, flagz);
......@@ -504,44 +395,44 @@ int __tsan_mutex_pre_unlock(void *m, unsigned flagz) {
504395 } else {
505396 ret = MutexUnlock(thr, pc, (uptr)m, flagz);
506397 }
507 ThreadIgnoreBegin(thr, pc, /*save_stack=*/false);
508 ThreadIgnoreSyncBegin(thr, pc, /*save_stack=*/false);
398 ThreadIgnoreBegin(thr, 0);
399 ThreadIgnoreSyncBegin(thr, 0);
509400 return ret;
510401}
511402
512403INTERFACE_ATTRIBUTE
513404void __tsan_mutex_post_unlock(void *m, unsigned flagz) {
514405 SCOPED_ANNOTATION(__tsan_mutex_post_unlock);
515 ThreadIgnoreSyncEnd(thr, pc);
516 ThreadIgnoreEnd(thr, pc);
406 ThreadIgnoreSyncEnd(thr);
407 ThreadIgnoreEnd(thr);
517408}
518409
519410INTERFACE_ATTRIBUTE
520411void __tsan_mutex_pre_signal(void *addr, unsigned flagz) {
521412 SCOPED_ANNOTATION(__tsan_mutex_pre_signal);
522 ThreadIgnoreBegin(thr, pc, /*save_stack=*/false);
523 ThreadIgnoreSyncBegin(thr, pc, /*save_stack=*/false);
413 ThreadIgnoreBegin(thr, 0);
414 ThreadIgnoreSyncBegin(thr, 0);
524415}
525416
526417INTERFACE_ATTRIBUTE
527418void __tsan_mutex_post_signal(void *addr, unsigned flagz) {
528419 SCOPED_ANNOTATION(__tsan_mutex_post_signal);
529 ThreadIgnoreSyncEnd(thr, pc);
530 ThreadIgnoreEnd(thr, pc);
420 ThreadIgnoreSyncEnd(thr);
421 ThreadIgnoreEnd(thr);
531422}
532423
533424INTERFACE_ATTRIBUTE
534425void __tsan_mutex_pre_divert(void *addr, unsigned flagz) {
535426 SCOPED_ANNOTATION(__tsan_mutex_pre_divert);
536427 // Exit from ignore region started in __tsan_mutex_pre_lock/unlock/signal.
537 ThreadIgnoreSyncEnd(thr, pc);
538 ThreadIgnoreEnd(thr, pc);
428 ThreadIgnoreSyncEnd(thr);
429 ThreadIgnoreEnd(thr);
539430}
540431
541432INTERFACE_ATTRIBUTE
542433void __tsan_mutex_post_divert(void *addr, unsigned flagz) {
543434 SCOPED_ANNOTATION(__tsan_mutex_post_divert);
544 ThreadIgnoreBegin(thr, pc, /*save_stack=*/false);
545 ThreadIgnoreSyncBegin(thr, pc, /*save_stack=*/false);
435 ThreadIgnoreBegin(thr, 0);
436 ThreadIgnoreSyncBegin(thr, 0);
546437}
547438} // extern "C"
lib/tsan/tsan_interface_atomic.cpp+155-181
......@@ -32,6 +32,7 @@ using namespace __tsan;
3232static StaticSpinMutex mutex128;
3333#endif
3434
35#if SANITIZER_DEBUG
3536static bool IsLoadOrder(morder mo) {
3637 return mo == mo_relaxed || mo == mo_consume
3738 || mo == mo_acquire || mo == mo_seq_cst;
......@@ -40,6 +41,7 @@ static bool IsLoadOrder(morder mo) {
4041static bool IsStoreOrder(morder mo) {
4142 return mo == mo_relaxed || mo == mo_release || mo == mo_seq_cst;
4243}
44#endif
4345
4446static bool IsReleaseOrder(morder mo) {
4547 return mo == mo_release || mo == mo_acq_rel || mo == mo_seq_cst;
......@@ -161,16 +163,16 @@ a128 func_cas(volatile a128 *v, a128 cmp, a128 xch) {
161163}
162164#endif
163165
164template<typename T>
165static int SizeLog() {
166template <typename T>
167static int AccessSize() {
166168 if (sizeof(T) <= 1)
167 return kSizeLog1;
169 return 1;
168170 else if (sizeof(T) <= 2)
169 return kSizeLog2;
171 return 2;
170172 else if (sizeof(T) <= 4)
171 return kSizeLog4;
173 return 4;
172174 else
173 return kSizeLog8;
175 return 8;
174176 // For 16-byte atomics we also use 8-byte memory access,
175177 // this leads to false negatives only in very obscure cases.
176178}
......@@ -202,7 +204,7 @@ static memory_order to_mo(morder mo) {
202204 case mo_acq_rel: return memory_order_acq_rel;
203205 case mo_seq_cst: return memory_order_seq_cst;
204206 }
205 CHECK(0);
207 DCHECK(0);
206208 return memory_order_seq_cst;
207209}
208210
......@@ -219,27 +221,28 @@ static a128 NoTsanAtomicLoad(const volatile a128 *a, morder mo) {
219221#endif
220222
221223template <typename T>
222static T AtomicLoad(ThreadState *thr, uptr pc, const volatile T *a,
223 morder mo) NO_THREAD_SAFETY_ANALYSIS {
224 CHECK(IsLoadOrder(mo));
224static T AtomicLoad(ThreadState *thr, uptr pc, const volatile T *a, morder mo) {
225 DCHECK(IsLoadOrder(mo));
225226 // This fast-path is critical for performance.
226227 // Assume the access is atomic.
227228 if (!IsAcquireOrder(mo)) {
228 MemoryReadAtomic(thr, pc, (uptr)a, SizeLog<T>());
229 MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(),
230 kAccessRead | kAccessAtomic);
229231 return NoTsanAtomicLoad(a, mo);
230232 }
231233 // Don't create sync object if it does not exist yet. For example, an atomic
232234 // pointer is initialized to nullptr and then periodically acquire-loaded.
233235 T v = NoTsanAtomicLoad(a, mo);
234 SyncVar *s = ctx->metamap.GetIfExistsAndLock((uptr)a, false);
236 SyncVar *s = ctx->metamap.GetSyncIfExists((uptr)a);
235237 if (s) {
236 AcquireImpl(thr, pc, &s->clock);
238 SlotLocker locker(thr);
239 ReadLock lock(&s->mtx);
240 thr->clock.Acquire(s->clock);
237241 // Re-read under sync mutex because we need a consistent snapshot
238242 // of the value and the clock we acquire.
239243 v = NoTsanAtomicLoad(a, mo);
240 s->mtx.ReadUnlock();
241244 }
242 MemoryReadAtomic(thr, pc, (uptr)a, SizeLog<T>());
245 MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(), kAccessRead | kAccessAtomic);
243246 return v;
244247}
245248
......@@ -257,9 +260,9 @@ static void NoTsanAtomicStore(volatile a128 *a, a128 v, morder mo) {
257260
258261template <typename T>
259262static void AtomicStore(ThreadState *thr, uptr pc, volatile T *a, T v,
260 morder mo) NO_THREAD_SAFETY_ANALYSIS {
261 CHECK(IsStoreOrder(mo));
262 MemoryWriteAtomic(thr, pc, (uptr)a, SizeLog<T>());
263 morder mo) {
264 DCHECK(IsStoreOrder(mo));
265 MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(), kAccessWrite | kAccessAtomic);
263266 // This fast-path is critical for performance.
264267 // Assume the access is atomic.
265268 // Strictly saying even relaxed store cuts off release sequence,
......@@ -268,36 +271,35 @@ static void AtomicStore(ThreadState *thr, uptr pc, volatile T *a, T v,
268271 NoTsanAtomicStore(a, v, mo);
269272 return;
270273 }
271 __sync_synchronize();
272 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, (uptr)a, true);
273 thr->fast_state.IncrementEpoch();
274 // Can't increment epoch w/o writing to the trace as well.
275 TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
276 ReleaseStoreImpl(thr, pc, &s->clock);
277 NoTsanAtomicStore(a, v, mo);
278 s->mtx.Unlock();
274 SlotLocker locker(thr);
275 {
276 auto s = ctx->metamap.GetSyncOrCreate(thr, pc, (uptr)a, false);
277 Lock lock(&s->mtx);
278 thr->clock.ReleaseStore(&s->clock);
279 NoTsanAtomicStore(a, v, mo);
280 }
281 IncrementEpoch(thr);
279282}
280283
281284template <typename T, T (*F)(volatile T *v, T op)>
282static T AtomicRMW(ThreadState *thr, uptr pc, volatile T *a, T v,
283 morder mo) NO_THREAD_SAFETY_ANALYSIS {
284 MemoryWriteAtomic(thr, pc, (uptr)a, SizeLog<T>());
285 SyncVar *s = 0;
286 if (mo != mo_relaxed) {
287 s = ctx->metamap.GetOrCreateAndLock(thr, pc, (uptr)a, true);
288 thr->fast_state.IncrementEpoch();
289 // Can't increment epoch w/o writing to the trace as well.
290 TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
285static T AtomicRMW(ThreadState *thr, uptr pc, volatile T *a, T v, morder mo) {
286 MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(), kAccessWrite | kAccessAtomic);
287 if (LIKELY(mo == mo_relaxed))
288 return F(a, v);
289 SlotLocker locker(thr);
290 {
291 auto s = ctx->metamap.GetSyncOrCreate(thr, pc, (uptr)a, false);
292 RWLock lock(&s->mtx, IsReleaseOrder(mo));
291293 if (IsAcqRelOrder(mo))
292 AcquireReleaseImpl(thr, pc, &s->clock);
294 thr->clock.ReleaseAcquire(&s->clock);
293295 else if (IsReleaseOrder(mo))
294 ReleaseImpl(thr, pc, &s->clock);
296 thr->clock.Release(&s->clock);
295297 else if (IsAcquireOrder(mo))
296 AcquireImpl(thr, pc, &s->clock);
298 thr->clock.Acquire(s->clock);
299 v = F(a, v);
297300 }
298 v = F(a, v);
299 if (s)
300 s->mtx.Unlock();
301 if (IsReleaseOrder(mo))
302 IncrementEpoch(thr);
301303 return v;
302304}
303305
......@@ -402,46 +404,44 @@ static T NoTsanAtomicCAS(volatile T *a, T c, T v, morder mo, morder fmo) {
402404}
403405
404406template <typename T>
405static bool AtomicCAS(ThreadState *thr, uptr pc, volatile T *a, T *c, T v, morder mo,
406 morder fmo) NO_THREAD_SAFETY_ANALYSIS {
407static bool AtomicCAS(ThreadState *thr, uptr pc, volatile T *a, T *c, T v,
408 morder mo, morder fmo) {
407409 // 31.7.2.18: "The failure argument shall not be memory_order_release
408410 // nor memory_order_acq_rel". LLVM (2021-05) fallbacks to Monotonic
409411 // (mo_relaxed) when those are used.
410 CHECK(IsLoadOrder(fmo));
411
412 MemoryWriteAtomic(thr, pc, (uptr)a, SizeLog<T>());
413 SyncVar *s = 0;
414 bool write_lock = IsReleaseOrder(mo);
415
416 if (mo != mo_relaxed || fmo != mo_relaxed)
417 s = ctx->metamap.GetOrCreateAndLock(thr, pc, (uptr)a, write_lock);
418
419 T cc = *c;
420 T pr = func_cas(a, cc, v);
421 bool success = pr == cc;
422 if (!success) {
412 DCHECK(IsLoadOrder(fmo));
413
414 MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(), kAccessWrite | kAccessAtomic);
415 if (LIKELY(mo == mo_relaxed && fmo == mo_relaxed)) {
416 T cc = *c;
417 T pr = func_cas(a, cc, v);
418 if (pr == cc)
419 return true;
423420 *c = pr;
424 mo = fmo;
421 return false;
425422 }
426
427 if (s) {
428 thr->fast_state.IncrementEpoch();
429 // Can't increment epoch w/o writing to the trace as well.
430 TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
431
423 SlotLocker locker(thr);
424 bool release = IsReleaseOrder(mo);
425 bool success;
426 {
427 auto s = ctx->metamap.GetSyncOrCreate(thr, pc, (uptr)a, false);
428 RWLock lock(&s->mtx, release);
429 T cc = *c;
430 T pr = func_cas(a, cc, v);
431 success = pr == cc;
432 if (!success) {
433 *c = pr;
434 mo = fmo;
435 }
432436 if (success && IsAcqRelOrder(mo))
433 AcquireReleaseImpl(thr, pc, &s->clock);
437 thr->clock.ReleaseAcquire(&s->clock);
434438 else if (success && IsReleaseOrder(mo))
435 ReleaseImpl(thr, pc, &s->clock);
439 thr->clock.Release(&s->clock);
436440 else if (IsAcquireOrder(mo))
437 AcquireImpl(thr, pc, &s->clock);
438
439 if (write_lock)
440 s->mtx.Unlock();
441 else
442 s->mtx.ReadUnlock();
441 thr->clock.Acquire(s->clock);
443442 }
444
443 if (success && release)
444 IncrementEpoch(thr);
445445 return success;
446446}
447447
......@@ -485,380 +485,356 @@ static morder convert_morder(morder mo) {
485485 return (morder)(mo & 0x7fff);
486486}
487487
488#define SCOPED_ATOMIC(func, ...) \
489 ThreadState *const thr = cur_thread(); \
490 if (UNLIKELY(thr->ignore_sync || thr->ignore_interceptors)) { \
491 ProcessPendingSignals(thr); \
492 return NoTsanAtomic##func(__VA_ARGS__); \
493 } \
494 const uptr callpc = (uptr)__builtin_return_address(0); \
495 uptr pc = StackTrace::GetCurrentPc(); \
496 mo = convert_morder(mo); \
497 ScopedAtomic sa(thr, callpc, a, mo, __func__); \
498 return Atomic##func(thr, pc, __VA_ARGS__); \
499/**/
500
501class ScopedAtomic {
502 public:
503 ScopedAtomic(ThreadState *thr, uptr pc, const volatile void *a,
504 morder mo, const char *func)
505 : thr_(thr) {
506 FuncEntry(thr_, pc);
507 DPrintf("#%d: %s(%p, %d)\n", thr_->tid, func, a, mo);
508 }
509 ~ScopedAtomic() {
510 ProcessPendingSignals(thr_);
511 FuncExit(thr_);
512 }
513 private:
514 ThreadState *thr_;
515};
488# define ATOMIC_IMPL(func, ...) \
489 ThreadState *const thr = cur_thread(); \
490 ProcessPendingSignals(thr); \
491 if (UNLIKELY(thr->ignore_sync || thr->ignore_interceptors)) \
492 return NoTsanAtomic##func(__VA_ARGS__); \
493 mo = convert_morder(mo); \
494 return Atomic##func(thr, GET_CALLER_PC(), __VA_ARGS__);
516495
517496extern "C" {
518497SANITIZER_INTERFACE_ATTRIBUTE
519498a8 __tsan_atomic8_load(const volatile a8 *a, morder mo) {
520 SCOPED_ATOMIC(Load, a, mo);
499 ATOMIC_IMPL(Load, a, mo);
521500}
522501
523502SANITIZER_INTERFACE_ATTRIBUTE
524503a16 __tsan_atomic16_load(const volatile a16 *a, morder mo) {
525 SCOPED_ATOMIC(Load, a, mo);
504 ATOMIC_IMPL(Load, a, mo);
526505}
527506
528507SANITIZER_INTERFACE_ATTRIBUTE
529508a32 __tsan_atomic32_load(const volatile a32 *a, morder mo) {
530 SCOPED_ATOMIC(Load, a, mo);
509 ATOMIC_IMPL(Load, a, mo);
531510}
532511
533512SANITIZER_INTERFACE_ATTRIBUTE
534513a64 __tsan_atomic64_load(const volatile a64 *a, morder mo) {
535 SCOPED_ATOMIC(Load, a, mo);
514 ATOMIC_IMPL(Load, a, mo);
536515}
537516
538517#if __TSAN_HAS_INT128
539518SANITIZER_INTERFACE_ATTRIBUTE
540519a128 __tsan_atomic128_load(const volatile a128 *a, morder mo) {
541 SCOPED_ATOMIC(Load, a, mo);
520 ATOMIC_IMPL(Load, a, mo);
542521}
543522#endif
544523
545524SANITIZER_INTERFACE_ATTRIBUTE
546525void __tsan_atomic8_store(volatile a8 *a, a8 v, morder mo) {
547 SCOPED_ATOMIC(Store, a, v, mo);
526 ATOMIC_IMPL(Store, a, v, mo);
548527}
549528
550529SANITIZER_INTERFACE_ATTRIBUTE
551530void __tsan_atomic16_store(volatile a16 *a, a16 v, morder mo) {
552 SCOPED_ATOMIC(Store, a, v, mo);
531 ATOMIC_IMPL(Store, a, v, mo);
553532}
554533
555534SANITIZER_INTERFACE_ATTRIBUTE
556535void __tsan_atomic32_store(volatile a32 *a, a32 v, morder mo) {
557 SCOPED_ATOMIC(Store, a, v, mo);
536 ATOMIC_IMPL(Store, a, v, mo);
558537}
559538
560539SANITIZER_INTERFACE_ATTRIBUTE
561540void __tsan_atomic64_store(volatile a64 *a, a64 v, morder mo) {
562 SCOPED_ATOMIC(Store, a, v, mo);
541 ATOMIC_IMPL(Store, a, v, mo);
563542}
564543
565544#if __TSAN_HAS_INT128
566545SANITIZER_INTERFACE_ATTRIBUTE
567546void __tsan_atomic128_store(volatile a128 *a, a128 v, morder mo) {
568 SCOPED_ATOMIC(Store, a, v, mo);
547 ATOMIC_IMPL(Store, a, v, mo);
569548}
570549#endif
571550
572551SANITIZER_INTERFACE_ATTRIBUTE
573552a8 __tsan_atomic8_exchange(volatile a8 *a, a8 v, morder mo) {
574 SCOPED_ATOMIC(Exchange, a, v, mo);
553 ATOMIC_IMPL(Exchange, a, v, mo);
575554}
576555
577556SANITIZER_INTERFACE_ATTRIBUTE
578557a16 __tsan_atomic16_exchange(volatile a16 *a, a16 v, morder mo) {
579 SCOPED_ATOMIC(Exchange, a, v, mo);
558 ATOMIC_IMPL(Exchange, a, v, mo);
580559}
581560
582561SANITIZER_INTERFACE_ATTRIBUTE
583562a32 __tsan_atomic32_exchange(volatile a32 *a, a32 v, morder mo) {
584 SCOPED_ATOMIC(Exchange, a, v, mo);
563 ATOMIC_IMPL(Exchange, a, v, mo);
585564}
586565
587566SANITIZER_INTERFACE_ATTRIBUTE
588567a64 __tsan_atomic64_exchange(volatile a64 *a, a64 v, morder mo) {
589 SCOPED_ATOMIC(Exchange, a, v, mo);
568 ATOMIC_IMPL(Exchange, a, v, mo);
590569}
591570
592571#if __TSAN_HAS_INT128
593572SANITIZER_INTERFACE_ATTRIBUTE
594573a128 __tsan_atomic128_exchange(volatile a128 *a, a128 v, morder mo) {
595 SCOPED_ATOMIC(Exchange, a, v, mo);
574 ATOMIC_IMPL(Exchange, a, v, mo);
596575}
597576#endif
598577
599578SANITIZER_INTERFACE_ATTRIBUTE
600579a8 __tsan_atomic8_fetch_add(volatile a8 *a, a8 v, morder mo) {
601 SCOPED_ATOMIC(FetchAdd, a, v, mo);
580 ATOMIC_IMPL(FetchAdd, a, v, mo);
602581}
603582
604583SANITIZER_INTERFACE_ATTRIBUTE
605584a16 __tsan_atomic16_fetch_add(volatile a16 *a, a16 v, morder mo) {
606 SCOPED_ATOMIC(FetchAdd, a, v, mo);
585 ATOMIC_IMPL(FetchAdd, a, v, mo);
607586}
608587
609588SANITIZER_INTERFACE_ATTRIBUTE
610589a32 __tsan_atomic32_fetch_add(volatile a32 *a, a32 v, morder mo) {
611 SCOPED_ATOMIC(FetchAdd, a, v, mo);
590 ATOMIC_IMPL(FetchAdd, a, v, mo);
612591}
613592
614593SANITIZER_INTERFACE_ATTRIBUTE
615594a64 __tsan_atomic64_fetch_add(volatile a64 *a, a64 v, morder mo) {
616 SCOPED_ATOMIC(FetchAdd, a, v, mo);
595 ATOMIC_IMPL(FetchAdd, a, v, mo);
617596}
618597
619598#if __TSAN_HAS_INT128
620599SANITIZER_INTERFACE_ATTRIBUTE
621600a128 __tsan_atomic128_fetch_add(volatile a128 *a, a128 v, morder mo) {
622 SCOPED_ATOMIC(FetchAdd, a, v, mo);
601 ATOMIC_IMPL(FetchAdd, a, v, mo);
623602}
624603#endif
625604
626605SANITIZER_INTERFACE_ATTRIBUTE
627606a8 __tsan_atomic8_fetch_sub(volatile a8 *a, a8 v, morder mo) {
628 SCOPED_ATOMIC(FetchSub, a, v, mo);
607 ATOMIC_IMPL(FetchSub, a, v, mo);
629608}
630609
631610SANITIZER_INTERFACE_ATTRIBUTE
632611a16 __tsan_atomic16_fetch_sub(volatile a16 *a, a16 v, morder mo) {
633 SCOPED_ATOMIC(FetchSub, a, v, mo);
612 ATOMIC_IMPL(FetchSub, a, v, mo);
634613}
635614
636615SANITIZER_INTERFACE_ATTRIBUTE
637616a32 __tsan_atomic32_fetch_sub(volatile a32 *a, a32 v, morder mo) {
638 SCOPED_ATOMIC(FetchSub, a, v, mo);
617 ATOMIC_IMPL(FetchSub, a, v, mo);
639618}
640619
641620SANITIZER_INTERFACE_ATTRIBUTE
642621a64 __tsan_atomic64_fetch_sub(volatile a64 *a, a64 v, morder mo) {
643 SCOPED_ATOMIC(FetchSub, a, v, mo);
622 ATOMIC_IMPL(FetchSub, a, v, mo);
644623}
645624
646625#if __TSAN_HAS_INT128
647626SANITIZER_INTERFACE_ATTRIBUTE
648627a128 __tsan_atomic128_fetch_sub(volatile a128 *a, a128 v, morder mo) {
649 SCOPED_ATOMIC(FetchSub, a, v, mo);
628 ATOMIC_IMPL(FetchSub, a, v, mo);
650629}
651630#endif
652631
653632SANITIZER_INTERFACE_ATTRIBUTE
654633a8 __tsan_atomic8_fetch_and(volatile a8 *a, a8 v, morder mo) {
655 SCOPED_ATOMIC(FetchAnd, a, v, mo);
634 ATOMIC_IMPL(FetchAnd, a, v, mo);
656635}
657636
658637SANITIZER_INTERFACE_ATTRIBUTE
659638a16 __tsan_atomic16_fetch_and(volatile a16 *a, a16 v, morder mo) {
660 SCOPED_ATOMIC(FetchAnd, a, v, mo);
639 ATOMIC_IMPL(FetchAnd, a, v, mo);
661640}
662641
663642SANITIZER_INTERFACE_ATTRIBUTE
664643a32 __tsan_atomic32_fetch_and(volatile a32 *a, a32 v, morder mo) {
665 SCOPED_ATOMIC(FetchAnd, a, v, mo);
644 ATOMIC_IMPL(FetchAnd, a, v, mo);
666645}
667646
668647SANITIZER_INTERFACE_ATTRIBUTE
669648a64 __tsan_atomic64_fetch_and(volatile a64 *a, a64 v, morder mo) {
670 SCOPED_ATOMIC(FetchAnd, a, v, mo);
649 ATOMIC_IMPL(FetchAnd, a, v, mo);
671650}
672651
673652#if __TSAN_HAS_INT128
674653SANITIZER_INTERFACE_ATTRIBUTE
675654a128 __tsan_atomic128_fetch_and(volatile a128 *a, a128 v, morder mo) {
676 SCOPED_ATOMIC(FetchAnd, a, v, mo);
655 ATOMIC_IMPL(FetchAnd, a, v, mo);
677656}
678657#endif
679658
680659SANITIZER_INTERFACE_ATTRIBUTE
681660a8 __tsan_atomic8_fetch_or(volatile a8 *a, a8 v, morder mo) {
682 SCOPED_ATOMIC(FetchOr, a, v, mo);
661 ATOMIC_IMPL(FetchOr, a, v, mo);
683662}
684663
685664SANITIZER_INTERFACE_ATTRIBUTE
686665a16 __tsan_atomic16_fetch_or(volatile a16 *a, a16 v, morder mo) {
687 SCOPED_ATOMIC(FetchOr, a, v, mo);
666 ATOMIC_IMPL(FetchOr, a, v, mo);
688667}
689668
690669SANITIZER_INTERFACE_ATTRIBUTE
691670a32 __tsan_atomic32_fetch_or(volatile a32 *a, a32 v, morder mo) {
692 SCOPED_ATOMIC(FetchOr, a, v, mo);
671 ATOMIC_IMPL(FetchOr, a, v, mo);
693672}
694673
695674SANITIZER_INTERFACE_ATTRIBUTE
696675a64 __tsan_atomic64_fetch_or(volatile a64 *a, a64 v, morder mo) {
697 SCOPED_ATOMIC(FetchOr, a, v, mo);
676 ATOMIC_IMPL(FetchOr, a, v, mo);
698677}
699678
700679#if __TSAN_HAS_INT128
701680SANITIZER_INTERFACE_ATTRIBUTE
702681a128 __tsan_atomic128_fetch_or(volatile a128 *a, a128 v, morder mo) {
703 SCOPED_ATOMIC(FetchOr, a, v, mo);
682 ATOMIC_IMPL(FetchOr, a, v, mo);
704683}
705684#endif
706685
707686SANITIZER_INTERFACE_ATTRIBUTE
708687a8 __tsan_atomic8_fetch_xor(volatile a8 *a, a8 v, morder mo) {
709 SCOPED_ATOMIC(FetchXor, a, v, mo);
688 ATOMIC_IMPL(FetchXor, a, v, mo);
710689}
711690
712691SANITIZER_INTERFACE_ATTRIBUTE
713692a16 __tsan_atomic16_fetch_xor(volatile a16 *a, a16 v, morder mo) {
714 SCOPED_ATOMIC(FetchXor, a, v, mo);
693 ATOMIC_IMPL(FetchXor, a, v, mo);
715694}
716695
717696SANITIZER_INTERFACE_ATTRIBUTE
718697a32 __tsan_atomic32_fetch_xor(volatile a32 *a, a32 v, morder mo) {
719 SCOPED_ATOMIC(FetchXor, a, v, mo);
698 ATOMIC_IMPL(FetchXor, a, v, mo);
720699}
721700
722701SANITIZER_INTERFACE_ATTRIBUTE
723702a64 __tsan_atomic64_fetch_xor(volatile a64 *a, a64 v, morder mo) {
724 SCOPED_ATOMIC(FetchXor, a, v, mo);
703 ATOMIC_IMPL(FetchXor, a, v, mo);
725704}
726705
727706#if __TSAN_HAS_INT128
728707SANITIZER_INTERFACE_ATTRIBUTE
729708a128 __tsan_atomic128_fetch_xor(volatile a128 *a, a128 v, morder mo) {
730 SCOPED_ATOMIC(FetchXor, a, v, mo);
709 ATOMIC_IMPL(FetchXor, a, v, mo);
731710}
732711#endif
733712
734713SANITIZER_INTERFACE_ATTRIBUTE
735714a8 __tsan_atomic8_fetch_nand(volatile a8 *a, a8 v, morder mo) {
736 SCOPED_ATOMIC(FetchNand, a, v, mo);
715 ATOMIC_IMPL(FetchNand, a, v, mo);
737716}
738717
739718SANITIZER_INTERFACE_ATTRIBUTE
740719a16 __tsan_atomic16_fetch_nand(volatile a16 *a, a16 v, morder mo) {
741 SCOPED_ATOMIC(FetchNand, a, v, mo);
720 ATOMIC_IMPL(FetchNand, a, v, mo);
742721}
743722
744723SANITIZER_INTERFACE_ATTRIBUTE
745724a32 __tsan_atomic32_fetch_nand(volatile a32 *a, a32 v, morder mo) {
746 SCOPED_ATOMIC(FetchNand, a, v, mo);
725 ATOMIC_IMPL(FetchNand, a, v, mo);
747726}
748727
749728SANITIZER_INTERFACE_ATTRIBUTE
750729a64 __tsan_atomic64_fetch_nand(volatile a64 *a, a64 v, morder mo) {
751 SCOPED_ATOMIC(FetchNand, a, v, mo);
730 ATOMIC_IMPL(FetchNand, a, v, mo);
752731}
753732
754733#if __TSAN_HAS_INT128
755734SANITIZER_INTERFACE_ATTRIBUTE
756735a128 __tsan_atomic128_fetch_nand(volatile a128 *a, a128 v, morder mo) {
757 SCOPED_ATOMIC(FetchNand, a, v, mo);
736 ATOMIC_IMPL(FetchNand, a, v, mo);
758737}
759738#endif
760739
761740SANITIZER_INTERFACE_ATTRIBUTE
762741int __tsan_atomic8_compare_exchange_strong(volatile a8 *a, a8 *c, a8 v,
763742 morder mo, morder fmo) {
764 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
743 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
765744}
766745
767746SANITIZER_INTERFACE_ATTRIBUTE
768747int __tsan_atomic16_compare_exchange_strong(volatile a16 *a, a16 *c, a16 v,
769748 morder mo, morder fmo) {
770 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
749 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
771750}
772751
773752SANITIZER_INTERFACE_ATTRIBUTE
774753int __tsan_atomic32_compare_exchange_strong(volatile a32 *a, a32 *c, a32 v,
775754 morder mo, morder fmo) {
776 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
755 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
777756}
778757
779758SANITIZER_INTERFACE_ATTRIBUTE
780759int __tsan_atomic64_compare_exchange_strong(volatile a64 *a, a64 *c, a64 v,
781760 morder mo, morder fmo) {
782 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
761 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
783762}
784763
785764#if __TSAN_HAS_INT128
786765SANITIZER_INTERFACE_ATTRIBUTE
787766int __tsan_atomic128_compare_exchange_strong(volatile a128 *a, a128 *c, a128 v,
788767 morder mo, morder fmo) {
789 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
768 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
790769}
791770#endif
792771
793772SANITIZER_INTERFACE_ATTRIBUTE
794773int __tsan_atomic8_compare_exchange_weak(volatile a8 *a, a8 *c, a8 v,
795774 morder mo, morder fmo) {
796 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
775 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
797776}
798777
799778SANITIZER_INTERFACE_ATTRIBUTE
800779int __tsan_atomic16_compare_exchange_weak(volatile a16 *a, a16 *c, a16 v,
801780 morder mo, morder fmo) {
802 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
781 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
803782}
804783
805784SANITIZER_INTERFACE_ATTRIBUTE
806785int __tsan_atomic32_compare_exchange_weak(volatile a32 *a, a32 *c, a32 v,
807786 morder mo, morder fmo) {
808 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
787 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
809788}
810789
811790SANITIZER_INTERFACE_ATTRIBUTE
812791int __tsan_atomic64_compare_exchange_weak(volatile a64 *a, a64 *c, a64 v,
813792 morder mo, morder fmo) {
814 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
793 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
815794}
816795
817796#if __TSAN_HAS_INT128
818797SANITIZER_INTERFACE_ATTRIBUTE
819798int __tsan_atomic128_compare_exchange_weak(volatile a128 *a, a128 *c, a128 v,
820799 morder mo, morder fmo) {
821 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
800 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
822801}
823802#endif
824803
825804SANITIZER_INTERFACE_ATTRIBUTE
826805a8 __tsan_atomic8_compare_exchange_val(volatile a8 *a, a8 c, a8 v,
827806 morder mo, morder fmo) {
828 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
807 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
829808}
830809
831810SANITIZER_INTERFACE_ATTRIBUTE
832811a16 __tsan_atomic16_compare_exchange_val(volatile a16 *a, a16 c, a16 v,
833812 morder mo, morder fmo) {
834 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
813 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
835814}
836815
837816SANITIZER_INTERFACE_ATTRIBUTE
838817a32 __tsan_atomic32_compare_exchange_val(volatile a32 *a, a32 c, a32 v,
839818 morder mo, morder fmo) {
840 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
819 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
841820}
842821
843822SANITIZER_INTERFACE_ATTRIBUTE
844823a64 __tsan_atomic64_compare_exchange_val(volatile a64 *a, a64 c, a64 v,
845824 morder mo, morder fmo) {
846 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
825 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
847826}
848827
849828#if __TSAN_HAS_INT128
850829SANITIZER_INTERFACE_ATTRIBUTE
851830a128 __tsan_atomic128_compare_exchange_val(volatile a128 *a, a128 c, a128 v,
852831 morder mo, morder fmo) {
853 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
832 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
854833}
855834#endif
856835
857836SANITIZER_INTERFACE_ATTRIBUTE
858void __tsan_atomic_thread_fence(morder mo) {
859 char* a = 0;
860 SCOPED_ATOMIC(Fence, mo);
861}
837void __tsan_atomic_thread_fence(morder mo) { ATOMIC_IMPL(Fence, mo); }
862838
863839SANITIZER_INTERFACE_ATTRIBUTE
864840void __tsan_atomic_signal_fence(morder mo) {
......@@ -869,25 +845,23 @@ void __tsan_atomic_signal_fence(morder mo) {
869845
870846// Go
871847
872#define ATOMIC(func, ...) \
873 if (thr->ignore_sync) { \
874 NoTsanAtomic##func(__VA_ARGS__); \
875 } else { \
876 FuncEntry(thr, cpc); \
848# define ATOMIC(func, ...) \
849 if (thr->ignore_sync) { \
850 NoTsanAtomic##func(__VA_ARGS__); \
851 } else { \
852 FuncEntry(thr, cpc); \
877853 Atomic##func(thr, pc, __VA_ARGS__); \
878 FuncExit(thr); \
879 } \
880/**/
881
882#define ATOMIC_RET(func, ret, ...) \
883 if (thr->ignore_sync) { \
884 (ret) = NoTsanAtomic##func(__VA_ARGS__); \
885 } else { \
886 FuncEntry(thr, cpc); \
854 FuncExit(thr); \
855 }
856
857# define ATOMIC_RET(func, ret, ...) \
858 if (thr->ignore_sync) { \
859 (ret) = NoTsanAtomic##func(__VA_ARGS__); \
860 } else { \
861 FuncEntry(thr, cpc); \
887862 (ret) = Atomic##func(thr, pc, __VA_ARGS__); \
888 FuncExit(thr); \
889 } \
890/**/
863 FuncExit(thr); \
864 }
891865
892866extern "C" {
893867SANITIZER_INTERFACE_ATTRIBUTE
lib/tsan/tsan_interface_inl.h deleted-133
......@@ -1,133 +0,0 @@
1//===-- tsan_interface_inl.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
13#include "tsan_interface.h"
14#include "tsan_rtl.h"
15#include "sanitizer_common/sanitizer_ptrauth.h"
16
17#define CALLERPC ((uptr)__builtin_return_address(0))
18
19using namespace __tsan;
20
21void __tsan_read1(void *addr) {
22 MemoryRead(cur_thread(), CALLERPC, (uptr)addr, kSizeLog1);
23}
24
25void __tsan_read2(void *addr) {
26 MemoryRead(cur_thread(), CALLERPC, (uptr)addr, kSizeLog2);
27}
28
29void __tsan_read4(void *addr) {
30 MemoryRead(cur_thread(), CALLERPC, (uptr)addr, kSizeLog4);
31}
32
33void __tsan_read8(void *addr) {
34 MemoryRead(cur_thread(), CALLERPC, (uptr)addr, kSizeLog8);
35}
36
37void __tsan_write1(void *addr) {
38 MemoryWrite(cur_thread(), CALLERPC, (uptr)addr, kSizeLog1);
39}
40
41void __tsan_write2(void *addr) {
42 MemoryWrite(cur_thread(), CALLERPC, (uptr)addr, kSizeLog2);
43}
44
45void __tsan_write4(void *addr) {
46 MemoryWrite(cur_thread(), CALLERPC, (uptr)addr, kSizeLog4);
47}
48
49void __tsan_write8(void *addr) {
50 MemoryWrite(cur_thread(), CALLERPC, (uptr)addr, kSizeLog8);
51}
52
53void __tsan_read1_pc(void *addr, void *pc) {
54 MemoryRead(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog1);
55}
56
57void __tsan_read2_pc(void *addr, void *pc) {
58 MemoryRead(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog2);
59}
60
61void __tsan_read4_pc(void *addr, void *pc) {
62 MemoryRead(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog4);
63}
64
65void __tsan_read8_pc(void *addr, void *pc) {
66 MemoryRead(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog8);
67}
68
69void __tsan_write1_pc(void *addr, void *pc) {
70 MemoryWrite(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog1);
71}
72
73void __tsan_write2_pc(void *addr, void *pc) {
74 MemoryWrite(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog2);
75}
76
77void __tsan_write4_pc(void *addr, void *pc) {
78 MemoryWrite(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog4);
79}
80
81void __tsan_write8_pc(void *addr, void *pc) {
82 MemoryWrite(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog8);
83}
84
85void __tsan_vptr_update(void **vptr_p, void *new_val) {
86 CHECK_EQ(sizeof(vptr_p), 8);
87 if (*vptr_p != new_val) {
88 ThreadState *thr = cur_thread();
89 thr->is_vptr_access = true;
90 MemoryWrite(thr, CALLERPC, (uptr)vptr_p, kSizeLog8);
91 thr->is_vptr_access = false;
92 }
93}
94
95void __tsan_vptr_read(void **vptr_p) {
96 CHECK_EQ(sizeof(vptr_p), 8);
97 ThreadState *thr = cur_thread();
98 thr->is_vptr_access = true;
99 MemoryRead(thr, CALLERPC, (uptr)vptr_p, kSizeLog8);
100 thr->is_vptr_access = false;
101}
102
103void __tsan_func_entry(void *pc) {
104 FuncEntry(cur_thread(), STRIP_PAC_PC(pc));
105}
106
107void __tsan_func_exit() {
108 FuncExit(cur_thread());
109}
110
111void __tsan_ignore_thread_begin() {
112 ThreadIgnoreBegin(cur_thread(), CALLERPC);
113}
114
115void __tsan_ignore_thread_end() {
116 ThreadIgnoreEnd(cur_thread(), CALLERPC);
117}
118
119void __tsan_read_range(void *addr, uptr size) {
120 MemoryAccessRange(cur_thread(), CALLERPC, (uptr)addr, size, false);
121}
122
123void __tsan_write_range(void *addr, uptr size) {
124 MemoryAccessRange(cur_thread(), CALLERPC, (uptr)addr, size, true);
125}
126
127void __tsan_read_range_pc(void *addr, uptr size, void *pc) {
128 MemoryAccessRange(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, size, false);
129}
130
131void __tsan_write_range_pc(void *addr, uptr size, void *pc) {
132 MemoryAccessRange(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, size, true);
133}
lib/tsan/tsan_interface_java.cpp+143-151
......@@ -34,52 +34,49 @@ struct JavaContext {
3434 }
3535};
3636
37class ScopedJavaFunc {
38 public:
39 ScopedJavaFunc(ThreadState *thr, uptr pc)
40 : thr_(thr) {
41 Initialize(thr_);
42 FuncEntry(thr, pc);
43 }
44
45 ~ScopedJavaFunc() {
46 FuncExit(thr_);
47 // FIXME(dvyukov): process pending signals.
48 }
49
50 private:
51 ThreadState *thr_;
52};
53
5437static u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1];
5538static JavaContext *jctx;
5639
40MBlock *JavaHeapBlock(uptr addr, uptr *start) {
41 if (!jctx || addr < jctx->heap_begin ||
42 addr >= jctx->heap_begin + jctx->heap_size)
43 return nullptr;
44 for (uptr p = RoundDown(addr, kMetaShadowCell); p >= jctx->heap_begin;
45 p -= kMetaShadowCell) {
46 MBlock *b = ctx->metamap.GetBlock(p);
47 if (!b)
48 continue;
49 if (p + b->siz <= addr)
50 return nullptr;
51 *start = p;
52 return b;
53 }
54 return nullptr;
55}
56
5757} // namespace __tsan
5858
59#define SCOPED_JAVA_FUNC(func) \
59#define JAVA_FUNC_ENTER(func) \
6060 ThreadState *thr = cur_thread(); \
61 const uptr caller_pc = GET_CALLER_PC(); \
62 const uptr pc = StackTrace::GetCurrentPc(); \
63 (void)pc; \
64 ScopedJavaFunc scoped(thr, caller_pc); \
65/**/
61 (void)thr;
6662
6763void __tsan_java_init(jptr heap_begin, jptr heap_size) {
68 SCOPED_JAVA_FUNC(__tsan_java_init);
69 DPrintf("#%d: java_init(%p, %p)\n", thr->tid, heap_begin, heap_size);
70 CHECK_EQ(jctx, 0);
71 CHECK_GT(heap_begin, 0);
72 CHECK_GT(heap_size, 0);
73 CHECK_EQ(heap_begin % kHeapAlignment, 0);
74 CHECK_EQ(heap_size % kHeapAlignment, 0);
75 CHECK_LT(heap_begin, heap_begin + heap_size);
64 JAVA_FUNC_ENTER(__tsan_java_init);
65 Initialize(thr);
66 DPrintf("#%d: java_init(0x%zx, 0x%zx)\n", thr->tid, heap_begin, heap_size);
67 DCHECK_EQ(jctx, 0);
68 DCHECK_GT(heap_begin, 0);
69 DCHECK_GT(heap_size, 0);
70 DCHECK_EQ(heap_begin % kHeapAlignment, 0);
71 DCHECK_EQ(heap_size % kHeapAlignment, 0);
72 DCHECK_LT(heap_begin, heap_begin + heap_size);
7673 jctx = new(jctx_buf) JavaContext(heap_begin, heap_size);
7774}
7875
7976int __tsan_java_fini() {
80 SCOPED_JAVA_FUNC(__tsan_java_fini);
77 JAVA_FUNC_ENTER(__tsan_java_fini);
8178 DPrintf("#%d: java_fini()\n", thr->tid);
82 CHECK_NE(jctx, 0);
79 DCHECK_NE(jctx, 0);
8380 // FIXME(dvyukov): this does not call atexit() callbacks.
8481 int status = Finalize(thr);
8582 DPrintf("#%d: java_fini() = %d\n", thr->tid, status);
......@@ -87,74 +84,65 @@ int __tsan_java_fini() {
8784}
8885
8986void __tsan_java_alloc(jptr ptr, jptr size) {
90 SCOPED_JAVA_FUNC(__tsan_java_alloc);
91 DPrintf("#%d: java_alloc(%p, %p)\n", thr->tid, ptr, size);
92 CHECK_NE(jctx, 0);
93 CHECK_NE(size, 0);
94 CHECK_EQ(ptr % kHeapAlignment, 0);
95 CHECK_EQ(size % kHeapAlignment, 0);
96 CHECK_GE(ptr, jctx->heap_begin);
97 CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
98
99 OnUserAlloc(thr, pc, ptr, size, false);
87 JAVA_FUNC_ENTER(__tsan_java_alloc);
88 DPrintf("#%d: java_alloc(0x%zx, 0x%zx)\n", thr->tid, ptr, size);
89 DCHECK_NE(jctx, 0);
90 DCHECK_NE(size, 0);
91 DCHECK_EQ(ptr % kHeapAlignment, 0);
92 DCHECK_EQ(size % kHeapAlignment, 0);
93 DCHECK_GE(ptr, jctx->heap_begin);
94 DCHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
95
96 OnUserAlloc(thr, 0, ptr, size, false);
10097}
10198
10299void __tsan_java_free(jptr ptr, jptr size) {
103 SCOPED_JAVA_FUNC(__tsan_java_free);
104 DPrintf("#%d: java_free(%p, %p)\n", thr->tid, ptr, size);
105 CHECK_NE(jctx, 0);
106 CHECK_NE(size, 0);
107 CHECK_EQ(ptr % kHeapAlignment, 0);
108 CHECK_EQ(size % kHeapAlignment, 0);
109 CHECK_GE(ptr, jctx->heap_begin);
110 CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
111
112 ctx->metamap.FreeRange(thr->proc(), ptr, size);
100 JAVA_FUNC_ENTER(__tsan_java_free);
101 DPrintf("#%d: java_free(0x%zx, 0x%zx)\n", thr->tid, ptr, size);
102 DCHECK_NE(jctx, 0);
103 DCHECK_NE(size, 0);
104 DCHECK_EQ(ptr % kHeapAlignment, 0);
105 DCHECK_EQ(size % kHeapAlignment, 0);
106 DCHECK_GE(ptr, jctx->heap_begin);
107 DCHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
108
109 ctx->metamap.FreeRange(thr->proc(), ptr, size, false);
113110}
114111
115112void __tsan_java_move(jptr src, jptr dst, jptr size) {
116 SCOPED_JAVA_FUNC(__tsan_java_move);
117 DPrintf("#%d: java_move(%p, %p, %p)\n", thr->tid, src, dst, size);
118 CHECK_NE(jctx, 0);
119 CHECK_NE(size, 0);
120 CHECK_EQ(src % kHeapAlignment, 0);
121 CHECK_EQ(dst % kHeapAlignment, 0);
122 CHECK_EQ(size % kHeapAlignment, 0);
123 CHECK_GE(src, jctx->heap_begin);
124 CHECK_LE(src + size, jctx->heap_begin + jctx->heap_size);
125 CHECK_GE(dst, jctx->heap_begin);
126 CHECK_LE(dst + size, jctx->heap_begin + jctx->heap_size);
127 CHECK_NE(dst, src);
128 CHECK_NE(size, 0);
113 JAVA_FUNC_ENTER(__tsan_java_move);
114 DPrintf("#%d: java_move(0x%zx, 0x%zx, 0x%zx)\n", thr->tid, src, dst, size);
115 DCHECK_NE(jctx, 0);
116 DCHECK_NE(size, 0);
117 DCHECK_EQ(src % kHeapAlignment, 0);
118 DCHECK_EQ(dst % kHeapAlignment, 0);
119 DCHECK_EQ(size % kHeapAlignment, 0);
120 DCHECK_GE(src, jctx->heap_begin);
121 DCHECK_LE(src + size, jctx->heap_begin + jctx->heap_size);
122 DCHECK_GE(dst, jctx->heap_begin);
123 DCHECK_LE(dst + size, jctx->heap_begin + jctx->heap_size);
124 DCHECK_NE(dst, src);
125 DCHECK_NE(size, 0);
129126
130127 // Assuming it's not running concurrently with threads that do
131128 // memory accesses and mutex operations (stop-the-world phase).
132129 ctx->metamap.MoveMemory(src, dst, size);
133130
134 // Move shadow.
135 u64 *s = (u64*)MemToShadow(src);
136 u64 *d = (u64*)MemToShadow(dst);
137 u64 *send = (u64*)MemToShadow(src + size);
138 uptr inc = 1;
139 if (dst > src) {
140 s = (u64*)MemToShadow(src + size) - 1;
141 d = (u64*)MemToShadow(dst + size) - 1;
142 send = (u64*)MemToShadow(src) - 1;
143 inc = -1;
144 }
145 for (; s != send; s += inc, d += inc) {
146 *d = *s;
147 *s = 0;
148 }
131 // Clear the destination shadow range.
132 // We used to move shadow from src to dst, but the trace format does not
133 // support that anymore as it contains addresses of accesses.
134 RawShadow *d = MemToShadow(dst);
135 RawShadow *dend = MemToShadow(dst + size);
136 ShadowSet(d, dend, Shadow::kEmpty);
149137}
150138
151139jptr __tsan_java_find(jptr *from_ptr, jptr to) {
152 SCOPED_JAVA_FUNC(__tsan_java_find);
153 DPrintf("#%d: java_find(&%p, %p)\n", *from_ptr, to);
154 CHECK_EQ((*from_ptr) % kHeapAlignment, 0);
155 CHECK_EQ(to % kHeapAlignment, 0);
156 CHECK_GE(*from_ptr, jctx->heap_begin);
157 CHECK_LE(to, jctx->heap_begin + jctx->heap_size);
140 JAVA_FUNC_ENTER(__tsan_java_find);
141 DPrintf("#%d: java_find(&0x%zx, 0x%zx)\n", thr->tid, *from_ptr, to);
142 DCHECK_EQ((*from_ptr) % kHeapAlignment, 0);
143 DCHECK_EQ(to % kHeapAlignment, 0);
144 DCHECK_GE(*from_ptr, jctx->heap_begin);
145 DCHECK_LE(to, jctx->heap_begin + jctx->heap_size);
158146 for (uptr from = *from_ptr; from < to; from += kHeapAlignment) {
159147 MBlock *b = ctx->metamap.GetBlock(from);
160148 if (b) {
......@@ -166,101 +154,105 @@ jptr __tsan_java_find(jptr *from_ptr, jptr to) {
166154}
167155
168156void __tsan_java_finalize() {
169 SCOPED_JAVA_FUNC(__tsan_java_finalize);
170 DPrintf("#%d: java_mutex_finalize()\n", thr->tid);
171 AcquireGlobal(thr, 0);
157 JAVA_FUNC_ENTER(__tsan_java_finalize);
158 DPrintf("#%d: java_finalize()\n", thr->tid);
159 AcquireGlobal(thr);
172160}
173161
174162void __tsan_java_mutex_lock(jptr addr) {
175 SCOPED_JAVA_FUNC(__tsan_java_mutex_lock);
176 DPrintf("#%d: java_mutex_lock(%p)\n", thr->tid, addr);
177 CHECK_NE(jctx, 0);
178 CHECK_GE(addr, jctx->heap_begin);
179 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
180
181 MutexPostLock(thr, pc, addr, MutexFlagLinkerInit | MutexFlagWriteReentrant |
182 MutexFlagDoPreLockOnPostLock);
163 JAVA_FUNC_ENTER(__tsan_java_mutex_lock);
164 DPrintf("#%d: java_mutex_lock(0x%zx)\n", thr->tid, addr);
165 DCHECK_NE(jctx, 0);
166 DCHECK_GE(addr, jctx->heap_begin);
167 DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
168
169 MutexPostLock(thr, 0, addr,
170 MutexFlagLinkerInit | MutexFlagWriteReentrant |
171 MutexFlagDoPreLockOnPostLock);
183172}
184173
185174void __tsan_java_mutex_unlock(jptr addr) {
186 SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock);
187 DPrintf("#%d: java_mutex_unlock(%p)\n", thr->tid, addr);
188 CHECK_NE(jctx, 0);
189 CHECK_GE(addr, jctx->heap_begin);
190 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
175 JAVA_FUNC_ENTER(__tsan_java_mutex_unlock);
176 DPrintf("#%d: java_mutex_unlock(0x%zx)\n", thr->tid, addr);
177 DCHECK_NE(jctx, 0);
178 DCHECK_GE(addr, jctx->heap_begin);
179 DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
191180
192 MutexUnlock(thr, pc, addr);
181 MutexUnlock(thr, 0, addr);
193182}
194183
195184void __tsan_java_mutex_read_lock(jptr addr) {
196 SCOPED_JAVA_FUNC(__tsan_java_mutex_read_lock);
197 DPrintf("#%d: java_mutex_read_lock(%p)\n", thr->tid, addr);
198 CHECK_NE(jctx, 0);
199 CHECK_GE(addr, jctx->heap_begin);
200 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
201
202 MutexPostReadLock(thr, pc, addr, MutexFlagLinkerInit |
203 MutexFlagWriteReentrant | MutexFlagDoPreLockOnPostLock);
185 JAVA_FUNC_ENTER(__tsan_java_mutex_read_lock);
186 DPrintf("#%d: java_mutex_read_lock(0x%zx)\n", thr->tid, addr);
187 DCHECK_NE(jctx, 0);
188 DCHECK_GE(addr, jctx->heap_begin);
189 DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
190
191 MutexPostReadLock(thr, 0, addr,
192 MutexFlagLinkerInit | MutexFlagWriteReentrant |
193 MutexFlagDoPreLockOnPostLock);
204194}
205195
206196void __tsan_java_mutex_read_unlock(jptr addr) {
207 SCOPED_JAVA_FUNC(__tsan_java_mutex_read_unlock);
208 DPrintf("#%d: java_mutex_read_unlock(%p)\n", thr->tid, addr);
209 CHECK_NE(jctx, 0);
210 CHECK_GE(addr, jctx->heap_begin);
211 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
197 JAVA_FUNC_ENTER(__tsan_java_mutex_read_unlock);
198 DPrintf("#%d: java_mutex_read_unlock(0x%zx)\n", thr->tid, addr);
199 DCHECK_NE(jctx, 0);
200 DCHECK_GE(addr, jctx->heap_begin);
201 DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
212202
213 MutexReadUnlock(thr, pc, addr);
203 MutexReadUnlock(thr, 0, addr);
214204}
215205
216206void __tsan_java_mutex_lock_rec(jptr addr, int rec) {
217 SCOPED_JAVA_FUNC(__tsan_java_mutex_lock_rec);
218 DPrintf("#%d: java_mutex_lock_rec(%p, %d)\n", thr->tid, addr, rec);
219 CHECK_NE(jctx, 0);
220 CHECK_GE(addr, jctx->heap_begin);
221 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
222 CHECK_GT(rec, 0);
223
224 MutexPostLock(thr, pc, addr, MutexFlagLinkerInit | MutexFlagWriteReentrant |
225 MutexFlagDoPreLockOnPostLock | MutexFlagRecursiveLock, rec);
207 JAVA_FUNC_ENTER(__tsan_java_mutex_lock_rec);
208 DPrintf("#%d: java_mutex_lock_rec(0x%zx, %d)\n", thr->tid, addr, rec);
209 DCHECK_NE(jctx, 0);
210 DCHECK_GE(addr, jctx->heap_begin);
211 DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
212 DCHECK_GT(rec, 0);
213
214 MutexPostLock(thr, 0, addr,
215 MutexFlagLinkerInit | MutexFlagWriteReentrant |
216 MutexFlagDoPreLockOnPostLock | MutexFlagRecursiveLock,
217 rec);
226218}
227219
228220int __tsan_java_mutex_unlock_rec(jptr addr) {
229 SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock_rec);
230 DPrintf("#%d: java_mutex_unlock_rec(%p)\n", thr->tid, addr);
231 CHECK_NE(jctx, 0);
232 CHECK_GE(addr, jctx->heap_begin);
233 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
221 JAVA_FUNC_ENTER(__tsan_java_mutex_unlock_rec);
222 DPrintf("#%d: java_mutex_unlock_rec(0x%zx)\n", thr->tid, addr);
223 DCHECK_NE(jctx, 0);
224 DCHECK_GE(addr, jctx->heap_begin);
225 DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
234226
235 return MutexUnlock(thr, pc, addr, MutexFlagRecursiveUnlock);
227 return MutexUnlock(thr, 0, addr, MutexFlagRecursiveUnlock);
236228}
237229
238230void __tsan_java_acquire(jptr addr) {
239 SCOPED_JAVA_FUNC(__tsan_java_acquire);
240 DPrintf("#%d: java_acquire(%p)\n", thr->tid, addr);
241 CHECK_NE(jctx, 0);
242 CHECK_GE(addr, jctx->heap_begin);
243 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
231 JAVA_FUNC_ENTER(__tsan_java_acquire);
232 DPrintf("#%d: java_acquire(0x%zx)\n", thr->tid, addr);
233 DCHECK_NE(jctx, 0);
234 DCHECK_GE(addr, jctx->heap_begin);
235 DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
244236
245 Acquire(thr, caller_pc, addr);
237 Acquire(thr, 0, addr);
246238}
247239
248240void __tsan_java_release(jptr addr) {
249 SCOPED_JAVA_FUNC(__tsan_java_release);
250 DPrintf("#%d: java_release(%p)\n", thr->tid, addr);
251 CHECK_NE(jctx, 0);
252 CHECK_GE(addr, jctx->heap_begin);
253 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
241 JAVA_FUNC_ENTER(__tsan_java_release);
242 DPrintf("#%d: java_release(0x%zx)\n", thr->tid, addr);
243 DCHECK_NE(jctx, 0);
244 DCHECK_GE(addr, jctx->heap_begin);
245 DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
254246
255 Release(thr, caller_pc, addr);
247 Release(thr, 0, addr);
256248}
257249
258250void __tsan_java_release_store(jptr addr) {
259 SCOPED_JAVA_FUNC(__tsan_java_release);
260 DPrintf("#%d: java_release_store(%p)\n", thr->tid, addr);
261 CHECK_NE(jctx, 0);
262 CHECK_GE(addr, jctx->heap_begin);
263 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
251 JAVA_FUNC_ENTER(__tsan_java_release);
252 DPrintf("#%d: java_release_store(0x%zx)\n", thr->tid, addr);
253 DCHECK_NE(jctx, 0);
254 DCHECK_GE(addr, jctx->heap_begin);
255 DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
264256
265 ReleaseStore(thr, caller_pc, addr);
257 ReleaseStore(thr, 0, addr);
266258}
lib/tsan/tsan_malloc_mac.cpp+23-7
......@@ -12,11 +12,12 @@
1212//===----------------------------------------------------------------------===//
1313
1414#include "sanitizer_common/sanitizer_platform.h"
15#if SANITIZER_MAC
15#if SANITIZER_APPLE
1616
1717#include "sanitizer_common/sanitizer_errno.h"
1818#include "tsan_interceptors.h"
1919#include "tsan_stack_trace.h"
20#include "tsan_mman.h"
2021
2122using namespace __tsan;
2223#define COMMON_MALLOC_ZONE_NAME "tsan"
......@@ -29,16 +30,30 @@ using namespace __tsan;
2930 user_memalign(cur_thread(), StackTrace::GetCurrentPc(), alignment, size)
3031#define COMMON_MALLOC_MALLOC(size) \
3132 if (in_symbolizer()) return InternalAlloc(size); \
32 SCOPED_INTERCEPTOR_RAW(malloc, size); \
33 void *p = user_alloc(thr, pc, size)
33 void *p = 0; \
34 { \
35 SCOPED_INTERCEPTOR_RAW(malloc, size); \
36 p = user_alloc(thr, pc, size); \
37 } \
38 invoke_malloc_hook(p, size)
3439#define COMMON_MALLOC_REALLOC(ptr, size) \
3540 if (in_symbolizer()) return InternalRealloc(ptr, size); \
36 SCOPED_INTERCEPTOR_RAW(realloc, ptr, size); \
37 void *p = user_realloc(thr, pc, ptr, size)
41 if (ptr) \
42 invoke_free_hook(ptr); \
43 void *p = 0; \
44 { \
45 SCOPED_INTERCEPTOR_RAW(realloc, ptr, size); \
46 p = user_realloc(thr, pc, ptr, size); \
47 } \
48 invoke_malloc_hook(p, size)
3849#define COMMON_MALLOC_CALLOC(count, size) \
3950 if (in_symbolizer()) return InternalCalloc(count, size); \
40 SCOPED_INTERCEPTOR_RAW(calloc, size, count); \
41 void *p = user_calloc(thr, pc, size, count)
51 void *p = 0; \
52 { \
53 SCOPED_INTERCEPTOR_RAW(calloc, size, count); \
54 p = user_calloc(thr, pc, size, count); \
55 } \
56 invoke_malloc_hook(p, size * count)
4257#define COMMON_MALLOC_POSIX_MEMALIGN(memptr, alignment, size) \
4358 if (in_symbolizer()) { \
4459 void *p = InternalAlloc(size, nullptr, alignment); \
......@@ -55,6 +70,7 @@ using namespace __tsan;
5570 void *p = user_valloc(thr, pc, size)
5671#define COMMON_MALLOC_FREE(ptr) \
5772 if (in_symbolizer()) return InternalFree(ptr); \
73 invoke_free_hook(ptr); \
5874 SCOPED_INTERCEPTOR_RAW(free, ptr); \
5975 user_free(thr, pc, ptr)
6076#define COMMON_MALLOC_SIZE(ptr) uptr size = user_alloc_usable_size(ptr);
lib/tsan/tsan_mman.cpp+109-26
......@@ -15,27 +15,18 @@
1515#include "sanitizer_common/sanitizer_common.h"
1616#include "sanitizer_common/sanitizer_errno.h"
1717#include "sanitizer_common/sanitizer_placement_new.h"
18#include "tsan_interface.h"
1819#include "tsan_mman.h"
1920#include "tsan_rtl.h"
2021#include "tsan_report.h"
2122#include "tsan_flags.h"
2223
23// May be overriden by front-end.
24SANITIZER_WEAK_DEFAULT_IMPL
25void __sanitizer_malloc_hook(void *ptr, uptr size) {
26 (void)ptr;
27 (void)size;
28}
29
30SANITIZER_WEAK_DEFAULT_IMPL
31void __sanitizer_free_hook(void *ptr) {
32 (void)ptr;
33}
34
3524namespace __tsan {
3625
3726struct MapUnmapCallback {
3827 void OnMap(uptr p, uptr size) const { }
28 void OnMapSecondary(uptr p, uptr size, uptr user_begin,
29 uptr user_size) const {};
3930 void OnUnmap(uptr p, uptr size) const {
4031 // We are about to unmap a chunk of user memory.
4132 // Mark the corresponding shadow memory as not needed.
......@@ -69,8 +60,17 @@ Allocator *allocator() {
6960struct GlobalProc {
7061 Mutex mtx;
7162 Processor *proc;
72
73 GlobalProc() : mtx(MutexTypeGlobalProc), proc(ProcCreate()) {}
63 // This mutex represents the internal allocator combined for
64 // the purposes of deadlock detection. The internal allocator
65 // uses multiple mutexes, moreover they are locked only occasionally
66 // and they are spin mutexes which don't support deadlock detection.
67 // So we use this fake mutex to serve as a substitute for these mutexes.
68 CheckedMutex internal_alloc_mtx;
69
70 GlobalProc()
71 : mtx(MutexTypeGlobalProc),
72 proc(ProcCreate()),
73 internal_alloc_mtx(MutexTypeInternalAlloc) {}
7474};
7575
7676static char global_proc_placeholder[sizeof(GlobalProc)] ALIGNED(64);
......@@ -78,6 +78,11 @@ GlobalProc *global_proc() {
7878 return reinterpret_cast<GlobalProc*>(&global_proc_placeholder);
7979}
8080
81static void InternalAllocAccess() {
82 global_proc()->internal_alloc_mtx.Lock();
83 global_proc()->internal_alloc_mtx.Unlock();
84}
85
8186ScopedGlobalProcessor::ScopedGlobalProcessor() {
8287 GlobalProc *gp = global_proc();
8388 ThreadState *thr = cur_thread();
......@@ -110,6 +115,24 @@ ScopedGlobalProcessor::~ScopedGlobalProcessor() {
110115 gp->mtx.Unlock();
111116}
112117
118void AllocatorLock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
119 global_proc()->internal_alloc_mtx.Lock();
120 InternalAllocatorLock();
121}
122
123void AllocatorUnlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
124 InternalAllocatorUnlock();
125 global_proc()->internal_alloc_mtx.Unlock();
126}
127
128void GlobalProcessorLock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
129 global_proc()->mtx.Lock();
130}
131
132void GlobalProcessorUnlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
133 global_proc()->mtx.Unlock();
134}
135
113136static constexpr uptr kMaxAllowedMallocSize = 1ull << 40;
114137static uptr max_user_defined_malloc_size;
115138
......@@ -148,7 +171,7 @@ static void SignalUnsafeCall(ThreadState *thr, uptr pc) {
148171 ObtainCurrentStack(thr, pc, &stack);
149172 if (IsFiredSuppression(ctx, ReportTypeSignalUnsafe, stack))
150173 return;
151 ThreadRegistryLock l(ctx->thread_registry);
174 ThreadRegistryLock l(&ctx->thread_registry);
152175 ScopedReport rep(ReportTypeSignalUnsafe);
153176 rep.AddStack(stack, true);
154177 OutputReport(thr, rep);
......@@ -166,6 +189,12 @@ void *user_alloc_internal(ThreadState *thr, uptr pc, uptr sz, uptr align,
166189 GET_STACK_TRACE_FATAL(thr, pc);
167190 ReportAllocationSizeTooBig(sz, malloc_limit, &stack);
168191 }
192 if (UNLIKELY(IsRssLimitExceeded())) {
193 if (AllocatorMayReturnNull())
194 return nullptr;
195 GET_STACK_TRACE_FATAL(thr, pc);
196 ReportRssLimitExceeded(&stack);
197 }
169198 void *p = allocator()->Allocate(&thr->proc()->alloc_cache, sz, align);
170199 if (UNLIKELY(!p)) {
171200 SetAllocatorOutOfMemory();
......@@ -218,9 +247,18 @@ void *user_reallocarray(ThreadState *thr, uptr pc, void *p, uptr size, uptr n) {
218247}
219248
220249void OnUserAlloc(ThreadState *thr, uptr pc, uptr p, uptr sz, bool write) {
221 DPrintf("#%d: alloc(%zu) = %p\n", thr->tid, sz, p);
250 DPrintf("#%d: alloc(%zu) = 0x%zx\n", thr->tid, sz, p);
251 // Note: this can run before thread initialization/after finalization.
252 // As a result this is not necessarily synchronized with DoReset,
253 // which iterates over and resets all sync objects,
254 // but it is fine to create new MBlocks in this context.
222255 ctx->metamap.AllocBlock(thr, pc, p, sz);
223 if (write && thr->ignore_reads_and_writes == 0)
256 // If this runs before thread initialization/after finalization
257 // and we don't have trace initialized, we can't imitate writes.
258 // In such case just reset the shadow range, it is fine since
259 // it affects only a small fraction of special objects.
260 if (write && thr->ignore_reads_and_writes == 0 &&
261 atomic_load_relaxed(&thr->trace_pos))
224262 MemoryRangeImitateWrite(thr, pc, (uptr)p, sz);
225263 else
226264 MemoryResetRange(thr, pc, (uptr)p, sz);
......@@ -228,8 +266,15 @@ void OnUserAlloc(ThreadState *thr, uptr pc, uptr p, uptr sz, bool write) {
228266
229267void OnUserFree(ThreadState *thr, uptr pc, uptr p, bool write) {
230268 CHECK_NE(p, (void*)0);
231 uptr sz = ctx->metamap.FreeBlock(thr->proc(), p);
232 DPrintf("#%d: free(%p, %zu)\n", thr->tid, p, sz);
269 if (!thr->slot) {
270 // Very early/late in thread lifetime, or during fork.
271 UNUSED uptr sz = ctx->metamap.FreeBlock(thr->proc(), p, false);
272 DPrintf("#%d: free(0x%zx, %zu) (no slot)\n", thr->tid, p, sz);
273 return;
274 }
275 SlotLocker locker(thr);
276 uptr sz = ctx->metamap.FreeBlock(thr->proc(), p, true);
277 DPrintf("#%d: free(0x%zx, %zu)\n", thr->tid, p, sz);
233278 if (write && thr->ignore_reads_and_writes == 0)
234279 MemoryRangeFreed(thr, pc, (uptr)p, sz);
235280}
......@@ -309,8 +354,22 @@ void *user_pvalloc(ThreadState *thr, uptr pc, uptr sz) {
309354 return SetErrnoOnNull(user_alloc_internal(thr, pc, sz, PageSize));
310355}
311356
357static const void *user_alloc_begin(const void *p) {
358 if (p == nullptr || !IsAppMem((uptr)p))
359 return nullptr;
360 void *beg = allocator()->GetBlockBegin(p);
361 if (!beg)
362 return nullptr;
363
364 MBlock *b = ctx->metamap.GetBlock((uptr)beg);
365 if (!b)
366 return nullptr; // Not a valid pointer.
367
368 return (const void *)beg;
369}
370
312371uptr user_alloc_usable_size(const void *p) {
313 if (p == 0)
372 if (p == 0 || !IsAppMem((uptr)p))
314373 return 0;
315374 MBlock *b = ctx->metamap.GetBlock((uptr)p);
316375 if (!b)
......@@ -320,11 +379,21 @@ uptr user_alloc_usable_size(const void *p) {
320379 return b->siz;
321380}
322381
382uptr user_alloc_usable_size_fast(const void *p) {
383 MBlock *b = ctx->metamap.GetBlock((uptr)p);
384 // Static objects may have malloc'd before tsan completes
385 // initialization, and may believe returned ptrs to be valid.
386 if (!b)
387 return 0; // Not a valid pointer.
388 if (b->siz == 0)
389 return 1; // Zero-sized allocations are actually 1 byte.
390 return b->siz;
391}
392
323393void invoke_malloc_hook(void *ptr, uptr size) {
324394 ThreadState *thr = cur_thread();
325395 if (ctx == 0 || !ctx->initialized || thr->ignore_interceptors)
326396 return;
327 __sanitizer_malloc_hook(ptr, size);
328397 RunMallocHooks(ptr, size);
329398}
330399
......@@ -332,25 +401,26 @@ void invoke_free_hook(void *ptr) {
332401 ThreadState *thr = cur_thread();
333402 if (ctx == 0 || !ctx->initialized || thr->ignore_interceptors)
334403 return;
335 __sanitizer_free_hook(ptr);
336404 RunFreeHooks(ptr);
337405}
338406
339void *internal_alloc(MBlockType typ, uptr sz) {
407void *Alloc(uptr sz) {
340408 ThreadState *thr = cur_thread();
341409 if (thr->nomalloc) {
342410 thr->nomalloc = 0; // CHECK calls internal_malloc().
343411 CHECK(0);
344412 }
413 InternalAllocAccess();
345414 return InternalAlloc(sz, &thr->proc()->internal_alloc_cache);
346415}
347416
348void internal_free(void *p) {
417void FreeImpl(void *p) {
349418 ThreadState *thr = cur_thread();
350419 if (thr->nomalloc) {
351420 thr->nomalloc = 0; // CHECK calls internal_malloc().
352421 CHECK(0);
353422 }
423 InternalAllocAccess();
354424 InternalFree(p, &thr->proc()->internal_alloc_cache);
355425}
356426
......@@ -387,14 +457,27 @@ int __sanitizer_get_ownership(const void *p) {
387457 return allocator()->GetBlockBegin(p) != 0;
388458}
389459
460const void *__sanitizer_get_allocated_begin(const void *p) {
461 return user_alloc_begin(p);
462}
463
390464uptr __sanitizer_get_allocated_size(const void *p) {
391465 return user_alloc_usable_size(p);
392466}
393467
468uptr __sanitizer_get_allocated_size_fast(const void *p) {
469 DCHECK_EQ(p, __sanitizer_get_allocated_begin(p));
470 uptr ret = user_alloc_usable_size_fast(p);
471 DCHECK_EQ(ret, __sanitizer_get_allocated_size(p));
472 return ret;
473}
474
475void __sanitizer_purge_allocator() {
476 allocator()->ForceReleaseToOS();
477}
478
394479void __tsan_on_thread_idle() {
395480 ThreadState *thr = cur_thread();
396 thr->clock.ResetCached(&thr->proc()->clock_cache);
397 thr->last_sleep_clock.ResetCached(&thr->proc()->clock_cache);
398481 allocator()->SwallowCache(&thr->proc()->alloc_cache);
399482 internal_allocator()->SwallowCache(&thr->proc()->internal_alloc_cache);
400483 ctx->metamap.OnProcIdle(thr->proc());
lib/tsan/tsan_mman.h+22-31
......@@ -24,6 +24,10 @@ void ReplaceSystemMalloc();
2424void AllocatorProcStart(Processor *proc);
2525void AllocatorProcFinish(Processor *proc);
2626void AllocatorPrintStats();
27void AllocatorLock();
28void AllocatorUnlock();
29void GlobalProcessorLock();
30void GlobalProcessorUnlock();
2731
2832// For user allocations.
2933void *user_alloc_internal(ThreadState *thr, uptr pc, uptr sz,
......@@ -47,42 +51,29 @@ uptr user_alloc_usable_size(const void *p);
4751void invoke_malloc_hook(void *ptr, uptr size);
4852void invoke_free_hook(void *ptr);
4953
50enum MBlockType {
51 MBlockScopedBuf,
52 MBlockString,
53 MBlockStackTrace,
54 MBlockShadowStack,
55 MBlockSync,
56 MBlockClock,
57 MBlockThreadContex,
58 MBlockDeadInfo,
59 MBlockRacyStacks,
60 MBlockRacyAddresses,
61 MBlockAtExit,
62 MBlockFlag,
63 MBlockReport,
64 MBlockReportMop,
65 MBlockReportThread,
66 MBlockReportMutex,
67 MBlockReportLoc,
68 MBlockReportStack,
69 MBlockSuppression,
70 MBlockExpectRace,
71 MBlockSignal,
72 MBlockJmpBuf,
54// For internal data structures.
55void *Alloc(uptr sz);
56void FreeImpl(void *p);
7357
74 // This must be the last.
75 MBlockTypeCount
76};
58template <typename T, typename... Args>
59T *New(Args &&...args) {
60 return new (Alloc(sizeof(T))) T(static_cast<Args &&>(args)...);
61}
7762
78// For internal data structures.
79void *internal_alloc(MBlockType typ, uptr sz);
80void internal_free(void *p);
63template <typename T>
64void Free(T *&p) {
65 if (p == nullptr)
66 return;
67 FreeImpl(p);
68 p = nullptr;
69}
8170
8271template <typename T>
83void DestroyAndFree(T *p) {
72void DestroyAndFree(T *&p) {
73 if (p == nullptr)
74 return;
8475 p->~T();
85 internal_free(p);
76 Free(p);
8677}
8778
8879} // namespace __tsan
lib/tsan/tsan_mutexset.cpp+20-28
......@@ -10,66 +10,55 @@
1010//
1111//===----------------------------------------------------------------------===//
1212#include "tsan_mutexset.h"
13
14#include "sanitizer_common/sanitizer_placement_new.h"
1315#include "tsan_rtl.h"
1416
1517namespace __tsan {
1618
17const uptr MutexSet::kMaxSize;
18
1919MutexSet::MutexSet() {
20 size_ = 0;
21 internal_memset(&descs_, 0, sizeof(descs_));
2220}
2321
24void MutexSet::Add(u64 id, bool write, u64 epoch) {
22void MutexSet::Reset() { internal_memset(this, 0, sizeof(*this)); }
23
24void MutexSet::AddAddr(uptr addr, StackID stack_id, bool write) {
2525 // Look up existing mutex with the same id.
2626 for (uptr i = 0; i < size_; i++) {
27 if (descs_[i].id == id) {
27 if (descs_[i].addr == addr) {
2828 descs_[i].count++;
29 descs_[i].epoch = epoch;
29 descs_[i].seq = seq_++;
3030 return;
3131 }
3232 }
3333 // On overflow, find the oldest mutex and drop it.
3434 if (size_ == kMaxSize) {
35 u64 minepoch = (u64)-1;
36 u64 mini = (u64)-1;
35 uptr min = 0;
3736 for (uptr i = 0; i < size_; i++) {
38 if (descs_[i].epoch < minepoch) {
39 minepoch = descs_[i].epoch;
40 mini = i;
41 }
37 if (descs_[i].seq < descs_[min].seq)
38 min = i;
4239 }
43 RemovePos(mini);
40 RemovePos(min);
4441 CHECK_EQ(size_, kMaxSize - 1);
4542 }
4643 // Add new mutex descriptor.
47 descs_[size_].id = id;
44 descs_[size_].addr = addr;
45 descs_[size_].stack_id = stack_id;
4846 descs_[size_].write = write;
49 descs_[size_].epoch = epoch;
47 descs_[size_].seq = seq_++;
5048 descs_[size_].count = 1;
5149 size_++;
5250}
5351
54void MutexSet::Del(u64 id, bool write) {
52void MutexSet::DelAddr(uptr addr, bool destroy) {
5553 for (uptr i = 0; i < size_; i++) {
56 if (descs_[i].id == id) {
57 if (--descs_[i].count == 0)
54 if (descs_[i].addr == addr) {
55 if (destroy || --descs_[i].count == 0)
5856 RemovePos(i);
5957 return;
6058 }
6159 }
6260}
6361
64void MutexSet::Remove(u64 id) {
65 for (uptr i = 0; i < size_; i++) {
66 if (descs_[i].id == id) {
67 RemovePos(i);
68 return;
69 }
70 }
71}
72
7362void MutexSet::RemovePos(uptr i) {
7463 CHECK_LT(i, size_);
7564 descs_[i] = descs_[size_ - 1];
......@@ -85,4 +74,7 @@ MutexSet::Desc MutexSet::Get(uptr i) const {
8574 return descs_[i];
8675}
8776
77DynamicMutexSet::DynamicMutexSet() : ptr_(New<MutexSet>()) {}
78DynamicMutexSet::~DynamicMutexSet() { DestroyAndFree(ptr_); }
79
8880} // namespace __tsan
lib/tsan/tsan_mutexset.h+41-19
......@@ -21,34 +21,55 @@ class MutexSet {
2121 public:
2222 // Holds limited number of mutexes.
2323 // The oldest mutexes are discarded on overflow.
24 static const uptr kMaxSize = 16;
24 static constexpr uptr kMaxSize = 16;
2525 struct Desc {
26 u64 id;
27 u64 epoch;
28 int count;
26 uptr addr;
27 StackID stack_id;
28 u32 seq;
29 u32 count;
2930 bool write;
31
32 Desc() { internal_memset(this, 0, sizeof(*this)); }
33 Desc(const Desc& other) { *this = other; }
34 Desc& operator=(const MutexSet::Desc& other) {
35 internal_memcpy(this, &other, sizeof(*this));
36 return *this;
37 }
3038 };
3139
3240 MutexSet();
33 // The 'id' is obtained from SyncVar::GetId().
34 void Add(u64 id, bool write, u64 epoch);
35 void Del(u64 id, bool write);
36 void Remove(u64 id); // Removes the mutex completely (if it's destroyed).
41 void Reset();
42 void AddAddr(uptr addr, StackID stack_id, bool write);
43 void DelAddr(uptr addr, bool destroy = false);
3744 uptr Size() const;
3845 Desc Get(uptr i) const;
3946
40 void operator=(const MutexSet &other) {
41 internal_memcpy(this, &other, sizeof(*this));
42 }
43
4447 private:
4548#if !SANITIZER_GO
46 uptr size_;
49 u32 seq_ = 0;
50 uptr size_ = 0;
4751 Desc descs_[kMaxSize];
48#endif
4952
5053 void RemovePos(uptr i);
51 MutexSet(const MutexSet&);
54#endif
55};
56
57// MutexSet is too large to live on stack.
58// DynamicMutexSet can be use used to create local MutexSet's.
59class DynamicMutexSet {
60 public:
61 DynamicMutexSet();
62 ~DynamicMutexSet();
63 MutexSet* operator->() { return ptr_; }
64 operator MutexSet*() { return ptr_; }
65 DynamicMutexSet(const DynamicMutexSet&) = delete;
66 DynamicMutexSet& operator=(const DynamicMutexSet&) = delete;
67
68 private:
69 MutexSet* ptr_;
70#if SANITIZER_GO
71 MutexSet set_;
72#endif
5273};
5374
5475// Go does not have mutexes, so do not spend memory and time.
......@@ -56,12 +77,13 @@ class MutexSet {
5677// in different goroutine).
5778#if SANITIZER_GO
5879MutexSet::MutexSet() {}
59void MutexSet::Add(u64 id, bool write, u64 epoch) {}
60void MutexSet::Del(u64 id, bool write) {}
61void MutexSet::Remove(u64 id) {}
62void MutexSet::RemovePos(uptr i) {}
80void MutexSet::Reset() {}
81void MutexSet::AddAddr(uptr addr, StackID stack_id, bool write) {}
82void MutexSet::DelAddr(uptr addr, bool destroy) {}
6383uptr MutexSet::Size() const { return 0; }
6484MutexSet::Desc MutexSet::Get(uptr i) const { return Desc(); }
85DynamicMutexSet::DynamicMutexSet() : ptr_(&set_) {}
86DynamicMutexSet::~DynamicMutexSet() {}
6587#endif
6688
6789} // namespace __tsan
lib/tsan/tsan_new_delete.cpp created+199
......@@ -0,0 +1,199 @@
1//===-- tsan_new_delete.cpp ---------------------------------------------===//
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// Interceptors for operators new and delete.
12//===----------------------------------------------------------------------===//
13#include "interception/interception.h"
14#include "sanitizer_common/sanitizer_allocator.h"
15#include "sanitizer_common/sanitizer_allocator_report.h"
16#include "sanitizer_common/sanitizer_internal_defs.h"
17#include "tsan_interceptors.h"
18#include "tsan_rtl.h"
19
20using namespace __tsan;
21
22namespace std {
23struct nothrow_t {};
24enum class align_val_t: __sanitizer::uptr {};
25} // namespace std
26
27DECLARE_REAL(void *, malloc, uptr size)
28DECLARE_REAL(void, free, void *ptr)
29
30// TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
31#define OPERATOR_NEW_BODY(mangled_name, nothrow) \
32 if (in_symbolizer()) \
33 return InternalAlloc(size); \
34 void *p = 0; \
35 { \
36 SCOPED_INTERCEPTOR_RAW(mangled_name, size); \
37 p = user_alloc(thr, pc, size); \
38 if (!nothrow && UNLIKELY(!p)) { \
39 GET_STACK_TRACE_FATAL(thr, pc); \
40 ReportOutOfMemory(size, &stack); \
41 } \
42 } \
43 invoke_malloc_hook(p, size); \
44 return p;
45
46#define OPERATOR_NEW_BODY_ALIGN(mangled_name, nothrow) \
47 if (in_symbolizer()) \
48 return InternalAlloc(size, nullptr, (uptr)align); \
49 void *p = 0; \
50 { \
51 SCOPED_INTERCEPTOR_RAW(mangled_name, size); \
52 p = user_memalign(thr, pc, (uptr)align, size); \
53 if (!nothrow && UNLIKELY(!p)) { \
54 GET_STACK_TRACE_FATAL(thr, pc); \
55 ReportOutOfMemory(size, &stack); \
56 } \
57 } \
58 invoke_malloc_hook(p, size); \
59 return p;
60
61SANITIZER_INTERFACE_ATTRIBUTE
62void *operator new(__sanitizer::uptr size);
63void *operator new(__sanitizer::uptr size) {
64 OPERATOR_NEW_BODY(_Znwm, false /*nothrow*/);
65}
66
67SANITIZER_INTERFACE_ATTRIBUTE
68void *operator new[](__sanitizer::uptr size);
69void *operator new[](__sanitizer::uptr size) {
70 OPERATOR_NEW_BODY(_Znam, false /*nothrow*/);
71}
72
73SANITIZER_INTERFACE_ATTRIBUTE
74void *operator new(__sanitizer::uptr size, std::nothrow_t const&);
75void *operator new(__sanitizer::uptr size, std::nothrow_t const&) {
76 OPERATOR_NEW_BODY(_ZnwmRKSt9nothrow_t, true /*nothrow*/);
77}
78
79SANITIZER_INTERFACE_ATTRIBUTE
80void *operator new[](__sanitizer::uptr size, std::nothrow_t const&);
81void *operator new[](__sanitizer::uptr size, std::nothrow_t const&) {
82 OPERATOR_NEW_BODY(_ZnamRKSt9nothrow_t, true /*nothrow*/);
83}
84
85SANITIZER_INTERFACE_ATTRIBUTE
86void *operator new(__sanitizer::uptr size, std::align_val_t align);
87void *operator new(__sanitizer::uptr size, std::align_val_t align) {
88 OPERATOR_NEW_BODY_ALIGN(_ZnwmSt11align_val_t, false /*nothrow*/);
89}
90
91SANITIZER_INTERFACE_ATTRIBUTE
92void *operator new[](__sanitizer::uptr size, std::align_val_t align);
93void *operator new[](__sanitizer::uptr size, std::align_val_t align) {
94 OPERATOR_NEW_BODY_ALIGN(_ZnamSt11align_val_t, false /*nothrow*/);
95}
96
97SANITIZER_INTERFACE_ATTRIBUTE
98void *operator new(__sanitizer::uptr size, std::align_val_t align,
99 std::nothrow_t const&);
100void *operator new(__sanitizer::uptr size, std::align_val_t align,
101 std::nothrow_t const&) {
102 OPERATOR_NEW_BODY_ALIGN(_ZnwmSt11align_val_tRKSt9nothrow_t,
103 true /*nothrow*/);
104}
105
106SANITIZER_INTERFACE_ATTRIBUTE
107void *operator new[](__sanitizer::uptr size, std::align_val_t align,
108 std::nothrow_t const&);
109void *operator new[](__sanitizer::uptr size, std::align_val_t align,
110 std::nothrow_t const&) {
111 OPERATOR_NEW_BODY_ALIGN(_ZnamSt11align_val_tRKSt9nothrow_t,
112 true /*nothrow*/);
113}
114
115#define OPERATOR_DELETE_BODY(mangled_name) \
116 if (ptr == 0) return; \
117 if (in_symbolizer()) \
118 return InternalFree(ptr); \
119 invoke_free_hook(ptr); \
120 SCOPED_INTERCEPTOR_RAW(mangled_name, ptr); \
121 user_free(thr, pc, ptr);
122
123SANITIZER_INTERFACE_ATTRIBUTE
124void operator delete(void *ptr) NOEXCEPT;
125void operator delete(void *ptr) NOEXCEPT {
126 OPERATOR_DELETE_BODY(_ZdlPv);
127}
128
129SANITIZER_INTERFACE_ATTRIBUTE
130void operator delete[](void *ptr) NOEXCEPT;
131void operator delete[](void *ptr) NOEXCEPT {
132 OPERATOR_DELETE_BODY(_ZdaPv);
133}
134
135SANITIZER_INTERFACE_ATTRIBUTE
136void operator delete(void *ptr, std::nothrow_t const&);
137void operator delete(void *ptr, std::nothrow_t const&) {
138 OPERATOR_DELETE_BODY(_ZdlPvRKSt9nothrow_t);
139}
140
141SANITIZER_INTERFACE_ATTRIBUTE
142void operator delete[](void *ptr, std::nothrow_t const&);
143void operator delete[](void *ptr, std::nothrow_t const&) {
144 OPERATOR_DELETE_BODY(_ZdaPvRKSt9nothrow_t);
145}
146
147SANITIZER_INTERFACE_ATTRIBUTE
148void operator delete(void *ptr, __sanitizer::uptr size) NOEXCEPT;
149void operator delete(void *ptr, __sanitizer::uptr size) NOEXCEPT {
150 OPERATOR_DELETE_BODY(_ZdlPvm);
151}
152
153SANITIZER_INTERFACE_ATTRIBUTE
154void operator delete[](void *ptr, __sanitizer::uptr size) NOEXCEPT;
155void operator delete[](void *ptr, __sanitizer::uptr size) NOEXCEPT {
156 OPERATOR_DELETE_BODY(_ZdaPvm);
157}
158
159SANITIZER_INTERFACE_ATTRIBUTE
160void operator delete(void *ptr, std::align_val_t align) NOEXCEPT;
161void operator delete(void *ptr, std::align_val_t align) NOEXCEPT {
162 OPERATOR_DELETE_BODY(_ZdlPvSt11align_val_t);
163}
164
165SANITIZER_INTERFACE_ATTRIBUTE
166void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT;
167void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT {
168 OPERATOR_DELETE_BODY(_ZdaPvSt11align_val_t);
169}
170
171SANITIZER_INTERFACE_ATTRIBUTE
172void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&);
173void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&) {
174 OPERATOR_DELETE_BODY(_ZdlPvSt11align_val_tRKSt9nothrow_t);
175}
176
177SANITIZER_INTERFACE_ATTRIBUTE
178void operator delete[](void *ptr, std::align_val_t align,
179 std::nothrow_t const&);
180void operator delete[](void *ptr, std::align_val_t align,
181 std::nothrow_t const&) {
182 OPERATOR_DELETE_BODY(_ZdaPvSt11align_val_tRKSt9nothrow_t);
183}
184
185SANITIZER_INTERFACE_ATTRIBUTE
186void operator delete(void *ptr, __sanitizer::uptr size,
187 std::align_val_t align) NOEXCEPT;
188void operator delete(void *ptr, __sanitizer::uptr size,
189 std::align_val_t align) NOEXCEPT {
190 OPERATOR_DELETE_BODY(_ZdlPvmSt11align_val_t);
191}
192
193SANITIZER_INTERFACE_ATTRIBUTE
194void operator delete[](void *ptr, __sanitizer::uptr size,
195 std::align_val_t align) NOEXCEPT;
196void operator delete[](void *ptr, __sanitizer::uptr size,
197 std::align_val_t align) NOEXCEPT {
198 OPERATOR_DELETE_BODY(_ZdaPvmSt11align_val_t);
199}
lib/tsan/tsan_platform.h+568-841
......@@ -18,38 +18,42 @@
1818# error "Only 64-bit is supported"
1919#endif
2020
21#include "sanitizer_common/sanitizer_common.h"
2122#include "tsan_defs.h"
22#include "tsan_trace.h"
2323
2424namespace __tsan {
2525
26#if defined(__x86_64__)
27#define HAS_48_BIT_ADDRESS_SPACE 1
28#elif SANITIZER_IOSSIM // arm64 iOS simulators (order of #if matters)
29#define HAS_48_BIT_ADDRESS_SPACE 1
30#elif SANITIZER_IOS // arm64 iOS devices (order of #if matters)
31#define HAS_48_BIT_ADDRESS_SPACE 0
32#elif SANITIZER_MAC // arm64 macOS (order of #if matters)
33#define HAS_48_BIT_ADDRESS_SPACE 1
34#else
35#define HAS_48_BIT_ADDRESS_SPACE 0
36#endif
37
38#if !SANITIZER_GO
26enum {
27 // App memory is not mapped onto shadow memory range.
28 kBrokenMapping = 1 << 0,
29 // Mapping app memory and back does not produce the same address,
30 // this can lead to wrong addresses in reports and potentially
31 // other bad consequences.
32 kBrokenReverseMapping = 1 << 1,
33 // Mapping is non-linear for linear user range.
34 // This is bad and can lead to unpredictable memory corruptions, etc
35 // because range access functions assume linearity.
36 kBrokenLinearity = 1 << 2,
37 // Meta for an app region overlaps with the meta of another app region.
38 // This is determined by recomputing the individual meta regions for
39 // each app region.
40 //
41 // N.B. There is no "kBrokenReverseMetaMapping" constant because there
42 // is no MetaToMem function. However, note that (!kBrokenLinearity
43 // && !kBrokenAliasedMetas) implies that MemToMeta is invertible.
44 kBrokenAliasedMetas = 1 << 3,
45};
3946
40#if HAS_48_BIT_ADDRESS_SPACE
4147/*
4248C/C++ on linux/x86_64 and freebsd/x86_64
43490000 0000 1000 - 0080 0000 0000: main binary and/or MAP_32BIT mappings (512GB)
44500040 0000 0000 - 0100 0000 0000: -
450100 0000 0000 - 2000 0000 0000: shadow
462000 0000 0000 - 3000 0000 0000: -
473000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
484000 0000 0000 - 5500 0000 0000: -
510100 0000 0000 - 1000 0000 0000: shadow
521000 0000 0000 - 3000 0000 0000: -
533000 0000 0000 - 3400 0000 0000: metainfo (memory blocks and sync objects)
543400 0000 0000 - 5500 0000 0000: -
49555500 0000 0000 - 5680 0000 0000: pie binaries without ASLR or on 4.1+ kernels
505680 0000 0000 - 6000 0000 0000: -
516000 0000 0000 - 6200 0000 0000: traces
526200 0000 0000 - 7d00 0000 0000: -
565680 0000 0000 - 7d00 0000 0000: -
53577b00 0000 0000 - 7c00 0000 0000: heap
54587c00 0000 0000 - 7e80 0000 0000: -
55597e80 0000 0000 - 8000 0000 0000: modules and main thread stack
......@@ -65,15 +69,12 @@ C/C++ on netbsd/amd64 can reuse the same mapping:
6569 * Stack on NetBSD/amd64 has prereserved 128MB.
6670 * Heap grows downwards (top-down).
6771 * ASLR must be disabled per-process or globally.
68
6972*/
70struct Mapping {
73struct Mapping48AddressSpace {
7174 static const uptr kMetaShadowBeg = 0x300000000000ull;
7275 static const uptr kMetaShadowEnd = 0x340000000000ull;
73 static const uptr kTraceMemBeg = 0x600000000000ull;
74 static const uptr kTraceMemEnd = 0x620000000000ull;
7576 static const uptr kShadowBeg = 0x010000000000ull;
76 static const uptr kShadowEnd = 0x200000000000ull;
77 static const uptr kShadowEnd = 0x100000000000ull;
7778 static const uptr kHeapMemBeg = 0x7b0000000000ull;
7879 static const uptr kHeapMemEnd = 0x7c0000000000ull;
7980 static const uptr kLoAppMemBeg = 0x000000001000ull;
......@@ -82,36 +83,32 @@ struct Mapping {
8283 static const uptr kMidAppMemEnd = 0x568000000000ull;
8384 static const uptr kHiAppMemBeg = 0x7e8000000000ull;
8485 static const uptr kHiAppMemEnd = 0x800000000000ull;
85 static const uptr kAppMemMsk = 0x780000000000ull;
86 static const uptr kAppMemXor = 0x040000000000ull;
86 static const uptr kShadowMsk = 0x780000000000ull;
87 static const uptr kShadowXor = 0x040000000000ull;
88 static const uptr kShadowAdd = 0x000000000000ull;
8789 static const uptr kVdsoBeg = 0xf000000000000000ull;
8890};
8991
90#define TSAN_MID_APP_RANGE 1
91#elif defined(__mips64)
9292/*
9393C/C++ on linux/mips64 (40-bit VMA)
94940000 0000 00 - 0100 0000 00: - (4 GB)
95950100 0000 00 - 0200 0000 00: main binary (4 GB)
960200 0000 00 - 2000 0000 00: - (120 GB)
972000 0000 00 - 4000 0000 00: shadow (128 GB)
960200 0000 00 - 1200 0000 00: - (64 GB)
971200 0000 00 - 2200 0000 00: shadow (64 GB)
982200 0000 00 - 4000 0000 00: - (120 GB)
98994000 0000 00 - 5000 0000 00: metainfo (memory blocks and sync objects) (64 GB)
991005000 0000 00 - aa00 0000 00: - (360 GB)
100101aa00 0000 00 - ab00 0000 00: main binary (PIE) (4 GB)
101ab00 0000 00 - b000 0000 00: - (20 GB)
102b000 0000 00 - b200 0000 00: traces (8 GB)
103b200 0000 00 - fe00 0000 00: - (304 GB)
102ab00 0000 00 - fe00 0000 00: - (332 GB)
104103fe00 0000 00 - ff00 0000 00: heap (4 GB)
105104ff00 0000 00 - ff80 0000 00: - (2 GB)
106105ff80 0000 00 - ffff ffff ff: modules and main thread stack (<2 GB)
107106*/
108struct Mapping40 {
107struct MappingMips64_40 {
109108 static const uptr kMetaShadowBeg = 0x4000000000ull;
110109 static const uptr kMetaShadowEnd = 0x5000000000ull;
111 static const uptr kTraceMemBeg = 0xb000000000ull;
112 static const uptr kTraceMemEnd = 0xb200000000ull;
113 static const uptr kShadowBeg = 0x2000000000ull;
114 static const uptr kShadowEnd = 0x4000000000ull;
110 static const uptr kShadowBeg = 0x1200000000ull;
111 static const uptr kShadowEnd = 0x2200000000ull;
115112 static const uptr kHeapMemBeg = 0xfe00000000ull;
116113 static const uptr kHeapMemEnd = 0xff00000000ull;
117114 static const uptr kLoAppMemBeg = 0x0100000000ull;
......@@ -120,152 +117,170 @@ struct Mapping40 {
120117 static const uptr kMidAppMemEnd = 0xab00000000ull;
121118 static const uptr kHiAppMemBeg = 0xff80000000ull;
122119 static const uptr kHiAppMemEnd = 0xffffffffffull;
123 static const uptr kAppMemMsk = 0xf800000000ull;
124 static const uptr kAppMemXor = 0x0800000000ull;
120 static const uptr kShadowMsk = 0xf800000000ull;
121 static const uptr kShadowXor = 0x0800000000ull;
122 static const uptr kShadowAdd = 0x0000000000ull;
125123 static const uptr kVdsoBeg = 0xfffff00000ull;
126124};
127125
128#define TSAN_MID_APP_RANGE 1
129#define TSAN_RUNTIME_VMA 1
130#elif defined(__aarch64__) && defined(__APPLE__)
131126/*
132127C/C++ on Darwin/iOS/ARM64 (36-bit VMA, 64 GB VM)
1331280000 0000 00 - 0100 0000 00: - (4 GB)
1341290100 0000 00 - 0200 0000 00: main binary, modules, thread stacks (4 GB)
1351300200 0000 00 - 0300 0000 00: heap (4 GB)
1361310300 0000 00 - 0400 0000 00: - (4 GB)
1370400 0000 00 - 0c00 0000 00: shadow memory (32 GB)
1380c00 0000 00 - 0d00 0000 00: - (4 GB)
1320400 0000 00 - 0800 0000 00: shadow memory (16 GB)
1330800 0000 00 - 0d00 0000 00: - (20 GB)
1391340d00 0000 00 - 0e00 0000 00: metainfo (4 GB)
1400e00 0000 00 - 0f00 0000 00: - (4 GB)
1410f00 0000 00 - 0fc0 0000 00: traces (3 GB)
1420fc0 0000 00 - 1000 0000 00: -
1350e00 0000 00 - 1000 0000 00: -
143136*/
144struct Mapping {
137struct MappingAppleAarch64 {
145138 static const uptr kLoAppMemBeg = 0x0100000000ull;
146139 static const uptr kLoAppMemEnd = 0x0200000000ull;
147140 static const uptr kHeapMemBeg = 0x0200000000ull;
148141 static const uptr kHeapMemEnd = 0x0300000000ull;
149142 static const uptr kShadowBeg = 0x0400000000ull;
150 static const uptr kShadowEnd = 0x0c00000000ull;
143 static const uptr kShadowEnd = 0x0800000000ull;
151144 static const uptr kMetaShadowBeg = 0x0d00000000ull;
152145 static const uptr kMetaShadowEnd = 0x0e00000000ull;
153 static const uptr kTraceMemBeg = 0x0f00000000ull;
154 static const uptr kTraceMemEnd = 0x0fc0000000ull;
155146 static const uptr kHiAppMemBeg = 0x0fc0000000ull;
156147 static const uptr kHiAppMemEnd = 0x0fc0000000ull;
157 static const uptr kAppMemMsk = 0x0ull;
158 static const uptr kAppMemXor = 0x0ull;
148 static const uptr kShadowMsk = 0x0ull;
149 static const uptr kShadowXor = 0x0ull;
150 static const uptr kShadowAdd = 0x0200000000ull;
159151 static const uptr kVdsoBeg = 0x7000000000000000ull;
152 static const uptr kMidAppMemBeg = 0;
153 static const uptr kMidAppMemEnd = 0;
160154};
161155
162#elif defined(__aarch64__) && !defined(__APPLE__)
163// AArch64 supports multiple VMA which leads to multiple address transformation
164// functions. To support these multiple VMAS transformations and mappings TSAN
165// runtime for AArch64 uses an external memory read (vmaSize) to select which
166// mapping to use. Although slower, it make a same instrumented binary run on
167// multiple kernels.
168
169156/*
170157C/C++ on linux/aarch64 (39-bit VMA)
1710000 0010 00 - 0100 0000 00: main binary
1720100 0000 00 - 0800 0000 00: -
1730800 0000 00 - 2000 0000 00: shadow memory
1742000 0000 00 - 3100 0000 00: -
1753100 0000 00 - 3400 0000 00: metainfo
1763400 0000 00 - 5500 0000 00: -
1775500 0000 00 - 5600 0000 00: main binary (PIE)
1785600 0000 00 - 6000 0000 00: -
1796000 0000 00 - 6200 0000 00: traces
1806200 0000 00 - 7d00 0000 00: -
1817c00 0000 00 - 7d00 0000 00: heap
1827d00 0000 00 - 7fff ffff ff: modules and main thread stack
1580000 0010 00 - 0500 0000 00: main binary (20 GB)
1590100 0000 00 - 2000 0000 00: -
1602000 0000 00 - 4000 0000 00: shadow memory (128 GB)
1614000 0000 00 - 4800 0000 00: metainfo (32 GB)
1624800 0000 00 - 5500 0000 00: -
1635500 0000 00 - 5a00 0000 00: main binary (PIE) (20 GB)
1645600 0000 00 - 7c00 0000 00: -
1657a00 0000 00 - 7d00 0000 00: heap (12 GB)
1667d00 0000 00 - 7fff ffff ff: modules and main thread stack (12 GB)
183167*/
184struct Mapping39 {
168struct MappingAarch64_39 {
185169 static const uptr kLoAppMemBeg = 0x0000001000ull;
186 static const uptr kLoAppMemEnd = 0x0100000000ull;
187 static const uptr kShadowBeg = 0x0800000000ull;
188 static const uptr kShadowEnd = 0x2000000000ull;
189 static const uptr kMetaShadowBeg = 0x3100000000ull;
190 static const uptr kMetaShadowEnd = 0x3400000000ull;
170 static const uptr kLoAppMemEnd = 0x0500000000ull;
171 static const uptr kShadowBeg = 0x2000000000ull;
172 static const uptr kShadowEnd = 0x4000000000ull;
173 static const uptr kMetaShadowBeg = 0x4000000000ull;
174 static const uptr kMetaShadowEnd = 0x4800000000ull;
191175 static const uptr kMidAppMemBeg = 0x5500000000ull;
192 static const uptr kMidAppMemEnd = 0x5600000000ull;
193 static const uptr kTraceMemBeg = 0x6000000000ull;
194 static const uptr kTraceMemEnd = 0x6200000000ull;
195 static const uptr kHeapMemBeg = 0x7c00000000ull;
176 static const uptr kMidAppMemEnd = 0x5a00000000ull;
177 static const uptr kHeapMemBeg = 0x7a00000000ull;
196178 static const uptr kHeapMemEnd = 0x7d00000000ull;
197 static const uptr kHiAppMemBeg = 0x7e00000000ull;
179 static const uptr kHiAppMemBeg = 0x7d00000000ull;
198180 static const uptr kHiAppMemEnd = 0x7fffffffffull;
199 static const uptr kAppMemMsk = 0x7800000000ull;
200 static const uptr kAppMemXor = 0x0200000000ull;
181 static const uptr kShadowMsk = 0x7000000000ull;
182 static const uptr kShadowXor = 0x1000000000ull;
183 static const uptr kShadowAdd = 0x0000000000ull;
201184 static const uptr kVdsoBeg = 0x7f00000000ull;
202185};
203186
204187/*
205188C/C++ on linux/aarch64 (42-bit VMA)
20600000 0010 00 - 01000 0000 00: main binary
20701000 0000 00 - 10000 0000 00: -
20810000 0000 00 - 20000 0000 00: shadow memory
20920000 0000 00 - 26000 0000 00: -
21026000 0000 00 - 28000 0000 00: metainfo
21128000 0000 00 - 2aa00 0000 00: -
2122aa00 0000 00 - 2ab00 0000 00: main binary (PIE)
2132ab00 0000 00 - 36200 0000 00: -
21436200 0000 00 - 36240 0000 00: traces
21536240 0000 00 - 3e000 0000 00: -
2163e000 0000 00 - 3f000 0000 00: heap
2173f000 0000 00 - 3ffff ffff ff: modules and main thread stack
18900000 0010 00 - 02000 0000 00: main binary (128 GB)
19002000 0000 00 - 08000 0000 00: -
19110000 0000 00 - 20000 0000 00: shadow memory (1024 GB)
19220000 0000 00 - 24000 0000 00: metainfo (256 GB)
19324000 0000 00 - 2aa00 0000 00: -
1942aa00 0000 00 - 2c000 0000 00: main binary (PIE) (88 GB)
1952c000 0000 00 - 3c000 0000 00: -
1963c000 0000 00 - 3f000 0000 00: heap (192 GB)
1973f000 0000 00 - 3ffff ffff ff: modules and main thread stack (64 GB)
218198*/
219struct Mapping42 {
199struct MappingAarch64_42 {
220200 static const uptr kLoAppMemBeg = 0x00000001000ull;
221 static const uptr kLoAppMemEnd = 0x01000000000ull;
201 static const uptr kLoAppMemEnd = 0x02000000000ull;
222202 static const uptr kShadowBeg = 0x10000000000ull;
223203 static const uptr kShadowEnd = 0x20000000000ull;
224 static const uptr kMetaShadowBeg = 0x26000000000ull;
225 static const uptr kMetaShadowEnd = 0x28000000000ull;
204 static const uptr kMetaShadowBeg = 0x20000000000ull;
205 static const uptr kMetaShadowEnd = 0x24000000000ull;
226206 static const uptr kMidAppMemBeg = 0x2aa00000000ull;
227 static const uptr kMidAppMemEnd = 0x2ab00000000ull;
228 static const uptr kTraceMemBeg = 0x36200000000ull;
229 static const uptr kTraceMemEnd = 0x36400000000ull;
230 static const uptr kHeapMemBeg = 0x3e000000000ull;
207 static const uptr kMidAppMemEnd = 0x2c000000000ull;
208 static const uptr kHeapMemBeg = 0x3c000000000ull;
231209 static const uptr kHeapMemEnd = 0x3f000000000ull;
232210 static const uptr kHiAppMemBeg = 0x3f000000000ull;
233211 static const uptr kHiAppMemEnd = 0x3ffffffffffull;
234 static const uptr kAppMemMsk = 0x3c000000000ull;
235 static const uptr kAppMemXor = 0x04000000000ull;
212 static const uptr kShadowMsk = 0x38000000000ull;
213 static const uptr kShadowXor = 0x08000000000ull;
214 static const uptr kShadowAdd = 0x00000000000ull;
236215 static const uptr kVdsoBeg = 0x37f00000000ull;
237216};
238217
239struct Mapping48 {
218/*
219C/C++ on linux/aarch64 (48-bit VMA)
2200000 0000 1000 - 0a00 0000 0000: main binary (10240 GB)
2210a00 0000 1000 - 1554 0000 0000: -
2221554 0000 1000 - 5400 0000 0000: shadow memory (64176 GB)
2235400 0000 1000 - 8000 0000 0000: -
2248000 0000 1000 - 0a00 0000 0000: metainfo (32768 GB)
225a000 0000 1000 - aaaa 0000 0000: -
226aaaa 0000 1000 - ac00 0000 0000: main binary (PIE) (1368 GB)
227ac00 0000 1000 - fc00 0000 0000: -
228fc00 0000 1000 - ffff ffff ffff: modules and main thread stack (4096 GB)
229
230N.B. the shadow memory region has a strange start address, because it
231contains the shadows for the mid, high and low app regions (in this
232unusual order).
233*/
234struct MappingAarch64_48 {
240235 static const uptr kLoAppMemBeg = 0x0000000001000ull;
241 static const uptr kLoAppMemEnd = 0x0000200000000ull;
242 static const uptr kShadowBeg = 0x0002000000000ull;
243 static const uptr kShadowEnd = 0x0004000000000ull;
244 static const uptr kMetaShadowBeg = 0x0005000000000ull;
245 static const uptr kMetaShadowEnd = 0x0006000000000ull;
236 static const uptr kLoAppMemEnd = 0x00a0000000000ull;
237 static const uptr kShadowBeg = 0x0155400000000ull;
238 static const uptr kShadowEnd = 0x0540000000000ull;
239 static const uptr kMetaShadowBeg = 0x0800000000000ull;
240 static const uptr kMetaShadowEnd = 0x0a00000000000ull;
246241 static const uptr kMidAppMemBeg = 0x0aaaa00000000ull;
247 static const uptr kMidAppMemEnd = 0x0aaaf00000000ull;
248 static const uptr kTraceMemBeg = 0x0f06000000000ull;
249 static const uptr kTraceMemEnd = 0x0f06200000000ull;
250 static const uptr kHeapMemBeg = 0x0ffff00000000ull;
251 static const uptr kHeapMemEnd = 0x0ffff00000000ull;
252 static const uptr kHiAppMemBeg = 0x0ffff00000000ull;
242 static const uptr kMidAppMemEnd = 0x0ac0000000000ull;
243 static const uptr kHiAppMemBeg = 0x0fc0000000000ull;
253244 static const uptr kHiAppMemEnd = 0x1000000000000ull;
254 static const uptr kAppMemMsk = 0x0fff800000000ull;
255 static const uptr kAppMemXor = 0x0000800000000ull;
245 static const uptr kHeapMemBeg = 0x0fc0000000000ull;
246 static const uptr kHeapMemEnd = 0x0fc0000000000ull;
247 static const uptr kShadowMsk = 0x0c00000000000ull;
248 static const uptr kShadowXor = 0x0200000000000ull;
249 static const uptr kShadowAdd = 0x0000000000000ull;
256250 static const uptr kVdsoBeg = 0xffff000000000ull;
257251};
258252
259// Indicates the runtime will define the memory regions at runtime.
260#define TSAN_RUNTIME_VMA 1
261// Indicates that mapping defines a mid range memory segment.
262#define TSAN_MID_APP_RANGE 1
263#elif defined(__powerpc64__)
264// PPC64 supports multiple VMA which leads to multiple address transformation
265// functions. To support these multiple VMAS transformations and mappings TSAN
266// runtime for PPC64 uses an external memory read (vmaSize) to select which
267// mapping to use. Although slower, it make a same instrumented binary run on
268// multiple kernels.
253/* C/C++ on linux/loongarch64 (47-bit VMA)
2540000 0000 4000 - 0080 0000 0000: main binary
2550080 0000 0000 - 0100 0000 0000: -
2560100 0000 0000 - 1000 0000 0000: shadow memory
2571000 0000 0000 - 3000 0000 0000: -
2583000 0000 0000 - 3400 0000 0000: metainfo
2593400 0000 0000 - 5555 0000 0000: -
2605555 0000 0000 - 5556 0000 0000: main binary (PIE)
2615556 0000 0000 - 7ffe 0000 0000: -
2627ffe 0000 0000 - 7fff 0000 0000: heap
2637fff 0000 0000 - 7fff 8000 0000: -
2647fff 8000 0000 - 8000 0000 0000: modules and main thread stack
265*/
266struct MappingLoongArch64_47 {
267 static const uptr kMetaShadowBeg = 0x300000000000ull;
268 static const uptr kMetaShadowEnd = 0x340000000000ull;
269 static const uptr kShadowBeg = 0x010000000000ull;
270 static const uptr kShadowEnd = 0x100000000000ull;
271 static const uptr kHeapMemBeg = 0x7ffe00000000ull;
272 static const uptr kHeapMemEnd = 0x7fff00000000ull;
273 static const uptr kLoAppMemBeg = 0x000000004000ull;
274 static const uptr kLoAppMemEnd = 0x008000000000ull;
275 static const uptr kMidAppMemBeg = 0x555500000000ull;
276 static const uptr kMidAppMemEnd = 0x555600000000ull;
277 static const uptr kHiAppMemBeg = 0x7fff80000000ull;
278 static const uptr kHiAppMemEnd = 0x800000000000ull;
279 static const uptr kShadowMsk = 0x780000000000ull;
280 static const uptr kShadowXor = 0x040000000000ull;
281 static const uptr kShadowAdd = 0x000000000000ull;
282 static const uptr kVdsoBeg = 0x7fffffffc000ull;
283};
269284
270285/*
271286C/C++ on linux/powerpc64 (44-bit VMA)
......@@ -274,18 +289,16 @@ C/C++ on linux/powerpc64 (44-bit VMA)
2742890001 0000 0000 - 0b00 0000 0000: shadow
2752900b00 0000 0000 - 0b00 0000 0000: -
2762910b00 0000 0000 - 0d00 0000 0000: metainfo (memory blocks and sync objects)
2770d00 0000 0000 - 0d00 0000 0000: -
2780d00 0000 0000 - 0f00 0000 0000: traces
2790f00 0000 0000 - 0f00 0000 0000: -
2920d00 0000 0000 - 0f00 0000 0000: -
2802930f00 0000 0000 - 0f50 0000 0000: heap
2812940f50 0000 0000 - 0f60 0000 0000: -
2822950f60 0000 0000 - 1000 0000 0000: modules and main thread stack
283296*/
284struct Mapping44 {
297struct MappingPPC64_44 {
298 static const uptr kBroken = kBrokenMapping | kBrokenReverseMapping |
299 kBrokenLinearity | kBrokenAliasedMetas;
285300 static const uptr kMetaShadowBeg = 0x0b0000000000ull;
286301 static const uptr kMetaShadowEnd = 0x0d0000000000ull;
287 static const uptr kTraceMemBeg = 0x0d0000000000ull;
288 static const uptr kTraceMemEnd = 0x0f0000000000ull;
289302 static const uptr kShadowBeg = 0x000100000000ull;
290303 static const uptr kShadowEnd = 0x0b0000000000ull;
291304 static const uptr kLoAppMemBeg = 0x000000000100ull;
......@@ -294,188 +307,196 @@ struct Mapping44 {
294307 static const uptr kHeapMemEnd = 0x0f5000000000ull;
295308 static const uptr kHiAppMemBeg = 0x0f6000000000ull;
296309 static const uptr kHiAppMemEnd = 0x100000000000ull; // 44 bits
297 static const uptr kAppMemMsk = 0x0f0000000000ull;
298 static const uptr kAppMemXor = 0x002100000000ull;
310 static const uptr kShadowMsk = 0x0f0000000000ull;
311 static const uptr kShadowXor = 0x002100000000ull;
312 static const uptr kShadowAdd = 0x000000000000ull;
299313 static const uptr kVdsoBeg = 0x3c0000000000000ull;
314 static const uptr kMidAppMemBeg = 0;
315 static const uptr kMidAppMemEnd = 0;
300316};
301317
302318/*
303319C/C++ on linux/powerpc64 (46-bit VMA)
3043200000 0000 1000 - 0100 0000 0000: main binary
3053210100 0000 0000 - 0200 0000 0000: -
3060100 0000 0000 - 1000 0000 0000: shadow
3071000 0000 0000 - 1000 0000 0000: -
3081000 0000 0000 - 2000 0000 0000: metainfo (memory blocks and sync objects)
3092000 0000 0000 - 2000 0000 0000: -
3102000 0000 0000 - 2200 0000 0000: traces
3112200 0000 0000 - 3d00 0000 0000: -
3220100 0000 0000 - 0800 0000 0000: shadow
3230800 0000 0000 - 1000 0000 0000: -
3241000 0000 0000 - 1200 0000 0000: metainfo (memory blocks and sync objects)
3251200 0000 0000 - 3d00 0000 0000: -
3123263d00 0000 0000 - 3e00 0000 0000: heap
3133273e00 0000 0000 - 3e80 0000 0000: -
3143283e80 0000 0000 - 4000 0000 0000: modules and main thread stack
315329*/
316struct Mapping46 {
330struct MappingPPC64_46 {
317331 static const uptr kMetaShadowBeg = 0x100000000000ull;
318 static const uptr kMetaShadowEnd = 0x200000000000ull;
319 static const uptr kTraceMemBeg = 0x200000000000ull;
320 static const uptr kTraceMemEnd = 0x220000000000ull;
332 static const uptr kMetaShadowEnd = 0x120000000000ull;
321333 static const uptr kShadowBeg = 0x010000000000ull;
322 static const uptr kShadowEnd = 0x100000000000ull;
334 static const uptr kShadowEnd = 0x080000000000ull;
323335 static const uptr kHeapMemBeg = 0x3d0000000000ull;
324336 static const uptr kHeapMemEnd = 0x3e0000000000ull;
325337 static const uptr kLoAppMemBeg = 0x000000001000ull;
326338 static const uptr kLoAppMemEnd = 0x010000000000ull;
327339 static const uptr kHiAppMemBeg = 0x3e8000000000ull;
328340 static const uptr kHiAppMemEnd = 0x400000000000ull; // 46 bits
329 static const uptr kAppMemMsk = 0x3c0000000000ull;
330 static const uptr kAppMemXor = 0x020000000000ull;
341 static const uptr kShadowMsk = 0x3c0000000000ull;
342 static const uptr kShadowXor = 0x020000000000ull;
343 static const uptr kShadowAdd = 0x000000000000ull;
331344 static const uptr kVdsoBeg = 0x7800000000000000ull;
345 static const uptr kMidAppMemBeg = 0;
346 static const uptr kMidAppMemEnd = 0;
332347};
333348
334349/*
335350C/C++ on linux/powerpc64 (47-bit VMA)
3363510000 0000 1000 - 0100 0000 0000: main binary
3373520100 0000 0000 - 0200 0000 0000: -
3380100 0000 0000 - 1000 0000 0000: shadow
3391000 0000 0000 - 1000 0000 0000: -
3401000 0000 0000 - 2000 0000 0000: metainfo (memory blocks and sync objects)
3412000 0000 0000 - 2000 0000 0000: -
3422000 0000 0000 - 2200 0000 0000: traces
3432200 0000 0000 - 7d00 0000 0000: -
3530100 0000 0000 - 0800 0000 0000: shadow
3540800 0000 0000 - 1000 0000 0000: -
3551000 0000 0000 - 1200 0000 0000: metainfo (memory blocks and sync objects)
3561200 0000 0000 - 7d00 0000 0000: -
3443577d00 0000 0000 - 7e00 0000 0000: heap
3453587e00 0000 0000 - 7e80 0000 0000: -
3463597e80 0000 0000 - 8000 0000 0000: modules and main thread stack
347360*/
348struct Mapping47 {
361struct MappingPPC64_47 {
349362 static const uptr kMetaShadowBeg = 0x100000000000ull;
350 static const uptr kMetaShadowEnd = 0x200000000000ull;
351 static const uptr kTraceMemBeg = 0x200000000000ull;
352 static const uptr kTraceMemEnd = 0x220000000000ull;
363 static const uptr kMetaShadowEnd = 0x120000000000ull;
353364 static const uptr kShadowBeg = 0x010000000000ull;
354 static const uptr kShadowEnd = 0x100000000000ull;
365 static const uptr kShadowEnd = 0x080000000000ull;
355366 static const uptr kHeapMemBeg = 0x7d0000000000ull;
356367 static const uptr kHeapMemEnd = 0x7e0000000000ull;
357368 static const uptr kLoAppMemBeg = 0x000000001000ull;
358369 static const uptr kLoAppMemEnd = 0x010000000000ull;
359370 static const uptr kHiAppMemBeg = 0x7e8000000000ull;
360371 static const uptr kHiAppMemEnd = 0x800000000000ull; // 47 bits
361 static const uptr kAppMemMsk = 0x7c0000000000ull;
362 static const uptr kAppMemXor = 0x020000000000ull;
372 static const uptr kShadowMsk = 0x7c0000000000ull;
373 static const uptr kShadowXor = 0x020000000000ull;
374 static const uptr kShadowAdd = 0x000000000000ull;
363375 static const uptr kVdsoBeg = 0x7800000000000000ull;
376 static const uptr kMidAppMemBeg = 0;
377 static const uptr kMidAppMemEnd = 0;
364378};
365379
366// Indicates the runtime will define the memory regions at runtime.
367#define TSAN_RUNTIME_VMA 1
368#elif defined(__s390x__)
369380/*
370381C/C++ on linux/s390x
371382While the kernel provides a 64-bit address space, we have to restrict ourselves
372383to 48 bits due to how e.g. SyncVar::GetId() works.
3733840000 0000 1000 - 0e00 0000 0000: binary, modules, stacks - 14 TiB
3740e00 0000 0000 - 4000 0000 0000: -
3754000 0000 0000 - 8000 0000 0000: shadow - 64TiB (4 * app)
3768000 0000 0000 - 9000 0000 0000: -
3850e00 0000 0000 - 2000 0000 0000: -
3862000 0000 0000 - 4000 0000 0000: shadow - 32TiB (2 * app)
3874000 0000 0000 - 9000 0000 0000: -
3773889000 0000 0000 - 9800 0000 0000: metainfo - 8TiB (0.5 * app)
3789800 0000 0000 - a000 0000 0000: -
379a000 0000 0000 - b000 0000 0000: traces - 16TiB (max history * 128k threads)
380b000 0000 0000 - be00 0000 0000: -
3899800 0000 0000 - be00 0000 0000: -
381390be00 0000 0000 - c000 0000 0000: heap - 2TiB (max supported by the allocator)
382391*/
383struct Mapping {
392struct MappingS390x {
384393 static const uptr kMetaShadowBeg = 0x900000000000ull;
385394 static const uptr kMetaShadowEnd = 0x980000000000ull;
386 static const uptr kTraceMemBeg = 0xa00000000000ull;
387 static const uptr kTraceMemEnd = 0xb00000000000ull;
388 static const uptr kShadowBeg = 0x400000000000ull;
389 static const uptr kShadowEnd = 0x800000000000ull;
395 static const uptr kShadowBeg = 0x200000000000ull;
396 static const uptr kShadowEnd = 0x400000000000ull;
390397 static const uptr kHeapMemBeg = 0xbe0000000000ull;
391398 static const uptr kHeapMemEnd = 0xc00000000000ull;
392399 static const uptr kLoAppMemBeg = 0x000000001000ull;
393400 static const uptr kLoAppMemEnd = 0x0e0000000000ull;
394401 static const uptr kHiAppMemBeg = 0xc00000004000ull;
395402 static const uptr kHiAppMemEnd = 0xc00000004000ull;
396 static const uptr kAppMemMsk = 0xb00000000000ull;
397 static const uptr kAppMemXor = 0x100000000000ull;
403 static const uptr kShadowMsk = 0xb00000000000ull;
404 static const uptr kShadowXor = 0x100000000000ull;
405 static const uptr kShadowAdd = 0x000000000000ull;
398406 static const uptr kVdsoBeg = 0xfffffffff000ull;
407 static const uptr kMidAppMemBeg = 0;
408 static const uptr kMidAppMemEnd = 0;
399409};
400#endif
401
402#elif SANITIZER_GO && !SANITIZER_WINDOWS && HAS_48_BIT_ADDRESS_SPACE
403410
404411/* Go on linux, darwin and freebsd on x86_64
4054120000 0000 1000 - 0000 1000 0000: executable
4064130000 1000 0000 - 00c0 0000 0000: -
40741400c0 0000 0000 - 00e0 0000 0000: heap
40841500e0 0000 0000 - 2000 0000 0000: -
4092000 0000 0000 - 2380 0000 0000: shadow
4102380 0000 0000 - 3000 0000 0000: -
4162000 0000 0000 - 21c0 0000 0000: shadow
41721c0 0000 0000 - 3000 0000 0000: -
4114183000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
4124000 0000 0000 - 6000 0000 0000: -
4136000 0000 0000 - 6200 0000 0000: traces
4146200 0000 0000 - 8000 0000 0000: -
4194000 0000 0000 - 8000 0000 0000: -
415420*/
416421
417struct Mapping {
422struct MappingGo48 {
418423 static const uptr kMetaShadowBeg = 0x300000000000ull;
419424 static const uptr kMetaShadowEnd = 0x400000000000ull;
420 static const uptr kTraceMemBeg = 0x600000000000ull;
421 static const uptr kTraceMemEnd = 0x620000000000ull;
422425 static const uptr kShadowBeg = 0x200000000000ull;
423 static const uptr kShadowEnd = 0x238000000000ull;
424 static const uptr kAppMemBeg = 0x000000001000ull;
425 static const uptr kAppMemEnd = 0x00e000000000ull;
426 static const uptr kShadowEnd = 0x21c000000000ull;
427 static const uptr kLoAppMemBeg = 0x000000001000ull;
428 static const uptr kLoAppMemEnd = 0x00e000000000ull;
429 static const uptr kMidAppMemBeg = 0;
430 static const uptr kMidAppMemEnd = 0;
431 static const uptr kHiAppMemBeg = 0;
432 static const uptr kHiAppMemEnd = 0;
433 static const uptr kHeapMemBeg = 0;
434 static const uptr kHeapMemEnd = 0;
435 static const uptr kVdsoBeg = 0;
436 static const uptr kShadowMsk = 0;
437 static const uptr kShadowXor = 0;
438 static const uptr kShadowAdd = 0x200000000000ull;
426439};
427440
428#elif SANITIZER_GO && SANITIZER_WINDOWS
429
430441/* Go on windows
4314420000 0000 1000 - 0000 1000 0000: executable
4324430000 1000 0000 - 00f8 0000 0000: -
43344400c0 0000 0000 - 00e0 0000 0000: heap
43444500e0 0000 0000 - 0100 0000 0000: -
4350100 0000 0000 - 0500 0000 0000: shadow
4360500 0000 0000 - 0560 0000 0000: -
4370560 0000 0000 - 0760 0000 0000: traces
4380760 0000 0000 - 07d0 0000 0000: metainfo (memory blocks and sync objects)
4460100 0000 0000 - 0300 0000 0000: shadow
4470300 0000 0000 - 0700 0000 0000: -
4480700 0000 0000 - 0770 0000 0000: metainfo (memory blocks and sync objects)
43944907d0 0000 0000 - 8000 0000 0000: -
450PIE binaries currently not supported, but it should be theoretically possible.
440451*/
441452
442struct Mapping {
443 static const uptr kMetaShadowBeg = 0x076000000000ull;
444 static const uptr kMetaShadowEnd = 0x07d000000000ull;
445 static const uptr kTraceMemBeg = 0x056000000000ull;
446 static const uptr kTraceMemEnd = 0x076000000000ull;
453struct MappingGoWindows {
454 static const uptr kMetaShadowBeg = 0x070000000000ull;
455 static const uptr kMetaShadowEnd = 0x077000000000ull;
447456 static const uptr kShadowBeg = 0x010000000000ull;
448 static const uptr kShadowEnd = 0x050000000000ull;
449 static const uptr kAppMemBeg = 0x000000001000ull;
450 static const uptr kAppMemEnd = 0x00e000000000ull;
457 static const uptr kShadowEnd = 0x030000000000ull;
458 static const uptr kLoAppMemBeg = 0x000000001000ull;
459 static const uptr kLoAppMemEnd = 0x00e000000000ull;
460 static const uptr kMidAppMemBeg = 0;
461 static const uptr kMidAppMemEnd = 0;
462 static const uptr kHiAppMemBeg = 0;
463 static const uptr kHiAppMemEnd = 0;
464 static const uptr kHeapMemBeg = 0;
465 static const uptr kHeapMemEnd = 0;
466 static const uptr kVdsoBeg = 0;
467 static const uptr kShadowMsk = 0;
468 static const uptr kShadowXor = 0;
469 static const uptr kShadowAdd = 0x010000000000ull;
451470};
452471
453#elif SANITIZER_GO && defined(__powerpc64__)
454
455/* Only Mapping46 and Mapping47 are currently supported for powercp64 on Go. */
456
457472/* Go on linux/powerpc64 (46-bit VMA)
4584730000 0000 1000 - 0000 1000 0000: executable
4594740000 1000 0000 - 00c0 0000 0000: -
46047500c0 0000 0000 - 00e0 0000 0000: heap
46147600e0 0000 0000 - 2000 0000 0000: -
4622000 0000 0000 - 2380 0000 0000: shadow
4632380 0000 0000 - 2400 0000 0000: -
4642400 0000 0000 - 3400 0000 0000: metainfo (memory blocks and sync objects)
4653400 0000 0000 - 3600 0000 0000: -
4663600 0000 0000 - 3800 0000 0000: traces
4673800 0000 0000 - 4000 0000 0000: -
4772000 0000 0000 - 21c0 0000 0000: shadow
47821c0 0000 0000 - 2400 0000 0000: -
4792400 0000 0000 - 2470 0000 0000: metainfo (memory blocks and sync objects)
4802470 0000 0000 - 4000 0000 0000: -
468481*/
469482
470struct Mapping46 {
483struct MappingGoPPC64_46 {
471484 static const uptr kMetaShadowBeg = 0x240000000000ull;
472 static const uptr kMetaShadowEnd = 0x340000000000ull;
473 static const uptr kTraceMemBeg = 0x360000000000ull;
474 static const uptr kTraceMemEnd = 0x380000000000ull;
485 static const uptr kMetaShadowEnd = 0x247000000000ull;
475486 static const uptr kShadowBeg = 0x200000000000ull;
476 static const uptr kShadowEnd = 0x238000000000ull;
477 static const uptr kAppMemBeg = 0x000000001000ull;
478 static const uptr kAppMemEnd = 0x00e000000000ull;
487 static const uptr kShadowEnd = 0x21c000000000ull;
488 static const uptr kLoAppMemBeg = 0x000000001000ull;
489 static const uptr kLoAppMemEnd = 0x00e000000000ull;
490 static const uptr kMidAppMemBeg = 0;
491 static const uptr kMidAppMemEnd = 0;
492 static const uptr kHiAppMemBeg = 0;
493 static const uptr kHiAppMemEnd = 0;
494 static const uptr kHeapMemBeg = 0;
495 static const uptr kHeapMemEnd = 0;
496 static const uptr kVdsoBeg = 0;
497 static const uptr kShadowMsk = 0;
498 static const uptr kShadowXor = 0;
499 static const uptr kShadowAdd = 0x200000000000ull;
479500};
480501
481502/* Go on linux/powerpc64 (47-bit VMA)
......@@ -483,718 +504,424 @@ struct Mapping46 {
4835040000 1000 0000 - 00c0 0000 0000: -
48450500c0 0000 0000 - 00e0 0000 0000: heap
48550600e0 0000 0000 - 2000 0000 0000: -
4862000 0000 0000 - 3000 0000 0000: shadow
4873000 0000 0000 - 3000 0000 0000: -
4883000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
4894000 0000 0000 - 6000 0000 0000: -
4906000 0000 0000 - 6200 0000 0000: traces
4916200 0000 0000 - 8000 0000 0000: -
5072000 0000 0000 - 2800 0000 0000: shadow
5082800 0000 0000 - 3000 0000 0000: -
5093000 0000 0000 - 3200 0000 0000: metainfo (memory blocks and sync objects)
5103200 0000 0000 - 8000 0000 0000: -
492511*/
493512
494struct Mapping47 {
513struct MappingGoPPC64_47 {
495514 static const uptr kMetaShadowBeg = 0x300000000000ull;
496 static const uptr kMetaShadowEnd = 0x400000000000ull;
497 static const uptr kTraceMemBeg = 0x600000000000ull;
498 static const uptr kTraceMemEnd = 0x620000000000ull;
515 static const uptr kMetaShadowEnd = 0x320000000000ull;
499516 static const uptr kShadowBeg = 0x200000000000ull;
500 static const uptr kShadowEnd = 0x300000000000ull;
501 static const uptr kAppMemBeg = 0x000000001000ull;
502 static const uptr kAppMemEnd = 0x00e000000000ull;
517 static const uptr kShadowEnd = 0x280000000000ull;
518 static const uptr kLoAppMemBeg = 0x000000001000ull;
519 static const uptr kLoAppMemEnd = 0x00e000000000ull;
520 static const uptr kMidAppMemBeg = 0;
521 static const uptr kMidAppMemEnd = 0;
522 static const uptr kHiAppMemBeg = 0;
523 static const uptr kHiAppMemEnd = 0;
524 static const uptr kHeapMemBeg = 0;
525 static const uptr kHeapMemEnd = 0;
526 static const uptr kVdsoBeg = 0;
527 static const uptr kShadowMsk = 0;
528 static const uptr kShadowXor = 0;
529 static const uptr kShadowAdd = 0x200000000000ull;
503530};
504531
505#define TSAN_RUNTIME_VMA 1
506
507#elif SANITIZER_GO && defined(__aarch64__)
508
509532/* Go on linux/aarch64 (48-bit VMA) and darwin/aarch64 (47-bit VMA)
5105330000 0000 1000 - 0000 1000 0000: executable
5115340000 1000 0000 - 00c0 0000 0000: -
51253500c0 0000 0000 - 00e0 0000 0000: heap
51353600e0 0000 0000 - 2000 0000 0000: -
5142000 0000 0000 - 3000 0000 0000: shadow
5153000 0000 0000 - 3000 0000 0000: -
5163000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
5174000 0000 0000 - 6000 0000 0000: -
5186000 0000 0000 - 6200 0000 0000: traces
5196200 0000 0000 - 8000 0000 0000: -
5372000 0000 0000 - 2800 0000 0000: shadow
5382800 0000 0000 - 3000 0000 0000: -
5393000 0000 0000 - 3200 0000 0000: metainfo (memory blocks and sync objects)
5403200 0000 0000 - 8000 0000 0000: -
520541*/
521
522struct Mapping {
542struct MappingGoAarch64 {
523543 static const uptr kMetaShadowBeg = 0x300000000000ull;
524 static const uptr kMetaShadowEnd = 0x400000000000ull;
525 static const uptr kTraceMemBeg = 0x600000000000ull;
526 static const uptr kTraceMemEnd = 0x620000000000ull;
544 static const uptr kMetaShadowEnd = 0x320000000000ull;
527545 static const uptr kShadowBeg = 0x200000000000ull;
528 static const uptr kShadowEnd = 0x300000000000ull;
529 static const uptr kAppMemBeg = 0x000000001000ull;
530 static const uptr kAppMemEnd = 0x00e000000000ull;
546 static const uptr kShadowEnd = 0x280000000000ull;
547 static const uptr kLoAppMemBeg = 0x000000001000ull;
548 static const uptr kLoAppMemEnd = 0x00e000000000ull;
549 static const uptr kMidAppMemBeg = 0;
550 static const uptr kMidAppMemEnd = 0;
551 static const uptr kHiAppMemBeg = 0;
552 static const uptr kHiAppMemEnd = 0;
553 static const uptr kHeapMemBeg = 0;
554 static const uptr kHeapMemEnd = 0;
555 static const uptr kVdsoBeg = 0;
556 static const uptr kShadowMsk = 0;
557 static const uptr kShadowXor = 0;
558 static const uptr kShadowAdd = 0x200000000000ull;
531559};
532560
533// Indicates the runtime will define the memory regions at runtime.
534#define TSAN_RUNTIME_VMA 1
535
536#elif SANITIZER_GO && defined(__mips64)
537561/*
538562Go on linux/mips64 (47-bit VMA)
5395630000 0000 1000 - 0000 1000 0000: executable
5405640000 1000 0000 - 00c0 0000 0000: -
54156500c0 0000 0000 - 00e0 0000 0000: heap
54256600e0 0000 0000 - 2000 0000 0000: -
5432000 0000 0000 - 3000 0000 0000: shadow
5443000 0000 0000 - 3000 0000 0000: -
5453000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
5464000 0000 0000 - 6000 0000 0000: -
5476000 0000 0000 - 6200 0000 0000: traces
5486200 0000 0000 - 8000 0000 0000: -
5672000 0000 0000 - 2800 0000 0000: shadow
5682800 0000 0000 - 3000 0000 0000: -
5693000 0000 0000 - 3200 0000 0000: metainfo (memory blocks and sync objects)
5703200 0000 0000 - 8000 0000 0000: -
549571*/
550struct Mapping47 {
572struct MappingGoMips64_47 {
551573 static const uptr kMetaShadowBeg = 0x300000000000ull;
552 static const uptr kMetaShadowEnd = 0x400000000000ull;
553 static const uptr kTraceMemBeg = 0x600000000000ull;
554 static const uptr kTraceMemEnd = 0x620000000000ull;
574 static const uptr kMetaShadowEnd = 0x320000000000ull;
555575 static const uptr kShadowBeg = 0x200000000000ull;
556 static const uptr kShadowEnd = 0x300000000000ull;
557 static const uptr kAppMemBeg = 0x000000001000ull;
558 static const uptr kAppMemEnd = 0x00e000000000ull;
576 static const uptr kShadowEnd = 0x280000000000ull;
577 static const uptr kLoAppMemBeg = 0x000000001000ull;
578 static const uptr kLoAppMemEnd = 0x00e000000000ull;
579 static const uptr kMidAppMemBeg = 0;
580 static const uptr kMidAppMemEnd = 0;
581 static const uptr kHiAppMemBeg = 0;
582 static const uptr kHiAppMemEnd = 0;
583 static const uptr kHeapMemBeg = 0;
584 static const uptr kHeapMemEnd = 0;
585 static const uptr kVdsoBeg = 0;
586 static const uptr kShadowMsk = 0;
587 static const uptr kShadowXor = 0;
588 static const uptr kShadowAdd = 0x200000000000ull;
559589};
560590
561#define TSAN_RUNTIME_VMA 1
562
563#elif SANITIZER_GO && defined(__s390x__)
564591/*
565592Go on linux/s390x
5665930000 0000 1000 - 1000 0000 0000: executable and heap - 16 TiB
5675941000 0000 0000 - 4000 0000 0000: -
5684000 0000 0000 - 8000 0000 0000: shadow - 64TiB (4 * app)
5698000 0000 0000 - 9000 0000 0000: -
5954000 0000 0000 - 6000 0000 0000: shadow - 64TiB (4 * app)
5966000 0000 0000 - 9000 0000 0000: -
5705979000 0000 0000 - 9800 0000 0000: metainfo - 8TiB (0.5 * app)
5719800 0000 0000 - a000 0000 0000: -
572a000 0000 0000 - b000 0000 0000: traces - 16TiB (max history * 128k threads)
573598*/
574struct Mapping {
599struct MappingGoS390x {
575600 static const uptr kMetaShadowBeg = 0x900000000000ull;
576601 static const uptr kMetaShadowEnd = 0x980000000000ull;
577 static const uptr kTraceMemBeg = 0xa00000000000ull;
578 static const uptr kTraceMemEnd = 0xb00000000000ull;
579602 static const uptr kShadowBeg = 0x400000000000ull;
580 static const uptr kShadowEnd = 0x800000000000ull;
581 static const uptr kAppMemBeg = 0x000000001000ull;
582 static const uptr kAppMemEnd = 0x100000000000ull;
603 static const uptr kShadowEnd = 0x600000000000ull;
604 static const uptr kLoAppMemBeg = 0x000000001000ull;
605 static const uptr kLoAppMemEnd = 0x100000000000ull;
606 static const uptr kMidAppMemBeg = 0;
607 static const uptr kMidAppMemEnd = 0;
608 static const uptr kHiAppMemBeg = 0;
609 static const uptr kHiAppMemEnd = 0;
610 static const uptr kHeapMemBeg = 0;
611 static const uptr kHeapMemEnd = 0;
612 static const uptr kVdsoBeg = 0;
613 static const uptr kShadowMsk = 0;
614 static const uptr kShadowXor = 0;
615 static const uptr kShadowAdd = 0x400000000000ull;
583616};
584617
585#else
586# error "Unknown platform"
587#endif
588
589
590#ifdef TSAN_RUNTIME_VMA
591618extern uptr vmaSize;
592#endif
593
594
595enum MappingType {
596 MAPPING_LO_APP_BEG,
597 MAPPING_LO_APP_END,
598 MAPPING_HI_APP_BEG,
599 MAPPING_HI_APP_END,
600#ifdef TSAN_MID_APP_RANGE
601 MAPPING_MID_APP_BEG,
602 MAPPING_MID_APP_END,
603#endif
604 MAPPING_HEAP_BEG,
605 MAPPING_HEAP_END,
606 MAPPING_APP_BEG,
607 MAPPING_APP_END,
608 MAPPING_SHADOW_BEG,
609 MAPPING_SHADOW_END,
610 MAPPING_META_SHADOW_BEG,
611 MAPPING_META_SHADOW_END,
612 MAPPING_TRACE_BEG,
613 MAPPING_TRACE_END,
614 MAPPING_VDSO_BEG,
615};
616619
617template<typename Mapping, int Type>
618uptr MappingImpl(void) {
619 switch (Type) {
620#if !SANITIZER_GO
621 case MAPPING_LO_APP_BEG: return Mapping::kLoAppMemBeg;
622 case MAPPING_LO_APP_END: return Mapping::kLoAppMemEnd;
623# ifdef TSAN_MID_APP_RANGE
624 case MAPPING_MID_APP_BEG: return Mapping::kMidAppMemBeg;
625 case MAPPING_MID_APP_END: return Mapping::kMidAppMemEnd;
626# endif
627 case MAPPING_HI_APP_BEG: return Mapping::kHiAppMemBeg;
628 case MAPPING_HI_APP_END: return Mapping::kHiAppMemEnd;
629 case MAPPING_HEAP_BEG: return Mapping::kHeapMemBeg;
630 case MAPPING_HEAP_END: return Mapping::kHeapMemEnd;
631 case MAPPING_VDSO_BEG: return Mapping::kVdsoBeg;
632#else
633 case MAPPING_APP_BEG: return Mapping::kAppMemBeg;
634 case MAPPING_APP_END: return Mapping::kAppMemEnd;
635#endif
636 case MAPPING_SHADOW_BEG: return Mapping::kShadowBeg;
637 case MAPPING_SHADOW_END: return Mapping::kShadowEnd;
638 case MAPPING_META_SHADOW_BEG: return Mapping::kMetaShadowBeg;
639 case MAPPING_META_SHADOW_END: return Mapping::kMetaShadowEnd;
640 case MAPPING_TRACE_BEG: return Mapping::kTraceMemBeg;
641 case MAPPING_TRACE_END: return Mapping::kTraceMemEnd;
642 }
643}
644
645template<int Type>
646uptr MappingArchImpl(void) {
647#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
620template <typename Func, typename Arg>
621ALWAYS_INLINE auto SelectMapping(Arg arg) {
622#if SANITIZER_GO
623# if defined(__powerpc64__)
648624 switch (vmaSize) {
649 case 39: return MappingImpl<Mapping39, Type>();
650 case 42: return MappingImpl<Mapping42, Type>();
651 case 48: return MappingImpl<Mapping48, Type>();
625 case 46:
626 return Func::template Apply<MappingGoPPC64_46>(arg);
627 case 47:
628 return Func::template Apply<MappingGoPPC64_47>(arg);
652629 }
653 DCHECK(0);
654 return 0;
655#elif defined(__powerpc64__)
630# elif defined(__mips64)
631 return Func::template Apply<MappingGoMips64_47>(arg);
632# elif defined(__s390x__)
633 return Func::template Apply<MappingGoS390x>(arg);
634# elif defined(__aarch64__)
635 return Func::template Apply<MappingGoAarch64>(arg);
636# elif SANITIZER_WINDOWS
637 return Func::template Apply<MappingGoWindows>(arg);
638# else
639 return Func::template Apply<MappingGo48>(arg);
640# endif
641#else // SANITIZER_GO
642# if SANITIZER_IOS && !SANITIZER_IOSSIM
643 return Func::template Apply<MappingAppleAarch64>(arg);
644# elif defined(__x86_64__) || SANITIZER_APPLE
645 return Func::template Apply<Mapping48AddressSpace>(arg);
646# elif defined(__aarch64__)
656647 switch (vmaSize) {
657#if !SANITIZER_GO
658 case 44: return MappingImpl<Mapping44, Type>();
659#endif
660 case 46: return MappingImpl<Mapping46, Type>();
661 case 47: return MappingImpl<Mapping47, Type>();
648 case 39:
649 return Func::template Apply<MappingAarch64_39>(arg);
650 case 42:
651 return Func::template Apply<MappingAarch64_42>(arg);
652 case 48:
653 return Func::template Apply<MappingAarch64_48>(arg);
662654 }
663 DCHECK(0);
664 return 0;
665#elif defined(__mips64)
655# elif SANITIZER_LOONGARCH64
656 return Func::template Apply<MappingLoongArch64_47>(arg);
657# elif defined(__powerpc64__)
666658 switch (vmaSize) {
667#if !SANITIZER_GO
668 case 40: return MappingImpl<Mapping40, Type>();
669#else
670 case 47: return MappingImpl<Mapping47, Type>();
671#endif
659 case 44:
660 return Func::template Apply<MappingPPC64_44>(arg);
661 case 46:
662 return Func::template Apply<MappingPPC64_46>(arg);
663 case 47:
664 return Func::template Apply<MappingPPC64_47>(arg);
672665 }
673 DCHECK(0);
674 return 0;
675#else
676 return MappingImpl<Mapping, Type>();
677#endif
666# elif defined(__mips64)
667 return Func::template Apply<MappingMips64_40>(arg);
668# elif defined(__s390x__)
669 return Func::template Apply<MappingS390x>(arg);
670# else
671# error "unsupported platform"
672# endif
673#endif
674 Die();
675}
676
677template <typename Func>
678void ForEachMapping() {
679 Func::template Apply<Mapping48AddressSpace>();
680 Func::template Apply<MappingMips64_40>();
681 Func::template Apply<MappingAppleAarch64>();
682 Func::template Apply<MappingAarch64_39>();
683 Func::template Apply<MappingAarch64_42>();
684 Func::template Apply<MappingAarch64_48>();
685 Func::template Apply<MappingLoongArch64_47>();
686 Func::template Apply<MappingPPC64_44>();
687 Func::template Apply<MappingPPC64_46>();
688 Func::template Apply<MappingPPC64_47>();
689 Func::template Apply<MappingS390x>();
690 Func::template Apply<MappingGo48>();
691 Func::template Apply<MappingGoWindows>();
692 Func::template Apply<MappingGoPPC64_46>();
693 Func::template Apply<MappingGoPPC64_47>();
694 Func::template Apply<MappingGoAarch64>();
695 Func::template Apply<MappingGoMips64_47>();
696 Func::template Apply<MappingGoS390x>();
678697}
679698
680#if !SANITIZER_GO
681ALWAYS_INLINE
682uptr LoAppMemBeg(void) {
683 return MappingArchImpl<MAPPING_LO_APP_BEG>();
684}
685ALWAYS_INLINE
686uptr LoAppMemEnd(void) {
687 return MappingArchImpl<MAPPING_LO_APP_END>();
688}
699enum MappingType {
700 kLoAppMemBeg,
701 kLoAppMemEnd,
702 kHiAppMemBeg,
703 kHiAppMemEnd,
704 kMidAppMemBeg,
705 kMidAppMemEnd,
706 kHeapMemBeg,
707 kHeapMemEnd,
708 kShadowBeg,
709 kShadowEnd,
710 kMetaShadowBeg,
711 kMetaShadowEnd,
712 kVdsoBeg,
713};
689714
690#ifdef TSAN_MID_APP_RANGE
691ALWAYS_INLINE
692uptr MidAppMemBeg(void) {
693 return MappingArchImpl<MAPPING_MID_APP_BEG>();
694}
695ALWAYS_INLINE
696uptr MidAppMemEnd(void) {
697 return MappingArchImpl<MAPPING_MID_APP_END>();
698}
699#endif
715struct MappingField {
716 template <typename Mapping>
717 static uptr Apply(MappingType type) {
718 switch (type) {
719 case kLoAppMemBeg:
720 return Mapping::kLoAppMemBeg;
721 case kLoAppMemEnd:
722 return Mapping::kLoAppMemEnd;
723 case kMidAppMemBeg:
724 return Mapping::kMidAppMemBeg;
725 case kMidAppMemEnd:
726 return Mapping::kMidAppMemEnd;
727 case kHiAppMemBeg:
728 return Mapping::kHiAppMemBeg;
729 case kHiAppMemEnd:
730 return Mapping::kHiAppMemEnd;
731 case kHeapMemBeg:
732 return Mapping::kHeapMemBeg;
733 case kHeapMemEnd:
734 return Mapping::kHeapMemEnd;
735 case kVdsoBeg:
736 return Mapping::kVdsoBeg;
737 case kShadowBeg:
738 return Mapping::kShadowBeg;
739 case kShadowEnd:
740 return Mapping::kShadowEnd;
741 case kMetaShadowBeg:
742 return Mapping::kMetaShadowBeg;
743 case kMetaShadowEnd:
744 return Mapping::kMetaShadowEnd;
745 }
746 Die();
747 }
748};
700749
701750ALWAYS_INLINE
702uptr HeapMemBeg(void) {
703 return MappingArchImpl<MAPPING_HEAP_BEG>();
704}
751uptr LoAppMemBeg(void) { return SelectMapping<MappingField>(kLoAppMemBeg); }
705752ALWAYS_INLINE
706uptr HeapMemEnd(void) {
707 return MappingArchImpl<MAPPING_HEAP_END>();
708}
753uptr LoAppMemEnd(void) { return SelectMapping<MappingField>(kLoAppMemEnd); }
709754
710755ALWAYS_INLINE
711uptr HiAppMemBeg(void) {
712 return MappingArchImpl<MAPPING_HI_APP_BEG>();
713}
756uptr MidAppMemBeg(void) { return SelectMapping<MappingField>(kMidAppMemBeg); }
714757ALWAYS_INLINE
715uptr HiAppMemEnd(void) {
716 return MappingArchImpl<MAPPING_HI_APP_END>();
717}
758uptr MidAppMemEnd(void) { return SelectMapping<MappingField>(kMidAppMemEnd); }
718759
719760ALWAYS_INLINE
720uptr VdsoBeg(void) {
721 return MappingArchImpl<MAPPING_VDSO_BEG>();
722}
723
724#else
761uptr HeapMemBeg(void) { return SelectMapping<MappingField>(kHeapMemBeg); }
762ALWAYS_INLINE
763uptr HeapMemEnd(void) { return SelectMapping<MappingField>(kHeapMemEnd); }
725764
726765ALWAYS_INLINE
727uptr AppMemBeg(void) {
728 return MappingArchImpl<MAPPING_APP_BEG>();
729}
766uptr HiAppMemBeg(void) { return SelectMapping<MappingField>(kHiAppMemBeg); }
730767ALWAYS_INLINE
731uptr AppMemEnd(void) {
732 return MappingArchImpl<MAPPING_APP_END>();
733}
734
735#endif
768uptr HiAppMemEnd(void) { return SelectMapping<MappingField>(kHiAppMemEnd); }
736769
737static inline
738bool GetUserRegion(int i, uptr *start, uptr *end) {
739 switch (i) {
740 default:
741 return false;
742#if !SANITIZER_GO
743 case 0:
744 *start = LoAppMemBeg();
745 *end = LoAppMemEnd();
746 return true;
747 case 1:
748 *start = HiAppMemBeg();
749 *end = HiAppMemEnd();
750 return true;
751 case 2:
752 *start = HeapMemBeg();
753 *end = HeapMemEnd();
754 return true;
755# ifdef TSAN_MID_APP_RANGE
756 case 3:
757 *start = MidAppMemBeg();
758 *end = MidAppMemEnd();
759 return true;
760# endif
761#else
762 case 0:
763 *start = AppMemBeg();
764 *end = AppMemEnd();
765 return true;
766#endif
767 }
768}
769
770ALWAYS_INLINE
771uptr ShadowBeg(void) {
772 return MappingArchImpl<MAPPING_SHADOW_BEG>();
773}
774770ALWAYS_INLINE
775uptr ShadowEnd(void) {
776 return MappingArchImpl<MAPPING_SHADOW_END>();
777}
771uptr VdsoBeg(void) { return SelectMapping<MappingField>(kVdsoBeg); }
778772
779773ALWAYS_INLINE
780uptr MetaShadowBeg(void) {
781 return MappingArchImpl<MAPPING_META_SHADOW_BEG>();
782}
774uptr ShadowBeg(void) { return SelectMapping<MappingField>(kShadowBeg); }
783775ALWAYS_INLINE
784uptr MetaShadowEnd(void) {
785 return MappingArchImpl<MAPPING_META_SHADOW_END>();
786}
776uptr ShadowEnd(void) { return SelectMapping<MappingField>(kShadowEnd); }
787777
788778ALWAYS_INLINE
789uptr TraceMemBeg(void) {
790 return MappingArchImpl<MAPPING_TRACE_BEG>();
791}
779uptr MetaShadowBeg(void) { return SelectMapping<MappingField>(kMetaShadowBeg); }
792780ALWAYS_INLINE
793uptr TraceMemEnd(void) {
794 return MappingArchImpl<MAPPING_TRACE_END>();
795}
796
781uptr MetaShadowEnd(void) { return SelectMapping<MappingField>(kMetaShadowEnd); }
797782
798template<typename Mapping>
799bool IsAppMemImpl(uptr mem) {
800#if !SANITIZER_GO
783struct IsAppMemImpl {
784 template <typename Mapping>
785 static bool Apply(uptr mem) {
801786 return (mem >= Mapping::kHeapMemBeg && mem < Mapping::kHeapMemEnd) ||
802# ifdef TSAN_MID_APP_RANGE
803787 (mem >= Mapping::kMidAppMemBeg && mem < Mapping::kMidAppMemEnd) ||
804# endif
805788 (mem >= Mapping::kLoAppMemBeg && mem < Mapping::kLoAppMemEnd) ||
806789 (mem >= Mapping::kHiAppMemBeg && mem < Mapping::kHiAppMemEnd);
807#else
808 return mem >= Mapping::kAppMemBeg && mem < Mapping::kAppMemEnd;
809#endif
810}
811
812ALWAYS_INLINE
813bool IsAppMem(uptr mem) {
814#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
815 switch (vmaSize) {
816 case 39: return IsAppMemImpl<Mapping39>(mem);
817 case 42: return IsAppMemImpl<Mapping42>(mem);
818 case 48: return IsAppMemImpl<Mapping48>(mem);
819 }
820 DCHECK(0);
821 return false;
822#elif defined(__powerpc64__)
823 switch (vmaSize) {
824#if !SANITIZER_GO
825 case 44: return IsAppMemImpl<Mapping44>(mem);
826#endif
827 case 46: return IsAppMemImpl<Mapping46>(mem);
828 case 47: return IsAppMemImpl<Mapping47>(mem);
829 }
830 DCHECK(0);
831 return false;
832#elif defined(__mips64)
833 switch (vmaSize) {
834#if !SANITIZER_GO
835 case 40: return IsAppMemImpl<Mapping40>(mem);
836#else
837 case 47: return IsAppMemImpl<Mapping47>(mem);
838#endif
839790 }
840 DCHECK(0);
841 return false;
842#else
843 return IsAppMemImpl<Mapping>(mem);
844#endif
845}
846
847
848template<typename Mapping>
849bool IsShadowMemImpl(uptr mem) {
850 return mem >= Mapping::kShadowBeg && mem <= Mapping::kShadowEnd;
851}
791};
852792
853793ALWAYS_INLINE
854bool IsShadowMem(uptr mem) {
855#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
856 switch (vmaSize) {
857 case 39: return IsShadowMemImpl<Mapping39>(mem);
858 case 42: return IsShadowMemImpl<Mapping42>(mem);
859 case 48: return IsShadowMemImpl<Mapping48>(mem);
860 }
861 DCHECK(0);
862 return false;
863#elif defined(__powerpc64__)
864 switch (vmaSize) {
865#if !SANITIZER_GO
866 case 44: return IsShadowMemImpl<Mapping44>(mem);
867#endif
868 case 46: return IsShadowMemImpl<Mapping46>(mem);
869 case 47: return IsShadowMemImpl<Mapping47>(mem);
870 }
871 DCHECK(0);
872 return false;
873#elif defined(__mips64)
874 switch (vmaSize) {
875#if !SANITIZER_GO
876 case 40: return IsShadowMemImpl<Mapping40>(mem);
877#else
878 case 47: return IsShadowMemImpl<Mapping47>(mem);
879#endif
880 }
881 DCHECK(0);
882 return false;
883#else
884 return IsShadowMemImpl<Mapping>(mem);
885#endif
886}
794bool IsAppMem(uptr mem) { return SelectMapping<IsAppMemImpl>(mem); }
887795
888
889template<typename Mapping>
890bool IsMetaMemImpl(uptr mem) {
891 return mem >= Mapping::kMetaShadowBeg && mem <= Mapping::kMetaShadowEnd;
892}
893
894ALWAYS_INLINE
895bool IsMetaMem(uptr mem) {
896#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
897 switch (vmaSize) {
898 case 39: return IsMetaMemImpl<Mapping39>(mem);
899 case 42: return IsMetaMemImpl<Mapping42>(mem);
900 case 48: return IsMetaMemImpl<Mapping48>(mem);
901 }
902 DCHECK(0);
903 return false;
904#elif defined(__powerpc64__)
905 switch (vmaSize) {
906#if !SANITIZER_GO
907 case 44: return IsMetaMemImpl<Mapping44>(mem);
908#endif
909 case 46: return IsMetaMemImpl<Mapping46>(mem);
910 case 47: return IsMetaMemImpl<Mapping47>(mem);
796struct IsShadowMemImpl {
797 template <typename Mapping>
798 static bool Apply(uptr mem) {
799 return mem >= Mapping::kShadowBeg && mem <= Mapping::kShadowEnd;
911800 }
912 DCHECK(0);
913 return false;
914#elif defined(__mips64)
915 switch (vmaSize) {
916#if !SANITIZER_GO
917 case 40: return IsMetaMemImpl<Mapping40>(mem);
918#else
919 case 47: return IsMetaMemImpl<Mapping47>(mem);
920#endif
921 }
922 DCHECK(0);
923 return false;
924#else
925 return IsMetaMemImpl<Mapping>(mem);
926#endif
927}
928
929
930template<typename Mapping>
931uptr MemToShadowImpl(uptr x) {
932 DCHECK(IsAppMem(x));
933#if !SANITIZER_GO
934 return (((x) & ~(Mapping::kAppMemMsk | (kShadowCell - 1)))
935 ^ Mapping::kAppMemXor) * kShadowCnt;
936#else
937# ifndef SANITIZER_WINDOWS
938 return ((x & ~(kShadowCell - 1)) * kShadowCnt) | Mapping::kShadowBeg;
939# else
940 return ((x & ~(kShadowCell - 1)) * kShadowCnt) + Mapping::kShadowBeg;
941# endif
942#endif
943}
801};
944802
945803ALWAYS_INLINE
946uptr MemToShadow(uptr x) {
947#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
948 switch (vmaSize) {
949 case 39: return MemToShadowImpl<Mapping39>(x);
950 case 42: return MemToShadowImpl<Mapping42>(x);
951 case 48: return MemToShadowImpl<Mapping48>(x);
952 }
953 DCHECK(0);
954 return 0;
955#elif defined(__powerpc64__)
956 switch (vmaSize) {
957#if !SANITIZER_GO
958 case 44: return MemToShadowImpl<Mapping44>(x);
959#endif
960 case 46: return MemToShadowImpl<Mapping46>(x);
961 case 47: return MemToShadowImpl<Mapping47>(x);
962 }
963 DCHECK(0);
964 return 0;
965#elif defined(__mips64)
966 switch (vmaSize) {
967#if !SANITIZER_GO
968 case 40: return MemToShadowImpl<Mapping40>(x);
969#else
970 case 47: return MemToShadowImpl<Mapping47>(x);
971#endif
972 }
973 DCHECK(0);
974 return 0;
975#else
976 return MemToShadowImpl<Mapping>(x);
977#endif
804bool IsShadowMem(RawShadow *p) {
805 return SelectMapping<IsShadowMemImpl>(reinterpret_cast<uptr>(p));
978806}
979807
980
981template<typename Mapping>
982u32 *MemToMetaImpl(uptr x) {
983 DCHECK(IsAppMem(x));
984#if !SANITIZER_GO
985 return (u32*)(((((x) & ~(Mapping::kAppMemMsk | (kMetaShadowCell - 1)))) /
986 kMetaShadowCell * kMetaShadowSize) | Mapping::kMetaShadowBeg);
987#else
988# ifndef SANITIZER_WINDOWS
989 return (u32*)(((x & ~(kMetaShadowCell - 1)) / \
990 kMetaShadowCell * kMetaShadowSize) | Mapping::kMetaShadowBeg);
991# else
992 return (u32*)(((x & ~(kMetaShadowCell - 1)) / \
993 kMetaShadowCell * kMetaShadowSize) + Mapping::kMetaShadowBeg);
994# endif
995#endif
996}
808struct IsMetaMemImpl {
809 template <typename Mapping>
810 static bool Apply(uptr mem) {
811 return mem >= Mapping::kMetaShadowBeg && mem <= Mapping::kMetaShadowEnd;
812 }
813};
997814
998815ALWAYS_INLINE
999u32 *MemToMeta(uptr x) {
1000#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
1001 switch (vmaSize) {
1002 case 39: return MemToMetaImpl<Mapping39>(x);
1003 case 42: return MemToMetaImpl<Mapping42>(x);
1004 case 48: return MemToMetaImpl<Mapping48>(x);
1005 }
1006 DCHECK(0);
1007 return 0;
1008#elif defined(__powerpc64__)
1009 switch (vmaSize) {
1010#if !SANITIZER_GO
1011 case 44: return MemToMetaImpl<Mapping44>(x);
1012#endif
1013 case 46: return MemToMetaImpl<Mapping46>(x);
1014 case 47: return MemToMetaImpl<Mapping47>(x);
1015 }
1016 DCHECK(0);
1017 return 0;
1018#elif defined(__mips64)
1019 switch (vmaSize) {
1020#if !SANITIZER_GO
1021 case 40: return MemToMetaImpl<Mapping40>(x);
1022#else
1023 case 47: return MemToMetaImpl<Mapping47>(x);
1024#endif
816bool IsMetaMem(const u32 *p) {
817 return SelectMapping<IsMetaMemImpl>(reinterpret_cast<uptr>(p));
818}
819
820struct MemToShadowImpl {
821 template <typename Mapping>
822 static uptr Apply(uptr x) {
823 DCHECK(IsAppMemImpl::Apply<Mapping>(x));
824 return (((x) & ~(Mapping::kShadowMsk | (kShadowCell - 1))) ^
825 Mapping::kShadowXor) *
826 kShadowMultiplier +
827 Mapping::kShadowAdd;
1025828 }
1026 DCHECK(0);
1027 return 0;
1028#else
1029 return MemToMetaImpl<Mapping>(x);
1030#endif
1031}
1032
1033
1034template<typename Mapping>
1035uptr ShadowToMemImpl(uptr s) {
1036 DCHECK(IsShadowMem(s));
1037#if !SANITIZER_GO
1038 // The shadow mapping is non-linear and we've lost some bits, so we don't have
1039 // an easy way to restore the original app address. But the mapping is a
1040 // bijection, so we try to restore the address as belonging to low/mid/high
1041 // range consecutively and see if shadow->app->shadow mapping gives us the
1042 // same address.
1043 uptr p = (s / kShadowCnt) ^ Mapping::kAppMemXor;
1044 if (p >= Mapping::kLoAppMemBeg && p < Mapping::kLoAppMemEnd &&
1045 MemToShadow(p) == s)
1046 return p;
1047# ifdef TSAN_MID_APP_RANGE
1048 p = ((s / kShadowCnt) ^ Mapping::kAppMemXor) +
1049 (Mapping::kMidAppMemBeg & Mapping::kAppMemMsk);
1050 if (p >= Mapping::kMidAppMemBeg && p < Mapping::kMidAppMemEnd &&
1051 MemToShadow(p) == s)
1052 return p;
1053# endif
1054 return ((s / kShadowCnt) ^ Mapping::kAppMemXor) | Mapping::kAppMemMsk;
1055#else // #if !SANITIZER_GO
1056# ifndef SANITIZER_WINDOWS
1057 return (s & ~Mapping::kShadowBeg) / kShadowCnt;
1058# else
1059 return (s - Mapping::kShadowBeg) / kShadowCnt;
1060# endif // SANITIZER_WINDOWS
1061#endif
1062}
829};
1063830
1064831ALWAYS_INLINE
1065uptr ShadowToMem(uptr s) {
1066#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
1067 switch (vmaSize) {
1068 case 39: return ShadowToMemImpl<Mapping39>(s);
1069 case 42: return ShadowToMemImpl<Mapping42>(s);
1070 case 48: return ShadowToMemImpl<Mapping48>(s);
1071 }
1072 DCHECK(0);
1073 return 0;
1074#elif defined(__powerpc64__)
1075 switch (vmaSize) {
1076#if !SANITIZER_GO
1077 case 44: return ShadowToMemImpl<Mapping44>(s);
1078#endif
1079 case 46: return ShadowToMemImpl<Mapping46>(s);
1080 case 47: return ShadowToMemImpl<Mapping47>(s);
1081 }
1082 DCHECK(0);
1083 return 0;
1084#elif defined(__mips64)
1085 switch (vmaSize) {
1086#if !SANITIZER_GO
1087 case 40: return ShadowToMemImpl<Mapping40>(s);
1088#else
1089 case 47: return ShadowToMemImpl<Mapping47>(s);
1090#endif
1091 }
1092 DCHECK(0);
1093 return 0;
1094#else
1095 return ShadowToMemImpl<Mapping>(s);
1096#endif
832RawShadow *MemToShadow(uptr x) {
833 return reinterpret_cast<RawShadow *>(SelectMapping<MemToShadowImpl>(x));
1097834}
1098835
1099
1100
1101// The additional page is to catch shadow stack overflow as paging fault.
1102// Windows wants 64K alignment for mmaps.
1103const uptr kTotalTraceSize = (kTraceSize * sizeof(Event) + sizeof(Trace)
1104 + (64 << 10) + (64 << 10) - 1) & ~((64 << 10) - 1);
1105
1106template<typename Mapping>
1107uptr GetThreadTraceImpl(int tid) {
1108 uptr p = Mapping::kTraceMemBeg + (uptr)tid * kTotalTraceSize;
1109 DCHECK_LT(p, Mapping::kTraceMemEnd);
1110 return p;
1111}
836struct MemToMetaImpl {
837 template <typename Mapping>
838 static u32 *Apply(uptr x) {
839 DCHECK(IsAppMemImpl::Apply<Mapping>(x));
840 return (u32 *)(((((x) & ~(Mapping::kShadowMsk | (kMetaShadowCell - 1)))) /
841 kMetaShadowCell * kMetaShadowSize) |
842 Mapping::kMetaShadowBeg);
843 }
844};
1112845
1113846ALWAYS_INLINE
1114uptr GetThreadTrace(int tid) {
1115#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
1116 switch (vmaSize) {
1117 case 39: return GetThreadTraceImpl<Mapping39>(tid);
1118 case 42: return GetThreadTraceImpl<Mapping42>(tid);
1119 case 48: return GetThreadTraceImpl<Mapping48>(tid);
1120 }
1121 DCHECK(0);
1122 return 0;
1123#elif defined(__powerpc64__)
1124 switch (vmaSize) {
1125#if !SANITIZER_GO
1126 case 44: return GetThreadTraceImpl<Mapping44>(tid);
1127#endif
1128 case 46: return GetThreadTraceImpl<Mapping46>(tid);
1129 case 47: return GetThreadTraceImpl<Mapping47>(tid);
847u32 *MemToMeta(uptr x) { return SelectMapping<MemToMetaImpl>(x); }
848
849struct ShadowToMemImpl {
850 template <typename Mapping>
851 static uptr Apply(uptr sp) {
852 if (!IsShadowMemImpl::Apply<Mapping>(sp))
853 return 0;
854 // The shadow mapping is non-linear and we've lost some bits, so we don't
855 // have an easy way to restore the original app address. But the mapping is
856 // a bijection, so we try to restore the address as belonging to
857 // low/mid/high range consecutively and see if shadow->app->shadow mapping
858 // gives us the same address.
859 uptr p =
860 ((sp - Mapping::kShadowAdd) / kShadowMultiplier) ^ Mapping::kShadowXor;
861 if (p >= Mapping::kLoAppMemBeg && p < Mapping::kLoAppMemEnd &&
862 MemToShadowImpl::Apply<Mapping>(p) == sp)
863 return p;
864 if (Mapping::kMidAppMemBeg) {
865 uptr p_mid = p + (Mapping::kMidAppMemBeg & Mapping::kShadowMsk);
866 if (p_mid >= Mapping::kMidAppMemBeg && p_mid < Mapping::kMidAppMemEnd &&
867 MemToShadowImpl::Apply<Mapping>(p_mid) == sp)
868 return p_mid;
869 }
870 return p | Mapping::kShadowMsk;
1130871 }
1131 DCHECK(0);
1132 return 0;
1133#elif defined(__mips64)
1134 switch (vmaSize) {
1135#if !SANITIZER_GO
1136 case 40: return GetThreadTraceImpl<Mapping40>(tid);
1137#else
1138 case 47: return GetThreadTraceImpl<Mapping47>(tid);
1139#endif
1140 }
1141 DCHECK(0);
1142 return 0;
1143#else
1144 return GetThreadTraceImpl<Mapping>(tid);
1145#endif
1146}
1147
1148
1149template<typename Mapping>
1150uptr GetThreadTraceHeaderImpl(int tid) {
1151 uptr p = Mapping::kTraceMemBeg + (uptr)tid * kTotalTraceSize
1152 + kTraceSize * sizeof(Event);
1153 DCHECK_LT(p, Mapping::kTraceMemEnd);
1154 return p;
1155}
872};
1156873
1157874ALWAYS_INLINE
1158uptr GetThreadTraceHeader(int tid) {
1159#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
1160 switch (vmaSize) {
1161 case 39: return GetThreadTraceHeaderImpl<Mapping39>(tid);
1162 case 42: return GetThreadTraceHeaderImpl<Mapping42>(tid);
1163 case 48: return GetThreadTraceHeaderImpl<Mapping48>(tid);
1164 }
1165 DCHECK(0);
1166 return 0;
1167#elif defined(__powerpc64__)
1168 switch (vmaSize) {
1169#if !SANITIZER_GO
1170 case 44: return GetThreadTraceHeaderImpl<Mapping44>(tid);
1171#endif
1172 case 46: return GetThreadTraceHeaderImpl<Mapping46>(tid);
1173 case 47: return GetThreadTraceHeaderImpl<Mapping47>(tid);
875uptr ShadowToMem(RawShadow *s) {
876 return SelectMapping<ShadowToMemImpl>(reinterpret_cast<uptr>(s));
877}
878
879// Compresses addr to kCompressedAddrBits stored in least significant bits.
880ALWAYS_INLINE uptr CompressAddr(uptr addr) {
881 return addr & ((1ull << kCompressedAddrBits) - 1);
882}
883
884struct RestoreAddrImpl {
885 typedef uptr Result;
886 template <typename Mapping>
887 static Result Apply(uptr addr) {
888 // To restore the address we go over all app memory ranges and check if top
889 // 3 bits of the compressed addr match that of the app range. If yes, we
890 // assume that the compressed address come from that range and restore the
891 // missing top bits to match the app range address.
892 const uptr ranges[] = {
893 Mapping::kLoAppMemBeg, Mapping::kLoAppMemEnd, Mapping::kMidAppMemBeg,
894 Mapping::kMidAppMemEnd, Mapping::kHiAppMemBeg, Mapping::kHiAppMemEnd,
895 Mapping::kHeapMemBeg, Mapping::kHeapMemEnd,
896 };
897 const uptr indicator = 0x0e0000000000ull;
898 const uptr ind_lsb = 1ull << LeastSignificantSetBitIndex(indicator);
899 for (uptr i = 0; i < ARRAY_SIZE(ranges); i += 2) {
900 uptr beg = ranges[i];
901 uptr end = ranges[i + 1];
902 if (beg == end)
903 continue;
904 for (uptr p = beg; p < end; p = RoundDown(p + ind_lsb, ind_lsb)) {
905 if ((addr & indicator) == (p & indicator))
906 return addr | (p & ~(ind_lsb - 1));
907 }
908 }
909 Printf("ThreadSanitizer: failed to restore address 0x%zx\n", addr);
910 Die();
1174911 }
1175 DCHECK(0);
1176 return 0;
1177#elif defined(__mips64)
1178 switch (vmaSize) {
1179#if !SANITIZER_GO
1180 case 40: return GetThreadTraceHeaderImpl<Mapping40>(tid);
1181#else
1182 case 47: return GetThreadTraceHeaderImpl<Mapping47>(tid);
1183#endif
1184 }
1185 DCHECK(0);
1186 return 0;
1187#else
1188 return GetThreadTraceHeaderImpl<Mapping>(tid);
1189#endif
912};
913
914// Restores compressed addr from kCompressedAddrBits to full representation.
915// This is called only during reporting and is not performance-critical.
916inline uptr RestoreAddr(uptr addr) {
917 return SelectMapping<RestoreAddrImpl>(addr);
1190918}
1191919
1192920void InitializePlatform();
1193921void InitializePlatformEarly();
1194922void CheckAndProtect();
1195923void InitializeShadowMemoryPlatform();
1196void FlushShadowMemory();
1197void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive);
924void WriteMemoryProfile(char *buf, uptr buf_size, u64 uptime_ns);
1198925int ExtractResolvFDs(void *state, int *fds, int nfd);
1199926int ExtractRecvmsgFDs(void *msg, int *fds, int nfd);
1200927uptr ExtractLongJmpSp(uptr *env);
lib/tsan/tsan_platform_linux.cpp+89-68
......@@ -66,7 +66,8 @@ extern "C" void *__libc_stack_end;
6666void *__libc_stack_end = 0;
6767#endif
6868
69#if SANITIZER_LINUX && defined(__aarch64__) && !SANITIZER_GO
69#if SANITIZER_LINUX && (defined(__aarch64__) || defined(__loongarch_lp64)) && \
70 !SANITIZER_GO
7071# define INIT_LONGJMP_XOR_KEY 1
7172#else
7273# define INIT_LONGJMP_XOR_KEY 0
......@@ -85,78 +86,71 @@ static void InitializeLongjmpXorKey();
8586static uptr longjmp_xor_key;
8687#endif
8788
88#ifdef TSAN_RUNTIME_VMA
8989// Runtime detected VMA size.
9090uptr vmaSize;
91#endif
9291
9392enum {
94 MemTotal = 0,
95 MemShadow = 1,
96 MemMeta = 2,
97 MemFile = 3,
98 MemMmap = 4,
99 MemTrace = 5,
100 MemHeap = 6,
101 MemOther = 7,
102 MemCount = 8,
93 MemTotal,
94 MemShadow,
95 MemMeta,
96 MemFile,
97 MemMmap,
98 MemHeap,
99 MemOther,
100 MemCount,
103101};
104102
105void FillProfileCallback(uptr p, uptr rss, bool file,
106 uptr *mem, uptr stats_size) {
103void FillProfileCallback(uptr p, uptr rss, bool file, uptr *mem) {
107104 mem[MemTotal] += rss;
108105 if (p >= ShadowBeg() && p < ShadowEnd())
109106 mem[MemShadow] += rss;
110107 else if (p >= MetaShadowBeg() && p < MetaShadowEnd())
111108 mem[MemMeta] += rss;
112#if !SANITIZER_GO
109 else if ((p >= LoAppMemBeg() && p < LoAppMemEnd()) ||
110 (p >= MidAppMemBeg() && p < MidAppMemEnd()) ||
111 (p >= HiAppMemBeg() && p < HiAppMemEnd()))
112 mem[file ? MemFile : MemMmap] += rss;
113113 else if (p >= HeapMemBeg() && p < HeapMemEnd())
114114 mem[MemHeap] += rss;
115 else if (p >= LoAppMemBeg() && p < LoAppMemEnd())
116 mem[file ? MemFile : MemMmap] += rss;
117 else if (p >= HiAppMemBeg() && p < HiAppMemEnd())
118 mem[file ? MemFile : MemMmap] += rss;
119#else
120 else if (p >= AppMemBeg() && p < AppMemEnd())
121 mem[file ? MemFile : MemMmap] += rss;
122#endif
123 else if (p >= TraceMemBeg() && p < TraceMemEnd())
124 mem[MemTrace] += rss;
125115 else
126116 mem[MemOther] += rss;
127117}
128118
129void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive) {
119void WriteMemoryProfile(char *buf, uptr buf_size, u64 uptime_ns) {
130120 uptr mem[MemCount];
131 internal_memset(mem, 0, sizeof(mem[0]) * MemCount);
132 __sanitizer::GetMemoryProfile(FillProfileCallback, mem, 7);
133 StackDepotStats *stacks = StackDepotGetStats();
134 internal_snprintf(buf, buf_size,
135 "RSS %zd MB: shadow:%zd meta:%zd file:%zd mmap:%zd"
136 " trace:%zd heap:%zd other:%zd stacks=%zd[%zd] nthr=%zd/%zd\n",
121 internal_memset(mem, 0, sizeof(mem));
122 GetMemoryProfile(FillProfileCallback, mem);
123 auto meta = ctx->metamap.GetMemoryStats();
124 StackDepotStats stacks = StackDepotGetStats();
125 uptr nthread, nlive;
126 ctx->thread_registry.GetNumberOfThreads(&nthread, &nlive);
127 uptr trace_mem;
128 {
129 Lock l(&ctx->slot_mtx);
130 trace_mem = ctx->trace_part_total_allocated * sizeof(TracePart);
131 }
132 uptr internal_stats[AllocatorStatCount];
133 internal_allocator()->GetStats(internal_stats);
134 // All these are allocated from the common mmap region.
135 mem[MemMmap] -= meta.mem_block + meta.sync_obj + trace_mem +
136 stacks.allocated + internal_stats[AllocatorStatMapped];
137 if (s64(mem[MemMmap]) < 0)
138 mem[MemMmap] = 0;
139 internal_snprintf(
140 buf, buf_size,
141 "==%zu== %llus [%zu]: RSS %zd MB: shadow:%zd meta:%zd file:%zd"
142 " mmap:%zd heap:%zd other:%zd intalloc:%zd memblocks:%zd syncobj:%zu"
143 " trace:%zu stacks=%zd threads=%zu/%zu\n",
144 internal_getpid(), uptime_ns / (1000 * 1000 * 1000), ctx->global_epoch,
137145 mem[MemTotal] >> 20, mem[MemShadow] >> 20, mem[MemMeta] >> 20,
138 mem[MemFile] >> 20, mem[MemMmap] >> 20, mem[MemTrace] >> 20,
139 mem[MemHeap] >> 20, mem[MemOther] >> 20,
140 stacks->allocated >> 20, stacks->n_uniq_ids,
141 nlive, nthread);
142}
143
144#if SANITIZER_LINUX
145void FlushShadowMemoryCallback(
146 const SuspendedThreadsList &suspended_threads_list,
147 void *argument) {
148 ReleaseMemoryPagesToOS(ShadowBeg(), ShadowEnd());
149}
150#endif
151
152void FlushShadowMemory() {
153#if SANITIZER_LINUX
154 StopTheWorld(FlushShadowMemoryCallback, 0);
155#endif
146 mem[MemFile] >> 20, mem[MemMmap] >> 20, mem[MemHeap] >> 20,
147 mem[MemOther] >> 20, internal_stats[AllocatorStatMapped] >> 20,
148 meta.mem_block >> 20, meta.sync_obj >> 20, trace_mem >> 20,
149 stacks.allocated >> 20, nlive, nthread);
156150}
157151
158152#if !SANITIZER_GO
159// Mark shadow for .rodata sections with the special kShadowRodata marker.
153// Mark shadow for .rodata sections with the special Shadow::kRodata marker.
160154// Accesses to .rodata can't race, so this saves time, memory and trace space.
161155static void MapRodata() {
162156 // First create temp file.
......@@ -177,13 +171,14 @@ static void MapRodata() {
177171 return;
178172 internal_unlink(name); // Unlink it now, so that we can reuse the buffer.
179173 fd_t fd = openrv;
180 // Fill the file with kShadowRodata.
181 const uptr kMarkerSize = 512 * 1024 / sizeof(u64);
182 InternalMmapVector<u64> marker(kMarkerSize);
174 // Fill the file with Shadow::kRodata.
175 const uptr kMarkerSize = 512 * 1024 / sizeof(RawShadow);
176 InternalMmapVector<RawShadow> marker(kMarkerSize);
183177 // volatile to prevent insertion of memset
184 for (volatile u64 *p = marker.data(); p < marker.data() + kMarkerSize; p++)
185 *p = kShadowRodata;
186 internal_write(fd, marker.data(), marker.size() * sizeof(u64));
178 for (volatile RawShadow *p = marker.data(); p < marker.data() + kMarkerSize;
179 p++)
180 *p = Shadow::kRodata;
181 internal_write(fd, marker.data(), marker.size() * sizeof(RawShadow));
187182 // Map the file into memory.
188183 uptr page = internal_mmap(0, GetPageSizeCached(), PROT_READ | PROT_WRITE,
189184 MAP_PRIVATE | MAP_ANONYMOUS, fd, 0);
......@@ -203,9 +198,10 @@ static void MapRodata() {
203198 char *shadow_start = (char *)MemToShadow(segment.start);
204199 char *shadow_end = (char *)MemToShadow(segment.end);
205200 for (char *p = shadow_start; p < shadow_end;
206 p += marker.size() * sizeof(u64)) {
207 internal_mmap(p, Min<uptr>(marker.size() * sizeof(u64), shadow_end - p),
208 PROT_READ, MAP_PRIVATE | MAP_FIXED, fd, 0);
201 p += marker.size() * sizeof(RawShadow)) {
202 internal_mmap(
203 p, Min<uptr>(marker.size() * sizeof(RawShadow), shadow_end - p),
204 PROT_READ, MAP_PRIVATE | MAP_FIXED, fd, 0);
209205 }
210206 }
211207 }
......@@ -219,7 +215,6 @@ void InitializeShadowMemoryPlatform() {
219215#endif // #if !SANITIZER_GO
220216
221217void InitializePlatformEarly() {
222#ifdef TSAN_RUNTIME_VMA
223218 vmaSize =
224219 (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1);
225220#if defined(__aarch64__)
......@@ -236,6 +231,14 @@ void InitializePlatformEarly() {
236231 Die();
237232 }
238233#endif
234#elif SANITIZER_LOONGARCH64
235# if !SANITIZER_GO
236 if (vmaSize != 47) {
237 Printf("FATAL: ThreadSanitizer: unsupported VMA range\n");
238 Printf("FATAL: Found %zd - Supported 47\n", vmaSize);
239 Die();
240 }
241# endif
239242#elif defined(__powerpc64__)
240243# if !SANITIZER_GO
241244 if (vmaSize != 44 && vmaSize != 46 && vmaSize != 47) {
......@@ -265,7 +268,6 @@ void InitializePlatformEarly() {
265268 }
266269# endif
267270#endif
268#endif
269271}
270272
271273void InitializePlatform() {
......@@ -297,11 +299,12 @@ void InitializePlatform() {
297299 SetAddressSpaceUnlimited();
298300 reexec = true;
299301 }
300#if SANITIZER_LINUX && defined(__aarch64__)
302#if SANITIZER_ANDROID && (defined(__aarch64__) || defined(__x86_64__))
301303 // After patch "arm64: mm: support ARCH_MMAP_RND_BITS." is introduced in
302304 // linux kernel, the random gap between stack and mapped area is increased
303305 // from 128M to 36G on 39-bit aarch64. As it is almost impossible to cover
304306 // this big range, we should disable randomized virtual space on aarch64.
307 // ASLR personality check.
305308 int old_personality = personality(0xffffffff);
306309 if (old_personality != -1 && (old_personality & ADDR_NO_RANDOMIZE) == 0) {
307310 VReport(1, "WARNING: Program is run with randomized virtual address "
......@@ -310,6 +313,9 @@ void InitializePlatform() {
310313 CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1);
311314 reexec = true;
312315 }
316
317#endif
318#if SANITIZER_LINUX && (defined(__aarch64__) || defined(__loongarch_lp64))
313319 // Initialize the xor key used in {sig}{set,long}jump.
314320 InitializeLongjmpXorKey();
315321#endif
......@@ -341,7 +347,7 @@ int ExtractResolvFDs(void *state, int *fds, int nfd) {
341347}
342348
343349// Extract file descriptors passed via UNIX domain sockets.
344// This is requried to properly handle "open" of these fds.
350// This is required to properly handle "open" of these fds.
345351// see 'man recvmsg' and 'man 3 cmsg'.
346352int ExtractRecvmsgFDs(void *msgp, int *fds, int nfd) {
347353 int res = 0;
......@@ -382,6 +388,8 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) {
382388# else
383389 return mangled_sp;
384390# endif
391#elif defined(__loongarch_lp64)
392 return mangled_sp ^ longjmp_xor_key;
385393#elif defined(__powerpc64__)
386394 // Reverse of:
387395 // ld r4, -28696(r13)
......@@ -409,10 +417,16 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) {
409417#elif defined(__powerpc__)
410418# define LONG_JMP_SP_ENV_SLOT 0
411419#elif SANITIZER_FREEBSD
412# define LONG_JMP_SP_ENV_SLOT 2
420# ifdef __aarch64__
421# define LONG_JMP_SP_ENV_SLOT 1
422# else
423# define LONG_JMP_SP_ENV_SLOT 2
424# endif
413425#elif SANITIZER_LINUX
414426# ifdef __aarch64__
415427# define LONG_JMP_SP_ENV_SLOT 13
428# elif defined(__loongarch__)
429# define LONG_JMP_SP_ENV_SLOT 1
416430# elif defined(__mips64)
417431# define LONG_JMP_SP_ENV_SLOT 1
418432# elif defined(__s390x__)
......@@ -439,7 +453,11 @@ static void InitializeLongjmpXorKey() {
439453
440454 // 2. Retrieve vanilla/mangled SP.
441455 uptr sp;
456#ifdef __loongarch__
457 asm("move %0, $sp" : "=r" (sp));
458#else
442459 asm("mov %0, sp" : "=r" (sp));
460#endif
443461 uptr mangled_sp = ((uptr *)&env)[LONG_JMP_SP_ENV_SLOT];
444462
445463 // 3. xor SPs to obtain key.
......@@ -447,6 +465,8 @@ static void InitializeLongjmpXorKey() {
447465}
448466#endif
449467
468extern "C" void __tsan_tls_initialization() {}
469
450470void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size) {
451471 // Check that the thr object is in tls;
452472 const uptr thr_beg = (uptr)thr;
......@@ -456,9 +476,10 @@ void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size) {
456476 CHECK_GE(thr_end, tls_addr);
457477 CHECK_LE(thr_end, tls_addr + tls_size);
458478 // Since the thr object is huge, skip it.
459 MemoryRangeImitateWrite(thr, /*pc=*/2, tls_addr, thr_beg - tls_addr);
460 MemoryRangeImitateWrite(thr, /*pc=*/2, thr_end,
461 tls_addr + tls_size - thr_end);
479 const uptr pc = StackTrace::GetNextInstructionPc(
480 reinterpret_cast<uptr>(__tsan_tls_initialization));
481 MemoryRangeImitateWrite(thr, pc, tls_addr, thr_beg - tls_addr);
482 MemoryRangeImitateWrite(thr, pc, thr_end, tls_addr + tls_size - thr_end);
462483}
463484
464485// Note: this function runs with async signals enabled,
lib/tsan/tsan_platform_mac.cpp+130-149
......@@ -12,7 +12,7 @@
1212//===----------------------------------------------------------------------===//
1313
1414#include "sanitizer_common/sanitizer_platform.h"
15#if SANITIZER_MAC
15#if SANITIZER_APPLE
1616
1717#include "sanitizer_common/sanitizer_atomic.h"
1818#include "sanitizer_common/sanitizer_common.h"
......@@ -25,6 +25,7 @@
2525#include "tsan_rtl.h"
2626#include "tsan_flags.h"
2727
28#include <limits.h>
2829#include <mach/mach.h>
2930#include <pthread.h>
3031#include <signal.h>
......@@ -45,76 +46,86 @@
4546namespace __tsan {
4647
4748#if !SANITIZER_GO
48static void *SignalSafeGetOrAllocate(uptr *dst, uptr size) {
49 atomic_uintptr_t *a = (atomic_uintptr_t *)dst;
50 void *val = (void *)atomic_load_relaxed(a);
51 atomic_signal_fence(memory_order_acquire); // Turns the previous load into
52 // acquire wrt signals.
53 if (UNLIKELY(val == nullptr)) {
54 val = (void *)internal_mmap(nullptr, size, PROT_READ | PROT_WRITE,
55 MAP_PRIVATE | MAP_ANON, -1, 0);
56 CHECK(val);
57 void *cmp = nullptr;
58 if (!atomic_compare_exchange_strong(a, (uintptr_t *)&cmp, (uintptr_t)val,
59 memory_order_acq_rel)) {
60 internal_munmap(val, size);
61 val = cmp;
62 }
63 }
64 return val;
49static char main_thread_state[sizeof(ThreadState)] ALIGNED(
50 SANITIZER_CACHE_LINE_SIZE);
51static ThreadState *dead_thread_state;
52static pthread_key_t thread_state_key;
53
54// We rely on the following documented, but Darwin-specific behavior to keep the
55// reference to the ThreadState object alive in TLS:
56// pthread_key_create man page:
57// If, after all the destructors have been called for all non-NULL values with
58// associated destructors, there are still some non-NULL values with
59// associated destructors, then the process is repeated. If, after at least
60// [PTHREAD_DESTRUCTOR_ITERATIONS] iterations of destructor calls for
61// outstanding non-NULL values, there are still some non-NULL values with
62// associated destructors, the implementation stops calling destructors.
63static_assert(PTHREAD_DESTRUCTOR_ITERATIONS == 4, "Small number of iterations");
64static void ThreadStateDestructor(void *thr) {
65 int res = pthread_setspecific(thread_state_key, thr);
66 CHECK_EQ(res, 0);
6567}
6668
67// On OS X, accessing TLVs via __thread or manually by using pthread_key_* is
68// problematic, because there are several places where interceptors are called
69// when TLVs are not accessible (early process startup, thread cleanup, ...).
70// The following provides a "poor man's TLV" implementation, where we use the
71// shadow memory of the pointer returned by pthread_self() to store a pointer to
72// the ThreadState object. The main thread's ThreadState is stored separately
73// in a static variable, because we need to access it even before the
74// shadow memory is set up.
75static uptr main_thread_identity = 0;
76ALIGNED(64) static char main_thread_state[sizeof(ThreadState)];
77static ThreadState *main_thread_state_loc = (ThreadState *)main_thread_state;
78
79// We cannot use pthread_self() before libpthread has been initialized. Our
80// current heuristic for guarding this is checking `main_thread_identity` which
81// is only assigned in `__tsan::InitializePlatform`.
82static ThreadState **cur_thread_location() {
83 if (main_thread_identity == 0)
84 return &main_thread_state_loc;
85 uptr thread_identity = (uptr)pthread_self();
86 if (thread_identity == main_thread_identity)
87 return &main_thread_state_loc;
88 return (ThreadState **)MemToShadow(thread_identity);
69static void InitializeThreadStateStorage() {
70 int res;
71 CHECK_EQ(thread_state_key, 0);
72 res = pthread_key_create(&thread_state_key, ThreadStateDestructor);
73 CHECK_EQ(res, 0);
74 res = pthread_setspecific(thread_state_key, main_thread_state);
75 CHECK_EQ(res, 0);
76
77 auto dts = (ThreadState *)MmapOrDie(sizeof(ThreadState), "ThreadState");
78 dts->fast_state.SetIgnoreBit();
79 dts->ignore_interceptors = 1;
80 dts->is_dead = true;
81 const_cast<Tid &>(dts->tid) = kInvalidTid;
82 res = internal_mprotect(dts, sizeof(ThreadState), PROT_READ); // immutable
83 CHECK_EQ(res, 0);
84 dead_thread_state = dts;
8985}
9086
9187ThreadState *cur_thread() {
92 return (ThreadState *)SignalSafeGetOrAllocate(
93 (uptr *)cur_thread_location(), sizeof(ThreadState));
88 // Some interceptors get called before libpthread has been initialized and in
89 // these cases we must avoid calling any pthread APIs.
90 if (UNLIKELY(!thread_state_key)) {
91 return (ThreadState *)main_thread_state;
92 }
93
94 // We only reach this line after InitializeThreadStateStorage() ran, i.e,
95 // after TSan (and therefore libpthread) have been initialized.
96 ThreadState *thr = (ThreadState *)pthread_getspecific(thread_state_key);
97 if (UNLIKELY(!thr)) {
98 thr = (ThreadState *)MmapOrDie(sizeof(ThreadState), "ThreadState");
99 int res = pthread_setspecific(thread_state_key, thr);
100 CHECK_EQ(res, 0);
101 }
102 return thr;
94103}
95104
96105void set_cur_thread(ThreadState *thr) {
97 *cur_thread_location() = thr;
106 int res = pthread_setspecific(thread_state_key, thr);
107 CHECK_EQ(res, 0);
98108}
99109
100// TODO(kuba.brecka): This is not async-signal-safe. In particular, we call
101// munmap first and then clear `fake_tls`; if we receive a signal in between,
102// handler will try to access the unmapped ThreadState.
103110void cur_thread_finalize() {
104 ThreadState **thr_state_loc = cur_thread_location();
105 if (thr_state_loc == &main_thread_state_loc) {
111 ThreadState *thr = (ThreadState *)pthread_getspecific(thread_state_key);
112 CHECK(thr);
113 if (thr == (ThreadState *)main_thread_state) {
106114 // Calling dispatch_main() or xpc_main() actually invokes pthread_exit to
107115 // exit the main thread. Let's keep the main thread's ThreadState.
108116 return;
109117 }
110 internal_munmap(*thr_state_loc, sizeof(ThreadState));
111 *thr_state_loc = nullptr;
118 // Intercepted functions can still get called after cur_thread_finalize()
119 // (called from DestroyThreadState()), so put a fake thread state for "dead"
120 // threads. An alternative solution would be to release the ThreadState
121 // object from THREAD_DESTROY (which is delivered later and on the parent
122 // thread) instead of THREAD_TERMINATE.
123 int res = pthread_setspecific(thread_state_key, dead_thread_state);
124 CHECK_EQ(res, 0);
125 UnmapOrDie(thr, sizeof(ThreadState));
112126}
113127#endif
114128
115void FlushShadowMemory() {
116}
117
118129static void RegionMemUsage(uptr start, uptr end, uptr *res, uptr *dirty) {
119130 vm_address_t address = start;
120131 vm_address_t end_address = end;
......@@ -139,15 +150,13 @@ static void RegionMemUsage(uptr start, uptr end, uptr *res, uptr *dirty) {
139150 *dirty = dirty_pages * GetPageSizeCached();
140151}
141152
142void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive) {
153void WriteMemoryProfile(char *buf, uptr buf_size, u64 uptime_ns) {
143154 uptr shadow_res, shadow_dirty;
144155 uptr meta_res, meta_dirty;
145 uptr trace_res, trace_dirty;
146156 RegionMemUsage(ShadowBeg(), ShadowEnd(), &shadow_res, &shadow_dirty);
147157 RegionMemUsage(MetaShadowBeg(), MetaShadowEnd(), &meta_res, &meta_dirty);
148 RegionMemUsage(TraceMemBeg(), TraceMemEnd(), &trace_res, &trace_dirty);
149158
150#if !SANITIZER_GO
159# if !SANITIZER_GO
151160 uptr low_res, low_dirty;
152161 uptr high_res, high_dirty;
153162 uptr heap_res, heap_dirty;
......@@ -156,89 +165,70 @@ void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive) {
156165 RegionMemUsage(HeapMemBeg(), HeapMemEnd(), &heap_res, &heap_dirty);
157166#else // !SANITIZER_GO
158167 uptr app_res, app_dirty;
159 RegionMemUsage(AppMemBeg(), AppMemEnd(), &app_res, &app_dirty);
168 RegionMemUsage(LoAppMemBeg(), LoAppMemEnd(), &app_res, &app_dirty);
160169#endif
161170
162 StackDepotStats *stacks = StackDepotGetStats();
163 internal_snprintf(buf, buf_size,
164 "shadow (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
165 "meta (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
166 "traces (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
167#if !SANITIZER_GO
168 "low app (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
169 "high app (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
170 "heap (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
171#else // !SANITIZER_GO
172 "app (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
173#endif
174 "stacks: %zd unique IDs, %zd kB allocated\n"
175 "threads: %zd total, %zd live\n"
176 "------------------------------\n",
177 ShadowBeg(), ShadowEnd(), shadow_res / 1024, shadow_dirty / 1024,
178 MetaShadowBeg(), MetaShadowEnd(), meta_res / 1024, meta_dirty / 1024,
179 TraceMemBeg(), TraceMemEnd(), trace_res / 1024, trace_dirty / 1024,
180#if !SANITIZER_GO
181 LoAppMemBeg(), LoAppMemEnd(), low_res / 1024, low_dirty / 1024,
182 HiAppMemBeg(), HiAppMemEnd(), high_res / 1024, high_dirty / 1024,
183 HeapMemBeg(), HeapMemEnd(), heap_res / 1024, heap_dirty / 1024,
184#else // !SANITIZER_GO
185 AppMemBeg(), AppMemEnd(), app_res / 1024, app_dirty / 1024,
186#endif
187 stacks->n_uniq_ids, stacks->allocated / 1024,
188 nthread, nlive);
171 StackDepotStats stacks = StackDepotGetStats();
172 uptr nthread, nlive;
173 ctx->thread_registry.GetNumberOfThreads(&nthread, &nlive);
174 internal_snprintf(
175 buf, buf_size,
176 "shadow (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
177 "meta (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
178# if !SANITIZER_GO
179 "low app (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
180 "high app (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
181 "heap (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
182# else // !SANITIZER_GO
183 "app (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
184# endif
185 "stacks: %zd unique IDs, %zd kB allocated\n"
186 "threads: %zd total, %zd live\n"
187 "------------------------------\n",
188 ShadowBeg(), ShadowEnd(), shadow_res / 1024, shadow_dirty / 1024,
189 MetaShadowBeg(), MetaShadowEnd(), meta_res / 1024, meta_dirty / 1024,
190# if !SANITIZER_GO
191 LoAppMemBeg(), LoAppMemEnd(), low_res / 1024, low_dirty / 1024,
192 HiAppMemBeg(), HiAppMemEnd(), high_res / 1024, high_dirty / 1024,
193 HeapMemBeg(), HeapMemEnd(), heap_res / 1024, heap_dirty / 1024,
194# else // !SANITIZER_GO
195 LoAppMemBeg(), LoAppMemEnd(), app_res / 1024, app_dirty / 1024,
196# endif
197 stacks.n_uniq_ids, stacks.allocated / 1024, nthread, nlive);
189198}
190199
191#if !SANITIZER_GO
200# if !SANITIZER_GO
192201void InitializeShadowMemoryPlatform() { }
193202
194// On OS X, GCD worker threads are created without a call to pthread_create. We
195// need to properly register these threads with ThreadCreate and ThreadStart.
196// These threads don't have a parent thread, as they are created "spuriously".
197// We're using a libpthread API that notifies us about a newly created thread.
198// The `thread == pthread_self()` check indicates this is actually a worker
199// thread. If it's just a regular thread, this hook is called on the parent
200// thread.
201typedef void (*pthread_introspection_hook_t)(unsigned int event,
202 pthread_t thread, void *addr,
203 size_t size);
204extern "C" pthread_introspection_hook_t pthread_introspection_hook_install(
205 pthread_introspection_hook_t hook);
206static const uptr PTHREAD_INTROSPECTION_THREAD_CREATE = 1;
207static const uptr PTHREAD_INTROSPECTION_THREAD_TERMINATE = 3;
208static pthread_introspection_hook_t prev_pthread_introspection_hook;
209static void my_pthread_introspection_hook(unsigned int event, pthread_t thread,
210 void *addr, size_t size) {
211 if (event == PTHREAD_INTROSPECTION_THREAD_CREATE) {
212 if (thread == pthread_self()) {
213 // The current thread is a newly created GCD worker thread.
214 ThreadState *thr = cur_thread();
215 Processor *proc = ProcCreate();
216 ProcWire(proc, thr);
217 ThreadState *parent_thread_state = nullptr; // No parent.
218 int tid = ThreadCreate(parent_thread_state, 0, (uptr)thread, true);
219 CHECK_NE(tid, 0);
220 ThreadStart(thr, tid, GetTid(), ThreadType::Worker);
221 }
222 } else if (event == PTHREAD_INTROSPECTION_THREAD_TERMINATE) {
223 if (thread == pthread_self()) {
224 ThreadState *thr = cur_thread();
225 if (thr->tctx) {
226 DestroyThreadState();
227 }
228 }
203// Register GCD worker threads, which are created without an observable call to
204// pthread_create().
205static void ThreadCreateCallback(uptr thread, bool gcd_worker) {
206 if (gcd_worker) {
207 ThreadState *thr = cur_thread();
208 Processor *proc = ProcCreate();
209 ProcWire(proc, thr);
210 ThreadState *parent_thread_state = nullptr; // No parent.
211 Tid tid = ThreadCreate(parent_thread_state, 0, (uptr)thread, true);
212 CHECK_NE(tid, kMainTid);
213 ThreadStart(thr, tid, GetTid(), ThreadType::Worker);
229214 }
215}
230216
231 if (prev_pthread_introspection_hook != nullptr)
232 prev_pthread_introspection_hook(event, thread, addr, size);
217// Destroy thread state for *all* threads.
218static void ThreadTerminateCallback(uptr thread) {
219 ThreadState *thr = cur_thread();
220 if (thr->tctx) {
221 DestroyThreadState();
222 }
233223}
234224#endif
235225
236226void InitializePlatformEarly() {
237#if !SANITIZER_GO && !HAS_48_BIT_ADDRESS_SPACE
227# if !SANITIZER_GO && SANITIZER_IOS
238228 uptr max_vm = GetMaxUserVirtualAddress() + 1;
239 if (max_vm != Mapping::kHiAppMemEnd) {
229 if (max_vm != HiAppMemEnd()) {
240230 Printf("ThreadSanitizer: unsupported vm address limit %p, expected %p.\n",
241 max_vm, Mapping::kHiAppMemEnd);
231 (void *)max_vm, (void *)HiAppMemEnd());
242232 Die();
243233 }
244234#endif
......@@ -251,11 +241,13 @@ void InitializePlatform() {
251241#if !SANITIZER_GO
252242 CheckAndProtect();
253243
254 CHECK_EQ(main_thread_identity, 0);
255 main_thread_identity = (uptr)pthread_self();
244 InitializeThreadStateStorage();
256245
257 prev_pthread_introspection_hook =
258 pthread_introspection_hook_install(&my_pthread_introspection_hook);
246 ThreadEventCallbacks callbacks = {
247 .create = ThreadCreateCallback,
248 .terminate = ThreadTerminateCallback,
249 };
250 InstallPthreadIntrospectionHook(callbacks);
259251#endif
260252
261253 if (GetMacosAlignedVersion() >= MacosVersion(10, 14)) {
......@@ -281,25 +273,14 @@ uptr ExtractLongJmpSp(uptr *env) {
281273}
282274
283275#if !SANITIZER_GO
276extern "C" void __tsan_tls_initialization() {}
277
284278void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size) {
285 // The pointer to the ThreadState object is stored in the shadow memory
286 // of the tls.
287 uptr tls_end = tls_addr + tls_size;
288 uptr thread_identity = (uptr)pthread_self();
289 if (thread_identity == main_thread_identity) {
290 MemoryRangeImitateWrite(thr, /*pc=*/2, tls_addr, tls_size);
291 } else {
292 uptr thr_state_start = thread_identity;
293 uptr thr_state_end = thr_state_start + sizeof(uptr);
294 CHECK_GE(thr_state_start, tls_addr);
295 CHECK_LE(thr_state_start, tls_addr + tls_size);
296 CHECK_GE(thr_state_end, tls_addr);
297 CHECK_LE(thr_state_end, tls_addr + tls_size);
298 MemoryRangeImitateWrite(thr, /*pc=*/2, tls_addr,
299 thr_state_start - tls_addr);
300 MemoryRangeImitateWrite(thr, /*pc=*/2, thr_state_end,
301 tls_end - thr_state_end);
302 }
279 const uptr pc = StackTrace::GetNextInstructionPc(
280 reinterpret_cast<uptr>(__tsan_tls_initialization));
281 // Unlike Linux, we only store a pointer to the ThreadState object in TLS;
282 // just mark the entire range as written to.
283 MemoryRangeImitateWrite(thr, pc, tls_addr, tls_size);
303284}
304285#endif
305286
......@@ -320,4 +301,4 @@ int call_pthread_cancel_with_cleanup(int (*fn)(void *arg),
320301
321302} // namespace __tsan
322303
323#endif // SANITIZER_MAC
304#endif // SANITIZER_APPLE
lib/tsan/tsan_platform_posix.cpp+27-24
......@@ -14,12 +14,14 @@
1414#include "sanitizer_common/sanitizer_platform.h"
1515#if SANITIZER_POSIX
1616
17#include "sanitizer_common/sanitizer_common.h"
18#include "sanitizer_common/sanitizer_errno.h"
19#include "sanitizer_common/sanitizer_libc.h"
20#include "sanitizer_common/sanitizer_procmaps.h"
21#include "tsan_platform.h"
22#include "tsan_rtl.h"
17# include <dlfcn.h>
18
19# include "sanitizer_common/sanitizer_common.h"
20# include "sanitizer_common/sanitizer_errno.h"
21# include "sanitizer_common/sanitizer_libc.h"
22# include "sanitizer_common/sanitizer_procmaps.h"
23# include "tsan_platform.h"
24# include "tsan_rtl.h"
2325
2426namespace __tsan {
2527
......@@ -29,7 +31,8 @@ static const char kShadowMemoryMappingHint[] =
2931 "HINT: if %s is not supported in your environment, you may set "
3032 "TSAN_OPTIONS=%s=0\n";
3133
32static void DontDumpShadow(uptr addr, uptr size) {
34# if !SANITIZER_GO
35void DontDumpShadow(uptr addr, uptr size) {
3336 if (common_flags()->use_madv_dontdump)
3437 if (!DontDumpShadowMemory(addr, size)) {
3538 Printf(kShadowMemoryMappingWarning, SanitizerToolName, addr, addr + size,
......@@ -39,7 +42,6 @@ static void DontDumpShadow(uptr addr, uptr size) {
3942 }
4043}
4144
42#if !SANITIZER_GO
4345void InitializeShadowMemory() {
4446 // Map memory shadow.
4547 if (!MmapFixedSuperNoReserve(ShadowBeg(), ShadowEnd() - ShadowBeg(),
......@@ -70,6 +72,11 @@ void InitializeShadowMemory() {
7072 meta, meta + meta_size, meta_size >> 30);
7173
7274 InitializeShadowMemoryPlatform();
75
76 on_initialize = reinterpret_cast<void (*)(void)>(
77 dlsym(RTLD_DEFAULT, "__tsan_on_initialize"));
78 on_finalize =
79 reinterpret_cast<int (*)(int)>(dlsym(RTLD_DEFAULT, "__tsan_on_finalize"));
7380}
7481
7582static bool TryProtectRange(uptr beg, uptr end) {
......@@ -98,32 +105,28 @@ void CheckAndProtect() {
98105 continue;
99106 if (segment.start >= VdsoBeg()) // vdso
100107 break;
101 Printf("FATAL: ThreadSanitizer: unexpected memory mapping %p-%p\n",
108 Printf("FATAL: ThreadSanitizer: unexpected memory mapping 0x%zx-0x%zx\n",
102109 segment.start, segment.end);
103110 Die();
104111 }
105112
106#if defined(__aarch64__) && defined(__APPLE__) && !HAS_48_BIT_ADDRESS_SPACE
113# if SANITIZER_IOS && !SANITIZER_IOSSIM
107114 ProtectRange(HeapMemEnd(), ShadowBeg());
108115 ProtectRange(ShadowEnd(), MetaShadowBeg());
109 ProtectRange(MetaShadowEnd(), TraceMemBeg());
110#else
116 ProtectRange(MetaShadowEnd(), HiAppMemBeg());
117# else
111118 ProtectRange(LoAppMemEnd(), ShadowBeg());
112119 ProtectRange(ShadowEnd(), MetaShadowBeg());
113#ifdef TSAN_MID_APP_RANGE
114 ProtectRange(MetaShadowEnd(), MidAppMemBeg());
115 ProtectRange(MidAppMemEnd(), TraceMemBeg());
116#else
117 ProtectRange(MetaShadowEnd(), TraceMemBeg());
118#endif
119 // Memory for traces is mapped lazily in MapThreadTrace.
120 // Protect the whole range for now, so that user does not map something here.
121 ProtectRange(TraceMemBeg(), TraceMemEnd());
122 ProtectRange(TraceMemEnd(), HeapMemBeg());
120 if (MidAppMemBeg()) {
121 ProtectRange(MetaShadowEnd(), MidAppMemBeg());
122 ProtectRange(MidAppMemEnd(), HeapMemBeg());
123 } else {
124 ProtectRange(MetaShadowEnd(), HeapMemBeg());
125 }
123126 ProtectRange(HeapEnd(), HiAppMemBeg());
124#endif
127# endif
125128
126#if defined(__s390x__)
129# if defined(__s390x__)
127130 // Protect the rest of the address space.
128131 const uptr user_addr_max_l4 = 0x0020000000000000ull;
129132 const uptr user_addr_max_l5 = 0xfffffffffffff000ull;
lib/tsan/tsan_platform_windows.cpp created+33
......@@ -0,0 +1,33 @@
1//===-- tsan_platform_windows.cpp -----------------------------------------===//
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// Windows-specific code.
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_common/sanitizer_platform.h"
15#if SANITIZER_WINDOWS
16
17#include "tsan_platform.h"
18
19#include <stdlib.h>
20
21namespace __tsan {
22
23void WriteMemoryProfile(char *buf, uptr buf_size, u64 uptime_ns) {}
24
25void InitializePlatformEarly() {
26}
27
28void InitializePlatform() {
29}
30
31} // namespace __tsan
32
33#endif // SANITIZER_WINDOWS
lib/tsan/tsan_report.cpp+46-62
......@@ -19,22 +19,6 @@
1919
2020namespace __tsan {
2121
22ReportStack::ReportStack() : frames(nullptr), suppressable(false) {}
23
24ReportStack *ReportStack::New() {
25 void *mem = internal_alloc(MBlockReportStack, sizeof(ReportStack));
26 return new(mem) ReportStack();
27}
28
29ReportLocation::ReportLocation(ReportLocationType type)
30 : type(type), global(), heap_chunk_start(0), heap_chunk_size(0), tid(0),
31 fd(0), suppressable(false), stack(nullptr) {}
32
33ReportLocation *ReportLocation::New(ReportLocationType type) {
34 void *mem = internal_alloc(MBlockReportStack, sizeof(ReportLocation));
35 return new(mem) ReportLocation(type);
36}
37
3822class Decorator: public __sanitizer::SanitizerCommonDecorator {
3923 public:
4024 Decorator() : SanitizerCommonDecorator() { }
......@@ -68,7 +52,7 @@ ReportDesc::~ReportDesc() {
6852#if !SANITIZER_GO
6953
7054const int kThreadBufSize = 32;
71const char *thread_name(char *buf, int tid) {
55const char *thread_name(char *buf, Tid tid) {
7256 if (tid == kMainTid)
7357 return "main thread";
7458 internal_snprintf(buf, kThreadBufSize, "thread T%d", tid);
......@@ -114,12 +98,6 @@ static const char *ReportTypeString(ReportType typ, uptr tag) {
11498 UNREACHABLE("missing case");
11599}
116100
117#if SANITIZER_MAC
118static const char *const kInterposedFunctionPrefix = "wrap_";
119#else
120static const char *const kInterposedFunctionPrefix = "__interceptor_";
121#endif
122
123101void PrintStack(const ReportStack *ent) {
124102 if (ent == 0 || ent->frames == 0) {
125103 Printf(" [failed to restore the stack]\n\n");
......@@ -131,7 +109,7 @@ void PrintStack(const ReportStack *ent) {
131109 RenderFrame(&res, common_flags()->stack_trace_format, i,
132110 frame->info.address, &frame->info,
133111 common_flags()->symbolize_vs_style,
134 common_flags()->strip_path_prefix, kInterposedFunctionPrefix);
112 common_flags()->strip_path_prefix);
135113 Printf("%s\n", res.data());
136114 }
137115 Printf("\n");
......@@ -142,7 +120,7 @@ static void PrintMutexSet(Vector<ReportMopMutex> const& mset) {
142120 if (i == 0)
143121 Printf(" (mutexes:");
144122 const ReportMopMutex m = mset[i];
145 Printf(" %s M%llu", m.write ? "write" : "read", m.id);
123 Printf(" %s M%u", m.write ? "write" : "read", m.id);
146124 Printf(i == mset.Size() - 1 ? ")" : ",");
147125 }
148126}
......@@ -189,23 +167,25 @@ static void PrintLocation(const ReportLocation *loc) {
189167 if (loc->type == ReportLocationGlobal) {
190168 const DataInfo &global = loc->global;
191169 if (global.size != 0)
192 Printf(" Location is global '%s' of size %zu at %p (%s+%p)\n\n",
193 global.name, global.size, global.start,
170 Printf(" Location is global '%s' of size %zu at %p (%s+0x%zx)\n\n",
171 global.name, global.size, reinterpret_cast<void *>(global.start),
194172 StripModuleName(global.module), global.module_offset);
195173 else
196 Printf(" Location is global '%s' at %p (%s+%p)\n\n", global.name,
197 global.start, StripModuleName(global.module),
198 global.module_offset);
174 Printf(" Location is global '%s' at %p (%s+0x%zx)\n\n", global.name,
175 reinterpret_cast<void *>(global.start),
176 StripModuleName(global.module), global.module_offset);
199177 } else if (loc->type == ReportLocationHeap) {
200178 char thrbuf[kThreadBufSize];
201179 const char *object_type = GetObjectTypeFromTag(loc->external_tag);
202180 if (!object_type) {
203181 Printf(" Location is heap block of size %zu at %p allocated by %s:\n",
204 loc->heap_chunk_size, loc->heap_chunk_start,
182 loc->heap_chunk_size,
183 reinterpret_cast<void *>(loc->heap_chunk_start),
205184 thread_name(thrbuf, loc->tid));
206185 } else {
207186 Printf(" Location is %s of size %zu at %p allocated by %s:\n",
208 object_type, loc->heap_chunk_size, loc->heap_chunk_start,
187 object_type, loc->heap_chunk_size,
188 reinterpret_cast<void *>(loc->heap_chunk_start),
209189 thread_name(thrbuf, loc->tid));
210190 }
211191 print_stack = true;
......@@ -214,8 +194,9 @@ static void PrintLocation(const ReportLocation *loc) {
214194 } else if (loc->type == ReportLocationTLS) {
215195 Printf(" Location is TLS of %s.\n\n", thread_name(thrbuf, loc->tid));
216196 } else if (loc->type == ReportLocationFD) {
217 Printf(" Location is file descriptor %d created by %s at:\n",
218 loc->fd, thread_name(thrbuf, loc->tid));
197 Printf(" Location is file descriptor %d %s by %s at:\n", loc->fd,
198 loc->fd_closed ? "destroyed" : "created",
199 thread_name(thrbuf, loc->tid));
219200 print_stack = true;
220201 }
221202 Printf("%s", d.Default());
......@@ -225,27 +206,23 @@ static void PrintLocation(const ReportLocation *loc) {
225206
226207static void PrintMutexShort(const ReportMutex *rm, const char *after) {
227208 Decorator d;
228 Printf("%sM%zd%s%s", d.Mutex(), rm->id, d.Default(), after);
209 Printf("%sM%d%s%s", d.Mutex(), rm->id, d.Default(), after);
229210}
230211
231212static void PrintMutexShortWithAddress(const ReportMutex *rm,
232213 const char *after) {
233214 Decorator d;
234 Printf("%sM%zd (%p)%s%s", d.Mutex(), rm->id, rm->addr, d.Default(), after);
215 Printf("%sM%d (%p)%s%s", d.Mutex(), rm->id,
216 reinterpret_cast<void *>(rm->addr), d.Default(), after);
235217}
236218
237219static void PrintMutex(const ReportMutex *rm) {
238220 Decorator d;
239 if (rm->destroyed) {
240 Printf("%s", d.Mutex());
241 Printf(" Mutex M%llu is already destroyed.\n\n", rm->id);
242 Printf("%s", d.Default());
243 } else {
244 Printf("%s", d.Mutex());
245 Printf(" Mutex M%llu (%p) created at:\n", rm->id, rm->addr);
246 Printf("%s", d.Default());
247 PrintStack(rm->stack);
248 }
221 Printf("%s", d.Mutex());
222 Printf(" Mutex M%u (%p) created at:\n", rm->id,
223 reinterpret_cast<void *>(rm->addr));
224 Printf("%s", d.Default());
225 PrintStack(rm->stack);
249226}
250227
251228static void PrintThread(const ReportThread *rt) {
......@@ -259,12 +236,13 @@ static void PrintThread(const ReportThread *rt) {
259236 char thrbuf[kThreadBufSize];
260237 const char *thread_status = rt->running ? "running" : "finished";
261238 if (rt->thread_type == ThreadType::Worker) {
262 Printf(" (tid=%zu, %s) is a GCD worker thread\n", rt->os_id, thread_status);
239 Printf(" (tid=%llu, %s) is a GCD worker thread\n", rt->os_id,
240 thread_status);
263241 Printf("\n");
264242 Printf("%s", d.Default());
265243 return;
266244 }
267 Printf(" (tid=%zu, %s) created by %s", rt->os_id, thread_status,
245 Printf(" (tid=%llu, %s) created by %s", rt->os_id, thread_status,
268246 thread_name(thrbuf, rt->parent_tid));
269247 if (rt->stack)
270248 Printf(" at:");
......@@ -300,6 +278,7 @@ static bool FrameIsInternal(const SymbolizedStack *frame) {
300278 const char *module = frame->info.module;
301279 if (file != 0 &&
302280 (internal_strstr(file, "tsan_interceptors_posix.cpp") ||
281 internal_strstr(file, "tsan_interceptors_memintrinsics.cpp") ||
303282 internal_strstr(file, "sanitizer_common_interceptors.inc") ||
304283 internal_strstr(file, "tsan_interface_")))
305284 return true;
......@@ -323,6 +302,9 @@ void PrintReport(const ReportDesc *rep) {
323302 (int)internal_getpid());
324303 Printf("%s", d.Default());
325304
305 if (rep->typ == ReportTypeErrnoInSignal)
306 Printf(" Signal %u handler invoked at:\n", rep->signum);
307
326308 if (rep->typ == ReportTypeDeadlock) {
327309 char thrbuf[kThreadBufSize];
328310 Printf(" Cycle in lock order graph: ");
......@@ -394,7 +376,7 @@ void PrintReport(const ReportDesc *rep) {
394376
395377#else // #if !SANITIZER_GO
396378
397const u32 kMainGoroutineId = 1;
379const Tid kMainGoroutineId = 1;
398380
399381void PrintStack(const ReportStack *ent) {
400382 if (ent == 0 || ent->frames == 0) {
......@@ -405,16 +387,17 @@ void PrintStack(const ReportStack *ent) {
405387 for (int i = 0; frame; frame = frame->next, i++) {
406388 const AddressInfo &info = frame->info;
407389 Printf(" %s()\n %s:%d +0x%zx\n", info.function,
408 StripPathPrefix(info.file, common_flags()->strip_path_prefix),
409 info.line, (void *)info.module_offset);
390 StripPathPrefix(info.file, common_flags()->strip_path_prefix),
391 info.line, info.module_offset);
410392 }
411393}
412394
413395static void PrintMop(const ReportMop *mop, bool first) {
414396 Printf("\n");
415397 Printf("%s at %p by ",
416 (first ? (mop->write ? "Write" : "Read")
417 : (mop->write ? "Previous write" : "Previous read")), mop->addr);
398 (first ? (mop->write ? "Write" : "Read")
399 : (mop->write ? "Previous write" : "Previous read")),
400 reinterpret_cast<void *>(mop->addr));
418401 if (mop->tid == kMainGoroutineId)
419402 Printf("main goroutine:\n");
420403 else
......@@ -426,8 +409,8 @@ static void PrintLocation(const ReportLocation *loc) {
426409 switch (loc->type) {
427410 case ReportLocationHeap: {
428411 Printf("\n");
429 Printf("Heap block of size %zu at %p allocated by ",
430 loc->heap_chunk_size, loc->heap_chunk_start);
412 Printf("Heap block of size %zu at %p allocated by ", loc->heap_chunk_size,
413 reinterpret_cast<void *>(loc->heap_chunk_start));
431414 if (loc->tid == kMainGoroutineId)
432415 Printf("main goroutine:\n");
433416 else
......@@ -438,8 +421,9 @@ static void PrintLocation(const ReportLocation *loc) {
438421 case ReportLocationGlobal: {
439422 Printf("\n");
440423 Printf("Global var %s of size %zu at %p declared at %s:%zu\n",
441 loc->global.name, loc->global.size, loc->global.start,
442 loc->global.file, loc->global.line);
424 loc->global.name, loc->global.size,
425 reinterpret_cast<void *>(loc->global.start), loc->global.file,
426 loc->global.line);
443427 break;
444428 }
445429 default:
......@@ -469,13 +453,13 @@ void PrintReport(const ReportDesc *rep) {
469453 } else if (rep->typ == ReportTypeDeadlock) {
470454 Printf("WARNING: DEADLOCK\n");
471455 for (uptr i = 0; i < rep->mutexes.Size(); i++) {
472 Printf("Goroutine %d lock mutex %d while holding mutex %d:\n",
473 999, rep->mutexes[i]->id,
474 rep->mutexes[(i+1) % rep->mutexes.Size()]->id);
456 Printf("Goroutine %d lock mutex %u while holding mutex %u:\n", 999,
457 rep->mutexes[i]->id,
458 rep->mutexes[(i + 1) % rep->mutexes.Size()]->id);
475459 PrintStack(rep->stacks[2*i]);
476460 Printf("\n");
477 Printf("Mutex %d was previously locked here:\n",
478 rep->mutexes[(i+1) % rep->mutexes.Size()]->id);
461 Printf("Mutex %u was previously locked here:\n",
462 rep->mutexes[(i + 1) % rep->mutexes.Size()]->id);
479463 PrintStack(rep->stacks[2*i + 1]);
480464 Printf("\n");
481465 }
lib/tsan/tsan_report.h+18-25
......@@ -38,16 +38,12 @@ enum ReportType {
3838};
3939
4040struct ReportStack {
41 SymbolizedStack *frames;
42 bool suppressable;
43 static ReportStack *New();
44
45 private:
46 ReportStack();
41 SymbolizedStack *frames = nullptr;
42 bool suppressable = false;
4743};
4844
4945struct ReportMopMutex {
50 u64 id;
46 int id;
5147 bool write;
5248};
5349
......@@ -73,35 +69,31 @@ enum ReportLocationType {
7369};
7470
7571struct ReportLocation {
76 ReportLocationType type;
77 DataInfo global;
78 uptr heap_chunk_start;
79 uptr heap_chunk_size;
80 uptr external_tag;
81 int tid;
82 int fd;
83 bool suppressable;
84 ReportStack *stack;
85
86 static ReportLocation *New(ReportLocationType type);
87 private:
88 explicit ReportLocation(ReportLocationType type);
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;
8982};
9083
9184struct ReportThread {
92 int id;
85 Tid id;
9386 tid_t os_id;
9487 bool running;
9588 ThreadType thread_type;
9689 char *name;
97 u32 parent_tid;
90 Tid parent_tid;
9891 ReportStack *stack;
9992};
10093
10194struct ReportMutex {
102 u64 id;
95 int id;
10396 uptr addr;
104 bool destroyed;
10597 ReportStack *stack;
10698};
10799
......@@ -114,9 +106,10 @@ class ReportDesc {
114106 Vector<ReportLocation*> locs;
115107 Vector<ReportMutex*> mutexes;
116108 Vector<ReportThread*> threads;
117 Vector<int> unique_tids;
109 Vector<Tid> unique_tids;
118110 ReportStack *sleep;
119111 int count;
112 int signum = 0;
120113
121114 ReportDesc();
122115 ~ReportDesc();
lib/tsan/tsan_rtl.cpp+657-693
......@@ -16,6 +16,7 @@
1616#include "sanitizer_common/sanitizer_atomic.h"
1717#include "sanitizer_common/sanitizer_common.h"
1818#include "sanitizer_common/sanitizer_file.h"
19#include "sanitizer_common/sanitizer_interface_internal.h"
1920#include "sanitizer_common/sanitizer_libc.h"
2021#include "sanitizer_common/sanitizer_placement_new.h"
2122#include "sanitizer_common/sanitizer_stackdepot.h"
......@@ -28,29 +29,28 @@
2829#include "tsan_symbolize.h"
2930#include "ubsan/ubsan_init.h"
3031
31#ifdef __SSE3__
32// <emmintrin.h> transitively includes <stdlib.h>,
33// and it's prohibited to include std headers into tsan runtime.
34// So we do this dirty trick.
35#define _MM_MALLOC_H_INCLUDED
36#define __MM_MALLOC_H
37#include <emmintrin.h>
38typedef __m128i m128;
39#endif
40
4132volatile int __tsan_resumed = 0;
4233
4334extern "C" void __tsan_resume() {
4435 __tsan_resumed = 1;
4536}
4637
38SANITIZER_WEAK_DEFAULT_IMPL
39void __tsan_test_only_on_fork() {}
40
4741namespace __tsan {
4842
49#if !SANITIZER_GO && !SANITIZER_MAC
43#if !SANITIZER_GO
44void (*on_initialize)(void);
45int (*on_finalize)(int);
46#endif
47
48#if !SANITIZER_GO && !SANITIZER_APPLE
5049__attribute__((tls_model("initial-exec")))
51THREADLOCAL char cur_thread_placeholder[sizeof(ThreadState)] ALIGNED(64);
50THREADLOCAL char cur_thread_placeholder[sizeof(ThreadState)] ALIGNED(
51 SANITIZER_CACHE_LINE_SIZE);
5252#endif
53static char ctx_placeholder[sizeof(Context)] ALIGNED(64);
53static char ctx_placeholder[sizeof(Context)] ALIGNED(SANITIZER_CACHE_LINE_SIZE);
5454Context *ctx;
5555
5656// Can be overriden by a front-end.
......@@ -58,113 +58,404 @@ Context *ctx;
5858bool OnFinalize(bool failed);
5959void OnInitialize();
6060#else
61#include <dlfcn.h>
6261SANITIZER_WEAK_CXX_DEFAULT_IMPL
6362bool OnFinalize(bool failed) {
64#if !SANITIZER_GO
65 if (auto *ptr = dlsym(RTLD_DEFAULT, "__tsan_on_finalize"))
66 return reinterpret_cast<decltype(&__tsan_on_finalize)>(ptr)(failed);
67#endif
63# if !SANITIZER_GO
64 if (on_finalize)
65 return on_finalize(failed);
66# endif
6867 return failed;
6968}
69
7070SANITIZER_WEAK_CXX_DEFAULT_IMPL
7171void OnInitialize() {
72#if !SANITIZER_GO
73 if (auto *ptr = dlsym(RTLD_DEFAULT, "__tsan_on_initialize")) {
74 return reinterpret_cast<decltype(&__tsan_on_initialize)>(ptr)();
75 }
72# if !SANITIZER_GO
73 if (on_initialize)
74 on_initialize();
75# endif
76}
7677#endif
78
79static TracePart* TracePartAlloc(ThreadState* thr) {
80 TracePart* part = nullptr;
81 {
82 Lock lock(&ctx->slot_mtx);
83 uptr max_parts = Trace::kMinParts + flags()->history_size;
84 Trace* trace = &thr->tctx->trace;
85 if (trace->parts_allocated == max_parts ||
86 ctx->trace_part_finished_excess) {
87 part = ctx->trace_part_recycle.PopFront();
88 DPrintf("#%d: TracePartAlloc: part=%p\n", thr->tid, part);
89 if (part && part->trace) {
90 Trace* trace1 = part->trace;
91 Lock trace_lock(&trace1->mtx);
92 part->trace = nullptr;
93 TracePart* part1 = trace1->parts.PopFront();
94 CHECK_EQ(part, part1);
95 if (trace1->parts_allocated > trace1->parts.Size()) {
96 ctx->trace_part_finished_excess +=
97 trace1->parts_allocated - trace1->parts.Size();
98 trace1->parts_allocated = trace1->parts.Size();
99 }
100 }
101 }
102 if (trace->parts_allocated < max_parts) {
103 trace->parts_allocated++;
104 if (ctx->trace_part_finished_excess)
105 ctx->trace_part_finished_excess--;
106 }
107 if (!part)
108 ctx->trace_part_total_allocated++;
109 else if (ctx->trace_part_recycle_finished)
110 ctx->trace_part_recycle_finished--;
111 }
112 if (!part)
113 part = new (MmapOrDie(sizeof(*part), "TracePart")) TracePart();
114 return part;
115}
116
117static void TracePartFree(TracePart* part) SANITIZER_REQUIRES(ctx->slot_mtx) {
118 DCHECK(part->trace);
119 part->trace = nullptr;
120 ctx->trace_part_recycle.PushFront(part);
121}
122
123void TraceResetForTesting() {
124 Lock lock(&ctx->slot_mtx);
125 while (auto* part = ctx->trace_part_recycle.PopFront()) {
126 if (auto trace = part->trace)
127 CHECK_EQ(trace->parts.PopFront(), part);
128 UnmapOrDie(part, sizeof(*part));
129 }
130 ctx->trace_part_total_allocated = 0;
131 ctx->trace_part_recycle_finished = 0;
132 ctx->trace_part_finished_excess = 0;
77133}
134
135static void DoResetImpl(uptr epoch) {
136 ThreadRegistryLock lock0(&ctx->thread_registry);
137 Lock lock1(&ctx->slot_mtx);
138 CHECK_EQ(ctx->global_epoch, epoch);
139 ctx->global_epoch++;
140 CHECK(!ctx->resetting);
141 ctx->resetting = true;
142 for (u32 i = ctx->thread_registry.NumThreadsLocked(); i--;) {
143 ThreadContext* tctx = (ThreadContext*)ctx->thread_registry.GetThreadLocked(
144 static_cast<Tid>(i));
145 // Potentially we could purge all ThreadStatusDead threads from the
146 // registry. Since we reset all shadow, they can't race with anything
147 // anymore. However, their tid's can still be stored in some aux places
148 // (e.g. tid of thread that created something).
149 auto trace = &tctx->trace;
150 Lock lock(&trace->mtx);
151 bool attached = tctx->thr && tctx->thr->slot;
152 auto parts = &trace->parts;
153 bool local = false;
154 while (!parts->Empty()) {
155 auto part = parts->Front();
156 local = local || part == trace->local_head;
157 if (local)
158 CHECK(!ctx->trace_part_recycle.Queued(part));
159 else
160 ctx->trace_part_recycle.Remove(part);
161 if (attached && parts->Size() == 1) {
162 // The thread is running and this is the last/current part.
163 // Set the trace position to the end of the current part
164 // to force the thread to call SwitchTracePart and re-attach
165 // to a new slot and allocate a new trace part.
166 // Note: the thread is concurrently modifying the position as well,
167 // so this is only best-effort. The thread can only modify position
168 // within this part, because switching parts is protected by
169 // slot/trace mutexes that we hold here.
170 atomic_store_relaxed(
171 &tctx->thr->trace_pos,
172 reinterpret_cast<uptr>(&part->events[TracePart::kSize]));
173 break;
174 }
175 parts->Remove(part);
176 TracePartFree(part);
177 }
178 CHECK_LE(parts->Size(), 1);
179 trace->local_head = parts->Front();
180 if (tctx->thr && !tctx->thr->slot) {
181 atomic_store_relaxed(&tctx->thr->trace_pos, 0);
182 tctx->thr->trace_prev_pc = 0;
183 }
184 if (trace->parts_allocated > trace->parts.Size()) {
185 ctx->trace_part_finished_excess +=
186 trace->parts_allocated - trace->parts.Size();
187 trace->parts_allocated = trace->parts.Size();
188 }
189 }
190 while (ctx->slot_queue.PopFront()) {
191 }
192 for (auto& slot : ctx->slots) {
193 slot.SetEpoch(kEpochZero);
194 slot.journal.Reset();
195 slot.thr = nullptr;
196 ctx->slot_queue.PushBack(&slot);
197 }
198
199 DPrintf("Resetting shadow...\n");
200 auto shadow_begin = ShadowBeg();
201 auto shadow_end = ShadowEnd();
202#if SANITIZER_GO
203 CHECK_NE(0, ctx->mapped_shadow_begin);
204 shadow_begin = ctx->mapped_shadow_begin;
205 shadow_end = ctx->mapped_shadow_end;
206 VPrintf(2, "shadow_begin-shadow_end: (0x%zx-0x%zx)\n",
207 shadow_begin, shadow_end);
78208#endif
79209
80static ALIGNED(64) char thread_registry_placeholder[sizeof(ThreadRegistry)];
81
82static ThreadContextBase *CreateThreadContext(u32 tid) {
83 // Map thread trace when context is created.
84 char name[50];
85 internal_snprintf(name, sizeof(name), "trace %u", tid);
86 MapThreadTrace(GetThreadTrace(tid), TraceSize() * sizeof(Event), name);
87 const uptr hdr = GetThreadTraceHeader(tid);
88 internal_snprintf(name, sizeof(name), "trace header %u", tid);
89 MapThreadTrace(hdr, sizeof(Trace), name);
90 new((void*)hdr) Trace();
91 // We are going to use only a small part of the trace with the default
92 // value of history_size. However, the constructor writes to the whole trace.
93 // Release the unused part.
94 uptr hdr_end = hdr + sizeof(Trace);
95 hdr_end -= sizeof(TraceHeader) * (kTraceParts - TraceParts());
96 hdr_end = RoundUp(hdr_end, GetPageSizeCached());
97 if (hdr_end < hdr + sizeof(Trace)) {
98 ReleaseMemoryPagesToOS(hdr_end, hdr + sizeof(Trace));
99 uptr unused = hdr + sizeof(Trace) - hdr_end;
100 if (hdr_end != (uptr)MmapFixedNoAccess(hdr_end, unused)) {
101 Report("ThreadSanitizer: failed to mprotect(%p, %p)\n",
102 hdr_end, unused);
103 CHECK("unable to mprotect" && 0);
210#if SANITIZER_WINDOWS
211 auto resetFailed =
212 !ZeroMmapFixedRegion(shadow_begin, shadow_end - shadow_begin);
213#else
214 auto resetFailed =
215 !MmapFixedSuperNoReserve(shadow_begin, shadow_end-shadow_begin, "shadow");
216# if !SANITIZER_GO
217 DontDumpShadow(shadow_begin, shadow_end - shadow_begin);
218# endif
219#endif
220 if (resetFailed) {
221 Printf("failed to reset shadow memory\n");
222 Die();
223 }
224 DPrintf("Resetting meta shadow...\n");
225 ctx->metamap.ResetClocks();
226 StoreShadow(&ctx->last_spurious_race, Shadow::kEmpty);
227 ctx->resetting = false;
228}
229
230// Clang does not understand locking all slots in the loop:
231// error: expecting mutex 'slot.mtx' to be held at start of each loop
232void DoReset(ThreadState* thr, uptr epoch) SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
233 for (auto& slot : ctx->slots) {
234 slot.mtx.Lock();
235 if (UNLIKELY(epoch == 0))
236 epoch = ctx->global_epoch;
237 if (UNLIKELY(epoch != ctx->global_epoch)) {
238 // Epoch can't change once we've locked the first slot.
239 CHECK_EQ(slot.sid, 0);
240 slot.mtx.Unlock();
241 return;
242 }
243 }
244 DPrintf("#%d: DoReset epoch=%lu\n", thr ? thr->tid : -1, epoch);
245 DoResetImpl(epoch);
246 for (auto& slot : ctx->slots) slot.mtx.Unlock();
247}
248
249void FlushShadowMemory() { DoReset(nullptr, 0); }
250
251static TidSlot* FindSlotAndLock(ThreadState* thr)
252 SANITIZER_ACQUIRE(thr->slot->mtx) SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
253 CHECK(!thr->slot);
254 TidSlot* slot = nullptr;
255 for (;;) {
256 uptr epoch;
257 {
258 Lock lock(&ctx->slot_mtx);
259 epoch = ctx->global_epoch;
260 if (slot) {
261 // This is an exhausted slot from the previous iteration.
262 if (ctx->slot_queue.Queued(slot))
263 ctx->slot_queue.Remove(slot);
264 thr->slot_locked = false;
265 slot->mtx.Unlock();
266 }
267 for (;;) {
268 slot = ctx->slot_queue.PopFront();
269 if (!slot)
270 break;
271 if (slot->epoch() != kEpochLast) {
272 ctx->slot_queue.PushBack(slot);
273 break;
274 }
275 }
276 }
277 if (!slot) {
278 DoReset(thr, epoch);
279 continue;
104280 }
281 slot->mtx.Lock();
282 CHECK(!thr->slot_locked);
283 thr->slot_locked = true;
284 if (slot->thr) {
285 DPrintf("#%d: preempting sid=%d tid=%d\n", thr->tid, (u32)slot->sid,
286 slot->thr->tid);
287 slot->SetEpoch(slot->thr->fast_state.epoch());
288 slot->thr = nullptr;
289 }
290 if (slot->epoch() != kEpochLast)
291 return slot;
105292 }
106 void *mem = internal_alloc(MBlockThreadContex, sizeof(ThreadContext));
107 return new(mem) ThreadContext(tid);
108293}
109294
295void SlotAttachAndLock(ThreadState* thr) {
296 TidSlot* slot = FindSlotAndLock(thr);
297 DPrintf("#%d: SlotAttach: slot=%u\n", thr->tid, static_cast<int>(slot->sid));
298 CHECK(!slot->thr);
299 CHECK(!thr->slot);
300 slot->thr = thr;
301 thr->slot = slot;
302 Epoch epoch = EpochInc(slot->epoch());
303 CHECK(!EpochOverflow(epoch));
304 slot->SetEpoch(epoch);
305 thr->fast_state.SetSid(slot->sid);
306 thr->fast_state.SetEpoch(epoch);
307 if (thr->slot_epoch != ctx->global_epoch) {
308 thr->slot_epoch = ctx->global_epoch;
309 thr->clock.Reset();
110310#if !SANITIZER_GO
111static const u32 kThreadQuarantineSize = 16;
112#else
113static const u32 kThreadQuarantineSize = 64;
311 thr->last_sleep_stack_id = kInvalidStackID;
312 thr->last_sleep_clock.Reset();
313#endif
314 }
315 thr->clock.Set(slot->sid, epoch);
316 slot->journal.PushBack({thr->tid, epoch});
317}
318
319static void SlotDetachImpl(ThreadState* thr, bool exiting) {
320 TidSlot* slot = thr->slot;
321 thr->slot = nullptr;
322 if (thr != slot->thr) {
323 slot = nullptr; // we don't own the slot anymore
324 if (thr->slot_epoch != ctx->global_epoch) {
325 TracePart* part = nullptr;
326 auto* trace = &thr->tctx->trace;
327 {
328 Lock l(&trace->mtx);
329 auto* parts = &trace->parts;
330 // The trace can be completely empty in an unlikely event
331 // the thread is preempted right after it acquired the slot
332 // in ThreadStart and did not trace any events yet.
333 CHECK_LE(parts->Size(), 1);
334 part = parts->PopFront();
335 thr->tctx->trace.local_head = nullptr;
336 atomic_store_relaxed(&thr->trace_pos, 0);
337 thr->trace_prev_pc = 0;
338 }
339 if (part) {
340 Lock l(&ctx->slot_mtx);
341 TracePartFree(part);
342 }
343 }
344 return;
345 }
346 CHECK(exiting || thr->fast_state.epoch() == kEpochLast);
347 slot->SetEpoch(thr->fast_state.epoch());
348 slot->thr = nullptr;
349}
350
351void SlotDetach(ThreadState* thr) {
352 Lock lock(&thr->slot->mtx);
353 SlotDetachImpl(thr, true);
354}
355
356void SlotLock(ThreadState* thr) SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
357 DCHECK(!thr->slot_locked);
358#if SANITIZER_DEBUG
359 // Check these mutexes are not locked.
360 // We can call DoReset from SlotAttachAndLock, which will lock
361 // these mutexes, but it happens only every once in a while.
362 { ThreadRegistryLock lock(&ctx->thread_registry); }
363 { Lock lock(&ctx->slot_mtx); }
114364#endif
365 TidSlot* slot = thr->slot;
366 slot->mtx.Lock();
367 thr->slot_locked = true;
368 if (LIKELY(thr == slot->thr && thr->fast_state.epoch() != kEpochLast))
369 return;
370 SlotDetachImpl(thr, false);
371 thr->slot_locked = false;
372 slot->mtx.Unlock();
373 SlotAttachAndLock(thr);
374}
375
376void SlotUnlock(ThreadState* thr) {
377 DCHECK(thr->slot_locked);
378 thr->slot_locked = false;
379 thr->slot->mtx.Unlock();
380}
115381
116382Context::Context()
117383 : initialized(),
118384 report_mtx(MutexTypeReport),
119385 nreported(),
120 nmissed_expected(),
121 thread_registry(new (thread_registry_placeholder) ThreadRegistry(
122 CreateThreadContext, kMaxTid, kThreadQuarantineSize, kMaxTidReuse)),
386 thread_registry([](Tid tid) -> ThreadContextBase* {
387 return new (Alloc(sizeof(ThreadContext))) ThreadContext(tid);
388 }),
123389 racy_mtx(MutexTypeRacy),
124390 racy_stacks(),
125 racy_addresses(),
126391 fired_suppressions_mtx(MutexTypeFired),
127 clock_alloc(LINKER_INITIALIZED, "clock allocator") {
392 slot_mtx(MutexTypeSlots),
393 resetting() {
128394 fired_suppressions.reserve(8);
395 for (uptr i = 0; i < ARRAY_SIZE(slots); i++) {
396 TidSlot* slot = &slots[i];
397 slot->sid = static_cast<Sid>(i);
398 slot_queue.PushBack(slot);
399 }
400 global_epoch = 1;
129401}
130402
403TidSlot::TidSlot() : mtx(MutexTypeSlot) {}
404
131405// The objects are allocated in TLS, so one may rely on zero-initialization.
132ThreadState::ThreadState(Context *ctx, u32 tid, int unique_id, u64 epoch,
133 unsigned reuse_count, uptr stk_addr, uptr stk_size,
134 uptr tls_addr, uptr tls_size)
135 : fast_state(tid, epoch)
136 // Do not touch these, rely on zero initialization,
137 // they may be accessed before the ctor.
138 // , ignore_reads_and_writes()
139 // , ignore_interceptors()
140 ,
141 clock(tid, reuse_count)
142#if !SANITIZER_GO
143 ,
144 jmp_bufs()
145#endif
146 ,
147 tid(tid),
148 unique_id(unique_id),
149 stk_addr(stk_addr),
150 stk_size(stk_size),
151 tls_addr(tls_addr),
152 tls_size(tls_size)
406ThreadState::ThreadState(Tid tid)
407 // Do not touch these, rely on zero initialization,
408 // they may be accessed before the ctor.
409 // ignore_reads_and_writes()
410 // ignore_interceptors()
411 : tid(tid) {
412 CHECK_EQ(reinterpret_cast<uptr>(this) % SANITIZER_CACHE_LINE_SIZE, 0);
153413#if !SANITIZER_GO
154 ,
155 last_sleep_clock(tid)
414 // C/C++ uses fixed size shadow stack.
415 const int kInitStackSize = kShadowStackSize;
416 shadow_stack = static_cast<uptr*>(
417 MmapNoReserveOrDie(kInitStackSize * sizeof(uptr), "shadow stack"));
418 SetShadowRegionHugePageMode(reinterpret_cast<uptr>(shadow_stack),
419 kInitStackSize * sizeof(uptr));
420#else
421 // Go uses malloc-allocated shadow stack with dynamic size.
422 const int kInitStackSize = 8;
423 shadow_stack = static_cast<uptr*>(Alloc(kInitStackSize * sizeof(uptr)));
156424#endif
157{
425 shadow_stack_pos = shadow_stack;
426 shadow_stack_end = shadow_stack + kInitStackSize;
158427}
159428
160429#if !SANITIZER_GO
161static void MemoryProfiler(Context *ctx, fd_t fd, int i) {
162 uptr n_threads;
163 uptr n_running_threads;
164 ctx->thread_registry->GetNumberOfThreads(&n_threads, &n_running_threads);
430void MemoryProfiler(u64 uptime) {
431 if (ctx->memprof_fd == kInvalidFd)
432 return;
165433 InternalMmapVector<char> buf(4096);
166 WriteMemoryProfile(buf.data(), buf.size(), n_threads, n_running_threads);
167 WriteToFile(fd, buf.data(), internal_strlen(buf.data()));
434 WriteMemoryProfile(buf.data(), buf.size(), uptime);
435 WriteToFile(ctx->memprof_fd, buf.data(), internal_strlen(buf.data()));
436}
437
438static bool InitializeMemoryProfiler() {
439 ctx->memprof_fd = kInvalidFd;
440 const char *fname = flags()->profile_memory;
441 if (!fname || !fname[0])
442 return false;
443 if (internal_strcmp(fname, "stdout") == 0) {
444 ctx->memprof_fd = 1;
445 } else if (internal_strcmp(fname, "stderr") == 0) {
446 ctx->memprof_fd = 2;
447 } else {
448 InternalScopedString filename;
449 filename.append("%s.%d", fname, (int)internal_getpid());
450 ctx->memprof_fd = OpenFile(filename.data(), WrOnly);
451 if (ctx->memprof_fd == kInvalidFd) {
452 Printf("ThreadSanitizer: failed to open memory profile file '%s'\n",
453 filename.data());
454 return false;
455 }
456 }
457 MemoryProfiler(0);
458 return true;
168459}
169460
170461static void *BackgroundThread(void *arg) {
......@@ -172,64 +463,43 @@ static void *BackgroundThread(void *arg) {
172463 // We don't use ScopedIgnoreInterceptors, because we want ignores to be
173464 // enabled even when the thread function exits (e.g. during pthread thread
174465 // shutdown code).
175 cur_thread_init();
176 cur_thread()->ignore_interceptors++;
466 cur_thread_init()->ignore_interceptors++;
177467 const u64 kMs2Ns = 1000 * 1000;
468 const u64 start = NanoTime();
178469
179 fd_t mprof_fd = kInvalidFd;
180 if (flags()->profile_memory && flags()->profile_memory[0]) {
181 if (internal_strcmp(flags()->profile_memory, "stdout") == 0) {
182 mprof_fd = 1;
183 } else if (internal_strcmp(flags()->profile_memory, "stderr") == 0) {
184 mprof_fd = 2;
185 } else {
186 InternalScopedString filename;
187 filename.append("%s.%d", flags()->profile_memory, (int)internal_getpid());
188 fd_t fd = OpenFile(filename.data(), WrOnly);
189 if (fd == kInvalidFd) {
190 Printf("ThreadSanitizer: failed to open memory profile file '%s'\n",
191 filename.data());
192 } else {
193 mprof_fd = fd;
194 }
195 }
196 }
197
198 u64 last_flush = NanoTime();
470 u64 last_flush = start;
199471 uptr last_rss = 0;
200 for (int i = 0;
201 atomic_load(&ctx->stop_background_thread, memory_order_relaxed) == 0;
202 i++) {
472 while (!atomic_load_relaxed(&ctx->stop_background_thread)) {
203473 SleepForMillis(100);
204474 u64 now = NanoTime();
205475
206476 // Flush memory if requested.
207477 if (flags()->flush_memory_ms > 0) {
208478 if (last_flush + flags()->flush_memory_ms * kMs2Ns < now) {
209 VPrintf(1, "ThreadSanitizer: periodic memory flush\n");
479 VReport(1, "ThreadSanitizer: periodic memory flush\n");
210480 FlushShadowMemory();
211 last_flush = NanoTime();
481 now = last_flush = NanoTime();
212482 }
213483 }
214 // GetRSS can be expensive on huge programs, so don't do it every 100ms.
215484 if (flags()->memory_limit_mb > 0) {
216485 uptr rss = GetRSS();
217486 uptr limit = uptr(flags()->memory_limit_mb) << 20;
218 VPrintf(1, "ThreadSanitizer: memory flush check"
219 " RSS=%llu LAST=%llu LIMIT=%llu\n",
487 VReport(1,
488 "ThreadSanitizer: memory flush check"
489 " RSS=%llu LAST=%llu LIMIT=%llu\n",
220490 (u64)rss >> 20, (u64)last_rss >> 20, (u64)limit >> 20);
221491 if (2 * rss > limit + last_rss) {
222 VPrintf(1, "ThreadSanitizer: flushing memory due to RSS\n");
492 VReport(1, "ThreadSanitizer: flushing memory due to RSS\n");
223493 FlushShadowMemory();
224494 rss = GetRSS();
225 VPrintf(1, "ThreadSanitizer: memory flushed RSS=%llu\n", (u64)rss>>20);
495 now = NanoTime();
496 VReport(1, "ThreadSanitizer: memory flushed RSS=%llu\n",
497 (u64)rss >> 20);
226498 }
227499 last_rss = rss;
228500 }
229501
230 // Write memory profile if requested.
231 if (mprof_fd != kInvalidFd)
232 MemoryProfiler(ctx, mprof_fd, i);
502 MemoryProfiler(now - start);
233503
234504 // Flush symbolizer cache if requested.
235505 if (flags()->flush_symbolizer_ms > 0) {
......@@ -260,31 +530,96 @@ static void StopBackgroundThread() {
260530#endif
261531
262532void DontNeedShadowFor(uptr addr, uptr size) {
263 ReleaseMemoryPagesToOS(MemToShadow(addr), MemToShadow(addr + size));
533 ReleaseMemoryPagesToOS(reinterpret_cast<uptr>(MemToShadow(addr)),
534 reinterpret_cast<uptr>(MemToShadow(addr + size)));
264535}
265536
266537#if !SANITIZER_GO
538// We call UnmapShadow before the actual munmap, at that point we don't yet
539// know if the provided address/size are sane. We can't call UnmapShadow
540// after the actual munmap becuase at that point the memory range can
541// already be reused for something else, so we can't rely on the munmap
542// return value to understand is the values are sane.
543// While calling munmap with insane values (non-canonical address, negative
544// size, etc) is an error, the kernel won't crash. We must also try to not
545// crash as the failure mode is very confusing (paging fault inside of the
546// runtime on some derived shadow address).
547static bool IsValidMmapRange(uptr addr, uptr size) {
548 if (size == 0)
549 return true;
550 if (static_cast<sptr>(size) < 0)
551 return false;
552 if (!IsAppMem(addr) || !IsAppMem(addr + size - 1))
553 return false;
554 // Check that if the start of the region belongs to one of app ranges,
555 // end of the region belongs to the same region.
556 const uptr ranges[][2] = {
557 {LoAppMemBeg(), LoAppMemEnd()},
558 {MidAppMemBeg(), MidAppMemEnd()},
559 {HiAppMemBeg(), HiAppMemEnd()},
560 };
561 for (auto range : ranges) {
562 if (addr >= range[0] && addr < range[1])
563 return addr + size <= range[1];
564 }
565 return false;
566}
567
267568void UnmapShadow(ThreadState *thr, uptr addr, uptr size) {
268 if (size == 0) return;
569 if (size == 0 || !IsValidMmapRange(addr, size))
570 return;
269571 DontNeedShadowFor(addr, size);
270572 ScopedGlobalProcessor sgp;
271 ctx->metamap.ResetRange(thr->proc(), addr, size);
573 SlotLocker locker(thr, true);
574 ctx->metamap.ResetRange(thr->proc(), addr, size, true);
272575}
273576#endif
274577
275578void MapShadow(uptr addr, uptr size) {
579 // Ensure thead registry lock held, so as to synchronize
580 // with DoReset, which also access the mapped_shadow_* ctxt fields.
581 ThreadRegistryLock lock0(&ctx->thread_registry);
582 static bool data_mapped = false;
583
584#if !SANITIZER_GO
276585 // Global data is not 64K aligned, but there are no adjacent mappings,
277586 // so we can get away with unaligned mapping.
278587 // CHECK_EQ(addr, addr & ~((64 << 10) - 1)); // windows wants 64K alignment
279588 const uptr kPageSize = GetPageSizeCached();
280589 uptr shadow_begin = RoundDownTo((uptr)MemToShadow(addr), kPageSize);
281590 uptr shadow_end = RoundUpTo((uptr)MemToShadow(addr + size), kPageSize);
282 if (!MmapFixedSuperNoReserve(shadow_begin, shadow_end - shadow_begin,
283 "shadow"))
591 if (!MmapFixedNoReserve(shadow_begin, shadow_end - shadow_begin, "shadow"))
284592 Die();
593#else
594 uptr shadow_begin = RoundDownTo((uptr)MemToShadow(addr), (64 << 10));
595 uptr shadow_end = RoundUpTo((uptr)MemToShadow(addr + size), (64 << 10));
596 VPrintf(2, "MapShadow for (0x%zx-0x%zx), begin/end: (0x%zx-0x%zx)\n",
597 addr, addr + size, shadow_begin, shadow_end);
598
599 if (!data_mapped) {
600 // First call maps data+bss.
601 if (!MmapFixedSuperNoReserve(shadow_begin, shadow_end - shadow_begin, "shadow"))
602 Die();
603 } else {
604 VPrintf(2, "ctx->mapped_shadow_{begin,end} = (0x%zx-0x%zx)\n",
605 ctx->mapped_shadow_begin, ctx->mapped_shadow_end);
606 // Second and subsequent calls map heap.
607 if (shadow_end <= ctx->mapped_shadow_end)
608 return;
609 if (!ctx->mapped_shadow_begin || ctx->mapped_shadow_begin > shadow_begin)
610 ctx->mapped_shadow_begin = shadow_begin;
611 if (shadow_begin < ctx->mapped_shadow_end)
612 shadow_begin = ctx->mapped_shadow_end;
613 VPrintf(2, "MapShadow begin/end = (0x%zx-0x%zx)\n",
614 shadow_begin, shadow_end);
615 if (!MmapFixedSuperNoReserve(shadow_begin, shadow_end - shadow_begin,
616 "shadow"))
617 Die();
618 ctx->mapped_shadow_end = shadow_end;
619 }
620#endif
285621
286622 // Meta shadow is 2:1, so tread carefully.
287 static bool data_mapped = false;
288623 static uptr mapped_meta_end = 0;
289624 uptr meta_begin = (uptr)MemToMeta(addr);
290625 uptr meta_end = (uptr)MemToMeta(addr + size);
......@@ -297,12 +632,11 @@ void MapShadow(uptr addr, uptr size) {
297632 "meta shadow"))
298633 Die();
299634 } else {
300 // Mapping continous heap.
635 // Mapping continuous heap.
301636 // Windows wants 64K alignment.
302637 meta_begin = RoundDownTo(meta_begin, 64 << 10);
303638 meta_end = RoundUpTo(meta_end, 64 << 10);
304 if (meta_end <= mapped_meta_end)
305 return;
639 CHECK_GT(meta_end, mapped_meta_end);
306640 if (meta_begin < mapped_meta_end)
307641 meta_begin = mapped_meta_end;
308642 if (!MmapFixedSuperNoReserve(meta_begin, meta_end - meta_begin,
......@@ -310,56 +644,8 @@ void MapShadow(uptr addr, uptr size) {
310644 Die();
311645 mapped_meta_end = meta_end;
312646 }
313 VPrintf(2, "mapped meta shadow for (%p-%p) at (%p-%p)\n",
314 addr, addr+size, meta_begin, meta_end);
315}
316
317void MapThreadTrace(uptr addr, uptr size, const char *name) {
318 DPrintf("#0: Mapping trace at %p-%p(0x%zx)\n", addr, addr + size, size);
319 CHECK_GE(addr, TraceMemBeg());
320 CHECK_LE(addr + size, TraceMemEnd());
321 CHECK_EQ(addr, addr & ~((64 << 10) - 1)); // windows wants 64K alignment
322 if (!MmapFixedSuperNoReserve(addr, size, name)) {
323 Printf("FATAL: ThreadSanitizer can not mmap thread trace (%p/%p)\n",
324 addr, size);
325 Die();
326 }
327}
328
329static void CheckShadowMapping() {
330 uptr beg, end;
331 for (int i = 0; GetUserRegion(i, &beg, &end); i++) {
332 // Skip cases for empty regions (heap definition for architectures that
333 // do not use 64-bit allocator).
334 if (beg == end)
335 continue;
336 VPrintf(3, "checking shadow region %p-%p\n", beg, end);
337 uptr prev = 0;
338 for (uptr p0 = beg; p0 <= end; p0 += (end - beg) / 4) {
339 for (int x = -(int)kShadowCell; x <= (int)kShadowCell; x += kShadowCell) {
340 const uptr p = RoundDown(p0 + x, kShadowCell);
341 if (p < beg || p >= end)
342 continue;
343 const uptr s = MemToShadow(p);
344 const uptr m = (uptr)MemToMeta(p);
345 VPrintf(3, " checking pointer %p: shadow=%p meta=%p\n", p, s, m);
346 CHECK(IsAppMem(p));
347 CHECK(IsShadowMem(s));
348 CHECK_EQ(p, ShadowToMem(s));
349 CHECK(IsMetaMem(m));
350 if (prev) {
351 // Ensure that shadow and meta mappings are linear within a single
352 // user range. Lots of code that processes memory ranges assumes it.
353 const uptr prev_s = MemToShadow(prev);
354 const uptr prev_m = (uptr)MemToMeta(prev);
355 CHECK_EQ(s - prev_s, (p - prev) * kShadowMultiplier);
356 CHECK_EQ((m - prev_m) / kMetaShadowSize,
357 (p - prev) / kMetaShadowCell);
358 }
359 prev = p;
360 }
361 }
362 }
647 VPrintf(2, "mapped meta shadow for (0x%zx-0x%zx) at (0x%zx-0x%zx)\n", addr,
648 addr + size, meta_begin, meta_end);
363649}
364650
365651#if !SANITIZER_GO
......@@ -380,15 +666,19 @@ void CheckUnwind() {
380666 // since we are going to die soon.
381667 ScopedIgnoreInterceptors ignore;
382668#if !SANITIZER_GO
383 cur_thread()->ignore_sync++;
384 cur_thread()->ignore_reads_and_writes++;
669 ThreadState* thr = cur_thread();
670 thr->nomalloc = false;
671 thr->ignore_sync++;
672 thr->ignore_reads_and_writes++;
673 atomic_store_relaxed(&thr->in_signal_handler, 0);
385674#endif
386675 PrintCurrentStackSlow(StackTrace::GetCurrentPc());
387676}
388677
678bool is_initialized;
679
389680void Initialize(ThreadState *thr) {
390681 // Thread safe because done before all threads exist.
391 static bool is_initialized = false;
392682 if (is_initialized)
393683 return;
394684 is_initialized = true;
......@@ -409,9 +699,6 @@ void Initialize(ThreadState *thr) {
409699 __tsan::InitializePlatformEarly();
410700
411701#if !SANITIZER_GO
412 // Re-exec ourselves if we need to set additional env or command line args.
413 MaybeReexec();
414
415702 InitializeAllocator();
416703 ReplaceSystemMalloc();
417704#endif
......@@ -420,7 +707,6 @@ void Initialize(ThreadState *thr) {
420707 Processor *proc = ProcCreate();
421708 ProcWire(proc, thr);
422709 InitializeInterceptors();
423 CheckShadowMapping();
424710 InitializePlatform();
425711 InitializeDynamicAnnotations();
426712#if !SANITIZER_GO
......@@ -436,21 +722,23 @@ void Initialize(ThreadState *thr) {
436722 Symbolizer::GetOrInit()->AddHooks(EnterSymbolizer, ExitSymbolizer);
437723#endif
438724
439 VPrintf(1, "***** Running under ThreadSanitizer v2 (pid %d) *****\n",
725 VPrintf(1, "***** Running under ThreadSanitizer v3 (pid %d) *****\n",
440726 (int)internal_getpid());
441727
442728 // Initialize thread 0.
443 int tid = ThreadCreate(thr, 0, 0, true);
444 CHECK_EQ(tid, 0);
729 Tid tid = ThreadCreate(nullptr, 0, 0, true);
730 CHECK_EQ(tid, kMainTid);
445731 ThreadStart(thr, tid, GetTid(), ThreadType::Regular);
446732#if TSAN_CONTAINS_UBSAN
447733 __ubsan::InitAsPlugin();
448734#endif
449 ctx->initialized = true;
450735
451736#if !SANITIZER_GO
452737 Symbolizer::LateInitialize();
738 if (InitializeMemoryProfiler() || flags()->force_background_thread)
739 MaybeSpawnBackgroundThread();
453740#endif
741 ctx->initialized = true;
454742
455743 if (flags()->stop_on_start) {
456744 Printf("ThreadSanitizer is suspended at startup (pid %d)."
......@@ -476,20 +764,21 @@ void MaybeSpawnBackgroundThread() {
476764#endif
477765}
478766
479
480767int Finalize(ThreadState *thr) {
481768 bool failed = false;
482769
770#if !SANITIZER_GO
483771 if (common_flags()->print_module_map == 1)
484772 DumpProcessMap();
773#endif
485774
486775 if (flags()->atexit_sleep_ms > 0 && ThreadCount(thr) > 1)
487 SleepForMillis(flags()->atexit_sleep_ms);
776 internal_usleep(u64(flags()->atexit_sleep_ms) * 1000);
488777
489 // Wait for pending reports.
490 ctx->report_mtx.Lock();
491 { ScopedErrorReportLock l; }
492 ctx->report_mtx.Unlock();
778 {
779 // Wait for pending reports.
780 ScopedErrorReportLock lock;
781 }
493782
494783#if !SANITIZER_GO
495784 if (Verbosity()) AllocatorPrintStats();
......@@ -506,18 +795,8 @@ int Finalize(ThreadState *thr) {
506795#endif
507796 }
508797
509 if (ctx->nmissed_expected) {
510 failed = true;
511 Printf("ThreadSanitizer: missed %d expected races\n",
512 ctx->nmissed_expected);
513 }
514
515798 if (common_flags()->print_suppressions)
516799 PrintMatchedSuppressions();
517#if !SANITIZER_GO
518 if (flags()->print_benign)
519 PrintMatchedBenignRaces();
520#endif
521800
522801 failed = OnFinalize(failed);
523802
......@@ -525,10 +804,16 @@ int Finalize(ThreadState *thr) {
525804}
526805
527806#if !SANITIZER_GO
528void ForkBefore(ThreadState *thr, uptr pc) NO_THREAD_SAFETY_ANALYSIS {
529 ctx->thread_registry->Lock();
530 ctx->report_mtx.Lock();
807void ForkBefore(ThreadState* thr, uptr pc) SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
808 GlobalProcessorLock();
809 // Detaching from the slot makes OnUserFree skip writing to the shadow.
810 // The slot will be locked so any attempts to use it will deadlock anyway.
811 SlotDetach(thr);
812 for (auto& slot : ctx->slots) slot.mtx.Lock();
813 ctx->thread_registry.Lock();
814 ctx->slot_mtx.Lock();
531815 ScopedErrorReportLock::Lock();
816 AllocatorLock();
532817 // Suppress all reports in the pthread_atfork callbacks.
533818 // Reports will deadlock on the report_mtx.
534819 // We could ignore sync operations as well,
......@@ -537,36 +822,48 @@ void ForkBefore(ThreadState *thr, uptr pc) NO_THREAD_SAFETY_ANALYSIS {
537822 thr->suppress_reports++;
538823 // On OS X, REAL(fork) can call intercepted functions (OSSpinLockLock), and
539824 // we'll assert in CheckNoLocks() unless we ignore interceptors.
825 // On OS X libSystem_atfork_prepare/parent/child callbacks are called
826 // after/before our callbacks and they call free.
540827 thr->ignore_interceptors++;
828 // Disables memory write in OnUserAlloc/Free.
829 thr->ignore_reads_and_writes++;
830
831 __tsan_test_only_on_fork();
541832}
542833
543void ForkParentAfter(ThreadState *thr, uptr pc) NO_THREAD_SAFETY_ANALYSIS {
834static void ForkAfter(ThreadState* thr) SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
544835 thr->suppress_reports--; // Enabled in ForkBefore.
545836 thr->ignore_interceptors--;
837 thr->ignore_reads_and_writes--;
838 AllocatorUnlock();
546839 ScopedErrorReportLock::Unlock();
547 ctx->report_mtx.Unlock();
548 ctx->thread_registry->Unlock();
840 ctx->slot_mtx.Unlock();
841 ctx->thread_registry.Unlock();
842 for (auto& slot : ctx->slots) slot.mtx.Unlock();
843 SlotAttachAndLock(thr);
844 SlotUnlock(thr);
845 GlobalProcessorUnlock();
549846}
550847
551void ForkChildAfter(ThreadState *thr, uptr pc) NO_THREAD_SAFETY_ANALYSIS {
552 thr->suppress_reports--; // Enabled in ForkBefore.
553 thr->ignore_interceptors--;
554 ScopedErrorReportLock::Unlock();
555 ctx->report_mtx.Unlock();
556 ctx->thread_registry->Unlock();
848void ForkParentAfter(ThreadState* thr, uptr pc) { ForkAfter(thr); }
557849
558 uptr nthread = 0;
559 ctx->thread_registry->GetNumberOfThreads(0, 0, &nthread /* alive threads */);
560 VPrintf(1, "ThreadSanitizer: forked new process with pid %d,"
561 " parent had %d threads\n", (int)internal_getpid(), (int)nthread);
850void ForkChildAfter(ThreadState* thr, uptr pc, bool start_thread) {
851 ForkAfter(thr);
852 u32 nthread = ctx->thread_registry.OnFork(thr->tid);
853 VPrintf(1,
854 "ThreadSanitizer: forked new process with pid %d,"
855 " parent had %d threads\n",
856 (int)internal_getpid(), (int)nthread);
562857 if (nthread == 1) {
563 StartBackgroundThread();
858 if (start_thread)
859 StartBackgroundThread();
564860 } else {
565861 // We've just forked a multi-threaded process. We cannot reasonably function
566862 // after that (some mutexes may be locked before fork). So just enable
567863 // ignores for everything in the hope that we will exec soon.
568864 ctx->after_multithreaded_fork = true;
569865 thr->ignore_interceptors++;
866 thr->suppress_reports++;
570867 ThreadIgnoreBegin(thr, pc);
571868 ThreadIgnoreSyncBegin(thr, pc);
572869 }
......@@ -578,19 +875,20 @@ NOINLINE
578875void GrowShadowStack(ThreadState *thr) {
579876 const int sz = thr->shadow_stack_end - thr->shadow_stack;
580877 const int newsz = 2 * sz;
581 uptr *newstack = (uptr*)internal_alloc(MBlockShadowStack,
582 newsz * sizeof(uptr));
878 auto *newstack = (uptr *)Alloc(newsz * sizeof(uptr));
583879 internal_memcpy(newstack, thr->shadow_stack, sz * sizeof(uptr));
584 internal_free(thr->shadow_stack);
880 Free(thr->shadow_stack);
585881 thr->shadow_stack = newstack;
586882 thr->shadow_stack_pos = newstack + sz;
587883 thr->shadow_stack_end = newstack + newsz;
588884}
589885#endif
590886
591u32 CurrentStackId(ThreadState *thr, uptr pc) {
887StackID CurrentStackId(ThreadState *thr, uptr pc) {
888#if !SANITIZER_GO
592889 if (!thr->is_inited) // May happen during bootstrap.
593 return 0;
890 return kInvalidStackID;
891#endif
594892 if (pc != 0) {
595893#if !SANITIZER_GO
596894 DCHECK_LT(thr->shadow_stack_pos, thr->shadow_stack_end);
......@@ -601,486 +899,149 @@ u32 CurrentStackId(ThreadState *thr, uptr pc) {
601899 thr->shadow_stack_pos[0] = pc;
602900 thr->shadow_stack_pos++;
603901 }
604 u32 id = StackDepotPut(
902 StackID id = StackDepotPut(
605903 StackTrace(thr->shadow_stack, thr->shadow_stack_pos - thr->shadow_stack));
606904 if (pc != 0)
607905 thr->shadow_stack_pos--;
608906 return id;
609907}
610908
611void TraceSwitch(ThreadState *thr) {
612#if !SANITIZER_GO
613 if (ctx->after_multithreaded_fork)
614 return;
615#endif
616 thr->nomalloc++;
617 Trace *thr_trace = ThreadTrace(thr->tid);
618 Lock l(&thr_trace->mtx);
619 unsigned trace = (thr->fast_state.epoch() / kTracePartSize) % TraceParts();
620 TraceHeader *hdr = &thr_trace->headers[trace];
621 hdr->epoch0 = thr->fast_state.epoch();
622 ObtainCurrentStack(thr, 0, &hdr->stack0);
623 hdr->mset0 = thr->mset;
624 thr->nomalloc--;
625}
626
627Trace *ThreadTrace(int tid) {
628 return (Trace*)GetThreadTraceHeader(tid);
629}
630
631uptr TraceTopPC(ThreadState *thr) {
632 Event *events = (Event*)GetThreadTrace(thr->tid);
633 uptr pc = events[thr->fast_state.GetTracePos()];
634 return pc;
635}
636
637uptr TraceSize() {
638 return (uptr)(1ull << (kTracePartSizeBits + flags()->history_size + 1));
639}
640
641uptr TraceParts() {
642 return TraceSize() / kTracePartSize;
643}
644
645#if !SANITIZER_GO
646extern "C" void __tsan_trace_switch() {
647 TraceSwitch(cur_thread());
648}
649
650extern "C" void __tsan_report_race() {
651 ReportRace(cur_thread());
652}
653#endif
654
655ALWAYS_INLINE
656Shadow LoadShadow(u64 *p) {
657 u64 raw = atomic_load((atomic_uint64_t*)p, memory_order_relaxed);
658 return Shadow(raw);
659}
660
661ALWAYS_INLINE
662void StoreShadow(u64 *sp, u64 s) {
663 atomic_store((atomic_uint64_t*)sp, s, memory_order_relaxed);
664}
665
666ALWAYS_INLINE
667void StoreIfNotYetStored(u64 *sp, u64 *s) {
668 StoreShadow(sp, *s);
669 *s = 0;
670}
671
672ALWAYS_INLINE
673void HandleRace(ThreadState *thr, u64 *shadow_mem,
674 Shadow cur, Shadow old) {
675 thr->racy_state[0] = cur.raw();
676 thr->racy_state[1] = old.raw();
677 thr->racy_shadow_addr = shadow_mem;
678#if !SANITIZER_GO
679 HACKY_CALL(__tsan_report_race);
680#else
681 ReportRace(thr);
682#endif
683}
684
685static inline bool HappensBefore(Shadow old, ThreadState *thr) {
686 return thr->clock.get(old.TidWithIgnore()) >= old.epoch();
687}
688
689ALWAYS_INLINE
690void MemoryAccessImpl1(ThreadState *thr, uptr addr,
691 int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic,
692 u64 *shadow_mem, Shadow cur) {
693
694 // This potentially can live in an MMX/SSE scratch register.
695 // The required intrinsics are:
696 // __m128i _mm_move_epi64(__m128i*);
697 // _mm_storel_epi64(u64*, __m128i);
698 u64 store_word = cur.raw();
699 bool stored = false;
700
701 // scan all the shadow values and dispatch to 4 categories:
702 // same, replace, candidate and race (see comments below).
703 // we consider only 3 cases regarding access sizes:
704 // equal, intersect and not intersect. initially I considered
705 // larger and smaller as well, it allowed to replace some
706 // 'candidates' with 'same' or 'replace', but I think
707 // it's just not worth it (performance- and complexity-wise).
708
709 Shadow old(0);
710
711 // It release mode we manually unroll the loop,
712 // because empirically gcc generates better code this way.
713 // However, we can't afford unrolling in debug mode, because the function
714 // consumes almost 4K of stack. Gtest gives only 4K of stack to death test
715 // threads, which is not enough for the unrolled loop.
716#if SANITIZER_DEBUG
717 for (int idx = 0; idx < 4; idx++) {
718#include "tsan_update_shadow_word_inl.h"
719 }
720#else
721 int idx = 0;
722#include "tsan_update_shadow_word_inl.h"
723 idx = 1;
724 if (stored) {
725#include "tsan_update_shadow_word_inl.h"
726 } else {
727#include "tsan_update_shadow_word_inl.h"
728 }
729 idx = 2;
730 if (stored) {
731#include "tsan_update_shadow_word_inl.h"
732 } else {
733#include "tsan_update_shadow_word_inl.h"
734 }
735 idx = 3;
736 if (stored) {
737#include "tsan_update_shadow_word_inl.h"
738 } else {
739#include "tsan_update_shadow_word_inl.h"
740 }
741#endif
742
743 // we did not find any races and had already stored
744 // the current access info, so we are done
745 if (LIKELY(stored))
746 return;
747 // choose a random candidate slot and replace it
748 StoreShadow(shadow_mem + (cur.epoch() % kShadowCnt), store_word);
749 return;
750 RACE:
751 HandleRace(thr, shadow_mem, cur, old);
752 return;
753}
754
755void UnalignedMemoryAccess(ThreadState *thr, uptr pc, uptr addr,
756 int size, bool kAccessIsWrite, bool kIsAtomic) {
757 while (size) {
758 int size1 = 1;
759 int kAccessSizeLog = kSizeLog1;
760 if (size >= 8 && (addr & ~7) == ((addr + 7) & ~7)) {
761 size1 = 8;
762 kAccessSizeLog = kSizeLog8;
763 } else if (size >= 4 && (addr & ~7) == ((addr + 3) & ~7)) {
764 size1 = 4;
765 kAccessSizeLog = kSizeLog4;
766 } else if (size >= 2 && (addr & ~7) == ((addr + 1) & ~7)) {
767 size1 = 2;
768 kAccessSizeLog = kSizeLog2;
769 }
770 MemoryAccess(thr, pc, addr, kAccessSizeLog, kAccessIsWrite, kIsAtomic);
771 addr += size1;
772 size -= size1;
773 }
774}
775
776ALWAYS_INLINE
777bool ContainsSameAccessSlow(u64 *s, u64 a, u64 sync_epoch, bool is_write) {
778 Shadow cur(a);
779 for (uptr i = 0; i < kShadowCnt; i++) {
780 Shadow old(LoadShadow(&s[i]));
781 if (Shadow::Addr0AndSizeAreEqual(cur, old) &&
782 old.TidWithIgnore() == cur.TidWithIgnore() &&
783 old.epoch() > sync_epoch &&
784 old.IsAtomic() == cur.IsAtomic() &&
785 old.IsRead() <= cur.IsRead())
786 return true;
909static bool TraceSkipGap(ThreadState* thr) {
910 Trace *trace = &thr->tctx->trace;
911 Event *pos = reinterpret_cast<Event *>(atomic_load_relaxed(&thr->trace_pos));
912 DCHECK_EQ(reinterpret_cast<uptr>(pos + 1) & TracePart::kAlignment, 0);
913 auto *part = trace->parts.Back();
914 DPrintf("#%d: TraceSwitchPart enter trace=%p parts=%p-%p pos=%p\n", thr->tid,
915 trace, trace->parts.Front(), part, pos);
916 if (!part)
917 return false;
918 // We can get here when we still have space in the current trace part.
919 // The fast-path check in TraceAcquire has false positives in the middle of
920 // the part. Check if we are indeed at the end of the current part or not,
921 // and fill any gaps with NopEvent's.
922 Event* end = &part->events[TracePart::kSize];
923 DCHECK_GE(pos, &part->events[0]);
924 DCHECK_LE(pos, end);
925 if (pos + 1 < end) {
926 if ((reinterpret_cast<uptr>(pos) & TracePart::kAlignment) ==
927 TracePart::kAlignment)
928 *pos++ = NopEvent;
929 *pos++ = NopEvent;
930 DCHECK_LE(pos + 2, end);
931 atomic_store_relaxed(&thr->trace_pos, reinterpret_cast<uptr>(pos));
932 return true;
787933 }
934 // We are indeed at the end.
935 for (; pos < end; pos++) *pos = NopEvent;
788936 return false;
789937}
790938
791#if defined(__SSE3__)
792#define SHUF(v0, v1, i0, i1, i2, i3) _mm_castps_si128(_mm_shuffle_ps( \
793 _mm_castsi128_ps(v0), _mm_castsi128_ps(v1), \
794 (i0)*1 + (i1)*4 + (i2)*16 + (i3)*64))
795ALWAYS_INLINE
796bool ContainsSameAccessFast(u64 *s, u64 a, u64 sync_epoch, bool is_write) {
797 // This is an optimized version of ContainsSameAccessSlow.
798 // load current access into access[0:63]
799 const m128 access = _mm_cvtsi64_si128(a);
800 // duplicate high part of access in addr0:
801 // addr0[0:31] = access[32:63]
802 // addr0[32:63] = access[32:63]
803 // addr0[64:95] = access[32:63]
804 // addr0[96:127] = access[32:63]
805 const m128 addr0 = SHUF(access, access, 1, 1, 1, 1);
806 // load 4 shadow slots
807 const m128 shadow0 = _mm_load_si128((__m128i*)s);
808 const m128 shadow1 = _mm_load_si128((__m128i*)s + 1);
809 // load high parts of 4 shadow slots into addr_vect:
810 // addr_vect[0:31] = shadow0[32:63]
811 // addr_vect[32:63] = shadow0[96:127]
812 // addr_vect[64:95] = shadow1[32:63]
813 // addr_vect[96:127] = shadow1[96:127]
814 m128 addr_vect = SHUF(shadow0, shadow1, 1, 3, 1, 3);
815 if (!is_write) {
816 // set IsRead bit in addr_vect
817 const m128 rw_mask1 = _mm_cvtsi64_si128(1<<15);
818 const m128 rw_mask = SHUF(rw_mask1, rw_mask1, 0, 0, 0, 0);
819 addr_vect = _mm_or_si128(addr_vect, rw_mask);
820 }
821 // addr0 == addr_vect?
822 const m128 addr_res = _mm_cmpeq_epi32(addr0, addr_vect);
823 // epoch1[0:63] = sync_epoch
824 const m128 epoch1 = _mm_cvtsi64_si128(sync_epoch);
825 // epoch[0:31] = sync_epoch[0:31]
826 // epoch[32:63] = sync_epoch[0:31]
827 // epoch[64:95] = sync_epoch[0:31]
828 // epoch[96:127] = sync_epoch[0:31]
829 const m128 epoch = SHUF(epoch1, epoch1, 0, 0, 0, 0);
830 // load low parts of shadow cell epochs into epoch_vect:
831 // epoch_vect[0:31] = shadow0[0:31]
832 // epoch_vect[32:63] = shadow0[64:95]
833 // epoch_vect[64:95] = shadow1[0:31]
834 // epoch_vect[96:127] = shadow1[64:95]
835 const m128 epoch_vect = SHUF(shadow0, shadow1, 0, 2, 0, 2);
836 // epoch_vect >= sync_epoch?
837 const m128 epoch_res = _mm_cmpgt_epi32(epoch_vect, epoch);
838 // addr_res & epoch_res
839 const m128 res = _mm_and_si128(addr_res, epoch_res);
840 // mask[0] = res[7]
841 // mask[1] = res[15]
842 // ...
843 // mask[15] = res[127]
844 const int mask = _mm_movemask_epi8(res);
845 return mask != 0;
846}
847#endif
848
849ALWAYS_INLINE
850bool ContainsSameAccess(u64 *s, u64 a, u64 sync_epoch, bool is_write) {
851#if defined(__SSE3__)
852 bool res = ContainsSameAccessFast(s, a, sync_epoch, is_write);
853 // NOTE: this check can fail if the shadow is concurrently mutated
854 // by other threads. But it still can be useful if you modify
855 // ContainsSameAccessFast and want to ensure that it's not completely broken.
856 // DCHECK_EQ(res, ContainsSameAccessSlow(s, a, sync_epoch, is_write));
857 return res;
858#else
859 return ContainsSameAccessSlow(s, a, sync_epoch, is_write);
860#endif
861}
862
863ALWAYS_INLINE USED
864void MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
865 int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic) {
866 u64 *shadow_mem = (u64*)MemToShadow(addr);
867 DPrintf2("#%d: MemoryAccess: @%p %p size=%d"
868 " is_write=%d shadow_mem=%p {%zx, %zx, %zx, %zx}\n",
869 (int)thr->fast_state.tid(), (void*)pc, (void*)addr,
870 (int)(1 << kAccessSizeLog), kAccessIsWrite, shadow_mem,
871 (uptr)shadow_mem[0], (uptr)shadow_mem[1],
872 (uptr)shadow_mem[2], (uptr)shadow_mem[3]);
873#if SANITIZER_DEBUG
874 if (!IsAppMem(addr)) {
875 Printf("Access to non app mem %zx\n", addr);
876 DCHECK(IsAppMem(addr));
877 }
878 if (!IsShadowMem((uptr)shadow_mem)) {
879 Printf("Bad shadow addr %p (%zx)\n", shadow_mem, addr);
880 DCHECK(IsShadowMem((uptr)shadow_mem));
881 }
882#endif
883
884 if (!SANITIZER_GO && !kAccessIsWrite && *shadow_mem == kShadowRodata) {
885 // Access to .rodata section, no races here.
886 // Measurements show that it can be 10-20% of all memory accesses.
887 return;
888 }
889
890 FastState fast_state = thr->fast_state;
891 if (UNLIKELY(fast_state.GetIgnoreBit())) {
892 return;
893 }
894
895 Shadow cur(fast_state);
896 cur.SetAddr0AndSizeLog(addr & 7, kAccessSizeLog);
897 cur.SetWrite(kAccessIsWrite);
898 cur.SetAtomic(kIsAtomic);
899
900 if (LIKELY(ContainsSameAccess(shadow_mem, cur.raw(),
901 thr->fast_synch_epoch, kAccessIsWrite))) {
902 return;
903 }
904
905 if (kCollectHistory) {
906 fast_state.IncrementEpoch();
907 thr->fast_state = fast_state;
908 TraceAddEvent(thr, fast_state, EventTypeMop, pc);
909 cur.IncrementEpoch();
910 }
911
912 MemoryAccessImpl1(thr, addr, kAccessSizeLog, kAccessIsWrite, kIsAtomic,
913 shadow_mem, cur);
914}
915
916// Called by MemoryAccessRange in tsan_rtl_thread.cpp
917ALWAYS_INLINE USED
918void MemoryAccessImpl(ThreadState *thr, uptr addr,
919 int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic,
920 u64 *shadow_mem, Shadow cur) {
921 if (LIKELY(ContainsSameAccess(shadow_mem, cur.raw(),
922 thr->fast_synch_epoch, kAccessIsWrite))) {
923 return;
924 }
925
926 MemoryAccessImpl1(thr, addr, kAccessSizeLog, kAccessIsWrite, kIsAtomic,
927 shadow_mem, cur);
928}
929
930static void MemoryRangeSet(ThreadState *thr, uptr pc, uptr addr, uptr size,
931 u64 val) {
932 (void)thr;
933 (void)pc;
934 if (size == 0)
939NOINLINE
940void TraceSwitchPart(ThreadState* thr) {
941 if (TraceSkipGap(thr))
935942 return;
936 // FIXME: fix me.
937 uptr offset = addr % kShadowCell;
938 if (offset) {
939 offset = kShadowCell - offset;
940 if (size <= offset)
943#if !SANITIZER_GO
944 if (ctx->after_multithreaded_fork) {
945 // We just need to survive till exec.
946 TracePart* part = thr->tctx->trace.parts.Back();
947 if (part) {
948 atomic_store_relaxed(&thr->trace_pos,
949 reinterpret_cast<uptr>(&part->events[0]));
941950 return;
942 addr += offset;
943 size -= offset;
944 }
945 DCHECK_EQ(addr % 8, 0);
946 // If a user passes some insane arguments (memset(0)),
947 // let it just crash as usual.
948 if (!IsAppMem(addr) || !IsAppMem(addr + size - 1))
949 return;
950 // Don't want to touch lots of shadow memory.
951 // If a program maps 10MB stack, there is no need reset the whole range.
952 size = (size + (kShadowCell - 1)) & ~(kShadowCell - 1);
953 // UnmapOrDie/MmapFixedNoReserve does not work on Windows.
954 if (SANITIZER_WINDOWS || size < common_flags()->clear_shadow_mmap_threshold) {
955 u64 *p = (u64*)MemToShadow(addr);
956 CHECK(IsShadowMem((uptr)p));
957 CHECK(IsShadowMem((uptr)(p + size * kShadowCnt / kShadowCell - 1)));
958 // FIXME: may overwrite a part outside the region
959 for (uptr i = 0; i < size / kShadowCell * kShadowCnt;) {
960 p[i++] = val;
961 for (uptr j = 1; j < kShadowCnt; j++)
962 p[i++] = 0;
963 }
964 } else {
965 // The region is big, reset only beginning and end.
966 const uptr kPageSize = GetPageSizeCached();
967 u64 *begin = (u64*)MemToShadow(addr);
968 u64 *end = begin + size / kShadowCell * kShadowCnt;
969 u64 *p = begin;
970 // Set at least first kPageSize/2 to page boundary.
971 while ((p < begin + kPageSize / kShadowSize / 2) || ((uptr)p % kPageSize)) {
972 *p++ = val;
973 for (uptr j = 1; j < kShadowCnt; j++)
974 *p++ = 0;
975 }
976 // Reset middle part.
977 u64 *p1 = p;
978 p = RoundDown(end, kPageSize);
979 if (!MmapFixedSuperNoReserve((uptr)p1, (uptr)p - (uptr)p1))
980 Die();
981 // Set the ending.
982 while (p < end) {
983 *p++ = val;
984 for (uptr j = 1; j < kShadowCnt; j++)
985 *p++ = 0;
986951 }
987952 }
953#endif
954 TraceSwitchPartImpl(thr);
988955}
989956
990void MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size) {
991 MemoryRangeSet(thr, pc, addr, size, 0);
992}
993
994void MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size) {
995 // Processing more than 1k (4k of shadow) is expensive,
996 // can cause excessive memory consumption (user does not necessary touch
997 // the whole range) and most likely unnecessary.
998 if (size > 1024)
999 size = 1024;
1000 CHECK_EQ(thr->is_freeing, false);
1001 thr->is_freeing = true;
1002 MemoryAccessRange(thr, pc, addr, size, true);
1003 thr->is_freeing = false;
1004 if (kCollectHistory) {
1005 thr->fast_state.IncrementEpoch();
1006 TraceAddEvent(thr, thr->fast_state, EventTypeMop, pc);
957void TraceSwitchPartImpl(ThreadState* thr) {
958 SlotLocker locker(thr, true);
959 Trace* trace = &thr->tctx->trace;
960 TracePart* part = TracePartAlloc(thr);
961 part->trace = trace;
962 thr->trace_prev_pc = 0;
963 TracePart* recycle = nullptr;
964 // Keep roughly half of parts local to the thread
965 // (not queued into the recycle queue).
966 uptr local_parts = (Trace::kMinParts + flags()->history_size + 1) / 2;
967 {
968 Lock lock(&trace->mtx);
969 if (trace->parts.Empty())
970 trace->local_head = part;
971 if (trace->parts.Size() >= local_parts) {
972 recycle = trace->local_head;
973 trace->local_head = trace->parts.Next(recycle);
974 }
975 trace->parts.PushBack(part);
976 atomic_store_relaxed(&thr->trace_pos,
977 reinterpret_cast<uptr>(&part->events[0]));
1007978 }
1008 Shadow s(thr->fast_state);
1009 s.ClearIgnoreBit();
1010 s.MarkAsFreed();
1011 s.SetWrite(true);
1012 s.SetAddr0AndSizeLog(0, 3);
1013 MemoryRangeSet(thr, pc, addr, size, s.raw());
1014}
1015
1016void MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size) {
1017 if (kCollectHistory) {
1018 thr->fast_state.IncrementEpoch();
1019 TraceAddEvent(thr, thr->fast_state, EventTypeMop, pc);
979 // Make this part self-sufficient by restoring the current stack
980 // and mutex set in the beginning of the trace.
981 TraceTime(thr);
982 {
983 // Pathologically large stacks may not fit into the part.
984 // In these cases we log only fixed number of top frames.
985 const uptr kMaxFrames = 1000;
986 // Check that kMaxFrames won't consume the whole part.
987 static_assert(kMaxFrames < TracePart::kSize / 2, "kMaxFrames is too big");
988 uptr* pos = Max(&thr->shadow_stack[0], thr->shadow_stack_pos - kMaxFrames);
989 for (; pos < thr->shadow_stack_pos; pos++) {
990 if (TryTraceFunc(thr, *pos))
991 continue;
992 CHECK(TraceSkipGap(thr));
993 CHECK(TryTraceFunc(thr, *pos));
994 }
1020995 }
1021 Shadow s(thr->fast_state);
1022 s.ClearIgnoreBit();
1023 s.SetWrite(true);
1024 s.SetAddr0AndSizeLog(0, 3);
1025 MemoryRangeSet(thr, pc, addr, size, s.raw());
1026}
1027
1028void MemoryRangeImitateWriteOrResetRange(ThreadState *thr, uptr pc, uptr addr,
1029 uptr size) {
1030 if (thr->ignore_reads_and_writes == 0)
1031 MemoryRangeImitateWrite(thr, pc, addr, size);
1032 else
1033 MemoryResetRange(thr, pc, addr, size);
1034}
1035
1036ALWAYS_INLINE USED
1037void FuncEntry(ThreadState *thr, uptr pc) {
1038 DPrintf2("#%d: FuncEntry %p\n", (int)thr->fast_state.tid(), (void*)pc);
1039 if (kCollectHistory) {
1040 thr->fast_state.IncrementEpoch();
1041 TraceAddEvent(thr, thr->fast_state, EventTypeFuncEnter, pc);
996 for (uptr i = 0; i < thr->mset.Size(); i++) {
997 MutexSet::Desc d = thr->mset.Get(i);
998 for (uptr i = 0; i < d.count; i++)
999 TraceMutexLock(thr, d.write ? EventType::kLock : EventType::kRLock, 0,
1000 d.addr, d.stack_id);
10421001 }
1043
1044 // Shadow stack maintenance can be replaced with
1045 // stack unwinding during trace switch (which presumably must be faster).
1046 DCHECK_GE(thr->shadow_stack_pos, thr->shadow_stack);
1047#if !SANITIZER_GO
1048 DCHECK_LT(thr->shadow_stack_pos, thr->shadow_stack_end);
1049#else
1050 if (thr->shadow_stack_pos == thr->shadow_stack_end)
1051 GrowShadowStack(thr);
1052#endif
1053 thr->shadow_stack_pos[0] = pc;
1054 thr->shadow_stack_pos++;
1055}
1056
1057ALWAYS_INLINE USED
1058void FuncExit(ThreadState *thr) {
1059 DPrintf2("#%d: FuncExit\n", (int)thr->fast_state.tid());
1060 if (kCollectHistory) {
1061 thr->fast_state.IncrementEpoch();
1062 TraceAddEvent(thr, thr->fast_state, EventTypeFuncExit, 0);
1002 // Callers of TraceSwitchPart expect that TraceAcquire will always succeed
1003 // after the call. It's possible that TryTraceFunc/TraceMutexLock above
1004 // filled the trace part exactly up to the TracePart::kAlignment gap
1005 // and the next TraceAcquire won't succeed. Skip the gap to avoid that.
1006 EventFunc *ev;
1007 if (!TraceAcquire(thr, &ev)) {
1008 CHECK(TraceSkipGap(thr));
1009 CHECK(TraceAcquire(thr, &ev));
10631010 }
1064
1065 DCHECK_GT(thr->shadow_stack_pos, thr->shadow_stack);
1066#if !SANITIZER_GO
1067 DCHECK_LT(thr->shadow_stack_pos, thr->shadow_stack_end);
1068#endif
1069 thr->shadow_stack_pos--;
1011 {
1012 Lock lock(&ctx->slot_mtx);
1013 // There is a small chance that the slot may be not queued at this point.
1014 // This can happen if the slot has kEpochLast epoch and another thread
1015 // in FindSlotAndLock discovered that it's exhausted and removed it from
1016 // the slot queue. kEpochLast can happen in 2 cases: (1) if TraceSwitchPart
1017 // was called with the slot locked and epoch already at kEpochLast,
1018 // or (2) if we've acquired a new slot in SlotLock in the beginning
1019 // of the function and the slot was at kEpochLast - 1, so after increment
1020 // in SlotAttachAndLock it become kEpochLast.
1021 if (ctx->slot_queue.Queued(thr->slot)) {
1022 ctx->slot_queue.Remove(thr->slot);
1023 ctx->slot_queue.PushBack(thr->slot);
1024 }
1025 if (recycle)
1026 ctx->trace_part_recycle.PushBack(recycle);
1027 }
1028 DPrintf("#%d: TraceSwitchPart exit parts=%p-%p pos=0x%zx\n", thr->tid,
1029 trace->parts.Front(), trace->parts.Back(),
1030 atomic_load_relaxed(&thr->trace_pos));
10701031}
10711032
1072void ThreadIgnoreBegin(ThreadState *thr, uptr pc, bool save_stack) {
1033void ThreadIgnoreBegin(ThreadState* thr, uptr pc) {
10731034 DPrintf("#%d: ThreadIgnoreBegin\n", thr->tid);
10741035 thr->ignore_reads_and_writes++;
10751036 CHECK_GT(thr->ignore_reads_and_writes, 0);
10761037 thr->fast_state.SetIgnoreBit();
10771038#if !SANITIZER_GO
1078 if (save_stack && !ctx->after_multithreaded_fork)
1039 if (pc && !ctx->after_multithreaded_fork)
10791040 thr->mop_ignore_set.Add(CurrentStackId(thr, pc));
10801041#endif
10811042}
10821043
1083void ThreadIgnoreEnd(ThreadState *thr, uptr pc) {
1044void ThreadIgnoreEnd(ThreadState *thr) {
10841045 DPrintf("#%d: ThreadIgnoreEnd\n", thr->tid);
10851046 CHECK_GT(thr->ignore_reads_and_writes, 0);
10861047 thr->ignore_reads_and_writes--;
......@@ -1100,17 +1061,17 @@ uptr __tsan_testonly_shadow_stack_current_size() {
11001061}
11011062#endif
11021063
1103void ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc, bool save_stack) {
1064void ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc) {
11041065 DPrintf("#%d: ThreadIgnoreSyncBegin\n", thr->tid);
11051066 thr->ignore_sync++;
11061067 CHECK_GT(thr->ignore_sync, 0);
11071068#if !SANITIZER_GO
1108 if (save_stack && !ctx->after_multithreaded_fork)
1069 if (pc && !ctx->after_multithreaded_fork)
11091070 thr->sync_ignore_set.Add(CurrentStackId(thr, pc));
11101071#endif
11111072}
11121073
1113void ThreadIgnoreSyncEnd(ThreadState *thr, uptr pc) {
1074void ThreadIgnoreSyncEnd(ThreadState *thr) {
11141075 DPrintf("#%d: ThreadIgnoreSyncEnd\n", thr->tid);
11151076 CHECK_GT(thr->ignore_sync, 0);
11161077 thr->ignore_sync--;
......@@ -1129,7 +1090,6 @@ void build_consistency_debug() {}
11291090#else
11301091void build_consistency_release() {}
11311092#endif
1132
11331093} // namespace __tsan
11341094
11351095#if SANITIZER_CHECK_DEADLOCKS
......@@ -1137,23 +1097,27 @@ namespace __sanitizer {
11371097using namespace __tsan;
11381098MutexMeta mutex_meta[] = {
11391099 {MutexInvalid, "Invalid", {}},
1140 {MutexThreadRegistry, "ThreadRegistry", {}},
1141 {MutexTypeTrace, "Trace", {MutexLeaf}},
1142 {MutexTypeReport, "Report", {MutexTypeSyncVar}},
1143 {MutexTypeSyncVar, "SyncVar", {}},
1100 {MutexThreadRegistry,
1101 "ThreadRegistry",
1102 {MutexTypeSlots, MutexTypeTrace, MutexTypeReport}},
1103 {MutexTypeReport, "Report", {MutexTypeTrace}},
1104 {MutexTypeSyncVar, "SyncVar", {MutexTypeReport, MutexTypeTrace}},
11441105 {MutexTypeAnnotations, "Annotations", {}},
1145 {MutexTypeAtExit, "AtExit", {MutexTypeSyncVar}},
1106 {MutexTypeAtExit, "AtExit", {}},
11461107 {MutexTypeFired, "Fired", {MutexLeaf}},
11471108 {MutexTypeRacy, "Racy", {MutexLeaf}},
1148 {MutexTypeGlobalProc, "GlobalProc", {}},
1109 {MutexTypeGlobalProc, "GlobalProc", {MutexTypeSlot, MutexTypeSlots}},
1110 {MutexTypeInternalAlloc, "InternalAlloc", {MutexLeaf}},
1111 {MutexTypeTrace, "Trace", {}},
1112 {MutexTypeSlot,
1113 "Slot",
1114 {MutexMulti, MutexTypeTrace, MutexTypeSyncVar, MutexThreadRegistry,
1115 MutexTypeSlots}},
1116 {MutexTypeSlots, "Slots", {MutexTypeTrace, MutexTypeReport}},
11491117 {},
11501118};
11511119
11521120void PrintMutexPC(uptr pc) { StackTrace(&pc, 1).Print(); }
1153} // namespace __sanitizer
1154#endif
11551121
1156#if !SANITIZER_GO
1157// Must be included in this file to make sure everything is inlined.
1158# include "tsan_interface_inl.h"
1122} // namespace __sanitizer
11591123#endif
lib/tsan/tsan_rtl.h+376-429
......@@ -34,17 +34,19 @@
3434#include "sanitizer_common/sanitizer_suppressions.h"
3535#include "sanitizer_common/sanitizer_thread_registry.h"
3636#include "sanitizer_common/sanitizer_vector.h"
37#include "tsan_clock.h"
3837#include "tsan_defs.h"
3938#include "tsan_flags.h"
39#include "tsan_ignoreset.h"
40#include "tsan_ilist.h"
4041#include "tsan_mman.h"
41#include "tsan_sync.h"
42#include "tsan_trace.h"
43#include "tsan_report.h"
44#include "tsan_platform.h"
4542#include "tsan_mutexset.h"
46#include "tsan_ignoreset.h"
43#include "tsan_platform.h"
44#include "tsan_report.h"
45#include "tsan_shadow.h"
4746#include "tsan_stack_trace.h"
47#include "tsan_sync.h"
48#include "tsan_trace.h"
49#include "tsan_vector_clock.h"
4850
4951#if SANITIZER_WORDSIZE != 64
5052# error "ThreadSanitizer is supported only on 64-bit platforms"
......@@ -54,7 +56,8 @@ namespace __tsan {
5456
5557#if !SANITIZER_GO
5658struct MapUnmapCallback;
57#if defined(__mips64) || defined(__aarch64__) || defined(__powerpc__)
59#if defined(__mips64) || defined(__aarch64__) || defined(__loongarch__) || \
60 defined(__powerpc__)
5861
5962struct AP32 {
6063 static const uptr kSpaceBeg = 0;
......@@ -69,6 +72,11 @@ struct AP32 {
6972typedef SizeClassAllocator32<AP32> PrimaryAllocator;
7073#else
7174struct AP64 { // Allocator64 parameters. Deliberately using a short name.
75# if defined(__s390x__)
76 typedef MappingS390x Mapping;
77# else
78 typedef Mapping48AddressSpace Mapping;
79# endif
7280 static const uptr kSpaceBeg = Mapping::kHeapMemBeg;
7381 static const uptr kSpaceSize = Mapping::kHeapMemEnd - Mapping::kHeapMemBeg;
7482 static const uptr kMetadataSize = 0;
......@@ -84,240 +92,6 @@ typedef Allocator::AllocatorCache AllocatorCache;
8492Allocator *allocator();
8593#endif
8694
87const u64 kShadowRodata = (u64)-1; // .rodata shadow marker
88
89// FastState (from most significant bit):
90// ignore : 1
91// tid : kTidBits
92// unused : -
93// history_size : 3
94// epoch : kClkBits
95class FastState {
96 public:
97 FastState(u64 tid, u64 epoch) {
98 x_ = tid << kTidShift;
99 x_ |= epoch;
100 DCHECK_EQ(tid, this->tid());
101 DCHECK_EQ(epoch, this->epoch());
102 DCHECK_EQ(GetIgnoreBit(), false);
103 }
104
105 explicit FastState(u64 x)
106 : x_(x) {
107 }
108
109 u64 raw() const {
110 return x_;
111 }
112
113 u64 tid() const {
114 u64 res = (x_ & ~kIgnoreBit) >> kTidShift;
115 return res;
116 }
117
118 u64 TidWithIgnore() const {
119 u64 res = x_ >> kTidShift;
120 return res;
121 }
122
123 u64 epoch() const {
124 u64 res = x_ & ((1ull << kClkBits) - 1);
125 return res;
126 }
127
128 void IncrementEpoch() {
129 u64 old_epoch = epoch();
130 x_ += 1;
131 DCHECK_EQ(old_epoch + 1, epoch());
132 (void)old_epoch;
133 }
134
135 void SetIgnoreBit() { x_ |= kIgnoreBit; }
136 void ClearIgnoreBit() { x_ &= ~kIgnoreBit; }
137 bool GetIgnoreBit() const { return (s64)x_ < 0; }
138
139 void SetHistorySize(int hs) {
140 CHECK_GE(hs, 0);
141 CHECK_LE(hs, 7);
142 x_ = (x_ & ~(kHistoryMask << kHistoryShift)) | (u64(hs) << kHistoryShift);
143 }
144
145 ALWAYS_INLINE
146 int GetHistorySize() const {
147 return (int)((x_ >> kHistoryShift) & kHistoryMask);
148 }
149
150 void ClearHistorySize() {
151 SetHistorySize(0);
152 }
153
154 ALWAYS_INLINE
155 u64 GetTracePos() const {
156 const int hs = GetHistorySize();
157 // When hs == 0, the trace consists of 2 parts.
158 const u64 mask = (1ull << (kTracePartSizeBits + hs + 1)) - 1;
159 return epoch() & mask;
160 }
161
162 private:
163 friend class Shadow;
164 static const int kTidShift = 64 - kTidBits - 1;
165 static const u64 kIgnoreBit = 1ull << 63;
166 static const u64 kFreedBit = 1ull << 63;
167 static const u64 kHistoryShift = kClkBits;
168 static const u64 kHistoryMask = 7;
169 u64 x_;
170};
171
172// Shadow (from most significant bit):
173// freed : 1
174// tid : kTidBits
175// is_atomic : 1
176// is_read : 1
177// size_log : 2
178// addr0 : 3
179// epoch : kClkBits
180class Shadow : public FastState {
181 public:
182 explicit Shadow(u64 x)
183 : FastState(x) {
184 }
185
186 explicit Shadow(const FastState &s)
187 : FastState(s.x_) {
188 ClearHistorySize();
189 }
190
191 void SetAddr0AndSizeLog(u64 addr0, unsigned kAccessSizeLog) {
192 DCHECK_EQ((x_ >> kClkBits) & 31, 0);
193 DCHECK_LE(addr0, 7);
194 DCHECK_LE(kAccessSizeLog, 3);
195 x_ |= ((kAccessSizeLog << 3) | addr0) << kClkBits;
196 DCHECK_EQ(kAccessSizeLog, size_log());
197 DCHECK_EQ(addr0, this->addr0());
198 }
199
200 void SetWrite(unsigned kAccessIsWrite) {
201 DCHECK_EQ(x_ & kReadBit, 0);
202 if (!kAccessIsWrite)
203 x_ |= kReadBit;
204 DCHECK_EQ(kAccessIsWrite, IsWrite());
205 }
206
207 void SetAtomic(bool kIsAtomic) {
208 DCHECK(!IsAtomic());
209 if (kIsAtomic)
210 x_ |= kAtomicBit;
211 DCHECK_EQ(IsAtomic(), kIsAtomic);
212 }
213
214 bool IsAtomic() const {
215 return x_ & kAtomicBit;
216 }
217
218 bool IsZero() const {
219 return x_ == 0;
220 }
221
222 static inline bool TidsAreEqual(const Shadow s1, const Shadow s2) {
223 u64 shifted_xor = (s1.x_ ^ s2.x_) >> kTidShift;
224 DCHECK_EQ(shifted_xor == 0, s1.TidWithIgnore() == s2.TidWithIgnore());
225 return shifted_xor == 0;
226 }
227
228 static ALWAYS_INLINE
229 bool Addr0AndSizeAreEqual(const Shadow s1, const Shadow s2) {
230 u64 masked_xor = ((s1.x_ ^ s2.x_) >> kClkBits) & 31;
231 return masked_xor == 0;
232 }
233
234 static ALWAYS_INLINE bool TwoRangesIntersect(Shadow s1, Shadow s2,
235 unsigned kS2AccessSize) {
236 bool res = false;
237 u64 diff = s1.addr0() - s2.addr0();
238 if ((s64)diff < 0) { // s1.addr0 < s2.addr0
239 // if (s1.addr0() + size1) > s2.addr0()) return true;
240 if (s1.size() > -diff)
241 res = true;
242 } else {
243 // if (s2.addr0() + kS2AccessSize > s1.addr0()) return true;
244 if (kS2AccessSize > diff)
245 res = true;
246 }
247 DCHECK_EQ(res, TwoRangesIntersectSlow(s1, s2));
248 DCHECK_EQ(res, TwoRangesIntersectSlow(s2, s1));
249 return res;
250 }
251
252 u64 ALWAYS_INLINE addr0() const { return (x_ >> kClkBits) & 7; }
253 u64 ALWAYS_INLINE size() const { return 1ull << size_log(); }
254 bool ALWAYS_INLINE IsWrite() const { return !IsRead(); }
255 bool ALWAYS_INLINE IsRead() const { return x_ & kReadBit; }
256
257 // The idea behind the freed bit is as follows.
258 // When the memory is freed (or otherwise unaccessible) we write to the shadow
259 // values with tid/epoch related to the free and the freed bit set.
260 // During memory accesses processing the freed bit is considered
261 // as msb of tid. So any access races with shadow with freed bit set
262 // (it is as if write from a thread with which we never synchronized before).
263 // This allows us to detect accesses to freed memory w/o additional
264 // overheads in memory access processing and at the same time restore
265 // tid/epoch of free.
266 void MarkAsFreed() {
267 x_ |= kFreedBit;
268 }
269
270 bool IsFreed() const {
271 return x_ & kFreedBit;
272 }
273
274 bool GetFreedAndReset() {
275 bool res = x_ & kFreedBit;
276 x_ &= ~kFreedBit;
277 return res;
278 }
279
280 bool ALWAYS_INLINE IsBothReadsOrAtomic(bool kIsWrite, bool kIsAtomic) const {
281 bool v = x_ & ((u64(kIsWrite ^ 1) << kReadShift)
282 | (u64(kIsAtomic) << kAtomicShift));
283 DCHECK_EQ(v, (!IsWrite() && !kIsWrite) || (IsAtomic() && kIsAtomic));
284 return v;
285 }
286
287 bool ALWAYS_INLINE IsRWNotWeaker(bool kIsWrite, bool kIsAtomic) const {
288 bool v = ((x_ >> kReadShift) & 3)
289 <= u64((kIsWrite ^ 1) | (kIsAtomic << 1));
290 DCHECK_EQ(v, (IsAtomic() < kIsAtomic) ||
291 (IsAtomic() == kIsAtomic && !IsWrite() <= !kIsWrite));
292 return v;
293 }
294
295 bool ALWAYS_INLINE IsRWWeakerOrEqual(bool kIsWrite, bool kIsAtomic) const {
296 bool v = ((x_ >> kReadShift) & 3)
297 >= u64((kIsWrite ^ 1) | (kIsAtomic << 1));
298 DCHECK_EQ(v, (IsAtomic() > kIsAtomic) ||
299 (IsAtomic() == kIsAtomic && !IsWrite() >= !kIsWrite));
300 return v;
301 }
302
303 private:
304 static const u64 kReadShift = 5 + kClkBits;
305 static const u64 kReadBit = 1ull << kReadShift;
306 static const u64 kAtomicShift = 6 + kClkBits;
307 static const u64 kAtomicBit = 1ull << kAtomicShift;
308
309 u64 size_log() const { return (x_ >> (3 + kClkBits)) & 3; }
310
311 static bool TwoRangesIntersectSlow(const Shadow s1, const Shadow s2) {
312 if (s1.addr0() == s2.addr0()) return true;
313 if (s1.addr0() < s2.addr0() && s1.addr0() + s1.size() > s2.addr0())
314 return true;
315 if (s2.addr0() < s1.addr0() && s2.addr0() + s2.size() > s1.addr0())
316 return true;
317 return false;
318 }
319};
320
32195struct ThreadSignalContext;
32296
32397struct JmpBuf {
......@@ -344,7 +118,6 @@ struct Processor {
344118#endif
345119 DenseSlabAllocCache block_cache;
346120 DenseSlabAllocCache sync_cache;
347 DenseSlabAllocCache clock_cache;
348121 DDPhysicalThread *dd_pt;
349122};
350123
......@@ -358,64 +131,86 @@ struct ScopedGlobalProcessor {
358131};
359132#endif
360133
134struct TidEpoch {
135 Tid tid;
136 Epoch epoch;
137};
138
139struct TidSlot {
140 Mutex mtx;
141 Sid sid;
142 atomic_uint32_t raw_epoch;
143 ThreadState *thr;
144 Vector<TidEpoch> journal;
145 INode node;
146
147 Epoch epoch() const {
148 return static_cast<Epoch>(atomic_load(&raw_epoch, memory_order_relaxed));
149 }
150
151 void SetEpoch(Epoch v) {
152 atomic_store(&raw_epoch, static_cast<u32>(v), memory_order_relaxed);
153 }
154
155 TidSlot();
156} ALIGNED(SANITIZER_CACHE_LINE_SIZE);
157
361158// This struct is stored in TLS.
362159struct ThreadState {
363160 FastState fast_state;
364 // Synch epoch represents the threads's epoch before the last synchronization
365 // action. It allows to reduce number of shadow state updates.
366 // For example, fast_synch_epoch=100, last write to addr X was at epoch=150,
367 // if we are processing write to X from the same thread at epoch=200,
368 // we do nothing, because both writes happen in the same 'synch epoch'.
369 // That is, if another memory access does not race with the former write,
370 // it does not race with the latter as well.
371 // QUESTION: can we can squeeze this into ThreadState::Fast?
372 // E.g. ThreadState::Fast is a 44-bit, 32 are taken by synch_epoch and 12 are
373 // taken by epoch between synchs.
374 // This way we can save one load from tls.
375 u64 fast_synch_epoch;
161 int ignore_sync;
162#if !SANITIZER_GO
163 int ignore_interceptors;
164#endif
165 uptr *shadow_stack_pos;
166
167 // Current position in tctx->trace.Back()->events (Event*).
168 atomic_uintptr_t trace_pos;
169 // PC of the last memory access, used to compute PC deltas in the trace.
170 uptr trace_prev_pc;
171
376172 // Technically `current` should be a separate THREADLOCAL variable;
377173 // but it is placed here in order to share cache line with previous fields.
378174 ThreadState* current;
175
176 atomic_sint32_t pending_signals;
177
178 VectorClock clock;
179
379180 // This is a slow path flag. On fast path, fast_state.GetIgnoreBit() is read.
380181 // We do not distinguish beteween ignoring reads and writes
381182 // for better performance.
382183 int ignore_reads_and_writes;
383 int ignore_sync;
384184 int suppress_reports;
385185 // Go does not support ignores.
386186#if !SANITIZER_GO
387187 IgnoreSet mop_ignore_set;
388188 IgnoreSet sync_ignore_set;
389189#endif
390 // C/C++ uses fixed size shadow stack embed into Trace.
391 // Go uses malloc-allocated shadow stack with dynamic size.
392190 uptr *shadow_stack;
393191 uptr *shadow_stack_end;
394 uptr *shadow_stack_pos;
395 u64 *racy_shadow_addr;
396 u64 racy_state[2];
397 MutexSet mset;
398 ThreadClock clock;
399192#if !SANITIZER_GO
400193 Vector<JmpBuf> jmp_bufs;
401 int ignore_interceptors;
402#endif
403 const u32 tid;
404 const int unique_id;
405 bool in_symbolizer;
194 int in_symbolizer;
195 atomic_uintptr_t in_blocking_func;
406196 bool in_ignored_lib;
407197 bool is_inited;
198#endif
199 MutexSet mset;
408200 bool is_dead;
409 bool is_freeing;
410 bool is_vptr_access;
411 const uptr stk_addr;
412 const uptr stk_size;
413 const uptr tls_addr;
414 const uptr tls_size;
201 const Tid tid;
202 uptr stk_addr;
203 uptr stk_size;
204 uptr tls_addr;
205 uptr tls_size;
415206 ThreadContext *tctx;
416207
417208 DDLogicalThread *dd_lt;
418209
210 TidSlot *slot;
211 uptr slot_epoch;
212 bool slot_locked;
213
419214 // Current wired Processor, or nullptr. Required to handle any events.
420215 Processor *proc1;
421216#if !SANITIZER_GO
......@@ -425,11 +220,11 @@ struct ThreadState {
425220#endif
426221
427222 atomic_uintptr_t in_signal_handler;
428 ThreadSignalContext *signal_ctx;
223 atomic_uintptr_t signal_ctx;
429224
430225#if !SANITIZER_GO
431 u32 last_sleep_stack_id;
432 ThreadClock last_sleep_clock;
226 StackID last_sleep_stack_id;
227 VectorClock last_sleep_clock;
433228#endif
434229
435230 // Set in regions of runtime that must be signal-safe and fork-safe.
......@@ -438,47 +233,43 @@ struct ThreadState {
438233
439234 const ReportDesc *current_report;
440235
441 explicit ThreadState(Context *ctx, u32 tid, int unique_id, u64 epoch,
442 unsigned reuse_count, uptr stk_addr, uptr stk_size,
443 uptr tls_addr, uptr tls_size);
444};
236 explicit ThreadState(Tid tid);
237} ALIGNED(SANITIZER_CACHE_LINE_SIZE);
445238
446239#if !SANITIZER_GO
447#if SANITIZER_MAC || SANITIZER_ANDROID
240#if SANITIZER_APPLE || SANITIZER_ANDROID
448241ThreadState *cur_thread();
449242void set_cur_thread(ThreadState *thr);
450243void cur_thread_finalize();
451inline void cur_thread_init() { }
452#else
244inline ThreadState *cur_thread_init() { return cur_thread(); }
245# else
453246__attribute__((tls_model("initial-exec")))
454247extern THREADLOCAL char cur_thread_placeholder[];
455248inline ThreadState *cur_thread() {
456249 return reinterpret_cast<ThreadState *>(cur_thread_placeholder)->current;
457250}
458inline void cur_thread_init() {
251inline ThreadState *cur_thread_init() {
459252 ThreadState *thr = reinterpret_cast<ThreadState *>(cur_thread_placeholder);
460253 if (UNLIKELY(!thr->current))
461254 thr->current = thr;
255 return thr->current;
462256}
463257inline void set_cur_thread(ThreadState *thr) {
464258 reinterpret_cast<ThreadState *>(cur_thread_placeholder)->current = thr;
465259}
466260inline void cur_thread_finalize() { }
467#endif // SANITIZER_MAC || SANITIZER_ANDROID
261# endif // SANITIZER_APPLE || SANITIZER_ANDROID
468262#endif // SANITIZER_GO
469263
470264class ThreadContext final : public ThreadContextBase {
471265 public:
472 explicit ThreadContext(int tid);
266 explicit ThreadContext(Tid tid);
473267 ~ThreadContext();
474268 ThreadState *thr;
475 u32 creation_stack_id;
476 SyncClock sync;
477 // Epoch at which the thread had started.
478 // If we see an event from the thread stamped by an older epoch,
479 // the event is from a dead thread that shared tid with this thread.
480 u64 epoch0;
481 u64 epoch1;
269 StackID creation_stack_id;
270 VectorClock *sync;
271 uptr sync_epoch;
272 Trace trace;
482273
483274 // Override superclass callbacks.
484275 void OnDead() override;
......@@ -492,13 +283,7 @@ class ThreadContext final : public ThreadContextBase {
492283
493284struct RacyStacks {
494285 MD5Hash hash[2];
495 bool operator==(const RacyStacks &other) const {
496 if (hash[0] == other.hash[0] && hash[1] == other.hash[1])
497 return true;
498 if (hash[0] == other.hash[1] && hash[1] == other.hash[0])
499 return true;
500 return false;
501 }
286 bool operator==(const RacyStacks &other) const;
502287};
503288
504289struct RacyAddress {
......@@ -524,28 +309,75 @@ struct Context {
524309
525310 Mutex report_mtx;
526311 int nreported;
527 int nmissed_expected;
528312 atomic_uint64_t last_symbolize_time_ns;
529313
530314 void *background_thread;
531315 atomic_uint32_t stop_background_thread;
532316
533 ThreadRegistry *thread_registry;
317 ThreadRegistry thread_registry;
318
319 // This is used to prevent a very unlikely but very pathological behavior.
320 // Since memory access handling is not synchronized with DoReset,
321 // a thread running concurrently with DoReset can leave a bogus shadow value
322 // that will be later falsely detected as a race. For such false races
323 // RestoreStack will return false and we will not report it.
324 // However, consider that a thread leaves a whole lot of such bogus values
325 // and these values are later read by a whole lot of threads.
326 // This will cause massive amounts of ReportRace calls and lots of
327 // serialization. In very pathological cases the resulting slowdown
328 // can be >100x. This is very unlikely, but it was presumably observed
329 // in practice: https://github.com/google/sanitizers/issues/1552
330 // If this happens, previous access sid+epoch will be the same for all of
331 // these false races b/c if the thread will try to increment epoch, it will
332 // notice that DoReset has happened and will stop producing bogus shadow
333 // values. So, last_spurious_race is used to remember the last sid+epoch
334 // for which RestoreStack returned false. Then it is used to filter out
335 // races with the same sid+epoch very early and quickly.
336 // It is of course possible that multiple threads left multiple bogus shadow
337 // values and all of them are read by lots of threads at the same time.
338 // In such case last_spurious_race will only be able to deduplicate a few
339 // races from one thread, then few from another and so on. An alternative
340 // would be to hold an array of such sid+epoch, but we consider such scenario
341 // as even less likely.
342 // Note: this can lead to some rare false negatives as well:
343 // 1. When a legit access with the same sid+epoch participates in a race
344 // as the "previous" memory access, it will be wrongly filtered out.
345 // 2. When RestoreStack returns false for a legit memory access because it
346 // was already evicted from the thread trace, we will still remember it in
347 // last_spurious_race. Then if there is another racing memory access from
348 // the same thread that happened in the same epoch, but was stored in the
349 // next thread trace part (which is still preserved in the thread trace),
350 // we will also wrongly filter it out while RestoreStack would actually
351 // succeed for that second memory access.
352 RawShadow last_spurious_race;
534353
535354 Mutex racy_mtx;
536355 Vector<RacyStacks> racy_stacks;
537 Vector<RacyAddress> racy_addresses;
538356 // Number of fired suppressions may be large enough.
539357 Mutex fired_suppressions_mtx;
540358 InternalMmapVector<FiredSuppression> fired_suppressions;
541359 DDetector *dd;
542360
543 ClockAlloc clock_alloc;
544
545361 Flags flags;
546
547 u64 int_alloc_cnt[MBlockTypeCount];
548 u64 int_alloc_siz[MBlockTypeCount];
362 fd_t memprof_fd;
363
364 // The last slot index (kFreeSid) is used to denote freed memory.
365 TidSlot slots[kThreadSlotCount - 1];
366
367 // Protects global_epoch, slot_queue, trace_part_recycle.
368 Mutex slot_mtx;
369 uptr global_epoch; // guarded by slot_mtx and by all slot mutexes
370 bool resetting; // global reset is in progress
371 IList<TidSlot, &TidSlot::node> slot_queue SANITIZER_GUARDED_BY(slot_mtx);
372 IList<TraceHeader, &TraceHeader::global, TracePart> trace_part_recycle
373 SANITIZER_GUARDED_BY(slot_mtx);
374 uptr trace_part_total_allocated SANITIZER_GUARDED_BY(slot_mtx);
375 uptr trace_part_recycle_finished SANITIZER_GUARDED_BY(slot_mtx);
376 uptr trace_part_finished_excess SANITIZER_GUARDED_BY(slot_mtx);
377#if SANITIZER_GO
378 uptr mapped_shadow_begin;
379 uptr mapped_shadow_end;
380#endif
549381};
550382
551383extern Context *ctx; // The one and the only global runtime context.
......@@ -574,17 +406,17 @@ uptr TagFromShadowStackFrame(uptr pc);
574406
575407class ScopedReportBase {
576408 public:
577 void AddMemoryAccess(uptr addr, uptr external_tag, Shadow s, StackTrace stack,
578 const MutexSet *mset);
409 void AddMemoryAccess(uptr addr, uptr external_tag, Shadow s, Tid tid,
410 StackTrace stack, const MutexSet *mset);
579411 void AddStack(StackTrace stack, bool suppressable = false);
580412 void AddThread(const ThreadContext *tctx, bool suppressable = false);
581 void AddThread(int unique_tid, bool suppressable = false);
582 void AddUniqueTid(int unique_tid);
583 void AddMutex(const SyncVar *s);
584 u64 AddMutex(u64 id);
413 void AddThread(Tid tid, bool suppressable = false);
414 void AddUniqueTid(Tid unique_tid);
415 int AddMutex(uptr addr, StackID creation_stack_id);
585416 void AddLocation(uptr addr, uptr size);
586 void AddSleep(u32 stack_id);
417 void AddSleep(StackID stack_id);
587418 void SetCount(int count);
419 void SetSigNum(int sig);
588420
589421 const ReportDesc *GetReport() const;
590422
......@@ -598,8 +430,6 @@ class ScopedReportBase {
598430 // at best it will cause deadlocks on internal mutexes.
599431 ScopedIgnoreInterceptors ignore_interceptors_;
600432
601 void AddDeadMutex(u64 id);
602
603433 ScopedReportBase(const ScopedReportBase &) = delete;
604434 void operator=(const ScopedReportBase &) = delete;
605435};
......@@ -615,8 +445,6 @@ class ScopedReport : public ScopedReportBase {
615445
616446bool ShouldReport(ThreadState *thr, ReportType typ);
617447ThreadContext *IsThreadStackOrTls(uptr addr, bool *is_stack);
618void RestoreStack(int tid, const u64 epoch, VarSizeStackTrace *stk,
619 MutexSet *mset, uptr *tag = nullptr);
620448
621449// The stack could look like:
622450// <start> | <main> | <foo> | tag | <bar>
......@@ -656,19 +484,20 @@ void MapThreadTrace(uptr addr, uptr size, const char *name);
656484void DontNeedShadowFor(uptr addr, uptr size);
657485void UnmapShadow(ThreadState *thr, uptr addr, uptr size);
658486void InitializeShadowMemory();
487void DontDumpShadow(uptr addr, uptr size);
659488void InitializeInterceptors();
660489void InitializeLibIgnore();
661490void InitializeDynamicAnnotations();
662491
663492void ForkBefore(ThreadState *thr, uptr pc);
664493void ForkParentAfter(ThreadState *thr, uptr pc);
665void ForkChildAfter(ThreadState *thr, uptr pc);
494void ForkChildAfter(ThreadState *thr, uptr pc, bool start_thread);
666495
667void ReportRace(ThreadState *thr);
496void ReportRace(ThreadState *thr, RawShadow *shadow_mem, Shadow cur, Shadow old,
497 AccessType typ);
668498bool OutputReport(ThreadState *thr, const ScopedReport &srep);
669499bool IsFiredSuppression(Context *ctx, ReportType type, StackTrace trace);
670500bool IsExpectedReport(uptr addr, uptr size);
671void PrintMatchedBenignRaces();
672501
673502#if defined(TSAN_DEBUG_OUTPUT) && TSAN_DEBUG_OUTPUT >= 1
674503# define DPrintf Printf
......@@ -682,10 +511,11 @@ void PrintMatchedBenignRaces();
682511# define DPrintf2(...)
683512#endif
684513
685u32 CurrentStackId(ThreadState *thr, uptr pc);
686ReportStack *SymbolizeStackId(u32 stack_id);
514StackID CurrentStackId(ThreadState *thr, uptr pc);
515ReportStack *SymbolizeStackId(StackID stack_id);
687516void PrintCurrentStack(ThreadState *thr, uptr pc);
688517void PrintCurrentStackSlow(uptr pc); // uses libunwind
518MBlock *JavaHeapBlock(uptr addr, uptr *start);
689519
690520void Initialize(ThreadState *thr);
691521void MaybeSpawnBackgroundThread();
......@@ -694,69 +524,49 @@ int Finalize(ThreadState *thr);
694524void OnUserAlloc(ThreadState *thr, uptr pc, uptr p, uptr sz, bool write);
695525void OnUserFree(ThreadState *thr, uptr pc, uptr p, bool write);
696526
697void MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
698 int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic);
699void MemoryAccessImpl(ThreadState *thr, uptr addr,
700 int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic,
701 u64 *shadow_mem, Shadow cur);
702void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
703 uptr size, bool is_write);
704void MemoryAccessRangeStep(ThreadState *thr, uptr pc, uptr addr,
705 uptr size, uptr step, bool is_write);
706void UnalignedMemoryAccess(ThreadState *thr, uptr pc, uptr addr,
707 int size, bool kAccessIsWrite, bool kIsAtomic);
708
709const int kSizeLog1 = 0;
710const int kSizeLog2 = 1;
711const int kSizeLog4 = 2;
712const int kSizeLog8 = 3;
713
714void ALWAYS_INLINE MemoryRead(ThreadState *thr, uptr pc,
715 uptr addr, int kAccessSizeLog) {
716 MemoryAccess(thr, pc, addr, kAccessSizeLog, false, false);
717}
718
719void ALWAYS_INLINE MemoryWrite(ThreadState *thr, uptr pc,
720 uptr addr, int kAccessSizeLog) {
721 MemoryAccess(thr, pc, addr, kAccessSizeLog, true, false);
722}
723
724void ALWAYS_INLINE MemoryReadAtomic(ThreadState *thr, uptr pc,
725 uptr addr, int kAccessSizeLog) {
726 MemoryAccess(thr, pc, addr, kAccessSizeLog, false, true);
727}
728
729void ALWAYS_INLINE MemoryWriteAtomic(ThreadState *thr, uptr pc,
730 uptr addr, int kAccessSizeLog) {
731 MemoryAccess(thr, pc, addr, kAccessSizeLog, true, true);
527void MemoryAccess(ThreadState *thr, uptr pc, uptr addr, uptr size,
528 AccessType typ);
529void UnalignedMemoryAccess(ThreadState *thr, uptr pc, uptr addr, uptr size,
530 AccessType typ);
531// This creates 2 non-inlined specialized versions of MemoryAccessRange.
532template <bool is_read>
533void MemoryAccessRangeT(ThreadState *thr, uptr pc, uptr addr, uptr size);
534
535ALWAYS_INLINE
536void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr, uptr size,
537 bool is_write) {
538 if (size == 0)
539 return;
540 if (is_write)
541 MemoryAccessRangeT<false>(thr, pc, addr, size);
542 else
543 MemoryAccessRangeT<true>(thr, pc, addr, size);
732544}
733545
734void MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size);
546void ShadowSet(RawShadow *p, RawShadow *end, RawShadow v);
735547void MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size);
548void MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size);
736549void MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size);
737550void MemoryRangeImitateWriteOrResetRange(ThreadState *thr, uptr pc, uptr addr,
738551 uptr size);
739552
740void ThreadIgnoreBegin(ThreadState *thr, uptr pc, bool save_stack = true);
741void ThreadIgnoreEnd(ThreadState *thr, uptr pc);
742void ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc, bool save_stack = true);
743void ThreadIgnoreSyncEnd(ThreadState *thr, uptr pc);
744
745void FuncEntry(ThreadState *thr, uptr pc);
746void FuncExit(ThreadState *thr);
553void ThreadIgnoreBegin(ThreadState *thr, uptr pc);
554void ThreadIgnoreEnd(ThreadState *thr);
555void ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc);
556void ThreadIgnoreSyncEnd(ThreadState *thr);
747557
748int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached);
749void ThreadStart(ThreadState *thr, int tid, tid_t os_id,
558Tid ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached);
559void ThreadStart(ThreadState *thr, Tid tid, tid_t os_id,
750560 ThreadType thread_type);
751561void ThreadFinish(ThreadState *thr);
752int ThreadConsumeTid(ThreadState *thr, uptr pc, uptr uid);
753void ThreadJoin(ThreadState *thr, uptr pc, int tid);
754void ThreadDetach(ThreadState *thr, uptr pc, int tid);
562Tid ThreadConsumeTid(ThreadState *thr, uptr pc, uptr uid);
563void ThreadJoin(ThreadState *thr, uptr pc, Tid tid);
564void ThreadDetach(ThreadState *thr, uptr pc, Tid tid);
755565void ThreadFinalize(ThreadState *thr);
756566void ThreadSetName(ThreadState *thr, const char *name);
757567int ThreadCount(ThreadState *thr);
758void ProcessPendingSignals(ThreadState *thr);
759void ThreadNotJoined(ThreadState *thr, uptr pc, int tid, uptr uid);
568void ProcessPendingSignalsImpl(ThreadState *thr);
569void ThreadNotJoined(ThreadState *thr, uptr pc, Tid tid, uptr uid);
760570
761571Processor *ProcCreate();
762572void ProcDestroy(Processor *proc);
......@@ -785,65 +595,12 @@ void Acquire(ThreadState *thr, uptr pc, uptr addr);
785595// handle Go finalizers. Namely, finalizer goroutine executes AcquireGlobal
786596// right before executing finalizers. This provides a coarse, but simple
787597// approximation of the actual required synchronization.
788void AcquireGlobal(ThreadState *thr, uptr pc);
598void AcquireGlobal(ThreadState *thr);
789599void Release(ThreadState *thr, uptr pc, uptr addr);
790600void ReleaseStoreAcquire(ThreadState *thr, uptr pc, uptr addr);
791601void ReleaseStore(ThreadState *thr, uptr pc, uptr addr);
792602void AfterSleep(ThreadState *thr, uptr pc);
793void AcquireImpl(ThreadState *thr, uptr pc, SyncClock *c);
794void ReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c);
795void ReleaseStoreAcquireImpl(ThreadState *thr, uptr pc, SyncClock *c);
796void ReleaseStoreImpl(ThreadState *thr, uptr pc, SyncClock *c);
797void AcquireReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c);
798
799// The hacky call uses custom calling convention and an assembly thunk.
800// It is considerably faster that a normal call for the caller
801// if it is not executed (it is intended for slow paths from hot functions).
802// The trick is that the call preserves all registers and the compiler
803// does not treat it as a call.
804// If it does not work for you, use normal call.
805#if !SANITIZER_DEBUG && defined(__x86_64__) && !SANITIZER_MAC
806// The caller may not create the stack frame for itself at all,
807// so we create a reserve stack frame for it (1024b must be enough).
808#define HACKY_CALL(f) \
809 __asm__ __volatile__("sub $1024, %%rsp;" \
810 CFI_INL_ADJUST_CFA_OFFSET(1024) \
811 ".hidden " #f "_thunk;" \
812 "call " #f "_thunk;" \
813 "add $1024, %%rsp;" \
814 CFI_INL_ADJUST_CFA_OFFSET(-1024) \
815 ::: "memory", "cc");
816#else
817#define HACKY_CALL(f) f()
818#endif
819
820void TraceSwitch(ThreadState *thr);
821uptr TraceTopPC(ThreadState *thr);
822uptr TraceSize();
823uptr TraceParts();
824Trace *ThreadTrace(int tid);
825
826extern "C" void __tsan_trace_switch();
827void ALWAYS_INLINE TraceAddEvent(ThreadState *thr, FastState fs,
828 EventType typ, u64 addr) {
829 if (!kCollectHistory)
830 return;
831 DCHECK_GE((int)typ, 0);
832 DCHECK_LE((int)typ, 7);
833 DCHECK_EQ(GetLsb(addr, kEventPCBits), addr);
834 u64 pos = fs.GetTracePos();
835 if (UNLIKELY((pos % kTracePartSize) == 0)) {
836#if !SANITIZER_GO
837 HACKY_CALL(__tsan_trace_switch);
838#else
839 TraceSwitch(thr);
840#endif
841 }
842 Event *trace = (Event*)GetThreadTrace(fs.tid());
843 Event *evp = &trace[pos];
844 Event ev = (u64)addr | ((u64)typ << kEventPCBits);
845 *evp = ev;
846}
603void IncrementEpoch(ThreadState *thr);
847604
848605#if !SANITIZER_GO
849606uptr ALWAYS_INLINE HeapEnd() {
......@@ -851,6 +608,13 @@ uptr ALWAYS_INLINE HeapEnd() {
851608}
852609#endif
853610
611void SlotAttachAndLock(ThreadState *thr) SANITIZER_ACQUIRE(thr->slot->mtx);
612void SlotDetach(ThreadState *thr);
613void SlotLock(ThreadState *thr) SANITIZER_ACQUIRE(thr->slot->mtx);
614void SlotUnlock(ThreadState *thr) SANITIZER_RELEASE(thr->slot->mtx);
615void DoReset(ThreadState *thr, uptr epoch);
616void FlushShadowMemory();
617
854618ThreadState *FiberCreate(ThreadState *thr, uptr pc, unsigned flags);
855619void FiberDestroy(ThreadState *thr, uptr pc, ThreadState *fiber);
856620void FiberSwitch(ThreadState *thr, uptr pc, ThreadState *fiber, unsigned flags);
......@@ -861,6 +625,189 @@ enum FiberSwitchFlags {
861625 FiberSwitchFlagNoSync = 1 << 0, // __tsan_switch_to_fiber_no_sync
862626};
863627
628class SlotLocker {
629 public:
630 ALWAYS_INLINE
631 SlotLocker(ThreadState *thr, bool recursive = false)
632 : thr_(thr), locked_(recursive ? thr->slot_locked : false) {
633#if !SANITIZER_GO
634 // We are in trouble if we are here with in_blocking_func set.
635 // If in_blocking_func is set, all signals will be delivered synchronously,
636 // which means we can't lock slots since the signal handler will try
637 // to lock it recursively and deadlock.
638 DCHECK(!atomic_load(&thr->in_blocking_func, memory_order_relaxed));
639#endif
640 if (!locked_)
641 SlotLock(thr_);
642 }
643
644 ALWAYS_INLINE
645 ~SlotLocker() {
646 if (!locked_)
647 SlotUnlock(thr_);
648 }
649
650 private:
651 ThreadState *thr_;
652 bool locked_;
653};
654
655class SlotUnlocker {
656 public:
657 SlotUnlocker(ThreadState *thr) : thr_(thr), locked_(thr->slot_locked) {
658 if (locked_)
659 SlotUnlock(thr_);
660 }
661
662 ~SlotUnlocker() {
663 if (locked_)
664 SlotLock(thr_);
665 }
666
667 private:
668 ThreadState *thr_;
669 bool locked_;
670};
671
672ALWAYS_INLINE void ProcessPendingSignals(ThreadState *thr) {
673 if (UNLIKELY(atomic_load_relaxed(&thr->pending_signals)))
674 ProcessPendingSignalsImpl(thr);
675}
676
677extern bool is_initialized;
678
679ALWAYS_INLINE
680void LazyInitialize(ThreadState *thr) {
681 // If we can use .preinit_array, assume that __tsan_init
682 // called from .preinit_array initializes runtime before
683 // any instrumented code except when tsan is used as a
684 // shared library.
685#if (!SANITIZER_CAN_USE_PREINIT_ARRAY || defined(SANITIZER_SHARED))
686 if (UNLIKELY(!is_initialized))
687 Initialize(thr);
688#endif
689}
690
691void TraceResetForTesting();
692void TraceSwitchPart(ThreadState *thr);
693void TraceSwitchPartImpl(ThreadState *thr);
694bool RestoreStack(EventType type, Sid sid, Epoch epoch, uptr addr, uptr size,
695 AccessType typ, Tid *ptid, VarSizeStackTrace *pstk,
696 MutexSet *pmset, uptr *ptag);
697
698template <typename EventT>
699ALWAYS_INLINE WARN_UNUSED_RESULT bool TraceAcquire(ThreadState *thr,
700 EventT **ev) {
701 // TraceSwitchPart accesses shadow_stack, but it's called infrequently,
702 // so we check it here proactively.
703 DCHECK(thr->shadow_stack);
704 Event *pos = reinterpret_cast<Event *>(atomic_load_relaxed(&thr->trace_pos));
705#if SANITIZER_DEBUG
706 // TraceSwitch acquires these mutexes,
707 // so we lock them here to detect deadlocks more reliably.
708 { Lock lock(&ctx->slot_mtx); }
709 { Lock lock(&thr->tctx->trace.mtx); }
710 TracePart *current = thr->tctx->trace.parts.Back();
711 if (current) {
712 DCHECK_GE(pos, &current->events[0]);
713 DCHECK_LE(pos, &current->events[TracePart::kSize]);
714 } else {
715 DCHECK_EQ(pos, nullptr);
716 }
717#endif
718 // TracePart is allocated with mmap and is at least 4K aligned.
719 // So the following check is a faster way to check for part end.
720 // It may have false positives in the middle of the trace,
721 // they are filtered out in TraceSwitch.
722 if (UNLIKELY(((uptr)(pos + 1) & TracePart::kAlignment) == 0))
723 return false;
724 *ev = reinterpret_cast<EventT *>(pos);
725 return true;
726}
727
728template <typename EventT>
729ALWAYS_INLINE void TraceRelease(ThreadState *thr, EventT *evp) {
730 DCHECK_LE(evp + 1, &thr->tctx->trace.parts.Back()->events[TracePart::kSize]);
731 atomic_store_relaxed(&thr->trace_pos, (uptr)(evp + 1));
732}
733
734template <typename EventT>
735void TraceEvent(ThreadState *thr, EventT ev) {
736 EventT *evp;
737 if (!TraceAcquire(thr, &evp)) {
738 TraceSwitchPart(thr);
739 UNUSED bool res = TraceAcquire(thr, &evp);
740 DCHECK(res);
741 }
742 *evp = ev;
743 TraceRelease(thr, evp);
744}
745
746ALWAYS_INLINE WARN_UNUSED_RESULT bool TryTraceFunc(ThreadState *thr,
747 uptr pc = 0) {
748 if (!kCollectHistory)
749 return true;
750 EventFunc *ev;
751 if (UNLIKELY(!TraceAcquire(thr, &ev)))
752 return false;
753 ev->is_access = 0;
754 ev->is_func = 1;
755 ev->pc = pc;
756 TraceRelease(thr, ev);
757 return true;
758}
759
760WARN_UNUSED_RESULT
761bool TryTraceMemoryAccess(ThreadState *thr, uptr pc, uptr addr, uptr size,
762 AccessType typ);
763WARN_UNUSED_RESULT
764bool TryTraceMemoryAccessRange(ThreadState *thr, uptr pc, uptr addr, uptr size,
765 AccessType typ);
766void TraceMemoryAccessRange(ThreadState *thr, uptr pc, uptr addr, uptr size,
767 AccessType typ);
768void TraceFunc(ThreadState *thr, uptr pc = 0);
769void TraceMutexLock(ThreadState *thr, EventType type, uptr pc, uptr addr,
770 StackID stk);
771void TraceMutexUnlock(ThreadState *thr, uptr addr);
772void TraceTime(ThreadState *thr);
773
774void TraceRestartFuncExit(ThreadState *thr);
775void TraceRestartFuncEntry(ThreadState *thr, uptr pc);
776
777void GrowShadowStack(ThreadState *thr);
778
779ALWAYS_INLINE
780void FuncEntry(ThreadState *thr, uptr pc) {
781 DPrintf2("#%d: FuncEntry %p\n", (int)thr->fast_state.sid(), (void *)pc);
782 if (UNLIKELY(!TryTraceFunc(thr, pc)))
783 return TraceRestartFuncEntry(thr, pc);
784 DCHECK_GE(thr->shadow_stack_pos, thr->shadow_stack);
785#if !SANITIZER_GO
786 DCHECK_LT(thr->shadow_stack_pos, thr->shadow_stack_end);
787#else
788 if (thr->shadow_stack_pos == thr->shadow_stack_end)
789 GrowShadowStack(thr);
790#endif
791 thr->shadow_stack_pos[0] = pc;
792 thr->shadow_stack_pos++;
793}
794
795ALWAYS_INLINE
796void FuncExit(ThreadState *thr) {
797 DPrintf2("#%d: FuncExit\n", (int)thr->fast_state.sid());
798 if (UNLIKELY(!TryTraceFunc(thr, 0)))
799 return TraceRestartFuncExit(thr);
800 DCHECK_GT(thr->shadow_stack_pos, thr->shadow_stack);
801#if !SANITIZER_GO
802 DCHECK_LT(thr->shadow_stack_pos, thr->shadow_stack_end);
803#endif
804 thr->shadow_stack_pos--;
805}
806
807#if !SANITIZER_GO
808extern void (*on_initialize)(void);
809extern int (*on_finalize)(int);
810#endif
864811} // namespace __tsan
865812
866813#endif // TSAN_RTL_H
lib/tsan/tsan_rtl_aarch64.S+6-31
......@@ -3,28 +3,6 @@
33
44#include "sanitizer_common/sanitizer_asm.h"
55
6#if defined(__APPLE__)
7.align 2
8
9.section __DATA,__nl_symbol_ptr,non_lazy_symbol_pointers
10.long _setjmp$non_lazy_ptr
11_setjmp$non_lazy_ptr:
12.indirect_symbol _setjmp
13.long 0
14
15.section __DATA,__nl_symbol_ptr,non_lazy_symbol_pointers
16.long __setjmp$non_lazy_ptr
17__setjmp$non_lazy_ptr:
18.indirect_symbol __setjmp
19.long 0
20
21.section __DATA,__nl_symbol_ptr,non_lazy_symbol_pointers
22.long _sigsetjmp$non_lazy_ptr
23_sigsetjmp$non_lazy_ptr:
24.indirect_symbol _sigsetjmp
25.long 0
26#endif
27
286#if !defined(__APPLE__)
297.section .text
308#else
......@@ -75,9 +53,8 @@ ASM_SYMBOL_INTERCEPTOR(setjmp):
7553 ldr x1, [x1, #:got_lo12:_ZN14__interception11real_setjmpE]
7654 ldr x1, [x1]
7755#else
78 adrp x1, _setjmp$non_lazy_ptr@page
79 add x1, x1, _setjmp$non_lazy_ptr@pageoff
80 ldr x1, [x1]
56 adrp x1, _setjmp@GOTPAGE
57 ldr x1, [x1, _setjmp@GOTPAGEOFF]
8158#endif
8259 br x1
8360
......@@ -126,9 +103,8 @@ ASM_SYMBOL_INTERCEPTOR(_setjmp):
126103 ldr x1, [x1, #:got_lo12:_ZN14__interception12real__setjmpE]
127104 ldr x1, [x1]
128105#else
129 adrp x1, __setjmp$non_lazy_ptr@page
130 add x1, x1, __setjmp$non_lazy_ptr@pageoff
131 ldr x1, [x1]
106 adrp x1, __setjmp@GOTPAGE
107 ldr x1, [x1, __setjmp@GOTPAGEOFF]
132108#endif
133109 br x1
134110
......@@ -179,9 +155,8 @@ ASM_SYMBOL_INTERCEPTOR(sigsetjmp):
179155 ldr x2, [x2, #:got_lo12:_ZN14__interception14real_sigsetjmpE]
180156 ldr x2, [x2]
181157#else
182 adrp x2, _sigsetjmp$non_lazy_ptr@page
183 add x2, x2, _sigsetjmp$non_lazy_ptr@pageoff
184 ldr x2, [x2]
158 adrp x2, _sigsetjmp@GOTPAGE
159 ldr x2, [x2, _sigsetjmp@GOTPAGEOFF]
185160#endif
186161 br x2
187162 CFI_ENDPROC
lib/tsan/tsan_rtl_access.cpp created+744
......@@ -0,0 +1,744 @@
1//===-- tsan_rtl_access.cpp -----------------------------------------------===//
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// Definitions of memory access and function entry/exit entry points.
12//===----------------------------------------------------------------------===//
13
14#include "tsan_rtl.h"
15
16namespace __tsan {
17
18ALWAYS_INLINE USED bool TryTraceMemoryAccess(ThreadState* thr, uptr pc,
19 uptr addr, uptr size,
20 AccessType typ) {
21 DCHECK(size == 1 || size == 2 || size == 4 || size == 8);
22 if (!kCollectHistory)
23 return true;
24 EventAccess* ev;
25 if (UNLIKELY(!TraceAcquire(thr, &ev)))
26 return false;
27 u64 size_log = size == 1 ? 0 : size == 2 ? 1 : size == 4 ? 2 : 3;
28 uptr pc_delta = pc - thr->trace_prev_pc + (1 << (EventAccess::kPCBits - 1));
29 thr->trace_prev_pc = pc;
30 if (LIKELY(pc_delta < (1 << EventAccess::kPCBits))) {
31 ev->is_access = 1;
32 ev->is_read = !!(typ & kAccessRead);
33 ev->is_atomic = !!(typ & kAccessAtomic);
34 ev->size_log = size_log;
35 ev->pc_delta = pc_delta;
36 DCHECK_EQ(ev->pc_delta, pc_delta);
37 ev->addr = CompressAddr(addr);
38 TraceRelease(thr, ev);
39 return true;
40 }
41 auto* evex = reinterpret_cast<EventAccessExt*>(ev);
42 evex->is_access = 0;
43 evex->is_func = 0;
44 evex->type = EventType::kAccessExt;
45 evex->is_read = !!(typ & kAccessRead);
46 evex->is_atomic = !!(typ & kAccessAtomic);
47 evex->size_log = size_log;
48 // Note: this is important, see comment in EventAccessExt.
49 evex->_ = 0;
50 evex->addr = CompressAddr(addr);
51 evex->pc = pc;
52 TraceRelease(thr, evex);
53 return true;
54}
55
56ALWAYS_INLINE
57bool TryTraceMemoryAccessRange(ThreadState* thr, uptr pc, uptr addr, uptr size,
58 AccessType typ) {
59 if (!kCollectHistory)
60 return true;
61 EventAccessRange* ev;
62 if (UNLIKELY(!TraceAcquire(thr, &ev)))
63 return false;
64 thr->trace_prev_pc = pc;
65 ev->is_access = 0;
66 ev->is_func = 0;
67 ev->type = EventType::kAccessRange;
68 ev->is_read = !!(typ & kAccessRead);
69 ev->is_free = !!(typ & kAccessFree);
70 ev->size_lo = size;
71 ev->pc = CompressAddr(pc);
72 ev->addr = CompressAddr(addr);
73 ev->size_hi = size >> EventAccessRange::kSizeLoBits;
74 TraceRelease(thr, ev);
75 return true;
76}
77
78void TraceMemoryAccessRange(ThreadState* thr, uptr pc, uptr addr, uptr size,
79 AccessType typ) {
80 if (LIKELY(TryTraceMemoryAccessRange(thr, pc, addr, size, typ)))
81 return;
82 TraceSwitchPart(thr);
83 UNUSED bool res = TryTraceMemoryAccessRange(thr, pc, addr, size, typ);
84 DCHECK(res);
85}
86
87void TraceFunc(ThreadState* thr, uptr pc) {
88 if (LIKELY(TryTraceFunc(thr, pc)))
89 return;
90 TraceSwitchPart(thr);
91 UNUSED bool res = TryTraceFunc(thr, pc);
92 DCHECK(res);
93}
94
95NOINLINE void TraceRestartFuncEntry(ThreadState* thr, uptr pc) {
96 TraceSwitchPart(thr);
97 FuncEntry(thr, pc);
98}
99
100NOINLINE void TraceRestartFuncExit(ThreadState* thr) {
101 TraceSwitchPart(thr);
102 FuncExit(thr);
103}
104
105void TraceMutexLock(ThreadState* thr, EventType type, uptr pc, uptr addr,
106 StackID stk) {
107 DCHECK(type == EventType::kLock || type == EventType::kRLock);
108 if (!kCollectHistory)
109 return;
110 EventLock ev;
111 ev.is_access = 0;
112 ev.is_func = 0;
113 ev.type = type;
114 ev.pc = CompressAddr(pc);
115 ev.stack_lo = stk;
116 ev.stack_hi = stk >> EventLock::kStackIDLoBits;
117 ev._ = 0;
118 ev.addr = CompressAddr(addr);
119 TraceEvent(thr, ev);
120}
121
122void TraceMutexUnlock(ThreadState* thr, uptr addr) {
123 if (!kCollectHistory)
124 return;
125 EventUnlock ev;
126 ev.is_access = 0;
127 ev.is_func = 0;
128 ev.type = EventType::kUnlock;
129 ev._ = 0;
130 ev.addr = CompressAddr(addr);
131 TraceEvent(thr, ev);
132}
133
134void TraceTime(ThreadState* thr) {
135 if (!kCollectHistory)
136 return;
137 FastState fast_state = thr->fast_state;
138 EventTime ev;
139 ev.is_access = 0;
140 ev.is_func = 0;
141 ev.type = EventType::kTime;
142 ev.sid = static_cast<u64>(fast_state.sid());
143 ev.epoch = static_cast<u64>(fast_state.epoch());
144 ev._ = 0;
145 TraceEvent(thr, ev);
146}
147
148NOINLINE void DoReportRace(ThreadState* thr, RawShadow* shadow_mem, Shadow cur,
149 Shadow old,
150 AccessType typ) SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
151 // For the free shadow markers the first element (that contains kFreeSid)
152 // triggers the race, but the second element contains info about the freeing
153 // thread, take it.
154 if (old.sid() == kFreeSid)
155 old = Shadow(LoadShadow(&shadow_mem[1]));
156 // This prevents trapping on this address in future.
157 for (uptr i = 0; i < kShadowCnt; i++)
158 StoreShadow(&shadow_mem[i], i == 0 ? Shadow::kRodata : Shadow::kEmpty);
159 // See the comment in MemoryRangeFreed as to why the slot is locked
160 // for free memory accesses. ReportRace must not be called with
161 // the slot locked because of the fork. But MemoryRangeFreed is not
162 // called during fork because fork sets ignore_reads_and_writes,
163 // so simply unlocking the slot should be fine.
164 if (typ & kAccessSlotLocked)
165 SlotUnlock(thr);
166 ReportRace(thr, shadow_mem, cur, Shadow(old), typ);
167 if (typ & kAccessSlotLocked)
168 SlotLock(thr);
169}
170
171#if !TSAN_VECTORIZE
172ALWAYS_INLINE
173bool ContainsSameAccess(RawShadow* s, Shadow cur, int unused0, int unused1,
174 AccessType typ) {
175 for (uptr i = 0; i < kShadowCnt; i++) {
176 auto old = LoadShadow(&s[i]);
177 if (!(typ & kAccessRead)) {
178 if (old == cur.raw())
179 return true;
180 continue;
181 }
182 auto masked = static_cast<RawShadow>(static_cast<u32>(old) |
183 static_cast<u32>(Shadow::kRodata));
184 if (masked == cur.raw())
185 return true;
186 if (!(typ & kAccessNoRodata) && !SANITIZER_GO) {
187 if (old == Shadow::kRodata)
188 return true;
189 }
190 }
191 return false;
192}
193
194ALWAYS_INLINE
195bool CheckRaces(ThreadState* thr, RawShadow* shadow_mem, Shadow cur,
196 int unused0, int unused1, AccessType typ) {
197 bool stored = false;
198 for (uptr idx = 0; idx < kShadowCnt; idx++) {
199 RawShadow* sp = &shadow_mem[idx];
200 Shadow old(LoadShadow(sp));
201 if (LIKELY(old.raw() == Shadow::kEmpty)) {
202 if (!(typ & kAccessCheckOnly) && !stored)
203 StoreShadow(sp, cur.raw());
204 return false;
205 }
206 if (LIKELY(!(cur.access() & old.access())))
207 continue;
208 if (LIKELY(cur.sid() == old.sid())) {
209 if (!(typ & kAccessCheckOnly) &&
210 LIKELY(cur.access() == old.access() && old.IsRWWeakerOrEqual(typ))) {
211 StoreShadow(sp, cur.raw());
212 stored = true;
213 }
214 continue;
215 }
216 if (LIKELY(old.IsBothReadsOrAtomic(typ)))
217 continue;
218 if (LIKELY(thr->clock.Get(old.sid()) >= old.epoch()))
219 continue;
220 DoReportRace(thr, shadow_mem, cur, old, typ);
221 return true;
222 }
223 // We did not find any races and had already stored
224 // the current access info, so we are done.
225 if (LIKELY(stored))
226 return false;
227 // Choose a random candidate slot and replace it.
228 uptr index =
229 atomic_load_relaxed(&thr->trace_pos) / sizeof(Event) % kShadowCnt;
230 StoreShadow(&shadow_mem[index], cur.raw());
231 return false;
232}
233
234# define LOAD_CURRENT_SHADOW(cur, shadow_mem) UNUSED int access = 0, shadow = 0
235
236#else /* !TSAN_VECTORIZE */
237
238ALWAYS_INLINE
239bool ContainsSameAccess(RawShadow* unused0, Shadow unused1, m128 shadow,
240 m128 access, AccessType typ) {
241 // Note: we could check if there is a larger access of the same type,
242 // e.g. we just allocated/memset-ed a block (so it contains 8 byte writes)
243 // and now do smaller reads/writes, these can also be considered as "same
244 // access". However, it will make the check more expensive, so it's unclear
245 // if it's worth it. But this would conserve trace space, so it's useful
246 // besides potential speed up.
247 if (!(typ & kAccessRead)) {
248 const m128 same = _mm_cmpeq_epi32(shadow, access);
249 return _mm_movemask_epi8(same);
250 }
251 // For reads we need to reset read bit in the shadow,
252 // because we need to match read with both reads and writes.
253 // Shadow::kRodata has only read bit set, so it does what we want.
254 // We also abuse it for rodata check to save few cycles
255 // since we already loaded Shadow::kRodata into a register.
256 // Reads from rodata can't race.
257 // Measurements show that they can be 10-20% of all memory accesses.
258 // Shadow::kRodata has epoch 0 which cannot appear in shadow normally
259 // (thread epochs start from 1). So the same read bit mask
260 // serves as rodata indicator.
261 const m128 read_mask = _mm_set1_epi32(static_cast<u32>(Shadow::kRodata));
262 const m128 masked_shadow = _mm_or_si128(shadow, read_mask);
263 m128 same = _mm_cmpeq_epi32(masked_shadow, access);
264 // Range memory accesses check Shadow::kRodata before calling this,
265 // Shadow::kRodatas is not possible for free memory access
266 // and Go does not use Shadow::kRodata.
267 if (!(typ & kAccessNoRodata) && !SANITIZER_GO) {
268 const m128 ro = _mm_cmpeq_epi32(shadow, read_mask);
269 same = _mm_or_si128(ro, same);
270 }
271 return _mm_movemask_epi8(same);
272}
273
274NOINLINE void DoReportRaceV(ThreadState* thr, RawShadow* shadow_mem, Shadow cur,
275 u32 race_mask, m128 shadow, AccessType typ) {
276 // race_mask points which of the shadow elements raced with the current
277 // access. Extract that element.
278 CHECK_NE(race_mask, 0);
279 u32 old;
280 // Note: _mm_extract_epi32 index must be a constant value.
281 switch (__builtin_ffs(race_mask) / 4) {
282 case 0:
283 old = _mm_extract_epi32(shadow, 0);
284 break;
285 case 1:
286 old = _mm_extract_epi32(shadow, 1);
287 break;
288 case 2:
289 old = _mm_extract_epi32(shadow, 2);
290 break;
291 case 3:
292 old = _mm_extract_epi32(shadow, 3);
293 break;
294 }
295 Shadow prev(static_cast<RawShadow>(old));
296 // For the free shadow markers the first element (that contains kFreeSid)
297 // triggers the race, but the second element contains info about the freeing
298 // thread, take it.
299 if (prev.sid() == kFreeSid)
300 prev = Shadow(static_cast<RawShadow>(_mm_extract_epi32(shadow, 1)));
301 DoReportRace(thr, shadow_mem, cur, prev, typ);
302}
303
304ALWAYS_INLINE
305bool CheckRaces(ThreadState* thr, RawShadow* shadow_mem, Shadow cur,
306 m128 shadow, m128 access, AccessType typ) {
307 // Note: empty/zero slots don't intersect with any access.
308 const m128 zero = _mm_setzero_si128();
309 const m128 mask_access = _mm_set1_epi32(0x000000ff);
310 const m128 mask_sid = _mm_set1_epi32(0x0000ff00);
311 const m128 mask_read_atomic = _mm_set1_epi32(0xc0000000);
312 const m128 access_and = _mm_and_si128(access, shadow);
313 const m128 access_xor = _mm_xor_si128(access, shadow);
314 const m128 intersect = _mm_and_si128(access_and, mask_access);
315 const m128 not_intersect = _mm_cmpeq_epi32(intersect, zero);
316 const m128 not_same_sid = _mm_and_si128(access_xor, mask_sid);
317 const m128 same_sid = _mm_cmpeq_epi32(not_same_sid, zero);
318 const m128 both_read_or_atomic = _mm_and_si128(access_and, mask_read_atomic);
319 const m128 no_race =
320 _mm_or_si128(_mm_or_si128(not_intersect, same_sid), both_read_or_atomic);
321 const int race_mask = _mm_movemask_epi8(_mm_cmpeq_epi32(no_race, zero));
322 if (UNLIKELY(race_mask))
323 goto SHARED;
324
325STORE : {
326 if (typ & kAccessCheckOnly)
327 return false;
328 // We could also replace different sid's if access is the same,
329 // rw weaker and happens before. However, just checking access below
330 // is not enough because we also need to check that !both_read_or_atomic
331 // (reads from different sids can be concurrent).
332 // Theoretically we could replace smaller accesses with larger accesses,
333 // but it's unclear if it's worth doing.
334 const m128 mask_access_sid = _mm_set1_epi32(0x0000ffff);
335 const m128 not_same_sid_access = _mm_and_si128(access_xor, mask_access_sid);
336 const m128 same_sid_access = _mm_cmpeq_epi32(not_same_sid_access, zero);
337 const m128 access_read_atomic =
338 _mm_set1_epi32((typ & (kAccessRead | kAccessAtomic)) << 30);
339 const m128 rw_weaker =
340 _mm_cmpeq_epi32(_mm_max_epu32(shadow, access_read_atomic), shadow);
341 const m128 rewrite = _mm_and_si128(same_sid_access, rw_weaker);
342 const int rewrite_mask = _mm_movemask_epi8(rewrite);
343 int index = __builtin_ffs(rewrite_mask);
344 if (UNLIKELY(index == 0)) {
345 const m128 empty = _mm_cmpeq_epi32(shadow, zero);
346 const int empty_mask = _mm_movemask_epi8(empty);
347 index = __builtin_ffs(empty_mask);
348 if (UNLIKELY(index == 0))
349 index = (atomic_load_relaxed(&thr->trace_pos) / 2) % 16;
350 }
351 StoreShadow(&shadow_mem[index / 4], cur.raw());
352 // We could zero other slots determined by rewrite_mask.
353 // That would help other threads to evict better slots,
354 // but it's unclear if it's worth it.
355 return false;
356}
357
358SHARED:
359 m128 thread_epochs = _mm_set1_epi32(0x7fffffff);
360 // Need to unwind this because _mm_extract_epi8/_mm_insert_epi32
361 // indexes must be constants.
362# define LOAD_EPOCH(idx) \
363 if (LIKELY(race_mask & (1 << (idx * 4)))) { \
364 u8 sid = _mm_extract_epi8(shadow, idx * 4 + 1); \
365 u16 epoch = static_cast<u16>(thr->clock.Get(static_cast<Sid>(sid))); \
366 thread_epochs = _mm_insert_epi32(thread_epochs, u32(epoch) << 16, idx); \
367 }
368 LOAD_EPOCH(0);
369 LOAD_EPOCH(1);
370 LOAD_EPOCH(2);
371 LOAD_EPOCH(3);
372# undef LOAD_EPOCH
373 const m128 mask_epoch = _mm_set1_epi32(0x3fff0000);
374 const m128 shadow_epochs = _mm_and_si128(shadow, mask_epoch);
375 const m128 concurrent = _mm_cmplt_epi32(thread_epochs, shadow_epochs);
376 const int concurrent_mask = _mm_movemask_epi8(concurrent);
377 if (LIKELY(concurrent_mask == 0))
378 goto STORE;
379
380 DoReportRaceV(thr, shadow_mem, cur, concurrent_mask, shadow, typ);
381 return true;
382}
383
384# define LOAD_CURRENT_SHADOW(cur, shadow_mem) \
385 const m128 access = _mm_set1_epi32(static_cast<u32>((cur).raw())); \
386 const m128 shadow = _mm_load_si128(reinterpret_cast<m128*>(shadow_mem))
387#endif
388
389char* DumpShadow(char* buf, RawShadow raw) {
390 if (raw == Shadow::kEmpty) {
391 internal_snprintf(buf, 64, "0");
392 return buf;
393 }
394 Shadow s(raw);
395 AccessType typ;
396 s.GetAccess(nullptr, nullptr, &typ);
397 internal_snprintf(buf, 64, "{tid=%u@%u access=0x%x typ=%x}",
398 static_cast<u32>(s.sid()), static_cast<u32>(s.epoch()),
399 s.access(), static_cast<u32>(typ));
400 return buf;
401}
402
403// TryTrace* and TraceRestart* functions allow to turn memory access and func
404// entry/exit callbacks into leaf functions with all associated performance
405// benefits. These hottest callbacks do only 2 slow path calls: report a race
406// and trace part switching. Race reporting is easy to turn into a tail call, we
407// just always return from the runtime after reporting a race. But trace part
408// switching is harder because it needs to be in the middle of callbacks. To
409// turn it into a tail call we immidiately return after TraceRestart* functions,
410// but TraceRestart* functions themselves recurse into the callback after
411// switching trace part. As the result the hottest callbacks contain only tail
412// calls, which effectively makes them leaf functions (can use all registers,
413// no frame setup, etc).
414NOINLINE void TraceRestartMemoryAccess(ThreadState* thr, uptr pc, uptr addr,
415 uptr size, AccessType typ) {
416 TraceSwitchPart(thr);
417 MemoryAccess(thr, pc, addr, size, typ);
418}
419
420ALWAYS_INLINE USED void MemoryAccess(ThreadState* thr, uptr pc, uptr addr,
421 uptr size, AccessType typ) {
422 RawShadow* shadow_mem = MemToShadow(addr);
423 UNUSED char memBuf[4][64];
424 DPrintf2("#%d: Access: %d@%d %p/%zd typ=0x%x {%s, %s, %s, %s}\n", thr->tid,
425 static_cast<int>(thr->fast_state.sid()),
426 static_cast<int>(thr->fast_state.epoch()), (void*)addr, size,
427 static_cast<int>(typ), DumpShadow(memBuf[0], shadow_mem[0]),
428 DumpShadow(memBuf[1], shadow_mem[1]),
429 DumpShadow(memBuf[2], shadow_mem[2]),
430 DumpShadow(memBuf[3], shadow_mem[3]));
431
432 FastState fast_state = thr->fast_state;
433 Shadow cur(fast_state, addr, size, typ);
434
435 LOAD_CURRENT_SHADOW(cur, shadow_mem);
436 if (LIKELY(ContainsSameAccess(shadow_mem, cur, shadow, access, typ)))
437 return;
438 if (UNLIKELY(fast_state.GetIgnoreBit()))
439 return;
440 if (!TryTraceMemoryAccess(thr, pc, addr, size, typ))
441 return TraceRestartMemoryAccess(thr, pc, addr, size, typ);
442 CheckRaces(thr, shadow_mem, cur, shadow, access, typ);
443}
444
445void MemoryAccess16(ThreadState* thr, uptr pc, uptr addr, AccessType typ);
446
447NOINLINE
448void RestartMemoryAccess16(ThreadState* thr, uptr pc, uptr addr,
449 AccessType typ) {
450 TraceSwitchPart(thr);
451 MemoryAccess16(thr, pc, addr, typ);
452}
453
454ALWAYS_INLINE USED void MemoryAccess16(ThreadState* thr, uptr pc, uptr addr,
455 AccessType typ) {
456 const uptr size = 16;
457 FastState fast_state = thr->fast_state;
458 if (UNLIKELY(fast_state.GetIgnoreBit()))
459 return;
460 Shadow cur(fast_state, 0, 8, typ);
461 RawShadow* shadow_mem = MemToShadow(addr);
462 bool traced = false;
463 {
464 LOAD_CURRENT_SHADOW(cur, shadow_mem);
465 if (LIKELY(ContainsSameAccess(shadow_mem, cur, shadow, access, typ)))
466 goto SECOND;
467 if (!TryTraceMemoryAccessRange(thr, pc, addr, size, typ))
468 return RestartMemoryAccess16(thr, pc, addr, typ);
469 traced = true;
470 if (UNLIKELY(CheckRaces(thr, shadow_mem, cur, shadow, access, typ)))
471 return;
472 }
473SECOND:
474 shadow_mem += kShadowCnt;
475 LOAD_CURRENT_SHADOW(cur, shadow_mem);
476 if (LIKELY(ContainsSameAccess(shadow_mem, cur, shadow, access, typ)))
477 return;
478 if (!traced && !TryTraceMemoryAccessRange(thr, pc, addr, size, typ))
479 return RestartMemoryAccess16(thr, pc, addr, typ);
480 CheckRaces(thr, shadow_mem, cur, shadow, access, typ);
481}
482
483NOINLINE
484void RestartUnalignedMemoryAccess(ThreadState* thr, uptr pc, uptr addr,
485 uptr size, AccessType typ) {
486 TraceSwitchPart(thr);
487 UnalignedMemoryAccess(thr, pc, addr, size, typ);
488}
489
490ALWAYS_INLINE USED void UnalignedMemoryAccess(ThreadState* thr, uptr pc,
491 uptr addr, uptr size,
492 AccessType typ) {
493 DCHECK_LE(size, 8);
494 FastState fast_state = thr->fast_state;
495 if (UNLIKELY(fast_state.GetIgnoreBit()))
496 return;
497 RawShadow* shadow_mem = MemToShadow(addr);
498 bool traced = false;
499 uptr size1 = Min<uptr>(size, RoundUp(addr + 1, kShadowCell) - addr);
500 {
501 Shadow cur(fast_state, addr, size1, typ);
502 LOAD_CURRENT_SHADOW(cur, shadow_mem);
503 if (LIKELY(ContainsSameAccess(shadow_mem, cur, shadow, access, typ)))
504 goto SECOND;
505 if (!TryTraceMemoryAccessRange(thr, pc, addr, size, typ))
506 return RestartUnalignedMemoryAccess(thr, pc, addr, size, typ);
507 traced = true;
508 if (UNLIKELY(CheckRaces(thr, shadow_mem, cur, shadow, access, typ)))
509 return;
510 }
511SECOND:
512 uptr size2 = size - size1;
513 if (LIKELY(size2 == 0))
514 return;
515 shadow_mem += kShadowCnt;
516 Shadow cur(fast_state, 0, size2, typ);
517 LOAD_CURRENT_SHADOW(cur, shadow_mem);
518 if (LIKELY(ContainsSameAccess(shadow_mem, cur, shadow, access, typ)))
519 return;
520 if (!traced && !TryTraceMemoryAccessRange(thr, pc, addr, size, typ))
521 return RestartUnalignedMemoryAccess(thr, pc, addr, size, typ);
522 CheckRaces(thr, shadow_mem, cur, shadow, access, typ);
523}
524
525void ShadowSet(RawShadow* p, RawShadow* end, RawShadow v) {
526 DCHECK_LE(p, end);
527 DCHECK(IsShadowMem(p));
528 DCHECK(IsShadowMem(end));
529 UNUSED const uptr kAlign = kShadowCnt * kShadowSize;
530 DCHECK_EQ(reinterpret_cast<uptr>(p) % kAlign, 0);
531 DCHECK_EQ(reinterpret_cast<uptr>(end) % kAlign, 0);
532#if !TSAN_VECTORIZE
533 for (; p < end; p += kShadowCnt) {
534 p[0] = v;
535 for (uptr i = 1; i < kShadowCnt; i++) p[i] = Shadow::kEmpty;
536 }
537#else
538 m128 vv = _mm_setr_epi32(
539 static_cast<u32>(v), static_cast<u32>(Shadow::kEmpty),
540 static_cast<u32>(Shadow::kEmpty), static_cast<u32>(Shadow::kEmpty));
541 m128* vp = reinterpret_cast<m128*>(p);
542 m128* vend = reinterpret_cast<m128*>(end);
543 for (; vp < vend; vp++) _mm_store_si128(vp, vv);
544#endif
545}
546
547static void MemoryRangeSet(uptr addr, uptr size, RawShadow val) {
548 if (size == 0)
549 return;
550 DCHECK_EQ(addr % kShadowCell, 0);
551 DCHECK_EQ(size % kShadowCell, 0);
552 // If a user passes some insane arguments (memset(0)),
553 // let it just crash as usual.
554 if (!IsAppMem(addr) || !IsAppMem(addr + size - 1))
555 return;
556 RawShadow* begin = MemToShadow(addr);
557 RawShadow* end = begin + size / kShadowCell * kShadowCnt;
558 // Don't want to touch lots of shadow memory.
559 // If a program maps 10MB stack, there is no need reset the whole range.
560 // UnmapOrDie/MmapFixedNoReserve does not work on Windows.
561 if (SANITIZER_WINDOWS ||
562 size <= common_flags()->clear_shadow_mmap_threshold) {
563 ShadowSet(begin, end, val);
564 return;
565 }
566 // The region is big, reset only beginning and end.
567 const uptr kPageSize = GetPageSizeCached();
568 // Set at least first kPageSize/2 to page boundary.
569 RawShadow* mid1 =
570 Min(end, reinterpret_cast<RawShadow*>(RoundUp(
571 reinterpret_cast<uptr>(begin) + kPageSize / 2, kPageSize)));
572 ShadowSet(begin, mid1, val);
573 // Reset middle part.
574 RawShadow* mid2 = RoundDown(end, kPageSize);
575 if (mid2 > mid1) {
576 if (!MmapFixedSuperNoReserve((uptr)mid1, (uptr)mid2 - (uptr)mid1))
577 Die();
578 }
579 // Set the ending.
580 ShadowSet(mid2, end, val);
581}
582
583void MemoryResetRange(ThreadState* thr, uptr pc, uptr addr, uptr size) {
584 uptr addr1 = RoundDown(addr, kShadowCell);
585 uptr size1 = RoundUp(size + addr - addr1, kShadowCell);
586 MemoryRangeSet(addr1, size1, Shadow::kEmpty);
587}
588
589void MemoryRangeFreed(ThreadState* thr, uptr pc, uptr addr, uptr size) {
590 // Callers must lock the slot to ensure synchronization with the reset.
591 // The problem with "freed" memory is that it's not "monotonic"
592 // with respect to bug detection: freed memory is bad to access,
593 // but then if the heap block is reallocated later, it's good to access.
594 // As the result a garbage "freed" shadow can lead to a false positive
595 // if it happens to match a real free in the thread trace,
596 // but the heap block was reallocated before the current memory access,
597 // so it's still good to access. It's not the case with data races.
598 DCHECK(thr->slot_locked);
599 DCHECK_EQ(addr % kShadowCell, 0);
600 size = RoundUp(size, kShadowCell);
601 // Processing more than 1k (2k of shadow) is expensive,
602 // can cause excessive memory consumption (user does not necessary touch
603 // the whole range) and most likely unnecessary.
604 size = Min<uptr>(size, 1024);
605 const AccessType typ = kAccessWrite | kAccessFree | kAccessSlotLocked |
606 kAccessCheckOnly | kAccessNoRodata;
607 TraceMemoryAccessRange(thr, pc, addr, size, typ);
608 RawShadow* shadow_mem = MemToShadow(addr);
609 Shadow cur(thr->fast_state, 0, kShadowCell, typ);
610#if TSAN_VECTORIZE
611 const m128 access = _mm_set1_epi32(static_cast<u32>(cur.raw()));
612 const m128 freed = _mm_setr_epi32(
613 static_cast<u32>(Shadow::FreedMarker()),
614 static_cast<u32>(Shadow::FreedInfo(cur.sid(), cur.epoch())), 0, 0);
615 for (; size; size -= kShadowCell, shadow_mem += kShadowCnt) {
616 const m128 shadow = _mm_load_si128((m128*)shadow_mem);
617 if (UNLIKELY(CheckRaces(thr, shadow_mem, cur, shadow, access, typ)))
618 return;
619 _mm_store_si128((m128*)shadow_mem, freed);
620 }
621#else
622 for (; size; size -= kShadowCell, shadow_mem += kShadowCnt) {
623 if (UNLIKELY(CheckRaces(thr, shadow_mem, cur, 0, 0, typ)))
624 return;
625 StoreShadow(&shadow_mem[0], Shadow::FreedMarker());
626 StoreShadow(&shadow_mem[1], Shadow::FreedInfo(cur.sid(), cur.epoch()));
627 StoreShadow(&shadow_mem[2], Shadow::kEmpty);
628 StoreShadow(&shadow_mem[3], Shadow::kEmpty);
629 }
630#endif
631}
632
633void MemoryRangeImitateWrite(ThreadState* thr, uptr pc, uptr addr, uptr size) {
634 DCHECK_EQ(addr % kShadowCell, 0);
635 size = RoundUp(size, kShadowCell);
636 TraceMemoryAccessRange(thr, pc, addr, size, kAccessWrite);
637 Shadow cur(thr->fast_state, 0, 8, kAccessWrite);
638 MemoryRangeSet(addr, size, cur.raw());
639}
640
641void MemoryRangeImitateWriteOrResetRange(ThreadState* thr, uptr pc, uptr addr,
642 uptr size) {
643 if (thr->ignore_reads_and_writes == 0)
644 MemoryRangeImitateWrite(thr, pc, addr, size);
645 else
646 MemoryResetRange(thr, pc, addr, size);
647}
648
649ALWAYS_INLINE
650bool MemoryAccessRangeOne(ThreadState* thr, RawShadow* shadow_mem, Shadow cur,
651 AccessType typ) {
652 LOAD_CURRENT_SHADOW(cur, shadow_mem);
653 if (LIKELY(ContainsSameAccess(shadow_mem, cur, shadow, access, typ)))
654 return false;
655 return CheckRaces(thr, shadow_mem, cur, shadow, access, typ);
656}
657
658template <bool is_read>
659NOINLINE void RestartMemoryAccessRange(ThreadState* thr, uptr pc, uptr addr,
660 uptr size) {
661 TraceSwitchPart(thr);
662 MemoryAccessRangeT<is_read>(thr, pc, addr, size);
663}
664
665template <bool is_read>
666void MemoryAccessRangeT(ThreadState* thr, uptr pc, uptr addr, uptr size) {
667 const AccessType typ =
668 (is_read ? kAccessRead : kAccessWrite) | kAccessNoRodata;
669 RawShadow* shadow_mem = MemToShadow(addr);
670 DPrintf2("#%d: MemoryAccessRange: @%p %p size=%d is_read=%d\n", thr->tid,
671 (void*)pc, (void*)addr, (int)size, is_read);
672
673#if SANITIZER_DEBUG
674 if (!IsAppMem(addr)) {
675 Printf("Access to non app mem %zx\n", addr);
676 DCHECK(IsAppMem(addr));
677 }
678 if (!IsAppMem(addr + size - 1)) {
679 Printf("Access to non app mem %zx\n", addr + size - 1);
680 DCHECK(IsAppMem(addr + size - 1));
681 }
682 if (!IsShadowMem(shadow_mem)) {
683 Printf("Bad shadow addr %p (%zx)\n", static_cast<void*>(shadow_mem), addr);
684 DCHECK(IsShadowMem(shadow_mem));
685 }
686 if (!IsShadowMem(shadow_mem + size * kShadowCnt - 1)) {
687 Printf("Bad shadow addr %p (%zx)\n",
688 static_cast<void*>(shadow_mem + size * kShadowCnt - 1),
689 addr + size - 1);
690 DCHECK(IsShadowMem(shadow_mem + size * kShadowCnt - 1));
691 }
692#endif
693
694 // Access to .rodata section, no races here.
695 // Measurements show that it can be 10-20% of all memory accesses.
696 // Check here once to not check for every access separately.
697 // Note: we could (and should) do this only for the is_read case
698 // (writes shouldn't go to .rodata). But it happens in Chromium tests:
699 // https://bugs.chromium.org/p/chromium/issues/detail?id=1275581#c19
700 // Details are unknown since it happens only on CI machines.
701 if (*shadow_mem == Shadow::kRodata)
702 return;
703
704 FastState fast_state = thr->fast_state;
705 if (UNLIKELY(fast_state.GetIgnoreBit()))
706 return;
707
708 if (!TryTraceMemoryAccessRange(thr, pc, addr, size, typ))
709 return RestartMemoryAccessRange<is_read>(thr, pc, addr, size);
710
711 if (UNLIKELY(addr % kShadowCell)) {
712 // Handle unaligned beginning, if any.
713 uptr size1 = Min(size, RoundUp(addr, kShadowCell) - addr);
714 size -= size1;
715 Shadow cur(fast_state, addr, size1, typ);
716 if (UNLIKELY(MemoryAccessRangeOne(thr, shadow_mem, cur, typ)))
717 return;
718 shadow_mem += kShadowCnt;
719 }
720 // Handle middle part, if any.
721 Shadow cur(fast_state, 0, kShadowCell, typ);
722 for (; size >= kShadowCell; size -= kShadowCell, shadow_mem += kShadowCnt) {
723 if (UNLIKELY(MemoryAccessRangeOne(thr, shadow_mem, cur, typ)))
724 return;
725 }
726 // Handle ending, if any.
727 if (UNLIKELY(size)) {
728 Shadow cur(fast_state, 0, size, typ);
729 if (UNLIKELY(MemoryAccessRangeOne(thr, shadow_mem, cur, typ)))
730 return;
731 }
732}
733
734template void MemoryAccessRangeT<true>(ThreadState* thr, uptr pc, uptr addr,
735 uptr size);
736template void MemoryAccessRangeT<false>(ThreadState* thr, uptr pc, uptr addr,
737 uptr size);
738
739} // namespace __tsan
740
741#if !SANITIZER_GO
742// Must be included in this file to make sure everything is inlined.
743# include "tsan_interface.inc"
744#endif
lib/tsan/tsan_rtl_amd64.S+4-160
......@@ -9,166 +9,6 @@
99.section __TEXT,__text
1010#endif
1111
12ASM_HIDDEN(__tsan_trace_switch)
13.globl ASM_SYMBOL(__tsan_trace_switch_thunk)
14ASM_SYMBOL(__tsan_trace_switch_thunk):
15 CFI_STARTPROC
16 # Save scratch registers.
17 push %rax
18 CFI_ADJUST_CFA_OFFSET(8)
19 CFI_REL_OFFSET(%rax, 0)
20 push %rcx
21 CFI_ADJUST_CFA_OFFSET(8)
22 CFI_REL_OFFSET(%rcx, 0)
23 push %rdx
24 CFI_ADJUST_CFA_OFFSET(8)
25 CFI_REL_OFFSET(%rdx, 0)
26 push %rsi
27 CFI_ADJUST_CFA_OFFSET(8)
28 CFI_REL_OFFSET(%rsi, 0)
29 push %rdi
30 CFI_ADJUST_CFA_OFFSET(8)
31 CFI_REL_OFFSET(%rdi, 0)
32 push %r8
33 CFI_ADJUST_CFA_OFFSET(8)
34 CFI_REL_OFFSET(%r8, 0)
35 push %r9
36 CFI_ADJUST_CFA_OFFSET(8)
37 CFI_REL_OFFSET(%r9, 0)
38 push %r10
39 CFI_ADJUST_CFA_OFFSET(8)
40 CFI_REL_OFFSET(%r10, 0)
41 push %r11
42 CFI_ADJUST_CFA_OFFSET(8)
43 CFI_REL_OFFSET(%r11, 0)
44 # Align stack frame.
45 push %rbx # non-scratch
46 CFI_ADJUST_CFA_OFFSET(8)
47 CFI_REL_OFFSET(%rbx, 0)
48 mov %rsp, %rbx # save current rsp
49 CFI_DEF_CFA_REGISTER(%rbx)
50 shr $4, %rsp # clear 4 lsb, align to 16
51 shl $4, %rsp
52
53 call ASM_SYMBOL(__tsan_trace_switch)
54
55 # Unalign stack frame back.
56 mov %rbx, %rsp # restore the original rsp
57 CFI_DEF_CFA_REGISTER(%rsp)
58 pop %rbx
59 CFI_ADJUST_CFA_OFFSET(-8)
60 # Restore scratch registers.
61 pop %r11
62 CFI_ADJUST_CFA_OFFSET(-8)
63 pop %r10
64 CFI_ADJUST_CFA_OFFSET(-8)
65 pop %r9
66 CFI_ADJUST_CFA_OFFSET(-8)
67 pop %r8
68 CFI_ADJUST_CFA_OFFSET(-8)
69 pop %rdi
70 CFI_ADJUST_CFA_OFFSET(-8)
71 pop %rsi
72 CFI_ADJUST_CFA_OFFSET(-8)
73 pop %rdx
74 CFI_ADJUST_CFA_OFFSET(-8)
75 pop %rcx
76 CFI_ADJUST_CFA_OFFSET(-8)
77 pop %rax
78 CFI_ADJUST_CFA_OFFSET(-8)
79 CFI_RESTORE(%rax)
80 CFI_RESTORE(%rbx)
81 CFI_RESTORE(%rcx)
82 CFI_RESTORE(%rdx)
83 CFI_RESTORE(%rsi)
84 CFI_RESTORE(%rdi)
85 CFI_RESTORE(%r8)
86 CFI_RESTORE(%r9)
87 CFI_RESTORE(%r10)
88 CFI_RESTORE(%r11)
89 ret
90 CFI_ENDPROC
91
92ASM_HIDDEN(__tsan_report_race)
93.globl ASM_SYMBOL(__tsan_report_race_thunk)
94ASM_SYMBOL(__tsan_report_race_thunk):
95 CFI_STARTPROC
96 # Save scratch registers.
97 push %rax
98 CFI_ADJUST_CFA_OFFSET(8)
99 CFI_REL_OFFSET(%rax, 0)
100 push %rcx
101 CFI_ADJUST_CFA_OFFSET(8)
102 CFI_REL_OFFSET(%rcx, 0)
103 push %rdx
104 CFI_ADJUST_CFA_OFFSET(8)
105 CFI_REL_OFFSET(%rdx, 0)
106 push %rsi
107 CFI_ADJUST_CFA_OFFSET(8)
108 CFI_REL_OFFSET(%rsi, 0)
109 push %rdi
110 CFI_ADJUST_CFA_OFFSET(8)
111 CFI_REL_OFFSET(%rdi, 0)
112 push %r8
113 CFI_ADJUST_CFA_OFFSET(8)
114 CFI_REL_OFFSET(%r8, 0)
115 push %r9
116 CFI_ADJUST_CFA_OFFSET(8)
117 CFI_REL_OFFSET(%r9, 0)
118 push %r10
119 CFI_ADJUST_CFA_OFFSET(8)
120 CFI_REL_OFFSET(%r10, 0)
121 push %r11
122 CFI_ADJUST_CFA_OFFSET(8)
123 CFI_REL_OFFSET(%r11, 0)
124 # Align stack frame.
125 push %rbx # non-scratch
126 CFI_ADJUST_CFA_OFFSET(8)
127 CFI_REL_OFFSET(%rbx, 0)
128 mov %rsp, %rbx # save current rsp
129 CFI_DEF_CFA_REGISTER(%rbx)
130 shr $4, %rsp # clear 4 lsb, align to 16
131 shl $4, %rsp
132
133 call ASM_SYMBOL(__tsan_report_race)
134
135 # Unalign stack frame back.
136 mov %rbx, %rsp # restore the original rsp
137 CFI_DEF_CFA_REGISTER(%rsp)
138 pop %rbx
139 CFI_ADJUST_CFA_OFFSET(-8)
140 # Restore scratch registers.
141 pop %r11
142 CFI_ADJUST_CFA_OFFSET(-8)
143 pop %r10
144 CFI_ADJUST_CFA_OFFSET(-8)
145 pop %r9
146 CFI_ADJUST_CFA_OFFSET(-8)
147 pop %r8
148 CFI_ADJUST_CFA_OFFSET(-8)
149 pop %rdi
150 CFI_ADJUST_CFA_OFFSET(-8)
151 pop %rsi
152 CFI_ADJUST_CFA_OFFSET(-8)
153 pop %rdx
154 CFI_ADJUST_CFA_OFFSET(-8)
155 pop %rcx
156 CFI_ADJUST_CFA_OFFSET(-8)
157 pop %rax
158 CFI_ADJUST_CFA_OFFSET(-8)
159 CFI_RESTORE(%rax)
160 CFI_RESTORE(%rbx)
161 CFI_RESTORE(%rcx)
162 CFI_RESTORE(%rdx)
163 CFI_RESTORE(%rsi)
164 CFI_RESTORE(%rdi)
165 CFI_RESTORE(%r8)
166 CFI_RESTORE(%r9)
167 CFI_RESTORE(%r10)
168 CFI_RESTORE(%r11)
169 ret
170 CFI_ENDPROC
171
17212ASM_HIDDEN(__tsan_setjmp)
17313#if defined(__NetBSD__)
17414.comm _ZN14__interception15real___setjmp14E,8,8
......@@ -185,6 +25,7 @@ ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(setjmp))
18525ASM_SYMBOL_INTERCEPTOR(setjmp):
18626#endif
18727 CFI_STARTPROC
28 _CET_ENDBR
18829 // save env parameter
18930 push %rdi
19031 CFI_ADJUST_CFA_OFFSET(8)
......@@ -226,6 +67,7 @@ ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(setjmp))
22667ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(_setjmp))
22768ASM_SYMBOL_INTERCEPTOR(_setjmp):
22869 CFI_STARTPROC
70 _CET_ENDBR
22971 // save env parameter
23072 push %rdi
23173 CFI_ADJUST_CFA_OFFSET(8)
......@@ -267,6 +109,7 @@ ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(sigsetjmp))
267109ASM_SYMBOL_INTERCEPTOR(sigsetjmp):
268110#endif
269111 CFI_STARTPROC
112 _CET_ENDBR
270113 // save env parameter
271114 push %rdi
272115 CFI_ADJUST_CFA_OFFSET(8)
......@@ -323,6 +166,7 @@ ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(sigsetjmp))
323166ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp))
324167ASM_SYMBOL_INTERCEPTOR(__sigsetjmp):
325168 CFI_STARTPROC
169 _CET_ENDBR
326170 // save env parameter
327171 push %rdi
328172 CFI_ADJUST_CFA_OFFSET(8)
lib/tsan/tsan_rtl_mutex.cpp+369-338
......@@ -23,6 +23,8 @@
2323namespace __tsan {
2424
2525void ReportDeadlock(ThreadState *thr, uptr pc, DDReport *r);
26void ReportDestroyLocked(ThreadState *thr, uptr pc, uptr addr,
27 FastState last_lock, StackID creation_stack_id);
2628
2729struct Callback final : public DDCallback {
2830 ThreadState *thr;
......@@ -35,27 +37,27 @@ struct Callback final : public DDCallback {
3537 DDCallback::lt = thr->dd_lt;
3638 }
3739
38 u32 Unwind() override { return CurrentStackId(thr, pc); }
39 int UniqueTid() override { return thr->unique_id; }
40 StackID Unwind() override { return CurrentStackId(thr, pc); }
41 int UniqueTid() override { return thr->tid; }
4042};
4143
4244void DDMutexInit(ThreadState *thr, uptr pc, SyncVar *s) {
4345 Callback cb(thr, pc);
4446 ctx->dd->MutexInit(&cb, &s->dd);
45 s->dd.ctx = s->GetId();
47 s->dd.ctx = s->addr;
4648}
4749
4850static void ReportMutexMisuse(ThreadState *thr, uptr pc, ReportType typ,
49 uptr addr, u64 mid) {
51 uptr addr, StackID creation_stack_id) {
5052 // In Go, these misuses are either impossible, or detected by std lib,
5153 // or false positives (e.g. unlock in a different thread).
5254 if (SANITIZER_GO)
5355 return;
5456 if (!ShouldReport(thr, typ))
5557 return;
56 ThreadRegistryLock l(ctx->thread_registry);
58 ThreadRegistryLock l(&ctx->thread_registry);
5759 ScopedReport rep(typ);
58 rep.AddMutex(mid);
60 rep.AddMutex(addr, creation_stack_id);
5961 VarSizeStackTrace trace;
6062 ObtainCurrentStack(thr, pc, &trace);
6163 rep.AddStack(trace, true);
......@@ -63,185 +65,197 @@ static void ReportMutexMisuse(ThreadState *thr, uptr pc, ReportType typ,
6365 OutputReport(thr, rep);
6466}
6567
66void MutexCreate(ThreadState *thr, uptr pc, uptr addr, u32 flagz) NO_THREAD_SAFETY_ANALYSIS {
68static void RecordMutexLock(ThreadState *thr, uptr pc, uptr addr,
69 StackID stack_id, bool write) {
70 auto typ = write ? EventType::kLock : EventType::kRLock;
71 // Note: it's important to trace before modifying mutex set
72 // because tracing can switch trace part and we write the current
73 // mutex set in the beginning of each part.
74 // If we do it in the opposite order, we will write already reduced
75 // mutex set in the beginning of the part and then trace unlock again.
76 TraceMutexLock(thr, typ, pc, addr, stack_id);
77 thr->mset.AddAddr(addr, stack_id, write);
78}
79
80static void RecordMutexUnlock(ThreadState *thr, uptr addr) {
81 // See the comment in RecordMutexLock re order of operations.
82 TraceMutexUnlock(thr, addr);
83 thr->mset.DelAddr(addr);
84}
85
86void MutexCreate(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
6787 DPrintf("#%d: MutexCreate %zx flagz=0x%x\n", thr->tid, addr, flagz);
68 if (!(flagz & MutexFlagLinkerInit) && IsAppMem(addr)) {
69 CHECK(!thr->is_freeing);
70 thr->is_freeing = true;
71 MemoryWrite(thr, pc, addr, kSizeLog1);
72 thr->is_freeing = false;
73 }
74 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
88 if (!(flagz & MutexFlagLinkerInit) && pc && IsAppMem(addr))
89 MemoryAccess(thr, pc, addr, 1, kAccessWrite);
90 SlotLocker locker(thr);
91 auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
7592 s->SetFlags(flagz & MutexCreationFlagMask);
76 if (!SANITIZER_GO && s->creation_stack_id == 0)
93 // Save stack in the case the sync object was created before as atomic.
94 if (!SANITIZER_GO && s->creation_stack_id == kInvalidStackID)
7795 s->creation_stack_id = CurrentStackId(thr, pc);
78 s->mtx.Unlock();
7996}
8097
81void MutexDestroy(ThreadState *thr, uptr pc, uptr addr, u32 flagz) NO_THREAD_SAFETY_ANALYSIS {
98void MutexDestroy(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
8299 DPrintf("#%d: MutexDestroy %zx\n", thr->tid, addr);
83 SyncVar *s = ctx->metamap.GetIfExistsAndLock(addr, true);
84 if (s == 0)
85 return;
86 if ((flagz & MutexFlagLinkerInit)
87 || s->IsFlagSet(MutexFlagLinkerInit)
88 || ((flagz & MutexFlagNotStatic) && !s->IsFlagSet(MutexFlagNotStatic))) {
89 // Destroy is no-op for linker-initialized mutexes.
90 s->mtx.Unlock();
91 return;
92 }
93 if (common_flags()->detect_deadlocks) {
94 Callback cb(thr, pc);
95 ctx->dd->MutexDestroy(&cb, &s->dd);
96 ctx->dd->MutexInit(&cb, &s->dd);
97 }
98100 bool unlock_locked = false;
99 if (flags()->report_destroy_locked && s->owner_tid != kInvalidTid &&
100 !s->IsFlagSet(MutexFlagBroken)) {
101 s->SetFlags(MutexFlagBroken);
102 unlock_locked = true;
103 }
104 u64 mid = s->GetId();
105 u64 last_lock = s->last_lock;
106 if (!unlock_locked)
107 s->Reset(thr->proc()); // must not reset it before the report is printed
108 s->mtx.Unlock();
109 if (unlock_locked && ShouldReport(thr, ReportTypeMutexDestroyLocked)) {
110 ThreadRegistryLock l(ctx->thread_registry);
111 ScopedReport rep(ReportTypeMutexDestroyLocked);
112 rep.AddMutex(mid);
113 VarSizeStackTrace trace;
114 ObtainCurrentStack(thr, pc, &trace);
115 rep.AddStack(trace, true);
116 FastState last(last_lock);
117 RestoreStack(last.tid(), last.epoch(), &trace, 0);
118 rep.AddStack(trace, true);
119 rep.AddLocation(addr, 1);
120 OutputReport(thr, rep);
121
122 SyncVar *s = ctx->metamap.GetIfExistsAndLock(addr, true);
123 if (s != 0) {
124 s->Reset(thr->proc());
125 s->mtx.Unlock();
101 StackID creation_stack_id;
102 FastState last_lock;
103 {
104 auto s = ctx->metamap.GetSyncIfExists(addr);
105 if (!s)
106 return;
107 SlotLocker locker(thr);
108 {
109 Lock lock(&s->mtx);
110 creation_stack_id = s->creation_stack_id;
111 last_lock = s->last_lock;
112 if ((flagz & MutexFlagLinkerInit) || s->IsFlagSet(MutexFlagLinkerInit) ||
113 ((flagz & MutexFlagNotStatic) && !s->IsFlagSet(MutexFlagNotStatic))) {
114 // Destroy is no-op for linker-initialized mutexes.
115 return;
116 }
117 if (common_flags()->detect_deadlocks) {
118 Callback cb(thr, pc);
119 ctx->dd->MutexDestroy(&cb, &s->dd);
120 ctx->dd->MutexInit(&cb, &s->dd);
121 }
122 if (flags()->report_destroy_locked && s->owner_tid != kInvalidTid &&
123 !s->IsFlagSet(MutexFlagBroken)) {
124 s->SetFlags(MutexFlagBroken);
125 unlock_locked = true;
126 }
127 s->Reset();
126128 }
129 // Imitate a memory write to catch unlock-destroy races.
130 if (pc && IsAppMem(addr))
131 MemoryAccess(thr, pc, addr, 1,
132 kAccessWrite | kAccessFree | kAccessSlotLocked);
127133 }
128 thr->mset.Remove(mid);
129 // Imitate a memory write to catch unlock-destroy races.
130 // Do this outside of sync mutex, because it can report a race which locks
131 // sync mutexes.
132 if (IsAppMem(addr)) {
133 CHECK(!thr->is_freeing);
134 thr->is_freeing = true;
135 MemoryWrite(thr, pc, addr, kSizeLog1);
136 thr->is_freeing = false;
137 }
134 if (unlock_locked && ShouldReport(thr, ReportTypeMutexDestroyLocked))
135 ReportDestroyLocked(thr, pc, addr, last_lock, creation_stack_id);
136 thr->mset.DelAddr(addr, true);
138137 // s will be destroyed and freed in MetaMap::FreeBlock.
139138}
140139
141void MutexPreLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) NO_THREAD_SAFETY_ANALYSIS {
140void MutexPreLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
142141 DPrintf("#%d: MutexPreLock %zx flagz=0x%x\n", thr->tid, addr, flagz);
143 if (!(flagz & MutexFlagTryLock) && common_flags()->detect_deadlocks) {
144 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, false);
142 if (flagz & MutexFlagTryLock)
143 return;
144 if (!common_flags()->detect_deadlocks)
145 return;
146 Callback cb(thr, pc);
147 {
148 SlotLocker locker(thr);
149 auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
150 ReadLock lock(&s->mtx);
145151 s->UpdateFlags(flagz);
146 if (s->owner_tid != thr->tid) {
147 Callback cb(thr, pc);
152 if (s->owner_tid != thr->tid)
148153 ctx->dd->MutexBeforeLock(&cb, &s->dd, true);
149 s->mtx.ReadUnlock();
150 ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
151 } else {
152 s->mtx.ReadUnlock();
153 }
154154 }
155 ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
155156}
156157
157void MutexPostLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz,
158 int rec) NO_THREAD_SAFETY_ANALYSIS {
158void MutexPostLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz, int rec) {
159159 DPrintf("#%d: MutexPostLock %zx flag=0x%x rec=%d\n",
160160 thr->tid, addr, flagz, rec);
161161 if (flagz & MutexFlagRecursiveLock)
162162 CHECK_GT(rec, 0);
163163 else
164164 rec = 1;
165 if (IsAppMem(addr))
166 MemoryReadAtomic(thr, pc, addr, kSizeLog1);
167 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
168 s->UpdateFlags(flagz);
169 thr->fast_state.IncrementEpoch();
170 TraceAddEvent(thr, thr->fast_state, EventTypeLock, s->GetId());
165 if (pc && IsAppMem(addr))
166 MemoryAccess(thr, pc, addr, 1, kAccessRead | kAccessAtomic);
171167 bool report_double_lock = false;
172 if (s->owner_tid == kInvalidTid) {
173 CHECK_EQ(s->recursion, 0);
174 s->owner_tid = thr->tid;
175 s->last_lock = thr->fast_state.raw();
176 } else if (s->owner_tid == thr->tid) {
177 CHECK_GT(s->recursion, 0);
178 } else if (flags()->report_mutex_bugs && !s->IsFlagSet(MutexFlagBroken)) {
179 s->SetFlags(MutexFlagBroken);
180 report_double_lock = true;
181 }
182 const bool first = s->recursion == 0;
183 s->recursion += rec;
184 if (first) {
185 AcquireImpl(thr, pc, &s->clock);
186 AcquireImpl(thr, pc, &s->read_clock);
187 } else if (!s->IsFlagSet(MutexFlagWriteReentrant)) {
188 }
189 thr->mset.Add(s->GetId(), true, thr->fast_state.epoch());
190168 bool pre_lock = false;
191 if (first && common_flags()->detect_deadlocks) {
192 pre_lock = (flagz & MutexFlagDoPreLockOnPostLock) &&
193 !(flagz & MutexFlagTryLock);
194 Callback cb(thr, pc);
195 if (pre_lock)
196 ctx->dd->MutexBeforeLock(&cb, &s->dd, true);
197 ctx->dd->MutexAfterLock(&cb, &s->dd, true, flagz & MutexFlagTryLock);
169 bool first = false;
170 StackID creation_stack_id = kInvalidStackID;
171 {
172 SlotLocker locker(thr);
173 auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
174 creation_stack_id = s->creation_stack_id;
175 RecordMutexLock(thr, pc, addr, creation_stack_id, true);
176 {
177 Lock lock(&s->mtx);
178 first = s->recursion == 0;
179 s->UpdateFlags(flagz);
180 if (s->owner_tid == kInvalidTid) {
181 CHECK_EQ(s->recursion, 0);
182 s->owner_tid = thr->tid;
183 s->last_lock = thr->fast_state;
184 } else if (s->owner_tid == thr->tid) {
185 CHECK_GT(s->recursion, 0);
186 } else if (flags()->report_mutex_bugs && !s->IsFlagSet(MutexFlagBroken)) {
187 s->SetFlags(MutexFlagBroken);
188 report_double_lock = true;
189 }
190 s->recursion += rec;
191 if (first) {
192 if (!thr->ignore_sync) {
193 thr->clock.Acquire(s->clock);
194 thr->clock.Acquire(s->read_clock);
195 }
196 }
197 if (first && common_flags()->detect_deadlocks) {
198 pre_lock = (flagz & MutexFlagDoPreLockOnPostLock) &&
199 !(flagz & MutexFlagTryLock);
200 Callback cb(thr, pc);
201 if (pre_lock)
202 ctx->dd->MutexBeforeLock(&cb, &s->dd, true);
203 ctx->dd->MutexAfterLock(&cb, &s->dd, true, flagz & MutexFlagTryLock);
204 }
205 }
198206 }
199 u64 mid = s->GetId();
200 s->mtx.Unlock();
201 // Can't touch s after this point.
202 s = 0;
203207 if (report_double_lock)
204 ReportMutexMisuse(thr, pc, ReportTypeMutexDoubleLock, addr, mid);
208 ReportMutexMisuse(thr, pc, ReportTypeMutexDoubleLock, addr,
209 creation_stack_id);
205210 if (first && pre_lock && common_flags()->detect_deadlocks) {
206211 Callback cb(thr, pc);
207212 ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
208213 }
209214}
210215
211int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) NO_THREAD_SAFETY_ANALYSIS {
216int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
212217 DPrintf("#%d: MutexUnlock %zx flagz=0x%x\n", thr->tid, addr, flagz);
213 if (IsAppMem(addr))
214 MemoryReadAtomic(thr, pc, addr, kSizeLog1);
215 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
216 thr->fast_state.IncrementEpoch();
217 TraceAddEvent(thr, thr->fast_state, EventTypeUnlock, s->GetId());
218 int rec = 0;
218 if (pc && IsAppMem(addr))
219 MemoryAccess(thr, pc, addr, 1, kAccessRead | kAccessAtomic);
220 StackID creation_stack_id;
221 RecordMutexUnlock(thr, addr);
219222 bool report_bad_unlock = false;
220 if (!SANITIZER_GO && (s->recursion == 0 || s->owner_tid != thr->tid)) {
221 if (flags()->report_mutex_bugs && !s->IsFlagSet(MutexFlagBroken)) {
222 s->SetFlags(MutexFlagBroken);
223 report_bad_unlock = true;
224 }
225 } else {
226 rec = (flagz & MutexFlagRecursiveUnlock) ? s->recursion : 1;
227 s->recursion -= rec;
228 if (s->recursion == 0) {
229 s->owner_tid = kInvalidTid;
230 ReleaseStoreImpl(thr, pc, &s->clock);
231 } else {
223 int rec = 0;
224 {
225 SlotLocker locker(thr);
226 auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
227 bool released = false;
228 {
229 Lock lock(&s->mtx);
230 creation_stack_id = s->creation_stack_id;
231 if (!SANITIZER_GO && (s->recursion == 0 || s->owner_tid != thr->tid)) {
232 if (flags()->report_mutex_bugs && !s->IsFlagSet(MutexFlagBroken)) {
233 s->SetFlags(MutexFlagBroken);
234 report_bad_unlock = true;
235 }
236 } else {
237 rec = (flagz & MutexFlagRecursiveUnlock) ? s->recursion : 1;
238 s->recursion -= rec;
239 if (s->recursion == 0) {
240 s->owner_tid = kInvalidTid;
241 if (!thr->ignore_sync) {
242 thr->clock.ReleaseStore(&s->clock);
243 released = true;
244 }
245 }
246 }
247 if (common_flags()->detect_deadlocks && s->recursion == 0 &&
248 !report_bad_unlock) {
249 Callback cb(thr, pc);
250 ctx->dd->MutexBeforeUnlock(&cb, &s->dd, true);
251 }
232252 }
253 if (released)
254 IncrementEpoch(thr);
233255 }
234 thr->mset.Del(s->GetId(), true);
235 if (common_flags()->detect_deadlocks && s->recursion == 0 &&
236 !report_bad_unlock) {
237 Callback cb(thr, pc);
238 ctx->dd->MutexBeforeUnlock(&cb, &s->dd, true);
239 }
240 u64 mid = s->GetId();
241 s->mtx.Unlock();
242 // Can't touch s after this point.
243256 if (report_bad_unlock)
244 ReportMutexMisuse(thr, pc, ReportTypeMutexBadUnlock, addr, mid);
257 ReportMutexMisuse(thr, pc, ReportTypeMutexBadUnlock, addr,
258 creation_stack_id);
245259 if (common_flags()->detect_deadlocks && !report_bad_unlock) {
246260 Callback cb(thr, pc);
247261 ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
......@@ -249,282 +263,275 @@ int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) NO_THREAD_SAFET
249263 return rec;
250264}
251265
252void MutexPreReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) NO_THREAD_SAFETY_ANALYSIS {
266void MutexPreReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
253267 DPrintf("#%d: MutexPreReadLock %zx flagz=0x%x\n", thr->tid, addr, flagz);
254 if (!(flagz & MutexFlagTryLock) && common_flags()->detect_deadlocks) {
255 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, false);
268 if ((flagz & MutexFlagTryLock) || !common_flags()->detect_deadlocks)
269 return;
270 Callback cb(thr, pc);
271 {
272 SlotLocker locker(thr);
273 auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
274 ReadLock lock(&s->mtx);
256275 s->UpdateFlags(flagz);
257 Callback cb(thr, pc);
258276 ctx->dd->MutexBeforeLock(&cb, &s->dd, false);
259 s->mtx.ReadUnlock();
260 ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
261277 }
278 ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
262279}
263280
264void MutexPostReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) NO_THREAD_SAFETY_ANALYSIS {
281void MutexPostReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
265282 DPrintf("#%d: MutexPostReadLock %zx flagz=0x%x\n", thr->tid, addr, flagz);
266 if (IsAppMem(addr))
267 MemoryReadAtomic(thr, pc, addr, kSizeLog1);
268 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, false);
269 s->UpdateFlags(flagz);
270 thr->fast_state.IncrementEpoch();
271 TraceAddEvent(thr, thr->fast_state, EventTypeRLock, s->GetId());
283 if (pc && IsAppMem(addr))
284 MemoryAccess(thr, pc, addr, 1, kAccessRead | kAccessAtomic);
272285 bool report_bad_lock = false;
273 if (s->owner_tid != kInvalidTid) {
274 if (flags()->report_mutex_bugs && !s->IsFlagSet(MutexFlagBroken)) {
275 s->SetFlags(MutexFlagBroken);
276 report_bad_lock = true;
277 }
278 }
279 AcquireImpl(thr, pc, &s->clock);
280 s->last_lock = thr->fast_state.raw();
281 thr->mset.Add(s->GetId(), false, thr->fast_state.epoch());
282286 bool pre_lock = false;
283 if (common_flags()->detect_deadlocks) {
284 pre_lock = (flagz & MutexFlagDoPreLockOnPostLock) &&
285 !(flagz & MutexFlagTryLock);
286 Callback cb(thr, pc);
287 if (pre_lock)
288 ctx->dd->MutexBeforeLock(&cb, &s->dd, false);
289 ctx->dd->MutexAfterLock(&cb, &s->dd, false, flagz & MutexFlagTryLock);
287 StackID creation_stack_id = kInvalidStackID;
288 {
289 SlotLocker locker(thr);
290 auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
291 creation_stack_id = s->creation_stack_id;
292 RecordMutexLock(thr, pc, addr, creation_stack_id, false);
293 {
294 ReadLock lock(&s->mtx);
295 s->UpdateFlags(flagz);
296 if (s->owner_tid != kInvalidTid) {
297 if (flags()->report_mutex_bugs && !s->IsFlagSet(MutexFlagBroken)) {
298 s->SetFlags(MutexFlagBroken);
299 report_bad_lock = true;
300 }
301 }
302 if (!thr->ignore_sync)
303 thr->clock.Acquire(s->clock);
304 s->last_lock = thr->fast_state;
305 if (common_flags()->detect_deadlocks) {
306 pre_lock = (flagz & MutexFlagDoPreLockOnPostLock) &&
307 !(flagz & MutexFlagTryLock);
308 Callback cb(thr, pc);
309 if (pre_lock)
310 ctx->dd->MutexBeforeLock(&cb, &s->dd, false);
311 ctx->dd->MutexAfterLock(&cb, &s->dd, false, flagz & MutexFlagTryLock);
312 }
313 }
290314 }
291 u64 mid = s->GetId();
292 s->mtx.ReadUnlock();
293 // Can't touch s after this point.
294 s = 0;
295315 if (report_bad_lock)
296 ReportMutexMisuse(thr, pc, ReportTypeMutexBadReadLock, addr, mid);
316 ReportMutexMisuse(thr, pc, ReportTypeMutexBadReadLock, addr,
317 creation_stack_id);
297318 if (pre_lock && common_flags()->detect_deadlocks) {
298319 Callback cb(thr, pc);
299320 ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
300321 }
301322}
302323
303void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) NO_THREAD_SAFETY_ANALYSIS {
324void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) {
304325 DPrintf("#%d: MutexReadUnlock %zx\n", thr->tid, addr);
305 if (IsAppMem(addr))
306 MemoryReadAtomic(thr, pc, addr, kSizeLog1);
307 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
308 thr->fast_state.IncrementEpoch();
309 TraceAddEvent(thr, thr->fast_state, EventTypeRUnlock, s->GetId());
326 if (pc && IsAppMem(addr))
327 MemoryAccess(thr, pc, addr, 1, kAccessRead | kAccessAtomic);
328 RecordMutexUnlock(thr, addr);
329 StackID creation_stack_id;
310330 bool report_bad_unlock = false;
311 if (s->owner_tid != kInvalidTid) {
312 if (flags()->report_mutex_bugs && !s->IsFlagSet(MutexFlagBroken)) {
313 s->SetFlags(MutexFlagBroken);
314 report_bad_unlock = true;
331 {
332 SlotLocker locker(thr);
333 auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
334 bool released = false;
335 {
336 Lock lock(&s->mtx);
337 creation_stack_id = s->creation_stack_id;
338 if (s->owner_tid != kInvalidTid) {
339 if (flags()->report_mutex_bugs && !s->IsFlagSet(MutexFlagBroken)) {
340 s->SetFlags(MutexFlagBroken);
341 report_bad_unlock = true;
342 }
343 }
344 if (!thr->ignore_sync) {
345 thr->clock.Release(&s->read_clock);
346 released = true;
347 }
348 if (common_flags()->detect_deadlocks && s->recursion == 0) {
349 Callback cb(thr, pc);
350 ctx->dd->MutexBeforeUnlock(&cb, &s->dd, false);
351 }
315352 }
353 if (released)
354 IncrementEpoch(thr);
316355 }
317 ReleaseImpl(thr, pc, &s->read_clock);
318 if (common_flags()->detect_deadlocks && s->recursion == 0) {
319 Callback cb(thr, pc);
320 ctx->dd->MutexBeforeUnlock(&cb, &s->dd, false);
321 }
322 u64 mid = s->GetId();
323 s->mtx.Unlock();
324 // Can't touch s after this point.
325 thr->mset.Del(mid, false);
326356 if (report_bad_unlock)
327 ReportMutexMisuse(thr, pc, ReportTypeMutexBadReadUnlock, addr, mid);
357 ReportMutexMisuse(thr, pc, ReportTypeMutexBadReadUnlock, addr,
358 creation_stack_id);
328359 if (common_flags()->detect_deadlocks) {
329360 Callback cb(thr, pc);
330361 ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
331362 }
332363}
333364
334void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) NO_THREAD_SAFETY_ANALYSIS {
365void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) {
335366 DPrintf("#%d: MutexReadOrWriteUnlock %zx\n", thr->tid, addr);
336 if (IsAppMem(addr))
337 MemoryReadAtomic(thr, pc, addr, kSizeLog1);
338 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
339 bool write = true;
367 if (pc && IsAppMem(addr))
368 MemoryAccess(thr, pc, addr, 1, kAccessRead | kAccessAtomic);
369 RecordMutexUnlock(thr, addr);
370 StackID creation_stack_id;
340371 bool report_bad_unlock = false;
341 if (s->owner_tid == kInvalidTid) {
342 // Seems to be read unlock.
343 write = false;
344 thr->fast_state.IncrementEpoch();
345 TraceAddEvent(thr, thr->fast_state, EventTypeRUnlock, s->GetId());
346 ReleaseImpl(thr, pc, &s->read_clock);
347 } else if (s->owner_tid == thr->tid) {
348 // Seems to be write unlock.
349 thr->fast_state.IncrementEpoch();
350 TraceAddEvent(thr, thr->fast_state, EventTypeUnlock, s->GetId());
351 CHECK_GT(s->recursion, 0);
352 s->recursion--;
353 if (s->recursion == 0) {
354 s->owner_tid = kInvalidTid;
355 ReleaseStoreImpl(thr, pc, &s->clock);
356 } else {
372 bool write = true;
373 {
374 SlotLocker locker(thr);
375 auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
376 bool released = false;
377 {
378 Lock lock(&s->mtx);
379 creation_stack_id = s->creation_stack_id;
380 if (s->owner_tid == kInvalidTid) {
381 // Seems to be read unlock.
382 write = false;
383 if (!thr->ignore_sync) {
384 thr->clock.Release(&s->read_clock);
385 released = true;
386 }
387 } else if (s->owner_tid == thr->tid) {
388 // Seems to be write unlock.
389 CHECK_GT(s->recursion, 0);
390 s->recursion--;
391 if (s->recursion == 0) {
392 s->owner_tid = kInvalidTid;
393 if (!thr->ignore_sync) {
394 thr->clock.ReleaseStore(&s->clock);
395 released = true;
396 }
397 }
398 } else if (!s->IsFlagSet(MutexFlagBroken)) {
399 s->SetFlags(MutexFlagBroken);
400 report_bad_unlock = true;
401 }
402 if (common_flags()->detect_deadlocks && s->recursion == 0) {
403 Callback cb(thr, pc);
404 ctx->dd->MutexBeforeUnlock(&cb, &s->dd, write);
405 }
357406 }
358 } else if (!s->IsFlagSet(MutexFlagBroken)) {
359 s->SetFlags(MutexFlagBroken);
360 report_bad_unlock = true;
407 if (released)
408 IncrementEpoch(thr);
361409 }
362 thr->mset.Del(s->GetId(), write);
363 if (common_flags()->detect_deadlocks && s->recursion == 0) {
364 Callback cb(thr, pc);
365 ctx->dd->MutexBeforeUnlock(&cb, &s->dd, write);
366 }
367 u64 mid = s->GetId();
368 s->mtx.Unlock();
369 // Can't touch s after this point.
370410 if (report_bad_unlock)
371 ReportMutexMisuse(thr, pc, ReportTypeMutexBadUnlock, addr, mid);
411 ReportMutexMisuse(thr, pc, ReportTypeMutexBadUnlock, addr,
412 creation_stack_id);
372413 if (common_flags()->detect_deadlocks) {
373414 Callback cb(thr, pc);
374415 ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
375416 }
376417}
377418
378void MutexRepair(ThreadState *thr, uptr pc, uptr addr) NO_THREAD_SAFETY_ANALYSIS {
419void MutexRepair(ThreadState *thr, uptr pc, uptr addr) {
379420 DPrintf("#%d: MutexRepair %zx\n", thr->tid, addr);
380 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
421 SlotLocker locker(thr);
422 auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
423 Lock lock(&s->mtx);
381424 s->owner_tid = kInvalidTid;
382425 s->recursion = 0;
383 s->mtx.Unlock();
384426}
385427
386void MutexInvalidAccess(ThreadState *thr, uptr pc, uptr addr) NO_THREAD_SAFETY_ANALYSIS {
428void MutexInvalidAccess(ThreadState *thr, uptr pc, uptr addr) {
387429 DPrintf("#%d: MutexInvalidAccess %zx\n", thr->tid, addr);
388 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
389 u64 mid = s->GetId();
390 s->mtx.Unlock();
391 ReportMutexMisuse(thr, pc, ReportTypeMutexInvalidAccess, addr, mid);
430 StackID creation_stack_id = kInvalidStackID;
431 {
432 SlotLocker locker(thr);
433 auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
434 if (s)
435 creation_stack_id = s->creation_stack_id;
436 }
437 ReportMutexMisuse(thr, pc, ReportTypeMutexInvalidAccess, addr,
438 creation_stack_id);
392439}
393440
394void Acquire(ThreadState *thr, uptr pc, uptr addr) NO_THREAD_SAFETY_ANALYSIS {
441void Acquire(ThreadState *thr, uptr pc, uptr addr) {
395442 DPrintf("#%d: Acquire %zx\n", thr->tid, addr);
396443 if (thr->ignore_sync)
397444 return;
398 SyncVar *s = ctx->metamap.GetIfExistsAndLock(addr, false);
445 auto s = ctx->metamap.GetSyncIfExists(addr);
399446 if (!s)
400447 return;
401 AcquireImpl(thr, pc, &s->clock);
402 s->mtx.ReadUnlock();
403}
404
405static void UpdateClockCallback(ThreadContextBase *tctx_base, void *arg) {
406 ThreadState *thr = reinterpret_cast<ThreadState*>(arg);
407 ThreadContext *tctx = static_cast<ThreadContext*>(tctx_base);
408 u64 epoch = tctx->epoch1;
409 if (tctx->status == ThreadStatusRunning) {
410 epoch = tctx->thr->fast_state.epoch();
411 tctx->thr->clock.NoteGlobalAcquire(epoch);
412 }
413 thr->clock.set(&thr->proc()->clock_cache, tctx->tid, epoch);
448 SlotLocker locker(thr);
449 if (!s->clock)
450 return;
451 ReadLock lock(&s->mtx);
452 thr->clock.Acquire(s->clock);
414453}
415454
416void AcquireGlobal(ThreadState *thr, uptr pc) {
455void AcquireGlobal(ThreadState *thr) {
417456 DPrintf("#%d: AcquireGlobal\n", thr->tid);
418457 if (thr->ignore_sync)
419458 return;
420 ThreadRegistryLock l(ctx->thread_registry);
421 ctx->thread_registry->RunCallbackForEachThreadLocked(
422 UpdateClockCallback, thr);
459 SlotLocker locker(thr);
460 for (auto &slot : ctx->slots) thr->clock.Set(slot.sid, slot.epoch());
423461}
424462
425void ReleaseStoreAcquire(ThreadState *thr, uptr pc, uptr addr) NO_THREAD_SAFETY_ANALYSIS {
426 DPrintf("#%d: ReleaseStoreAcquire %zx\n", thr->tid, addr);
463void Release(ThreadState *thr, uptr pc, uptr addr) {
464 DPrintf("#%d: Release %zx\n", thr->tid, addr);
427465 if (thr->ignore_sync)
428466 return;
429 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
430 thr->fast_state.IncrementEpoch();
431 // Can't increment epoch w/o writing to the trace as well.
432 TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
433 ReleaseStoreAcquireImpl(thr, pc, &s->clock);
434 s->mtx.Unlock();
467 SlotLocker locker(thr);
468 {
469 auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, false);
470 Lock lock(&s->mtx);
471 thr->clock.Release(&s->clock);
472 }
473 IncrementEpoch(thr);
435474}
436475
437void Release(ThreadState *thr, uptr pc, uptr addr) NO_THREAD_SAFETY_ANALYSIS {
438 DPrintf("#%d: Release %zx\n", thr->tid, addr);
476void ReleaseStore(ThreadState *thr, uptr pc, uptr addr) {
477 DPrintf("#%d: ReleaseStore %zx\n", thr->tid, addr);
439478 if (thr->ignore_sync)
440479 return;
441 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
442 thr->fast_state.IncrementEpoch();
443 // Can't increment epoch w/o writing to the trace as well.
444 TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
445 ReleaseImpl(thr, pc, &s->clock);
446 s->mtx.Unlock();
480 SlotLocker locker(thr);
481 {
482 auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, false);
483 Lock lock(&s->mtx);
484 thr->clock.ReleaseStore(&s->clock);
485 }
486 IncrementEpoch(thr);
447487}
448488
449void ReleaseStore(ThreadState *thr, uptr pc, uptr addr) NO_THREAD_SAFETY_ANALYSIS {
450 DPrintf("#%d: ReleaseStore %zx\n", thr->tid, addr);
489void ReleaseStoreAcquire(ThreadState *thr, uptr pc, uptr addr) {
490 DPrintf("#%d: ReleaseStoreAcquire %zx\n", thr->tid, addr);
451491 if (thr->ignore_sync)
452492 return;
453 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
454 thr->fast_state.IncrementEpoch();
455 // Can't increment epoch w/o writing to the trace as well.
456 TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
457 ReleaseStoreImpl(thr, pc, &s->clock);
458 s->mtx.Unlock();
493 SlotLocker locker(thr);
494 {
495 auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, false);
496 Lock lock(&s->mtx);
497 thr->clock.ReleaseStoreAcquire(&s->clock);
498 }
499 IncrementEpoch(thr);
459500}
460501
461#if !SANITIZER_GO
462static void UpdateSleepClockCallback(ThreadContextBase *tctx_base, void *arg) {
463 ThreadState *thr = reinterpret_cast<ThreadState*>(arg);
464 ThreadContext *tctx = static_cast<ThreadContext*>(tctx_base);
465 u64 epoch = tctx->epoch1;
466 if (tctx->status == ThreadStatusRunning)
467 epoch = tctx->thr->fast_state.epoch();
468 thr->last_sleep_clock.set(&thr->proc()->clock_cache, tctx->tid, epoch);
502void IncrementEpoch(ThreadState *thr) {
503 DCHECK(!thr->ignore_sync);
504 DCHECK(thr->slot_locked);
505 Epoch epoch = EpochInc(thr->fast_state.epoch());
506 if (!EpochOverflow(epoch)) {
507 Sid sid = thr->fast_state.sid();
508 thr->clock.Set(sid, epoch);
509 thr->fast_state.SetEpoch(epoch);
510 thr->slot->SetEpoch(epoch);
511 TraceTime(thr);
512 }
469513}
470514
515#if !SANITIZER_GO
471516void AfterSleep(ThreadState *thr, uptr pc) {
472 DPrintf("#%d: AfterSleep %zx\n", thr->tid);
517 DPrintf("#%d: AfterSleep\n", thr->tid);
473518 if (thr->ignore_sync)
474519 return;
475520 thr->last_sleep_stack_id = CurrentStackId(thr, pc);
476 ThreadRegistryLock l(ctx->thread_registry);
477 ctx->thread_registry->RunCallbackForEachThreadLocked(
478 UpdateSleepClockCallback, thr);
521 thr->last_sleep_clock.Reset();
522 SlotLocker locker(thr);
523 for (auto &slot : ctx->slots)
524 thr->last_sleep_clock.Set(slot.sid, slot.epoch());
479525}
480526#endif
481527
482void AcquireImpl(ThreadState *thr, uptr pc, SyncClock *c) {
483 if (thr->ignore_sync)
484 return;
485 thr->clock.set(thr->fast_state.epoch());
486 thr->clock.acquire(&thr->proc()->clock_cache, c);
487}
488
489void ReleaseStoreAcquireImpl(ThreadState *thr, uptr pc, SyncClock *c) {
490 if (thr->ignore_sync)
491 return;
492 thr->clock.set(thr->fast_state.epoch());
493 thr->fast_synch_epoch = thr->fast_state.epoch();
494 thr->clock.releaseStoreAcquire(&thr->proc()->clock_cache, c);
495}
496
497void ReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c) {
498 if (thr->ignore_sync)
499 return;
500 thr->clock.set(thr->fast_state.epoch());
501 thr->fast_synch_epoch = thr->fast_state.epoch();
502 thr->clock.release(&thr->proc()->clock_cache, c);
503}
504
505void ReleaseStoreImpl(ThreadState *thr, uptr pc, SyncClock *c) {
506 if (thr->ignore_sync)
507 return;
508 thr->clock.set(thr->fast_state.epoch());
509 thr->fast_synch_epoch = thr->fast_state.epoch();
510 thr->clock.ReleaseStore(&thr->proc()->clock_cache, c);
511}
512
513void AcquireReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c) {
514 if (thr->ignore_sync)
515 return;
516 thr->clock.set(thr->fast_state.epoch());
517 thr->fast_synch_epoch = thr->fast_state.epoch();
518 thr->clock.acq_rel(&thr->proc()->clock_cache, c);
519}
520
521528void ReportDeadlock(ThreadState *thr, uptr pc, DDReport *r) {
522529 if (r == 0 || !ShouldReport(thr, ReportTypeDeadlock))
523530 return;
524 ThreadRegistryLock l(ctx->thread_registry);
531 ThreadRegistryLock l(&ctx->thread_registry);
525532 ScopedReport rep(ReportTypeDeadlock);
526533 for (int i = 0; i < r->n; i++) {
527 rep.AddMutex(r->loop[i].mtx_ctx0);
534 rep.AddMutex(r->loop[i].mtx_ctx0, r->loop[i].stk[0]);
528535 rep.AddUniqueTid((int)r->loop[i].thr_ctx);
529536 rep.AddThread((int)r->loop[i].thr_ctx);
530537 }
......@@ -532,7 +539,7 @@ void ReportDeadlock(ThreadState *thr, uptr pc, DDReport *r) {
532539 for (int i = 0; i < r->n; i++) {
533540 for (int j = 0; j < (flags()->second_deadlock_stack ? 2 : 1); j++) {
534541 u32 stk = r->loop[i].stk[j];
535 if (stk && stk != 0xffffffff) {
542 if (stk && stk != kInvalidStackID) {
536543 rep.AddStack(StackDepotGet(stk), true);
537544 } else {
538545 // Sometimes we fail to extract the stack trace (FIXME: investigate),
......@@ -544,4 +551,28 @@ void ReportDeadlock(ThreadState *thr, uptr pc, DDReport *r) {
544551 OutputReport(thr, rep);
545552}
546553
554void ReportDestroyLocked(ThreadState *thr, uptr pc, uptr addr,
555 FastState last_lock, StackID creation_stack_id) {
556 // We need to lock the slot during RestoreStack because it protects
557 // the slot journal.
558 Lock slot_lock(&ctx->slots[static_cast<uptr>(last_lock.sid())].mtx);
559 ThreadRegistryLock l0(&ctx->thread_registry);
560 Lock slots_lock(&ctx->slot_mtx);
561 ScopedReport rep(ReportTypeMutexDestroyLocked);
562 rep.AddMutex(addr, creation_stack_id);
563 VarSizeStackTrace trace;
564 ObtainCurrentStack(thr, pc, &trace);
565 rep.AddStack(trace, true);
566
567 Tid tid;
568 DynamicMutexSet mset;
569 uptr tag;
570 if (!RestoreStack(EventType::kLock, last_lock.sid(), last_lock.epoch(), addr,
571 0, kAccessWrite, &tid, &trace, mset, &tag))
572 return;
573 rep.AddStack(trace, true);
574 rep.AddLocation(addr, 1);
575 OutputReport(thr, rep);
576}
577
547578} // namespace __tsan
lib/tsan/tsan_rtl_proc.cpp-1
......@@ -35,7 +35,6 @@ void ProcDestroy(Processor *proc) {
3535#if !SANITIZER_GO
3636 AllocatorProcFinish(proc);
3737#endif
38 ctx->clock_alloc.FlushCache(&proc->clock_cache);
3938 ctx->metamap.OnProcIdle(proc);
4039 if (common_flags()->detect_deadlocks)
4140 ctx->dd->DestroyPhysicalThread(proc->dd_pt);
lib/tsan/tsan_rtl_report.cpp+388-290
......@@ -10,20 +10,20 @@
1010//
1111//===----------------------------------------------------------------------===//
1212
13#include "sanitizer_common/sanitizer_common.h"
1314#include "sanitizer_common/sanitizer_libc.h"
1415#include "sanitizer_common/sanitizer_placement_new.h"
1516#include "sanitizer_common/sanitizer_stackdepot.h"
16#include "sanitizer_common/sanitizer_common.h"
1717#include "sanitizer_common/sanitizer_stacktrace.h"
18#include "tsan_fd.h"
19#include "tsan_flags.h"
20#include "tsan_mman.h"
1821#include "tsan_platform.h"
22#include "tsan_report.h"
1923#include "tsan_rtl.h"
2024#include "tsan_suppressions.h"
2125#include "tsan_symbolize.h"
22#include "tsan_report.h"
2326#include "tsan_sync.h"
24#include "tsan_mman.h"
25#include "tsan_flags.h"
26#include "tsan_fd.h"
2727
2828namespace __tsan {
2929
......@@ -68,8 +68,10 @@ static void StackStripMain(SymbolizedStack *frames) {
6868 } else if (last && 0 == internal_strcmp(last, "__tsan_thread_start_func")) {
6969 last_frame->ClearAll();
7070 last_frame2->next = nullptr;
71 // Strip global ctors init.
72 } else if (last && 0 == internal_strcmp(last, "__do_global_ctors_aux")) {
71 // Strip global ctors init, .preinit_array and main caller.
72 } else if (last && (0 == internal_strcmp(last, "__do_global_ctors_aux") ||
73 0 == internal_strcmp(last, "__libc_csu_init") ||
74 0 == internal_strcmp(last, "__libc_start_main"))) {
7375 last_frame->ClearAll();
7476 last_frame2->next = nullptr;
7577 // If both are 0, then we probably just failed to symbolize.
......@@ -120,7 +122,7 @@ static ReportStack *SymbolizeStack(StackTrace trace) {
120122 }
121123 StackStripMain(top);
122124
123 ReportStack *stack = ReportStack::New();
125 auto *stack = New<ReportStack>();
124126 stack->frames = top;
125127 return stack;
126128}
......@@ -132,7 +134,7 @@ bool ShouldReport(ThreadState *thr, ReportType typ) {
132134 CheckedMutex::CheckNoLocks();
133135 // For the same reason check we didn't lock thread_registry yet.
134136 if (SANITIZER_DEBUG)
135 ThreadRegistryLock l(ctx->thread_registry);
137 ThreadRegistryLock l(&ctx->thread_registry);
136138 if (!flags()->report_bugs || thr->suppress_reports)
137139 return false;
138140 switch (typ) {
......@@ -154,9 +156,8 @@ bool ShouldReport(ThreadState *thr, ReportType typ) {
154156}
155157
156158ScopedReportBase::ScopedReportBase(ReportType typ, uptr tag) {
157 ctx->thread_registry->CheckLocked();
158 void *mem = internal_alloc(MBlockReport, sizeof(ReportDesc));
159 rep_ = new(mem) ReportDesc;
159 ctx->thread_registry.CheckLocked();
160 rep_ = New<ReportDesc>();
160161 rep_->typ = typ;
161162 rep_->tag = tag;
162163 ctx->report_mtx.Lock();
......@@ -165,7 +166,6 @@ ScopedReportBase::ScopedReportBase(ReportType typ, uptr tag) {
165166ScopedReportBase::~ScopedReportBase() {
166167 ctx->report_mtx.Unlock();
167168 DestroyAndFree(rep_);
168 rep_ = nullptr;
169169}
170170
171171void ScopedReportBase::AddStack(StackTrace stack, bool suppressable) {
......@@ -175,28 +175,31 @@ void ScopedReportBase::AddStack(StackTrace stack, bool suppressable) {
175175}
176176
177177void ScopedReportBase::AddMemoryAccess(uptr addr, uptr external_tag, Shadow s,
178 StackTrace stack, const MutexSet *mset) {
179 void *mem = internal_alloc(MBlockReportMop, sizeof(ReportMop));
180 ReportMop *mop = new(mem) ReportMop;
178 Tid tid, StackTrace stack,
179 const MutexSet *mset) {
180 uptr addr0, size;
181 AccessType typ;
182 s.GetAccess(&addr0, &size, &typ);
183 auto *mop = New<ReportMop>();
181184 rep_->mops.PushBack(mop);
182 mop->tid = s.tid();
183 mop->addr = addr + s.addr0();
184 mop->size = s.size();
185 mop->write = s.IsWrite();
186 mop->atomic = s.IsAtomic();
185 mop->tid = tid;
186 mop->addr = addr + addr0;
187 mop->size = size;
188 mop->write = !(typ & kAccessRead);
189 mop->atomic = typ & kAccessAtomic;
187190 mop->stack = SymbolizeStack(stack);
188191 mop->external_tag = external_tag;
189192 if (mop->stack)
190193 mop->stack->suppressable = true;
191194 for (uptr i = 0; i < mset->Size(); i++) {
192195 MutexSet::Desc d = mset->Get(i);
193 u64 mid = this->AddMutex(d.id);
194 ReportMopMutex mtx = {mid, d.write};
196 int id = this->AddMutex(d.addr, d.stack_id);
197 ReportMopMutex mtx = {id, d.write};
195198 mop->mset.PushBack(mtx);
196199 }
197200}
198201
199void ScopedReportBase::AddUniqueTid(int unique_tid) {
202void ScopedReportBase::AddUniqueTid(Tid unique_tid) {
200203 rep_->unique_tids.PushBack(unique_tid);
201204}
202205
......@@ -205,8 +208,7 @@ void ScopedReportBase::AddThread(const ThreadContext *tctx, bool suppressable) {
205208 if ((u32)rep_->threads[i]->id == tctx->tid)
206209 return;
207210 }
208 void *mem = internal_alloc(MBlockReportThread, sizeof(ReportThread));
209 ReportThread *rt = new(mem) ReportThread;
211 auto *rt = New<ReportThread>();
210212 rep_->threads.PushBack(rt);
211213 rt->id = tctx->tid;
212214 rt->os_id = tctx->os_id;
......@@ -221,22 +223,10 @@ void ScopedReportBase::AddThread(const ThreadContext *tctx, bool suppressable) {
221223}
222224
223225#if !SANITIZER_GO
224static bool FindThreadByUidLockedCallback(ThreadContextBase *tctx, void *arg) {
225 int unique_id = *(int *)arg;
226 return tctx->unique_id == (u32)unique_id;
227}
228
229static ThreadContext *FindThreadByUidLocked(int unique_id) {
230 ctx->thread_registry->CheckLocked();
226static ThreadContext *FindThreadByTidLocked(Tid tid) {
227 ctx->thread_registry.CheckLocked();
231228 return static_cast<ThreadContext *>(
232 ctx->thread_registry->FindThreadContextLocked(
233 FindThreadByUidLockedCallback, &unique_id));
234}
235
236static ThreadContext *FindThreadByTidLocked(int tid) {
237 ctx->thread_registry->CheckLocked();
238 return static_cast<ThreadContext*>(
239 ctx->thread_registry->GetThreadLocked(tid));
229 ctx->thread_registry.GetThreadLocked(tid));
240230}
241231
242232static bool IsInStackOrTls(ThreadContextBase *tctx_base, void *arg) {
......@@ -251,10 +241,10 @@ static bool IsInStackOrTls(ThreadContextBase *tctx_base, void *arg) {
251241}
252242
253243ThreadContext *IsThreadStackOrTls(uptr addr, bool *is_stack) {
254 ctx->thread_registry->CheckLocked();
255 ThreadContext *tctx = static_cast<ThreadContext*>(
256 ctx->thread_registry->FindThreadContextLocked(IsInStackOrTls,
257 (void*)addr));
244 ctx->thread_registry.CheckLocked();
245 ThreadContext *tctx =
246 static_cast<ThreadContext *>(ctx->thread_registry.FindThreadContextLocked(
247 IsInStackOrTls, (void *)addr));
258248 if (!tctx)
259249 return 0;
260250 ThreadState *thr = tctx->thr;
......@@ -264,58 +254,24 @@ ThreadContext *IsThreadStackOrTls(uptr addr, bool *is_stack) {
264254}
265255#endif
266256
267void ScopedReportBase::AddThread(int unique_tid, bool suppressable) {
257void ScopedReportBase::AddThread(Tid tid, bool suppressable) {
268258#if !SANITIZER_GO
269 if (const ThreadContext *tctx = FindThreadByUidLocked(unique_tid))
259 if (const ThreadContext *tctx = FindThreadByTidLocked(tid))
270260 AddThread(tctx, suppressable);
271261#endif
272262}
273263
274void ScopedReportBase::AddMutex(const SyncVar *s) {
275 for (uptr i = 0; i < rep_->mutexes.Size(); i++) {
276 if (rep_->mutexes[i]->id == s->uid)
277 return;
278 }
279 void *mem = internal_alloc(MBlockReportMutex, sizeof(ReportMutex));
280 ReportMutex *rm = new(mem) ReportMutex;
281 rep_->mutexes.PushBack(rm);
282 rm->id = s->uid;
283 rm->addr = s->addr;
284 rm->destroyed = false;
285 rm->stack = SymbolizeStackId(s->creation_stack_id);
286}
287
288u64 ScopedReportBase::AddMutex(u64 id) NO_THREAD_SAFETY_ANALYSIS {
289 u64 uid = 0;
290 u64 mid = id;
291 uptr addr = SyncVar::SplitId(id, &uid);
292 SyncVar *s = ctx->metamap.GetIfExistsAndLock(addr, true);
293 // Check that the mutex is still alive.
294 // Another mutex can be created at the same address,
295 // so check uid as well.
296 if (s && s->CheckId(uid)) {
297 mid = s->uid;
298 AddMutex(s);
299 } else {
300 AddDeadMutex(id);
301 }
302 if (s)
303 s->mtx.Unlock();
304 return mid;
305}
306
307void ScopedReportBase::AddDeadMutex(u64 id) {
264int ScopedReportBase::AddMutex(uptr addr, StackID creation_stack_id) {
308265 for (uptr i = 0; i < rep_->mutexes.Size(); i++) {
309 if (rep_->mutexes[i]->id == id)
310 return;
266 if (rep_->mutexes[i]->addr == addr)
267 return rep_->mutexes[i]->id;
311268 }
312 void *mem = internal_alloc(MBlockReportMutex, sizeof(ReportMutex));
313 ReportMutex *rm = new(mem) ReportMutex;
269 auto *rm = New<ReportMutex>();
314270 rep_->mutexes.PushBack(rm);
315 rm->id = id;
316 rm->addr = 0;
317 rm->destroyed = true;
318 rm->stack = 0;
271 rm->id = rep_->mutexes.Size() - 1;
272 rm->addr = addr;
273 rm->stack = SymbolizeStackId(creation_stack_id);
274 return rm->id;
319275}
320276
321277void ScopedReportBase::AddLocation(uptr addr, uptr size) {
......@@ -323,43 +279,46 @@ void ScopedReportBase::AddLocation(uptr addr, uptr size) {
323279 return;
324280#if !SANITIZER_GO
325281 int fd = -1;
326 int creat_tid = kInvalidTid;
327 u32 creat_stack = 0;
328 if (FdLocation(addr, &fd, &creat_tid, &creat_stack)) {
329 ReportLocation *loc = ReportLocation::New(ReportLocationFD);
282 Tid creat_tid = kInvalidTid;
283 StackID creat_stack = 0;
284 bool closed = false;
285 if (FdLocation(addr, &fd, &creat_tid, &creat_stack, &closed)) {
286 auto *loc = New<ReportLocation>();
287 loc->type = ReportLocationFD;
288 loc->fd_closed = closed;
330289 loc->fd = fd;
331290 loc->tid = creat_tid;
332291 loc->stack = SymbolizeStackId(creat_stack);
333292 rep_->locs.PushBack(loc);
334 ThreadContext *tctx = FindThreadByUidLocked(creat_tid);
335 if (tctx)
336 AddThread(tctx);
293 AddThread(creat_tid);
337294 return;
338295 }
339296 MBlock *b = 0;
297 uptr block_begin = 0;
340298 Allocator *a = allocator();
341299 if (a->PointerIsMine((void*)addr)) {
342 void *block_begin = a->GetBlockBegin((void*)addr);
300 block_begin = (uptr)a->GetBlockBegin((void *)addr);
343301 if (block_begin)
344 b = ctx->metamap.GetBlock((uptr)block_begin);
302 b = ctx->metamap.GetBlock(block_begin);
345303 }
304 if (!b)
305 b = JavaHeapBlock(addr, &block_begin);
346306 if (b != 0) {
347 ThreadContext *tctx = FindThreadByTidLocked(b->tid);
348 ReportLocation *loc = ReportLocation::New(ReportLocationHeap);
349 loc->heap_chunk_start = (uptr)allocator()->GetBlockBegin((void *)addr);
307 auto *loc = New<ReportLocation>();
308 loc->type = ReportLocationHeap;
309 loc->heap_chunk_start = block_begin;
350310 loc->heap_chunk_size = b->siz;
351311 loc->external_tag = b->tag;
352 loc->tid = tctx ? tctx->tid : b->tid;
312 loc->tid = b->tid;
353313 loc->stack = SymbolizeStackId(b->stk);
354314 rep_->locs.PushBack(loc);
355 if (tctx)
356 AddThread(tctx);
315 AddThread(b->tid);
357316 return;
358317 }
359318 bool is_stack = false;
360319 if (ThreadContext *tctx = IsThreadStackOrTls(addr, &is_stack)) {
361 ReportLocation *loc =
362 ReportLocation::New(is_stack ? ReportLocationStack : ReportLocationTLS);
320 auto *loc = New<ReportLocation>();
321 loc->type = is_stack ? ReportLocationStack : ReportLocationTLS;
363322 loc->tid = tctx->tid;
364323 rep_->locs.PushBack(loc);
365324 AddThread(tctx);
......@@ -373,13 +332,15 @@ void ScopedReportBase::AddLocation(uptr addr, uptr size) {
373332}
374333
375334#if !SANITIZER_GO
376void ScopedReportBase::AddSleep(u32 stack_id) {
335void ScopedReportBase::AddSleep(StackID stack_id) {
377336 rep_->sleep = SymbolizeStackId(stack_id);
378337}
379338#endif
380339
381340void ScopedReportBase::SetCount(int count) { rep_->count = count; }
382341
342void ScopedReportBase::SetSigNum(int sig) { rep_->signum = sig; }
343
383344const ReportDesc *ScopedReportBase::GetReport() const { return rep_; }
384345
385346ScopedReport::ScopedReport(ReportType typ, uptr tag)
......@@ -387,67 +348,256 @@ ScopedReport::ScopedReport(ReportType typ, uptr tag)
387348
388349ScopedReport::~ScopedReport() {}
389350
390void RestoreStack(int tid, const u64 epoch, VarSizeStackTrace *stk,
391 MutexSet *mset, uptr *tag) {
351// Replays the trace up to last_pos position in the last part
352// or up to the provided epoch/sid (whichever is earlier)
353// and calls the provided function f for each event.
354template <typename Func>
355void TraceReplay(Trace *trace, TracePart *last, Event *last_pos, Sid sid,
356 Epoch epoch, Func f) {
357 TracePart *part = trace->parts.Front();
358 Sid ev_sid = kFreeSid;
359 Epoch ev_epoch = kEpochOver;
360 for (;;) {
361 DCHECK_EQ(part->trace, trace);
362 // Note: an event can't start in the last element.
363 // Since an event can take up to 2 elements,
364 // we ensure we have at least 2 before adding an event.
365 Event *end = &part->events[TracePart::kSize - 1];
366 if (part == last)
367 end = last_pos;
368 f(kFreeSid, kEpochOver, nullptr); // notify about part start
369 for (Event *evp = &part->events[0]; evp < end; evp++) {
370 Event *evp0 = evp;
371 if (!evp->is_access && !evp->is_func) {
372 switch (evp->type) {
373 case EventType::kTime: {
374 auto *ev = reinterpret_cast<EventTime *>(evp);
375 ev_sid = static_cast<Sid>(ev->sid);
376 ev_epoch = static_cast<Epoch>(ev->epoch);
377 if (ev_sid == sid && ev_epoch > epoch)
378 return;
379 break;
380 }
381 case EventType::kAccessExt:
382 FALLTHROUGH;
383 case EventType::kAccessRange:
384 FALLTHROUGH;
385 case EventType::kLock:
386 FALLTHROUGH;
387 case EventType::kRLock:
388 // These take 2 Event elements.
389 evp++;
390 break;
391 case EventType::kUnlock:
392 // This takes 1 Event element.
393 break;
394 }
395 }
396 CHECK_NE(ev_sid, kFreeSid);
397 CHECK_NE(ev_epoch, kEpochOver);
398 f(ev_sid, ev_epoch, evp0);
399 }
400 if (part == last)
401 return;
402 part = trace->parts.Next(part);
403 CHECK(part);
404 }
405 CHECK(0);
406}
407
408static void RestoreStackMatch(VarSizeStackTrace *pstk, MutexSet *pmset,
409 Vector<uptr> *stack, MutexSet *mset, uptr pc,
410 bool *found) {
411 DPrintf2(" MATCHED\n");
412 *pmset = *mset;
413 stack->PushBack(pc);
414 pstk->Init(&(*stack)[0], stack->Size());
415 stack->PopBack();
416 *found = true;
417}
418
419// Checks if addr1|size1 is fully contained in addr2|size2.
420// We check for fully contained instread of just overlapping
421// because a memory access is always traced once, but can be
422// split into multiple accesses in the shadow.
423static constexpr bool IsWithinAccess(uptr addr1, uptr size1, uptr addr2,
424 uptr size2) {
425 return addr1 >= addr2 && addr1 + size1 <= addr2 + size2;
426}
427
428// Replays the trace of slot sid up to the target event identified
429// by epoch/addr/size/typ and restores and returns tid, stack, mutex set
430// and tag for that event. If there are multiple such events, it returns
431// the last one. Returns false if the event is not present in the trace.
432bool RestoreStack(EventType type, Sid sid, Epoch epoch, uptr addr, uptr size,
433 AccessType typ, Tid *ptid, VarSizeStackTrace *pstk,
434 MutexSet *pmset, uptr *ptag) {
392435 // This function restores stack trace and mutex set for the thread/epoch.
393436 // It does so by getting stack trace and mutex set at the beginning of
394437 // trace part, and then replaying the trace till the given epoch.
395 Trace* trace = ThreadTrace(tid);
396 ReadLock l(&trace->mtx);
397 const int partidx = (epoch / kTracePartSize) % TraceParts();
398 TraceHeader* hdr = &trace->headers[partidx];
399 if (epoch < hdr->epoch0 || epoch >= hdr->epoch0 + kTracePartSize)
400 return;
401 CHECK_EQ(RoundDown(epoch, kTracePartSize), hdr->epoch0);
402 const u64 epoch0 = RoundDown(epoch, TraceSize());
403 const u64 eend = epoch % TraceSize();
404 const u64 ebegin = RoundDown(eend, kTracePartSize);
405 DPrintf("#%d: RestoreStack epoch=%zu ebegin=%zu eend=%zu partidx=%d\n",
406 tid, (uptr)epoch, (uptr)ebegin, (uptr)eend, partidx);
407 Vector<uptr> stack;
408 stack.Resize(hdr->stack0.size + 64);
409 for (uptr i = 0; i < hdr->stack0.size; i++) {
410 stack[i] = hdr->stack0.trace[i];
411 DPrintf2(" #%02zu: pc=%zx\n", i, stack[i]);
412 }
413 if (mset)
414 *mset = hdr->mset0;
415 uptr pos = hdr->stack0.size;
416 Event *events = (Event*)GetThreadTrace(tid);
417 for (uptr i = ebegin; i <= eend; i++) {
418 Event ev = events[i];
419 EventType typ = (EventType)(ev >> kEventPCBits);
420 uptr pc = (uptr)(ev & ((1ull << kEventPCBits) - 1));
421 DPrintf2(" %zu typ=%d pc=%zx\n", i, typ, pc);
422 if (typ == EventTypeMop) {
423 stack[pos] = pc;
424 } else if (typ == EventTypeFuncEnter) {
425 if (stack.Size() < pos + 2)
426 stack.Resize(pos + 2);
427 stack[pos++] = pc;
428 } else if (typ == EventTypeFuncExit) {
429 if (pos > 0)
430 pos--;
438 DPrintf2("RestoreStack: sid=%u@%u addr=0x%zx/%zu typ=%x\n",
439 static_cast<int>(sid), static_cast<int>(epoch), addr, size,
440 static_cast<int>(typ));
441 ctx->slot_mtx.CheckLocked(); // needed to prevent trace part recycling
442 ctx->thread_registry.CheckLocked();
443 TidSlot *slot = &ctx->slots[static_cast<uptr>(sid)];
444 Tid tid = kInvalidTid;
445 // Need to lock the slot mutex as it protects slot->journal.
446 slot->mtx.CheckLocked();
447 for (uptr i = 0; i < slot->journal.Size(); i++) {
448 DPrintf2(" journal: epoch=%d tid=%d\n",
449 static_cast<int>(slot->journal[i].epoch), slot->journal[i].tid);
450 if (i == slot->journal.Size() - 1 || slot->journal[i + 1].epoch > epoch) {
451 tid = slot->journal[i].tid;
452 break;
431453 }
432 if (mset) {
433 if (typ == EventTypeLock) {
434 mset->Add(pc, true, epoch0 + i);
435 } else if (typ == EventTypeUnlock) {
436 mset->Del(pc, true);
437 } else if (typ == EventTypeRLock) {
438 mset->Add(pc, false, epoch0 + i);
439 } else if (typ == EventTypeRUnlock) {
440 mset->Del(pc, false);
441 }
454 }
455 if (tid == kInvalidTid)
456 return false;
457 *ptid = tid;
458 ThreadContext *tctx =
459 static_cast<ThreadContext *>(ctx->thread_registry.GetThreadLocked(tid));
460 Trace *trace = &tctx->trace;
461 // Snapshot first/last parts and the current position in the last part.
462 TracePart *first_part;
463 TracePart *last_part;
464 Event *last_pos;
465 {
466 Lock lock(&trace->mtx);
467 first_part = trace->parts.Front();
468 if (!first_part) {
469 DPrintf2("RestoreStack: tid=%d trace=%p no trace parts\n", tid, trace);
470 return false;
442471 }
443 for (uptr j = 0; j <= pos; j++)
444 DPrintf2(" #%zu: %zx\n", j, stack[j]);
472 last_part = trace->parts.Back();
473 last_pos = trace->final_pos;
474 if (tctx->thr)
475 last_pos = (Event *)atomic_load_relaxed(&tctx->thr->trace_pos);
445476 }
446 if (pos == 0 && stack[0] == 0)
447 return;
448 pos++;
449 stk->Init(&stack[0], pos);
450 ExtractTagFromStack(stk, tag);
477 DynamicMutexSet mset;
478 Vector<uptr> stack;
479 uptr prev_pc = 0;
480 bool found = false;
481 bool is_read = typ & kAccessRead;
482 bool is_atomic = typ & kAccessAtomic;
483 bool is_free = typ & kAccessFree;
484 DPrintf2("RestoreStack: tid=%d parts=[%p-%p] last_pos=%p\n", tid,
485 trace->parts.Front(), last_part, last_pos);
486 TraceReplay(
487 trace, last_part, last_pos, sid, epoch,
488 [&](Sid ev_sid, Epoch ev_epoch, Event *evp) {
489 if (evp == nullptr) {
490 // Each trace part is self-consistent, so we reset state.
491 stack.Resize(0);
492 mset->Reset();
493 prev_pc = 0;
494 return;
495 }
496 bool match = ev_sid == sid && ev_epoch == epoch;
497 if (evp->is_access) {
498 if (evp->is_func == 0 && evp->type == EventType::kAccessExt &&
499 evp->_ == 0) // NopEvent
500 return;
501 auto *ev = reinterpret_cast<EventAccess *>(evp);
502 uptr ev_addr = RestoreAddr(ev->addr);
503 uptr ev_size = 1 << ev->size_log;
504 uptr ev_pc =
505 prev_pc + ev->pc_delta - (1 << (EventAccess::kPCBits - 1));
506 prev_pc = ev_pc;
507 DPrintf2(" Access: pc=0x%zx addr=0x%zx/%zu type=%u/%u\n", ev_pc,
508 ev_addr, ev_size, ev->is_read, ev->is_atomic);
509 if (match && type == EventType::kAccessExt &&
510 IsWithinAccess(addr, size, ev_addr, ev_size) &&
511 is_read == ev->is_read && is_atomic == ev->is_atomic && !is_free)
512 RestoreStackMatch(pstk, pmset, &stack, mset, ev_pc, &found);
513 return;
514 }
515 if (evp->is_func) {
516 auto *ev = reinterpret_cast<EventFunc *>(evp);
517 if (ev->pc) {
518 DPrintf2(" FuncEnter: pc=0x%llx\n", ev->pc);
519 stack.PushBack(ev->pc);
520 } else {
521 DPrintf2(" FuncExit\n");
522 // We don't log pathologically large stacks in each part,
523 // if the stack was truncated we can have more func exits than
524 // entries.
525 if (stack.Size())
526 stack.PopBack();
527 }
528 return;
529 }
530 switch (evp->type) {
531 case EventType::kAccessExt: {
532 auto *ev = reinterpret_cast<EventAccessExt *>(evp);
533 uptr ev_addr = RestoreAddr(ev->addr);
534 uptr ev_size = 1 << ev->size_log;
535 prev_pc = ev->pc;
536 DPrintf2(" AccessExt: pc=0x%llx addr=0x%zx/%zu type=%u/%u\n",
537 ev->pc, ev_addr, ev_size, ev->is_read, ev->is_atomic);
538 if (match && type == EventType::kAccessExt &&
539 IsWithinAccess(addr, size, ev_addr, ev_size) &&
540 is_read == ev->is_read && is_atomic == ev->is_atomic &&
541 !is_free)
542 RestoreStackMatch(pstk, pmset, &stack, mset, ev->pc, &found);
543 break;
544 }
545 case EventType::kAccessRange: {
546 auto *ev = reinterpret_cast<EventAccessRange *>(evp);
547 uptr ev_addr = RestoreAddr(ev->addr);
548 uptr ev_size =
549 (ev->size_hi << EventAccessRange::kSizeLoBits) + ev->size_lo;
550 uptr ev_pc = RestoreAddr(ev->pc);
551 prev_pc = ev_pc;
552 DPrintf2(" Range: pc=0x%zx addr=0x%zx/%zu type=%u/%u\n", ev_pc,
553 ev_addr, ev_size, ev->is_read, ev->is_free);
554 if (match && type == EventType::kAccessExt &&
555 IsWithinAccess(addr, size, ev_addr, ev_size) &&
556 is_read == ev->is_read && !is_atomic && is_free == ev->is_free)
557 RestoreStackMatch(pstk, pmset, &stack, mset, ev_pc, &found);
558 break;
559 }
560 case EventType::kLock:
561 FALLTHROUGH;
562 case EventType::kRLock: {
563 auto *ev = reinterpret_cast<EventLock *>(evp);
564 bool is_write = ev->type == EventType::kLock;
565 uptr ev_addr = RestoreAddr(ev->addr);
566 uptr ev_pc = RestoreAddr(ev->pc);
567 StackID stack_id =
568 (ev->stack_hi << EventLock::kStackIDLoBits) + ev->stack_lo;
569 DPrintf2(" Lock: pc=0x%zx addr=0x%zx stack=%u write=%d\n", ev_pc,
570 ev_addr, stack_id, is_write);
571 mset->AddAddr(ev_addr, stack_id, is_write);
572 // Events with ev_pc == 0 are written to the beginning of trace
573 // part as initial mutex set (are not real).
574 if (match && type == EventType::kLock && addr == ev_addr && ev_pc)
575 RestoreStackMatch(pstk, pmset, &stack, mset, ev_pc, &found);
576 break;
577 }
578 case EventType::kUnlock: {
579 auto *ev = reinterpret_cast<EventUnlock *>(evp);
580 uptr ev_addr = RestoreAddr(ev->addr);
581 DPrintf2(" Unlock: addr=0x%zx\n", ev_addr);
582 mset->DelAddr(ev_addr);
583 break;
584 }
585 case EventType::kTime:
586 // TraceReplay already extracted sid/epoch from it,
587 // nothing else to do here.
588 break;
589 }
590 });
591 ExtractTagFromStack(pstk, ptag);
592 return found;
593}
594
595bool RacyStacks::operator==(const RacyStacks &other) const {
596 if (hash[0] == other.hash[0] && hash[1] == other.hash[1])
597 return true;
598 if (hash[0] == other.hash[1] && hash[1] == other.hash[0])
599 return true;
600 return false;
451601}
452602
453603static bool FindRacyStacks(const RacyStacks &hash) {
......@@ -478,35 +628,6 @@ static bool HandleRacyStacks(ThreadState *thr, VarSizeStackTrace traces[2]) {
478628 return false;
479629}
480630
481static bool FindRacyAddress(const RacyAddress &ra0) {
482 for (uptr i = 0; i < ctx->racy_addresses.Size(); i++) {
483 RacyAddress ra2 = ctx->racy_addresses[i];
484 uptr maxbeg = max(ra0.addr_min, ra2.addr_min);
485 uptr minend = min(ra0.addr_max, ra2.addr_max);
486 if (maxbeg < minend) {
487 VPrintf(2, "ThreadSanitizer: suppressing report as doubled (addr)\n");
488 return true;
489 }
490 }
491 return false;
492}
493
494static bool HandleRacyAddress(ThreadState *thr, uptr addr_min, uptr addr_max) {
495 if (!flags()->suppress_equal_addresses)
496 return false;
497 RacyAddress ra0 = {addr_min, addr_max};
498 {
499 ReadLock lock(&ctx->racy_mtx);
500 if (FindRacyAddress(ra0))
501 return true;
502 }
503 Lock lock(&ctx->racy_mtx);
504 if (FindRacyAddress(ra0))
505 return true;
506 ctx->racy_addresses.PushBack(ra0);
507 return false;
508}
509
510631bool OutputReport(ThreadState *thr, const ScopedReport &srep) {
511632 // These should have been checked in ShouldReport.
512633 // It's too late to check them here, we have already taken locks.
......@@ -532,10 +653,7 @@ bool OutputReport(ThreadState *thr, const ScopedReport &srep) {
532653 ctx->fired_suppressions.push_back(s);
533654 }
534655 {
535 bool old_is_freeing = thr->is_freeing;
536 thr->is_freeing = false;
537656 bool suppressed = OnReport(rep, pc_or_addr != 0);
538 thr->is_freeing = old_is_freeing;
539657 if (suppressed) {
540658 thr->current_report = nullptr;
541659 return false;
......@@ -582,101 +700,81 @@ static bool IsFiredSuppression(Context *ctx, ReportType type, uptr addr) {
582700 return false;
583701}
584702
585static bool RaceBetweenAtomicAndFree(ThreadState *thr) {
586 Shadow s0(thr->racy_state[0]);
587 Shadow s1(thr->racy_state[1]);
588 CHECK(!(s0.IsAtomic() && s1.IsAtomic()));
589 if (!s0.IsAtomic() && !s1.IsAtomic())
590 return true;
591 if (s0.IsAtomic() && s1.IsFreed())
592 return true;
593 if (s1.IsAtomic() && thr->is_freeing)
594 return true;
595 return false;
703static bool SpuriousRace(Shadow old) {
704 Shadow last(LoadShadow(&ctx->last_spurious_race));
705 return last.sid() == old.sid() && last.epoch() == old.epoch();
596706}
597707
598void ReportRace(ThreadState *thr) {
708void ReportRace(ThreadState *thr, RawShadow *shadow_mem, Shadow cur, Shadow old,
709 AccessType typ0) {
599710 CheckedMutex::CheckNoLocks();
600711
601712 // Symbolizer makes lots of intercepted calls. If we try to process them,
602713 // at best it will cause deadlocks on internal mutexes.
603714 ScopedIgnoreInterceptors ignore;
604715
716 uptr addr = ShadowToMem(shadow_mem);
717 DPrintf("#%d: ReportRace %p\n", thr->tid, (void *)addr);
605718 if (!ShouldReport(thr, ReportTypeRace))
606719 return;
607 if (!flags()->report_atomic_races && !RaceBetweenAtomicAndFree(thr))
720 uptr addr_off0, size0;
721 cur.GetAccess(&addr_off0, &size0, nullptr);
722 uptr addr_off1, size1, typ1;
723 old.GetAccess(&addr_off1, &size1, &typ1);
724 if (!flags()->report_atomic_races &&
725 ((typ0 & kAccessAtomic) || (typ1 & kAccessAtomic)) &&
726 !(typ0 & kAccessFree) && !(typ1 & kAccessFree))
727 return;
728 if (SpuriousRace(old))
608729 return;
609730
610 bool freed = false;
611 {
612 Shadow s(thr->racy_state[1]);
613 freed = s.GetFreedAndReset();
614 thr->racy_state[1] = s.raw();
615 }
616
617 uptr addr = ShadowToMem((uptr)thr->racy_shadow_addr);
618 uptr addr_min = 0;
619 uptr addr_max = 0;
620 {
621 uptr a0 = addr + Shadow(thr->racy_state[0]).addr0();
622 uptr a1 = addr + Shadow(thr->racy_state[1]).addr0();
623 uptr e0 = a0 + Shadow(thr->racy_state[0]).size();
624 uptr e1 = a1 + Shadow(thr->racy_state[1]).size();
625 addr_min = min(a0, a1);
626 addr_max = max(e0, e1);
627 if (IsExpectedReport(addr_min, addr_max - addr_min))
628 return;
629 }
630 if (HandleRacyAddress(thr, addr_min, addr_max))
731 const uptr kMop = 2;
732 Shadow s[kMop] = {cur, old};
733 uptr addr0 = addr + addr_off0;
734 uptr addr1 = addr + addr_off1;
735 uptr end0 = addr0 + size0;
736 uptr end1 = addr1 + size1;
737 uptr addr_min = min(addr0, addr1);
738 uptr addr_max = max(end0, end1);
739 if (IsExpectedReport(addr_min, addr_max - addr_min))
631740 return;
632741
633 ReportType typ = ReportTypeRace;
634 if (thr->is_vptr_access && freed)
635 typ = ReportTypeVptrUseAfterFree;
636 else if (thr->is_vptr_access)
637 typ = ReportTypeVptrRace;
638 else if (freed)
639 typ = ReportTypeUseAfterFree;
742 ReportType rep_typ = ReportTypeRace;
743 if ((typ0 & kAccessVptr) && (typ1 & kAccessFree))
744 rep_typ = ReportTypeVptrUseAfterFree;
745 else if (typ0 & kAccessVptr)
746 rep_typ = ReportTypeVptrRace;
747 else if (typ1 & kAccessFree)
748 rep_typ = ReportTypeUseAfterFree;
640749
641 if (IsFiredSuppression(ctx, typ, addr))
750 if (IsFiredSuppression(ctx, rep_typ, addr))
642751 return;
643752
644 const uptr kMop = 2;
645753 VarSizeStackTrace traces[kMop];
646 uptr tags[kMop] = {kExternalTagNone};
647 uptr toppc = TraceTopPC(thr);
648 if (toppc >> kEventPCBits) {
649 // This is a work-around for a known issue.
650 // The scenario where this happens is rather elaborate and requires
651 // an instrumented __sanitizer_report_error_summary callback and
652 // a __tsan_symbolize_external callback and a race during a range memory
653 // access larger than 8 bytes. MemoryAccessRange adds the current PC to
654 // the trace and starts processing memory accesses. A first memory access
655 // triggers a race, we report it and call the instrumented
656 // __sanitizer_report_error_summary, which adds more stuff to the trace
657 // since it is intrumented. Then a second memory access in MemoryAccessRange
658 // also triggers a race and we get here and call TraceTopPC to get the
659 // current PC, however now it contains some unrelated events from the
660 // callback. Most likely, TraceTopPC will now return a EventTypeFuncExit
661 // event. Later we subtract -1 from it (in GetPreviousInstructionPc)
662 // and the resulting PC has kExternalPCBit set, so we pass it to
663 // __tsan_symbolize_external_ex. __tsan_symbolize_external_ex is within its
664 // rights to crash since the PC is completely bogus.
665 // test/tsan/double_race.cpp contains a test case for this.
666 toppc = 0;
667 }
668 ObtainCurrentStack(thr, toppc, &traces[0], &tags[0]);
669 if (IsFiredSuppression(ctx, typ, traces[0]))
754 Tid tids[kMop] = {thr->tid, kInvalidTid};
755 uptr tags[kMop] = {kExternalTagNone, kExternalTagNone};
756
757 ObtainCurrentStack(thr, thr->trace_prev_pc, &traces[0], &tags[0]);
758 if (IsFiredSuppression(ctx, rep_typ, traces[0]))
670759 return;
671760
672 // MutexSet is too large to live on stack.
673 Vector<u64> mset_buffer;
674 mset_buffer.Resize(sizeof(MutexSet) / sizeof(u64) + 1);
675 MutexSet *mset2 = new(&mset_buffer[0]) MutexSet();
761 DynamicMutexSet mset1;
762 MutexSet *mset[kMop] = {&thr->mset, mset1};
676763
677 Shadow s2(thr->racy_state[1]);
678 RestoreStack(s2.tid(), s2.epoch(), &traces[1], mset2, &tags[1]);
679 if (IsFiredSuppression(ctx, typ, traces[1]))
764 // We need to lock the slot during RestoreStack because it protects
765 // the slot journal.
766 Lock slot_lock(&ctx->slots[static_cast<uptr>(s[1].sid())].mtx);
767 ThreadRegistryLock l0(&ctx->thread_registry);
768 Lock slots_lock(&ctx->slot_mtx);
769 if (SpuriousRace(old))
770 return;
771 if (!RestoreStack(EventType::kAccessExt, s[1].sid(), s[1].epoch(), addr1,
772 size1, typ1, &tids[1], &traces[1], mset[1], &tags[1])) {
773 StoreShadow(&ctx->last_spurious_race, old.raw());
774 return;
775 }
776
777 if (IsFiredSuppression(ctx, rep_typ, traces[1]))
680778 return;
681779
682780 if (HandleRacyStacks(thr, traces))
......@@ -686,39 +784,41 @@ void ReportRace(ThreadState *thr) {
686784 uptr tag = kExternalTagNone;
687785 for (uptr i = 0; i < kMop; i++) {
688786 if (tags[i] != kExternalTagNone) {
689 typ = ReportTypeExternalRace;
787 rep_typ = ReportTypeExternalRace;
690788 tag = tags[i];
691789 break;
692790 }
693791 }
694792
695 ThreadRegistryLock l0(ctx->thread_registry);
696 ScopedReport rep(typ, tag);
697 for (uptr i = 0; i < kMop; i++) {
698 Shadow s(thr->racy_state[i]);
699 rep.AddMemoryAccess(addr, tags[i], s, traces[i],
700 i == 0 ? &thr->mset : mset2);
701 }
793 ScopedReport rep(rep_typ, tag);
794 for (uptr i = 0; i < kMop; i++)
795 rep.AddMemoryAccess(addr, tags[i], s[i], tids[i], traces[i], mset[i]);
702796
703797 for (uptr i = 0; i < kMop; i++) {
704 FastState s(thr->racy_state[i]);
705 ThreadContext *tctx = static_cast<ThreadContext*>(
706 ctx->thread_registry->GetThreadLocked(s.tid()));
707 if (s.epoch() < tctx->epoch0 || s.epoch() > tctx->epoch1)
708 continue;
798 ThreadContext *tctx = static_cast<ThreadContext *>(
799 ctx->thread_registry.GetThreadLocked(tids[i]));
709800 rep.AddThread(tctx);
710801 }
711802
712803 rep.AddLocation(addr_min, addr_max - addr_min);
713804
714#if !SANITIZER_GO
715 {
716 Shadow s(thr->racy_state[1]);
717 if (s.epoch() <= thr->last_sleep_clock.get(s.tid()))
718 rep.AddSleep(thr->last_sleep_stack_id);
805 if (flags()->print_full_thread_history) {
806 const ReportDesc *rep_desc = rep.GetReport();
807 for (uptr i = 0; i < rep_desc->threads.Size(); i++) {
808 Tid parent_tid = rep_desc->threads[i]->parent_tid;
809 if (parent_tid == kMainTid || parent_tid == kInvalidTid)
810 continue;
811 ThreadContext *parent_tctx = static_cast<ThreadContext *>(
812 ctx->thread_registry.GetThreadLocked(parent_tid));
813 rep.AddThread(parent_tctx);
814 }
719815 }
720#endif
721816
817#if !SANITIZER_GO
818 if (!((typ0 | typ1) & kAccessFree) &&
819 s[1].epoch() <= thr->last_sleep_clock.Get(s[1].sid()))
820 rep.AddSleep(thr->last_sleep_stack_id);
821#endif
722822 OutputReport(thr, rep);
723823}
724824
......@@ -738,9 +838,7 @@ void PrintCurrentStack(ThreadState *thr, uptr pc) {
738838ALWAYS_INLINE USED void PrintCurrentStackSlow(uptr pc) {
739839#if !SANITIZER_GO
740840 uptr bp = GET_CURRENT_FRAME();
741 BufferedStackTrace *ptrace =
742 new(internal_alloc(MBlockStackTrace, sizeof(BufferedStackTrace)))
743 BufferedStackTrace();
841 auto *ptrace = New<BufferedStackTrace>();
744842 ptrace->Unwind(pc, bp, nullptr, false);
745843
746844 for (uptr i = 0; i < ptrace->size / 2; i++) {
lib/tsan/tsan_rtl_thread.cpp+185-268
......@@ -21,133 +21,14 @@ namespace __tsan {
2121
2222// ThreadContext implementation.
2323
24ThreadContext::ThreadContext(int tid)
25 : ThreadContextBase(tid)
26 , thr()
27 , sync()
28 , epoch0()
29 , epoch1() {
30}
24ThreadContext::ThreadContext(Tid tid) : ThreadContextBase(tid), thr(), sync() {}
3125
3226#if !SANITIZER_GO
3327ThreadContext::~ThreadContext() {
3428}
3529#endif
3630
37void ThreadContext::OnDead() {
38 CHECK_EQ(sync.size(), 0);
39}
40
41void ThreadContext::OnJoined(void *arg) {
42 ThreadState *caller_thr = static_cast<ThreadState *>(arg);
43 AcquireImpl(caller_thr, 0, &sync);
44 sync.Reset(&caller_thr->proc()->clock_cache);
45}
46
47struct OnCreatedArgs {
48 ThreadState *thr;
49 uptr pc;
50};
51
52void ThreadContext::OnCreated(void *arg) {
53 thr = 0;
54 if (tid == kMainTid)
55 return;
56 OnCreatedArgs *args = static_cast<OnCreatedArgs *>(arg);
57 if (!args->thr) // GCD workers don't have a parent thread.
58 return;
59 args->thr->fast_state.IncrementEpoch();
60 // Can't increment epoch w/o writing to the trace as well.
61 TraceAddEvent(args->thr, args->thr->fast_state, EventTypeMop, 0);
62 ReleaseImpl(args->thr, 0, &sync);
63 creation_stack_id = CurrentStackId(args->thr, args->pc);
64}
65
66void ThreadContext::OnReset() {
67 CHECK_EQ(sync.size(), 0);
68 uptr trace_p = GetThreadTrace(tid);
69 ReleaseMemoryPagesToOS(trace_p, trace_p + TraceSize() * sizeof(Event));
70 //!!! ReleaseMemoryToOS(GetThreadTraceHeader(tid), sizeof(Trace));
71}
72
73void ThreadContext::OnDetached(void *arg) {
74 ThreadState *thr1 = static_cast<ThreadState*>(arg);
75 sync.Reset(&thr1->proc()->clock_cache);
76}
77
78struct OnStartedArgs {
79 ThreadState *thr;
80 uptr stk_addr;
81 uptr stk_size;
82 uptr tls_addr;
83 uptr tls_size;
84};
85
86void ThreadContext::OnStarted(void *arg) {
87 OnStartedArgs *args = static_cast<OnStartedArgs*>(arg);
88 thr = args->thr;
89 // RoundUp so that one trace part does not contain events
90 // from different threads.
91 epoch0 = RoundUp(epoch1 + 1, kTracePartSize);
92 epoch1 = (u64)-1;
93 new(thr) ThreadState(ctx, tid, unique_id, epoch0, reuse_count,
94 args->stk_addr, args->stk_size, args->tls_addr, args->tls_size);
95#if !SANITIZER_GO
96 thr->shadow_stack = &ThreadTrace(thr->tid)->shadow_stack[0];
97 thr->shadow_stack_pos = thr->shadow_stack;
98 thr->shadow_stack_end = thr->shadow_stack + kShadowStackSize;
99#else
100 // Setup dynamic shadow stack.
101 const int kInitStackSize = 8;
102 thr->shadow_stack = (uptr*)internal_alloc(MBlockShadowStack,
103 kInitStackSize * sizeof(uptr));
104 thr->shadow_stack_pos = thr->shadow_stack;
105 thr->shadow_stack_end = thr->shadow_stack + kInitStackSize;
106#endif
107 if (common_flags()->detect_deadlocks)
108 thr->dd_lt = ctx->dd->CreateLogicalThread(unique_id);
109 thr->fast_state.SetHistorySize(flags()->history_size);
110 // Commit switch to the new part of the trace.
111 // TraceAddEvent will reset stack0/mset0 in the new part for us.
112 TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
113
114 thr->fast_synch_epoch = epoch0;
115 AcquireImpl(thr, 0, &sync);
116 sync.Reset(&thr->proc()->clock_cache);
117 thr->is_inited = true;
118 DPrintf("#%d: ThreadStart epoch=%zu stk_addr=%zx stk_size=%zx "
119 "tls_addr=%zx tls_size=%zx\n",
120 tid, (uptr)epoch0, args->stk_addr, args->stk_size,
121 args->tls_addr, args->tls_size);
122}
123
124void ThreadContext::OnFinished() {
125#if SANITIZER_GO
126 internal_free(thr->shadow_stack);
127 thr->shadow_stack = nullptr;
128 thr->shadow_stack_pos = nullptr;
129 thr->shadow_stack_end = nullptr;
130#endif
131 if (!detached) {
132 thr->fast_state.IncrementEpoch();
133 // Can't increment epoch w/o writing to the trace as well.
134 TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
135 ReleaseImpl(thr, 0, &sync);
136 }
137 epoch1 = thr->fast_state.epoch();
138
139 if (common_flags()->detect_deadlocks)
140 ctx->dd->DestroyLogicalThread(thr->dd_lt);
141 thr->clock.ResetCached(&thr->proc()->clock_cache);
142#if !SANITIZER_GO
143 thr->last_sleep_clock.ResetCached(&thr->proc()->clock_cache);
144#endif
145#if !SANITIZER_GO
146 PlatformCleanUpThreadState(thr);
147#endif
148 thr->~ThreadState();
149 thr = 0;
150}
31void ThreadContext::OnReset() { CHECK(!sync); }
15132
15233#if !SANITIZER_GO
15334struct ThreadLeak {
......@@ -155,9 +36,9 @@ struct ThreadLeak {
15536 int count;
15637};
15738
158static void MaybeReportThreadLeak(ThreadContextBase *tctx_base, void *arg) {
159 Vector<ThreadLeak> &leaks = *(Vector<ThreadLeak>*)arg;
160 ThreadContext *tctx = static_cast<ThreadContext*>(tctx_base);
39static void CollectThreadLeaks(ThreadContextBase *tctx_base, void *arg) {
40 auto &leaks = *static_cast<Vector<ThreadLeak> *>(arg);
41 auto *tctx = static_cast<ThreadContext *>(tctx_base);
16142 if (tctx->detached || tctx->status != ThreadStatusFinished)
16243 return;
16344 for (uptr i = 0; i < leaks.Size(); i++) {
......@@ -166,12 +47,13 @@ static void MaybeReportThreadLeak(ThreadContextBase *tctx_base, void *arg) {
16647 return;
16748 }
16849 }
169 ThreadLeak leak = {tctx, 1};
170 leaks.PushBack(leak);
50 leaks.PushBack({tctx, 1});
17151}
17252#endif
17353
174#if !SANITIZER_GO
54// Disabled on Mac because lldb test TestTsanBasic fails:
55// https://reviews.llvm.org/D112603#3163158
56#if !SANITIZER_GO && !SANITIZER_APPLE
17557static void ReportIgnoresEnabled(ThreadContext *tctx, IgnoreSet *set) {
17658 if (tctx->tid == kMainTid) {
17759 Printf("ThreadSanitizer: main thread finished with ignores enabled\n");
......@@ -206,10 +88,10 @@ void ThreadFinalize(ThreadState *thr) {
20688#if !SANITIZER_GO
20789 if (!ShouldReport(thr, ReportTypeThreadLeak))
20890 return;
209 ThreadRegistryLock l(ctx->thread_registry);
91 ThreadRegistryLock l(&ctx->thread_registry);
21092 Vector<ThreadLeak> leaks;
211 ctx->thread_registry->RunCallbackForEachThreadLocked(
212 MaybeReportThreadLeak, &leaks);
93 ctx->thread_registry.RunCallbackForEachThreadLocked(CollectThreadLeaks,
94 &leaks);
21395 for (uptr i = 0; i < leaks.Size(); i++) {
21496 ScopedReport rep(ReportTypeThreadLeak);
21597 rep.AddThread(leaks[i].tctx, true);
......@@ -221,21 +103,63 @@ void ThreadFinalize(ThreadState *thr) {
221103
222104int ThreadCount(ThreadState *thr) {
223105 uptr result;
224 ctx->thread_registry->GetNumberOfThreads(0, 0, &result);
106 ctx->thread_registry.GetNumberOfThreads(0, 0, &result);
225107 return (int)result;
226108}
227109
228int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached) {
229 OnCreatedArgs args = { thr, pc };
230 u32 parent_tid = thr ? thr->tid : kInvalidTid; // No parent for GCD workers.
231 int tid =
232 ctx->thread_registry->CreateThread(uid, detached, parent_tid, &args);
233 DPrintf("#%d: ThreadCreate tid=%d uid=%zu\n", parent_tid, tid, uid);
110struct OnCreatedArgs {
111 VectorClock *sync;
112 uptr sync_epoch;
113 StackID stack;
114};
115
116Tid ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached) {
117 // The main thread and GCD workers don't have a parent thread.
118 Tid parent = kInvalidTid;
119 OnCreatedArgs arg = {nullptr, 0, kInvalidStackID};
120 if (thr) {
121 parent = thr->tid;
122 arg.stack = CurrentStackId(thr, pc);
123 if (!thr->ignore_sync) {
124 SlotLocker locker(thr);
125 thr->clock.ReleaseStore(&arg.sync);
126 arg.sync_epoch = ctx->global_epoch;
127 IncrementEpoch(thr);
128 }
129 }
130 Tid tid = ctx->thread_registry.CreateThread(uid, detached, parent, &arg);
131 DPrintf("#%d: ThreadCreate tid=%d uid=%zu\n", parent, tid, uid);
234132 return tid;
235133}
236134
237void ThreadStart(ThreadState *thr, int tid, tid_t os_id,
135void ThreadContext::OnCreated(void *arg) {
136 OnCreatedArgs *args = static_cast<OnCreatedArgs *>(arg);
137 sync = args->sync;
138 sync_epoch = args->sync_epoch;
139 creation_stack_id = args->stack;
140}
141
142extern "C" void __tsan_stack_initialization() {}
143
144struct OnStartedArgs {
145 ThreadState *thr;
146 uptr stk_addr;
147 uptr stk_size;
148 uptr tls_addr;
149 uptr tls_size;
150};
151
152void ThreadStart(ThreadState *thr, Tid tid, tid_t os_id,
238153 ThreadType thread_type) {
154 ctx->thread_registry.StartThread(tid, os_id, thread_type, thr);
155 if (!thr->ignore_sync) {
156 SlotAttachAndLock(thr);
157 if (thr->tctx->sync_epoch == ctx->global_epoch)
158 thr->clock.Acquire(thr->tctx->sync);
159 SlotUnlock(thr);
160 }
161 Free(thr->tctx->sync);
162
239163 uptr stk_addr = 0;
240164 uptr stk_size = 0;
241165 uptr tls_addr = 0;
......@@ -244,22 +168,11 @@ void ThreadStart(ThreadState *thr, int tid, tid_t os_id,
244168 if (thread_type != ThreadType::Fiber)
245169 GetThreadStackAndTls(tid == kMainTid, &stk_addr, &stk_size, &tls_addr,
246170 &tls_size);
247
248 if (tid != kMainTid) {
249 if (stk_addr && stk_size)
250 MemoryRangeImitateWrite(thr, /*pc=*/ 1, stk_addr, stk_size);
251
252 if (tls_addr && tls_size) ImitateTlsWrite(thr, tls_addr, tls_size);
253 }
254171#endif
255
256 ThreadRegistry *tr = ctx->thread_registry;
257 OnStartedArgs args = { thr, stk_addr, stk_size, tls_addr, tls_size };
258 tr->StartThread(tid, os_id, thread_type, &args);
259
260 tr->Lock();
261 thr->tctx = (ThreadContext*)tr->GetThreadLocked(tid);
262 tr->Unlock();
172 thr->stk_addr = stk_addr;
173 thr->stk_size = stk_size;
174 thr->tls_addr = tls_addr;
175 thr->tls_size = tls_size;
263176
264177#if !SANITIZER_GO
265178 if (ctx->after_multithreaded_fork) {
......@@ -268,16 +181,99 @@ void ThreadStart(ThreadState *thr, int tid, tid_t os_id,
268181 ThreadIgnoreSyncBegin(thr, 0);
269182 }
270183#endif
184
185#if !SANITIZER_GO
186 // Don't imitate stack/TLS writes for the main thread,
187 // because its initialization is synchronized with all
188 // subsequent threads anyway.
189 if (tid != kMainTid) {
190 if (stk_addr && stk_size) {
191 const uptr pc = StackTrace::GetNextInstructionPc(
192 reinterpret_cast<uptr>(__tsan_stack_initialization));
193 MemoryRangeImitateWrite(thr, pc, stk_addr, stk_size);
194 }
195
196 if (tls_addr && tls_size)
197 ImitateTlsWrite(thr, tls_addr, tls_size);
198 }
199#endif
200}
201
202void ThreadContext::OnStarted(void *arg) {
203 thr = static_cast<ThreadState *>(arg);
204 DPrintf("#%d: ThreadStart\n", tid);
205 new (thr) ThreadState(tid);
206 if (common_flags()->detect_deadlocks)
207 thr->dd_lt = ctx->dd->CreateLogicalThread(tid);
208 thr->tctx = this;
209#if !SANITIZER_GO
210 thr->is_inited = true;
211#endif
271212}
272213
273214void ThreadFinish(ThreadState *thr) {
215 DPrintf("#%d: ThreadFinish\n", thr->tid);
274216 ThreadCheckIgnore(thr);
275217 if (thr->stk_addr && thr->stk_size)
276218 DontNeedShadowFor(thr->stk_addr, thr->stk_size);
277219 if (thr->tls_addr && thr->tls_size)
278220 DontNeedShadowFor(thr->tls_addr, thr->tls_size);
279221 thr->is_dead = true;
280 ctx->thread_registry->FinishThread(thr->tid);
222#if !SANITIZER_GO
223 thr->is_inited = false;
224 thr->ignore_interceptors++;
225 PlatformCleanUpThreadState(thr);
226#endif
227 if (!thr->ignore_sync) {
228 SlotLocker locker(thr);
229 ThreadRegistryLock lock(&ctx->thread_registry);
230 // Note: detached is protected by the thread registry mutex,
231 // the thread may be detaching concurrently in another thread.
232 if (!thr->tctx->detached) {
233 thr->clock.ReleaseStore(&thr->tctx->sync);
234 thr->tctx->sync_epoch = ctx->global_epoch;
235 IncrementEpoch(thr);
236 }
237 }
238#if !SANITIZER_GO
239 UnmapOrDie(thr->shadow_stack, kShadowStackSize * sizeof(uptr));
240#else
241 Free(thr->shadow_stack);
242#endif
243 thr->shadow_stack = nullptr;
244 thr->shadow_stack_pos = nullptr;
245 thr->shadow_stack_end = nullptr;
246 if (common_flags()->detect_deadlocks)
247 ctx->dd->DestroyLogicalThread(thr->dd_lt);
248 SlotDetach(thr);
249 ctx->thread_registry.FinishThread(thr->tid);
250 thr->~ThreadState();
251}
252
253void ThreadContext::OnFinished() {
254 Lock lock(&ctx->slot_mtx);
255 Lock lock1(&trace.mtx);
256 // Queue all trace parts into the global recycle queue.
257 auto parts = &trace.parts;
258 while (trace.local_head) {
259 CHECK(parts->Queued(trace.local_head));
260 ctx->trace_part_recycle.PushBack(trace.local_head);
261 trace.local_head = parts->Next(trace.local_head);
262 }
263 ctx->trace_part_recycle_finished += parts->Size();
264 if (ctx->trace_part_recycle_finished > Trace::kFinishedThreadHi) {
265 ctx->trace_part_finished_excess += parts->Size();
266 trace.parts_allocated = 0;
267 } else if (ctx->trace_part_recycle_finished > Trace::kFinishedThreadLo &&
268 parts->Size() > 1) {
269 ctx->trace_part_finished_excess += parts->Size() - 1;
270 trace.parts_allocated = 1;
271 }
272 // From now on replay will use trace->final_pos.
273 trace.final_pos = (Event *)atomic_load_relaxed(&thr->trace_pos);
274 atomic_store_relaxed(&thr->trace_pos, 0);
275 thr->tctx = nullptr;
276 thr = nullptr;
281277}
282278
283279struct ConsumeThreadContext {
......@@ -285,131 +281,52 @@ struct ConsumeThreadContext {
285281 ThreadContextBase *tctx;
286282};
287283
288static bool ConsumeThreadByUid(ThreadContextBase *tctx, void *arg) {
289 ConsumeThreadContext *findCtx = (ConsumeThreadContext *)arg;
290 if (tctx->user_id == findCtx->uid && tctx->status != ThreadStatusInvalid) {
291 if (findCtx->tctx) {
292 // Ensure that user_id is unique. If it's not the case we are screwed.
293 // Something went wrong before, but now there is no way to recover.
294 // Returning a wrong thread is not an option, it may lead to very hard
295 // to debug false positives (e.g. if we join a wrong thread).
296 Report("ThreadSanitizer: dup thread with used id 0x%zx\n", findCtx->uid);
297 Die();
298 }
299 findCtx->tctx = tctx;
300 tctx->user_id = 0;
301 }
302 return false;
284Tid ThreadConsumeTid(ThreadState *thr, uptr pc, uptr uid) {
285 return ctx->thread_registry.ConsumeThreadUserId(uid);
303286}
304287
305int ThreadConsumeTid(ThreadState *thr, uptr pc, uptr uid) {
306 ConsumeThreadContext findCtx = {uid, nullptr};
307 ctx->thread_registry->FindThread(ConsumeThreadByUid, &findCtx);
308 int tid = findCtx.tctx ? findCtx.tctx->tid : kInvalidTid;
309 DPrintf("#%d: ThreadTid uid=%zu tid=%d\n", thr->tid, uid, tid);
310 return tid;
311}
288struct JoinArg {
289 VectorClock *sync;
290 uptr sync_epoch;
291};
312292
313void ThreadJoin(ThreadState *thr, uptr pc, int tid) {
293void ThreadJoin(ThreadState *thr, uptr pc, Tid tid) {
314294 CHECK_GT(tid, 0);
315 CHECK_LT(tid, kMaxTid);
316295 DPrintf("#%d: ThreadJoin tid=%d\n", thr->tid, tid);
317 ctx->thread_registry->JoinThread(tid, thr);
296 JoinArg arg = {};
297 ctx->thread_registry.JoinThread(tid, &arg);
298 if (!thr->ignore_sync) {
299 SlotLocker locker(thr);
300 if (arg.sync_epoch == ctx->global_epoch)
301 thr->clock.Acquire(arg.sync);
302 }
303 Free(arg.sync);
318304}
319305
320void ThreadDetach(ThreadState *thr, uptr pc, int tid) {
321 CHECK_GT(tid, 0);
322 CHECK_LT(tid, kMaxTid);
323 ctx->thread_registry->DetachThread(tid, thr);
306void ThreadContext::OnJoined(void *ptr) {
307 auto arg = static_cast<JoinArg *>(ptr);
308 arg->sync = sync;
309 arg->sync_epoch = sync_epoch;
310 sync = nullptr;
311 sync_epoch = 0;
324312}
325313
326void ThreadNotJoined(ThreadState *thr, uptr pc, int tid, uptr uid) {
327 CHECK_GT(tid, 0);
328 CHECK_LT(tid, kMaxTid);
329 ctx->thread_registry->SetThreadUserId(tid, uid);
330}
314void ThreadContext::OnDead() { CHECK_EQ(sync, nullptr); }
331315
332void ThreadSetName(ThreadState *thr, const char *name) {
333 ctx->thread_registry->SetThreadName(thr->tid, name);
316void ThreadDetach(ThreadState *thr, uptr pc, Tid tid) {
317 CHECK_GT(tid, 0);
318 ctx->thread_registry.DetachThread(tid, thr);
334319}
335320
336void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
337 uptr size, bool is_write) {
338 if (size == 0)
339 return;
340
341 u64 *shadow_mem = (u64*)MemToShadow(addr);
342 DPrintf2("#%d: MemoryAccessRange: @%p %p size=%d is_write=%d\n",
343 thr->tid, (void*)pc, (void*)addr,
344 (int)size, is_write);
321void ThreadContext::OnDetached(void *arg) { Free(sync); }
345322
346#if SANITIZER_DEBUG
347 if (!IsAppMem(addr)) {
348 Printf("Access to non app mem %zx\n", addr);
349 DCHECK(IsAppMem(addr));
350 }
351 if (!IsAppMem(addr + size - 1)) {
352 Printf("Access to non app mem %zx\n", addr + size - 1);
353 DCHECK(IsAppMem(addr + size - 1));
354 }
355 if (!IsShadowMem((uptr)shadow_mem)) {
356 Printf("Bad shadow addr %p (%zx)\n", shadow_mem, addr);
357 DCHECK(IsShadowMem((uptr)shadow_mem));
358 }
359 if (!IsShadowMem((uptr)(shadow_mem + size * kShadowCnt / 8 - 1))) {
360 Printf("Bad shadow addr %p (%zx)\n",
361 shadow_mem + size * kShadowCnt / 8 - 1, addr + size - 1);
362 DCHECK(IsShadowMem((uptr)(shadow_mem + size * kShadowCnt / 8 - 1)));
363 }
364#endif
365
366 if (*shadow_mem == kShadowRodata) {
367 DCHECK(!is_write);
368 // Access to .rodata section, no races here.
369 // Measurements show that it can be 10-20% of all memory accesses.
370 return;
371 }
372
373 FastState fast_state = thr->fast_state;
374 if (fast_state.GetIgnoreBit())
375 return;
376
377 fast_state.IncrementEpoch();
378 thr->fast_state = fast_state;
379 TraceAddEvent(thr, fast_state, EventTypeMop, pc);
380
381 bool unaligned = (addr % kShadowCell) != 0;
323void ThreadNotJoined(ThreadState *thr, uptr pc, Tid tid, uptr uid) {
324 CHECK_GT(tid, 0);
325 ctx->thread_registry.SetThreadUserId(tid, uid);
326}
382327
383 // Handle unaligned beginning, if any.
384 for (; addr % kShadowCell && size; addr++, size--) {
385 int const kAccessSizeLog = 0;
386 Shadow cur(fast_state);
387 cur.SetWrite(is_write);
388 cur.SetAddr0AndSizeLog(addr & (kShadowCell - 1), kAccessSizeLog);
389 MemoryAccessImpl(thr, addr, kAccessSizeLog, is_write, false,
390 shadow_mem, cur);
391 }
392 if (unaligned)
393 shadow_mem += kShadowCnt;
394 // Handle middle part, if any.
395 for (; size >= kShadowCell; addr += kShadowCell, size -= kShadowCell) {
396 int const kAccessSizeLog = 3;
397 Shadow cur(fast_state);
398 cur.SetWrite(is_write);
399 cur.SetAddr0AndSizeLog(0, kAccessSizeLog);
400 MemoryAccessImpl(thr, addr, kAccessSizeLog, is_write, false,
401 shadow_mem, cur);
402 shadow_mem += kShadowCnt;
403 }
404 // Handle ending, if any.
405 for (; size; addr++, size--) {
406 int const kAccessSizeLog = 0;
407 Shadow cur(fast_state);
408 cur.SetWrite(is_write);
409 cur.SetAddr0AndSizeLog(addr & (kShadowCell - 1), kAccessSizeLog);
410 MemoryAccessImpl(thr, addr, kAccessSizeLog, is_write, false,
411 shadow_mem, cur);
412 }
328void ThreadSetName(ThreadState *thr, const char *name) {
329 ctx->thread_registry.SetThreadName(thr->tid, name);
413330}
414331
415332#if !SANITIZER_GO
......@@ -421,10 +338,10 @@ void FiberSwitchImpl(ThreadState *from, ThreadState *to) {
421338}
422339
423340ThreadState *FiberCreate(ThreadState *thr, uptr pc, unsigned flags) {
424 void *mem = internal_alloc(MBlockThreadContex, sizeof(ThreadState));
341 void *mem = Alloc(sizeof(ThreadState));
425342 ThreadState *fiber = static_cast<ThreadState *>(mem);
426343 internal_memset(fiber, 0, sizeof(*fiber));
427 int tid = ThreadCreate(thr, pc, 0, true);
344 Tid tid = ThreadCreate(thr, pc, 0, true);
428345 FiberSwitchImpl(thr, fiber);
429346 ThreadStart(fiber, tid, 0, ThreadType::Fiber);
430347 FiberSwitchImpl(fiber, thr);
......@@ -435,7 +352,7 @@ void FiberDestroy(ThreadState *thr, uptr pc, ThreadState *fiber) {
435352 FiberSwitchImpl(thr, fiber);
436353 ThreadFinish(fiber);
437354 FiberSwitchImpl(fiber, thr);
438 internal_free(fiber);
355 Free(fiber);
439356}
440357
441358void FiberSwitch(ThreadState *thr, uptr pc,
lib/tsan/tsan_shadow.h created+193
......@@ -0,0 +1,193 @@
1//===-- tsan_shadow.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#ifndef TSAN_SHADOW_H
10#define TSAN_SHADOW_H
11
12#include "tsan_defs.h"
13
14namespace __tsan {
15
16class FastState {
17 public:
18 FastState() { Reset(); }
19
20 void Reset() {
21 part_.unused0_ = 0;
22 part_.sid_ = static_cast<u8>(kFreeSid);
23 part_.epoch_ = static_cast<u16>(kEpochLast);
24 part_.unused1_ = 0;
25 part_.ignore_accesses_ = false;
26 }
27
28 void SetSid(Sid sid) { part_.sid_ = static_cast<u8>(sid); }
29
30 Sid sid() const { return static_cast<Sid>(part_.sid_); }
31
32 Epoch epoch() const { return static_cast<Epoch>(part_.epoch_); }
33
34 void SetEpoch(Epoch epoch) { part_.epoch_ = static_cast<u16>(epoch); }
35
36 void SetIgnoreBit() { part_.ignore_accesses_ = 1; }
37 void ClearIgnoreBit() { part_.ignore_accesses_ = 0; }
38 bool GetIgnoreBit() const { return part_.ignore_accesses_; }
39
40 private:
41 friend class Shadow;
42 struct Parts {
43 u32 unused0_ : 8;
44 u32 sid_ : 8;
45 u32 epoch_ : kEpochBits;
46 u32 unused1_ : 1;
47 u32 ignore_accesses_ : 1;
48 };
49 union {
50 Parts part_;
51 u32 raw_;
52 };
53};
54
55static_assert(sizeof(FastState) == kShadowSize, "bad FastState size");
56
57class Shadow {
58 public:
59 static constexpr RawShadow kEmpty = static_cast<RawShadow>(0);
60
61 Shadow(FastState state, u32 addr, u32 size, AccessType typ) {
62 raw_ = state.raw_;
63 DCHECK_GT(size, 0);
64 DCHECK_LE(size, 8);
65 UNUSED Sid sid0 = part_.sid_;
66 UNUSED u16 epoch0 = part_.epoch_;
67 raw_ |= (!!(typ & kAccessAtomic) << kIsAtomicShift) |
68 (!!(typ & kAccessRead) << kIsReadShift) |
69 (((((1u << size) - 1) << (addr & 0x7)) & 0xff) << kAccessShift);
70 // Note: we don't check kAccessAtomic because it overlaps with
71 // FastState::ignore_accesses_ and it may be set spuriously.
72 DCHECK_EQ(part_.is_read_, !!(typ & kAccessRead));
73 DCHECK_EQ(sid(), sid0);
74 DCHECK_EQ(epoch(), epoch0);
75 }
76
77 explicit Shadow(RawShadow x = Shadow::kEmpty) { raw_ = static_cast<u32>(x); }
78
79 RawShadow raw() const { return static_cast<RawShadow>(raw_); }
80 Sid sid() const { return part_.sid_; }
81 Epoch epoch() const { return static_cast<Epoch>(part_.epoch_); }
82 u8 access() const { return part_.access_; }
83
84 void GetAccess(uptr *addr, uptr *size, AccessType *typ) const {
85 DCHECK(part_.access_ != 0 || raw_ == static_cast<u32>(Shadow::kRodata));
86 if (addr)
87 *addr = part_.access_ ? __builtin_ffs(part_.access_) - 1 : 0;
88 if (size)
89 *size = part_.access_ == kFreeAccess ? kShadowCell
90 : __builtin_popcount(part_.access_);
91 if (typ) {
92 *typ = part_.is_read_ ? kAccessRead : kAccessWrite;
93 if (part_.is_atomic_)
94 *typ |= kAccessAtomic;
95 if (part_.access_ == kFreeAccess)
96 *typ |= kAccessFree;
97 }
98 }
99
100 ALWAYS_INLINE
101 bool IsBothReadsOrAtomic(AccessType typ) const {
102 u32 is_read = !!(typ & kAccessRead);
103 u32 is_atomic = !!(typ & kAccessAtomic);
104 bool res =
105 raw_ & ((is_atomic << kIsAtomicShift) | (is_read << kIsReadShift));
106 DCHECK_EQ(res,
107 (part_.is_read_ && is_read) || (part_.is_atomic_ && is_atomic));
108 return res;
109 }
110
111 ALWAYS_INLINE
112 bool IsRWWeakerOrEqual(AccessType typ) const {
113 u32 is_read = !!(typ & kAccessRead);
114 u32 is_atomic = !!(typ & kAccessAtomic);
115 UNUSED u32 res0 =
116 (part_.is_atomic_ > is_atomic) ||
117 (part_.is_atomic_ == is_atomic && part_.is_read_ >= is_read);
118#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
119 const u32 kAtomicReadMask = (1 << kIsAtomicShift) | (1 << kIsReadShift);
120 bool res = (raw_ & kAtomicReadMask) >=
121 ((is_atomic << kIsAtomicShift) | (is_read << kIsReadShift));
122
123 DCHECK_EQ(res, res0);
124 return res;
125#else
126 return res0;
127#endif
128 }
129
130 // The FreedMarker must not pass "the same access check" so that we don't
131 // return from the race detection algorithm early.
132 static RawShadow FreedMarker() {
133 FastState fs;
134 fs.SetSid(kFreeSid);
135 fs.SetEpoch(kEpochLast);
136 Shadow s(fs, 0, 8, kAccessWrite);
137 return s.raw();
138 }
139
140 static RawShadow FreedInfo(Sid sid, Epoch epoch) {
141 Shadow s;
142 s.part_.sid_ = sid;
143 s.part_.epoch_ = static_cast<u16>(epoch);
144 s.part_.access_ = kFreeAccess;
145 return s.raw();
146 }
147
148 private:
149 struct Parts {
150 u8 access_;
151 Sid sid_;
152 u16 epoch_ : kEpochBits;
153 u16 is_read_ : 1;
154 u16 is_atomic_ : 1;
155 };
156 union {
157 Parts part_;
158 u32 raw_;
159 };
160
161 static constexpr u8 kFreeAccess = 0x81;
162
163#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
164 static constexpr uptr kAccessShift = 0;
165 static constexpr uptr kIsReadShift = 30;
166 static constexpr uptr kIsAtomicShift = 31;
167#else
168 static constexpr uptr kAccessShift = 24;
169 static constexpr uptr kIsReadShift = 1;
170 static constexpr uptr kIsAtomicShift = 0;
171#endif
172
173 public:
174 // .rodata shadow marker, see MapRodata and ContainsSameAccessFast.
175 static constexpr RawShadow kRodata =
176 static_cast<RawShadow>(1 << kIsReadShift);
177};
178
179static_assert(sizeof(Shadow) == kShadowSize, "bad Shadow size");
180
181ALWAYS_INLINE RawShadow LoadShadow(RawShadow *p) {
182 return static_cast<RawShadow>(
183 atomic_load((atomic_uint32_t *)p, memory_order_relaxed));
184}
185
186ALWAYS_INLINE void StoreShadow(RawShadow *sp, RawShadow s) {
187 atomic_store((atomic_uint32_t *)sp, static_cast<u32>(s),
188 memory_order_relaxed);
189}
190
191} // namespace __tsan
192
193#endif
lib/tsan/tsan_spinlock_defs_mac.h created+45
......@@ -0,0 +1,45 @@
1//===-- tsan_spinlock_defs_mac.h -------------------------------===//
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// Mac-specific forward-declared function defintions that may be
12// deprecated in later versions of the OS.
13// These are needed for interceptors.
14//
15//===----------------------------------------------------------------------===//
16
17#if SANITIZER_APPLE
18
19#ifndef TSAN_SPINLOCK_DEFS_MAC_H
20#define TSAN_SPINLOCK_DEFS_MAC_H
21
22#include <stdint.h>
23
24extern "C" {
25
26/*
27Provides forward declarations related to OSSpinLocks on Darwin. These functions are
28deprecated on macOS version 10.12 and later,
29and are no longer included in the system headers.
30
31However, the symbols are still available on the system, so we provide these forward
32declarations to prevent compilation errors in tsan_interceptors_mac.cpp, which
33references these functions when defining TSAN interceptor functions.
34*/
35
36typedef int32_t OSSpinLock;
37
38void OSSpinLockLock(volatile OSSpinLock *__lock);
39void OSSpinLockUnlock(volatile OSSpinLock *__lock);
40bool OSSpinLockTry(volatile OSSpinLock *__lock);
41
42}
43
44#endif //TSAN_SPINLOCK_DEFS_MAC_H
45#endif // SANITIZER_APPLE
lib/tsan/tsan_stack_trace.cpp+4-8
......@@ -23,14 +23,10 @@ VarSizeStackTrace::~VarSizeStackTrace() {
2323}
2424
2525void VarSizeStackTrace::ResizeBuffer(uptr new_size) {
26 if (trace_buffer) {
27 internal_free(trace_buffer);
28 }
29 trace_buffer =
30 (new_size > 0)
31 ? (uptr *)internal_alloc(MBlockStackTrace,
32 new_size * sizeof(trace_buffer[0]))
33 : nullptr;
26 Free(trace_buffer);
27 trace_buffer = (new_size > 0)
28 ? (uptr *)Alloc(new_size * sizeof(trace_buffer[0]))
29 : nullptr;
3430 trace = trace_buffer;
3531 size = new_size;
3632}
lib/tsan/tsan_suppressions.cpp+3-2
......@@ -10,15 +10,16 @@
1010//
1111//===----------------------------------------------------------------------===//
1212
13#include "tsan_suppressions.h"
14
1315#include "sanitizer_common/sanitizer_common.h"
1416#include "sanitizer_common/sanitizer_libc.h"
1517#include "sanitizer_common/sanitizer_placement_new.h"
1618#include "sanitizer_common/sanitizer_suppressions.h"
17#include "tsan_suppressions.h"
18#include "tsan_rtl.h"
1919#include "tsan_flags.h"
2020#include "tsan_mman.h"
2121#include "tsan_platform.h"
22#include "tsan_rtl.h"
2223
2324#if !SANITIZER_GO
2425// Suppressions for true/false positives in standard libraries.
lib/tsan/tsan_symbolize.cpp+2-1
......@@ -110,7 +110,8 @@ ReportLocation *SymbolizeData(uptr addr) {
110110 DataInfo info;
111111 if (!Symbolizer::GetOrInit()->SymbolizeData(addr, &info))
112112 return 0;
113 ReportLocation *ent = ReportLocation::New(ReportLocationGlobal);
113 auto *ent = New<ReportLocation>();
114 ent->type = ReportLocationGlobal;
114115 internal_memcpy(&ent->global, &info, sizeof(info));
115116 return ent;
116117}
lib/tsan/tsan_sync.cpp+64-68
......@@ -18,42 +18,31 @@ namespace __tsan {
1818
1919void DDMutexInit(ThreadState *thr, uptr pc, SyncVar *s);
2020
21SyncVar::SyncVar() : mtx(MutexTypeSyncVar) { Reset(0); }
21SyncVar::SyncVar() : mtx(MutexTypeSyncVar) { Reset(); }
2222
23void SyncVar::Init(ThreadState *thr, uptr pc, uptr addr, u64 uid) {
23void SyncVar::Init(ThreadState *thr, uptr pc, uptr addr, bool save_stack) {
24 Reset();
2425 this->addr = addr;
25 this->uid = uid;
26 this->next = 0;
27
28 creation_stack_id = 0;
29 if (!SANITIZER_GO) // Go does not use them
26 next = 0;
27 if (save_stack && !SANITIZER_GO) // Go does not use them
3028 creation_stack_id = CurrentStackId(thr, pc);
3129 if (common_flags()->detect_deadlocks)
3230 DDMutexInit(thr, pc, this);
3331}
3432
35void SyncVar::Reset(Processor *proc) {
36 uid = 0;
37 creation_stack_id = 0;
33void SyncVar::Reset() {
34 CHECK(!ctx->resetting);
35 creation_stack_id = kInvalidStackID;
3836 owner_tid = kInvalidTid;
39 last_lock = 0;
37 last_lock.Reset();
4038 recursion = 0;
4139 atomic_store_relaxed(&flags, 0);
42
43 if (proc == 0) {
44 CHECK_EQ(clock.size(), 0);
45 CHECK_EQ(read_clock.size(), 0);
46 } else {
47 clock.Reset(&proc->clock_cache);
48 read_clock.Reset(&proc->clock_cache);
49 }
40 Free(clock);
41 Free(read_clock);
5042}
5143
5244MetaMap::MetaMap()
53 : block_alloc_(LINKER_INITIALIZED, "heap block allocator"),
54 sync_alloc_(LINKER_INITIALIZED, "sync allocator") {
55 atomic_store(&uid_gen_, 0, memory_order_relaxed);
56}
45 : block_alloc_("heap block allocator"), sync_alloc_("sync allocator") {}
5746
5847void MetaMap::AllocBlock(ThreadState *thr, uptr pc, uptr p, uptr sz) {
5948 u32 idx = block_alloc_.Alloc(&thr->proc()->block_cache);
......@@ -67,16 +56,16 @@ void MetaMap::AllocBlock(ThreadState *thr, uptr pc, uptr p, uptr sz) {
6756 *meta = idx | kFlagBlock;
6857}
6958
70uptr MetaMap::FreeBlock(Processor *proc, uptr p) {
59uptr MetaMap::FreeBlock(Processor *proc, uptr p, bool reset) {
7160 MBlock* b = GetBlock(p);
7261 if (b == 0)
7362 return 0;
7463 uptr sz = RoundUpTo(b->siz, kMetaShadowCell);
75 FreeRange(proc, p, sz);
64 FreeRange(proc, p, sz, reset);
7665 return sz;
7766}
7867
79bool MetaMap::FreeRange(Processor *proc, uptr p, uptr sz) {
68bool MetaMap::FreeRange(Processor *proc, uptr p, uptr sz, bool reset) {
8069 bool has_something = false;
8170 u32 *meta = MemToMeta(p);
8271 u32 *end = MemToMeta(p + sz);
......@@ -98,7 +87,8 @@ bool MetaMap::FreeRange(Processor *proc, uptr p, uptr sz) {
9887 DCHECK(idx & kFlagSync);
9988 SyncVar *s = sync_alloc_.Map(idx & ~kFlagMask);
10089 u32 next = s->next;
101 s->Reset(proc);
90 if (reset)
91 s->Reset();
10292 sync_alloc_.Free(&proc->sync_cache, idx & ~kFlagMask);
10393 idx = next;
10494 } else {
......@@ -115,30 +105,30 @@ bool MetaMap::FreeRange(Processor *proc, uptr p, uptr sz) {
115105// which can be huge. The function probes pages one-by-one until it finds a page
116106// without meta objects, at this point it stops freeing meta objects. Because
117107// thread stacks grow top-down, we do the same starting from end as well.
118void MetaMap::ResetRange(Processor *proc, uptr p, uptr sz) {
108void MetaMap::ResetRange(Processor *proc, uptr p, uptr sz, bool reset) {
119109 if (SANITIZER_GO) {
120110 // UnmapOrDie/MmapFixedNoReserve does not work on Windows,
121111 // so we do the optimization only for C/C++.
122 FreeRange(proc, p, sz);
112 FreeRange(proc, p, sz, reset);
123113 return;
124114 }
125115 const uptr kMetaRatio = kMetaShadowCell / kMetaShadowSize;
126116 const uptr kPageSize = GetPageSizeCached() * kMetaRatio;
127117 if (sz <= 4 * kPageSize) {
128118 // If the range is small, just do the normal free procedure.
129 FreeRange(proc, p, sz);
119 FreeRange(proc, p, sz, reset);
130120 return;
131121 }
132122 // First, round both ends of the range to page size.
133123 uptr diff = RoundUp(p, kPageSize) - p;
134124 if (diff != 0) {
135 FreeRange(proc, p, diff);
125 FreeRange(proc, p, diff, reset);
136126 p += diff;
137127 sz -= diff;
138128 }
139129 diff = p + sz - RoundDown(p + sz, kPageSize);
140130 if (diff != 0) {
141 FreeRange(proc, p + sz - diff, diff);
131 FreeRange(proc, p + sz - diff, diff, reset);
142132 sz -= diff;
143133 }
144134 // Now we must have a non-empty page-aligned range.
......@@ -149,7 +139,7 @@ void MetaMap::ResetRange(Processor *proc, uptr p, uptr sz) {
149139 const uptr sz0 = sz;
150140 // Probe start of the range.
151141 for (uptr checked = 0; sz > 0; checked += kPageSize) {
152 bool has_something = FreeRange(proc, p, kPageSize);
142 bool has_something = FreeRange(proc, p, kPageSize, reset);
153143 p += kPageSize;
154144 sz -= kPageSize;
155145 if (!has_something && checked > (128 << 10))
......@@ -157,7 +147,7 @@ void MetaMap::ResetRange(Processor *proc, uptr p, uptr sz) {
157147 }
158148 // Probe end of the range.
159149 for (uptr checked = 0; sz > 0; checked += kPageSize) {
160 bool has_something = FreeRange(proc, p + sz - kPageSize, kPageSize);
150 bool has_something = FreeRange(proc, p + sz - kPageSize, kPageSize, reset);
161151 sz -= kPageSize;
162152 // Stacks grow down, so sync object are most likely at the end of the region
163153 // (if it is a stack). The very end of the stack is TLS and tsan increases
......@@ -176,6 +166,27 @@ void MetaMap::ResetRange(Processor *proc, uptr p, uptr sz) {
176166 Die();
177167}
178168
169void MetaMap::ResetClocks() {
170 // This can be called from the background thread
171 // which does not have proc/cache.
172 // The cache is too large for stack.
173 static InternalAllocatorCache cache;
174 internal_memset(&cache, 0, sizeof(cache));
175 internal_allocator()->InitCache(&cache);
176 sync_alloc_.ForEach([&](SyncVar *s) {
177 if (s->clock) {
178 InternalFree(s->clock, &cache);
179 s->clock = nullptr;
180 }
181 if (s->read_clock) {
182 InternalFree(s->read_clock, &cache);
183 s->read_clock = nullptr;
184 }
185 s->last_lock.Reset();
186 });
187 internal_allocator()->DestroyCache(&cache);
188}
189
179190MBlock* MetaMap::GetBlock(uptr p) {
180191 u32 *meta = MemToMeta(p);
181192 u32 idx = *meta;
......@@ -190,63 +201,41 @@ MBlock* MetaMap::GetBlock(uptr p) {
190201 }
191202}
192203
193SyncVar* MetaMap::GetOrCreateAndLock(ThreadState *thr, uptr pc,
194 uptr addr, bool write_lock) {
195 return GetAndLock(thr, pc, addr, write_lock, true);
196}
197
198SyncVar* MetaMap::GetIfExistsAndLock(uptr addr, bool write_lock) {
199 return GetAndLock(0, 0, addr, write_lock, false);
200}
201
202SyncVar *MetaMap::GetAndLock(ThreadState *thr, uptr pc, uptr addr, bool write_lock,
203 bool create) NO_THREAD_SAFETY_ANALYSIS {
204SyncVar *MetaMap::GetSync(ThreadState *thr, uptr pc, uptr addr, bool create,
205 bool save_stack) {
206 DCHECK(!create || thr->slot_locked);
204207 u32 *meta = MemToMeta(addr);
205208 u32 idx0 = *meta;
206209 u32 myidx = 0;
207 SyncVar *mys = 0;
210 SyncVar *mys = nullptr;
208211 for (;;) {
209 u32 idx = idx0;
210 for (;;) {
211 if (idx == 0)
212 break;
213 if (idx & kFlagBlock)
214 break;
212 for (u32 idx = idx0; idx && !(idx & kFlagBlock);) {
215213 DCHECK(idx & kFlagSync);
216214 SyncVar * s = sync_alloc_.Map(idx & ~kFlagMask);
217 if (s->addr == addr) {
218 if (myidx != 0) {
219 mys->Reset(thr->proc());
215 if (LIKELY(s->addr == addr)) {
216 if (UNLIKELY(myidx != 0)) {
217 mys->Reset();
220218 sync_alloc_.Free(&thr->proc()->sync_cache, myidx);
221219 }
222 if (write_lock)
223 s->mtx.Lock();
224 else
225 s->mtx.ReadLock();
226220 return s;
227221 }
228222 idx = s->next;
229223 }
230224 if (!create)
231 return 0;
232 if (*meta != idx0) {
225 return nullptr;
226 if (UNLIKELY(*meta != idx0)) {
233227 idx0 = *meta;
234228 continue;
235229 }
236230
237 if (myidx == 0) {
238 const u64 uid = atomic_fetch_add(&uid_gen_, 1, memory_order_relaxed);
231 if (LIKELY(myidx == 0)) {
239232 myidx = sync_alloc_.Alloc(&thr->proc()->sync_cache);
240233 mys = sync_alloc_.Map(myidx);
241 mys->Init(thr, pc, addr, uid);
234 mys->Init(thr, pc, addr, save_stack);
242235 }
243236 mys->next = idx0;
244237 if (atomic_compare_exchange_strong((atomic_uint32_t*)meta, &idx0,
245238 myidx | kFlagSync, memory_order_release)) {
246 if (write_lock)
247 mys->mtx.Lock();
248 else
249 mys->mtx.ReadLock();
250239 return mys;
251240 }
252241 }
......@@ -290,4 +279,11 @@ void MetaMap::OnProcIdle(Processor *proc) {
290279 sync_alloc_.FlushCache(&proc->sync_cache);
291280}
292281
282MetaMap::MemoryStats MetaMap::GetMemoryStats() const {
283 MemoryStats stats;
284 stats.mem_block = block_alloc_.AllocatedMemory();
285 stats.sync_obj = sync_alloc_.AllocatedMemory();
286 return stats;
287}
288
293289} // namespace __tsan
lib/tsan/tsan_sync.h+43-37
......@@ -16,8 +16,9 @@
1616#include "sanitizer_common/sanitizer_common.h"
1717#include "sanitizer_common/sanitizer_deadlock_detector_interface.h"
1818#include "tsan_defs.h"
19#include "tsan_clock.h"
2019#include "tsan_dense_alloc.h"
20#include "tsan_shadow.h"
21#include "tsan_vector_clock.h"
2122
2223namespace __tsan {
2324
......@@ -46,39 +47,25 @@ enum MutexFlags {
4647 MutexFlagNotStatic,
4748};
4849
50// SyncVar is a descriptor of a user synchronization object
51// (mutex or an atomic variable).
4952struct SyncVar {
5053 SyncVar();
5154
5255 uptr addr; // overwritten by DenseSlabAlloc freelist
5356 Mutex mtx;
54 u64 uid; // Globally unique id.
55 u32 creation_stack_id;
56 u32 owner_tid; // Set only by exclusive owners.
57 u64 last_lock;
57 StackID creation_stack_id;
58 Tid owner_tid; // Set only by exclusive owners.
59 FastState last_lock;
5860 int recursion;
5961 atomic_uint32_t flags;
6062 u32 next; // in MetaMap
6163 DDMutex dd;
62 SyncClock read_clock; // Used for rw mutexes only.
63 // The clock is placed last, so that it is situated on a different cache line
64 // with the mtx. This reduces contention for hot sync objects.
65 SyncClock clock;
64 VectorClock *read_clock; // Used for rw mutexes only.
65 VectorClock *clock;
6666
67 void Init(ThreadState *thr, uptr pc, uptr addr, u64 uid);
68 void Reset(Processor *proc);
69
70 u64 GetId() const {
71 // 48 lsb is addr, then 14 bits is low part of uid, then 2 zero bits.
72 return GetLsb((u64)addr | (uid << 48), 60);
73 }
74 bool CheckId(u64 uid) const {
75 CHECK_EQ(uid, GetLsb(uid, 14));
76 return GetLsb(this->uid, 14) == uid;
77 }
78 static uptr SplitId(u64 id, u64 *uid) {
79 *uid = id >> 48;
80 return (uptr)GetLsb(id, 48);
81 }
67 void Init(ThreadState *thr, uptr pc, uptr addr, bool save_stack);
68 void Reset();
8269
8370 bool IsFlagSet(u32 f) const {
8471 return atomic_load_relaxed(&flags) & f;
......@@ -101,28 +88,48 @@ struct SyncVar {
10188 }
10289};
10390
104/* MetaMap allows to map arbitrary user pointers onto various descriptors.
105 Currently it maps pointers to heap block descriptors and sync var descs.
106 It uses 1/2 direct shadow, see tsan_platform.h.
107*/
91// MetaMap maps app addresses to heap block (MBlock) and sync var (SyncVar)
92// descriptors. It uses 1/2 direct shadow, see tsan_platform.h for the mapping.
10893class MetaMap {
10994 public:
11095 MetaMap();
11196
11297 void AllocBlock(ThreadState *thr, uptr pc, uptr p, uptr sz);
113 uptr FreeBlock(Processor *proc, uptr p);
114 bool FreeRange(Processor *proc, uptr p, uptr sz);
115 void ResetRange(Processor *proc, uptr p, uptr sz);
98
99 // FreeBlock resets all sync objects in the range if reset=true and must not
100 // run concurrently with ResetClocks which resets all sync objects
101 // w/o any synchronization (as part of DoReset).
102 // If we don't have a thread slot (very early/late in thread lifetime or
103 // Go/Java callbacks) or the slot is not locked, then reset must be set to
104 // false. In such case sync object clocks will be reset later (when it's
105 // reused or during the next ResetClocks).
106 uptr FreeBlock(Processor *proc, uptr p, bool reset);
107 bool FreeRange(Processor *proc, uptr p, uptr sz, bool reset);
108 void ResetRange(Processor *proc, uptr p, uptr sz, bool reset);
109 // Reset vector clocks of all sync objects.
110 // Must be called when no other threads access sync objects.
111 void ResetClocks();
116112 MBlock* GetBlock(uptr p);
117113
118 SyncVar* GetOrCreateAndLock(ThreadState *thr, uptr pc,
119 uptr addr, bool write_lock);
120 SyncVar* GetIfExistsAndLock(uptr addr, bool write_lock);
114 SyncVar *GetSyncOrCreate(ThreadState *thr, uptr pc, uptr addr,
115 bool save_stack) {
116 return GetSync(thr, pc, addr, true, save_stack);
117 }
118 SyncVar *GetSyncIfExists(uptr addr) {
119 return GetSync(nullptr, 0, addr, false, false);
120 }
121121
122122 void MoveMemory(uptr src, uptr dst, uptr sz);
123123
124124 void OnProcIdle(Processor *proc);
125125
126 struct MemoryStats {
127 uptr mem_block;
128 uptr sync_obj;
129 };
130
131 MemoryStats GetMemoryStats() const;
132
126133 private:
127134 static const u32 kFlagMask = 3u << 30;
128135 static const u32 kFlagBlock = 1u << 30;
......@@ -131,10 +138,9 @@ class MetaMap {
131138 typedef DenseSlabAlloc<SyncVar, 1 << 20, 1 << 10, kFlagMask> SyncAlloc;
132139 BlockAlloc block_alloc_;
133140 SyncAlloc sync_alloc_;
134 atomic_uint64_t uid_gen_;
135141
136 SyncVar* GetAndLock(ThreadState *thr, uptr pc, uptr addr, bool write_lock,
137 bool create);
142 SyncVar *GetSync(ThreadState *thr, uptr pc, uptr addr, bool create,
143 bool save_stack);
138144};
139145
140146} // namespace __tsan
lib/tsan/tsan_trace.h+180-37
......@@ -13,58 +13,201 @@
1313#define TSAN_TRACE_H
1414
1515#include "tsan_defs.h"
16#include "tsan_stack_trace.h"
16#include "tsan_ilist.h"
1717#include "tsan_mutexset.h"
18#include "tsan_stack_trace.h"
1819
1920namespace __tsan {
2021
21const int kTracePartSizeBits = 13;
22const int kTracePartSize = 1 << kTracePartSizeBits;
23const int kTraceParts = 2 * 1024 * 1024 / kTracePartSize;
24const int kTraceSize = kTracePartSize * kTraceParts;
25
26// Must fit into 3 bits.
27enum EventType {
28 EventTypeMop,
29 EventTypeFuncEnter,
30 EventTypeFuncExit,
31 EventTypeLock,
32 EventTypeUnlock,
33 EventTypeRLock,
34 EventTypeRUnlock
22enum class EventType : u64 {
23 kAccessExt,
24 kAccessRange,
25 kLock,
26 kRLock,
27 kUnlock,
28 kTime,
29};
30
31// "Base" type for all events for type dispatch.
32struct Event {
33 // We use variable-length type encoding to give more bits to some event
34 // types that need them. If is_access is set, this is EventAccess.
35 // Otherwise, if is_func is set, this is EventFunc.
36 // Otherwise type denotes the type.
37 u64 is_access : 1;
38 u64 is_func : 1;
39 EventType type : 3;
40 u64 _ : 59;
41};
42static_assert(sizeof(Event) == 8, "bad Event size");
43
44// Nop event used as padding and does not affect state during replay.
45static constexpr Event NopEvent = {1, 0, EventType::kAccessExt, 0};
46
47// Compressed memory access can represent only some events with PCs
48// close enough to each other. Otherwise we fall back to EventAccessExt.
49struct EventAccess {
50 static constexpr uptr kPCBits = 15;
51 static_assert(kPCBits + kCompressedAddrBits + 5 == 64,
52 "unused bits in EventAccess");
53
54 u64 is_access : 1; // = 1
55 u64 is_read : 1;
56 u64 is_atomic : 1;
57 u64 size_log : 2;
58 u64 pc_delta : kPCBits; // signed delta from the previous memory access PC
59 u64 addr : kCompressedAddrBits;
3560};
61static_assert(sizeof(EventAccess) == 8, "bad EventAccess size");
3662
37// Represents a thread event (from most significant bit):
38// u64 typ : 3; // EventType.
39// u64 addr : 61; // Associated pc.
40typedef u64 Event;
63// Function entry (pc != 0) or exit (pc == 0).
64struct EventFunc {
65 u64 is_access : 1; // = 0
66 u64 is_func : 1; // = 1
67 u64 pc : 62;
68};
69static_assert(sizeof(EventFunc) == 8, "bad EventFunc size");
70
71// Extended memory access with full PC.
72struct EventAccessExt {
73 // Note: precisely specifying the unused parts of the bitfield is critical for
74 // performance. If we don't specify them, compiler will generate code to load
75 // the old value and shuffle it to extract the unused bits to apply to the new
76 // value. If we specify the unused part and store 0 in there, all that
77 // unnecessary code goes away (store of the 0 const is combined with other
78 // constant parts).
79 static constexpr uptr kUnusedBits = 11;
80 static_assert(kCompressedAddrBits + kUnusedBits + 9 == 64,
81 "unused bits in EventAccessExt");
82
83 u64 is_access : 1; // = 0
84 u64 is_func : 1; // = 0
85 EventType type : 3; // = EventType::kAccessExt
86 u64 is_read : 1;
87 u64 is_atomic : 1;
88 u64 size_log : 2;
89 u64 _ : kUnusedBits;
90 u64 addr : kCompressedAddrBits;
91 u64 pc;
92};
93static_assert(sizeof(EventAccessExt) == 16, "bad EventAccessExt size");
94
95// Access to a memory range.
96struct EventAccessRange {
97 static constexpr uptr kSizeLoBits = 13;
98 static_assert(kCompressedAddrBits + kSizeLoBits + 7 == 64,
99 "unused bits in EventAccessRange");
100
101 u64 is_access : 1; // = 0
102 u64 is_func : 1; // = 0
103 EventType type : 3; // = EventType::kAccessRange
104 u64 is_read : 1;
105 u64 is_free : 1;
106 u64 size_lo : kSizeLoBits;
107 u64 pc : kCompressedAddrBits;
108 u64 addr : kCompressedAddrBits;
109 u64 size_hi : 64 - kCompressedAddrBits;
110};
111static_assert(sizeof(EventAccessRange) == 16, "bad EventAccessRange size");
41112
42const uptr kEventPCBits = 61;
113// Mutex lock.
114struct EventLock {
115 static constexpr uptr kStackIDLoBits = 15;
116 static constexpr uptr kStackIDHiBits =
117 sizeof(StackID) * kByteBits - kStackIDLoBits;
118 static constexpr uptr kUnusedBits = 3;
119 static_assert(kCompressedAddrBits + kStackIDLoBits + 5 == 64,
120 "unused bits in EventLock");
121 static_assert(kCompressedAddrBits + kStackIDHiBits + kUnusedBits == 64,
122 "unused bits in EventLock");
123
124 u64 is_access : 1; // = 0
125 u64 is_func : 1; // = 0
126 EventType type : 3; // = EventType::kLock or EventType::kRLock
127 u64 pc : kCompressedAddrBits;
128 u64 stack_lo : kStackIDLoBits;
129 u64 stack_hi : sizeof(StackID) * kByteBits - kStackIDLoBits;
130 u64 _ : kUnusedBits;
131 u64 addr : kCompressedAddrBits;
132};
133static_assert(sizeof(EventLock) == 16, "bad EventLock size");
134
135// Mutex unlock.
136struct EventUnlock {
137 static constexpr uptr kUnusedBits = 15;
138 static_assert(kCompressedAddrBits + kUnusedBits + 5 == 64,
139 "unused bits in EventUnlock");
140
141 u64 is_access : 1; // = 0
142 u64 is_func : 1; // = 0
143 EventType type : 3; // = EventType::kUnlock
144 u64 _ : kUnusedBits;
145 u64 addr : kCompressedAddrBits;
146};
147static_assert(sizeof(EventUnlock) == 8, "bad EventUnlock size");
148
149// Time change event.
150struct EventTime {
151 static constexpr uptr kUnusedBits = 37;
152 static_assert(kUnusedBits + sizeof(Sid) * kByteBits + kEpochBits + 5 == 64,
153 "unused bits in EventTime");
154
155 u64 is_access : 1; // = 0
156 u64 is_func : 1; // = 0
157 EventType type : 3; // = EventType::kTime
158 u64 sid : sizeof(Sid) * kByteBits;
159 u64 epoch : kEpochBits;
160 u64 _ : kUnusedBits;
161};
162static_assert(sizeof(EventTime) == 8, "bad EventTime size");
163
164struct Trace;
43165
44166struct TraceHeader {
45#if !SANITIZER_GO
46 BufferedStackTrace stack0; // Start stack for the trace.
47#else
48 VarSizeStackTrace stack0;
49#endif
50 u64 epoch0; // Start epoch for the trace.
51 MutexSet mset0;
52
53 TraceHeader() : stack0(), epoch0() {}
167 Trace* trace = nullptr; // back-pointer to Trace containing this part
168 INode trace_parts; // in Trace::parts
169 INode global; // in Contex::trace_part_recycle
54170};
55171
172struct TracePart : TraceHeader {
173 // There are a lot of goroutines in Go, so we use smaller parts.
174 static constexpr uptr kByteSize = (SANITIZER_GO ? 128 : 256) << 10;
175 static constexpr uptr kSize =
176 (kByteSize - sizeof(TraceHeader)) / sizeof(Event);
177 // TraceAcquire does a fast event pointer overflow check by comparing
178 // pointer into TracePart::events with kAlignment mask. Since TracePart's
179 // are allocated page-aligned, this check detects end of the array
180 // (it also have false positives in the middle that are filtered separately).
181 // This also requires events to be the last field.
182 static constexpr uptr kAlignment = 0xff0;
183 Event events[kSize];
184
185 TracePart() {}
186};
187static_assert(sizeof(TracePart) == TracePart::kByteSize, "bad TracePart size");
188
56189struct Trace {
57190 Mutex mtx;
58#if !SANITIZER_GO
59 // Must be last to catch overflow as paging fault.
60 // Go shadow stack is dynamically allocated.
61 uptr shadow_stack[kShadowStackSize];
62#endif
63 // Must be the last field, because we unmap the unused part in
64 // CreateThreadContext.
65 TraceHeader headers[kTraceParts];
191 IList<TraceHeader, &TraceHeader::trace_parts, TracePart> parts;
192 // First node non-queued into ctx->trace_part_recycle.
193 TracePart* local_head;
194 // Final position in the last part for finished threads.
195 Event* final_pos = nullptr;
196 // Number of trace parts allocated on behalf of this trace specifically.
197 // Total number of parts in this trace can be larger if we retake some
198 // parts from other traces.
199 uptr parts_allocated = 0;
66200
67201 Trace() : mtx(MutexTypeTrace) {}
202
203 // We need at least 3 parts per thread, because we want to keep at last
204 // 2 parts per thread that are not queued into ctx->trace_part_recycle
205 // (the current one being filled and one full part that ensures that
206 // we always have at least one part worth of previous memory accesses).
207 static constexpr uptr kMinParts = 3;
208
209 static constexpr uptr kFinishedThreadLo = 16;
210 static constexpr uptr kFinishedThreadHi = 64;
68211};
69212
70213} // namespace __tsan
lib/tsan/tsan_update_shadow_word_inl.h deleted-59
......@@ -1,59 +0,0 @@
1//===-- tsan_update_shadow_word_inl.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// Body of the hottest inner loop.
12// If we wrap this body into a function, compilers (both gcc and clang)
13// produce sligtly less efficient code.
14//===----------------------------------------------------------------------===//
15do {
16 const unsigned kAccessSize = 1 << kAccessSizeLog;
17 u64 *sp = &shadow_mem[idx];
18 old = LoadShadow(sp);
19 if (LIKELY(old.IsZero())) {
20 if (!stored) {
21 StoreIfNotYetStored(sp, &store_word);
22 stored = true;
23 }
24 break;
25 }
26 // is the memory access equal to the previous?
27 if (LIKELY(Shadow::Addr0AndSizeAreEqual(cur, old))) {
28 // same thread?
29 if (LIKELY(Shadow::TidsAreEqual(old, cur))) {
30 if (LIKELY(old.IsRWWeakerOrEqual(kAccessIsWrite, kIsAtomic))) {
31 StoreIfNotYetStored(sp, &store_word);
32 stored = true;
33 }
34 break;
35 }
36 if (HappensBefore(old, thr)) {
37 if (old.IsRWWeakerOrEqual(kAccessIsWrite, kIsAtomic)) {
38 StoreIfNotYetStored(sp, &store_word);
39 stored = true;
40 }
41 break;
42 }
43 if (LIKELY(old.IsBothReadsOrAtomic(kAccessIsWrite, kIsAtomic)))
44 break;
45 goto RACE;
46 }
47 // Do the memory access intersect?
48 if (Shadow::TwoRangesIntersect(old, cur, kAccessSize)) {
49 if (Shadow::TidsAreEqual(old, cur))
50 break;
51 if (old.IsBothReadsOrAtomic(kAccessIsWrite, kIsAtomic))
52 break;
53 if (LIKELY(HappensBefore(old, thr)))
54 break;
55 goto RACE;
56 }
57 // The accesses do not intersect.
58 break;
59} while (0);
lib/tsan/tsan_vector_clock.cpp created+126
......@@ -0,0 +1,126 @@
1//===-- tsan_vector_clock.cpp ---------------------------------------------===//
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#include "tsan_vector_clock.h"
13
14#include "sanitizer_common/sanitizer_placement_new.h"
15#include "tsan_mman.h"
16
17namespace __tsan {
18
19#if TSAN_VECTORIZE
20const uptr kVectorClockSize = kThreadSlotCount * sizeof(Epoch) / sizeof(m128);
21#endif
22
23VectorClock::VectorClock() { Reset(); }
24
25void VectorClock::Reset() {
26#if !TSAN_VECTORIZE
27 for (uptr i = 0; i < kThreadSlotCount; i++)
28 clk_[i] = kEpochZero;
29#else
30 m128 z = _mm_setzero_si128();
31 m128* vclk = reinterpret_cast<m128*>(clk_);
32 for (uptr i = 0; i < kVectorClockSize; i++) _mm_store_si128(&vclk[i], z);
33#endif
34}
35
36void VectorClock::Acquire(const VectorClock* src) {
37 if (!src)
38 return;
39#if !TSAN_VECTORIZE
40 for (uptr i = 0; i < kThreadSlotCount; i++)
41 clk_[i] = max(clk_[i], src->clk_[i]);
42#else
43 m128* __restrict vdst = reinterpret_cast<m128*>(clk_);
44 m128 const* __restrict vsrc = reinterpret_cast<m128 const*>(src->clk_);
45 for (uptr i = 0; i < kVectorClockSize; i++) {
46 m128 s = _mm_load_si128(&vsrc[i]);
47 m128 d = _mm_load_si128(&vdst[i]);
48 m128 m = _mm_max_epu16(s, d);
49 _mm_store_si128(&vdst[i], m);
50 }
51#endif
52}
53
54static VectorClock* AllocClock(VectorClock** dstp) {
55 if (UNLIKELY(!*dstp))
56 *dstp = New<VectorClock>();
57 return *dstp;
58}
59
60void VectorClock::Release(VectorClock** dstp) const {
61 VectorClock* dst = AllocClock(dstp);
62 dst->Acquire(this);
63}
64
65void VectorClock::ReleaseStore(VectorClock** dstp) const {
66 VectorClock* dst = AllocClock(dstp);
67 *dst = *this;
68}
69
70VectorClock& VectorClock::operator=(const VectorClock& other) {
71#if !TSAN_VECTORIZE
72 for (uptr i = 0; i < kThreadSlotCount; i++)
73 clk_[i] = other.clk_[i];
74#else
75 m128* __restrict vdst = reinterpret_cast<m128*>(clk_);
76 m128 const* __restrict vsrc = reinterpret_cast<m128 const*>(other.clk_);
77 for (uptr i = 0; i < kVectorClockSize; i++) {
78 m128 s = _mm_load_si128(&vsrc[i]);
79 _mm_store_si128(&vdst[i], s);
80 }
81#endif
82 return *this;
83}
84
85void VectorClock::ReleaseStoreAcquire(VectorClock** dstp) {
86 VectorClock* dst = AllocClock(dstp);
87#if !TSAN_VECTORIZE
88 for (uptr i = 0; i < kThreadSlotCount; i++) {
89 Epoch tmp = dst->clk_[i];
90 dst->clk_[i] = clk_[i];
91 clk_[i] = max(clk_[i], tmp);
92 }
93#else
94 m128* __restrict vdst = reinterpret_cast<m128*>(dst->clk_);
95 m128* __restrict vclk = reinterpret_cast<m128*>(clk_);
96 for (uptr i = 0; i < kVectorClockSize; i++) {
97 m128 t = _mm_load_si128(&vdst[i]);
98 m128 c = _mm_load_si128(&vclk[i]);
99 m128 m = _mm_max_epu16(c, t);
100 _mm_store_si128(&vdst[i], c);
101 _mm_store_si128(&vclk[i], m);
102 }
103#endif
104}
105
106void VectorClock::ReleaseAcquire(VectorClock** dstp) {
107 VectorClock* dst = AllocClock(dstp);
108#if !TSAN_VECTORIZE
109 for (uptr i = 0; i < kThreadSlotCount; i++) {
110 dst->clk_[i] = max(dst->clk_[i], clk_[i]);
111 clk_[i] = dst->clk_[i];
112 }
113#else
114 m128* __restrict vdst = reinterpret_cast<m128*>(dst->clk_);
115 m128* __restrict vclk = reinterpret_cast<m128*>(clk_);
116 for (uptr i = 0; i < kVectorClockSize; i++) {
117 m128 c = _mm_load_si128(&vclk[i]);
118 m128 d = _mm_load_si128(&vdst[i]);
119 m128 m = _mm_max_epu16(c, d);
120 _mm_store_si128(&vdst[i], m);
121 _mm_store_si128(&vclk[i], m);
122 }
123#endif
124}
125
126} // namespace __tsan
lib/tsan/tsan_vector_clock.h created+51
......@@ -0,0 +1,51 @@
1//===-- tsan_vector_clock.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_VECTOR_CLOCK_H
13#define TSAN_VECTOR_CLOCK_H
14
15#include "tsan_defs.h"
16
17namespace __tsan {
18
19// Fixed-size vector clock, used both for threads and sync objects.
20class VectorClock {
21 public:
22 VectorClock();
23
24 Epoch Get(Sid sid) const;
25 void Set(Sid sid, Epoch v);
26
27 void Reset();
28 void Acquire(const VectorClock* src);
29 void Release(VectorClock** dstp) const;
30 void ReleaseStore(VectorClock** dstp) const;
31 void ReleaseStoreAcquire(VectorClock** dstp);
32 void ReleaseAcquire(VectorClock** dstp);
33
34 VectorClock& operator=(const VectorClock& other);
35
36 private:
37 Epoch clk_[kThreadSlotCount] VECTOR_ALIGNED;
38};
39
40ALWAYS_INLINE Epoch VectorClock::Get(Sid sid) const {
41 return clk_[static_cast<u8>(sid)];
42}
43
44ALWAYS_INLINE void VectorClock::Set(Sid sid, Epoch v) {
45 DCHECK_GE(v, clk_[static_cast<u8>(sid)]);
46 clk_[static_cast<u8>(sid)] = v;
47}
48
49} // namespace __tsan
50
51#endif // TSAN_VECTOR_CLOCK_H